EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
7 u! p# R" R: V5 h5 {: L楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~. e1 o+ F) B- F& h: k, I
这里有相应的模拟器源码,就当送给大侠了~~  Q) M4 Z) R% N# S3 r& O& {. B+ x
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
# E. B& q6 N, f1 \能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。! Y* Z/ o& G( y. ~: Q. B; h' ^( C
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
9 e, J5 z: ~' C  {: C' Q这里有相应的模拟器源码,就当送给大侠 ...

! f  T6 L: g) A; i6 _& w0 c5 O1 y' \聲音部分(Audoi Process Unit = APU):* C/ R0 F+ w! O. A
.\NES\APU.cpp* C. M3 z1 f4 l0 Y
.\NES\APU.h' y" L+ [! |: y+ ^( ?6 ?1 y
: {2 H( @4 [: t, V1 ]) ^" d/ m

" g0 z( n$ n! s" v( A影像處理部份(Picture Processing Unit = PPU):2 N# s8 F) M3 e" x7 K. L  y7 Y
.\NES\PPU.cpp. S1 x6 Y: F9 ]
.\NES\PPU.h
! @, [4 y7 E. Q$ g# ]+ v2 x8 w5 I! i9 _+ ^8 h
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
% E) p4 X7 t3 G4 P) a(由于很多专用术语和算法机理都不明白,所以看不大懂……)  {+ ^! `4 l% ^% R
//////////////////////////////////////////////////////////////////////////
2 k3 F* M% h# Z' P$ a1 U//                                                                      //
: R& Q# o1 l2 I  s) _4 X//      NES APU core                                                    //
; S) C. t7 b( C; L% ~0 c//                                                           Norix      //
: f$ ^( o4 \0 C8 J//                                               written     2002/06/27 //
6 R: L6 J- J; K2 T: R" f//                                               last modify ----/--/-- //2 }3 e( U( D2 j/ W2 y5 @# r
//////////////////////////////////////////////////////////////////////////
% }2 W: [5 a6 Z0 ^: }#include "DebugOut.h"- W4 \+ q  M9 ^' J9 A6 n- Z+ S
#include "App.h"
4 ^/ b1 M- ~& C: i- c#include "Config.h"
1 r4 c0 Z9 m+ X( N! n& l& K% l- `7 I/ @; }
#include "nes.h"
! g2 Y! s( {  I' J#include "mmu.h"
6 |% C% f. }( k& L% I+ ]#include "cpu.h"
5 n; |6 E4 m2 t# @0 J7 V#include "ppu.h"
1 I; W, a- f/ {% k) B- \% Z#include "rom.h"
8 B7 ^" A" `& b#include "apu.h"9 N$ m9 O4 M  g) V
2 H1 e! ?0 c1 ?% ^1 ^0 N6 [! x
// Volume adjust; d5 V) }: g% i5 h  O: n( Y
// Internal sounds
2 I* y; K8 S$ ]0 d#define        RECTANGLE_VOL        (0x0F0)
; W) m5 k9 J$ X# P- ^7 ]; k7 l#define        TRIANGLE_VOL        (0x130)( O  p& p. ?; f. o: X: ~
#define        NOISE_VOL        (0x0C0). ]7 e5 I2 m" c  t0 d0 M& w
#define        DPCM_VOL        (0x0F0)
! b3 J5 K- F# B' t) b0 t. ~// Extra sounds* _6 p; E  N! p3 ~
#define        VRC6_VOL        (0x0F0)5 Y; l- I/ ~4 J( n, Z) F
#define        VRC7_VOL        (0x130)! k/ d) Z5 r7 u9 D
#define        FDS_VOL                (0x0F0)- @5 }& f/ E4 J
#define        MMC5_VOL        (0x0F0)$ ]& I% l4 j0 k* ~" C- m
#define        N106_VOL        (0x088)# S! h% w  K/ m; E# b! e; n
#define        FME7_VOL        (0x130)& R: t) t5 F( K, Y- B
+ v. v5 O7 I& I6 e" q
APU::APU( NES* parent )* R% M# p6 n0 I( H& t
{9 k0 p( m/ m2 C
        exsound_select = 0;
7 {& \* x4 b! N6 W7 d  c$ H" u  K7 V0 O& b5 x, c# s1 @
        nes = parent;
1 V  w, y3 H6 }+ c* q4 Z        internal.SetParent( parent );
) v- {7 R! w7 m) R
. S2 s1 q; V+ [, ~        last_data = last_diff = 0;
6 k/ G3 t0 m  s  L
$ m7 g7 V: }: T2 M        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );: x+ |" {  i' s& _' a/ Z/ w% I# d
5 g/ g' f3 N0 v
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );8 [  j# ]4 z0 f- d* P3 ^
        ZEROMEMORY( &queue, sizeof(queue) );
- h  V& |0 ]* Q6 t7 x% {; y        ZEROMEMORY( &exqueue, sizeof(exqueue) );
$ T; [" j; V5 {/ i2 q. w9 @9 I$ |1 R" Y9 H5 `
        for( INT i = 0; i < 16; i++ ) {
; H6 p  K3 W' _- i( H: g5 ^* _                m_bMute = TRUE;
- A/ q, K, h$ V8 R        }
) P6 J+ A1 e3 _" ]}
5 V+ V: I# p7 x) K/ V. _) i- S
$ c; q" R3 @( B0 r4 h/ f- nAPU::~APU()
# u" z3 P9 v+ X{
$ X" W( G$ ~, R5 ^) k  r}( j" L% x4 {: S, V- b

5 u* U+ D+ Y" x+ ^void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
  Q* f& v' @* N- {0 q{  n6 Y& p2 m( ]" {
        queue.data[queue.wrptr].time = writetime;
+ g2 T: p% L/ b7 \# |        queue.data[queue.wrptr].addr = addr;
! x2 t+ ], @  v% s6 z. t        queue.data[queue.wrptr].data = data;
+ _4 I( @0 N0 M. y        queue.wrptr++;/ i) @! M& K) O" S
        queue.wrptr&=QUEUE_LENGTH-1;0 [( e' b3 Q5 `: Z# t" w
        if( queue.wrptr == queue.rdptr ) {
1 E0 Y/ k" S4 Y, L- u) C8 Z                DEBUGOUT( "queue overflow.\n" );7 F5 S( [2 Q4 K
        }4 W* F1 m- o; W& d. T9 U" B8 F: r# i
}: B4 m5 }% |: @- w3 j
4 ^8 I: A; h/ |) K7 j8 c
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )* |/ n* ]/ c& j" b. T% m$ n2 y1 d, |. K
{
+ }. R! h  r( i9 n        if( queue.wrptr == queue.rdptr ) {. z6 R) e& L5 A, ]+ r$ P. _
                return        FALSE;
  T3 {; w% C0 O. j0 L( [9 Q2 \6 i        }
' }0 s  i# \8 v0 k% q7 }, J        if( queue.data[queue.rdptr].time <= writetime ) {) V! x3 b8 N# ]" z% y; |+ y, T
                ret = queue.data[queue.rdptr];
7 b7 q+ {% S- ?" j0 z: h                queue.rdptr++;
) J5 j  [: ^# i, `$ c3 @                queue.rdptr&=QUEUE_LENGTH-1;7 B) G; B" Z# Z7 e5 D0 c
                return        TRUE;
8 y6 b9 F; Q6 U' ~9 I        }$ m, V/ w8 m+ R* W. ?# F& v
        return        FALSE;$ }  U2 c. Z5 X2 O* k
}
  ]3 i+ e3 @: ~) i, S
' I. p0 m4 J3 ~' W6 yvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
4 `& S& A& Q) Z9 J{
& k! I0 P4 ^9 F! i5 a        exqueue.data[exqueue.wrptr].time = writetime;/ ~2 F" f% i) A
        exqueue.data[exqueue.wrptr].addr = addr;
+ O2 B; Z' c9 {2 T& v        exqueue.data[exqueue.wrptr].data = data;6 S! Q: s+ Y" W% @( a/ t3 A
        exqueue.wrptr++;
; ?. k/ L) g& ~        exqueue.wrptr&=QUEUE_LENGTH-1;, K' Z: v6 e  \" r
        if( exqueue.wrptr == exqueue.rdptr ) {
; g4 b8 h/ y  t                DEBUGOUT( "exqueue overflow.\n" );
3 h( y. ~3 G! i, h4 _        }
, m0 E. a" y# z}
4 L3 f3 D4 P$ V1 v0 X# u1 N- Z6 a
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )/ k2 t5 |' k/ N% l' h& _7 R
{5 O: O2 p: M, s  ^8 [
        if( exqueue.wrptr == exqueue.rdptr ) {
7 Y) k- t) ~. @3 n! K6 }                return        FALSE;
5 j4 H/ {. k; |& U        }
( F, s8 o( u' [' Y  Z; q' S        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
, }" K9 P/ m( C) o2 G# U) p                ret = exqueue.data[exqueue.rdptr];
2 M3 ]: j6 B" u. A) Z* Q* \$ f) s                exqueue.rdptr++;
; ^6 r; L/ R4 C, u                exqueue.rdptr&=QUEUE_LENGTH-1;
4 q; F8 _. f6 L( n) f* `0 {                return        TRUE;
# P2 a$ B7 @) o3 F* L" Q7 d        }' f! [. T! `2 c9 [
        return        FALSE;
. v( m3 Z) p3 k+ I4 ]0 c8 w}9 ~9 h; o9 e: ?2 v4 Z9 {
. E1 P6 ~: I( m! w- ~% ^
void        APU::QueueClear()
. l8 y2 ?3 q( |' J$ n{
* [, d' s5 |1 J1 R        ZEROMEMORY( &queue, sizeof(queue) );* q. e& s- Z3 L+ T! ^
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
; y2 D4 H! k" O2 `}
0 D  ^/ p& [- _$ Z1 T- F; {0 F8 f; h& a0 u; ]
void        APU::QueueFlush()6 L6 H, z  G) W+ c  j0 C
{4 Y; y( S  O1 ]
        while( queue.wrptr != queue.rdptr ) {0 o- G& Y% V, a: m( U! d
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );  w3 _# v8 n4 j! J0 R/ R& C
                queue.rdptr++;
4 ^9 m' m( G; L9 Y                queue.rdptr&=QUEUE_LENGTH-1;
$ W0 f& u  t3 |6 b        }; v, v' [1 a- q4 J

$ G8 P" f; u+ a& W        while( exqueue.wrptr != exqueue.rdptr ) {; b( D2 a* g, n3 k8 H
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
5 z' L& p, C2 a+ a: c+ {                exqueue.rdptr++;
2 u- W! A6 K: b                exqueue.rdptr&=QUEUE_LENGTH-1;
2 [3 ^6 A5 J$ U* ]        }9 h- ~% x- q2 H7 ]& i+ R
}, v. N  V/ c* S! m' u* ^$ I
& c+ d  e- s( w) F4 e: s
void        APU::SoundSetup()5 a, ^$ x2 h' h/ T. T3 V+ t) U" ^
{( A% _# F0 Y& f5 D4 Z8 J
        FLOAT        fClock = nes->nescfg->CpuClock;+ k$ K  k1 c- e, @: _
        INT        nRate = (INT)Config.sound.nRate;
7 F1 ?9 f7 W& _5 i6 W0 }        internal.Setup( fClock, nRate );$ I; o9 O5 d, G+ D
        vrc6.Setup( fClock, nRate );" Z) I  P; H% U
        vrc7.Setup( fClock, nRate );
7 T+ m: ~% R" h/ I; \        mmc5.Setup( fClock, nRate );
7 Z" @4 [0 m! }( W% j5 y+ j        fds.Setup ( fClock, nRate );
1 ?( v( O! e1 a$ v( ]) ]        n106.Setup( fClock, nRate );
7 c: F) L3 j% V# q        fme7.Setup( fClock, nRate );
, y  {  r  V/ R1 D  q% Q8 A}
& g- @0 v+ `9 x8 s! ^/ Y* M+ H2 x
void        APU::Reset()! v: ]) H- C/ |0 U
{
- @6 L6 w8 z( |4 [& ?( ?7 b3 ?        ZEROMEMORY( &queue, sizeof(queue) );
- U5 ~% ]' K6 f& t" M8 Z2 N* W        ZEROMEMORY( &exqueue, sizeof(exqueue) );
3 k% o6 Q# I/ P* V$ g# P" }% x/ l! i4 k2 |
        elapsed_time = 0;6 z  D. K( ]. _5 N1 C& _( R$ d
+ W/ [$ t; v2 K6 x$ q
        FLOAT        fClock = nes->nescfg->CpuClock;; S$ O  N1 L3 K" F
        INT        nRate = (INT)Config.sound.nRate;
3 Z' T+ t& W* _. k        internal.Reset( fClock, nRate );0 U7 A( c( k# p* x
        vrc6.Reset( fClock, nRate );5 ?" u3 y' o! `7 n0 ~
        vrc7.Reset( fClock, nRate );
# U0 |% G3 g4 ]3 K        mmc5.Reset( fClock, nRate );; l" j5 A2 [2 Q4 g
        fds.Reset ( fClock, nRate );& P# l8 W" |, _& I4 Y
        n106.Reset( fClock, nRate );
) b4 \& G) c( x- j# \* n9 }8 d        fme7.Reset( fClock, nRate );& @2 O; x. C: x7 c. u

, N! t. x& J' ^# k        SoundSetup();
* v3 N/ m9 Z/ d/ Q; q/ }+ i- m}9 e) C7 I8 v& t2 m+ N( O/ }
* L- |( E7 m7 K
void        APU::SelectExSound( BYTE data )
4 ~8 {: D, @3 u! O: W{2 G: ^) o1 S. h
        exsound_select = data;4 i8 b& x0 O+ P
}
1 w' i4 j  c1 X
' P) B- G. P5 z. yBYTE        APU::Read( WORD addr )
% \: b# C" m  T3 R{1 m; H- B3 I! R$ n; q% j" E7 |
        return        internal.SyncRead( addr );: x7 x6 A  W9 Z* m
}
8 I, R6 E+ y: V0 \6 t/ ?0 s) I1 D; k. K7 y9 [# z2 d
void        APU::Write( WORD addr, BYTE data )3 B9 n3 y" U) Y" P' x
{
% t; Z' r$ O" R: d+ M/ G# V        // $4018偼VirtuaNES屌桳億乕僩
$ \% v$ q; e* `        if( addr >= 0x4000 && addr <= 0x401F ) {* a0 q! N: z% N4 p
                internal.SyncWrite( addr, data );, t/ C; Q8 O+ p  G4 P/ u
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );8 }0 o! L9 z& q6 [, V
        }
, J6 B' ]  p- ]3 A% g5 G}4 A. z4 G9 y9 W# O' B
& ?: J5 ?5 h5 Z+ f/ e$ o
BYTE        APU::ExRead( WORD addr )
9 R: D% b. Y" H2 K9 N- C" {& F{6 R: U, i- i: B' l3 s
BYTE        data = 0;
' G7 k$ ?- W- G! n1 M4 E2 F) @4 U' G) W' j1 b; p' b; }9 I8 h4 D
        if( exsound_select & 0x10 ) {
( }' _% l' w; G7 @0 l                if( addr == 0x4800 ) {
" a! I! W. M& I$ X9 c5 }, c                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
4 w) R3 F& f3 d2 F                }! ]  B7 k+ S( t3 b; t7 P' L
        }5 i) |# U. Y4 V( K4 _. Z. t
        if( exsound_select & 0x04 ) {9 p9 d% K: ~! t7 L' V
                if( addr >= 0x4040 && addr < 0x4100 ) {
: r4 q! P$ B0 t4 p" e) q                        data = fds.SyncRead( addr );& d  i2 c1 m* e
                }5 H, H# ]( I! H
        }
* X& {1 B& `+ J        if( exsound_select & 0x08 ) {
' X/ f7 `5 Y0 c; y* Z% G6 g/ A4 V                if( addr >= 0x5000 && addr <= 0x5015 ) {
+ U& `5 t# X  M$ k' \+ G                        data = mmc5.SyncRead( addr );+ x: M! o+ \3 G( m
                }
, w; c4 T  S% s, ~' P1 ?        }
# {2 m+ \5 L3 s  @. M  Z
" V3 e/ h" P0 {; i, y9 I        return        data;
, ?$ k4 Y: V0 y' Z/ b+ X) b}# G0 Z0 U* ^0 ^$ G- |3 M; M

3 H1 d  {2 {4 d  Q' j& f! u" Uvoid        APU::ExWrite( WORD addr, BYTE data )
/ C* [4 ~6 W' Y2 C' Q{
9 G0 t3 E# p  }' E: N        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
' ]- E' C8 t. F# ]- `& }8 g( S) Y+ F! ^, j
        if( exsound_select & 0x04 ) {* b4 k% X. U# T  s$ {0 S* l
                if( addr >= 0x4040 && addr < 0x4100 ) {0 J1 U! G+ }' g
                        fds.SyncWrite( addr, data );
0 y* W0 ^( z. R* Q5 Z9 m                }
, @4 M- x( e6 q- Z        }& P& m/ O/ Z. e; _9 Q

8 E& G/ J, p1 ~, L& D        if( exsound_select & 0x08 ) {5 Q0 b- ]0 B5 u% p7 e
                if( addr >= 0x5000 && addr <= 0x5015 ) {( O: r3 ]& |2 i* n# n0 u
                        mmc5.SyncWrite( addr, data );
9 `. Y$ z! m! J* c# w2 H+ W                }
4 X. l7 r) _& V+ ]8 y5 q' X        }
  d1 D# \$ p- ^/ q- W+ P. }  I% d) l. F}7 c' [4 F. m2 h2 G" B6 v8 c0 l
) R( ]( Q  X& N$ j
void        APU::Sync()4 F" S# c) m& V) K  n$ c" h
{# T0 s9 R, _5 Y! s5 u, Y. ~; E
}( E# O% K. u- ^+ B: f* E/ v
9 Y, v  o: [- J
void        APU::SyncDPCM( INT cycles )( t# a( s& z0 V- }5 P% ?
{' H$ Y8 @1 }. E9 z+ B/ F
        internal.Sync( cycles );& C& I" c$ ^5 X  D; u4 G/ k

- Q& a) ^' {/ n1 O) ]8 Z7 d        if( exsound_select & 0x04 ) {
) P6 G* O9 B( ]1 q2 N( A" n                fds.Sync( cycles );
5 i1 V3 N( ]7 N# T6 Z        }3 y; S* m: p/ s# v* |% q7 ?8 ~
        if( exsound_select & 0x08 ) {0 @. M) ^* y) @, r
                mmc5.Sync( cycles );+ h* }- ~1 M0 p4 C9 g
        }
' ~" K3 b+ }( @% h8 G' b; [: M}
5 S4 P% @$ C9 C; G
# }' ?8 K0 B$ p+ \& Wvoid        APU::WriteProcess( WORD addr, BYTE data )
, _6 H9 X' i* x: X3 b  m6 R{) s' }- I) t0 y$ F( Q" R
        // $4018偼VirtuaNES屌桳億乕僩/ M7 |% d/ y# s
        if( addr >= 0x4000 && addr <= 0x401F ) {
8 u+ V1 a: q/ \" I                internal.Write( addr, data );
! N/ H- {7 N( u9 m        }
0 J% k8 b  N5 F& O4 y# K& C" d}
. C) w8 x. a. n, |% L4 {  }: {* k& a5 Q1 X* ~1 u" K3 f
void        APU::WriteExProcess( WORD addr, BYTE data )3 @. X% M+ |- q2 b5 P
{: r! q, C$ s1 {3 w% ]! B3 n
        if( exsound_select & 0x01 ) {
& m3 `5 w. m4 J' e                vrc6.Write( addr, data );
0 @* T: R7 y7 H4 \1 _1 P: B$ X        }( H, T  W0 }. [3 t2 G
        if( exsound_select & 0x02 ) {# @/ j$ s6 ~: w+ z2 ^+ u# ~6 ~
                vrc7.Write( addr, data );$ v  r- [7 F, F  h
        }2 l! Z% X8 s3 `6 m  ?: ~% @
        if( exsound_select & 0x04 ) {% w! J7 N$ T% F- ]6 X3 k/ z, c1 ]
                fds.Write( addr, data );
8 @% y- O' a! G        }
! }. K9 I$ p. K2 I        if( exsound_select & 0x08 ) {; i. h, L7 j( F! F* w( [$ C, H5 D
                mmc5.Write( addr, data );
. |! Y0 u  k8 P* i        }4 I6 l! O8 D" K8 k- l4 X8 W8 E# }7 v
        if( exsound_select & 0x10 ) {
9 F. p0 Q/ ~5 w0 [                if( addr == 0x0000 ) {
4 B" o4 ?  Z' k5 t$ N5 g) j                        BYTE        dummy = n106.Read( addr );, {- O! h, Y1 W+ A. y
                } else {
1 {8 s( k8 K: E/ H8 S                        n106.Write( addr, data );
% H* H7 b: Y, v7 F5 N( N, P# u                }
3 O* k5 |6 Z4 u; b, j4 I9 I        }  f% U. K' I9 q* d
        if( exsound_select & 0x20 ) {
& X: m" K4 q( n! g                fme7.Write( addr, data );" y7 t0 b# F) W( N. |' N
        }; I1 O6 r% H3 P+ g8 K2 N' i
}
. j! d" h4 N, B; u; C( H* B% o. F* E0 R1 i9 S
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )6 i/ d$ _9 K! |1 X4 ^  I5 ^
{7 V" V  _& Y- @. g1 l  K+ Y& f
INT        nBits = Config.sound.nBits;
* S. c6 R9 K. Y; I- g1 J+ SDWORD        dwLength = dwSize / (nBits/8);
+ P0 [: f& A% ?* \% GINT        output;
3 X. d6 [9 E2 M  n  AQUEUEDATA q;
* x. q7 W( ]  M1 A; z+ Y5 h) d; nDWORD        writetime;# D  z% V7 {2 Y7 W$ h/ [% R  J
8 N7 \3 ^5 n3 |9 Q& d
LPSHORT        pSoundBuf = m_SoundBuffer;
, t3 M# P; s7 y. _INT        nCcount = 0;3 q# D* c; o2 y+ y5 O7 n
& K  G- f8 Q. S0 f0 ^! r1 k+ j
INT        nFilterType = Config.sound.nFilterType;
7 R; L) C% D; _; n
4 B+ c+ u; v: o5 p  Q        if( !Config.sound.bEnable ) {2 S, \3 F  e) X( ]+ y
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );! O3 j- V7 L( h
                return;
2 g* q. ~6 B9 g) H( o        }
0 ^2 m+ N3 v; S
& P% v" t: l& J- u1 |% {        // Volume setup
3 [% \# Z3 H' h4 E2 E% Z$ t        //  0:Master
# O2 s) R: s, k! T  P  a9 P: {        //  1:Rectangle 1
2 q# p( x/ E/ _* P  g        //  2:Rectangle 22 _! I# E! a3 A7 ?
        //  3:Triangle
8 Z1 @' o& d" |- ?. v5 K        //  4:Noise" ]1 Z# X; }" F! o4 J* ^
        //  5:DPCM
8 ]+ L6 G2 z/ G/ r* Y) f, I  q* L        //  6:VRC6  _8 r: N5 T. E
        //  7:VRC7' Z- i! }7 \8 Z) ^' s
        //  8:FDS
* m# ^& z4 j  b# s* V: e, }: K        //  9:MMC5
5 ?) K" p1 Y0 E2 X        // 10:N1060 \; u9 @6 ^7 Q
        // 11:FME7
: T2 X3 W  Y+ w4 n: j        INT        vol[24];1 t/ ]- M8 k' Q) t
        BOOL*        bMute = m_bMute;9 E3 `! ^  {+ L- ~) p3 F
        SHORT*        nVolume = Config.sound.nVolume;
& ~& h' s6 ?4 \! k8 e. u; D1 E- ]# B% s+ L$ d. l7 {
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;2 P+ Q1 F3 V0 N5 X, l3 G

+ Y0 Q' G" `0 @, l        // Internal6 ?- F* |0 @( R6 ~! G1 Q# s9 A
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
  K' t. g0 A5 f, u# |1 E' ~$ \6 p8 `        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
# v( S8 z; k) b! M        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;0 g' r% F0 T3 Q$ D# J, i; i
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;7 v( G) v( i& `  O
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;6 k1 K9 u# w( Q' l. Z
" w' {( y: m1 M
        // VRC6
# d; o' b5 K, Y& F3 @        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;" `$ m' [( u) E
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;+ I! v  b" R9 }4 t, u
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
( H- J& B3 @7 p. w' u, s0 j! i: G0 b7 o' S% Z3 ^
        // VRC7$ A) X" R8 z/ W2 ^
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;4 G$ {& U3 w; P$ ^! p6 q
6 n: {6 w9 h2 B& \
        // FDS, D9 K5 N. J# s3 ]9 j
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;/ g! j5 V, f) Y+ K  Z; a

9 `+ r: i% o* v5 e2 [/ o        // MMC5- ~* Y  Q# I5 e. M$ a( l
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;, ?% }9 i9 v$ H- ^  f7 g3 l
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;# H: i& M7 u5 F# u: @& g
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
+ v/ p# ?# H! t9 c
" X% T7 C& |6 d1 y& W( r8 x        // N1065 s7 V9 e* _: G) }* g
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;  J# W8 B, A) }% K
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! w" J/ ?. \5 F
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;& y+ e. ~4 v8 B% I$ C) g! ^
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
7 N' j! A# i" k' }$ _' u        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;  Q8 L, x/ W/ _$ v: h
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 E+ R/ V7 ?8 E  C        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
/ j4 L' g- g! Z1 f        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 X: |+ G, P- k  p

$ P; |4 Q2 b+ _. C" _! P        // FME7
* T) ~, r  g1 i" m        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
4 u; {' z# l$ _. p; l3 d        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
9 L  g* _$ {: J. P        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;. g; w5 t8 r  N

! {% j1 F  L5 \; v//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
! s' M9 O1 M9 C5 [( a* [, S        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
& U- J$ X# E/ p  J4 I0 d
- ?) k+ {4 M& Q0 X+ j2 A6 d        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
- y* s  ?8 D# p: O& V  c6 B: l        if( elapsed_time > nes->cpu->GetTotalCycles() ) {, `1 S+ Y( z) e! X' b& I* {
                QueueFlush();+ Y; n+ \, u0 E) w
        }
2 v; q- Q7 S/ h& y  I
+ X- Z6 y" R6 j/ j- {. g: d0 E        while( dwLength-- ) {' E  R  a# h5 J2 r6 O/ r- Q4 m& ^
                writetime = (DWORD)elapsed_time;: a: s  y. W5 {! [

9 c  h( E" r) R) i. N( J+ H# r                while( GetQueue( writetime, q ) ) {
% L$ y/ V2 N" L+ t+ d0 s- u( g! A                        WriteProcess( q.addr, q.data );
! F( s4 L3 N* |! g& ^' b                }
# k7 d- C: S# [. s7 s& x5 l4 T1 V1 t1 b8 k+ z
                while( GetExQueue( writetime, q ) ) {7 Q6 m( w, u" j+ z2 a0 U. j
                        WriteExProcess( q.addr, q.data );
$ Q* c; G; k; {, B: L8 d                }
3 n: E5 E! A8 |6 W
2 U1 l7 ~, S7 h4 d% _                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME77 A) {' p* c0 K% {6 T8 B( }& ^6 c
                output = 0;
8 [  u' f  R/ G# d  F                output += internal.Process( 0 )*vol[0];
; _5 ^  u$ \2 Y: x# c' g9 ~                output += internal.Process( 1 )*vol[1];" c3 O0 u8 Y; E3 D
                output += internal.Process( 2 )*vol[2];* {* J' G" F1 L, y( u7 D
                output += internal.Process( 3 )*vol[3];
6 l. ^- J8 x( a8 h0 s                output += internal.Process( 4 )*vol[4];; Q: W2 I4 N( K2 g: M0 ~

/ I) d* `$ C8 T" [3 Y' v                if( exsound_select & 0x01 ) {/ h9 Y# x& f+ m/ m9 K: l
                        output += vrc6.Process( 0 )*vol[5];9 P) _# e  R0 S7 b6 `+ a* V
                        output += vrc6.Process( 1 )*vol[6];
" j7 q/ S8 o8 c. x) |                        output += vrc6.Process( 2 )*vol[7];
; a6 _% Z4 s% C' t* C* T: S                }
5 S! e: Z' ]  ^. `. @- l$ x! }$ y' M                if( exsound_select & 0x02 ) {
( |+ i- x6 M: u+ I) _# z. |                        output += vrc7.Process( 0 )*vol[8];
! t' @: ]3 a) I5 q) N0 u                }5 C, }: b5 X! q! A% x8 X/ V
                if( exsound_select & 0x04 ) {9 d* f, l' p6 X: E4 P. C" t6 c
                        output += fds.Process( 0 )*vol[9];' A' c$ L% V/ h: t9 \0 Q2 g4 |6 |
                }
+ J2 f; m$ K( G/ u4 H" b                if( exsound_select & 0x08 ) {
. W% o& A5 H: d                        output += mmc5.Process( 0 )*vol[10];
& q* F! k# T) c% }  n8 u                        output += mmc5.Process( 1 )*vol[11];' l1 s: U5 W2 e
                        output += mmc5.Process( 2 )*vol[12];
+ J+ [/ g3 M9 n, n$ L9 W+ }- F9 l7 V                }
$ C$ [9 k* i0 S                if( exsound_select & 0x10 ) {2 S6 e2 B' ^9 o8 H
                        output += n106.Process( 0 )*vol[13];- \2 F- H. ]' Q
                        output += n106.Process( 1 )*vol[14];2 b% [3 n2 d: R; x( [3 u1 E: z
                        output += n106.Process( 2 )*vol[15];
  I6 i8 ^7 C9 O, H% l' F                        output += n106.Process( 3 )*vol[16];7 k. u  q3 C% R9 F& b
                        output += n106.Process( 4 )*vol[17];0 {9 f" ]1 F: u) h3 @
                        output += n106.Process( 5 )*vol[18];6 S8 l8 U9 H' p1 Z/ N9 \9 L
                        output += n106.Process( 6 )*vol[19];& o% Y+ F: c& `- D: x
                        output += n106.Process( 7 )*vol[20];
) K9 K7 ?  i; D9 }' S! v0 t0 R9 D                }
$ @6 A1 X+ B! P8 U                if( exsound_select & 0x20 ) {
* i5 }, H: s% C2 G                        fme7.Process( 3 );        // Envelope & Noise" n. O& _. }: O( D$ W
                        output += fme7.Process( 0 )*vol[21];6 r& x* N8 t  Z2 u0 n9 N
                        output += fme7.Process( 1 )*vol[22];
' F  o/ ]- a4 p9 g9 z' U$ X( k  d                        output += fme7.Process( 2 )*vol[23];
* \% k; x! U. @                }/ L$ z# r; ?1 d4 i  c  D1 H
% i! V# e8 g4 x$ p+ T
                output >>= 8;
& `) o$ A* m& l- Z/ U5 u& Z8 w' v
7 \' Z, ?" |2 W, c" g* z                if( nFilterType == 1 ) {
7 @. k: U( A9 h. [9 v                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)+ c/ x5 t% J5 s' P2 Q+ F) [+ J
                        output = (lowpass_filter[0]+output)/2;/ Z+ ?$ M& g8 B( {
                        lowpass_filter[0] = output;
) {, N9 c0 o6 e1 R% y2 a+ E                } else if( nFilterType == 2 ) {
& c0 @- z' i5 e; U% E( ^. M                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
0 k4 E% I( h' y" |0 q) h                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;$ j3 I, a. B5 K' n$ X) x
                        lowpass_filter[1] = lowpass_filter[0];
8 E; R( _1 X) |+ n8 z                        lowpass_filter[0] = output;
; Y6 R5 _3 g1 m4 |1 @, {                } else if( nFilterType == 3 ) {1 v+ l  V2 X$ |0 r3 o0 R+ p
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
' n5 F# q$ R' C1 r- y                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;% `) U  V- I* \; D5 i
                        lowpass_filter[2] = lowpass_filter[1];
; l. p& \3 V, {- q# h+ k                        lowpass_filter[1] = lowpass_filter[0];! u3 a+ T0 S  J; Q+ M+ r0 ~
                        lowpass_filter[0] = output;8 J7 L. D7 z6 }- {
                } else if( nFilterType == 4 ) {
9 T1 ]& D( i& h2 m                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)% `( b7 O1 E; V: u, G
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;! R, y* {4 U9 @7 O2 A- n
                        lowpass_filter[1] = lowpass_filter[0];
9 ?6 U9 L! H4 D% p                        lowpass_filter[0] = output;/ Z9 Z' O" p, x- v& w7 z: s
                }
) G8 G; s0 I  J4 j
* f# V; k& m# B% v- v5 K/ m#if        08 T4 i" i3 ~! c* N( C5 f
                // DC惉暘偺僇僢僩# o/ g; S2 s5 I2 L5 J, H
                {
. K7 A8 x4 m) V" }! g8 _                static double ave = 0.0, max=0.0, min=0.0;" u5 Z& Y; G0 a4 [& L  C
                double delta;
( M: H4 Q! y; y" ~, E                delta = (max-min)/32768.0;1 `! `! g. L7 r" e( }, |$ u+ b! V
                max -= delta;' V) f5 T' p# A; C6 Q8 I
                min += delta;
! n" \- `  E& j8 w% M. L                if( output > max ) max = output;( Z/ o/ A' P. W- s
                if( output < min ) min = output;& X8 I# Y- a' M  ~8 O
                ave -= ave/1024.0;
* k! ~! |% j1 I# ]8 H. g, b                ave += (max+min)/2048.0;
) i/ P( B3 O) S( J# H  k0 z                output -= (INT)ave;
1 Q# ^' D2 F3 n$ @% c: j* E3 o                }" a/ I5 m/ F( J$ @. p. u; `2 @
#endif5 @5 b' v) {# y* ?; Y. u$ ^7 B
#if        11 ^  D. Q# u' G1 ?+ j
                // DC惉暘偺僇僢僩(HPF TEST)9 M/ |* X' K1 l" `7 ?$ X6 q
                {
) N0 ?5 a: A9 }: Z7 E% j' Q. v5 L//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
5 M9 @7 N5 A0 |! W                static        double        cutofftemp = (2.0*3.141592653579*40.0);
4 u1 t$ b' y% a& ^: I+ I  T4 S                double        cutoff = cutofftemp/(double)Config.sound.nRate;
/ @6 S" E! u% N2 a2 q& }% [                static        double        tmp = 0.0;
7 v, R- U' K+ G2 s0 G# E                double        in, out;
$ e) o, r  \8 f* R' q8 `5 N, r7 |- W3 s: t- I
                in = (double)output;+ H% V2 i/ \) e6 {% [+ r3 C; c* m* E( g6 u
                out = (in - tmp);
- T1 L9 S- g: W2 W' t" B+ Y. ~                tmp = tmp + cutoff * out;5 \0 [8 W3 z5 u/ v

& E4 y, f' `: Y# v* ?, n3 x# K                output = (INT)out;$ @; C3 f: y. e/ Q* E* J
                }
( o! K: s4 f' F6 }; g#endif! ^  w9 @8 N4 A% K5 z4 f7 s5 V  v
#if        0
2 V/ G* @$ Q  t3 D$ [                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)0 ?6 w8 Q; D+ S/ `! q: ^* F
                {0 p" C' h2 r* d
                INT        diff = abs(output-last_data);
. k+ A; w9 Q/ R6 ^6 Q  ~                if( diff > 0x4000 ) {% V6 B. Z! t' v/ j% M
                        output /= 4;3 i& c4 {& ]0 g* i' y7 z
                } else & i$ Q: z2 z/ }! ~# Z
                if( diff > 0x3000 ) {# K; \* N8 M3 L$ T7 h
                        output /= 3;
# i9 J9 I( u. R0 n# K! k                } else
% r  v+ D3 n) N% ^0 e                if( diff > 0x2000 ) {
. U5 \" c; Y9 f; M  w: D                        output /= 2;
7 x5 }% p! [9 z# @  i                }
/ q+ q' `% s( a2 ]% c                last_data = output;* z. d( L# o$ Z. q" b  s7 d9 J
                }
. B" ^  j- l% s; `5 ]#endif/ m* h0 R3 z% v
                // Limit
' O; W( {! i; B; j                if( output > 0x7FFF ) {$ M5 |# L- N, `; i& q
                        output = 0x7FFF;: d7 c9 v, S  W1 F, g5 p7 F
                } else if( output < -0x8000 ) {# t8 q) v( K/ r/ y' x
                        output = -0x8000;
0 }6 R3 W( b- p2 n, P/ Y& n$ l) e                }- c" b' Y3 w! A* I: \, R

% R* J  B) \) t9 r5 C                if( nBits != 8 ) {$ \. E6 _% S& D, c+ d. [
                        *(SHORT*)lpBuffer = (SHORT)output;! I* c% W. e8 r& Q7 r4 a. d! P
                        lpBuffer += sizeof(SHORT);; K  O) @+ w$ f7 r2 T3 C
                } else {# b8 ]% ?7 b6 c% `: ^- ~: @0 Y4 M) v0 q1 c
                        *lpBuffer++ = (output>>8)^0x80;
2 x* d: U& _( E  R0 R/ r4 ?; ?                }
1 T7 h% h. F4 y, }* p/ i) J; \! k1 w2 x' D) Z# E. j' o$ P
                if( nCcount < 0x0100 )1 @7 S! p5 x* @! ?
                        pSoundBuf[nCcount++] = (SHORT)output;; @8 L( y3 ]& ?7 A+ f0 [

# `% l. `$ ^: q$ R* N: A//                elapsedtime += cycle_rate;* i% r0 m2 E0 C, {! o
                elapsed_time += cycle_rate;
- |3 n$ Q, s! I1 r$ A, ~        }/ i4 I, w) [  T

  i2 B( H! }) C0 v! v5 L; j$ E2 d#if        15 L9 P) F7 ^8 _$ k) |, }" S1 _: l
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {; O5 t$ z' W! [4 X8 D( U
                elapsed_time = nes->cpu->GetTotalCycles();1 P* ^2 }2 I5 [: q3 G! T3 l
        }
5 l8 b9 y; D9 ^9 v  N5 ?- x, p        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {. F& a* J, q, [: S* }9 ~. l& N; C
                elapsed_time = nes->cpu->GetTotalCycles();9 T, {6 ]/ C1 Y) V
        }. e3 \  }. A7 ~* \+ t0 X) V
#else
  a) U7 H# _# E$ I+ A# J        elapsed_time = nes->cpu->GetTotalCycles();
& ~& u5 _# F+ e4 X' Z6 C2 F; ]#endif1 i" x* ^5 b- M5 ?' ]/ c' C( J
}- e) r* q4 o" o1 X: d

5 a4 j, L( o, F+ u" O' s3 [// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)) W9 j1 }' E8 a! C
INT        APU::GetChannelFrequency( INT no ): Y, {. u' r7 e. k
{' i& E6 h9 O. C9 B* h
        if( !m_bMute[0] )
2 u1 q. u" v# i% z                return        0;
% @: f4 B+ y" b  w0 \7 o3 j" U0 J! \; L7 n% Q
        // Internal8 x% a6 S' V' S9 j% }# y
        if( no < 5 ) {
  p3 x1 h) Q# }1 B) |& s3 F                return        m_bMute[no+1]?internal.GetFreq( no ):0;) ?; D9 W; L4 ~7 U
        }
& U# o0 M% h! g/ v7 e' D0 n        // VRC6, g  `6 F" Z) V! Z6 X
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {0 [. f6 R- D3 B( R; T' R* r' M
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
, O1 n/ g$ I! e: U$ G        }
/ h2 w8 o1 c. O  d8 ]        // FDS2 K3 y$ ?8 K( Q( W" `- ~
        if( (exsound_select & 0x04) && no == 0x300 ) {
& X% w# h" h2 w5 y% `/ ~* R                return        m_bMute[6]?fds.GetFreq( 0 ):0;
7 t& q$ B# ?$ T        }
+ B! O) q" J# K        // MMC51 q3 b) d% c3 S% |. {* J
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
: h. p  j8 v8 n$ I: t- C                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
8 E. M2 Y# m7 j: x! ~/ m7 v  a6 v        }
" j) j; b4 t7 K* u        // N106
8 O3 i# ]* W- w+ ~        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
% n+ U" t, ?9 L+ m" _4 h                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
7 g2 E8 l9 |/ M/ e        }
1 a! ~# M1 P. D) Q        // FME7
6 H8 }& u9 Q( ^6 Z( V  B! [        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {. p3 S" \  @' o4 q1 B
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
0 O+ h+ w. c2 }& u. ]0 n        }9 W! R4 r+ V9 Y2 U6 D
        // VRC7) S7 O; {: n$ [
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
" u. [" o* w- ~' K                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;1 @. x( @: y: l: F
        }" r4 g" T& Y% ?) A) n
        return        0;
- j& n% Y& C" B: {5 R: o. ]2 ~}: k: ]6 K* W* P0 X7 X) K* K+ o

4 q9 }; y4 O, T, _// State Save/Load" X+ k8 p6 b/ M
void        APU::SaveState( LPBYTE p )! S2 c, V( c" h, x# h- a- S
{
, c9 d, y2 @! k8 b" E( Z#ifdef        _DEBUG" K3 M% |) z6 R5 ?
LPBYTE        pold = p;
  X) q$ ^! _7 e, V! @#endif
. c& L: a' u* U* m; N
8 O2 h: f( g& T8 ]        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞, l5 `9 W; T% M9 X2 Y; Y& g7 w
        QueueFlush();
1 y8 r5 ~- ]6 d* s5 w% c9 X0 A5 T+ K0 K. l& F# d1 S
        internal.SaveState( p );& x- \6 A9 V( ]7 \8 V" s4 _+ E4 R
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding% k8 \5 O  a7 J, m  V
+ r. L1 m8 i9 j+ B. g" W+ v
        // VRC66 V! E4 h  R0 \( R+ B
        if( exsound_select & 0x01 ) {* z( @" G9 m# a2 a  D
                vrc6.SaveState( p );
' B" e1 j$ N# Z! k! P( P                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding9 g* M9 M$ l3 o5 }/ m
        }, x. [/ l( x& h( B
        // VRC7 (not support)- }* X5 V0 y: @$ z. T  M  @* {: a
        if( exsound_select & 0x02 ) {: e2 c  d9 v" l7 x
                vrc7.SaveState( p );2 Y2 m. N2 O" T2 H. w
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding/ S  M, z5 E- e5 x
        }! }0 \7 ~+ J( E* v  V! y# X) b5 X9 s, q
        // FDS5 n, x0 |+ f, ?5 n6 X5 n
        if( exsound_select & 0x04 ) {' r! j' m, r) Z# M- K
                fds.SaveState( p );# G" g" o! l1 t2 s$ U+ }
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
! F. A+ h/ H6 i6 J1 W5 C        }6 E" |( W0 ^" z2 y0 @1 e4 i
        // MMC5
1 Y5 ?; [+ V" {9 b8 F        if( exsound_select & 0x08 ) {3 s: ^+ L# z" F. Z
                mmc5.SaveState( p );8 l4 D" R8 j. _& A& F
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
: T1 k) s+ r/ X! w* k, I, k        }) O+ _  L, d  y6 t) x/ x% m
        // N106- m5 L" g7 \( D) E* M
        if( exsound_select & 0x10 ) {
+ ?0 S; v0 M, K2 `6 l+ V                n106.SaveState( p );7 i6 K, K9 J) i( H1 h6 o
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
  q( {' p6 N) N6 y9 q        }, O- q6 b9 E$ G+ {
        // FME7
" D& F. o+ ~) w) U/ y( r9 v, a) R        if( exsound_select & 0x20 ) {
: J. Y& ?/ r; V                fme7.SaveState( p );
- ?3 X4 a: f: f/ X3 }( i% [                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding4 |; ~% Y! k! P6 O$ @' z
        }- c( u6 P) _3 J! J- E0 H+ |4 k
+ W1 D$ Q& {# _: r
#ifdef        _DEBUG) |0 G# A& n) `0 l6 I
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
: g& I3 E! m$ {& t2 c#endif9 m5 S6 _+ W; M! ]
}7 Y- z5 s7 M9 h3 |! F7 T/ Q
1 f$ j" e+ s  J4 H7 @/ G
void        APU::LoadState( LPBYTE p )
+ C. w8 i5 _! R" g& j$ g{7 T( ~% S" B: H+ }
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
) F# n1 ~+ H, `# v# \5 z/ L. G        QueueClear();
' o: [/ o! V- B" J% ?) V3 p% G# T
% ]2 L* P' v; c8 L& L: e, W; u        internal.LoadState( p );: U- O/ V9 T" t/ {# T( ?, d
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
4 U+ U. c" v9 _9 M# z# G! H( `
! c& J& u* L: t1 g: `        // VRC6
2 ]. i9 p# V6 J, E" h, p        if( exsound_select & 0x01 ) {
9 j2 g- B, E  m; T9 w! m                vrc6.LoadState( p );
! D3 N, }/ F2 U% B8 G/ ~                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding3 i! \7 y( J/ t, l
        }
5 w& F5 [9 ?  j0 ~        // VRC7 (not support)
9 v/ F3 J5 @. n        if( exsound_select & 0x02 ) {* e( Z. n! f3 {; O9 I, q  `
                vrc7.LoadState( p );, P5 a, s1 I2 p4 L0 m$ Z! D* K7 V! `
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
) S% z$ X3 e. H0 }        }
# ?! n) k$ z' P( Y, E1 \        // FDS
) U/ f7 E9 G" L3 E" e        if( exsound_select & 0x04 ) {! z  ?0 g' R: I, g# B. G
                fds.LoadState( p );$ i5 R: h+ s  J& h
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding! H5 k: t6 u. f6 r
        }4 m5 a" X7 }/ U
        // MMC5
; F% m$ `7 c& m6 \        if( exsound_select & 0x08 ) {
+ ]3 U* _2 X4 n( k' ]                mmc5.LoadState( p );
5 F5 l! F) C& K                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding* t0 F% o& q9 w0 X! k: j5 ~3 M  G
        }
% R! \& N$ v! K5 n4 Z        // N106
; Z3 D3 R; z8 U        if( exsound_select & 0x10 ) {
- }: G, ?! L$ K/ @                n106.LoadState( p );
# L- u3 O2 [6 L7 Y  b) M7 ?                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
+ u% F: K6 ]( O. O        }6 v3 R, G' C) s* J
        // FME7( N" }$ W7 T/ h- e
        if( exsound_select & 0x20 ) {
- c$ q9 c$ F% b, X. F                fme7.LoadState( p );
9 l7 V) @0 k) }5 Z, a# J$ @                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding" z. J: S$ Z% _3 l$ h
        }3 v  y& n9 i( V- q' Y+ W
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
5 Q( C! u4 t% n( j可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
% ], l0 Y$ T7 _' |  D4 R; V感激不尽~~
$ y* G. a% W7 x. J0 o- Q9 {/ T" Z* X
恩 我對模擬器不是很有研究,
' ]3 K" b1 G! J# r( m( T雖然要了解源碼內容,可能不是很困難,
6 N1 H. |: |% n" G  Q不過還是要花時間,個人目前蠻忙碌的。& a0 T: [  O% ^

( n9 B# L& I! j) r( B4 o4 p給你一個朋友的MSN,你可以跟他討論看看,
  y$ }$ L* }* P( k; ?他本身是程式設計師,也對FC模擬器很有興趣。
! Y( n8 h/ L8 j; B$ U+ \
; I$ V* B) D3 H7 N& LMSN我就PM到你的信箱了。/ \' c7 ~; p) B0 {' n

, w9 ?2 e; j" K* e* |希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
( S4 r: m/ n. u# h呵…… 谢过团长大人~~

& ?+ g2 q: [& Z# ~2 F* v( ?  [6 m1 l# T' h: D0 u# S
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
8 t; Q4 [. w' w6 ]团长的朋友都是神,那团长就是神的boss。

7 q8 \$ w6 ?- ^& G: m哈 不敢當,我只是個平凡人,
, o! M* x( y/ Y要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
  s  H. @6 E; T% WZYH" L/ d; }& H5 C4 I+ ], j
QQ:4147343063 w' m4 y" g0 M4 c: G6 W- |) o
Mail:zyh-01@126.com* z. b) C+ |! Y6 ^2 R' V

5 Q9 V- ^# \$ u5 Q他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 , {  A: M+ e& P% r4 N1 `
再次对团长大人和悠悠哥的无私帮助表示感谢~~
6 s8 V" d' o- }& E
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-28 05:24 , Processed in 1.096680 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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