EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
- g9 S  Q$ S6 ?( D9 J/ o9 b楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~! X8 P- G+ y. j" L4 ?: g* s7 _
这里有相应的模拟器源码,就当送给大侠了~~
  s4 W1 V5 a- }8 F! |9 b6 X4 bhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 : f2 A+ o: j* w% j: k" A
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。: c+ j0 @, M7 A( x; A/ e4 g
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~8 L# b' c  c  Q' {2 _4 h  _% A
这里有相应的模拟器源码,就当送给大侠 ...
" q+ Z+ v* e9 e0 i+ E
聲音部分(Audoi Process Unit = APU):
8 J- R& b, N+ |' t. D.\NES\APU.cpp# \' K8 [  H) g8 H
.\NES\APU.h5 F9 _% r/ k/ o5 S
9 j: x2 f0 G( |; F" b* _, ?! r
" t1 Q3 c; c; ]
影像處理部份(Picture Processing Unit = PPU):
8 ]8 {* E0 _8 C% y( S4 I, D3 X; r.\NES\PPU.cpp( U5 o/ E4 u! G
.\NES\PPU.h( x; ?# K+ h( A6 Q
  G5 W2 Y+ o# }* h* Y$ B: \; k* y5 q6 Y
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
  H' A$ W. ~7 o- Y5 u(由于很多专用术语和算法机理都不明白,所以看不大懂……)# ?* g  m+ s$ f- v
//////////////////////////////////////////////////////////////////////////
/ a% x- j! ^9 O+ y- |2 j4 ]//                                                                      //) j4 c# o/ O& {, P/ w8 N& L7 i/ L
//      NES APU core                                                    //
* f4 P# f9 _( }* c% r% e//                                                           Norix      //
- V2 T  G& u* ~/ L9 S6 `//                                               written     2002/06/27 //
, f3 ]# r# g( s3 c//                                               last modify ----/--/-- //: c, W5 \7 C; I# B
//////////////////////////////////////////////////////////////////////////
' f; e* l% y# C$ l: _#include "DebugOut.h"
- \" z9 a) u; [2 B, H#include "App.h"$ ?) R0 S( }9 i5 C! u, `
#include "Config.h"
  w& e8 g; m# h* p% b6 P$ \5 G/ u- r3 n, F! U4 _, ?
#include "nes.h"
+ u; c" Q' t- s" M  Y#include "mmu.h"
2 Z* \: V$ a/ i. \#include "cpu.h"
( V! ^- L- P# X3 T#include "ppu.h"# L7 x' V5 |$ e) H! @3 X$ I
#include "rom.h"
1 T% j4 x% j4 G  U+ X; [#include "apu.h"
" ?, K4 a7 _' ?+ |
2 y' ~6 c$ @1 b9 o$ n8 K! X+ a- n$ m// Volume adjust9 ^( W! g. ~7 g  P
// Internal sounds
; j# }' {& r; N  s+ x* F#define        RECTANGLE_VOL        (0x0F0)
* d; c9 O' v* X9 [#define        TRIANGLE_VOL        (0x130)
3 H. I" p( @: N" b% s#define        NOISE_VOL        (0x0C0)( ~  }5 f( i+ ]; V3 ^0 ?/ C6 u
#define        DPCM_VOL        (0x0F0)# K  j/ b8 h; x, j: n9 j" V
// Extra sounds
" U5 L2 S2 a0 ^; d' Q9 Y#define        VRC6_VOL        (0x0F0)
* C: T$ h9 P0 z0 h& s  U#define        VRC7_VOL        (0x130)9 D& g* C; [3 g
#define        FDS_VOL                (0x0F0); U. N. D: B% P/ `; n4 \
#define        MMC5_VOL        (0x0F0)" f2 j6 @' S6 q
#define        N106_VOL        (0x088)
9 A5 a0 Q: |7 w9 [  n. x/ V6 }! o#define        FME7_VOL        (0x130)
  H* F2 b4 X: x. X1 d6 B3 Q7 I
3 N# t1 y+ C& S' ~% O  |APU::APU( NES* parent )
! M* ]+ R! L2 D$ {4 U  t6 }{
7 t0 L2 l! B* [& J; y  G        exsound_select = 0;) w, |3 j; |1 e3 l  n. r
% F. B  F* Z4 o: Y% k
        nes = parent;
4 P+ Y) p, w- a5 c- r' K        internal.SetParent( parent );
  q. z  x! d$ ?5 q! O/ l& ]/ L) p, p
        last_data = last_diff = 0;
! w8 W: ]1 X. ]  K$ Q4 m9 S8 i; C# T+ F1 A& J
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );/ y; p; L. Y9 q2 C) t! b6 K& f
/ q" |- p4 x3 a3 n4 z# j" x# _
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );) l2 l, v- A, Q6 x% X
        ZEROMEMORY( &queue, sizeof(queue) );
& |' }* M4 a; z! a8 d# |0 S        ZEROMEMORY( &exqueue, sizeof(exqueue) );
' b. K* D5 g4 j% w" M) W' I; O# G& P- u+ N
        for( INT i = 0; i < 16; i++ ) {
- v; a( R( y; s. Z, l- h  h2 @4 E7 D                m_bMute = TRUE;8 P; b' ]/ L& M' Q
        }2 h! Z* n: D6 M, v3 Z) q9 D7 S
}  }7 s3 @1 x, ]2 R  X% r6 K( o2 k

" C2 G* w& ~( h. nAPU::~APU()
, ^0 ?( Y/ j8 q: a) V{
1 n% d3 i; @% f9 z; J}: }7 T4 [: d% s- x- [% z
5 q! Q% m, z4 U' }
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
  J# C+ p0 I7 a{
: p# L: X9 q& U' @4 k' g        queue.data[queue.wrptr].time = writetime;0 x1 M# z) X$ _3 i: y
        queue.data[queue.wrptr].addr = addr;/ @0 W7 L8 i; W, S+ N, ?4 U3 E
        queue.data[queue.wrptr].data = data;$ o7 a8 I6 q, \% a) ~
        queue.wrptr++;( f' Z2 @3 s7 ~
        queue.wrptr&=QUEUE_LENGTH-1;
  l  ?& T' p( B- `        if( queue.wrptr == queue.rdptr ) {
$ z$ s( K& f$ Y+ F4 A                DEBUGOUT( "queue overflow.\n" );
: R$ c) u' H$ {        }/ N* i# r  S+ V8 O' {7 |8 g$ j
}
) Y$ [, O1 `3 y" }. K/ D$ |8 `: b# Y  m/ K) Y2 l  E0 E9 N
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
8 @1 [$ W  D# ~# W{8 A# i" u6 O7 y8 D
        if( queue.wrptr == queue.rdptr ) {
$ r( ~) s/ t4 P1 {$ T. a! N( [, m/ l                return        FALSE;; Q) X% {! N" c2 V' v
        }
7 x  A0 v6 x' M4 x+ u        if( queue.data[queue.rdptr].time <= writetime ) {# x1 {# i2 e: [/ w
                ret = queue.data[queue.rdptr];. [9 v7 {; F2 Z4 y
                queue.rdptr++;
+ k9 |% g' c  J4 x                queue.rdptr&=QUEUE_LENGTH-1;
. z; K7 V6 ?- W+ ?                return        TRUE;+ P  C: J3 t3 X
        }
( y0 P1 _+ y" E0 q6 K        return        FALSE;
$ }/ i, b; b% v7 @1 j; O6 i/ @; P6 U5 d}
& e4 w8 h  K  B  O8 ~: E8 ?& g- {7 y  C
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )  _9 e; J- S- o8 F# x
{
% l$ P2 [  d8 W7 j! z3 p: J$ p) S        exqueue.data[exqueue.wrptr].time = writetime;* C8 j9 A3 ?6 R/ x" l7 B* e
        exqueue.data[exqueue.wrptr].addr = addr;+ ~4 Q2 n# G* H7 y2 r% z
        exqueue.data[exqueue.wrptr].data = data;
1 I5 @( N, L' O3 q) y        exqueue.wrptr++;8 J- M7 g7 ~% ?
        exqueue.wrptr&=QUEUE_LENGTH-1;
6 l, J& C0 {: x; A        if( exqueue.wrptr == exqueue.rdptr ) {3 s8 F9 z4 a. a/ ~4 H7 m
                DEBUGOUT( "exqueue overflow.\n" );, s; W$ B" X& L2 [
        }
1 ]6 w. N! x" X7 z9 H5 L: M& e}
6 P- M7 E$ D) J3 q1 |( B: `7 _/ J, F, ]+ L$ ~( p$ N
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
7 M9 E+ c4 z, Q. G& l{3 ~/ H2 y& F# p3 A
        if( exqueue.wrptr == exqueue.rdptr ) {
) g  L4 [5 x9 i2 I5 q! T5 T                return        FALSE;
1 ]0 S" X& v- b, y" c& Q. o& b        }
3 W8 d' Z0 x9 J$ E        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
6 I( A5 C$ |; i/ v# n( P                ret = exqueue.data[exqueue.rdptr];# Q& _, z0 {; G0 e4 D1 p
                exqueue.rdptr++;7 {5 Y5 i: I( ~* O" w! ?2 l# z
                exqueue.rdptr&=QUEUE_LENGTH-1;2 ]3 M$ P, {5 U4 E3 w
                return        TRUE;: f# G5 z9 O' j1 V' ^
        }
; j! I! P0 U9 m+ }        return        FALSE;
. o! ?9 Z. Y! U3 Z5 k2 i}
9 p& Y0 C0 t# l2 N4 A# N, t- X- ~) S& h! d- j! w
void        APU::QueueClear()
0 L% i2 L; ]+ \3 t2 U( {! ~, E{, P; Q1 D$ i# q$ U" y
        ZEROMEMORY( &queue, sizeof(queue) );+ _! X7 [: v3 v  w: y
        ZEROMEMORY( &exqueue, sizeof(exqueue) );) Z& l0 R. G' T* P5 |) V! r
}
1 q! C2 n) H' i7 U
& Z. f! E- u1 z; T* [3 W& Fvoid        APU::QueueFlush()
2 f: W& j( j; f. V7 R{" d$ O: F- N3 ]- ]/ H6 w5 J4 B
        while( queue.wrptr != queue.rdptr ) {/ G' J+ V* R7 \+ Y
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );; J# d4 \( T. I2 v4 l
                queue.rdptr++;6 i$ C& e2 S( A& Q/ T: l
                queue.rdptr&=QUEUE_LENGTH-1;
% a$ I0 A2 [$ q        }
/ g( V3 E7 S" h$ Q. |& {3 }5 a* D" H: ~( Z. @, O* U/ o
        while( exqueue.wrptr != exqueue.rdptr ) {
" o9 z' X( k: F# ]                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );6 Z# d  O: K: E
                exqueue.rdptr++;
* T3 T5 Z% _# I4 c7 e                exqueue.rdptr&=QUEUE_LENGTH-1;
/ _5 ~) t  A/ b! g& j1 F- @        }
, Z& @  y* n$ W% `# a1 J8 Y}- F2 J' K& Y1 X. d6 C/ y
6 V. T" D4 }  J' u7 f# R" O0 W2 V
void        APU::SoundSetup()+ S+ _, Z3 Q# a
{
! z! o2 B' t0 T* O7 Y: T- l8 d        FLOAT        fClock = nes->nescfg->CpuClock;' {" \  L8 Z! M' n* o
        INT        nRate = (INT)Config.sound.nRate;9 E- ]9 n. a: I
        internal.Setup( fClock, nRate );) J# W7 P- b7 B9 X
        vrc6.Setup( fClock, nRate );
& p$ P# Y; o; W5 C        vrc7.Setup( fClock, nRate );" D' c, O# T/ c. R& s) S
        mmc5.Setup( fClock, nRate );: X, X8 R1 f' L4 `0 n
        fds.Setup ( fClock, nRate );7 a  p3 O2 {0 Z) j
        n106.Setup( fClock, nRate );
, M% x! _- \8 B/ w/ L        fme7.Setup( fClock, nRate );3 i& C; C4 A9 n6 g* ^7 `( y
}, Z! S# G. |. ?) L
' `9 O2 J2 y% R7 L4 L& Y( |5 F( X3 a0 h7 q
void        APU::Reset()  R- w( f4 k2 z+ v: H% J
{$ c: Q  P4 |! p9 `1 v  W0 g
        ZEROMEMORY( &queue, sizeof(queue) );9 P3 [+ N; I. ]) u
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
  {3 E1 A/ p6 h# [. a
8 {1 u* d8 ^2 p( F* b8 n# y        elapsed_time = 0;) c1 b' |1 ~! `

% Y- o8 @  _4 B/ J- g6 _" J4 f. ~  `        FLOAT        fClock = nes->nescfg->CpuClock;
8 Z! A( S+ L$ K, P# R1 V( J  z        INT        nRate = (INT)Config.sound.nRate;
/ q+ O( b/ G3 _  B& |1 {        internal.Reset( fClock, nRate );
: ~$ }9 k8 U8 N# g9 \+ A8 d        vrc6.Reset( fClock, nRate );
2 d7 n+ M' f' l& J) H: K        vrc7.Reset( fClock, nRate );! ^. g) S. D- x) F% ?
        mmc5.Reset( fClock, nRate );2 @/ F+ t3 [1 B4 N6 n3 {' z; p. m
        fds.Reset ( fClock, nRate );
, \0 [  N1 N4 ]; K- h6 n        n106.Reset( fClock, nRate );1 r; p" u5 i9 b7 r4 L4 O4 q3 P
        fme7.Reset( fClock, nRate );
4 g5 c9 {7 n! l" m5 x2 e
& V: r, V1 U3 k9 o1 c8 E1 {! Y        SoundSetup();1 q9 z% ]. [7 ~' E
}' J9 A0 Z+ D# ?% G( {9 s
- g: Z# N# _7 F. [0 C5 u& x4 I
void        APU::SelectExSound( BYTE data )/ r3 O3 Y' x1 q# t2 a
{
6 e- D. d# c$ W* G  m8 s5 Q7 f5 L        exsound_select = data;
8 I- h4 v( y* L1 F0 Q; P' e1 {}
3 O, [5 @  s9 {( E+ y9 ]
! N  N' J( Q. w8 y8 o. w. [BYTE        APU::Read( WORD addr )
8 N  n# N0 m& R, y7 [3 V& v{' `$ Y5 s7 E3 c( N" a, {/ c% ], w, `
        return        internal.SyncRead( addr );
1 ~8 V, o8 s6 I0 q8 U}0 C% }! M1 Z- l/ `3 w

7 Y* m7 A6 x& m/ X* L- zvoid        APU::Write( WORD addr, BYTE data )
. o) a( b8 c/ ~& i3 h6 ?# @{7 x# ~! t, h! {4 [
        // $4018偼VirtuaNES屌桳億乕僩
5 O) C, w" M7 N; V, a. O5 k        if( addr >= 0x4000 && addr <= 0x401F ) {  [7 m$ j9 N' B+ S' }8 ]5 O
                internal.SyncWrite( addr, data );$ S! y1 E$ G( w
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
7 p5 G: A7 o2 o8 G- U        }
4 P  J' ~" `; L, r1 r: S  l2 A}5 P+ y; r7 a8 n3 W2 S. }' l

, F7 z" m& U' E1 rBYTE        APU::ExRead( WORD addr )9 t8 e1 J0 m/ C1 d9 J: ^7 M
{
4 |- H3 c& s4 g8 b+ D6 ZBYTE        data = 0;
$ ^: D& F& i$ U+ Q
$ j! i( u& V) ^+ e6 E. N6 T        if( exsound_select & 0x10 ) {) w( g) S6 P5 Z: J
                if( addr == 0x4800 ) {
+ Y! E& }$ K4 x2 W- u" v                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
4 ]5 I2 F9 ?; {. Q, u' @                }
1 t2 D8 K9 O9 S5 s/ e        }
% _* A9 W/ p, \& K# j- R7 o        if( exsound_select & 0x04 ) {
3 G& D1 T$ s+ u9 @+ T. z5 M( h                if( addr >= 0x4040 && addr < 0x4100 ) {+ w2 ?! M  |* v* }) b6 y6 @3 Q
                        data = fds.SyncRead( addr );/ K0 g+ a- C. c) b+ W# P: {! |
                }
( L0 f" J# \) J2 Y; f$ K) @        }5 U. h+ T2 o6 b, l: T: r- J
        if( exsound_select & 0x08 ) {
& k# s. U; t& s9 h5 |; X% ]9 u; U                if( addr >= 0x5000 && addr <= 0x5015 ) {
! q3 O2 V; w5 j8 J                        data = mmc5.SyncRead( addr );9 j: @7 H0 l1 d# `* |/ B5 `% J' e
                }3 P  u, f1 z8 W9 b/ Y
        }
, K/ L/ _% D; Q3 w! s( a- o1 R8 D" A# a3 F( @' R  x+ y
        return        data;
' j: L& b! L: O9 f6 h9 V}# c8 j& l; ]+ @

4 t3 P4 \* z, D, s# {void        APU::ExWrite( WORD addr, BYTE data )
( r, C% A' B# ^5 N2 N# ]5 U% h+ Q+ Z{' ^0 }8 R8 N$ k: h
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );% C9 \1 C) K! @/ ?3 z3 B
4 E3 D3 Y) V# L0 \1 ]- G0 M% l$ O# D
        if( exsound_select & 0x04 ) {: z, F' U6 p7 C+ n, J; f. R0 `
                if( addr >= 0x4040 && addr < 0x4100 ) {! t* K6 v# p+ ]5 D4 T
                        fds.SyncWrite( addr, data );
: S. t6 [* f; Z& j; B9 C$ C                }" G7 V9 ]2 z) O1 F. D' R) s2 b' o+ ^
        }8 o0 e5 ~* M$ H% q8 q' C
9 K$ O: B5 l; i  R% C0 W
        if( exsound_select & 0x08 ) {: @- j9 n" N0 t, U/ Q' w
                if( addr >= 0x5000 && addr <= 0x5015 ) {3 J0 W( h! {* ~/ P( b# i3 h
                        mmc5.SyncWrite( addr, data );
6 {. m5 ~$ E' W                }
8 k" O6 ~' b- H        }- l, ^% w' W" |* s$ m8 |7 F
}4 o: D8 q- R/ q( P* [

/ A9 \6 F, l. n8 ]! ovoid        APU::Sync()# u8 l) Q' w) a3 u3 A/ ~3 p
{
. X& c4 J/ w3 Y" @% x2 j}
0 b' Z: {& U3 o" @9 R' f! @/ `( q4 r0 j* x
void        APU::SyncDPCM( INT cycles )' R! \" ?3 I, i0 t
{. P/ P- J3 z  M& M
        internal.Sync( cycles );9 L  ^: x0 s/ s4 G1 G' \" Z

; F# y8 k* Z; c9 b7 }        if( exsound_select & 0x04 ) {
) q& o9 i! ~/ @0 t: Y) F                fds.Sync( cycles );
: p+ q* T1 q4 H6 n- P' K        }
6 ?  B; V6 x  |& J        if( exsound_select & 0x08 ) {
" R  l; g2 n: I8 U4 H* f+ t                mmc5.Sync( cycles );: ?4 ^5 a7 \  M8 k, _
        }* Z; X# C" l0 e" @) b1 X+ d
}
1 l& g5 I8 i, W# I' _2 ^
" H  |& t% [, b' G; ]% Dvoid        APU::WriteProcess( WORD addr, BYTE data )) d0 C1 D! `+ x. I" R% r
{
5 Y& L! D4 i' w7 i, a% u  ]5 H        // $4018偼VirtuaNES屌桳億乕僩+ o  @+ m; O6 `! t
        if( addr >= 0x4000 && addr <= 0x401F ) {8 |3 s3 a0 b1 E* }! T3 N  P0 Y
                internal.Write( addr, data );
  {$ G7 I( M( L! c# V7 A( n        }
) x' D1 f! U' f+ N4 v6 y}  K2 e, w" T8 u, A  N

8 A" ^$ p6 }* ?void        APU::WriteExProcess( WORD addr, BYTE data )( f! U9 e9 L  z
{
9 y# [5 p$ ~% Y: I) ?( U1 o( n. Q( f! o        if( exsound_select & 0x01 ) {7 R" |: m5 G, j4 _- _; x
                vrc6.Write( addr, data );
/ g% V+ s! I8 Z" H$ ~6 E. W3 l8 q        }
: p! Q1 E5 o) C; m9 ?        if( exsound_select & 0x02 ) {
9 `7 p# z7 J9 S! M- Q8 E! Y3 M0 V* _2 P                vrc7.Write( addr, data );: i' L* u! w' v* h7 v
        }! p8 U8 V$ x9 A# @
        if( exsound_select & 0x04 ) {
, g9 u. h' Y" P9 P                fds.Write( addr, data );
, _0 |, e; n0 E' _        }
# F4 c8 s+ c9 S  x        if( exsound_select & 0x08 ) {* u. T2 q9 f1 t9 W
                mmc5.Write( addr, data );2 y3 D+ [8 k% `
        }8 Q% n! j1 V& g" C0 D
        if( exsound_select & 0x10 ) {7 Z4 |6 G) t1 v1 w
                if( addr == 0x0000 ) {) j+ O# L2 G4 _9 f. ?5 a, a4 T5 p
                        BYTE        dummy = n106.Read( addr );
7 k3 K1 _# L% j- _                } else {
4 @4 P% G! y9 Q: K                        n106.Write( addr, data );
7 O7 W5 y) a% }' `                }2 D0 J: @9 W6 f2 G8 a* f9 e
        }8 d8 ]* `4 w; c8 V3 C% I
        if( exsound_select & 0x20 ) {
3 ^( v. w" j: \; D; N* z8 _                fme7.Write( addr, data );
" }# N1 b5 A9 R, o; A# H$ m9 T% P6 n6 z        }
- D" i$ B5 j: C( H0 x}
9 ~2 h  R/ U0 r& ~9 w& L
4 _) v: Z( P) ~) u6 D; u' Rvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
. ]; ^# A( K% p3 Z, N: u{$ J- ?/ M0 b5 ]4 `2 Q% @" E; R3 [
INT        nBits = Config.sound.nBits;
- s' `: \+ I" B: ^7 J& l! a. q3 {DWORD        dwLength = dwSize / (nBits/8);
1 w- B1 X# a$ o3 B) LINT        output;
. c& K% t* W, J3 ~QUEUEDATA q;
4 b% O; v- U+ T$ k& z0 [' uDWORD        writetime;
' p/ ]" R' {( ~" I5 g
. F* {2 n4 c& A; o" D$ YLPSHORT        pSoundBuf = m_SoundBuffer;, N8 C/ `5 o6 _% `7 k
INT        nCcount = 0;$ J" t4 \8 E4 I+ g( R" l: |1 Z

* e1 J, d! h! o8 W4 A" yINT        nFilterType = Config.sound.nFilterType;3 S, Q" ~* l# H3 b) x, w5 l+ M
& B$ `2 Q# H, I+ d4 h3 z7 }
        if( !Config.sound.bEnable ) {7 d0 _' q( C$ Y  t9 j, r1 O
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
) f) [: |9 q/ E+ o# T5 m! _                return;
) t/ b  |/ L( y/ v$ @8 _! ~2 P, c( L        }# g3 X- y' M- @' t6 O; ]+ D$ ^) Y
8 o! I9 A% I( `) m
        // Volume setup: j  K0 s5 r; E  c0 Q$ A4 K( q
        //  0:Master
" ]( K5 t8 R1 V- `( s5 t        //  1:Rectangle 1
. l( a, c$ X9 I% p        //  2:Rectangle 26 U: ^4 ]% b' z' ?- z) l
        //  3:Triangle
. v0 K( T! R$ O2 y- [. ^( _6 s        //  4:Noise. }$ s% m4 r& d/ {- e2 `
        //  5:DPCM
5 F; g! s  ]% a, p0 ^        //  6:VRC66 p8 Y. i/ J5 h8 Y' m! `
        //  7:VRC71 S) w, v3 a8 Y- _$ t+ g: t( x
        //  8:FDS$ K" i$ |) }, j" ^% G
        //  9:MMC5
% a$ z; x% H! N        // 10:N106
) K- {, A" {" j" H. X7 x# v$ `2 J% _        // 11:FME7
  B9 v$ U1 \( f        INT        vol[24];8 p* n8 m6 o" ]
        BOOL*        bMute = m_bMute;; b) U: d# v3 \+ x$ N* U1 K$ `  l+ o
        SHORT*        nVolume = Config.sound.nVolume;# i' L7 k- @* m& r+ f

+ D, a0 t; @6 f) F        INT        nMasterVolume = bMute[0]?nVolume[0]:0;/ o+ l( ?/ g- H$ f* {5 f

# G9 M4 ~: c3 I9 S4 l5 H        // Internal5 `+ L: H) b3 H
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
, p8 h) }( S( w! ?        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;" D2 r2 {# n( i6 s
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;$ N8 l% q- u. R6 y' x
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
6 E: H# o, j- t- C3 q7 c        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
7 A9 z* e# S' s# x  l7 n2 k. B$ @" C# L( H; _. |* Y4 t# R
        // VRC6
) d5 z* F# M% U        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
6 y* \5 x, M. n9 l' Z/ l" S9 A        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
' \9 J# D4 {$ }- v/ }        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;0 V5 g9 b7 P$ X

8 b' @- z- D7 T9 s" A# ~3 U        // VRC7
0 m$ f1 c! S/ h7 f8 w2 E# {& P# i        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;! }8 X/ O; X1 n: s

+ ]( d8 Y* A6 i8 ?+ T! _        // FDS  _' f2 t* m: N5 `+ w& ^1 j9 C: q
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
' k6 @4 [3 e9 p( J  {) a4 i
- H5 ]* S3 Z. E8 x        // MMC5
+ n; r5 Q% Y2 r$ O" R  a1 o! z" Y        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
6 Z: y* \9 t% |- a% h0 n        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
: R3 M, M* g( |% V  i        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
, B5 R2 Y( I4 j! J8 z
- i# @* m: @0 B0 D  ^6 @+ i$ y        // N1060 Q+ t4 p: Z8 C# D7 [0 D
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;2 v5 v4 r& E# D' q" g
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;, C; V$ A4 B9 Z4 f9 M6 Q) n
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
  i' I9 K2 q% t7 a        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
' r4 y! m' L  [7 E4 E        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
. u6 O4 j5 [8 r. r) e" F- @        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
6 R- d0 [) q, w9 n        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 C: F5 ^# f( u        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
2 W+ z4 J! I; F. k6 {
% Y  B' L' k& l# f        // FME76 I1 m6 A4 T2 b( S4 I- N
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
: M) t/ t2 }3 [: V8 Z0 i        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
) o( l$ S5 x  ^) m6 p5 P+ I* ?9 t  J        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;& L* h+ W. a$ s
+ Y7 g6 Q) F, K1 J# f
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;" Z1 ^9 }2 u! }3 j
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
2 G9 i, U% u) j) X
3 @; x5 g0 _% S        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟4 |& U6 _8 A% `1 P, @* Q
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
+ z1 b1 e- S/ k: X                QueueFlush();
* v3 K4 @! O: _9 L! {/ b        }, I  e* p4 u7 x2 ?
1 {" v9 j$ y  Z3 T) q! g* g
        while( dwLength-- ) {
0 r" e9 R$ d* ~1 h$ E                writetime = (DWORD)elapsed_time;
! m9 f* l: v/ O$ q; b# }
) i8 O$ L$ M; H' j( z7 r( B, N                while( GetQueue( writetime, q ) ) {
0 M( X3 X9 y; F1 h8 v! L, _. u                        WriteProcess( q.addr, q.data );5 T* g4 X/ E  n9 \8 _
                }0 {7 \! B9 F, e5 h5 S
& h: D. O7 g1 a5 t# I1 V
                while( GetExQueue( writetime, q ) ) {
5 c' P* M# x) K# E; Y                        WriteExProcess( q.addr, q.data );
0 S! e: b+ z7 F1 \3 B' B3 |3 Q                }
( }. M/ `. n3 _( R5 p5 i4 g% i2 n' M* Y
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
" Q8 f; ?5 g1 @! M+ T                output = 0;
. m& N: e( v* Q                output += internal.Process( 0 )*vol[0];; E$ {. w* v5 j! R" h5 E
                output += internal.Process( 1 )*vol[1];& Z8 O! }. O3 M6 t% u1 {3 g
                output += internal.Process( 2 )*vol[2];
1 [' a, e) T, I! I1 \/ h- I7 \% i                output += internal.Process( 3 )*vol[3];2 U# @' e: H# z/ n/ Z. c1 v
                output += internal.Process( 4 )*vol[4];
5 Y1 Y9 F) o8 y, i" z
. p; }: k3 J: m9 h4 P. m0 m! T                if( exsound_select & 0x01 ) {2 t& Z8 X0 p6 f3 Q% d
                        output += vrc6.Process( 0 )*vol[5];
+ h- |# U/ I6 h, F1 a9 ]                        output += vrc6.Process( 1 )*vol[6];
; N% Q; \% q. A. B4 T                        output += vrc6.Process( 2 )*vol[7];/ Q- n) ^. D2 I. A
                }
# K2 D# ~- W  m( d5 m                if( exsound_select & 0x02 ) {
- y% g6 f. ~( @; Z- l# |$ W                        output += vrc7.Process( 0 )*vol[8];
6 n4 {5 v. ]7 K3 j% T+ G( H                }
7 r/ W, K; Y/ v/ G9 b0 C5 O2 [                if( exsound_select & 0x04 ) {) D5 j7 D! I3 C6 E2 i; X( T( F% L
                        output += fds.Process( 0 )*vol[9];: j& C2 X- y( ]) k4 I2 _6 ^
                }8 }. D0 P3 m- t5 Y
                if( exsound_select & 0x08 ) {4 U! d- _1 S" K% a9 I3 y
                        output += mmc5.Process( 0 )*vol[10];
) S/ [9 f( a0 A+ w5 Z0 ^/ l                        output += mmc5.Process( 1 )*vol[11];# G$ ]/ D* D( j" i. S8 g  f
                        output += mmc5.Process( 2 )*vol[12];# G8 `6 j, F9 U) i0 q7 f* Y
                }
1 M0 l0 l: g( R, y) H" k/ c) w; @                if( exsound_select & 0x10 ) {
6 L1 Z2 x2 r% K4 w+ g, E                        output += n106.Process( 0 )*vol[13];
6 y) v  k1 F2 G! C# ~4 ^                        output += n106.Process( 1 )*vol[14];( g/ [1 s2 z+ q# d: v
                        output += n106.Process( 2 )*vol[15];/ u' D) k4 o! W. J7 E& n& \
                        output += n106.Process( 3 )*vol[16];
5 Z! x8 v2 I8 N- l* W, {( ?                        output += n106.Process( 4 )*vol[17];2 M1 Z6 N8 C, r+ x9 ?' D
                        output += n106.Process( 5 )*vol[18];
& V* x- C, E9 {0 `; K( M7 `                        output += n106.Process( 6 )*vol[19];- O+ \3 I+ d) H4 ?9 z( P
                        output += n106.Process( 7 )*vol[20];, P0 L! X2 j# V) f
                }
( {% ?/ E* |/ O1 L) g! @                if( exsound_select & 0x20 ) {& Z/ {% P9 ?, S- L
                        fme7.Process( 3 );        // Envelope & Noise. [/ a4 D" k6 {4 x& y8 P. }
                        output += fme7.Process( 0 )*vol[21];% q) ^$ j- s! W" e+ J- z
                        output += fme7.Process( 1 )*vol[22];$ F9 a: S$ @& r" {8 \& O
                        output += fme7.Process( 2 )*vol[23];
  g1 n& l8 A; |6 Y8 j' a8 O2 A                }
: w# t( A4 p* G, X4 z& P- m% M, q
                output >>= 8;/ Z5 E+ k/ V1 f

9 I' F+ U0 e4 f& O4 X9 d& N                if( nFilterType == 1 ) {! @0 e7 y' T# h9 C
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
. c- J4 [1 X  _                        output = (lowpass_filter[0]+output)/2;" m8 a7 N" l- z/ q: Z% @
                        lowpass_filter[0] = output;
# N" e+ d; t% |# [& w% S                } else if( nFilterType == 2 ) {; a. Q1 T/ }2 q/ t* n
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1): V5 l* W9 ^- W: m) l
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
/ F: q, U, U1 m                        lowpass_filter[1] = lowpass_filter[0];8 ^! N" Q, Z' i! `5 |
                        lowpass_filter[0] = output;5 j1 H# H( I- w8 z; K( J
                } else if( nFilterType == 3 ) {( O5 J6 U; Z: P7 Y' F* h5 n3 v
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
9 ]0 ?& o2 P4 ]0 J                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
, Q/ q) O. h- v/ C                        lowpass_filter[2] = lowpass_filter[1];
) {8 f: C' m9 Z6 z4 U+ A                        lowpass_filter[1] = lowpass_filter[0];$ ^; K1 p: f* s
                        lowpass_filter[0] = output;0 x, |$ e7 b# k* P& H# `- v
                } else if( nFilterType == 4 ) {
& P& a, F7 F9 C% ?$ d  z                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)1 X# D$ W+ |5 g7 l# G  Y
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
* _  i! [, m* N. t: V                        lowpass_filter[1] = lowpass_filter[0];
, S3 _  K5 c1 _. d                        lowpass_filter[0] = output;& N% z: `8 V! ~( s0 q
                }& V* L: l1 X* H7 P

. a+ x5 `' Q! P8 e  V$ n0 N6 r#if        0& E) P4 E7 P$ J( H' b4 G
                // DC惉暘偺僇僢僩+ b3 O, I/ ^  e% j- }7 V' Y
                {3 A6 F- o5 R- s/ K
                static double ave = 0.0, max=0.0, min=0.0;3 |  b% c6 e4 ]1 S$ b( _
                double delta;! t7 ]% b' z: G6 W! _* d5 g$ G& _" q
                delta = (max-min)/32768.0;
7 y( i8 s" A6 l% b8 N                max -= delta;% _$ n3 G0 @) \3 L' A( R$ R; d" o
                min += delta;- u" C) x0 Y' q
                if( output > max ) max = output;* H! j  y9 V; Z# k% S8 O2 w& @
                if( output < min ) min = output;
  _: G/ S' S8 p                ave -= ave/1024.0;
# x4 `$ e8 ?# ^- N                ave += (max+min)/2048.0;: q" o) @3 X- R
                output -= (INT)ave;' F: z+ r8 w6 c
                }
% x* q* O8 j$ @9 u#endif- J( Q9 E% `$ J) p
#if        14 L* M7 ~2 @& @: B2 R
                // DC惉暘偺僇僢僩(HPF TEST)9 [' d& B/ r1 E& t: M6 g3 \
                {
% g, c6 ]: e3 j7 _2 T8 }//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);9 W. d4 i/ g( G$ v4 J7 n
                static        double        cutofftemp = (2.0*3.141592653579*40.0);* f7 r4 r' j( X9 a0 e
                double        cutoff = cutofftemp/(double)Config.sound.nRate;/ t7 [+ }9 h0 x$ E" J$ C2 i& P
                static        double        tmp = 0.0;: K! x2 e1 `- P& Y; d# @
                double        in, out;1 ?- U1 m  |% {! [- U
) E1 T" f) ]& O/ x. s' j# i$ B# V
                in = (double)output;. ^# F! \4 I% j6 ?& @8 _
                out = (in - tmp);
; T$ q, W2 t* _                tmp = tmp + cutoff * out;
0 _1 H  V; ]9 z! Q8 D# N
% y" J8 p: S1 ?- Q' g# _2 |                output = (INT)out;
9 p6 X; t$ g  l. Z% i                }
# C7 D- b9 E" I2 F2 L  s#endif& o% N! |4 B. O4 d" z% |$ ~
#if        0# ]9 I* D# o6 F0 s& f- F+ _* F$ ]
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)7 `) ?# V  l4 `# q4 q
                {5 c" O" ?+ Z  s1 b( Q" A& Y) J
                INT        diff = abs(output-last_data);* ]( j! j1 u# n7 |# Y( `7 @
                if( diff > 0x4000 ) {4 O" h- q$ r1 _) l0 G1 u
                        output /= 4;
9 X& y- |) Y3 T. U9 X+ y                } else
# ~* V+ U5 C- A. x                if( diff > 0x3000 ) {+ M) z7 u- p+ g6 r. O
                        output /= 3;9 N% A- [% g. @5 l/ n& _
                } else
$ N! A+ W+ n- s8 i& n  V                if( diff > 0x2000 ) {
" ^6 L' o& e! f$ |- L                        output /= 2;4 A5 x4 P$ s5 [1 n: ~, L
                }
$ D5 R4 o5 g6 N& E* J+ b                last_data = output;2 Z) a# \. D% r# }( l! Q$ D9 {
                }7 c9 B7 e( r% s1 H
#endif9 y( _) f1 a2 i; o$ i3 |5 z; [) Z
                // Limit
, f. r& r/ u; F# f% b                if( output > 0x7FFF ) {* }* f. G6 z5 s# N: X
                        output = 0x7FFF;( c  `, F+ L) n0 q/ |
                } else if( output < -0x8000 ) {
" s8 ]2 |& Q4 C% U- y                        output = -0x8000;
( @% Y! j1 e; o( ?( i  T5 H                }3 ^5 G* k3 k: e( X1 x

1 r. c/ B! Y; M                if( nBits != 8 ) {5 l, k0 p9 U- A( _7 E/ H7 L7 i0 N8 S* s
                        *(SHORT*)lpBuffer = (SHORT)output;0 Y8 r8 P1 I* f, b8 n
                        lpBuffer += sizeof(SHORT);/ w1 w) p3 @* n: F
                } else {: N# @8 `& z. _, T5 o( h" J
                        *lpBuffer++ = (output>>8)^0x80;. j; ^4 g% e2 W7 c% G
                }. r/ W; K5 u( I% Q% m
0 x2 E+ e4 S5 ?
                if( nCcount < 0x0100 )
1 |! X  B: d- ]6 P" r+ o9 E; y6 X1 R                        pSoundBuf[nCcount++] = (SHORT)output;
6 a% z% I, W9 N- L# F
# x0 J2 ]2 G1 p4 k) d//                elapsedtime += cycle_rate;
# D/ R5 ^# h5 P! _* y6 t                elapsed_time += cycle_rate;: D" @/ m( T) h4 Z1 N  w+ l
        }
0 m: u/ S, _0 R! ?! `
& @3 {$ X: O2 K4 }% X1 a8 Y) @4 r( z#if        1
0 s6 p1 f3 e, q" ~9 R: i! d        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {. _0 A& `3 H5 i8 b; z5 n. U& k+ K- U
                elapsed_time = nes->cpu->GetTotalCycles();6 d0 G( s6 A8 k$ ?7 a$ e8 W
        }
6 L  q8 d. n4 ~3 _        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {4 j5 z. q3 n; ]! [7 u2 l# t4 ]
                elapsed_time = nes->cpu->GetTotalCycles();5 y1 y+ ]/ @  E# [+ T
        }
$ W! g2 ?4 k+ D#else8 a+ o' U6 @; ~3 r
        elapsed_time = nes->cpu->GetTotalCycles();5 r; B9 N$ |3 r! [. T
#endif
2 b' B0 R+ x# x% [. s}
! P0 i( w0 c5 G1 g1 L4 p4 W' o5 V5 t5 d( w  b3 s6 ]
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)  H3 V6 G7 G3 r* v' r) K# e
INT        APU::GetChannelFrequency( INT no )7 z! i" k& b" T+ ]% E5 p
{" g$ X7 E0 u) ]3 G' c" {$ b
        if( !m_bMute[0] )
' s# V3 m$ p7 X! x+ Y                return        0;
" V( I* }- r/ b7 F3 |/ m% V, o5 }! c. h* V- T/ [1 q. t
        // Internal
$ J, q- H3 {9 V+ y        if( no < 5 ) {6 [9 L6 \5 J' P: {! S
                return        m_bMute[no+1]?internal.GetFreq( no ):0;+ C* c, p8 x1 j$ t5 j- M
        }6 P! o! j) [$ _; _3 R
        // VRC6
3 E# c8 \. g% C& {' R        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {& \# K- m2 E; [1 P, E
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;; Q1 h( Q9 s' n& {: v
        }
3 l! h+ G$ M1 g7 Q6 n, a        // FDS& s& ?$ E) }5 }. }( @# b$ t0 K
        if( (exsound_select & 0x04) && no == 0x300 ) {
: X1 a: l+ _" U  Y3 ]) k; q                return        m_bMute[6]?fds.GetFreq( 0 ):0;
; \  @' l' {/ N) ~8 B0 g        }
! t: Y" c( Z3 p: {) J        // MMC5% X7 v5 q+ j# y2 L9 O1 o1 q
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
3 o5 O; |: e; n9 L4 l' v! Q                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
* B3 J. C: {5 J/ F        }
( a" ~; m2 e1 j" r* F        // N106
( ]% K, N; X7 z; x1 z4 ~        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
( `7 K  h4 `( G) A- L                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
6 z" V) k( Y4 ~2 |3 i) ~) p        }
% p  E8 _) {- o9 r5 K: [        // FME7
0 H; X/ s3 j4 f$ B        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {' u2 K5 D+ n$ L: d2 P$ \
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;( ^( `1 A/ F3 J* y; b
        }2 D* l  |: e$ S! o+ h
        // VRC7& n4 `3 N* A! R
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
; j- r- V* m" X6 U! c                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;9 F  v/ \- B! g8 E' V
        }/ W( \9 M# y6 W0 M! E
        return        0;
2 q/ m7 P  I2 i/ q: }  @}
9 n& X  }5 F, o9 {1 d# N2 T  Y! e1 b( t+ m) X: U/ d: Y7 a
// State Save/Load
7 T/ f. o, f$ G" K% n5 Wvoid        APU::SaveState( LPBYTE p )
; G3 Y$ S0 M; ?( s+ P% M, E- h{, p/ S* S1 _/ C0 X
#ifdef        _DEBUG
8 q/ m. a* d# W2 [- z$ s* {LPBYTE        pold = p;0 U+ d* U+ G% u4 B+ R
#endif: l; i0 w9 F* V' [$ M( N/ C
; e% R6 b, f. D: ]4 j7 q/ v& Q
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
' c# p8 U, F. `6 z  F# ]( m9 ^        QueueFlush();* x5 G$ ]" l" O' V! c

5 s2 h# C( L4 G6 E        internal.SaveState( p );* }0 M3 j7 u# x4 y( V
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding- i' ]) b& L& e) D+ J- L

/ @2 x' m7 m5 r: e, f        // VRC6
% r* k# Y4 f7 Q& U8 e' {+ ]        if( exsound_select & 0x01 ) {
+ F# M) t0 T( d  a- t* e                vrc6.SaveState( p );% J6 ]7 U! I1 U4 y
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
+ B+ k& j! l. j1 C/ d        }+ y, s$ @8 ]" Z4 r0 _
        // VRC7 (not support)
3 ]8 k; G9 _1 L3 }% Z        if( exsound_select & 0x02 ) {
2 `% c. a+ Z8 x+ i4 k                vrc7.SaveState( p );! `" Z; J: s& y7 `: E
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding0 i2 ?, m, [4 u) n
        }
. z! d+ O4 Y0 @. N" Z5 _6 X) B        // FDS
" e: y# v$ t- W/ `& L% y        if( exsound_select & 0x04 ) {/ H- x/ N: f* }+ B+ M  g
                fds.SaveState( p );
$ m* o- b4 W+ X                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
5 C: a% R$ v/ U/ I  C) o& U        }8 b. E% J0 S; f# i; i- m: v( K
        // MMC5) h( f0 ?* K# E; S+ ]
        if( exsound_select & 0x08 ) {
# ]2 X6 X3 ], Q" n2 B2 g9 _4 y                mmc5.SaveState( p );
( c& }8 e0 E+ U! C                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
9 o- t4 w6 U$ T% y$ T( G' \        }3 _5 s+ s/ X1 E% a% T
        // N106# h- ~6 b% x% t" _* ^& a
        if( exsound_select & 0x10 ) {! k. B* Y! s* w; T; ]
                n106.SaveState( p );
1 T- V# x, t: n( [) K- h0 O! w) J                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding2 Y# X0 f( z: @% K) f' G4 ^* S# P
        }1 C8 ]! d& ~& z  U/ B4 b
        // FME7' }1 Q) c/ @# |; n9 N0 y
        if( exsound_select & 0x20 ) {
3 T6 ]. T# ]/ C7 I2 V                fme7.SaveState( p );
( W, _$ G8 |5 E                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding* ^( L" ^* j& O# w0 M5 {; @9 t
        }
9 b8 @0 G# W. q+ Z. r
& B! _! C1 I4 _' }#ifdef        _DEBUG& P/ ]1 G) Y7 V- ~2 ~
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );& H5 {6 O8 [$ w7 a3 d* b: W9 i' b7 h
#endif1 h# b6 e3 Y7 b7 k4 C" O& f
}, _4 v; x+ E+ D6 I; M: u/ O! B: ?
" \8 X' j# s* o6 Z
void        APU::LoadState( LPBYTE p )0 q% q, t+ ^7 W
{
" `* F' t/ f8 s- e) C* Y4 _" P2 Z        // 帪娫幉傪摨婜偝偣傞堊偵徚偡7 H4 ^9 C& R* Y3 Y6 y3 h0 l, M
        QueueClear();
0 s' V" {3 N3 n4 L
9 ^# J1 r6 l9 O" d, y        internal.LoadState( p );% V  S0 Q' w  F3 i9 F' ~0 x
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
" H4 c& ?6 I" O% I
0 X/ K* t0 q5 E  b        // VRC6
3 `. S, H2 Q5 H: t3 o        if( exsound_select & 0x01 ) {+ s+ I# Q* i9 ]" V
                vrc6.LoadState( p );0 a* |2 d6 G. P7 e
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
4 e$ G" ?  H& B        }; _; M$ ~) s; Z& g7 G
        // VRC7 (not support)2 o8 ~& H6 Z" I/ ~& e
        if( exsound_select & 0x02 ) {
% }3 E4 w6 F4 Y4 H. J; y                vrc7.LoadState( p );
/ y+ O) l% t. x+ C                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding: p, K$ C: _; U
        }/ i6 q7 W3 {3 Q* V0 s
        // FDS
  z; N1 X: k9 a, z: [9 H        if( exsound_select & 0x04 ) {
  z5 L/ B6 S: i1 s7 k, l( @( l                fds.LoadState( p );, q9 {" h( X+ L# f# W* h& [% r
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding" A9 ~. z( X5 D; T4 y6 o
        }' f( |2 p! ?- P4 }2 K
        // MMC5
; w$ x# P# y2 ]' b0 W4 F& g        if( exsound_select & 0x08 ) {
8 v' G) D) v6 v) d3 t- v9 g                mmc5.LoadState( p );
: l. Z% _# ?: M4 U9 ~6 i                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
; I- \) b6 u! k& U  v        }
; e; K. L( n' m4 |) j& ^+ Q) g: {        // N1068 H& Q2 d0 c* }4 q  H' p
        if( exsound_select & 0x10 ) {
0 v$ Q$ [  S$ V3 i/ s                n106.LoadState( p );4 b8 s1 w+ ^* H& z
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
$ n& c& p! n7 a0 [  U& z1 |% }        }1 A" t2 X2 _1 ~* ?2 I
        // FME7' j0 q  m& i0 |7 y  r
        if( exsound_select & 0x20 ) {; k: N; P+ j6 L  w) p2 o) x1 i
                fme7.LoadState( p );
0 N8 S0 N+ {) k/ [" |                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
) u- F- d) D9 u; {3 |        }
0 o2 ]% m- A  q9 R( u0 s7 M}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
7 l. e& X+ k' O  |1 P; n可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
/ J. ^* P: l! k8 y( K6 F感激不尽~~

* c: E7 f$ P3 b5 A9 H6 P, U+ S- E' c恩 我對模擬器不是很有研究,+ H- F- T& t) y: Y9 P0 h3 _1 D
雖然要了解源碼內容,可能不是很困難,
! u. s6 C; x- l" \+ z- M+ ~" D不過還是要花時間,個人目前蠻忙碌的。" A6 i0 g: }3 y( Q6 _

& Y& R6 ~( D. B8 ]7 G/ |- \給你一個朋友的MSN,你可以跟他討論看看,  a- h; _1 O: H" v5 k+ `
他本身是程式設計師,也對FC模擬器很有興趣。. _" y4 f3 u9 E! C: f% _# r9 d% s

% |0 Y/ N* u# h4 tMSN我就PM到你的信箱了。1 n: c3 `7 N$ d' b; g: a  [; \! s
8 m' q7 Q' b, k$ o, V2 l
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
) |7 e  t4 A3 I5 H呵…… 谢过团长大人~~

. j9 B% i) F7 j/ r
6 j" @& [, \! I+ P哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 6 {3 F" `8 @+ {5 B6 t9 a, }, ?
团长的朋友都是神,那团长就是神的boss。

! O7 j2 p6 v1 H0 D哈 不敢當,我只是個平凡人,7 z6 U- I% Z" S( y8 x6 b, u3 |. r
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
" _% @; P, F7 ?& qZYH3 c' n: x6 X; y; h
QQ:414734306$ u- v7 _( `  j7 c8 L2 Y. `0 h. ^: V
Mail:zyh-01@126.com
" l* Y, V! d; w  @% f, |) u$ R6 \3 M- j2 \/ G5 T! Z& T
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
1 G% p; L  ^3 x5 Y0 H* u; @再次对团长大人和悠悠哥的无私帮助表示感谢~~

- O1 u: ~$ ?( E# G( _1 q不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-3 11:50 , Processed in 1.102539 second(s), 18 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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