EMU618社区

 找回密码
 立即注册
搜索
查看: 1887|回复: 14

[求助] 【模拟器代码问题】模拟器如何通过代码控制Rom的背景音乐

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?
/ V9 U; u- _7 D: [# v. rPS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

发表于 2009-11-2 22:57:37 | 显示全部楼层
看了下VirtualNes的源码,是APU那部分,全称应该是Audio Process Unit

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。$ K8 }2 o! C+ G1 D& l8 T. w* L
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
3 W+ O: |! n+ |8 b5 Z4 n' _3 [这里有相应的模拟器源码,就当送给大侠了~~
* k/ i6 s) j( e- K/ Y& W5 ihttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 - ~& o! C+ w8 L
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
* {* v8 Z# U! s7 a; U: |楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~2 k3 j  J- E2 R" |, ~
这里有相应的模拟器源码,就当送给大侠 ...

* G. Z5 I, U  n聲音部分(Audoi Process Unit = APU):
. M" N' c2 G6 W% B, A; y.\NES\APU.cpp
) h8 S& x4 _0 B, Y% ^, m.\NES\APU.h7 J( G. [; a6 q1 ?, C

1 @3 }$ _; y  a3 N3 H
  {* h4 S( _: S影像處理部份(Picture Processing Unit = PPU):
( E) U! J* g& z8 O.\NES\PPU.cpp
( i9 d! I- V" B.\NES\PPU.h
# v9 t% R/ B% L3 U3 B* p3 x0 ^% E1 h2 k7 t
如果原碼用C跟ASM混搭也不錯

该用户从未签到

发表于 2009-11-8 13:03:26 | 显示全部楼层
楼上是高手 哈哈

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
, ?1 E; v0 _- c7 {: v, K/ U2 d& V感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
( w, S; q. i7 E# O$ I8 a$ ^( C(由于很多专用术语和算法机理都不明白,所以看不大懂……)' {8 o! D+ a2 q2 o
//////////////////////////////////////////////////////////////////////////0 H4 }8 @( f9 S2 e* a! G+ k
//                                                                      //9 Y1 h, D0 j7 ^. w% S9 ]% Q
//      NES APU core                                                    //! o# m8 ~/ p' O4 y
//                                                           Norix      //" C) H6 F. k! c& N
//                                               written     2002/06/27 //% {- w3 o& M2 ^- g* R3 Z
//                                               last modify ----/--/-- //5 t& k; X- }9 {1 c5 q: F0 Y: |
//////////////////////////////////////////////////////////////////////////4 b! N2 i% m% G3 c7 D
#include "DebugOut.h"
  u! Z/ T4 Y( a! c#include "App.h"9 I2 U8 u! v- y$ Z/ l% h3 T
#include "Config.h"; C' C7 y7 K! D

& T" ~& u7 ?2 N, a#include "nes.h"
8 M' c: ^5 L, {" M% U#include "mmu.h"$ U. \3 a  a# I+ U. N
#include "cpu.h"
4 R: z" y* i$ a/ |( o9 ~' A$ f) l#include "ppu.h"$ S) o# d, r8 ~8 i7 R. \+ d
#include "rom.h"
4 A5 E2 u& j& a1 C#include "apu.h"  ~2 f5 W6 K& v1 x
# n3 n1 M3 n) L* m7 Q, u9 X
// Volume adjust
* d1 m9 j" P& s1 v/ r% m7 y" e) m9 d// Internal sounds; s0 u+ V8 ~6 a5 y+ _5 I2 S
#define        RECTANGLE_VOL        (0x0F0)
' r' `5 K% b2 s1 y2 \4 l& C#define        TRIANGLE_VOL        (0x130)
- G1 H& `2 ?" M2 g' c9 v6 s#define        NOISE_VOL        (0x0C0)0 s) o$ A' Q; K6 t& K
#define        DPCM_VOL        (0x0F0)  |: r2 |: Z8 T" v# {; B
// Extra sounds5 L$ k, A, L0 J
#define        VRC6_VOL        (0x0F0)
. Z: n1 k$ w# }' u- l3 a- P; O#define        VRC7_VOL        (0x130)
! H& I; ~! |0 n0 h#define        FDS_VOL                (0x0F0)
, n5 {) _4 {- V#define        MMC5_VOL        (0x0F0)5 y4 v) E+ r& z5 T5 d0 e4 U
#define        N106_VOL        (0x088)
% b- I# E$ h% n#define        FME7_VOL        (0x130)
$ ?+ l( u7 r9 {9 k6 p$ j
0 R; U+ E4 n4 v5 F& @APU::APU( NES* parent )
1 X8 G2 u5 z9 u3 Y{! \# e. M- A- t) y* _6 S
        exsound_select = 0;" f/ M, u3 H+ ^: C' f' f

- t/ S1 Q; o' Q3 T5 t        nes = parent;' [% m# y% W5 a; M7 _# x
        internal.SetParent( parent );
  x0 u2 C0 V( ~; E6 S0 R1 }+ Q- R: B1 U; T
        last_data = last_diff = 0;. |6 o0 p) n) o- Z: a8 N0 T
* W6 w( @  N& U& i3 g* h" w
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );, D0 n, R5 z. o: y& }
! v( o# R- I/ h# `# \0 [) r7 o
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );! R) C/ Q/ P, @
        ZEROMEMORY( &queue, sizeof(queue) );
. k& _& r! \; f1 x1 i( W, G# Y" c        ZEROMEMORY( &exqueue, sizeof(exqueue) );, d2 C! S) @' Y

1 B; O2 N( U2 j        for( INT i = 0; i < 16; i++ ) {' P- x. x6 t+ g% G
                m_bMute = TRUE;) J1 X: j$ s. I
        }% V  [% M  C5 ^) p$ p
}
5 y: q2 j) N$ `. a2 t- k/ M2 Z+ N% K6 Y& K/ E2 `8 R& G! y7 Z' G
APU::~APU(): y3 h4 O" r+ [+ P' [; Q) q# ^8 G; G
{
- f3 I! \" w6 x8 s. e}
/ A9 b2 |/ h2 M' p, E, s/ @; t$ [7 Z2 o- r
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
# B2 T9 l- `+ O* a{
* Z  s( Q% S1 C$ ]: s7 [        queue.data[queue.wrptr].time = writetime;
& a) p- G8 ^" v( \1 {        queue.data[queue.wrptr].addr = addr;
' A4 `/ W" O7 m+ r        queue.data[queue.wrptr].data = data;8 B2 B1 a" U- M+ d0 b- I( s
        queue.wrptr++;
3 o1 n4 f0 a3 f. b8 r  K" A        queue.wrptr&=QUEUE_LENGTH-1;& G2 b& V1 o( [: K# q
        if( queue.wrptr == queue.rdptr ) {: p5 S$ \, X, d3 Z
                DEBUGOUT( "queue overflow.\n" );
. e2 Z4 L. I: L. C( v* ~( t- F        }
( U# t. m! `* q0 l}
4 S, U6 V% p8 }& `; V) T
8 ]* Z& k5 E  e" b$ ?3 G: BBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
! u) u1 v! E: f; K, B, `2 ?{  ]; S7 [  a, i% h" ?9 f  V4 y
        if( queue.wrptr == queue.rdptr ) {9 @2 B6 i/ ^$ b# ^
                return        FALSE;' \& D0 r# Y; E% Y; E4 d8 P
        }
! e# F4 h. L) [        if( queue.data[queue.rdptr].time <= writetime ) {
+ [. K, `7 i; M                ret = queue.data[queue.rdptr];
% e5 }+ m- O$ l! F% L9 P                queue.rdptr++;
4 Q4 d; j2 h8 V1 _/ V1 a+ f                queue.rdptr&=QUEUE_LENGTH-1;. n* A& Q% C" u
                return        TRUE;, n* o) l/ D& m4 ?4 T" S  I
        }" A! {- F* i4 O! w. B/ ?$ U( f
        return        FALSE;
" d" J6 z: p/ }+ S}
- ~$ n8 D; v4 z" D6 A0 Y3 {1 @: c9 B3 r* `- v! Y0 ]" u
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )3 x4 g0 }8 D0 W* I$ j7 A* {
{6 A& W% I* W0 W$ d
        exqueue.data[exqueue.wrptr].time = writetime;1 W- Z6 l5 y2 Z  c: ^1 w: w. ?
        exqueue.data[exqueue.wrptr].addr = addr;2 `4 q% y: {$ c. m+ T
        exqueue.data[exqueue.wrptr].data = data;& z" C( H) D5 F! X
        exqueue.wrptr++;
. R( b# G& `% K% m! T8 T        exqueue.wrptr&=QUEUE_LENGTH-1;5 f! K$ B) ^/ Z/ x- d7 ^
        if( exqueue.wrptr == exqueue.rdptr ) {
: {0 p% Y: @2 l. n/ H. z6 g                DEBUGOUT( "exqueue overflow.\n" );! e7 N6 J& \8 P
        }! K, e: K+ _1 @9 S7 m
}% _5 i. ]' q4 `$ e! O

, W7 H, l7 M$ z4 F' l* M# d. u5 pBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
5 Q! H8 z% b+ `# F( ]{
7 U3 n' ]1 y/ e. t        if( exqueue.wrptr == exqueue.rdptr ) {8 U4 o8 @2 u2 X) |: ]( ]5 @
                return        FALSE;: c8 N0 c/ L  l$ C
        }
) L. b- \( `3 t7 T/ @5 e        if( exqueue.data[exqueue.rdptr].time <= writetime ) {3 G) G6 b3 q  V8 m; ]9 V
                ret = exqueue.data[exqueue.rdptr];8 o6 ^; X! K/ ~! e0 h
                exqueue.rdptr++;
. I. D; t! m( X                exqueue.rdptr&=QUEUE_LENGTH-1;
! P7 M1 ~/ J* B3 k. G                return        TRUE;& D3 B2 G& C# n  l& J
        }
2 J1 B& Q" d: G5 A4 c. R( q! h        return        FALSE;! |& S# c; T8 P# L1 H% `& c
}/ b+ v- h: `: s; X
: J- E/ J2 I1 x
void        APU::QueueClear()9 z! I+ C# ^! p- m7 y
{
9 J! F/ ?% n. t) H. W+ Q        ZEROMEMORY( &queue, sizeof(queue) );
: {! f; J6 u. v( j; p& j( `        ZEROMEMORY( &exqueue, sizeof(exqueue) );
& P- z3 Y  d; h5 _2 F6 X' p/ w$ ?2 f}# d: J+ X* r/ G  F

* H6 o4 l" m* E! i5 R7 ^/ X  W2 x! Tvoid        APU::QueueFlush()
8 ^  r6 J0 D# m9 J: y5 g; P3 H; V  _{" t4 S/ @% _! L
        while( queue.wrptr != queue.rdptr ) {) G6 P2 F: g* }; q
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
6 E9 w; v+ F1 f1 r, j9 Y7 r7 U                queue.rdptr++;
) X' |6 @- u  Z0 @                queue.rdptr&=QUEUE_LENGTH-1;! l* t$ m' l% ^: \
        }4 B7 I3 c% @% t4 ~

$ [( P& w+ E9 m. @) G) q        while( exqueue.wrptr != exqueue.rdptr ) {: ~* d5 _% P& H1 J
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
3 P9 m) k/ r0 o- f3 X  N/ v                exqueue.rdptr++;1 ]  }/ b. }9 i) H
                exqueue.rdptr&=QUEUE_LENGTH-1;2 q: c" O0 x8 i9 ^" k
        }
1 L& i, m7 j* b5 D* `}8 B0 o( R3 Y2 Z; x( {

4 \5 \+ d! w; T, r* {void        APU::SoundSetup()- O; V( d: T" ^
{
$ x( n1 Y1 k6 e; |1 |        FLOAT        fClock = nes->nescfg->CpuClock;( K6 V, g/ f' ~% A& B* c% Y
        INT        nRate = (INT)Config.sound.nRate;8 R5 c+ s! Q6 p& T& `2 U
        internal.Setup( fClock, nRate );
! e4 d' ]1 w- A        vrc6.Setup( fClock, nRate );
3 w/ Y9 n5 S2 K8 m: Y        vrc7.Setup( fClock, nRate );$ p6 x. g8 E! H  G2 a% M
        mmc5.Setup( fClock, nRate );4 w" h0 H5 @$ Y8 H& p* b' O  x! i3 g
        fds.Setup ( fClock, nRate );
' l; E; C5 p# a2 r2 Q        n106.Setup( fClock, nRate );( z9 z. Y( G& m) `
        fme7.Setup( fClock, nRate );) g" e7 C* Q5 |7 P$ _" m2 u7 G
}
3 h" F! N6 X( }( [" I# s7 b4 G' J2 }9 q6 ~) g4 z
void        APU::Reset()
9 _" |. r/ V2 Q" m" P{. A# r8 o1 X) q1 s  ?7 Z
        ZEROMEMORY( &queue, sizeof(queue) );
0 E, ]) Y! A# \5 I& N        ZEROMEMORY( &exqueue, sizeof(exqueue) );5 \1 \; f& B# n, r& H

  k) y" G2 ?6 v# ?/ W4 e; D        elapsed_time = 0;
: w, S8 u7 s8 R, e6 ?5 o
; k& k# W1 U! h! g5 r$ E        FLOAT        fClock = nes->nescfg->CpuClock;' D' y' j. \, U) z3 a
        INT        nRate = (INT)Config.sound.nRate;
0 X+ j- Z7 C5 m# j& g3 O  O2 @* Z        internal.Reset( fClock, nRate );
0 N* W5 Q1 Z2 S  W- s  n. Q        vrc6.Reset( fClock, nRate );, y) B8 d# ^( `: H: T) b: n, ?* |
        vrc7.Reset( fClock, nRate );
9 x( S1 R" h' A- [        mmc5.Reset( fClock, nRate );
: w% @1 P  P6 X; h+ s        fds.Reset ( fClock, nRate );
, F) i9 _1 p+ O        n106.Reset( fClock, nRate );
2 ~% M8 x& P1 u! e- S, B- ]9 g$ ^        fme7.Reset( fClock, nRate );# ], [$ ]' W0 K5 R* U

: L; J# a5 @# `        SoundSetup();% @, _; L: X% |3 Z
}
/ N8 [% j* E6 \% C$ m1 j+ {
5 c0 V0 \, Q- ]* ?void        APU::SelectExSound( BYTE data )
8 u  c  S; c7 ]. Y. ~! ?{, |; U5 k. R2 E- g
        exsound_select = data;
  a9 n% V- r9 z/ o3 S1 o}
3 Y1 V, p; w1 b- A, T
7 d3 J& N: G2 X" ?BYTE        APU::Read( WORD addr )
2 H8 l. ~* w( t& X% [2 V{5 b0 h* Y" f* M% Y! S7 J$ \
        return        internal.SyncRead( addr );
: a) _/ b% a( z6 \}! _* [% K0 P2 ~* W4 j
6 L$ s9 z1 |, A+ z
void        APU::Write( WORD addr, BYTE data )0 x- ~% P* Q  j  o5 {
{
& _' B5 ]) {4 s8 b! ?, V        // $4018偼VirtuaNES屌桳億乕僩
6 {3 s. ~) r# F" E$ f  K        if( addr >= 0x4000 && addr <= 0x401F ) {8 D9 z4 D* J% Z; o0 V) L2 m
                internal.SyncWrite( addr, data );
" _' B% x8 Z$ E4 O8 p2 |; f                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
% K2 @* U" c0 w5 ^0 G* r6 h        }
8 }7 V: N) B4 N}8 T; L- X- U+ Z# D% ~, B
  O, G# P8 ~5 M7 W) N8 ^& W7 d
BYTE        APU::ExRead( WORD addr )
5 w8 f) L; K- Z! }{
/ k& C4 }0 v, a0 [BYTE        data = 0;6 P, ^$ x* A& \9 `3 A
( J3 j5 S+ }7 Z, s
        if( exsound_select & 0x10 ) {" ]! Z" S, |/ g; k
                if( addr == 0x4800 ) {3 {* u  K( s3 J# O
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );2 {# q8 e( v) }. I9 @6 c" `
                }
: ^( y  [7 W+ l9 I. }3 f5 ?        }
$ p8 Z, y+ m& Z. |! d        if( exsound_select & 0x04 ) {# l3 T+ u' k  I- ~8 q! a7 f3 l# ~5 i0 W
                if( addr >= 0x4040 && addr < 0x4100 ) {6 |2 ~2 j1 J1 i( k8 k/ g# Y
                        data = fds.SyncRead( addr );9 Z( z  U. _, T% F9 O0 s( c
                }
# v5 p8 r! i1 k2 b9 x9 K        }
7 D6 J. e. r$ M, N' R- r        if( exsound_select & 0x08 ) {5 n: w. f1 v4 f  K# G; [( S
                if( addr >= 0x5000 && addr <= 0x5015 ) {1 L0 w; }: |3 M# h3 O; w$ f
                        data = mmc5.SyncRead( addr );* n- A1 |8 O9 [
                }
; h) G, x, r6 E4 f+ B        }  J) b1 U1 \5 S8 o) |3 N4 o; Q

. G2 q. G! X; j, ?- w" m) x% B        return        data;
7 N: V) w. u0 A: @. N}( R" Z0 U& {8 e8 U/ B

: @" j9 y! Q" U) Y3 L& rvoid        APU::ExWrite( WORD addr, BYTE data )% n, j+ u! n  F
{
* A& U3 h- Z% p  y6 @' J        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
3 i0 K0 A3 B: b0 `( q$ _" @
! G, O! f# Y9 x. _4 B- D        if( exsound_select & 0x04 ) {
0 r, A$ R, a+ h( y5 {  T' e( @                if( addr >= 0x4040 && addr < 0x4100 ) {
5 Y. y# P$ |6 e% D8 T                        fds.SyncWrite( addr, data );3 A% V( r5 ~. {( l' i7 l+ Z
                }7 C7 B" `$ |8 g" p# K
        }( s( z$ {4 S0 A" e# g

7 R6 c" z- J4 k, b  D( Q        if( exsound_select & 0x08 ) {9 C5 i: Z2 h% X9 \7 u+ u0 o2 j
                if( addr >= 0x5000 && addr <= 0x5015 ) {
3 h8 L) |1 R; b, p6 F                        mmc5.SyncWrite( addr, data );
- z1 U+ ]9 r9 r! i, x7 l; n                }
: J9 c4 T7 _0 F/ E        }8 c3 C6 k  h' U3 e
}
% Z$ |8 D8 }: c$ k
0 `  U  I" G, i# m0 Xvoid        APU::Sync()5 B6 [& |. E; `
{
2 O2 J/ l" H% N1 E! v}. J( P! _- t. Y& s
/ H/ t  R% K; J; q+ x  |
void        APU::SyncDPCM( INT cycles )
/ f7 n3 p! w! M" B  Y{
3 q3 M5 U! N( n" {; n) c        internal.Sync( cycles );8 l# y; T& k4 u1 Q+ C1 p' R0 [

; m! v5 |8 h! N. N4 w' v2 u0 q5 g        if( exsound_select & 0x04 ) {4 [1 n) Z5 I$ y9 I) o
                fds.Sync( cycles );5 e2 {) }6 l  a2 ?
        }
, C! k9 [, u" S( u( |        if( exsound_select & 0x08 ) {/ R% P, N, c. i  _% _
                mmc5.Sync( cycles );
2 `( A8 O0 }9 N& f4 {# O. c        }
$ _. s; `: J3 _8 z: \1 p}
: Z/ O% |! O6 B. l9 N' f& u; Q8 y9 w# [1 q( [
void        APU::WriteProcess( WORD addr, BYTE data )& E- R% T+ t, F5 h8 O
{
: L( x! F! b2 n7 m0 ~        // $4018偼VirtuaNES屌桳億乕僩7 @4 v: V* `+ M/ `" B
        if( addr >= 0x4000 && addr <= 0x401F ) {7 D8 K7 @/ i3 x
                internal.Write( addr, data );
6 g- C  I6 v7 c7 A) d! v3 N        }7 o$ [* G5 Q1 K/ D- N. j2 e+ y' ?
}4 j" a) K) _; a0 C1 Q3 u  M: f
6 c1 e9 k, _0 x7 N- p% H4 L9 W
void        APU::WriteExProcess( WORD addr, BYTE data )$ Q6 V% }; n. \7 L9 D
{$ ?; B/ T+ C  j& A7 S
        if( exsound_select & 0x01 ) {  Z$ e0 N1 I' Y$ w+ x" k
                vrc6.Write( addr, data );
& n" e( i0 s# Q2 T        }' H4 I5 t3 L. p* \5 ^3 B
        if( exsound_select & 0x02 ) {
2 T; @- t5 c/ {% N; K                vrc7.Write( addr, data );
& y& |  C  r* R1 M" \        }5 f0 B, h2 p. ]; O3 m$ a" v0 E
        if( exsound_select & 0x04 ) {0 A& \+ b0 ^& r# Y1 D
                fds.Write( addr, data );6 n# ^0 h( J% ~, V
        }: |9 ]1 c( n! j
        if( exsound_select & 0x08 ) {
  S# ^5 {9 K9 a- e                mmc5.Write( addr, data );+ ~$ ~. [* p& u1 ~
        }# d5 ^% G0 _8 n  l' N2 O7 G
        if( exsound_select & 0x10 ) {0 z  k- |: Y, O6 n  j. y
                if( addr == 0x0000 ) {+ ?. b5 R- s& ]4 T2 L
                        BYTE        dummy = n106.Read( addr );
5 O; x; \8 @7 E: |0 k                } else {# l- _& ?& a, v, h2 J
                        n106.Write( addr, data );
7 b9 J# U/ |/ P5 q. @# }2 k                }
8 V. I* N+ G/ ^        }9 I: ^9 j8 \3 m7 p( K; |4 n6 R
        if( exsound_select & 0x20 ) {+ n: f# c+ P4 g" G3 I- m6 a) o! ]0 O
                fme7.Write( addr, data );
6 Q; [8 I1 s* x, S1 D- X        }* z7 _. M6 l1 N0 Z4 V
}% @0 Y' M( I$ n) M7 `; i- n
0 b8 ?0 B1 B/ l5 o9 Z8 L0 n3 ^. {- I
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize ). t5 Q  j7 u4 C& [8 t2 {1 N
{
1 X* A% d/ L) L, T: x" fINT        nBits = Config.sound.nBits;8 b6 s9 G! W4 t
DWORD        dwLength = dwSize / (nBits/8);  G: @; t* K$ F
INT        output;
8 g  R, _* h7 eQUEUEDATA q;# S$ o$ S% H$ l
DWORD        writetime;
4 e4 a4 {5 |: Z6 Y1 |$ h- S% `4 l! T9 A+ w& S
LPSHORT        pSoundBuf = m_SoundBuffer;
+ x9 ^% ]% T) a% E' x" J4 [5 EINT        nCcount = 0;
5 f6 v# J0 ^6 C2 D3 w6 W  }& ~3 m+ y  [9 }8 {6 w5 ]
INT        nFilterType = Config.sound.nFilterType;
9 U5 Y) N/ e$ h3 z: K' J% L  e/ i* ], T* `& V) B- R' z3 W" `- z+ z
        if( !Config.sound.bEnable ) {
. H8 ~: ~' w. G1 c                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );+ h8 s" r) x/ U) Y# o5 v$ v
                return;# |+ R% k! R6 I
        }
* `. g( ~3 P! ~3 ^
, ]# z6 T% F+ A: n) y4 f% g! [        // Volume setup( J9 ~- h6 X4 ]; l( {
        //  0:Master& ]( c4 K2 d. q* [1 F
        //  1:Rectangle 1
# F" Q( ~3 b! _  U2 j        //  2:Rectangle 2
8 d9 V5 j3 W0 q) Z% F  h        //  3:Triangle- |  Z0 M" L8 j6 L+ |
        //  4:Noise
5 v0 X0 o9 M; {7 R! d4 b6 G. l        //  5:DPCM
4 n0 Z  b- H& Q9 A( O        //  6:VRC6, y! e$ b+ X5 V' C# m
        //  7:VRC7
' W' b$ g" F, e6 ~# T" C9 U. d8 \        //  8:FDS
4 Y9 P; [4 Z0 R, j$ ?* i        //  9:MMC5
+ ?" W+ Z6 A) ?7 [        // 10:N106# [9 a8 W0 A* ^* P+ G% m) k* ~. N
        // 11:FME76 M& `1 T1 m4 D
        INT        vol[24];* `9 ]; u* I4 H. w8 R
        BOOL*        bMute = m_bMute;" _7 I& |9 H6 @3 O+ ^
        SHORT*        nVolume = Config.sound.nVolume;
/ y9 c0 O6 M! l' B
* ^* k6 j  x) F# _1 r        INT        nMasterVolume = bMute[0]?nVolume[0]:0;3 X; r/ N! H/ L1 X' d

- O5 }1 I* ~- X0 b- G! b; T" d        // Internal
" r1 q: L9 _4 a) A# o        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;' E' K3 W) u2 A" ]" u
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
/ W$ t  E4 v! m; \+ E" d        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;4 ]3 O+ D3 D4 e+ N: {9 H' l2 v
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
; ]% Z- r- t; V* h        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;$ E" B  U9 C2 P/ B3 r

6 u$ n1 K" h/ y) h        // VRC6. I* _1 i* O; f* F" ~
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
3 s$ e0 Z5 K9 f1 P' h8 s% i) w        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
' s; B8 d9 [0 O$ O        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
* A- U/ N2 Y( n% ~, `9 f
. @" k' i# V' r. D# c% V, t! v  F        // VRC7$ H, k8 Q8 P4 x$ H/ o8 @! ^
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;# S& o2 q( |$ K, y0 U1 r
$ d$ S4 {6 c, D0 r; s; m6 }
        // FDS  }0 r' _1 M  j: F0 `
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;$ l$ H2 M) _" ^
. ]$ W  n: R) W8 k& |& b8 w8 p1 O
        // MMC5
2 s8 t( z5 d6 y        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
7 ?5 T* {7 Q* d" x+ ]        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
4 u6 o3 o) Z; Y0 Z  s0 y        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
" ^7 G, N5 W- q! C. m  Y' z# t" w
        // N106
  C, f0 @  e7 j& ~9 Z: ^" h        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;2 P! n5 K4 j) ?5 G( C/ x* {5 C
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
6 |1 g( S) W$ F& a0 A        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;5 i) M% `, A2 I0 M- s
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;, \/ a- \/ S7 g/ `  E. J6 ^
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
+ X- N6 F$ S0 b, a        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;% Z' D4 Q* P* O3 X9 U
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
$ v  g- i3 N/ {1 s" G        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;2 B. P( G/ k9 A- |0 c+ |8 a

# _4 B& ]$ Q6 @1 \* \        // FME7
' v2 ~. U; p; v( E- b, ^) d+ d        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;7 o+ ^  S; e2 s5 X! g9 L: E
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
/ u8 {6 R+ m2 T! a; D$ Y2 n) [. `        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;* s' N! E" x, W. ^; Y5 G1 a3 i) [8 D
: r3 L& C6 V3 `! L
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
5 t9 }" f0 R+ |: O" T4 ]        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;# ]4 R4 s# k, R

( G' j% r! Q2 E" p3 O+ u        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
4 T* ^# ^; d( b- r        if( elapsed_time > nes->cpu->GetTotalCycles() ) {6 Y3 \/ D' H6 H: T! x: X  q; E
                QueueFlush();
) J: h' M$ e  o! e7 u6 r/ I3 Y        }
1 H9 ]& X: `0 {; m( B
; j5 {/ K( F9 h; }        while( dwLength-- ) {' u; p+ }$ u" w: D  U0 Z
                writetime = (DWORD)elapsed_time;
. U3 |7 U1 _$ }% r+ C0 C. q/ l( d  k/ Q; d) i6 j) h
                while( GetQueue( writetime, q ) ) {
# E( C3 E$ Q5 [                        WriteProcess( q.addr, q.data );6 T$ w9 r1 ?* e$ z% r
                }
- B# ~. q" Z* U  t: Q2 G" m& @1 P  g
                while( GetExQueue( writetime, q ) ) {- |) ^5 p) B9 w  X  X' C- v/ F3 y
                        WriteExProcess( q.addr, q.data );0 A9 l- O4 Z( T$ _6 ~4 H5 P
                }6 O& L1 u. g/ h) v

3 [* ]9 D4 @' r- a0 Z                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7' K' `8 ?8 D7 i- O0 Q5 Y5 F+ D
                output = 0;/ y' R* q5 X- z4 k/ ?
                output += internal.Process( 0 )*vol[0];: b2 `9 G9 y! z  V, @
                output += internal.Process( 1 )*vol[1];+ f# M) _, n& ]/ \
                output += internal.Process( 2 )*vol[2];
! p, E9 S4 [; ?9 k                output += internal.Process( 3 )*vol[3];
& }4 N8 ]! T) H; b8 I( N4 ~1 ~6 c0 X' P                output += internal.Process( 4 )*vol[4];' [; o( B4 X! |: R0 S
  C: Y" G4 c$ N5 R  j
                if( exsound_select & 0x01 ) {
5 \! \3 E! j0 ?$ ?" z                        output += vrc6.Process( 0 )*vol[5];  P) c& R; s, O& e9 k$ L- m+ n" n
                        output += vrc6.Process( 1 )*vol[6];
+ Z" N0 D9 ]+ \                        output += vrc6.Process( 2 )*vol[7];* H! j2 F( R, T9 P. l' N& U8 N, {" ?
                }- }; h6 H: T% L8 a, S  x
                if( exsound_select & 0x02 ) {
3 o4 p  d8 I% x" L/ L                        output += vrc7.Process( 0 )*vol[8];: {/ u* U7 {! b: h
                }* b$ x, d! h8 B0 U2 I1 q# A
                if( exsound_select & 0x04 ) {
( V0 o  J* }, m3 i6 z7 b' N                        output += fds.Process( 0 )*vol[9];
7 s" {8 l% o( R                }% V, h8 w2 Z. b4 A0 F) o; v6 a
                if( exsound_select & 0x08 ) {7 r# y7 g% @! s5 O5 Z$ R
                        output += mmc5.Process( 0 )*vol[10];
8 G) {& L, ~! \                        output += mmc5.Process( 1 )*vol[11];. N9 @" K' G% k# N; m
                        output += mmc5.Process( 2 )*vol[12];) @9 P" b$ l7 P
                }; p& }7 h9 n6 q
                if( exsound_select & 0x10 ) {
/ J; b9 n8 r3 u6 j( H4 M# P, Z$ r                        output += n106.Process( 0 )*vol[13];
( D# K' d+ d6 s1 {* X9 `                        output += n106.Process( 1 )*vol[14];4 H/ k) D8 w1 @$ a+ o
                        output += n106.Process( 2 )*vol[15];3 u8 o2 c4 g2 u% \# A
                        output += n106.Process( 3 )*vol[16];2 Q1 n9 V* J2 @* A
                        output += n106.Process( 4 )*vol[17];6 t5 E' v( E+ |7 A$ v$ I
                        output += n106.Process( 5 )*vol[18];
8 B9 }/ x8 `+ n# O8 }, V                        output += n106.Process( 6 )*vol[19];% t$ c4 |3 y( y$ y4 K. T+ |
                        output += n106.Process( 7 )*vol[20];
) D5 X# m+ q5 Y# f                }
# b- ?2 C$ f7 e4 C  x* o; h$ ?% I                if( exsound_select & 0x20 ) {
- f/ n' h+ M8 E6 p+ N                        fme7.Process( 3 );        // Envelope & Noise
' {  h6 r% ~3 N- q/ B5 l2 y6 Y                        output += fme7.Process( 0 )*vol[21];( w8 N, s2 t$ i. i
                        output += fme7.Process( 1 )*vol[22];- y0 N; O1 W/ @5 v3 B/ b2 m
                        output += fme7.Process( 2 )*vol[23];6 M4 E: q, [- v2 S
                }
' p+ f8 x7 x( ?: L, W) ^. |- ~6 h( |8 f' j' L1 q
                output >>= 8;
4 W  y0 C( N! L
# s# o9 b- n: I* h! t' j                if( nFilterType == 1 ) {/ @! B' F, t' M) F. l
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
: I5 p1 u/ M7 X' y5 v- I                        output = (lowpass_filter[0]+output)/2;3 n6 A  O% t5 _) e' F5 n% H
                        lowpass_filter[0] = output;8 a0 v: K, P  d% i
                } else if( nFilterType == 2 ) {6 \& q$ a3 o  ^5 p9 q7 {
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
# J/ y) G2 h: s. W6 A                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
) d7 v& s( X! z8 L6 O                        lowpass_filter[1] = lowpass_filter[0];
' {$ F7 z) K8 P! i* o2 f                        lowpass_filter[0] = output;/ D( b( |, w# H
                } else if( nFilterType == 3 ) {
* T& L9 F4 I/ Z: k+ \! u. K: B                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
1 r# }$ k5 \: v                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;# b- B; z+ U/ G( Z: Q
                        lowpass_filter[2] = lowpass_filter[1];
8 w3 P/ j* a2 W, d% V/ m" a- m                        lowpass_filter[1] = lowpass_filter[0];4 Y5 o. O" t! S$ n% r& z+ H" O
                        lowpass_filter[0] = output;8 l# |5 ~2 U' d  U/ h" t
                } else if( nFilterType == 4 ) {
5 j9 q( m% h( c                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)1 P* b2 L+ O0 U1 b. X; w! s
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;2 K+ N8 \  i: w% l' P# I
                        lowpass_filter[1] = lowpass_filter[0];7 _* ^$ L1 t: W, E
                        lowpass_filter[0] = output;
" _( u: S- i7 R6 w! s                }, N. r! n, s) Z, |4 L/ E1 t

4 Z* |  ~3 i0 Y9 W% }  B#if        0/ u, O# Q$ g% H0 S. a: {
                // DC惉暘偺僇僢僩2 ~1 K1 O, D$ A1 _; w: `
                {
( E) U5 [+ k* J  C                static double ave = 0.0, max=0.0, min=0.0;3 ^+ ^4 o4 C- p% G% ?" ^9 a& `
                double delta;+ n& N8 r$ l: b) |
                delta = (max-min)/32768.0;* E6 k0 F9 _  G& d* d, T0 g4 y% _/ V
                max -= delta;
' u7 m% b! s; O( T                min += delta;
2 c, U  T) s, N9 W9 e                if( output > max ) max = output;
& D* R( g2 U* M8 c                if( output < min ) min = output;8 }$ Y1 W/ a5 d
                ave -= ave/1024.0;' ~/ @/ b% I+ ]; c
                ave += (max+min)/2048.0;
8 K+ ], y8 r/ q  T/ L" A                output -= (INT)ave;/ J2 D3 I9 ?( N" q. w8 g
                }0 B: V9 b9 n! D% ~# J
#endif
* x8 Z( s+ U4 g, l8 v#if        1  ^. e" u+ |# E
                // DC惉暘偺僇僢僩(HPF TEST)
# q+ e% y' @6 y7 V; D& l0 [                {1 e: P/ |+ P8 K2 W
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);3 I6 c8 N1 f( Z; j
                static        double        cutofftemp = (2.0*3.141592653579*40.0);$ n  m* ~  F( c( V! O/ x
                double        cutoff = cutofftemp/(double)Config.sound.nRate;# H2 R' z( o3 ^0 x6 q, H# S
                static        double        tmp = 0.0;. D7 y# K; w( z
                double        in, out;9 j, t3 o& l1 m$ o  n" ^
; L4 O( p# Q9 a8 v
                in = (double)output;- o. U7 ]1 J* K! ?
                out = (in - tmp);
; o3 z9 B/ p* q9 x6 q# C: b                tmp = tmp + cutoff * out;
. s2 o2 Z" d  W( A1 @% M
" B0 l' m1 q! J0 u4 y3 [' P                output = (INT)out;
: @3 q% m1 R$ p                }# K) f4 |( n: Q
#endif
5 l  E4 h5 b/ C5 `. B9 v, z' A$ N#if        0
7 x7 x- n, m* D# a2 b                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
. x5 v; o9 ^8 [% W; K' u                {
! s- u' b$ H+ K4 P                INT        diff = abs(output-last_data);
9 O; T* V$ L( o% \  g                if( diff > 0x4000 ) {
6 V. M7 e  U3 [- g; ^- z7 p                        output /= 4;. c# i8 r' A: j, `$ U8 E
                } else ! o! _: q5 A2 O( H! ~* I- n
                if( diff > 0x3000 ) {' L* Q6 {0 r2 D' X0 a6 w2 P/ z
                        output /= 3;
+ h7 R2 V- n, g                } else
- [5 d& f* y) ~" H, u" i                if( diff > 0x2000 ) {8 ]) ~3 L' t7 \5 T
                        output /= 2;4 ?# l1 O$ C+ n& i
                }
, _* b8 O% A; o) H2 c. I  q2 [4 L                last_data = output;1 t- [7 q$ ?& |  x
                }7 X7 o1 q  m! ^: F. Q6 p
#endif2 V- L' c( i8 `7 C
                // Limit
/ Y  ]% {" b; I8 }; ?* \; ?7 C2 q                if( output > 0x7FFF ) {
. w, Q# N5 b9 E8 ?. k, ^: m, d' A                        output = 0x7FFF;& j. {) j* L$ s+ b
                } else if( output < -0x8000 ) {+ Q8 O- A6 W; h" @% E  Q0 H9 e& N2 \
                        output = -0x8000;
1 k  z9 @7 H( L0 L/ m. P                }+ F+ A4 x) T6 [2 m9 C
# c7 L) K& p" r% P, Z: `1 u7 D
                if( nBits != 8 ) {$ Z- J& J6 |- j% C- t- o
                        *(SHORT*)lpBuffer = (SHORT)output;
) i5 k- a' k3 s4 L) [/ j6 C                        lpBuffer += sizeof(SHORT);
" S7 z' _7 F# I- B- a                } else {
; J# }# c5 T+ c) C# c0 t                        *lpBuffer++ = (output>>8)^0x80;0 ], Y& e$ d; T$ P
                }/ K# l4 X+ s3 D7 E: E4 r/ r" J5 l

$ A% E- s' Y7 C3 N* z1 j9 f                if( nCcount < 0x0100 )
2 |- u. ]0 Y. Q4 G2 i5 O. c                        pSoundBuf[nCcount++] = (SHORT)output;0 p; o& v, n& |8 Z( I8 Z

  E  R2 s. k7 p, p. U4 g//                elapsedtime += cycle_rate;& {; g8 \5 l7 C: V* h% d
                elapsed_time += cycle_rate;
6 f. f% L: L+ P5 n2 B, I        }
+ h# R5 g& D5 s  v: l; k, E6 d- c; F& _) y# Z9 z0 ^
#if        1
& z, N8 _' n% B) o3 J: F        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {4 @% j: r! l9 h5 V7 d$ u) N* P
                elapsed_time = nes->cpu->GetTotalCycles();" B& s8 |9 t$ t1 G6 L
        }
+ W: P. b3 K- X$ ~9 t        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
  a9 W3 x/ o, ~# s                elapsed_time = nes->cpu->GetTotalCycles();
: \5 X1 f, F( x  O        }5 K+ ?5 j4 V! {3 _0 r4 G9 j
#else
; W) M2 `4 c. }8 q( G+ `        elapsed_time = nes->cpu->GetTotalCycles();! @. t3 I7 N& A* ?. o
#endif7 g/ [7 ^+ N, |5 C; J8 k& J) `/ l
}2 R5 l8 f- d3 y) `! c- [
6 ~. K- Y3 _' v1 I  E! y6 w: J. q
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)7 @( i6 t0 X" C& @. D' Z/ Y
INT        APU::GetChannelFrequency( INT no )- F2 e3 S6 B6 {
{
$ \0 x; g; s, R: ~) W  b        if( !m_bMute[0] )
' e/ R  c. Y& A' H4 w! L5 w                return        0;
+ c! N4 K3 [& ]! V3 n1 ~: B0 W% B
& ^6 O$ M- x* o        // Internal
6 r' p2 k7 p; h, n- U! }        if( no < 5 ) {
; M, q" C; N7 {3 `0 B$ s0 c                return        m_bMute[no+1]?internal.GetFreq( no ):0;3 e1 }  Y5 w7 y8 m
        }! r; k9 r1 u" g9 E) f' f
        // VRC6
' ~  w3 x2 J0 K# {! ]7 v( Y        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
4 X) a" d' N) L4 [                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
1 I9 K1 f4 U: O! a        }
2 n& X) K' ]+ V' [, X8 ^        // FDS. E! V' s0 j6 ]8 t: s/ e
        if( (exsound_select & 0x04) && no == 0x300 ) {
% P$ r- ~6 `0 ^9 Y                return        m_bMute[6]?fds.GetFreq( 0 ):0;
: I& F/ g3 I2 O        }2 c+ `/ Q. \+ n* Y( s
        // MMC5, u' Q; R1 K. v) {; P( N! }, b6 ^  b
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
+ }' J5 r* _9 C, i: ^8 _                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
+ j- x8 c- g% d: {. _; V        }+ C/ }# v4 a% L. V9 D" j) L
        // N106& N- Y+ F& F+ J' N$ ?; Z
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
0 o* p& a3 F, ^. G$ \                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;# \. Y3 r. {- ?  W% d( P! [5 ^8 n
        }
+ v5 ?) ]6 e7 S        // FME7
' X0 U8 y; M$ N) W* V        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
% I2 g+ I3 r$ \" J) I                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;9 ]. R  A& B) f6 Z; @7 f
        }. s  F/ b$ x/ g: N
        // VRC7, m9 L1 E% Q  o, l
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
4 w; q. Y9 S. Q/ C                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
2 }0 s( E! u+ q2 W/ U  W2 f, D        }
$ K, M& \2 D" W2 s        return        0;
  ]1 o, G5 ?5 E) g6 C}, V  ~( J- [  I9 y

3 w3 p/ E* h% u0 b" P: c// State Save/Load: A4 X& V8 J4 o9 H+ [% N3 g) ~
void        APU::SaveState( LPBYTE p )' s# k# Z# A% B. t9 n' E; K
{9 q& x8 A1 [3 E0 I. L
#ifdef        _DEBUG8 q2 u! a1 h2 N2 j" S
LPBYTE        pold = p;- R. I: m, j) ^# z
#endif( i  k. w4 p; T" L0 u
! `. ]+ G3 }2 L3 Q
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
  S" E; D6 \( _! |# @        QueueFlush();& [; J0 T( @9 [
5 z3 B! K' f$ Y, T
        internal.SaveState( p );
* n/ m! |3 r" [) j) E" [' d8 p        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
* y6 g- _/ n) U! z, N9 `
+ J# L, F$ S' y, L) x        // VRC6' y( D" I  k5 M( |: F" [
        if( exsound_select & 0x01 ) {' _: }% ^: m8 x6 k4 J  o
                vrc6.SaveState( p );8 J. h- m7 X% ?/ Z2 y
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
3 z* X2 R5 C4 o) V9 x- ~6 x        }) ^# _, F. |1 J+ t/ G
        // VRC7 (not support)
1 J6 o" P2 ?) A& h$ I4 _, V! j3 h        if( exsound_select & 0x02 ) {6 q0 y8 P. {& V$ W, }  M' G
                vrc7.SaveState( p );
( _6 V$ b/ S( }! a" {                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding: q  P- [9 e5 V
        }
4 J1 `, K% q4 ?/ u9 j6 W7 F        // FDS
( z) E  k! g/ H' T        if( exsound_select & 0x04 ) {0 g  N6 m$ h8 p( D
                fds.SaveState( p );) ^9 O+ Z, n- G; O$ D/ i
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
! o  y# J  O6 [" O# W& Y$ C        }
) }  u" _+ `4 q5 [        // MMC5
9 C3 c: |  j8 I5 W4 k        if( exsound_select & 0x08 ) {1 W. N' k, {* n3 h8 J
                mmc5.SaveState( p );
- F1 b. [, z4 R2 m* A' a- \- t8 Q                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding* \3 ]$ Y2 O3 [
        }# ~, t+ ]" I( [4 {
        // N106
3 g% m0 A' D, b7 Z! T        if( exsound_select & 0x10 ) {: W! }) v4 I5 G4 k3 u8 @  Y! m
                n106.SaveState( p );3 \7 r' ~' H1 \  E7 v
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding+ ^% t# n( O9 H7 h0 o& T
        }
' Z  w4 `, [% e$ M) `        // FME7
- I% p# K0 \6 d  f. M, }        if( exsound_select & 0x20 ) {# s3 W% l9 b9 j4 P1 k
                fme7.SaveState( p );
0 a9 E. K- }) y( \1 ^                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
. D! B) S. e. s8 ~* d        }0 N/ u2 R+ I; X, D/ _" P
4 L: T$ ]2 F% `- ]3 s
#ifdef        _DEBUG7 \2 m  a- A2 F9 I) f
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
7 W' h6 r) T1 I8 P/ r. F2 ?#endif: l& c  x) S0 m& z% U$ d
}6 O8 |6 w5 n5 N) z6 r4 z2 `
# |- Y/ ^1 v( ]0 t; G
void        APU::LoadState( LPBYTE p ), C, h! a- h, J1 t
{
& Q0 k# Y0 g8 d        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
: ^; ?% [4 m6 }. v; v        QueueClear();* Y. Z& q% J/ b" [1 G; N6 p

' M% u) L- f! b& x3 [        internal.LoadState( p );6 T1 K" a" S2 W8 C3 E$ q
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
1 p3 x/ L0 M5 X5 c
5 W: W$ Z' z( ]$ d# G. b        // VRC67 f  a$ l( H) M1 X: ]" [7 v
        if( exsound_select & 0x01 ) {$ H% o/ d% y* K* A3 A" x
                vrc6.LoadState( p );& ~# A7 t$ Z2 X2 ~# w2 a: R+ Q; o
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
- o2 ?  C8 X4 U5 ~        }  _; ^) C, Z( ~5 q
        // VRC7 (not support)
! O. R. T3 T& `. b' W  s        if( exsound_select & 0x02 ) {; }  B& ~: @/ ^" ]& ^
                vrc7.LoadState( p );! ?$ d2 f' h4 P
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
# p- A/ y! ]5 r2 G8 ~/ P) [        }& |) `; M; E  q* I- V
        // FDS
; r7 Z" G8 f0 b4 ]. b3 X9 W        if( exsound_select & 0x04 ) {- p& ~7 u- _$ @+ e( E) x) u6 e! ^
                fds.LoadState( p );
2 q( H  P( Q$ ]" u3 j6 ~                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
3 ~6 _: w" z$ J: \3 U        }
  J7 j( [! l+ h( j        // MMC5
) f+ W( m" e: ^        if( exsound_select & 0x08 ) {8 J( |5 A  L) m) c5 w* f1 W9 R
                mmc5.LoadState( p );% O7 F6 g" P5 x8 k" w! E
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding( F5 F; ?" b( z8 O
        }
; z  y. S% q, _; p; @        // N106
/ E. N* L8 w! q( I3 j: {$ K- y* ?        if( exsound_select & 0x10 ) {
7 z! {& p6 T% G( M                n106.LoadState( p );
( @! e$ H% s* B& c) j2 N                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
- Q& N+ v( t, b3 |/ A) g        }
/ ]9 _& C! d0 B6 J# b2 D, G        // FME75 v" X2 x' [! p
        if( exsound_select & 0x20 ) {: x* @# p! ?7 l$ v
                fme7.LoadState( p );
6 }* b+ k; p9 n& _2 ]% x) b! a                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding0 i0 m8 C9 L5 g2 G* Y
        }) `2 L  z* ?) W2 A1 E' ]3 c! T
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
8 K$ |- g- r. H$ C5 A9 e; Y可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。4 k" B; i  W5 u) u( X
感激不尽~~

' v! E. |- G, u3 E恩 我對模擬器不是很有研究,6 }4 {/ F0 z/ p' h0 D# J0 m" c5 k6 J
雖然要了解源碼內容,可能不是很困難,
, I; t) O; @) [不過還是要花時間,個人目前蠻忙碌的。
4 g$ L+ W4 q# V/ m: c* N
0 D- l" j: Y/ p% e# V給你一個朋友的MSN,你可以跟他討論看看,
$ ^9 }  @5 _# G: r( B2 P他本身是程式設計師,也對FC模擬器很有興趣。
3 w2 k5 e2 `* B3 Z' B4 s$ J% M3 j3 U" S% j6 R3 B0 S$ `2 o
MSN我就PM到你的信箱了。! R" }* V4 i3 [8 b! i) K& k1 m# @/ [

4 j+ E  `8 J5 u6 `0 S: g. c希望你能有所得。

该用户从未签到

 楼主| 发表于 2009-11-9 13:23:59 | 显示全部楼层
呵…… 谢过团长大人~~

签到天数: 80 天

[LV.6]常住居民II

发表于 2009-11-9 16:02:29 | 显示全部楼层
团长的朋友都是神,那团长就是神的boss。

该用户从未签到

发表于 2009-11-20 13:13:25 | 显示全部楼层
原帖由 独孤残云 于 2009-11-9 13:23 发表
2 S/ [  y; Q: N1 s3 s呵…… 谢过团长大人~~

* B+ N& ]& k' c2 Q; w) I
1 _0 f$ p* y& ?9 ^, {哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 & B* h) j; ]( p# e
团长的朋友都是神,那团长就是神的boss。
  r7 z1 p# d/ s) M1 G3 l
哈 不敢當,我只是個平凡人,
) W- r8 H* ^' y  J" ?要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
# h' w9 w% f! k' N8 K2 ?" y9 g+ YZYH
6 v+ m8 K! v- L( MQQ:414734306! H9 s. N3 [7 \, C5 `) ^7 P
Mail:zyh-01@126.com
5 ^% b/ G2 o0 X+ y- c! z, R2 S$ C. t! b- K3 r8 ]
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

 楼主| 发表于 2009-11-27 09:48:23 | 显示全部楼层
再次对团长大人和悠悠哥的无私帮助表示感谢~~

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
8 C  U, R; U! \2 [! U再次对团长大人和悠悠哥的无私帮助表示感谢~~

. y- H% `5 i) L7 r6 U5 S不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|国治模拟精品屋 ( 沪ICP备15012945号-1 )

GMT+8, 2026-2-3 15:29 , Processed in 1.107421 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表