EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
$ q1 c) F/ z* }% A5 i% P楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
9 k# `7 S7 }/ @' e9 N$ \这里有相应的模拟器源码,就当送给大侠了~~: c: E* B( }! p6 t; {# v0 i
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
& F" h. c' y; g能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
4 N3 A) g0 y0 C" w6 x; a# @0 l/ @( F楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~. L) n1 [/ X$ C& j) ~" E
这里有相应的模拟器源码,就当送给大侠 ...

7 N" E+ ?! D7 \  t0 y! R& ]$ Q: g聲音部分(Audoi Process Unit = APU):
4 T5 C9 j6 s7 w.\NES\APU.cpp  m( n" L7 b6 L! [2 ~7 Y
.\NES\APU.h
: G0 Q# G$ W) c  v" ]; M1 ^" j  P* x0 {( c% i

2 K2 @& K" D0 \8 `4 s影像處理部份(Picture Processing Unit = PPU):
$ A3 y, W: M  X# a  v.\NES\PPU.cpp7 a$ ]2 q) m# L: ~$ P8 P- x# g
.\NES\PPU.h
" Q! F1 G0 H# s6 @$ J5 g3 i( J% Z$ `
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
" ^; W2 C, i6 l(由于很多专用术语和算法机理都不明白,所以看不大懂……)
/ [" o4 q( T# s% }- z( i, y2 m& G//////////////////////////////////////////////////////////////////////////  C6 U" H7 v, R4 p1 k  L7 N8 m
//                                                                      //
, s# v# o: J# u$ p, ~, }//      NES APU core                                                    //
0 n+ F. ?/ X2 Z2 I//                                                           Norix      //
# ?7 o+ l( a. @( T* n. `1 D1 A//                                               written     2002/06/27 //" h" d) J$ w% u+ \
//                                               last modify ----/--/-- //
7 c* d4 R/ D  ?0 R0 m//////////////////////////////////////////////////////////////////////////
' U$ J! M) o! ]( n& }3 T' H& X: t#include "DebugOut.h". j' S) ~* R1 K. m4 e4 ~
#include "App.h"
* \6 \( H3 u* B) D0 k#include "Config.h"
; [  |: ~  b% p, `
3 @" l5 _* G5 s#include "nes.h"
1 |7 T5 M6 _! V7 L#include "mmu.h"
# j- i* B8 H0 c) p( K) y+ ?#include "cpu.h"
3 e  b- r4 e: u+ E' Y: D#include "ppu.h"
2 F2 `' F! X3 k#include "rom.h": ]& A/ p+ P9 {5 o; q# Q9 h
#include "apu.h", `! J1 `: a# o% _! h
4 ^" x2 D' s0 z) u& g. q
// Volume adjust2 @" x$ A  A6 G/ y0 D4 ~, {
// Internal sounds
5 E- ]* R* p1 f1 C7 Q# t; _' E3 x#define        RECTANGLE_VOL        (0x0F0)8 U/ d! s' {5 c* `  ?- a$ y% G8 {3 R
#define        TRIANGLE_VOL        (0x130)
: V  ?! u6 @6 K7 y1 p#define        NOISE_VOL        (0x0C0)
& i: q% i/ P2 P#define        DPCM_VOL        (0x0F0)
# G9 P% L/ Q# H' N1 T2 u// Extra sounds# M: d* K+ H6 _& E6 g' E1 I
#define        VRC6_VOL        (0x0F0)4 P' I$ ^! c2 ~# @+ f
#define        VRC7_VOL        (0x130)
5 C* c* D- Y6 ?' k' Y& p# @# _2 y8 H#define        FDS_VOL                (0x0F0)
. T( ]; G/ c4 l. `8 O#define        MMC5_VOL        (0x0F0)- m* ?- H: c) h% z' S3 U
#define        N106_VOL        (0x088)
: {0 Q4 ~1 w2 o- y: B$ T#define        FME7_VOL        (0x130)
) a7 T/ Q) V3 Z* I* l* b+ h- B
- N8 r+ [: [* Y  a2 Z8 ]APU::APU( NES* parent )1 |" @  Y0 v2 K6 I% S$ F) u
{
# }2 ^6 [" O& Y9 K        exsound_select = 0;- V" s6 l( w1 Z- ^' g1 D4 E

+ V/ f- k) i7 b+ @        nes = parent;2 ?9 z, z% R2 \9 e: U
        internal.SetParent( parent );
5 A5 `( E- v3 L  T0 O- @  I
1 g5 b" X( l0 z) M/ i& E        last_data = last_diff = 0;1 x+ @% G2 q8 B$ {: M5 e" C+ V

6 D- @+ X, e, K9 z4 o, O& }        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
# C' W$ C3 F  m$ R& p0 b! O" I4 G7 D2 b" m/ z  U* m- E+ M
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
: X+ b1 p2 W8 E0 d- E        ZEROMEMORY( &queue, sizeof(queue) );8 h$ e4 a' x7 V. c5 m. `2 K0 V% {
        ZEROMEMORY( &exqueue, sizeof(exqueue) );& {, p) \: l/ R$ w1 D2 O8 W$ T. S: h
! W& ?8 U" B6 }1 `
        for( INT i = 0; i < 16; i++ ) {2 n% z' i1 [( Z- @% T
                m_bMute = TRUE;
% N4 \1 R/ t1 l  S        }
- Y# O$ w. M6 B}, y0 M' N  Y. K* z# @; O+ W
6 \  a7 X! C5 A6 S+ N
APU::~APU(), d' X7 g" N3 J) B
{  H; ]& P0 p9 |( ^# {
}0 ?  c4 v5 X7 o5 `+ O2 O
) a; A$ n6 D& g: Y: g( u4 y3 g
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
# Y0 i0 i+ M1 c8 S" A{
* }1 d  t9 q9 i0 ?$ e/ W0 H1 Q        queue.data[queue.wrptr].time = writetime;
: a- B+ T* K/ Q- z+ D. D. I( J        queue.data[queue.wrptr].addr = addr;
2 c5 S" G' [4 h2 ]# L% \        queue.data[queue.wrptr].data = data;
) ]9 T2 f* ?' L/ r        queue.wrptr++;
, t- V6 g5 f' V4 P        queue.wrptr&=QUEUE_LENGTH-1;) y- u  a1 ^, s! O2 }3 ?0 G3 Z/ D
        if( queue.wrptr == queue.rdptr ) {: g. n0 |) L9 a  Y5 R, T& {3 a
                DEBUGOUT( "queue overflow.\n" );  N' ^- ~8 S+ @# }4 G
        }
0 A7 B0 ?. A7 l2 B4 W$ f+ u}
5 E& _0 x( R* q7 O9 A' h% o, Y7 m# p( I3 x: m$ H
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
: ^+ ]7 G: W: y{  n  Q, n; R2 P  _* x
        if( queue.wrptr == queue.rdptr ) {
; n+ f7 s  X6 \8 @                return        FALSE;
, h9 l3 ^+ I( X, \/ z/ h        }4 z" @  x/ J' [
        if( queue.data[queue.rdptr].time <= writetime ) {
0 l# X3 o1 V2 [9 v+ w) c# g$ d. F                ret = queue.data[queue.rdptr];
7 {5 V+ Y3 t' W) q9 L! ?0 T# A! i                queue.rdptr++;
6 M/ N7 R) x7 r5 q3 D: p. f$ X                queue.rdptr&=QUEUE_LENGTH-1;
/ t1 P. `0 s; K6 b) O                return        TRUE;
7 T" ~% z4 ]% B3 M        }+ D* H+ K2 t7 w# ~- E
        return        FALSE;, M  A# j  m; d! j1 e# F
}
" J9 e) A5 Z/ M+ e  ^- J9 k6 w, x2 [1 m- ~7 ]) [! i
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
+ T# B# A2 g  F( n" V{
6 n6 p2 v( x# x5 \( }8 m        exqueue.data[exqueue.wrptr].time = writetime;$ f! W2 {8 \4 E! e  M+ d+ q
        exqueue.data[exqueue.wrptr].addr = addr;
6 S6 S" [0 Q, c        exqueue.data[exqueue.wrptr].data = data;; b" p6 j! i& }3 ^# `/ w) u! Q# w/ t
        exqueue.wrptr++;2 o0 u6 a  X: x- f. j
        exqueue.wrptr&=QUEUE_LENGTH-1;
2 D8 n$ `6 d0 i9 n5 H" G        if( exqueue.wrptr == exqueue.rdptr ) {
* C1 ?/ z- R* B+ [& u" k                DEBUGOUT( "exqueue overflow.\n" );6 q  ?$ p4 o$ Q! ^& X3 m
        }4 c! B3 _5 _. t( X* J2 q% y
}4 R! R3 M& G- v2 y. `) U

6 V& h  \4 w& Z4 G+ qBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
4 l9 P, z! ^* i/ n{" l6 P; E5 u  ^
        if( exqueue.wrptr == exqueue.rdptr ) {
2 e" i9 W) K' M& Q  B2 y( q                return        FALSE;7 ?% |3 i9 Z, z9 |6 Q
        }  O. H6 T1 c' A; q5 e: D
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {# h8 g/ a- O5 l/ U4 j$ Y
                ret = exqueue.data[exqueue.rdptr];
1 c3 _" W* {" V1 j* b# a                exqueue.rdptr++;
( t, @: e0 l: P! q1 ]! |                exqueue.rdptr&=QUEUE_LENGTH-1;7 t: X$ _" r8 ]  O# e
                return        TRUE;3 b0 h0 u6 r' p  v6 x0 q
        }7 t0 I4 H: M2 [7 ?, y
        return        FALSE;2 i% ~4 L$ D, X# ^
}, N. f3 Y) v  R4 d  m, q$ Z

( E9 X0 ^) f, K; p+ F- v; Avoid        APU::QueueClear()* N# Q% K1 ?3 y6 O4 I
{6 j! R: }  [! f$ M5 y4 v/ c1 g+ w
        ZEROMEMORY( &queue, sizeof(queue) );
7 @3 |1 I- A3 _, v. X# p) `, s        ZEROMEMORY( &exqueue, sizeof(exqueue) );
" a' ^- C$ r( Z) e$ _, j5 ]1 [}# g2 Q/ T9 z2 R) J. C3 Z

" h2 O/ K/ {! n0 b) k! k5 Qvoid        APU::QueueFlush()
9 O2 T$ {  J  H( b3 y{4 V5 i7 _* I+ m( _" `
        while( queue.wrptr != queue.rdptr ) {2 b$ t& p1 X2 V
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
& L0 m* v0 S- k& }' s                queue.rdptr++;
) v( D8 ~/ M: O3 V5 N                queue.rdptr&=QUEUE_LENGTH-1;
1 u" J- V1 _3 X' ^% j        }
$ C4 F2 }, A) B$ q; V8 Z% }* x
        while( exqueue.wrptr != exqueue.rdptr ) {. O' v) z  Z) n" ^/ L: ~/ Z2 U% r) e
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );: |3 Z, h2 D$ x- {8 M
                exqueue.rdptr++;
/ s/ m5 V; p& R) |                exqueue.rdptr&=QUEUE_LENGTH-1;
, H' p- o% ?# X+ h) `        }
0 b* G5 |1 C* {5 a1 e+ Z1 P}4 M% t* }$ h1 E) X! t; h
/ X6 {& h# X, o9 G0 k# k# q
void        APU::SoundSetup()2 X5 A8 [6 M5 H  M& q8 I
{! w2 g+ j& R/ H! v) M& Z
        FLOAT        fClock = nes->nescfg->CpuClock;7 u8 O3 I, ^( L
        INT        nRate = (INT)Config.sound.nRate;
+ J" R0 k# n+ n# X        internal.Setup( fClock, nRate );* P( G0 e/ N. Y0 g- }
        vrc6.Setup( fClock, nRate );1 |; `# w, t9 V5 M$ D8 ~# Q! U
        vrc7.Setup( fClock, nRate );. P1 q  c" f/ y- `& Y
        mmc5.Setup( fClock, nRate );7 n- S* K( X1 K: f) B
        fds.Setup ( fClock, nRate );
1 P; B5 U& K9 j0 n        n106.Setup( fClock, nRate );0 g; ~8 a6 C7 v) |0 k% j
        fme7.Setup( fClock, nRate );
1 g  O, u& E' E9 N! H}; |% R- M& M' k# a" z
: a. @; ]5 _+ ?+ O3 c
void        APU::Reset()
  J- J0 p$ E( r" i- ~2 B6 E1 k{
6 @9 H  Z8 o1 u; S        ZEROMEMORY( &queue, sizeof(queue) );, L8 w  ]8 x8 d+ P/ i& @! o
        ZEROMEMORY( &exqueue, sizeof(exqueue) );- B9 V; J9 F) u) ^: G! Z! r4 ~
) w- B9 i, n0 p9 a( y7 N
        elapsed_time = 0;
% x4 F3 x, Q, ^
0 I4 ~% X7 e$ _  ^  Q2 x; y) c        FLOAT        fClock = nes->nescfg->CpuClock;
' g, T0 v. y5 K' g% ]2 j, P  J+ s+ A- ~        INT        nRate = (INT)Config.sound.nRate;3 O3 n4 @2 ]# X$ b
        internal.Reset( fClock, nRate );
$ \0 _6 E4 j# H0 L$ C$ a        vrc6.Reset( fClock, nRate );
5 Z: T+ H$ m1 [$ y        vrc7.Reset( fClock, nRate );
5 ^4 H9 h8 h5 p        mmc5.Reset( fClock, nRate );; M- p/ K5 C. f( \. |& F7 [
        fds.Reset ( fClock, nRate );
6 K0 L- J+ m) B7 Y) v5 i        n106.Reset( fClock, nRate );
! f5 x% h' N6 B9 j        fme7.Reset( fClock, nRate );+ k7 f1 N. R, {( y( A/ b' }

% z1 P7 [& s2 o5 s6 t- v$ v        SoundSetup();
. R) E1 A4 g( @' B}/ K3 Q$ E$ A  y6 |2 Y" t( ~

7 x  W! y- a+ V1 S$ @  lvoid        APU::SelectExSound( BYTE data )
* m2 t- H" g  Q& C% A4 z. B{
4 S7 ~# V: G) w- d" K( B        exsound_select = data;
* l2 A0 x2 m& @1 d+ F4 R- x}( v7 J7 m/ z  R3 H7 Y
. q/ X* L; o) G( q! [/ ~1 L0 W
BYTE        APU::Read( WORD addr ): E  a4 {9 S( j8 b" x5 z; o
{  T2 V- X, i, P- t) C4 K/ m
        return        internal.SyncRead( addr );
& u+ C0 `5 a' o+ m}
1 Y1 |) |% T- y0 g1 \  o8 Z: X% c: J/ f8 J3 P9 t8 C" l
void        APU::Write( WORD addr, BYTE data )6 w9 C1 b/ [, {3 Y  Y& o& w
{
: D: T1 i" M' }9 v        // $4018偼VirtuaNES屌桳億乕僩
' f5 T; ^8 A9 Q        if( addr >= 0x4000 && addr <= 0x401F ) {7 b, `0 h1 C7 S5 U6 @
                internal.SyncWrite( addr, data );
) S1 y8 a+ I" }( `                SetQueue( nes->cpu->GetTotalCycles(), addr, data );9 f! I0 l: d8 M3 O
        }" [3 L! ~) n* i; _/ X( `6 a3 o
}. o& X8 k6 u; X

- H$ q! T/ k# a, oBYTE        APU::ExRead( WORD addr )! J3 t/ u2 a" {6 o
{
* p, o9 ]/ C# @2 s3 y1 _5 uBYTE        data = 0;
+ y  Y7 r; c1 {( j- S4 {
' v4 T& R; E6 w  {6 o  K        if( exsound_select & 0x10 ) {) ?3 o% L) c6 T: C
                if( addr == 0x4800 ) {
5 a5 t6 R/ _5 h                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
' Z3 y/ P3 C- B9 Q( W                }
0 b. B8 \. h/ f/ X' H        }
6 t1 |& i& A4 K0 C        if( exsound_select & 0x04 ) {
% C: J' T8 D0 z2 Q8 S5 f                if( addr >= 0x4040 && addr < 0x4100 ) {2 V2 ]1 C# i" \: @+ @3 Z. _
                        data = fds.SyncRead( addr );. d! k- u. u1 o) Z- g3 k
                }
- F4 u% c4 g, ~        }
5 {% |) y; U1 I  B- }3 y        if( exsound_select & 0x08 ) {2 B8 W/ m8 @' r% v5 J$ a! ~
                if( addr >= 0x5000 && addr <= 0x5015 ) {
& w/ G0 ^: y- y+ W. h: R                        data = mmc5.SyncRead( addr );
! h* h# I, r: j/ E! e7 i                }
4 x( s+ t" m& d  |% D        }. C0 J! |& ^1 G
  P( C' w0 c: w+ k" n* u
        return        data;
! R5 e4 P1 |' s}/ u: b1 o, M+ T

# n5 h: W, j) }1 ?$ p+ Ivoid        APU::ExWrite( WORD addr, BYTE data )- h% O( K4 S2 Q0 y; f9 \1 j
{6 c+ {% @- H+ L, D2 u4 t- h
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
; Z: U1 b- l/ Y3 t4 i9 }& s% \2 {3 _
& _' B% R2 g: E$ S% D        if( exsound_select & 0x04 ) {
7 C" C2 p4 {5 V) O3 F+ P                if( addr >= 0x4040 && addr < 0x4100 ) {! v3 m! e3 \- b9 ^
                        fds.SyncWrite( addr, data );
1 e0 t  ^) C, @                }! N0 J) ~. {$ F
        }; {  M2 B# a  N2 }( y0 C- j4 s( {0 V1 C
1 \- M( C! Y% n+ P8 {9 V* |& E+ G
        if( exsound_select & 0x08 ) {
9 X& r- Z$ B! s% m: }8 @                if( addr >= 0x5000 && addr <= 0x5015 ) {! j0 F7 t5 Y3 k- `% c
                        mmc5.SyncWrite( addr, data );& {2 ^' T# a4 ~/ u! Q1 i) ]7 ~
                }
* b# ]' G' V4 ^( [        }9 V/ F. y, j' W. @  P
}
* C# i) E7 D) U( O4 ~1 X+ J0 u; Y
* U# {- x$ L! K9 X) n' Qvoid        APU::Sync()8 E$ h7 Y, l( o6 r
{2 w* r! y( c; |9 u; N6 N
}
# |; q; `) w- W; U1 ]) D) D6 r
( V: R' j# R% S, j' n2 \void        APU::SyncDPCM( INT cycles )1 m' P" h- T. @- P
{7 h1 L) ~% z( X+ F' `. _
        internal.Sync( cycles );9 R; I/ A0 p" j$ P! \( u

# d5 ]) n" p: C( h) u  H        if( exsound_select & 0x04 ) {
- t' F- M! @$ i# }/ ]+ o& e                fds.Sync( cycles );
& P( a: _" R; q7 I; G7 l$ P7 J        }$ b5 V& e& @6 k& C
        if( exsound_select & 0x08 ) {
4 E5 c$ G0 g' `. A                mmc5.Sync( cycles );  s: b: q, ?* i. T
        }
5 l. J+ r4 N+ F) }' b+ J  ~: M6 U" Y}0 Y% e) N% l! h, v, ]3 D( j4 e' c

* R, O' k9 s) t3 \  m5 i; Qvoid        APU::WriteProcess( WORD addr, BYTE data )6 |5 E( ?1 r7 Z2 N- ~
{
8 L$ q2 `& y0 O# N# r6 E        // $4018偼VirtuaNES屌桳億乕僩
6 j) J7 B* C  B  W$ j7 ^& [        if( addr >= 0x4000 && addr <= 0x401F ) {3 p  O" A1 m& }) }5 `
                internal.Write( addr, data );
3 D- a9 q" x( V, v$ ]3 H* Q        }+ s6 M8 n; {0 D. H$ E* R
}* R5 H# A, V5 e! l+ Y+ T
* F! `2 r, ~! V5 }* a6 a5 |7 X: t& w8 S
void        APU::WriteExProcess( WORD addr, BYTE data )+ C  J: h( e" b' M+ F( F. Z
{
, t1 R% i/ x$ @        if( exsound_select & 0x01 ) {
' b# z* [, h$ h+ x, E6 m9 n                vrc6.Write( addr, data );& o  M) E: F4 ?: c
        }0 j1 R% A3 z+ U/ E) |
        if( exsound_select & 0x02 ) {
, n2 ]3 H  U. |" Y* H                vrc7.Write( addr, data );- L. m4 u7 N( c% i3 @. x; a
        }
, }; p6 T4 s3 p% g        if( exsound_select & 0x04 ) {+ M1 D. l( A% l5 j1 e& m1 Q  q
                fds.Write( addr, data );* W: Z$ c5 Q0 M% K+ ?0 Z
        }
/ h5 m6 F' [9 V( f6 c        if( exsound_select & 0x08 ) {
2 A: |  e; \7 [7 u+ i+ c- V' U) r                mmc5.Write( addr, data );
5 ~/ Y6 f; Q) P( `2 b! Q        }
: h$ h* d9 c4 ^2 O" s: c7 m8 |        if( exsound_select & 0x10 ) {
% r$ m* R+ Q, T                if( addr == 0x0000 ) {" ?& p0 s, N, {2 l
                        BYTE        dummy = n106.Read( addr );: w" ?9 w' A7 a/ {' G
                } else {
/ V2 ?& }; y/ H; }" W- z                        n106.Write( addr, data );, N" J. b' U9 _2 o& m
                }5 ^7 E4 J7 a! R5 K5 n7 |
        }1 }; w* @# ^$ f9 W
        if( exsound_select & 0x20 ) {
! j* W, `' {0 }7 Z$ Z+ X                fme7.Write( addr, data );
/ Q) n/ j, S- x" m$ j1 ?( B        }# \) V1 {$ q. n' J. X. `, ^
}
4 G& H( w3 {4 h  X' k! C' o% k
9 r) a- U, `5 @% Bvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
% Y$ h. A& _4 a{
8 @  W5 K7 D0 E* ]INT        nBits = Config.sound.nBits;4 R, ]: G0 }# t, ]
DWORD        dwLength = dwSize / (nBits/8);3 G8 p! R% e4 g/ S+ ^& o8 T
INT        output;1 [% O, p0 j- J# b' W. ?
QUEUEDATA q;8 @2 W% g6 H3 u' [: Z
DWORD        writetime;
0 j- _3 C8 F; m+ @7 L0 W8 R  A+ \0 W$ p- B' W* g' l( b
LPSHORT        pSoundBuf = m_SoundBuffer;
% p4 d3 Y$ b$ F8 h& b% JINT        nCcount = 0;
1 z3 h, f. p9 m7 I9 m" W, z
& {7 X/ {+ @/ z- G$ hINT        nFilterType = Config.sound.nFilterType;
- ?3 p9 V6 X9 d5 `- L/ b. J. N3 J, e+ k9 x! s
        if( !Config.sound.bEnable ) {
' x' a1 |$ j! s. X                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );$ q# `1 v- t' C+ e; _# H
                return;
7 B( h, Z6 y( Q. n        }0 ]8 f! X; d0 w
; _8 A6 @6 a# M$ L7 F
        // Volume setup
; E7 {- @/ O5 ?        //  0:Master
# k6 Y: A9 x" v. K: ~* ^# @( o        //  1:Rectangle 1
2 R  }9 l# y: \9 n        //  2:Rectangle 2
: R+ I8 J" i$ l$ b" V$ s/ R        //  3:Triangle/ C) G, V. y. \- x2 \  Z
        //  4:Noise
* @% U& Y" D6 n        //  5:DPCM
. n! t/ h; U% i8 D        //  6:VRC6
7 h/ n1 x+ b$ L: L' e# H" t& l        //  7:VRC73 ~, h* p! `; O) _' r
        //  8:FDS1 {; f+ j) P  f6 T
        //  9:MMC5& b, m& t* e1 P9 @8 ?2 s  U
        // 10:N1067 P6 |4 c5 u: S( j# d  \
        // 11:FME79 N5 x, L# t- W
        INT        vol[24];) e  a  \1 R; `; f' ?  x: }, Q
        BOOL*        bMute = m_bMute;
* j' i; ?- h& l7 l! V( i        SHORT*        nVolume = Config.sound.nVolume;4 V. G! d  z4 W
4 E# k" }1 @6 P7 U8 k! A* @3 ]
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;! T4 w6 U; d! l& u1 ?& a: T! q% r# \

, W' e% B8 J( _        // Internal
4 |' I" b7 |, L  A$ l6 ]5 s        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;9 K; J! x+ `. f
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;' W/ _, j- V% o% q- x; a8 E, C! ~" M
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
' L$ z8 P) \4 v3 x( Q5 }( F        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
. @; K) \5 \4 Q4 [& V, Q        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;( |+ }( c  q( L

8 E  \+ Q9 m5 e% z  E/ z) g        // VRC62 S# v- S: i1 ~# i. p5 o
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;) Z* U  D2 c$ A
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;2 u9 M9 e# f2 ?2 P5 T& O3 [% h# s
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
+ p$ g- Q4 ~- F( n$ ?$ n: T/ Y  [7 x
        // VRC7- b( r) B0 Q3 \! W7 L" H3 }! t0 Z
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
+ W2 Y: Z2 {0 C' E
) n6 i, _) [3 ]- m4 s$ f3 V        // FDS$ \& _6 r& R0 @0 w( I5 S
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;& G3 Z% @! j3 p4 i5 q1 A9 o

/ [* ]9 Y+ h& j0 Z* O2 S4 b        // MMC5- e3 j6 q0 c5 p3 |1 r! T
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
! x6 d# D% z) s        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
; v" b/ }* F2 W- T& r        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;2 h3 _0 {$ V& _$ |# {$ V
; n1 B/ f3 ?: O. _2 T& i
        // N106
2 @$ I8 e! U5 }3 Q        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;8 I: w. K4 k- u$ s' q7 f
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
' W9 S9 M! d; ?" _, U! k' m        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;, w% n8 |+ K3 l* ^7 m0 N' q
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;" L3 R+ C5 S3 L5 Q
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
( L. k. ]. s$ ?- E6 R3 X2 @        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
2 l4 E2 G/ F7 Y8 a        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;) Q# U6 w* j9 w! H6 M1 ?$ L( U1 p1 q9 M
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
' m, \/ J* w. _) [5 T3 b
1 T3 c- _* ?# F9 v& y  ~& X        // FME7
; u0 F" X! n3 z5 b' W  f- n6 M        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;+ [' R1 ^, x4 ^' n
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
5 v6 R  K. W4 [+ c/ ]) G        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;" V$ \& e* X3 {! i& N, C
9 r( l9 X8 T! C9 l& C
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;+ \5 D% p/ n+ }9 J
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;( |1 ^) y: L/ W  x1 q
* t  C& v9 E% r" x0 W" c  \
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
/ I5 W0 c) E9 f0 H. K6 D( m/ H/ R. k        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
( S6 I7 J) j: H: r2 ^. y' |                QueueFlush();
: B7 d1 p: k1 i3 p: ]" a2 ~        }* G$ _- b6 b3 X; [# H! t, p: o
4 v1 k/ S+ y3 v+ K& M$ q
        while( dwLength-- ) {
! S4 H6 C7 j, l; T. C( {                writetime = (DWORD)elapsed_time;/ t8 b: |1 Y  {3 z
" J" N3 Q( p- x# [% ?- f
                while( GetQueue( writetime, q ) ) {
7 I# y) ]2 \0 B                        WriteProcess( q.addr, q.data );
* L! m9 d0 C6 W9 m' k/ K                }
; j& M$ f$ I. X4 K
9 P0 F* E( ^- \3 [9 `$ J. i; D3 J* z                while( GetExQueue( writetime, q ) ) {9 f" b1 x. z3 `
                        WriteExProcess( q.addr, q.data );4 n# o9 `6 Z  N7 W5 d  t
                }
' z, A) m( j9 w2 `, [4 S7 y6 b; E9 y# Y8 C3 s4 ?* p
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME72 z4 y+ v" {7 k, S; d
                output = 0;, n, `6 N+ T+ T1 N3 |( {) F
                output += internal.Process( 0 )*vol[0];( M* c2 b! ^4 S) a
                output += internal.Process( 1 )*vol[1];
5 q- \! o' p/ ~5 Z  |- |                output += internal.Process( 2 )*vol[2];
" ~/ ?  R: f" W2 H' t# G' L                output += internal.Process( 3 )*vol[3];
" ^( x: y/ c( ^6 P" @  u' W                output += internal.Process( 4 )*vol[4];. @  @, @0 P9 b
& _. n, p7 U$ [& T. O8 m1 s
                if( exsound_select & 0x01 ) {1 o! b( I2 I  u2 d: n0 v
                        output += vrc6.Process( 0 )*vol[5];
0 b, o6 F4 u9 ]" m0 Q' G8 ^                        output += vrc6.Process( 1 )*vol[6];6 G! e) v8 D4 A( {
                        output += vrc6.Process( 2 )*vol[7];" _, Y+ L" H) ?7 _2 q* j
                }
0 j  y: O- ]% n. m( v+ S                if( exsound_select & 0x02 ) {2 Y6 Z5 w0 k! y, w/ b1 v  n* Z5 n
                        output += vrc7.Process( 0 )*vol[8];, [; v- n8 p/ T8 u; n# f
                }2 D5 i3 n. d( J3 P- u& a! @  C
                if( exsound_select & 0x04 ) {
. H2 L9 p$ A( E                        output += fds.Process( 0 )*vol[9];7 b6 W& |' k9 x' I- h# b: X
                }5 Q4 _3 U/ |+ P6 Q0 H4 W' T
                if( exsound_select & 0x08 ) {
* \1 a1 o( g% R' [                        output += mmc5.Process( 0 )*vol[10];
( ^1 v3 |+ h( y. b                        output += mmc5.Process( 1 )*vol[11];6 g# f: ], l( X- S% }- Z8 G9 |
                        output += mmc5.Process( 2 )*vol[12];! s9 `& \9 Z0 Z' q; O- {% k5 p& _
                }
4 M1 a8 Y) Y% g9 b. r, Q7 a                if( exsound_select & 0x10 ) {  N0 D4 F. N  D. E( a5 }+ Y7 C
                        output += n106.Process( 0 )*vol[13];4 M! A- |# L% Q; l
                        output += n106.Process( 1 )*vol[14];
) r4 ]. z% }9 h" C* _* s                        output += n106.Process( 2 )*vol[15];
! ^2 q0 F: v! D, `2 e. [% ]                        output += n106.Process( 3 )*vol[16];- z9 D! ~# {/ ~' _
                        output += n106.Process( 4 )*vol[17];
& J5 S; ^; b  l( E8 M; [! f8 |                        output += n106.Process( 5 )*vol[18];
  f/ F1 Q6 |% J6 ?3 x7 e  A                        output += n106.Process( 6 )*vol[19];3 Y; J  i# u! I
                        output += n106.Process( 7 )*vol[20];0 f% }$ y! U5 W2 b! G' j
                }: L0 M2 C1 U8 Y4 a
                if( exsound_select & 0x20 ) {7 ]0 f4 X5 s; ]& S7 ?" j
                        fme7.Process( 3 );        // Envelope & Noise
8 W" j9 D, B. A" G                        output += fme7.Process( 0 )*vol[21];
( {. c" c5 }! t, p                        output += fme7.Process( 1 )*vol[22];; C* l. z, c) ^, z; f7 ^( G4 N
                        output += fme7.Process( 2 )*vol[23];
( M* e) X+ o% e9 X                }: Q  ?# q0 }; f+ u; |" Z
' Y+ c" V' l6 j2 i! ~" L
                output >>= 8;1 X! |# T9 U0 T) D( r
" N3 m! s* X- E
                if( nFilterType == 1 ) {1 A) c, v2 p) I( x6 S
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
4 m2 j4 G& ^% }  D# l                        output = (lowpass_filter[0]+output)/2;
5 c7 V% b- ?, M& L! L7 i0 C4 U  Y; n                        lowpass_filter[0] = output;
5 {2 v# H7 B  R# O" n                } else if( nFilterType == 2 ) {* C" e4 n0 ~4 V; ]
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)- c4 ~5 {- H+ I: w3 r
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
# W. t6 Q% G! c0 y# M" s2 J                        lowpass_filter[1] = lowpass_filter[0];0 i5 q5 B6 N- N! h, E( X* _
                        lowpass_filter[0] = output;1 P( t$ }. n/ Q6 L' l8 b9 J
                } else if( nFilterType == 3 ) {. |% q' \5 M; u
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)- h$ J6 f0 S6 S  t
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;" h3 |) \- r$ s5 \; R( U
                        lowpass_filter[2] = lowpass_filter[1];1 O+ ?: [( J" z" }+ o, G) B
                        lowpass_filter[1] = lowpass_filter[0];' a  v1 H" J: a3 Q, W! _
                        lowpass_filter[0] = output;
: ~& p1 G& \' h7 v% \. t, j/ M                } else if( nFilterType == 4 ) {
5 F4 i+ t4 q; T                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
  _+ s- z7 ~7 t/ V! C                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;2 u* |4 `: |, M) }# Q" N- X
                        lowpass_filter[1] = lowpass_filter[0];! j: L; P& K7 M( l' w: b
                        lowpass_filter[0] = output;8 N5 R+ Y) V7 I
                }
7 \$ w7 _* F/ z' W% W3 E4 V% |
- W! `+ d3 j- m- I, u5 i3 D#if        0$ [0 T/ m4 u! X- @4 {6 [2 g
                // DC惉暘偺僇僢僩5 C& R% v: m+ [+ Q$ V$ l
                {
# a  p3 k6 K9 `/ Z' x3 T! @                static double ave = 0.0, max=0.0, min=0.0;7 ^$ o4 K/ ?. k$ S! L8 k! U6 }6 A+ d' M
                double delta;$ m1 W$ a7 |% d
                delta = (max-min)/32768.0;
. N! A: K# Z- M! r& \                max -= delta;
8 V  V7 U- S: o                min += delta;( V" `* n0 C( S. N) S7 U# H1 A
                if( output > max ) max = output;
% |: u6 Z& @: b3 K/ p3 }                if( output < min ) min = output;
2 l* [, a% s/ F  h8 y$ C                ave -= ave/1024.0;
. [8 e0 [7 |- A" {3 L                ave += (max+min)/2048.0;
1 u& j: C$ k2 |3 ^) T                output -= (INT)ave;
+ f0 [$ Z- d1 o( n+ K, g                }
4 Z6 e; _+ }6 s* E% h$ E#endif
5 ]* e6 \& ?# m4 p8 b#if        17 u& t: P0 L* _4 o) Z
                // DC惉暘偺僇僢僩(HPF TEST)0 ^4 Z! ?( }1 Y4 z+ N8 Y4 P
                {
5 \3 M  K. s2 B, {& Q& [6 A//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
! n/ Q. s  y$ q: F7 q6 B                static        double        cutofftemp = (2.0*3.141592653579*40.0);. H% b; F" t' H0 P2 Q. Y( `
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
% S! j( K, B, H) {1 _) z                static        double        tmp = 0.0;
9 x$ w( Z' a. L2 \                double        in, out;
7 g6 W" Y; ]+ v2 O" `. z, ]
# C0 w5 X. k, O: x1 C4 d                in = (double)output;5 i8 R/ y% q  |
                out = (in - tmp);3 ?* J9 P8 H  N7 R
                tmp = tmp + cutoff * out;3 _' ?5 Z" r' Z- y2 |0 @) @

/ G+ b6 L# s( U& x  j4 M4 O                output = (INT)out;& ^8 D9 K- V1 u! N4 m
                }
- d2 d. i* _3 p' C  t$ `#endif
2 x5 `/ R/ z! Q# q! K#if        00 U; |( v( K8 H7 M+ `9 G7 s
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
+ ]% v8 W# h0 Y/ H                {
5 F8 K& R" ]# x, L0 Y! m                INT        diff = abs(output-last_data);
7 w8 S3 Q& q* [1 x9 c' l5 z                if( diff > 0x4000 ) {
& T; G* _! f& o/ s. ]& p$ c- C                        output /= 4;+ F. q1 z3 F: s+ F& b; p  D
                } else
" `& w. ^. E: M* U+ c                if( diff > 0x3000 ) {
3 J: P2 ]& X& i4 w2 X; W- N                        output /= 3;, I6 ?2 L/ M' N: Q: g/ }* K7 r2 L
                } else
- W- G; J1 m: p+ \5 H% G: ^                if( diff > 0x2000 ) {) _0 r& w0 z! T, w6 p
                        output /= 2;
1 y1 E) O5 E' I/ X# [2 \                }( ]: u, D. _2 T2 |  \6 ]
                last_data = output;
( q" [4 t2 j, }+ n                }
" N+ N) C) `" p% e% v#endif8 N& L  H1 E- x6 A) r( B, i/ Z
                // Limit
% `" g2 P& q8 I! i                if( output > 0x7FFF ) {* O4 T$ [1 X" i2 {% d/ y
                        output = 0x7FFF;, d7 O) i4 ?$ j; E4 r  B
                } else if( output < -0x8000 ) {
0 K# H  X: I. n+ t0 q                        output = -0x8000;
4 k; K0 `5 g0 `8 [0 V3 X                }2 ~4 b( y' _* H- h5 B5 d

! L; Z5 b' U3 H& F* Z5 b                if( nBits != 8 ) {* Z1 s! z  I' P5 G# \+ s# w
                        *(SHORT*)lpBuffer = (SHORT)output;
- p' K* n" @+ j! A                        lpBuffer += sizeof(SHORT);/ Q9 C  j" ]( J1 d+ ~
                } else {. q- i  F' h: F  c" H
                        *lpBuffer++ = (output>>8)^0x80;1 o0 ?, L2 M3 T$ W
                }
4 x+ W: ~& ]" J) N* C
7 E* r/ u, U6 d0 k' ~" C                if( nCcount < 0x0100 )
' W$ A7 y: C1 J# u1 V& z                        pSoundBuf[nCcount++] = (SHORT)output;4 A) f3 c5 R* J2 F3 P) Q

$ M4 a# {# w; G6 V//                elapsedtime += cycle_rate;7 \( l* x' [6 U) b# o
                elapsed_time += cycle_rate;+ x) m+ B! a% p4 F
        }. M& |4 _- @5 e7 |5 y  m. x

4 i" T# z3 C: |1 _#if        1
0 l/ a6 T. A8 E        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
% ]/ S: J- p9 `* s5 x, e9 Z1 }                elapsed_time = nes->cpu->GetTotalCycles();% R. ~8 ?) Y" s& v
        }' R& ?  o+ H$ w1 u, E: z
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {$ U: x7 j5 p$ R9 l4 D! v
                elapsed_time = nes->cpu->GetTotalCycles();
5 Y- J) p: S' W8 a% _        }5 t& _% K/ a  f8 y2 r
#else7 _( z" G4 P. z9 M3 i$ Z5 K- g
        elapsed_time = nes->cpu->GetTotalCycles();8 S; C' C& O7 N5 y+ f5 n' ]
#endif
1 G: |8 s% s% S2 B8 `# F}
, U7 W- m5 d' P* z6 ]  w3 q
2 q2 `4 O7 j9 q( Q8 o// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)' L9 w4 j& [9 N7 ?+ J0 a  q
INT        APU::GetChannelFrequency( INT no ). j; l4 J7 g- T; n; s" o
{/ A" L6 T# e0 O- c" d7 d4 Z4 Z3 a
        if( !m_bMute[0] )8 }3 U2 d  w0 }! V2 O; M) ?' z
                return        0;: A" L1 r/ A. v0 r- h% k: g; B; H" z

( j3 r) `  j$ I7 r2 p- [        // Internal
" I% Z. P6 i* W- y% ~' ]        if( no < 5 ) {: @3 }! `8 Z. i4 T' p* _4 v& w
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
( Q. J( F; \' p& N0 k        }, u  o( F/ }; v1 N9 i
        // VRC6
! g6 }8 |/ ^/ o' |: l+ j        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
" D2 d8 m& J* `( m! Z                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
4 L4 G  D3 n4 e' j8 }# O+ A        }% l' l" O# Y1 H+ [6 g# |
        // FDS
, D+ M8 d  g& y5 R9 M8 i        if( (exsound_select & 0x04) && no == 0x300 ) {
! K) h- M% A4 W2 q                return        m_bMute[6]?fds.GetFreq( 0 ):0;5 u$ c: _& u4 s$ f# S
        }" b& d3 Z: i$ V: u
        // MMC5; k/ M. l" Y" \( a- e; H
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
' p- ^# P1 ^6 o9 d4 y                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;% k' Q2 Q* r, O& |' w
        }
" N2 v( H3 q4 C1 b& F        // N106; ?! [+ A; z1 C+ \: S
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {: e* ]7 k, j  {
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
/ z- `, i: v7 H  G8 F1 V        }7 q$ @6 j8 c& ]3 q( l7 ?
        // FME70 P2 V, s8 W9 t2 m( e$ D
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
7 e7 u  V* e. j3 O  g) u2 p                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
# H& V- B9 x8 m- _# \  l! s        }4 E& E  K7 b! q+ a0 B
        // VRC7" G. d# k! O8 z- |7 h! x: F
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
5 E5 W3 I" f5 t* G( e5 X( f8 Z/ m  k                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
$ i% }) A. o7 h        }# G) s4 v3 C, j6 v( Y% `
        return        0;! }3 t( f" q, f! x6 _$ s% v
}
  j* B) J& ?5 q
5 p! ]) m& d0 R, h% v// State Save/Load% T- ^/ v8 N/ Q+ |
void        APU::SaveState( LPBYTE p )' a) a4 R8 n5 I5 @$ F  d7 Q2 Y
{
2 M1 V5 N8 I- A1 j7 J#ifdef        _DEBUG; ^9 p7 N7 [. U" I% O5 |- W3 F6 o7 s
LPBYTE        pold = p;
4 O1 H/ w7 }. c* N( c#endif+ A: |2 @4 i; t0 J4 j2 r9 M
+ M& T5 ]! B# {7 `* u
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞2 u9 I5 `( ?# H$ @
        QueueFlush();$ H) _+ h! _- z* U+ E$ y9 ]7 w
" u. y5 D( m/ ]" ]5 S  S
        internal.SaveState( p );
* ]9 q9 |8 b# a- i) }( S$ [        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
  ~8 P1 w! u9 }5 a2 w6 }* y& y5 _. ~8 K# G5 R
        // VRC6/ v2 Y% t" W  h% Q) X) _2 @7 E# ~: u
        if( exsound_select & 0x01 ) {) R4 |$ e1 e/ u4 |+ p
                vrc6.SaveState( p );
( t% w$ G- c" w  e& ]% a                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
* ~; O- P" W" T$ l& f5 t0 ?& V        }7 [1 x2 J' m2 Y& _9 p
        // VRC7 (not support)
) e/ A1 D, D! e. b) i- G) ~) [$ L# T        if( exsound_select & 0x02 ) {
7 A1 D$ z3 C3 `5 s7 ?                vrc7.SaveState( p );
7 k# Y" p& \6 G" F/ o2 y                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding2 |: {8 j0 Y/ r; v$ }0 b
        }
3 a9 l) a1 u$ _/ j3 m5 Q        // FDS
: J& Y  W4 A& ]# j% D9 ?; }        if( exsound_select & 0x04 ) {
8 i! f) Z9 {- [( T& G                fds.SaveState( p );
& @2 y( G! Z" Q4 I                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding' X+ a2 Y1 d! J8 P) J3 `. R
        }/ l4 W1 x( x9 I# b  v: W! A! h
        // MMC5
7 E( \% B$ g5 |7 F" A! T        if( exsound_select & 0x08 ) {
$ q8 @) t) W  K- q( w8 X$ \                mmc5.SaveState( p );
. [1 m2 [+ ^+ a2 }3 d; t! l                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
/ P& s7 c8 V1 C        }
5 q/ n- A/ e3 K* A& z  v5 w        // N106
) x) n/ D, s3 f. ?1 C' h% O8 G        if( exsound_select & 0x10 ) {  ]9 J0 {. G, ]" V
                n106.SaveState( p );
( F1 j. K7 S1 G' \1 y                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
$ k; D, G$ J# C4 Z4 s        }
. A. r9 T; S7 M        // FME7' U0 V6 o; o/ k- \& @7 ^
        if( exsound_select & 0x20 ) {2 H- S( F0 z/ S' {6 @( a
                fme7.SaveState( p );& C+ h4 `) Q' y% ~9 @, h
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
' F. \7 V# v+ r* t4 h1 A/ H        }# `  k5 C# S5 X/ o% ~

% }# l; x  X9 P) F  ]#ifdef        _DEBUG7 g9 c( U& u% A( e; ~1 `/ Y7 M3 L
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );$ h6 y# M, s7 S8 |) |, e; S* s
#endif: y- D# r+ @, x
}( D5 S9 W) l+ R! c
/ Y/ O3 J  n2 a. k# e
void        APU::LoadState( LPBYTE p )- f; o" c: {6 r) v4 ^$ C
{0 v' u3 O7 w6 l9 K3 r# d8 c
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
4 z& Q" _  Q1 g# W/ }        QueueClear();
) z  w4 v- i  `6 a
" _& u% A3 L% A        internal.LoadState( p );
* p+ A. d0 Y7 w& J        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding: U( o+ p( y& X7 l# i# m% U3 j

5 ~" d3 T6 Z/ l3 U: x9 f+ o8 \( o        // VRC6* b$ B3 f; Y( G" B% G) J8 z; R( R
        if( exsound_select & 0x01 ) {% k, |" \9 M0 k! r) ?/ I6 @
                vrc6.LoadState( p );2 W) V- J% C9 D
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding" j  o) g+ B" A) r
        }6 \' [) D7 @8 M# i
        // VRC7 (not support)
% q! v# x# s. [8 Q! D. y! L  y        if( exsound_select & 0x02 ) {
* N5 e' x% F* c/ ~4 R8 {                vrc7.LoadState( p );" ]9 z/ s6 ]7 d% f1 O( k& E, V6 g
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
* c  f0 l" N% d* F" E7 Q9 f$ x        }+ {! D2 v/ Q" v) N1 P
        // FDS; \* ~5 N( e2 c+ V, `
        if( exsound_select & 0x04 ) {$ w0 l% [; T) D- C6 i0 o
                fds.LoadState( p );& w0 W# E9 _3 L7 ?
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding0 n' M* s! [; G9 V1 ]
        }/ }* j8 ^1 q% K% W0 e$ }
        // MMC5# b3 B- f( T1 F3 N" [7 @
        if( exsound_select & 0x08 ) {
4 P% l5 X$ N9 W8 N3 a) S                mmc5.LoadState( p );
3 E6 k" Q+ ?/ I7 j7 U$ W5 U+ v  k                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding( d! ~0 g8 a0 c+ [
        }
6 c) n9 _4 l) c( e        // N1061 g# G" ^8 T8 n
        if( exsound_select & 0x10 ) {
2 z# M$ Z/ X0 w( v" k& H                n106.LoadState( p );
& q% Q0 I1 z% X; h                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
4 W7 @- u2 B: c* {  X3 n3 u        }- S1 w4 R0 b; B3 S$ N% n6 I
        // FME7# ~3 t2 ?* e1 g; a1 F# K
        if( exsound_select & 0x20 ) {
8 b+ D$ M, _( W% u" y, `. n: C$ m                fme7.LoadState( p );0 w1 e: y$ F% U
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding2 l% x' K! @$ m8 r
        }
# J" Y2 u2 Q2 j}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
5 l3 g7 d! H% @3 @5 C可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
" u8 u0 ]# ^# b7 ]& a4 ~, s感激不尽~~

. S* C3 v+ A; l) d: m7 |: h$ X恩 我對模擬器不是很有研究,, ]$ m! L# c) Q0 X
雖然要了解源碼內容,可能不是很困難,6 d" r/ x+ z- S( h/ }9 |
不過還是要花時間,個人目前蠻忙碌的。
0 P) C2 t) U' j- o% M! G! r* C: g7 z7 e* b. Y# T. I# u1 Y) N' S2 ]
給你一個朋友的MSN,你可以跟他討論看看,1 w% c9 D6 F3 P  }8 B
他本身是程式設計師,也對FC模擬器很有興趣。
! L" X6 }  {. _8 z0 B0 l% y. m
% x# X1 e( G+ |. X! a$ |MSN我就PM到你的信箱了。+ e% F0 N" }$ X7 n
# {! G% v8 R# @/ D5 |: w
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 # |5 w6 q1 r/ B- l* r+ y1 Z
呵…… 谢过团长大人~~

# T4 b! h! o. Y( Z) R! O8 m' B( M! J3 w
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
' \$ y5 N1 N) M% i9 _* I团长的朋友都是神,那团长就是神的boss。

" A9 l: h4 `! V) d哈 不敢當,我只是個平凡人,
1 ~7 s; l( B- |: d要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙/ c& [  j. m  F' E0 f; [* @1 E# V
ZYH7 B. Z* _* {) |, m6 _* Q# y
QQ:414734306/ t! u' o8 i1 v5 R3 L
Mail:zyh-01@126.com
# v# ^) F9 O/ ^9 _4 p
% L9 x9 D& q  `9 u! N$ M他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
- ]! i# Z! Z8 Q: m2 a再次对团长大人和悠悠哥的无私帮助表示感谢~~

! I+ y, U4 g" H! Z: D+ Y不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-11-29 16:48 , Processed in 1.199219 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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