EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?
5 [8 Z3 _/ }3 h) K1 ^+ R( h; V, r1 C2 DPS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
$ _( |+ b4 D! E2 u4 n楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~. O$ D5 _. C# N+ k' J, b
这里有相应的模拟器源码,就当送给大侠了~~
* M6 \/ Q& l8 W1 H2 ihttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 & U9 V8 H! q" p/ P3 r! A
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
( @+ ~" u5 a8 h3 @# P* [5 ^7 [楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~* Y9 {6 x) {! u  \8 e
这里有相应的模拟器源码,就当送给大侠 ...
, x# p9 n: A/ h5 Z
聲音部分(Audoi Process Unit = APU):
2 P. G' a, v- ]' z4 f6 L.\NES\APU.cpp
" ]8 `1 w8 A" S; f.\NES\APU.h' q: `( B% j# |2 j0 {7 b( F
1 k( J; h2 H& y$ L8 b! o% L9 B

6 T: b' _0 G6 C  t. z影像處理部份(Picture Processing Unit = PPU):
9 S# i, Q1 w( ~& X.\NES\PPU.cpp- v- y6 u0 f- m4 o% D" Q
.\NES\PPU.h$ d* d/ g0 |8 p  k) H
# Z- \& }  I1 _7 Y' }$ I7 A
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:' j, c( J3 u+ {  m% P0 u
(由于很多专用术语和算法机理都不明白,所以看不大懂……)) w1 }5 J9 ^' ]. z
//////////////////////////////////////////////////////////////////////////
/ i/ _3 e& Z; V: v$ l2 ?  i//                                                                      //
- i/ A9 H( l6 Z8 N. l! B/ [% }9 k$ a//      NES APU core                                                    //7 `  N& N) g( _, A6 A! [
//                                                           Norix      //
9 h' {4 b5 O8 }( u7 j2 x//                                               written     2002/06/27 //
( X! ]+ y7 I0 p" b) D//                                               last modify ----/--/-- //: k& D+ W% ^5 \8 ?) D  U
//////////////////////////////////////////////////////////////////////////! F  Z  U3 k- _1 R7 u9 K3 F: ?
#include "DebugOut.h"
5 o* e$ }. d$ [; }! a: W$ Z/ u#include "App.h"
3 g' ~1 g7 i% y3 [! Y#include "Config.h", O1 T  l1 f1 x

2 g1 g. J" ?/ X3 E& u" m# l' v#include "nes.h"
: a5 d7 z1 T. m6 r9 j#include "mmu.h"
: M* ^/ R- l5 Q- o+ x$ z#include "cpu.h"
% o- j5 r& ~3 N' v1 [#include "ppu.h"- _% u' u% E( A! S
#include "rom.h"+ ]+ o' J0 W1 @* i& Z. a" a0 l
#include "apu.h"
1 Z  N" S* G) U8 h5 b2 x) ^9 h' }1 ~3 H- D+ J+ S# I3 `3 O
// Volume adjust8 O! y% I: N; @! x% ^( f
// Internal sounds
) F' ?4 W; M) O3 G0 H$ d0 f1 [#define        RECTANGLE_VOL        (0x0F0)+ m5 L* t, H( }/ _  l
#define        TRIANGLE_VOL        (0x130)8 b. \2 ]3 {  [0 ?9 D1 z
#define        NOISE_VOL        (0x0C0)/ S! R# b% i) Q( \4 _
#define        DPCM_VOL        (0x0F0)
0 h; W8 b! F) G* }# c) n5 b/ ^// Extra sounds9 u, y) v1 y6 }& w
#define        VRC6_VOL        (0x0F0)
  K3 R% L! E  m' g6 \/ c* m#define        VRC7_VOL        (0x130)
0 _& v. v: a' t. @5 J#define        FDS_VOL                (0x0F0)
& p. \9 w  o4 T5 |+ z1 O! ]#define        MMC5_VOL        (0x0F0)! g! R" C6 `5 G3 s, V
#define        N106_VOL        (0x088)
- ]' s0 `0 C; ^( `2 X3 ?8 O% s" n#define        FME7_VOL        (0x130)
/ P6 Z+ B( |/ L6 E4 p0 }
) `8 X' k  E$ R, `/ bAPU::APU( NES* parent )
* d5 m2 x6 {4 h4 e; l" @: L. {{& Q* C$ u: _" w$ o/ P* s
        exsound_select = 0;
& }1 n$ p) e6 p- G
- v9 R2 E$ ]7 X3 [' Q  A8 R        nes = parent;
- c6 T: G1 l( u+ F0 v/ n) {/ T" P        internal.SetParent( parent );  Q% {* J' n$ D* D1 S

" X% R: D6 t1 z& a9 c7 R- d- w5 O        last_data = last_diff = 0;
. q  f+ K: H  C& a" I' [3 ?, F, v- Z+ V
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );; U, @* ]- w6 h3 ?

% p1 W8 W% F! [: m  x7 j& c        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );) K7 R' |& o2 w5 H- @; N6 k0 u- T8 [
        ZEROMEMORY( &queue, sizeof(queue) );+ p' Q' {; [  r6 B, B: C: c) `
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
5 W5 z4 l, r" x. U+ g- X" }) w+ F+ k3 l1 s: E
        for( INT i = 0; i < 16; i++ ) {
. w% D6 \& Z% `+ f$ i% y                m_bMute = TRUE;! \  m. N0 z2 z, G; j" W$ O  X0 ^
        }+ x2 h& D# Y3 \3 [7 h; v
}
8 r3 c% {% h: X2 ?, y" w* L( {) i, ?: X1 w* N& A
APU::~APU()+ R8 H/ I/ R4 W- E- u/ h7 M
{$ q  H$ V) J0 o3 a6 W! a0 ?
}
6 Z' _" l& ^4 Y. d% W2 D) E  c! b/ B8 ]) X3 m, T4 o
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
5 Z  t0 F6 E& a" I{
5 I, a1 M2 n0 S8 c. ?1 ?        queue.data[queue.wrptr].time = writetime;) B% D2 p# H7 W8 _" Q; Q- a
        queue.data[queue.wrptr].addr = addr;
5 v0 Q, U* ?3 B) [" N        queue.data[queue.wrptr].data = data;6 Z9 x, U6 p: ~5 m
        queue.wrptr++;
- R- R2 Y' h. W. N$ e. N        queue.wrptr&=QUEUE_LENGTH-1;, K3 T! B; O6 `6 v0 z8 m
        if( queue.wrptr == queue.rdptr ) {
/ n2 t3 k" a; h! _$ f                DEBUGOUT( "queue overflow.\n" );% G! y$ Z$ Z9 f( @1 a% j9 v8 i. s
        }7 I  F" V! U% g$ n* X
}# A+ L3 F, g+ ^5 b$ I0 ~7 h& M
0 ]/ d7 c" W8 F4 A
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
3 r7 h# Q- [( g. V5 M0 e  K{4 E* M9 A- P% o$ @& U
        if( queue.wrptr == queue.rdptr ) {
) R2 F( I8 }6 Q: D2 T6 o                return        FALSE;
5 z) |2 V) N: f) i- X        }
& v( ]6 t6 ~9 ~        if( queue.data[queue.rdptr].time <= writetime ) {) @' l' p) h" s7 x  _% [
                ret = queue.data[queue.rdptr];; @& x" F% s8 z4 i  @0 o
                queue.rdptr++;
# K! i! @6 A" R0 ]                queue.rdptr&=QUEUE_LENGTH-1;5 H" `& h2 Z- f* p7 k6 a3 E! d
                return        TRUE;! s5 n+ i  h8 h  O
        }
9 H8 e5 Y% t3 j# Q) Z4 M        return        FALSE;
$ s" C# V, t2 U8 K6 I6 E' ?1 a}
, U4 m5 M  F. R/ S5 Z/ y8 U: V0 x2 x0 D: D: G0 W
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )3 L/ R9 T: |; \1 ]5 P9 A% N9 v
{8 V9 K# V/ J. }& k" Z
        exqueue.data[exqueue.wrptr].time = writetime;1 Z) X7 I3 \4 @8 [# ^# W% E; U
        exqueue.data[exqueue.wrptr].addr = addr;$ _, y# S: H4 I3 G, k  O$ O  s
        exqueue.data[exqueue.wrptr].data = data;
# ~0 N* v& J5 a/ F& |        exqueue.wrptr++;$ p7 r/ r" L2 w8 f( b, m; }
        exqueue.wrptr&=QUEUE_LENGTH-1;
; h  c4 F+ n& h        if( exqueue.wrptr == exqueue.rdptr ) {
* ^9 r8 [2 J" ]. Z* k' D' `9 ]                DEBUGOUT( "exqueue overflow.\n" );3 n1 a; e, z4 s8 U- F
        }
* S6 F- S( q! Y# h6 r: G}3 k9 ^' l+ q6 O  [
7 I2 x$ E. O& S  v; Q' v! T
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
* g8 i: l6 s# {  z{6 Y7 \5 S! f. C( \
        if( exqueue.wrptr == exqueue.rdptr ) {
0 Z& B5 W9 D6 b/ l' v                return        FALSE;  W5 I" O" X3 a( g+ p8 v! W
        }
& a! L; A) T8 r! r        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
5 H5 k  G& p( C& ~                ret = exqueue.data[exqueue.rdptr];
# _: Y8 t8 d% N6 t9 k                exqueue.rdptr++;
: l4 T7 `, S5 u" s                exqueue.rdptr&=QUEUE_LENGTH-1;
# A% p$ I, o; \                return        TRUE;
$ t# j% J% @9 L" X1 q5 i$ n        }9 |4 p6 B9 h7 D; T8 v* G( ?
        return        FALSE;1 M4 b& F0 U' b" t9 a% T
}# G% n( r3 R% B  p0 }7 Q7 e
! a0 g0 r7 s' v0 r( a
void        APU::QueueClear()
* C. r9 Y/ V0 {4 F# b! o{; E/ }3 F* |, @& B
        ZEROMEMORY( &queue, sizeof(queue) );, C3 ~3 M. m6 {" y' T) ^3 g
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
! c5 n/ E  q1 r  m* Z}
0 x- e( p, K# ]  X' h9 f0 q& F0 K3 b9 c% d( T
void        APU::QueueFlush()5 _3 W; `' a; j0 c% j
{! E" N  M3 o5 t" W- l' h
        while( queue.wrptr != queue.rdptr ) {/ b/ `4 j8 S* A0 t8 M  o/ ~+ C: [
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );: X; V( ~8 R& J" L8 O  J
                queue.rdptr++;
- s) i8 n* a7 A" S                queue.rdptr&=QUEUE_LENGTH-1;* }6 G; W9 z4 S$ h0 B/ G
        }+ w2 F" A+ r+ G0 o2 ]
4 X+ T, U% m1 z* S# O
        while( exqueue.wrptr != exqueue.rdptr ) {
( e* T- i+ F  K& `# ?! }7 \0 Q                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
% u4 o  C" L! X  o9 g0 A                exqueue.rdptr++;
5 e* a. D9 L: ~                exqueue.rdptr&=QUEUE_LENGTH-1;
1 u! z! B& ^; R* @        }) r( {0 p7 p( Q
}
+ c7 F3 O& D7 A. L; t6 l& _2 t
, K6 W( B7 l7 lvoid        APU::SoundSetup()
5 g( J3 R  P7 C; M( ]' {7 A# g{4 r, D. Y% z5 K
        FLOAT        fClock = nes->nescfg->CpuClock;' T; l; `5 k5 o2 d
        INT        nRate = (INT)Config.sound.nRate;
8 c" H8 C1 u- p( S9 W; a0 p        internal.Setup( fClock, nRate );
! L& v( Y! Q/ y5 w        vrc6.Setup( fClock, nRate );% o$ }" f) X, B0 R. Y- r
        vrc7.Setup( fClock, nRate );
: f, F) z  u( K! W# l2 f        mmc5.Setup( fClock, nRate );; z3 Z5 t: ~& m% e! Y! r
        fds.Setup ( fClock, nRate );+ e5 J  C, A) z  x. g# C
        n106.Setup( fClock, nRate );
2 c* N+ N$ Y: U' W% ]        fme7.Setup( fClock, nRate );+ N8 H: @5 b4 A) T3 l7 `! i( [* n
}* f0 {, J* d* L" a/ d6 i& [2 [5 ~' x
' _! Q- B& {+ I2 e  L, m
void        APU::Reset()
0 V  s, Y# k! |  X{) h& ?1 w. O3 y& r
        ZEROMEMORY( &queue, sizeof(queue) );
9 I; x$ W$ t$ Z; C9 b9 u2 G6 {/ D        ZEROMEMORY( &exqueue, sizeof(exqueue) );
. k7 Q% I5 P$ j2 _2 M% V" Y2 }. T1 j, G% x  h  k  c; G
        elapsed_time = 0;
. A7 H+ E/ u4 }- N
, G/ h6 M' A& M8 i5 |/ H, K6 j        FLOAT        fClock = nes->nescfg->CpuClock;
- w5 u" h* x% q' H6 r- H7 I. @        INT        nRate = (INT)Config.sound.nRate;
. j4 e; H4 B/ r6 X0 J8 M3 r; Z        internal.Reset( fClock, nRate );& P  Y! W( Q) t8 i# a
        vrc6.Reset( fClock, nRate );
2 E1 V! V4 a0 l/ s% \* B0 r# g) `5 j        vrc7.Reset( fClock, nRate );( r+ U% ~; ?1 w( E; q0 L1 n
        mmc5.Reset( fClock, nRate );
% ^. Q; Y) m2 A  G4 ]        fds.Reset ( fClock, nRate );
$ y1 |3 [* i1 q! s1 T! L        n106.Reset( fClock, nRate );# y; e$ |, s* ]: W! B- q
        fme7.Reset( fClock, nRate );
; C; k* T& }/ t; E
0 _! q0 P9 U, ?& L5 ~        SoundSetup();
1 E5 g- y/ j/ e, Y% k1 M  V}1 B4 e7 I6 g+ a
, ~; Z, e" D; p( N5 w3 \6 b
void        APU::SelectExSound( BYTE data )1 l# r( {2 K6 S+ L2 S% n
{: E0 ?3 l, h  @: r! w0 D% V! v. d
        exsound_select = data;
5 r5 l" V  M, N( D8 P}  B9 ]" b- {1 P9 `  l- i$ G- @

$ K  \; M5 a7 n4 I4 Y2 d! E; Z3 h( r1 [0 _BYTE        APU::Read( WORD addr )' j5 k, t0 P0 \7 {6 T/ g
{
% D* A5 v1 T! s        return        internal.SyncRead( addr );
$ A% y* `# u4 Z$ _7 O* \) T* A}
) _2 M2 B0 Z: N$ t* z0 N6 k1 K0 V7 m6 i
void        APU::Write( WORD addr, BYTE data )+ W" e, m2 t4 @+ H6 C0 j6 W) j
{- M( P5 F6 J+ _1 I1 a9 E
        // $4018偼VirtuaNES屌桳億乕僩
4 S0 R7 v; J4 V, X        if( addr >= 0x4000 && addr <= 0x401F ) {
8 a1 j' y& z5 n                internal.SyncWrite( addr, data );
3 Y; X: U5 y+ P! E/ s( E$ D' o5 Y% l# H                SetQueue( nes->cpu->GetTotalCycles(), addr, data );; @5 a" a3 J! H) R2 p# A
        }+ |/ U. Q; I: e; L
}5 I$ n2 F: X: ~( L
6 w" s( ?! T7 X
BYTE        APU::ExRead( WORD addr )3 s% X9 b1 |& ]' Q: m. _$ _4 s) e
{
" k9 k7 E% R; I( aBYTE        data = 0;
/ A! e/ ^5 q2 t. \0 j: P+ v! i2 L8 N! g, ?
        if( exsound_select & 0x10 ) {
/ G0 c6 e! H- W4 N# n                if( addr == 0x4800 ) {
" E6 [' H  \4 P8 R# J/ _                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
, ?4 X8 H0 g/ C, c' s+ L' f) \                }: [( E) n3 F  t. B. e3 K
        }' d; z/ t* |0 w) O( ~3 t5 [$ y
        if( exsound_select & 0x04 ) {" C; U! _1 P: J( m
                if( addr >= 0x4040 && addr < 0x4100 ) {8 `  V2 j$ c8 @, R: r
                        data = fds.SyncRead( addr );) j8 k# |5 ]1 k$ Y# q! T  d& S2 h+ K
                }8 z( m. o1 p3 p/ ]' u
        }: o! W. ]0 `0 V: i0 K4 C; x) Z! s
        if( exsound_select & 0x08 ) {6 F" A! ]) p* l. Z( X# M
                if( addr >= 0x5000 && addr <= 0x5015 ) {
; U' d2 @" \  M' }/ z8 Y                        data = mmc5.SyncRead( addr );. ?* `' n+ H4 A# f5 j
                }( Z- q9 l% r+ X3 z8 E3 ]# u
        }; L- h" e7 _8 E1 _

. c# S" L' r0 {4 V* u        return        data;
& a1 I! t) m. [4 I+ h& U& j# }}
' w3 O% J/ [) {' d/ p( S1 u2 b2 F7 d
void        APU::ExWrite( WORD addr, BYTE data ); X2 h. D! k/ f5 v2 |; E
{
' `% e* ?& |" k' X- O        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
0 g4 c! l# e/ o  C  {" r$ p  E6 H8 e$ J# u" y; H; \
        if( exsound_select & 0x04 ) {# @4 [- D0 P/ r# ]
                if( addr >= 0x4040 && addr < 0x4100 ) {7 `9 U# |6 n2 q" c! Q' }
                        fds.SyncWrite( addr, data );
+ f+ [& e8 f5 V, N                }
' J+ F. N, y0 \5 z        }
) V, S4 a& q, s: ^" f! [6 i7 @  K( a6 D+ c3 C
        if( exsound_select & 0x08 ) {0 A9 j$ U* \1 v: `. a
                if( addr >= 0x5000 && addr <= 0x5015 ) {. v0 K9 v, P8 w  W8 I
                        mmc5.SyncWrite( addr, data );  F( w/ C- L# w$ ~: _! C
                }
/ ~, N) t- N7 e- ]8 t6 o1 Q        }
$ g( c% g7 p+ @# h; k- g}
) U  B, I' L' B* \. }1 L
( I1 ^2 v' }9 Q: X* t, avoid        APU::Sync(); {4 Q+ ~( J! x1 C! \- k6 k
{
; V* @7 u3 @' v; K: T2 l}3 z1 v, T/ w# Y1 X
0 D3 r2 g/ e9 _) y0 F/ Q  b+ G
void        APU::SyncDPCM( INT cycles )& d  i% o7 L) F0 E
{
6 |& T" ^5 H" U) A- A( A        internal.Sync( cycles );
3 m, m7 R- E0 V5 a. _( @, X( K* u% C4 m& _7 V  M7 Z! n/ ~0 i
        if( exsound_select & 0x04 ) {
2 R" L/ R# {. s- f. ^: c& [                fds.Sync( cycles );
  {/ G) w* `4 L( j        }, n8 z9 L2 @  g$ v1 S, _7 k' {8 _
        if( exsound_select & 0x08 ) {3 p) B8 i* g; S4 v# T5 D
                mmc5.Sync( cycles );' m4 M* _& G% g: t: V7 [
        }
5 V" f. H- }. K; p: L}* _5 u  Z6 Y0 ?' p6 B% K" {

% |6 q0 r9 H8 X* M. P+ Z/ @void        APU::WriteProcess( WORD addr, BYTE data )1 J# \1 b; _2 m5 x8 z
{0 E* K) E$ S  N" k" S8 \! p( E$ n
        // $4018偼VirtuaNES屌桳億乕僩
. d: n5 I  c$ m3 t% Y& A: t        if( addr >= 0x4000 && addr <= 0x401F ) {
4 [$ F6 i: U2 c0 x                internal.Write( addr, data );
; o5 U/ Q' Y$ s* u        }% d$ M5 e5 q4 w: j, g# H4 d
}
6 R+ D: e2 M: ]+ h& H* M3 ^
- C, A6 T- y( Cvoid        APU::WriteExProcess( WORD addr, BYTE data )
' L0 r1 V% p" W3 }{
, p2 J% D8 L* h' H* i% R; F( Q. F        if( exsound_select & 0x01 ) {
9 l: n1 A3 H+ H; _4 i8 E                vrc6.Write( addr, data );
1 @8 s5 a0 D% D7 o% A6 j' @: O        }
# A6 F2 h8 R% {- i/ v* w3 V        if( exsound_select & 0x02 ) {4 ~/ R, z6 t/ P$ b- ]* E
                vrc7.Write( addr, data );
" l$ c% Q, r  N1 l* _2 z* y        }
. Y; f$ I' E. C4 V, j& ?        if( exsound_select & 0x04 ) {9 c" `% \$ H& j
                fds.Write( addr, data );  J. |  c1 U; {9 e. w
        }
. e/ v* _% Z* A/ v( D8 N        if( exsound_select & 0x08 ) {
2 Z, e+ f; C/ p( s  z' ]                mmc5.Write( addr, data );" z- k+ l6 T' y9 ^7 d
        }$ O( d0 i: g& c8 F1 t
        if( exsound_select & 0x10 ) {$ [( F9 x/ H! S# r3 t( \9 y
                if( addr == 0x0000 ) {
" z5 y& U2 k- W* |6 @                        BYTE        dummy = n106.Read( addr );4 [7 _3 _0 g! y2 W/ O
                } else {
: C1 A) r+ J. S0 g8 y8 S4 h: [8 V                        n106.Write( addr, data );& G# `3 j: L4 `. b0 `& k( F; a9 p9 m
                }
; D2 d6 O" d1 T3 V- B3 g        }5 L( H4 n0 X$ k" B0 p
        if( exsound_select & 0x20 ) {
; X. Q$ v1 n4 `2 f! a  w+ q                fme7.Write( addr, data );' e$ C. {4 i1 }/ \' V
        }- X8 l" Q3 d0 J3 }, f; r- @
}7 I: r  r; l( X

3 g" L+ Q0 d% Q' o& @5 Wvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )+ V( B9 C! _1 ^
{( S: z; R9 {0 M
INT        nBits = Config.sound.nBits;
9 F# c3 w: y# B  f6 Z% \, eDWORD        dwLength = dwSize / (nBits/8);3 j: F' w! ]) w& h/ e
INT        output;
' \, v5 D5 A8 }QUEUEDATA q;
5 n9 I- ?; u/ O" p# I7 PDWORD        writetime;
7 l/ K: ]) v# {! ^# N( z3 @5 m
1 z! F6 o5 l' c  N0 qLPSHORT        pSoundBuf = m_SoundBuffer;! a0 t, e1 J: m, n* O2 U% W) f8 u8 w
INT        nCcount = 0;
! D9 t8 k  |8 @6 f1 F$ M2 b
7 M' [, H' i1 G5 C% o( g7 E/ h5 UINT        nFilterType = Config.sound.nFilterType;0 j. u' c. r: E' B0 H6 k3 ?

* X8 T; F& i/ ]8 h; \" l% d9 v5 @2 x) G        if( !Config.sound.bEnable ) {
! d' r, t* T$ L6 O) }2 M                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
# {! w/ C! o& ?; t* V                return;
, G8 q9 P) I. C4 x8 `1 T& V4 I) P9 {0 d: o        }0 B  |6 U0 `+ [$ T+ Z/ ~
5 k: f8 Q: r+ b% w7 @% A
        // Volume setup
2 R7 u* P1 a0 D: W        //  0:Master
% y1 s" S! c* R* l5 w/ e$ M9 c( A2 d        //  1:Rectangle 1
& ~$ s0 W3 R1 d/ a        //  2:Rectangle 2
/ o0 f7 N+ S  O+ Q9 `4 e        //  3:Triangle; h" Z- A3 }# m7 z
        //  4:Noise
5 O. ]6 ^0 C' |/ }        //  5:DPCM/ S) o# u/ O! W/ ~, q7 I
        //  6:VRC6
6 U" J' W" H# G9 v        //  7:VRC7
, d" \, k5 v. P/ Y        //  8:FDS; Q# {$ x& }7 k
        //  9:MMC5& A" d) i7 U3 N; H( L
        // 10:N106
! Z7 i) c. ?1 Q: n9 ^# J        // 11:FME76 ?- v& [0 b7 z3 @. c# ?; ~
        INT        vol[24];  g& C1 T& g9 e1 q4 y! ?( ^
        BOOL*        bMute = m_bMute;
. p3 [: J% B  o% ~: l/ j        SHORT*        nVolume = Config.sound.nVolume;9 }: U5 z' c+ L  @7 p
, @! ^2 G/ ~- x9 }: y
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
" F6 ]- j* ^1 ^6 o6 T4 C3 F; \# e* \* R+ H# j7 y
        // Internal/ j# ?- p& i9 w# u* {
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
/ G( _' s3 q6 w7 h8 s" Z; L6 t        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
, d9 ~: `, G% {% U, j        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
( \* u- }3 S7 A+ X8 @- u0 T        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
) n7 ]6 R" Q! v        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;+ e0 K' l) L9 R7 E& w

6 K" H( c" E' E) I  z9 `        // VRC6
/ L  N+ s; F1 T5 N* G  x# s        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
! O. ]2 S2 s6 O" D) n  I8 D" j* `5 c        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
& _4 `% ^; T4 H        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
8 b$ w# e3 N* A# `7 S+ K" G8 v" g! p
        // VRC7
4 S' A5 H8 m& U+ g        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
6 q. I6 Q% t$ I2 e
! I$ g; S5 Z" H4 m/ P( d        // FDS! n, ~9 h5 m+ b  X+ H
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;  |0 B, f& n) U, e% F0 m
7 b2 E; S" A! [
        // MMC5# o8 e8 U4 q% h4 `; [' \7 f
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
/ ^0 r) q( g  [8 t: V5 E        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;6 i, K% k7 |) l$ R2 B* M
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
" b1 b' N: U1 ~8 `5 z: K$ e$ Y2 W6 R2 u2 h2 F  H. _
        // N1066 m1 d2 J9 p3 S  F
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 {+ }  |7 a7 Y- x. i2 j4 C
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 ]5 `' i. A+ E
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;' @3 e7 C+ ]5 z5 s+ A) V) Y
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;( j# k7 M1 Y) G
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
2 e$ ?4 T6 w# ~3 ~        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;* U* ?+ o6 f8 M2 |4 ^# o" R5 I
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
8 ~; u: G+ y+ V( |5 k9 ?' y9 O/ U        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
6 M) O4 Q: N2 _, ^1 J- [  S( w- G# i: H6 e) n5 Z
        // FME72 L- q2 S! U3 A( C  a* X& r: Z' X9 T
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
7 e/ s! f8 s( p/ w5 L% P% Q' C+ g        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;4 l) h( a) q3 @5 d% X5 u+ D  y( e. `
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
, z# f) t$ c' L2 e; R3 F) n4 G3 s
, f" b! T9 }$ a* d1 b//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
7 C- M: M, U- h7 z" s        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
- @8 F9 C& B: M1 J, @) H
; U5 B  y2 Z/ o8 U( U* v" x) c0 e        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
: o* d& U# [/ s( }  b        if( elapsed_time > nes->cpu->GetTotalCycles() ) {9 T6 v! i1 R9 v; k4 B
                QueueFlush();
: G; a5 c( s, k* C9 X) D        }
  G) N2 {6 V+ ?% j3 o+ }* M% I4 c# d( A0 [5 B( ~
        while( dwLength-- ) {
' i0 H! ^- c$ D/ b3 M. S8 X                writetime = (DWORD)elapsed_time;
# I/ K1 L- m1 f( V9 L1 t9 v# J/ w: N  e+ ~* Q9 n
                while( GetQueue( writetime, q ) ) {
# l* d5 Z9 c( I- x3 ]! Y$ V                        WriteProcess( q.addr, q.data );
0 v1 W# ?5 k- a, ], A                }
5 t" O6 u$ [# e" G8 F( J, l, I4 }" y
                while( GetExQueue( writetime, q ) ) {
. ?+ N# E4 A# R2 p5 K' P                        WriteExProcess( q.addr, q.data );- i3 i& A6 r* p, G8 }- u' }
                }
" d* z! x) M; M; @
# [# _3 L0 {( j+ \9 S                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7! a. j, B: O- R6 F2 i; }
                output = 0;3 S$ S  k+ z, c& a2 c" |/ X
                output += internal.Process( 0 )*vol[0];; A: t" \8 s3 n( E) M' f2 b
                output += internal.Process( 1 )*vol[1];" ?' ~  C; n! \- q" N" ?
                output += internal.Process( 2 )*vol[2];" c+ W7 z& j. W0 B
                output += internal.Process( 3 )*vol[3];
, G- }, {6 ^. K                output += internal.Process( 4 )*vol[4];, N. y' d! b4 d: {4 U

7 H; u: h; ~; B) O; n" u2 }                if( exsound_select & 0x01 ) {  h- A0 c2 A$ _' Q0 t$ O
                        output += vrc6.Process( 0 )*vol[5];
$ V. u" p/ `8 ?% y: v: C- a( ]                        output += vrc6.Process( 1 )*vol[6];
/ _. Q" Q3 R! q' J! u! k                        output += vrc6.Process( 2 )*vol[7];/ J7 |$ g: \0 S
                }; e* {! w5 j. l7 B2 I
                if( exsound_select & 0x02 ) {( D9 T0 V3 R7 R1 f+ t
                        output += vrc7.Process( 0 )*vol[8];
( ]" M3 u$ k* p- C                }8 `! C2 P( ]* K( p4 f9 T( X
                if( exsound_select & 0x04 ) {
# f8 S  y( g; E  V' q                        output += fds.Process( 0 )*vol[9];
, W2 E7 K4 W3 \/ v6 O3 s! t- ^                }5 A# X2 k$ B- A1 g; z, m
                if( exsound_select & 0x08 ) {0 L, ?+ P# @" s7 @3 v
                        output += mmc5.Process( 0 )*vol[10];
- \' {: A  Z- f/ o/ j1 |  V  j# B                        output += mmc5.Process( 1 )*vol[11];* o' D3 Y$ p7 L* z# R+ r. {
                        output += mmc5.Process( 2 )*vol[12];
' d( U: [4 J) \5 {& C                }
/ x, p* p' O8 `% t4 L; F4 w                if( exsound_select & 0x10 ) {; G5 x9 w- h* ~
                        output += n106.Process( 0 )*vol[13];: f8 F7 L7 ]) \/ r; |
                        output += n106.Process( 1 )*vol[14];
- E0 }2 T6 x" u4 r2 p! `: t( u* Y/ Z                        output += n106.Process( 2 )*vol[15];
! }/ U7 O5 N8 P: J6 |. ]6 ?& @                        output += n106.Process( 3 )*vol[16];% R- i; \  r  S" K6 I: r: ]
                        output += n106.Process( 4 )*vol[17];0 a$ [+ L5 m! O" V7 m' ^2 K
                        output += n106.Process( 5 )*vol[18];9 C& {) \+ R; P- ?9 F
                        output += n106.Process( 6 )*vol[19];1 Z2 d" g1 ?, ?! v' q. h# U. p9 F' x
                        output += n106.Process( 7 )*vol[20];
6 P# n( R8 n+ D# p, H: e                }
. j% x  I& ]* f( t, d/ z                if( exsound_select & 0x20 ) {. i  c) }- F- A. \8 ^+ A
                        fme7.Process( 3 );        // Envelope & Noise
! U1 y$ M( U/ @% K" O* ~0 c' z& Q                        output += fme7.Process( 0 )*vol[21];, Z, q! L0 X) o
                        output += fme7.Process( 1 )*vol[22];, i# D9 L: H/ O# [3 j; B* I2 O6 h
                        output += fme7.Process( 2 )*vol[23];
' R, Y( m  _" B6 [. b                }: ?- _: H# a/ C

2 Q& K+ F: A- \& V' d' p+ o: O( d0 O                output >>= 8;2 {$ S% d8 {! z, I3 U9 W7 o/ m# d  E

8 g* H# f3 X) Y6 @1 j, a, x' S$ J                if( nFilterType == 1 ) {
; A' c9 v/ g( m. v! l                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
* x5 }3 e% P4 Q* K+ w- T' e" {$ v                        output = (lowpass_filter[0]+output)/2;1 e& e, U8 @5 z
                        lowpass_filter[0] = output;! A1 G: a' D) P# D  ]
                } else if( nFilterType == 2 ) {# j; S7 n  r% {- c; h2 G2 w
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)4 J; k1 O" {# y! S7 _
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
1 R5 ?7 ~! N. Z3 o0 R                        lowpass_filter[1] = lowpass_filter[0];% z2 x! ], Z: d9 n
                        lowpass_filter[0] = output;
) r" \7 m, V* F9 Z2 O9 r/ N& g                } else if( nFilterType == 3 ) {
% ^. a: h+ y) ]+ d& {3 i% f                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
8 w6 l( Q5 y. {                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
8 f4 a8 k6 t2 u* D' ^                        lowpass_filter[2] = lowpass_filter[1];! g2 H9 y# J& t$ |- S5 F
                        lowpass_filter[1] = lowpass_filter[0];
" c6 _7 ~" o4 l* f& s$ ^4 z$ j                        lowpass_filter[0] = output;
; V$ n/ ?% p7 u' |& e                } else if( nFilterType == 4 ) {. F2 s* q$ k6 e0 R. k
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3); R' X$ i7 `  S9 `0 [. Q
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;$ i1 j( P1 \, J# t
                        lowpass_filter[1] = lowpass_filter[0];- b1 L1 p. B$ P$ w" O- b! e8 H. [
                        lowpass_filter[0] = output;
( H" q% c6 X7 f. g                }
) ?, C1 H8 y0 I% X
4 v% o! ]! s1 Y6 R6 M#if        0  `, @* ]6 D7 j+ I
                // DC惉暘偺僇僢僩# x7 }, i2 C4 O3 D; I2 e
                {
2 p) w, e' y* X2 E* R3 \7 A                static double ave = 0.0, max=0.0, min=0.0;
3 c7 h' Y* @, e; M                double delta;3 N, c' ~/ k; n# w0 Y1 ^
                delta = (max-min)/32768.0;1 W2 f- S$ c6 R0 q2 G, v
                max -= delta;) G9 ]$ }* S5 P" o
                min += delta;
4 g- O2 ^, [& A, v8 V, V                if( output > max ) max = output;  }' u) {* V  c+ ?# i$ l' R
                if( output < min ) min = output;- Q% Q$ {* \7 q  s6 I
                ave -= ave/1024.0;  h+ {, ~0 p; J/ W
                ave += (max+min)/2048.0;  q9 q: C3 O/ M. s$ x4 K" a
                output -= (INT)ave;
& n: o" |5 r: y% w6 X                }$ n7 Q3 @* I: _) e
#endif  ^2 I* o9 \  |+ }# J( ^1 `( x. t
#if        1
9 ^) z# Q' M" n# J/ J2 [; q. C                // DC惉暘偺僇僢僩(HPF TEST)# ~- X1 i* [9 E( X
                {' \- X7 z; u% }/ n, o% N2 B
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
9 U( X* E+ Y# o4 l                static        double        cutofftemp = (2.0*3.141592653579*40.0);* n, [/ L# b) @: R/ |; j
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
6 o3 p- x; L* X, w! h7 ^& Q8 F. E: y                static        double        tmp = 0.0;
. z7 s: t* O! ^* J                double        in, out;: ]: ]9 E+ M! m. z9 P# A- L
! I0 T6 x+ I$ m( T( e! ?& R4 i: Q8 o
                in = (double)output;& S9 H  E" T9 y0 I
                out = (in - tmp);" D/ }3 G6 I( m  O% T; [
                tmp = tmp + cutoff * out;9 q1 c* J8 V) \7 F$ l! U( L
) _9 l! w) H- _0 m9 i
                output = (INT)out;( @, W6 l' Z, b6 _
                }8 l% }1 a9 l) U; C$ ^/ K$ @5 r
#endif5 w) V; x0 ]( J* o. D
#if        0
& N( K2 N9 g% ~" A- U+ o                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
1 A4 U# @! u" E7 U/ q                {
# R9 c; O, H. m- u. S1 n1 c  f4 Z- U/ \                INT        diff = abs(output-last_data);
  |. ~, K- d  O+ J1 @                if( diff > 0x4000 ) {! u; }% v4 f- m1 B+ t
                        output /= 4;
6 ?& @8 ~& V# R$ ~$ N% R- U8 _1 [                } else 6 z3 U# ?( N( X* O
                if( diff > 0x3000 ) {
$ _6 s$ ~2 W: |' M  i& L) j                        output /= 3;
* F( k% r& L) b                } else; R; Q% I2 f9 j' \, t/ t5 Y) q. H
                if( diff > 0x2000 ) {- N1 H: Z2 }( [: T! O: U
                        output /= 2;
/ `! B  j# J" u                }
( O  P" a+ F/ V. v  g* P                last_data = output;" w* n3 b) W, a8 \- j) X
                }0 _; q( |' O3 v( X" S9 u  r" ^
#endif
$ _" }2 n  M: |/ v                // Limit
  U3 ?+ {2 `3 i. Z) x9 Q& B3 \, E0 h                if( output > 0x7FFF ) {
" W) U/ z% |9 J" I. g                        output = 0x7FFF;
2 g+ d3 b  H: m; `                } else if( output < -0x8000 ) {  M; Y, g; d! ^4 L% V: H
                        output = -0x8000;
, V" U8 j- i% ?. ]% N- u3 x+ ~                }& }" C, p7 X5 p1 A  H$ c

( ~  l) T" o3 o                if( nBits != 8 ) {1 i% V- b" t5 n  h- d
                        *(SHORT*)lpBuffer = (SHORT)output;
- J( |( p# D( F/ i7 W) d                        lpBuffer += sizeof(SHORT);' {) n% E3 w/ K0 i  X5 G8 c  A4 `
                } else {
- R: F9 u- r( p                        *lpBuffer++ = (output>>8)^0x80;
1 k* H* a  g: X* v2 c: D+ m% p/ h- o2 l                }0 e( H: D; A( x( u- L) M: q5 ^; X
( V- a( w9 v# O- R
                if( nCcount < 0x0100 )
) Z0 J# v* S4 @4 b+ D% Q" u: ^                        pSoundBuf[nCcount++] = (SHORT)output;% ?3 l( y* x4 ]7 b7 M  T( w/ E

  q* s2 j4 E/ k+ Q9 ]0 y: l//                elapsedtime += cycle_rate;$ P2 n9 k  {1 ?* w. w- y- k- v
                elapsed_time += cycle_rate;' ]5 W: P) C1 r: H3 u! Y
        }0 t! f# V( g7 Q0 [/ m' B
; U8 @- j: G5 Z  a
#if        1' U, {) X  n6 h: I9 u  L/ _
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {7 @5 n* {. Z  v5 d3 T. @- k
                elapsed_time = nes->cpu->GetTotalCycles();' l. m& r$ `# o* @7 L8 r
        }
5 p% f) V' W7 x& y/ ^        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
) A& Y. j4 {: X                elapsed_time = nes->cpu->GetTotalCycles();
- H7 v( m+ x. H; z, y  h        }7 [, K. h3 i" n5 n& W" L
#else
' v( V! x% c8 t" n! P% l        elapsed_time = nes->cpu->GetTotalCycles();5 W9 {. w9 N' }( W$ {. \( @* n
#endif; u; o9 P  Y5 d% e. k
}  o# Z$ Q; ~: ]- ^* v

' X- [* \2 J3 i! F/ l4 t; D5 @// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)* O  \' t  r" t0 ^) W4 L
INT        APU::GetChannelFrequency( INT no )
! ~% `" a" w0 o6 Z+ x" a6 Z0 D{
* f  T. w% h$ y$ F9 [) F' v" b        if( !m_bMute[0] )9 J1 t* P! o3 \. {  d
                return        0;
3 l7 H3 _  j5 V3 p. E4 P
* E$ D4 H, x; r# s! H1 k: q0 t        // Internal. R! m9 l0 f' k5 k" J/ m* a
        if( no < 5 ) {
$ {0 B. N  e. T7 a: k) k3 w                return        m_bMute[no+1]?internal.GetFreq( no ):0;
1 ^9 M' M7 C0 t5 ^        }
3 d# J# F" S9 ^1 P8 p$ V7 W* k        // VRC64 M7 d! }4 O7 x) O
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {1 [0 A- B9 Y( ]" @1 k( Y6 V
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
$ A) i( \  u) n0 {7 ?; r6 h- \" x- u        }8 T8 O4 J" `$ R0 B$ T5 ^6 W6 |# N
        // FDS
% d8 M9 D) I) c. f$ a/ e7 l0 u        if( (exsound_select & 0x04) && no == 0x300 ) {
: f4 Q$ y/ n: A: i. h# B4 F                return        m_bMute[6]?fds.GetFreq( 0 ):0;$ j+ P3 f/ }/ h, h2 R, ^  u
        }
9 t, C& K: `; V; W) J4 r  v3 C        // MMC5
0 @, f3 C2 M) ]! ]1 I+ `9 X        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
1 |& j+ o  L% B                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
+ \9 I; @- b. e) r- o! ?9 U2 c; [        }& A7 B6 d+ c3 `: R& W* W, l
        // N1063 `; E; O0 h8 G
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
* |$ j, Y4 y& p% d0 U9 x8 R                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
* ]" Y5 G0 ^+ R7 W0 w8 ~$ i        }* s% K; p2 l2 K* R
        // FME7
- A! T& V) Z" p: [% g+ C! T        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {- B: r0 Y6 [9 l
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
  q. ]6 o0 O. G        }8 D3 H% b- ~5 H8 ?! z$ G2 y
        // VRC71 h5 T' ?7 J' f/ z" J
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {2 _- H/ \" S+ E2 }5 g5 _, I. g: Y
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;2 y! k. ?. W2 _9 c0 }0 B9 Z$ M
        }  x2 T9 e, Q; j7 {& n. U* `
        return        0;
7 |3 S$ @, R7 o4 N# d: y9 q}/ h! a1 r) L& M8 A- N
. ~( Y: \8 g) s
// State Save/Load
3 E" V& A( k6 t; e9 yvoid        APU::SaveState( LPBYTE p )
4 f- ]7 u8 ^3 C; V* G{! _. _3 b" ?+ Q1 x0 I. u- |
#ifdef        _DEBUG' D! O% Y+ s3 ^; ?
LPBYTE        pold = p;+ m" G# u4 ]. ~! k% |# \% @
#endif  D& l) O0 q3 J) r; j. d

; R2 E7 g# k; w7 p, M. N; ^& F        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞$ H  {+ q' N# x/ y. }/ Q* _7 e7 t
        QueueFlush();- G2 `* R# a" m0 k
$ q6 Y0 ^+ L. |& V4 Z
        internal.SaveState( p );$ q! \% E/ }4 b/ R! |
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding  {: p7 m5 K) a( S2 t6 @

  s  m- l  Z5 L, S# u        // VRC6
/ `; X% k8 S- T' C/ a% I, x  J        if( exsound_select & 0x01 ) {
# ?% K' A. @" ^9 h( Q4 b                vrc6.SaveState( p );; p) o- A* N* o* y5 W$ I* f0 [4 J
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
+ P( n5 J8 D* Y5 s        }
7 C) H4 ~* O7 a4 h% W        // VRC7 (not support)4 Q( ?# z, o0 Q' X
        if( exsound_select & 0x02 ) {
5 ~& o1 a! A. O9 o2 |" w                vrc7.SaveState( p );7 s6 ?  l7 D6 ~( V& F: }
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
2 }# s: V2 b9 S. [. C        }+ ^, V1 P" j" ~: p7 I' Z+ R
        // FDS5 t& C% u  [; N  ?. i0 I* u
        if( exsound_select & 0x04 ) {
$ N% A" b* Y& C. G# U$ Z                fds.SaveState( p );
7 ^% T: V7 h+ V1 l3 ?% v, J& b: Z                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding/ Y( K( u( C& @% [- Q! G
        }5 x4 O2 J, Q5 _: ~" Z
        // MMC5
9 E' C' F) e8 k        if( exsound_select & 0x08 ) {
6 O; M$ ~/ O1 c. W% ~3 g                mmc5.SaveState( p );
3 y) k3 }( L  c. T. C$ }                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
- W/ Y* L* B& H/ w! ~        }* X4 Z0 v% E9 [6 h2 |. d7 Q
        // N1063 S- Z$ d: d: s! _* U
        if( exsound_select & 0x10 ) {: W# N2 L& m' r$ d
                n106.SaveState( p );
; C2 @( ], a7 ~! Q# l                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding3 q! }. p  b# `0 V) ]: y- d
        }; p3 N3 q* W2 L0 }9 g* z5 m) X- F
        // FME7' d0 B6 Q) B" S. |
        if( exsound_select & 0x20 ) {  v- l  |1 U. c
                fme7.SaveState( p );: ?4 M' H/ y$ G1 ]3 y
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding$ A* ]3 P' g5 }) q4 N3 u
        }8 L0 M7 ^, _$ G+ V" |

% P+ ]- c- L# f/ j. X3 x* m9 h3 W6 w#ifdef        _DEBUG
( Q$ |$ E+ I4 K2 T  FDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );+ m" C+ P) y- J! E* r1 [: A
#endif, g# V, }) D- Q
}3 m  z4 c5 v4 t; K

4 a3 H0 C- b* q6 @void        APU::LoadState( LPBYTE p )+ g6 g9 q$ H+ E
{
1 X& A' G/ R" a: k7 z9 H7 G9 p0 u        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
7 ?' q6 H: b+ [" t* N  n        QueueClear();
& `' m2 {5 ~9 b% m# ]0 W7 j
9 F' I) T* y1 Q0 _$ W# x* }. w; [        internal.LoadState( p );
; o" q( D* o: ^. i5 }        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding/ A. I. ^9 a, b! w% F0 o5 D
1 f. B5 z+ c8 l8 F; _/ j( G* o
        // VRC6
: q; E2 Z! A. ?' c' P% y        if( exsound_select & 0x01 ) {1 w" g; I" l3 I3 z% D+ M- }: [
                vrc6.LoadState( p );' n$ {3 M8 S; T( z! q$ s
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
. E1 @" f" p1 V- `9 @! U        }- }# u  g4 u4 U0 i- B4 {0 s6 f
        // VRC7 (not support)& m  ?7 k4 Z; G+ _( R; V
        if( exsound_select & 0x02 ) {+ I8 u- ]$ }5 X6 R: k$ O
                vrc7.LoadState( p );
9 B  m" i- \$ r8 @) _                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding2 B. }* v8 y+ n' C
        }/ U, J+ a$ ~9 ?4 k$ q( M" `7 X& k5 r
        // FDS
5 I) a1 n$ |( a        if( exsound_select & 0x04 ) {
* }, [/ Q, M7 j( n                fds.LoadState( p );
9 ^; Z( L' Q1 t5 A                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
0 o+ ^1 p& G8 R% W. Y" m% i- ]        }! p) h# I/ A& N9 U# I; K
        // MMC5
! c" F. P5 Q" y/ k% @. Z" ]* R        if( exsound_select & 0x08 ) {8 t' {7 t3 I# i- N+ ]3 l( T+ L2 `
                mmc5.LoadState( p );- }. W* E5 Q8 I( _9 S
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
5 g! e& m7 d6 Q+ @        }: D0 \8 b: J. Z
        // N1063 ~% m! P6 x" y6 [. H# E6 L3 t
        if( exsound_select & 0x10 ) {
9 \$ V2 r1 P; N0 \* w                n106.LoadState( p );
1 s# c4 h% k6 I' D" m' k                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
# u) O% w- X4 j; [- }  H        }
4 t4 G8 t: i5 t/ C8 g8 p        // FME7
4 P3 ?" d" ?* ^+ C) |+ W# ^        if( exsound_select & 0x20 ) {
) G' M1 ~- i1 ]% S                fme7.LoadState( p );! E$ n* j. c' Q1 U
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding6 z8 q: W" E  k% }
        }
6 q/ Q! J1 J" ]3 @}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
, b( @1 K$ H6 a, S# H% s可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。1 B; S/ Z3 Z/ k
感激不尽~~
7 m: _, F" Y) [
恩 我對模擬器不是很有研究,% Z% F8 O$ O4 G* o6 X) p
雖然要了解源碼內容,可能不是很困難,
" X" k8 a; Q; {: Y) H! }  A不過還是要花時間,個人目前蠻忙碌的。0 N1 e- z/ U' _0 x" |, V/ ^  q
8 i& q1 Z& ]9 E
給你一個朋友的MSN,你可以跟他討論看看,% o. M& ~! f8 d7 h6 q- y: H
他本身是程式設計師,也對FC模擬器很有興趣。- q6 r( ]2 B5 ~5 g

9 B& b) f9 y  x& WMSN我就PM到你的信箱了。  z7 J7 [5 x5 b+ _. E& v

3 C1 V9 K, u; e& T0 K6 i; g' _希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 - y  q: }7 C5 E( F. F
呵…… 谢过团长大人~~

- h# J. C* n  l9 D) {3 R( _# g) m) }3 n0 u1 x' M3 P' s/ L5 K
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 8 |( {  l: p1 [" R
团长的朋友都是神,那团长就是神的boss。
2 U8 [( W! j: {* [- h
哈 不敢當,我只是個平凡人,
+ F; k8 [# ]+ J0 c要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
$ v2 V5 N+ X7 @, dZYH
/ \/ T" q' C* @5 d; A  P8 ?6 rQQ:414734306
  A, O! x* u, G/ b7 B& jMail:zyh-01@126.com
+ {8 D- i7 l# v, W; q6 O% e! T7 Q# `1 L4 J0 Y
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
: N9 E# G  L* D! u  P再次对团长大人和悠悠哥的无私帮助表示感谢~~

: ^' d! ~6 S9 ~& X不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-15 21:16 , Processed in 1.081055 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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