EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。' j. w  U# }. n4 ?
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
( {: q3 V( D' {- N& V: ?这里有相应的模拟器源码,就当送给大侠了~~( x% E% s7 B  Z1 l2 |
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表   V& L7 O" w: w1 W: Q9 z7 F
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
# _$ `+ A: z  f6 Z2 e- e楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
# ~9 }  R: ~2 h: _/ }这里有相应的模拟器源码,就当送给大侠 ...

5 M2 `9 T) w; q% X聲音部分(Audoi Process Unit = APU):
' |" L0 }. |3 D) k3 r5 O.\NES\APU.cpp
0 }( R+ x6 m! T  o.\NES\APU.h& }, z# B+ d6 z! @" d# C  {7 U) i
3 h- ~' l$ G# R9 t9 Q% {
. `- K. w! O9 x' X
影像處理部份(Picture Processing Unit = PPU):% C% Y0 m! u/ v3 b! A, W: z* q
.\NES\PPU.cpp/ N6 j8 m( Q- B- l# w" t
.\NES\PPU.h
# l7 g( K1 ^& o- Y4 _- M* j- U6 |7 c5 q
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。8 ]8 \# i/ D9 T
感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
; @: O$ @0 Z6 [) x" i(由于很多专用术语和算法机理都不明白,所以看不大懂……): f) k+ h: m* }! f0 |: h7 M
//////////////////////////////////////////////////////////////////////////! c8 I; |4 a# e3 J4 E& b
//                                                                      /// {+ b$ R! y. C/ H' Q
//      NES APU core                                                    //7 H$ {. G3 x4 R% Y
//                                                           Norix      //' H/ t3 Z; D- z' B0 I* ^
//                                               written     2002/06/27 //
! y% T+ |  l! K7 h" c//                                               last modify ----/--/-- //% @7 j5 o! V! C$ h: ~
//////////////////////////////////////////////////////////////////////////) Z: O; m* _( I/ ]' ]! {+ x
#include "DebugOut.h"
' U/ J) |( c$ n#include "App.h"
5 V5 T4 M$ g  E6 W$ r#include "Config.h"+ l* s, w# v; v- _$ w  l
: Z; N) _  U* |4 U
#include "nes.h"
) e, ^. M5 G( g#include "mmu.h"
  Q# K* G: y/ P7 n/ ?#include "cpu.h": n0 p& x* \0 k2 s' H  ^8 z
#include "ppu.h"
! n  @/ d8 e7 l% ?#include "rom.h"/ X0 @3 ^) [4 f8 A
#include "apu.h"
$ ?. c9 K1 t, `" y
3 y' @- r) ^( L( _" V' @  n// Volume adjust, z& H3 J4 K5 Y& r0 Z- C/ }4 _
// Internal sounds
4 L* d* B4 n. c#define        RECTANGLE_VOL        (0x0F0)$ F2 |% q( k' I0 N0 M+ U4 t9 W
#define        TRIANGLE_VOL        (0x130)$ Z8 m" C* P- p8 A( D
#define        NOISE_VOL        (0x0C0)+ I& P* k# i% i
#define        DPCM_VOL        (0x0F0)
% c7 o1 N. G. J- J& f// Extra sounds/ a9 ]& W2 |; t+ J/ `7 O: D
#define        VRC6_VOL        (0x0F0)9 b1 `; a4 M" U" a& f' o, a' t) S
#define        VRC7_VOL        (0x130): M1 R) _( ?/ x" o5 e% }
#define        FDS_VOL                (0x0F0)
9 r4 v8 O  T# y; h" d; Q#define        MMC5_VOL        (0x0F0)
6 O3 F% o4 Z5 r+ Z1 O$ s#define        N106_VOL        (0x088)
* ^+ T% g% J7 `1 V$ F#define        FME7_VOL        (0x130)
. J8 H1 c7 }/ h# A! u7 M' y; {# U3 s5 V: P
APU::APU( NES* parent )0 h0 F( Y/ U" y' R1 p" s" o/ _
{
+ L+ q* s! f5 Z9 W        exsound_select = 0;+ [/ Q- |* Y7 e6 s& G: V% C1 Q" a

: H1 c( `6 O5 k        nes = parent;
* ^& O5 M% a2 x+ n, F+ d        internal.SetParent( parent );
# Z7 D5 g2 \2 H& o* g% s+ A1 z1 d6 D  @9 S+ b
        last_data = last_diff = 0;
/ i$ v/ M% z3 b2 K  s; V% `+ L  q
( U- Z! u/ U1 Y# t3 v; K4 X        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
1 E$ a6 ]1 y2 a, G- }2 p( ^+ p& N' y) @3 H$ |
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );& T8 k+ A. p5 s. c& F. ~
        ZEROMEMORY( &queue, sizeof(queue) );
8 R9 U8 }* [& i! d$ [% C        ZEROMEMORY( &exqueue, sizeof(exqueue) );
- @2 t5 L1 u. s1 w: U+ x" M5 t3 a, W3 F8 R* J" x+ D; L
        for( INT i = 0; i < 16; i++ ) {
. v0 {6 P* B- [6 l9 M3 J7 O0 d                m_bMute = TRUE;& J6 w" t( [9 W! X% w; ?6 i
        }3 N) ~# p1 w$ H. [- T% n1 m/ B
}% V6 E! s) E% E, p6 C9 J
) Y6 ?' Z* M0 o# J+ M* |
APU::~APU()
' |" X& q5 |/ B. s{$ u( V) i2 r( X4 i4 n4 d
}  D4 q- }+ o4 J: L* i# D1 p' U! p

! H. S$ \( R4 z  Wvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )& F2 y" l% I7 U
{
& U; T( t# d' r' E5 D$ D        queue.data[queue.wrptr].time = writetime;) u2 F5 X- ~( \! y' J4 Q2 W
        queue.data[queue.wrptr].addr = addr;
- O; y! r& x4 p/ {4 T. m        queue.data[queue.wrptr].data = data;
: z9 o8 c, a; E; }5 ]( m        queue.wrptr++;
$ Q* @9 x5 D  ?" t        queue.wrptr&=QUEUE_LENGTH-1;) z# p( @7 ~) s1 F
        if( queue.wrptr == queue.rdptr ) {8 O: S" E2 D) ]% v& X0 @
                DEBUGOUT( "queue overflow.\n" );) D9 E; b5 A: G2 b" Y* a
        }* T6 \* @: e$ W* ^  M8 K! W  L
}
! x8 O8 h7 D, W# I! p
6 |& U5 p* d, o$ ]/ UBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
, ?) k9 o( l4 {3 d{4 k/ o( ?, X$ q6 Y- }
        if( queue.wrptr == queue.rdptr ) {4 y# Q) t8 L* r: J& d% Q
                return        FALSE;
1 G2 g! q! N; [. \8 n        }$ X' `/ E$ f/ V/ L- d( _
        if( queue.data[queue.rdptr].time <= writetime ) {
6 L2 E- E( o+ i  k) r( o                ret = queue.data[queue.rdptr];8 |% m0 B+ K0 P  b" J
                queue.rdptr++;
% }& [5 Z, w* H/ K7 \( F                queue.rdptr&=QUEUE_LENGTH-1;1 Z6 ~* l& p/ c( L3 \, F
                return        TRUE;/ d4 j4 ]4 Y) ^8 k0 a% J
        }* u9 U" e) D7 n" s1 B8 |" \
        return        FALSE;+ i% a7 o" [8 Q$ T
}
7 l7 v* B4 g' ~
8 ~! f8 o% ]; t! Z4 F' \void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )2 c7 E2 I. G( J* L" r5 G
{  \4 e: Y* S; A0 W
        exqueue.data[exqueue.wrptr].time = writetime;  G# l  F# E3 J5 P+ Q
        exqueue.data[exqueue.wrptr].addr = addr;4 e; L! c. d% T1 _! m) L* y. @  Y
        exqueue.data[exqueue.wrptr].data = data;
) v2 S2 p) |; H( `7 {2 [4 v        exqueue.wrptr++;
/ w9 W/ Q6 F  `1 C) d        exqueue.wrptr&=QUEUE_LENGTH-1;
" `& V; Y( _( W! C: J3 x( S4 U        if( exqueue.wrptr == exqueue.rdptr ) {
! t# U% o) u6 D3 z% H5 S4 L2 r) j                DEBUGOUT( "exqueue overflow.\n" );6 L1 F$ @, a$ h5 {0 e. e+ {" S
        }( k! H: ~4 h4 R7 r
}
; f$ x) ?* q1 v  T9 q8 E1 L: x! i/ P
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )! E: ?$ G' Y% p/ l6 B. `- T( ]
{
6 o6 e& Q2 G' J9 z0 P, s        if( exqueue.wrptr == exqueue.rdptr ) {
' u/ B$ b3 T. ]8 X                return        FALSE;
0 I  A* N! ^6 Q% `        }! K/ b8 F- P8 Y
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {" y* s! O) I5 S) F) J% f; c
                ret = exqueue.data[exqueue.rdptr];1 s% X( @, K. `& Y+ h, U
                exqueue.rdptr++;4 E* |2 ~/ F) G6 I) n6 _% A
                exqueue.rdptr&=QUEUE_LENGTH-1;
5 \* Q  X0 T( k% @, t                return        TRUE;
  r9 n" \2 P2 Y# ^        }
4 J  G% C8 k0 E4 T" A        return        FALSE;
# g+ P$ O1 X, h7 c( ^}1 A; M4 n* F# e: X! q6 Q

2 O3 P! I2 U1 Z$ B2 w8 Avoid        APU::QueueClear()
6 ~4 u- n. H% g7 ]" U{4 @+ O2 Z% b' f, e3 e
        ZEROMEMORY( &queue, sizeof(queue) );& S3 `* m; k. n) Z
        ZEROMEMORY( &exqueue, sizeof(exqueue) );! D4 m* Q6 K( A* k0 i
}
% n8 J( l2 G" T9 U; T
' `/ Q, t3 m+ B. Cvoid        APU::QueueFlush()
7 J- X$ N: J$ Q8 x5 q% ~+ t9 K" }) A{0 X6 m, E1 `8 w8 x1 q# C8 @
        while( queue.wrptr != queue.rdptr ) {
" n1 B" j0 n: Q/ P# v) x                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );$ n$ V0 w; p1 `; O# d4 v; z
                queue.rdptr++;! |( |1 y3 X: c4 w- w# _5 p
                queue.rdptr&=QUEUE_LENGTH-1;- P4 m7 V$ s2 o+ s+ D: F+ M  X
        }8 u3 U8 [0 G! T6 N6 E
. x& E; [( ^" O$ G/ `( h+ `. H; Z
        while( exqueue.wrptr != exqueue.rdptr ) {
% M' k7 s( N* S& ^1 g* ]7 G) N& \0 ]                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );$ _& Q7 A; r) D' b, n
                exqueue.rdptr++;- ?+ b% F9 x) k& o
                exqueue.rdptr&=QUEUE_LENGTH-1;
: A0 ^  c0 X  r; n/ E' r        }
+ k1 l3 ?& x& W4 s}0 d- N3 x, C3 ~, t

$ H- I2 W' {' e5 b/ [; {void        APU::SoundSetup()1 A4 a5 n9 ?- W9 T  g
{
& l8 U3 `! H* J; }/ V( Q        FLOAT        fClock = nes->nescfg->CpuClock;
7 s. z" k: c6 w/ X& c. F' z0 e        INT        nRate = (INT)Config.sound.nRate;
9 A. |1 a4 r. v+ X+ h        internal.Setup( fClock, nRate );( ?" |. u. K6 _( S
        vrc6.Setup( fClock, nRate );
/ b' i& h' g, [9 a        vrc7.Setup( fClock, nRate );2 H+ s  v6 w4 L, T# v
        mmc5.Setup( fClock, nRate );5 P! [5 h% G) W2 D7 ~0 X" s
        fds.Setup ( fClock, nRate );
% k7 y# z& ], _9 ^1 z        n106.Setup( fClock, nRate );' z4 ?; y+ u6 q' }2 q" @5 K
        fme7.Setup( fClock, nRate );
3 k# F; S) K* E5 g: Z/ p2 i}
, N) p1 e$ P3 P9 j" S8 f4 ^# ~
: V" S1 |- E/ M8 lvoid        APU::Reset()  E" Y8 L; `5 a
{  W; R* y* x0 V5 S
        ZEROMEMORY( &queue, sizeof(queue) );6 F$ e7 z* `" D- j% d5 B
        ZEROMEMORY( &exqueue, sizeof(exqueue) );: D# A+ v0 `% W

. @" D/ V( {0 q8 _4 J: n) H% j8 D        elapsed_time = 0;. `. K4 E2 @$ F$ Q  ]4 z" B

( p6 {9 A! i: q7 F) Z        FLOAT        fClock = nes->nescfg->CpuClock;
; `" D3 {: R6 O. v8 ], U! w0 m, K        INT        nRate = (INT)Config.sound.nRate;
3 V8 \8 |+ m3 P$ c+ x        internal.Reset( fClock, nRate );: ~+ }) d0 q5 U8 C' U' y
        vrc6.Reset( fClock, nRate );- L6 b' t; D9 x. i! C9 t. K* f
        vrc7.Reset( fClock, nRate );
$ i) m5 g- {4 t- z, T) e) B+ K        mmc5.Reset( fClock, nRate );
! U1 }9 j* m) H        fds.Reset ( fClock, nRate );
  x3 ?, t# ^% {# S        n106.Reset( fClock, nRate );4 Z! d. R0 \9 m
        fme7.Reset( fClock, nRate );0 u/ P0 @4 s5 m! j) F1 G
9 q1 Y* X; W, h9 p5 m
        SoundSetup();
) E* p" _6 g6 a}4 I+ |& x- N) o, q
1 Q# t/ I% W' y" G* B- N
void        APU::SelectExSound( BYTE data )
' |) ^  Q% \& b  V" r" q{# r6 O/ o1 ?( y  Y7 i: Q& @! f, c# c
        exsound_select = data;
1 }( [+ y+ f8 T+ c4 Z2 Y  }}, ^+ S1 P, v' ]* E

+ a" ?* w  q! o: r4 K9 wBYTE        APU::Read( WORD addr )1 Z) K  u! }, k, K* z, b
{
; V+ A& r. O) n( r1 e1 T        return        internal.SyncRead( addr );! s, d9 }1 U) A# E! R. ?
}7 L8 t6 l2 }, Y/ X) ~+ w$ b

( n6 o- j5 Y3 ?8 m0 Evoid        APU::Write( WORD addr, BYTE data )
2 Z% u  e( I: x$ Q{4 C$ h2 Z2 \0 d- K: R6 s
        // $4018偼VirtuaNES屌桳億乕僩, g* b* ~1 P7 R
        if( addr >= 0x4000 && addr <= 0x401F ) {
" F7 r! {7 w' B" Z9 A5 ^7 |                internal.SyncWrite( addr, data );
& {# N0 u4 A% t                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
9 p7 }: q  \4 q        }
; O  l/ [+ i# A5 M/ z0 e" {6 R9 b}
- x- c& r) P  Z7 y0 j( d7 K3 v7 k: [) T; R
BYTE        APU::ExRead( WORD addr )
$ T) v4 g5 F$ F; Y- R5 a{
& b; v! Z1 j& n5 X3 t$ P+ NBYTE        data = 0;
  M  S; x" z( _, n4 F6 Y- H6 K+ W4 ?" E6 F# P
        if( exsound_select & 0x10 ) {7 L; O4 ~* ?( U' P% Y1 F
                if( addr == 0x4800 ) {' }0 m8 i3 c# t3 f% d+ `7 l6 S
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );* t% {# a% y; ^9 `
                }2 J% m. I5 _5 X4 S! e
        }6 ~4 `- s' C! U: D
        if( exsound_select & 0x04 ) {
; S& p4 j* `2 ?3 M4 G1 C$ s                if( addr >= 0x4040 && addr < 0x4100 ) {
* w/ O* x0 A/ `& m$ z                        data = fds.SyncRead( addr );
" J) ]" v% P" H1 D" u  S) p+ j1 C                }2 r' `7 _' i: k' s, E
        }$ ]! s* b/ w0 `
        if( exsound_select & 0x08 ) {+ F) l* [! ~# L3 C: n0 F
                if( addr >= 0x5000 && addr <= 0x5015 ) {8 S- [& G8 C9 K) G* I) v  }
                        data = mmc5.SyncRead( addr );/ M$ l% e$ S: V8 T* `+ @0 B$ B
                }  N1 O8 ^" x2 G5 m  i5 J" ^
        }6 ^! a3 B' M( c5 c
% ?% I( S4 ?# q1 I/ q( Z# O
        return        data;; T6 f% B/ O% n9 s
}
. |7 [' E7 d2 t4 Z' b- m. R
5 j9 n+ S& U& @/ Mvoid        APU::ExWrite( WORD addr, BYTE data ): a0 h& o6 b$ d! {
{
1 I3 z" x1 Q4 l" b! d        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
5 F4 g# \% d. H- \
  G( [5 R$ X) [1 \1 m9 H& ?& I7 B        if( exsound_select & 0x04 ) {
  O  [# g$ H4 S7 ]$ M; d' y4 X                if( addr >= 0x4040 && addr < 0x4100 ) {- f, Z3 o  a- o$ C# Y
                        fds.SyncWrite( addr, data );
- ]5 L+ |0 }  D( @, k                }
! ?. O2 f7 q! q0 x; ^6 }        }5 L0 P1 {* ~" P0 d- b5 P4 B

" f4 ~! f- K# _8 a1 g% L* S        if( exsound_select & 0x08 ) {5 n# D! C) Q4 N6 r
                if( addr >= 0x5000 && addr <= 0x5015 ) {
2 f2 x* R: i; x9 P3 H$ \' m                        mmc5.SyncWrite( addr, data );
7 o- P. x+ ^/ \0 L6 S                }
7 o4 }: g' n- T% i        }
2 a/ G8 @6 }5 x8 w7 u7 c}
# v+ r6 `: b3 j* ~. D9 W7 [- \" }, q6 M
void        APU::Sync()
' w: b" I: w; c7 u{/ e1 Z2 o6 ]7 c- i- w, j. r, ^
}
8 F, j: r/ v  T. {* E4 _
) W0 \  y4 l* [6 Dvoid        APU::SyncDPCM( INT cycles )
. m/ s# J, h; L{( G/ f1 q2 @  f# s
        internal.Sync( cycles );
5 Z) M2 B& ]* D& i- a4 F. F
( U# M/ Q7 U% ]; {( W; P! q8 s        if( exsound_select & 0x04 ) {
4 L( `- w) W4 ?, {! ?5 I                fds.Sync( cycles );
$ p, k3 }% a2 u# t        }
/ ~& p4 F6 s; }0 M        if( exsound_select & 0x08 ) {) d6 a7 X8 w; w7 T# E# a
                mmc5.Sync( cycles );
4 D$ A5 [) T% v4 v( L        }
3 i3 s9 V" \" h0 b. N  }4 H}
: n8 G8 |- ^; c5 H4 C8 }
& v* z' y& g$ N1 a  |* E9 Vvoid        APU::WriteProcess( WORD addr, BYTE data ), \# |2 U5 F: T
{9 L2 {5 H- y" {+ X) t) g$ {4 ~
        // $4018偼VirtuaNES屌桳億乕僩
& d4 C6 h% x1 V        if( addr >= 0x4000 && addr <= 0x401F ) {
4 i5 m" Y" ^; A0 d* Q- G                internal.Write( addr, data );
6 |7 t* h# c" c( z  p/ D! \! m! k# B        }7 }% p5 }! F) Y/ R- `
}; {* C" ?( }3 ^9 l

$ M) T1 i! p7 h7 fvoid        APU::WriteExProcess( WORD addr, BYTE data )
2 F$ {9 S8 m9 }9 }; X& ]4 L{
" t% J/ r' r! q) `! l. l" O        if( exsound_select & 0x01 ) {& Z: w, [5 Z8 p( n! T' `& }
                vrc6.Write( addr, data );
( N* N2 A& _9 |+ g; C, {1 i        }# s+ i2 N# N+ e
        if( exsound_select & 0x02 ) {1 U# D2 V+ ]4 @3 O/ {/ S
                vrc7.Write( addr, data );, l& T7 M5 Q# @. H; Z" v
        }
* X0 e/ p9 A* Q        if( exsound_select & 0x04 ) {4 g2 S# }- S7 C- B! k
                fds.Write( addr, data );
4 O* Y. ]4 @+ J" I4 l0 N. A+ ^        }
& H7 s9 ?3 O9 u: E& ~# {        if( exsound_select & 0x08 ) {
# a; ^+ r' H' F$ }" I& E; o                mmc5.Write( addr, data );! w# v1 ~5 U6 a, B% g( \
        }
- c' @! e* S, H+ q5 s! Q" _        if( exsound_select & 0x10 ) {* U8 M9 s/ v5 [  Q9 G. x
                if( addr == 0x0000 ) {
9 @1 x" L% y! H                        BYTE        dummy = n106.Read( addr );2 R% h9 m7 l9 W$ V- C9 G7 u8 s
                } else {% |- ]. M6 i9 b: K$ V
                        n106.Write( addr, data );) N8 w& V& L* o) D
                }9 ^8 R8 L# D7 n5 h: Y
        }
2 O7 H% v; m/ @1 O        if( exsound_select & 0x20 ) {2 m3 ^! n" H; W
                fme7.Write( addr, data );$ `- D$ D( t1 _* U' e- z! E
        }2 }& e' F2 g4 I( v" c! n+ n
}" o/ a* P, D  }4 ^+ P
/ @& v  ^: v! p' P9 `
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )7 r, n( c2 z/ Q  A/ w0 b4 b
{
. |) P; |% p$ IINT        nBits = Config.sound.nBits;
4 Z4 C! \6 Q2 l3 D3 ]7 E) _5 ~DWORD        dwLength = dwSize / (nBits/8);
; e' }" \+ D4 N5 j, [4 n! ^! mINT        output;
$ {, m& ^2 g. ]2 k. M& u) i. BQUEUEDATA q;
# f% y1 Y9 Z" l) iDWORD        writetime;2 U, C( }: I$ n2 B# e: M( n

1 f, E% X( a& N1 \7 C2 v( j7 y: c. ]LPSHORT        pSoundBuf = m_SoundBuffer;
, n5 u6 w0 x; }6 q* X; |INT        nCcount = 0;# a6 x0 n% W1 V7 y# [

  u' d& {1 H  d  {, W  V* rINT        nFilterType = Config.sound.nFilterType;
5 r3 L. D) }8 ?8 u# A" u7 Z; q$ s+ ^- j4 L5 W  k! a
        if( !Config.sound.bEnable ) {
9 S4 G4 U" y9 B6 ]8 }                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
% I0 ^- j6 I) r8 u7 d                return;
! E* H" z0 ^% |) c3 A$ F        }. d4 A# a8 d1 Y" w8 O4 v' w

& O) {: z4 ?2 T  h1 A" M! C  G4 m        // Volume setup
' f- i" A* \% ^        //  0:Master
, n4 B+ h1 S% u& e6 D* I1 P8 L- `7 T        //  1:Rectangle 1
( p/ c: g" c4 x# J; K7 s        //  2:Rectangle 2) D9 s% h3 H3 t9 B: S' v: I% P2 X* d
        //  3:Triangle
! l3 D, \" a: J7 B% \* w        //  4:Noise
0 h5 T1 y% s4 O8 N* e        //  5:DPCM1 r* n$ n& J3 p, w. h# |
        //  6:VRC6' i5 B% _% ?7 {# Y1 w: e
        //  7:VRC7
5 g& p, y* _: S# n        //  8:FDS
5 y2 j1 y: m6 P! y: T. @        //  9:MMC5
3 t9 W9 Q1 q! v; [+ m# P        // 10:N106! O# K& x% ]0 x( W; \
        // 11:FME7
) @. {, q% T4 X9 V0 n; E' q, P        INT        vol[24];% K3 D' y5 B# g* x
        BOOL*        bMute = m_bMute;+ s% b9 w' ~& r6 F: _4 j# G# y7 \
        SHORT*        nVolume = Config.sound.nVolume;
1 a& s& B3 }" R( M6 B  Y+ w2 B6 X/ n- U7 W' h; J+ g
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
- o- {  h! m8 s" A2 f/ @; l! F* s& k; {  d: G$ d$ E
        // Internal4 ~$ Z* q: H/ ^! S9 Z* k. k- A9 G
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;0 j# E2 e- Y8 r. b
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
+ ^! S% g8 W. y# t2 L: k        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
- D5 ?9 k9 p) h        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
5 `- V) }  e! M# Z4 z6 X        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
. e: [3 ~, Q& D3 l  w
+ J1 P, B, x( E        // VRC6
9 I  _, w& x6 L! D        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;6 l- X4 \7 I6 V2 J
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;4 `8 g5 [$ n2 c% j& O
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;* S* a  U0 q5 b( |& S7 h
6 O  K. ^5 T4 e3 A8 ~
        // VRC7
6 w1 Z/ b. z) N/ X9 g        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
# Y0 Q, }# B$ s9 o1 n- L( k; I& o& r+ V
        // FDS
( A3 }% [# Z3 T* C$ H        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;/ ^0 w2 [% ~* b  f+ g

2 A/ O! g; K4 A* H2 C( I+ z        // MMC5
' G- P7 ^$ R2 t        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
3 ]" l: f, E( F: a8 X; |        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;3 l+ v' w8 J9 W2 j( Y. h% o
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;# ^1 A' \/ i5 N; D, I
. p4 J" p8 F, c* V8 y/ E% o! z+ y; m
        // N1064 ~( Z- J, C/ s0 T) R6 A4 M' B8 ^0 q
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;- Y# M- [+ ~9 n" D" x
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
! a- s& [8 f6 n        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;8 C9 j* \( `# i- r5 W* Y/ U3 H/ r
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
7 B* f$ o7 U$ ?5 k        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
4 i) x9 o. P2 H2 |; n        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
5 J( i" @  d% k8 U  t% x        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
( _' R/ a  n3 K" h! d        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
$ K) w! Y  `' q2 P/ w2 v0 Y; {4 D+ [$ @% ^, J
        // FME78 p+ v% O6 K( F+ j# [/ B0 w
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;, U3 c6 ]3 q6 K" j0 \
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;1 u+ v( O, n$ b" q4 I# b
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;. K, x. q8 c: k6 e& L( Q2 h

; U) E6 t, P  y" B* ~//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;3 u& F1 h8 l  s' t8 E) y- T+ l
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
; F4 d, l* ?6 x7 u4 E9 G
$ m# j* x0 c6 D; W+ J* U! |        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
2 c# w0 B6 C' \# e        if( elapsed_time > nes->cpu->GetTotalCycles() ) {3 T, z/ T) ^4 B6 D/ E% P
                QueueFlush();
. }- y* A# q  X& e. j1 ]        }
: H  P& }2 _, f5 y1 _/ ]" F4 s3 F+ s3 f6 Q3 F- g3 v
        while( dwLength-- ) {
# f6 N' P8 |# m; {: _                writetime = (DWORD)elapsed_time;
% T; T1 M, L9 s& p
6 E- E* ^" v5 X                while( GetQueue( writetime, q ) ) {7 _# H2 p' T; T4 n# J7 T) E# ?
                        WriteProcess( q.addr, q.data );
1 r0 @. E5 n2 u3 b8 f8 J, \                }- Y! o% v& f+ S3 G' U" w% E" j
3 n+ Z& u( L  d
                while( GetExQueue( writetime, q ) ) {5 F( j& M  m( o+ k. Y6 F
                        WriteExProcess( q.addr, q.data );0 `% y6 @- q9 n5 i' c
                }. G2 a( f' |# W9 F

& L. p4 L/ ~9 e: y8 s* z                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
7 T( E0 I  s2 E6 x( S7 u, I                output = 0;
5 j5 h' ]) x, U9 a1 J1 M                output += internal.Process( 0 )*vol[0];) K. U; n: [! {2 U4 ^8 T
                output += internal.Process( 1 )*vol[1];4 B* L" n: n. l, N- E' H
                output += internal.Process( 2 )*vol[2];
6 D9 C* w7 }7 w3 {3 t6 ~$ N                output += internal.Process( 3 )*vol[3];
& p9 q5 c8 Y- [; A  Z; r. ~                output += internal.Process( 4 )*vol[4];
' x; p0 J% A9 g  B8 Y
9 E8 F0 ]% v5 j1 G( R# |) \# K                if( exsound_select & 0x01 ) {
! T5 h5 r! E, c6 K; d                        output += vrc6.Process( 0 )*vol[5];$ @) ^- p8 D% `! ]# F
                        output += vrc6.Process( 1 )*vol[6];
1 I  r$ H$ }  H5 W; _5 f                        output += vrc6.Process( 2 )*vol[7];0 O/ @" d& C4 x
                }6 D" v9 S0 g, a) p& Y* O
                if( exsound_select & 0x02 ) {
5 M9 F  e! s; y% ~+ P! u1 e3 P9 S                        output += vrc7.Process( 0 )*vol[8];
9 n, [3 X* D/ s# N6 r% d4 t' L                }( K. y/ U3 r; L6 T% I
                if( exsound_select & 0x04 ) {; f5 U; H: g9 L
                        output += fds.Process( 0 )*vol[9];8 {% [' ?8 c" y* x
                }0 E& a  K0 w% E0 t# R0 R
                if( exsound_select & 0x08 ) {. J8 i# A; h- S9 w3 z, Y$ r) C4 y
                        output += mmc5.Process( 0 )*vol[10];9 ?4 \: o: Q, _* Z# k
                        output += mmc5.Process( 1 )*vol[11];, O/ _) w, `/ _7 f5 e
                        output += mmc5.Process( 2 )*vol[12];! W7 k6 T/ M) q1 r1 ?* |+ m
                }3 Q( e- k7 ]9 n" @, a& x1 S; _6 U
                if( exsound_select & 0x10 ) {" l" \6 N1 `% _# e1 [5 [0 \
                        output += n106.Process( 0 )*vol[13];
. {  |( F* r' ~  i# L0 C                        output += n106.Process( 1 )*vol[14];
- r& j: h& w' d/ V7 W                        output += n106.Process( 2 )*vol[15];
' L* H! A* A9 c3 `7 A) H% A( h                        output += n106.Process( 3 )*vol[16];5 j3 L" v+ M% }6 z! E$ i
                        output += n106.Process( 4 )*vol[17];
7 V: K. ^# V( ]$ Y7 y+ S                        output += n106.Process( 5 )*vol[18];( S  |$ Y& O0 _0 k1 ]) U
                        output += n106.Process( 6 )*vol[19];' ?: c" E  o  p4 L
                        output += n106.Process( 7 )*vol[20];
( ?! a- p# J  x% H. _8 d                }- ~' ?2 _% y; C) ]. m4 K3 x, y+ S
                if( exsound_select & 0x20 ) {
7 o1 l1 ^, @0 v; S. {                        fme7.Process( 3 );        // Envelope & Noise
3 R& N& M" |  k$ L  V- P/ l: }                        output += fme7.Process( 0 )*vol[21];" `* w: \$ `! z" ]1 r. d+ z
                        output += fme7.Process( 1 )*vol[22];# R" X0 p) j$ `) E# a$ X
                        output += fme7.Process( 2 )*vol[23];
0 V' k, \/ C& A5 w0 A# p/ \8 u& L                }
  {( V" `; i) N+ C
8 S! n: }4 {* L- ^* Z                output >>= 8;
; u8 m* q1 o8 P- [3 A6 F7 k1 [1 `* E3 V  `) C# J
                if( nFilterType == 1 ) {9 F- ~+ n1 V* ]5 |
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
- Z( B9 Q1 A- b' k% @+ b  H                        output = (lowpass_filter[0]+output)/2;% Q) ]9 |4 z! g
                        lowpass_filter[0] = output;
3 e- v9 ]) A. |2 i! m" |4 t6 }                } else if( nFilterType == 2 ) {
1 D7 N% U( J0 N5 U/ w( l                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)6 x: [( q$ P& ]
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;0 M7 M% m% _, V5 D
                        lowpass_filter[1] = lowpass_filter[0];8 R& E( x, E/ n2 C6 Y% a
                        lowpass_filter[0] = output;
) \, B5 i% {3 _! b5 q% @* a# l4 C! Z                } else if( nFilterType == 3 ) {
3 \; S& I4 G; |; O$ Q- d                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
1 y# O, G' |  x4 p3 x9 Q                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;8 c  ]+ R: t- Z
                        lowpass_filter[2] = lowpass_filter[1];
6 L5 Z2 F! e5 K4 ~                        lowpass_filter[1] = lowpass_filter[0];
3 _7 A, c5 U& Q                        lowpass_filter[0] = output;. `9 H7 _( U5 p4 B' b6 R, M
                } else if( nFilterType == 4 ) {
9 q2 h& }9 s5 W$ j                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
6 W+ u( ^2 W9 l- U- r3 a) B  I% }                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;4 @& W6 M, h, T" u7 [& Q
                        lowpass_filter[1] = lowpass_filter[0];# U, @. z! ^& u3 X  o/ L  o7 i
                        lowpass_filter[0] = output;
5 \- v1 _& F" U( U. P# \2 P$ k                }5 h0 c' j3 T4 g: S0 B
, @& W0 h/ i# h8 v! E
#if        0
5 U1 N3 Q9 h! |9 h3 k; B  I; h                // DC惉暘偺僇僢僩
% g" a2 K. G$ c5 ]' J                {
2 p) L* {7 L! m: i# K* ?: u/ k% V                static double ave = 0.0, max=0.0, min=0.0;
. _% @" V* c, K9 d- Q                double delta;
9 s+ N% ~+ ~( l$ c1 i+ x+ @2 M& B                delta = (max-min)/32768.0;3 ]5 R4 k1 I. j9 p0 W
                max -= delta;* U! e3 q  g% X% E) |7 R/ u5 u1 O
                min += delta;' ?% p( V' n' n# v. ^
                if( output > max ) max = output;
8 ?" R3 s4 n0 q5 R                if( output < min ) min = output;9 w. M, H  Y' `8 Y
                ave -= ave/1024.0;
) l. D) t7 F; G! C                ave += (max+min)/2048.0;, E/ s% X4 m: i. t4 E8 {) a; G* s
                output -= (INT)ave;; Y$ `. I% n9 v- p
                }
6 }9 E+ d; r# s; w#endif
7 T& _2 `; V, T2 K#if        1
" h# I# b3 P- s7 {# w                // DC惉暘偺僇僢僩(HPF TEST)
% x" U! g3 d  I& T7 N; ]                {
" \+ e2 S! a9 h$ m( L9 X; n//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);, u' J, M& c1 |! |5 i; d9 I: Z5 S  m
                static        double        cutofftemp = (2.0*3.141592653579*40.0);1 Q7 ^1 H' g+ d. A/ e1 k. g6 i
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
8 z  C/ o" a; O                static        double        tmp = 0.0;
/ R7 W* M3 q6 \                double        in, out;; d* l) Q, \& `. R

7 b! t  r, f# J: p) Y                in = (double)output;
- F' Y2 A- r$ n                out = (in - tmp);
9 |$ r) N" P; e; q) p1 h( @4 m                tmp = tmp + cutoff * out;
2 j9 x. X% g+ I$ w$ x/ n
  F/ m* ^8 D7 z  }# ]8 j. r                output = (INT)out;
  q* N! ]( L( f7 G3 U; L/ q                }, u2 ?, }( v9 ^6 e* {
#endif+ e! e! t3 v# R/ y9 s
#if        0  ^: c& P2 A/ J2 a: R/ w
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)5 |* }4 U% c. e
                {
, ~( m9 G  x$ u                INT        diff = abs(output-last_data);
& G% T: }5 X7 S. U( l; r* z6 a                if( diff > 0x4000 ) {5 P9 z$ L( B  W8 s' z! ^  u2 X1 ^
                        output /= 4;
* M' {  K# E4 l! |                } else
- G# _; H" V1 \5 {4 C                if( diff > 0x3000 ) {
5 g7 O6 u7 {6 g5 k6 G                        output /= 3;0 \0 @6 u/ G; P' h2 E, u5 c
                } else
; p/ D, i3 s# t# n3 V! }+ W  a- p                if( diff > 0x2000 ) {
3 N' O2 i- B, {& d; v/ S) Q/ a                        output /= 2;( ?. r) J4 s) @
                }
! I' d3 a# L( d! B& [8 I, H                last_data = output;
5 ]) y" U( s) @, w1 G6 I                }
% m& G+ A% v3 h6 e) c) g' Q7 R7 s7 C#endif
3 B1 v( \8 |, N( W0 s                // Limit
# k. I7 k8 q, G& V; R; I- m                if( output > 0x7FFF ) {& A- I1 l, q- X- m4 |3 V- y
                        output = 0x7FFF;0 Q3 {# ~6 t$ l0 i5 b# P4 ~
                } else if( output < -0x8000 ) {" z6 q8 h- ^2 q
                        output = -0x8000;7 g0 x8 u- o9 h7 _7 C+ K/ S/ Z; D, v$ Z
                }
" j6 v( l" e6 i3 f
) P1 @7 T! B& Z( R% G- \                if( nBits != 8 ) {
: H% Y& n/ K1 X' U, ^1 |& ?                        *(SHORT*)lpBuffer = (SHORT)output;
* x) ], u- Z2 O7 J' m* I                        lpBuffer += sizeof(SHORT);
$ X' F. t$ S8 l2 N5 V                } else {
+ t3 Q. [1 m7 V5 }' P& [: ?/ {                        *lpBuffer++ = (output>>8)^0x80;9 I* y% K, r' n/ X6 }
                }
! n/ L7 S9 ^& j) {" o8 u% G
+ E3 n5 h: `8 E                if( nCcount < 0x0100 )3 u8 j( c6 T* H( Q$ Q8 @8 ?
                        pSoundBuf[nCcount++] = (SHORT)output;! W7 F( W* h6 s

5 }% k& [  e0 {& O1 H//                elapsedtime += cycle_rate;
+ Y% j7 f; g1 n4 k                elapsed_time += cycle_rate;
- N9 r( ]: n* @0 a0 U: x8 ]        }$ |5 a: Y5 o& Y; P
5 P, e) `9 }: V9 ^3 Y$ c
#if        1
, T* @: U' Z! I0 S5 x        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {1 _  ]1 g( o) o
                elapsed_time = nes->cpu->GetTotalCycles();
8 \2 k. t2 H# A  a$ Y        }
5 S* N5 e. s$ q6 N# N- P* I, t- K        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {% l6 K+ Y, b7 R6 a# j- ~2 A6 a& e
                elapsed_time = nes->cpu->GetTotalCycles();$ X7 K1 `6 l8 Z$ O
        }- r  L. u. b; r: Q) i4 H
#else* y6 \3 e( m1 i4 n* s5 E- O* K/ o7 P
        elapsed_time = nes->cpu->GetTotalCycles();
! X4 m( w3 S  u, T( d' @1 w#endif
9 M5 X7 ]0 M/ S: f1 ~" w+ p}
" J' m: `# G8 B8 s# n& l( u! {( ^# K0 P$ P1 S, k) I
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
6 B6 M1 x3 H7 x  c5 }- ?+ ]INT        APU::GetChannelFrequency( INT no )' p6 z; n9 f0 N% F3 r6 D
{
% a% D% r( r( E9 p2 @        if( !m_bMute[0] )
, w& Z2 C, f( @1 Q9 Z                return        0;
5 B9 t1 n$ s) X$ R6 f8 Q7 R; T
- s" h$ u9 @" y9 S% G        // Internal7 n# s! p( }, Y  D5 t
        if( no < 5 ) {
7 h% h) q/ r9 P( d, i1 L                return        m_bMute[no+1]?internal.GetFreq( no ):0;- n- O4 p+ m# C- P
        }
4 {; l' }: `4 ?3 `6 q! y        // VRC6& R( q' c/ n. q. {5 {) O
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
1 L# o  g5 w: \% j                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;" N, g" R- I$ P, N" T4 @4 R7 @( p
        }+ t) Y7 `) ]4 G4 I" Z
        // FDS2 v1 d, m+ F2 t/ A# q  n5 n
        if( (exsound_select & 0x04) && no == 0x300 ) {9 |, L* e) M0 q, F$ F
                return        m_bMute[6]?fds.GetFreq( 0 ):0;% K  }3 e2 c( w3 @
        }1 E! Y/ p6 p* R3 W/ E6 j$ _( z
        // MMC5
1 m+ {# ~$ j' D" C' ~        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
- B$ X+ w- F. O                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;; N6 K' ?; ~' f: ?; K3 a1 s" r$ S* D, }
        }" s3 P0 M& K" [& [+ ^& h  `
        // N106& b! d+ p+ M# V; a
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {- m' a* }5 w1 N+ d$ w
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;0 F3 l2 V9 x& V3 N# ?3 W7 G4 ?
        }+ l% S, C* g& z( j
        // FME7
& d; C8 {3 N3 ~6 ]9 K9 j7 Q        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {, X% `$ d' Y8 I0 Q
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
' N7 l4 ]/ L* U: v3 X1 n        }
( \% w, u( o, A! J- x: ?2 U        // VRC7
: `$ X3 E* ?/ a3 f+ J! [        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {3 c! m3 b! B# {8 n  o# I- D
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
4 z8 a3 g( M  ^        }9 A) Y0 v& ~, ~" }& ]0 h
        return        0;  o, e1 K4 H3 G2 P0 t
}
* }  Y! R' P$ q) x' X
, y. G, r  O6 {$ Q! R; S// State Save/Load
- t: U2 B' I: T+ Pvoid        APU::SaveState( LPBYTE p )/ q5 M7 _) c+ C# y7 d8 g
{) @8 w6 w/ q1 X3 X, N
#ifdef        _DEBUG
8 g8 s: `+ T; w# j/ YLPBYTE        pold = p;
7 U7 j+ a* _8 u8 u9 h#endif
9 Z* v: P. y# o4 K8 P; `5 Z" k. i3 l5 I- P, T2 e
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞8 I6 l+ O) N# V! I. H& Q6 Y
        QueueFlush();
+ h7 D, }8 p  S0 D8 i7 ?( m+ q6 p/ o
        internal.SaveState( p );
1 _: E, E" ?" v/ K; i        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
" R0 p. n0 X  C, M7 G& J( {
1 Y+ D. R( N" X, l( D' ?        // VRC64 `1 g' L* c; j: u9 y" u8 \
        if( exsound_select & 0x01 ) {1 u5 |8 u* k' B& b9 n
                vrc6.SaveState( p );( R- D5 h" @& A4 @6 K7 ?! B
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
$ O3 d: t* n# r; Y! ^        }) p( u9 P$ y2 }0 ^+ Y6 y4 U# w8 H
        // VRC7 (not support)
* N/ f' }; z- d3 [: ~& i2 ]" U        if( exsound_select & 0x02 ) {/ r  y) \" L4 I3 b" Y$ }/ d0 T6 e
                vrc7.SaveState( p );- j$ |7 p" R0 ^" \' ]0 ?! c1 q
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding/ Q; j2 r  j( |; N" Y  R
        }; Q/ m) O, v& k) L
        // FDS7 T# V; g" B: g% U/ u0 x$ k
        if( exsound_select & 0x04 ) {* ?4 Q2 X3 U- f7 k
                fds.SaveState( p );. s! b' [+ c) x, @1 }+ q! @
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
- J' g- K( w3 [. z: s        }% p$ x$ ?4 z5 q4 f2 j1 k+ h
        // MMC5) V& c$ S2 O8 H! o" `
        if( exsound_select & 0x08 ) {
- k- Y5 W5 H# y3 _" w3 K# u8 u! a' L                mmc5.SaveState( p );
  x( W1 W- E5 l. \# ]6 v, ?# R9 l4 T                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding; z( ~1 Q/ k, a: T9 E, s+ a
        }
- y; E* `! e! {: Q7 b5 U. q        // N106
+ N( A% w" V3 Q$ I        if( exsound_select & 0x10 ) {
1 W, b1 ^- x9 d; K3 ^1 B* O                n106.SaveState( p );6 t$ J* h1 T& d5 S* L4 w9 r
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding8 R  ~) Q2 m' Y
        }- u2 K0 Z4 r5 h$ ]7 V- l: u* q
        // FME7
3 L5 ]* V$ ^7 X7 {+ h+ h        if( exsound_select & 0x20 ) {1 h; L$ T# H+ g- k
                fme7.SaveState( p );
2 U6 W2 L1 F* s5 M                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding# L/ e' s7 |% f) e& j
        }
. W/ p7 m$ `1 m4 Z1 v' m, a! N% V( w, _2 v: t* z# @! e4 \& a
#ifdef        _DEBUG
8 u5 s- B7 |$ a" V0 ]1 T# ?DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
9 M/ y, t! _; _) J( G#endif
9 {9 K; W% J2 z9 J}# D" C/ Z, k  M/ n9 r' d
6 V! z& j( {8 \' Q  }7 E) w4 z7 b1 Q
void        APU::LoadState( LPBYTE p )
5 Y( `' ]( c: `* W  N  C; P/ I{: `: V( S" P- L5 Z9 ?1 F2 f
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡* U! z4 G' b* u0 ]3 ~9 z
        QueueClear();! |- s7 |5 Y* Q7 B3 ]1 r) V7 I

  W5 d/ P, p, w1 W5 c4 b7 }; C        internal.LoadState( p );+ c! C7 T3 w- g' J8 g* ]
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
& _! o/ U5 D- [( v) d3 [- e" b3 X  v  @3 I( {* O. A
        // VRC6
9 k4 m5 W% W5 j5 k7 c; h        if( exsound_select & 0x01 ) {
- n5 B, G0 g  I4 O                vrc6.LoadState( p );, G  E. p' C! g! e
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
) k: a! [( h. o& A; U9 |        }! u& V7 ~" K1 D$ B
        // VRC7 (not support)% C' J& [) ^* b
        if( exsound_select & 0x02 ) {- e; V* T) N$ E7 P
                vrc7.LoadState( p );/ Y( s; Q2 g% T: L! o' y  {
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
# e1 T9 I" b3 D) g0 L        }
  o' K$ z% k9 p  ^0 a' v4 I' ~7 p        // FDS# G5 O% `. [% E" s. v# q/ M
        if( exsound_select & 0x04 ) {
  R1 i- E+ L# {                fds.LoadState( p );
3 E) V& V- o& Z3 ~4 f                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
9 g. y% Q1 W; o1 `+ s        }
* v8 A* H+ r5 D: @6 P& q* m* G7 F        // MMC50 w1 \& v" v  G' s( [7 o
        if( exsound_select & 0x08 ) {
( h+ W9 t/ r) [0 A3 i                mmc5.LoadState( p );. c0 A) Z# C& ]2 O/ C" P
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding$ U9 a& O' w/ |8 b7 }* [" R& w
        }3 t9 K" @5 b! J0 R2 _5 E
        // N1061 T4 R1 b4 V4 R( P) B
        if( exsound_select & 0x10 ) {
+ z# w+ h4 T7 B                n106.LoadState( p );
* b! |7 N. D& Y8 @- c                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding9 @  ?7 a; }: n8 {/ `0 O
        }% W: E) K6 v/ _
        // FME7
- u/ G& Y( i2 @! E% C        if( exsound_select & 0x20 ) {- ~( _: g6 {0 H
                fme7.LoadState( p );
  C& i0 C# w5 P7 `/ M                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding1 U% E1 h  ~+ B, V7 J
        }; b4 V. |: t( ?; g
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
9 y: t6 f5 a# ]1 W9 P$ ~+ w6 J; D可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
; D2 F2 u, ^8 n( i感激不尽~~
' k0 Q6 u: D5 i1 e
恩 我對模擬器不是很有研究,
2 j/ J& g" F: _3 J7 d; d雖然要了解源碼內容,可能不是很困難,
5 n% e2 M9 Z$ ]# C1 g- i不過還是要花時間,個人目前蠻忙碌的。
" I  |$ S" ?( u9 [/ b; X( b# l" o% Q: _, e- L- ~
給你一個朋友的MSN,你可以跟他討論看看,4 y% \* R+ R$ S- m% g8 m" ~: D% _
他本身是程式設計師,也對FC模擬器很有興趣。" n1 p5 t8 D3 x, D+ D
3 u; b1 ~) g' L) ~2 J
MSN我就PM到你的信箱了。
- @2 H; y- v# Y- z7 d' G' `0 e+ T1 n+ R. ]8 D
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 6 B$ ^3 Y0 R3 h  L% p
呵…… 谢过团长大人~~

" _. w( `# ~8 Q1 e
* U' L) _$ i0 ^  s9 R. N哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 1 }' ]2 r2 e( i! C% K  H9 g6 ]
团长的朋友都是神,那团长就是神的boss。
2 \1 P0 k, Q+ t* Z
哈 不敢當,我只是個平凡人,! a- N5 S3 y7 @; G
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙' o3 i6 }$ }3 c# d0 b1 e
ZYH- S  [: n: r9 w; Q1 V, J5 H# y
QQ:414734306
, C4 Q3 P. E; C6 E& {7 v- HMail:zyh-01@126.com
+ L; M4 R5 ]6 g  E$ u* A
8 h6 Y# e$ [: T, d; p( m他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
" D% M% q1 a% P1 Q再次对团长大人和悠悠哥的无私帮助表示感谢~~
+ z2 m* ~% b0 ]/ k" y& _# z# P
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-13 15:38 , Processed in 1.103516 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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