EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?. Q  U: [' H: M3 ]% @* v6 B
PS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。9 h+ X" u  M& M/ w  s
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
: E9 |- S& j8 T这里有相应的模拟器源码,就当送给大侠了~~
, P1 ^# e$ u3 C0 a( z& E; |: nhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 " d! y) b+ D# \% H) D
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
! f. Y, C3 s! F6 m" @楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~5 E1 o* v5 p! c/ z4 r
这里有相应的模拟器源码,就当送给大侠 ...
( H) p5 ~8 B8 }
聲音部分(Audoi Process Unit = APU):$ n  j$ J7 h  }
.\NES\APU.cpp* V& w4 t* s7 |, a8 b
.\NES\APU.h6 Z! N" E+ K+ N" o* \# i

$ p8 ]' R" o' E3 _
9 F: h1 i9 L- ^2 W6 Q# V8 B, J, w# t影像處理部份(Picture Processing Unit = PPU):# v" S$ t+ D9 i6 M
.\NES\PPU.cpp) l# [: g& m" b2 {1 p- m  f
.\NES\PPU.h3 R2 h1 N3 [0 U. P& f; ~; o$ A) S
5 W7 ^1 Y: K+ f# Q0 ~
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:/ D9 X- n) A- P6 f: d9 H8 s
(由于很多专用术语和算法机理都不明白,所以看不大懂……)% b3 a4 d+ v2 T; U2 J. A
//////////////////////////////////////////////////////////////////////////' L6 B+ i, M' Y: R9 \+ q' n$ Q- ]5 A, W
//                                                                      //3 ?0 T% I/ G. F+ `7 ?
//      NES APU core                                                    //
3 l8 ]5 b  N) _# R! h' M//                                                           Norix      //
: c: y8 k8 T7 V2 B/ K& S//                                               written     2002/06/27 //
2 F1 {( L/ K+ A( l& s//                                               last modify ----/--/-- //
3 P' z, o9 _5 [) s; |//////////////////////////////////////////////////////////////////////////
- ]* b: S0 @' n& `# o+ C0 @#include "DebugOut.h": |* V& r! }+ V6 R/ M2 ]- k' A
#include "App.h") O& V3 v" C  F& b, `# O* h
#include "Config.h"# u. m8 h( A8 f% _: Y/ m6 z, N
) W' N1 P5 I! n2 N/ `/ p
#include "nes.h"
1 m: ^' @! R2 i" b#include "mmu.h"" g  R, X2 j6 z" p, w) D
#include "cpu.h"5 }9 ]2 L2 E. q: Q. [
#include "ppu.h"/ a# Y, J& U9 Q8 T8 e6 ]. j
#include "rom.h"
8 F/ G; k( t& _5 M+ c( L( v. n#include "apu.h"
+ ?( a* r+ b7 E! r( j' K. s7 |. A, [' v% W  Y% ~
// Volume adjust) o; m& t( j! a
// Internal sounds8 t3 s$ |7 m( x" r# C# i
#define        RECTANGLE_VOL        (0x0F0)
( ~4 N, @! K9 p' {! D  D4 x# Y#define        TRIANGLE_VOL        (0x130)0 G! ^2 o- k$ k
#define        NOISE_VOL        (0x0C0)3 d8 K! Z3 O" Q: ^' i
#define        DPCM_VOL        (0x0F0)
. B- e- f  l* Y( k: x// Extra sounds- |9 U% @, f& W
#define        VRC6_VOL        (0x0F0)0 d* b* K8 P6 L/ d
#define        VRC7_VOL        (0x130)
' P/ h/ D: a, w' T$ J8 X#define        FDS_VOL                (0x0F0)
0 D" D  Y. v4 G. L5 ^$ Q/ V#define        MMC5_VOL        (0x0F0)
, W  _2 e. Q) V. q#define        N106_VOL        (0x088)" E+ X( j* U( }# Q6 L) ?5 L
#define        FME7_VOL        (0x130): D, k- ?% g5 V3 V- F9 P
. H& ~1 _1 g, G
APU::APU( NES* parent )7 G& l! z& A8 x& ~+ I
{: c+ P2 ]) k% r/ ?2 }. y3 i( ~
        exsound_select = 0;
  Y$ D6 T) C. s% T7 `8 y2 Y( k0 w
2 d+ u/ P& P9 C7 m7 a& f0 j0 n$ Q        nes = parent;
9 a- g4 O7 z  N" P1 e: m        internal.SetParent( parent );2 w( u2 j) Y6 ^7 ^+ U- i2 E3 f
, }' [0 q3 ?  W! ^0 ]* ^
        last_data = last_diff = 0;
7 V6 _+ B! u' H" z0 T; G: Z0 P$ f% t+ M* @7 `1 ?: z
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
- z; l, ]) p# Y6 V' W# w! O
6 A$ j" h  J( X% j$ s        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
/ N) J: g3 R  {( t7 I! a        ZEROMEMORY( &queue, sizeof(queue) );
  L" k2 h4 X0 I. S& k! t        ZEROMEMORY( &exqueue, sizeof(exqueue) );
& }6 H/ K2 A' p8 V4 x, n7 q5 z
4 P  P! H3 I: P+ s& ]( Y3 A        for( INT i = 0; i < 16; i++ ) {
" V9 \9 {% Z" ^3 b$ `/ y7 `# ~                m_bMute = TRUE;
! u% i! ^! s, {( O% R+ W% W1 p        }2 u7 B3 l! f: B
}
1 V4 Q' e; y) E  k; N2 w5 b, ]) B9 `, ~4 b, g. g: b
APU::~APU()
% x1 t6 n1 U3 {) D+ \( C) |{/ U; T! e& t& r& ]
}' d+ u/ X: \4 L8 F8 t/ m: H

" I, o" F' q' ^6 A2 g9 w" f8 h1 Ovoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
- _: d, H, |5 n9 K. u{, H3 B. j! U( |  K& q
        queue.data[queue.wrptr].time = writetime;
$ g/ h6 g3 i3 ~+ z0 b( u        queue.data[queue.wrptr].addr = addr;% }4 M8 h: b' o* e, i# K3 O3 r
        queue.data[queue.wrptr].data = data;
3 i) g" Q1 ~% i1 e+ n: f1 P- x        queue.wrptr++;
$ u5 K2 S! c2 h3 |/ R        queue.wrptr&=QUEUE_LENGTH-1;
: ~: l$ K# M! m3 h# e        if( queue.wrptr == queue.rdptr ) {$ h7 _8 u+ `7 x- K3 ]: Y
                DEBUGOUT( "queue overflow.\n" );
) m4 q5 V/ B$ @+ K, q0 _  m        }8 w/ i( H3 a( D* t0 e# \
}( Q5 z6 f& V, y# G3 w8 B9 U% q
6 o4 j+ b" l0 I; L! k0 {! U
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
# D/ k$ |0 l6 d9 q+ r" n3 y( ]! R{
. D2 E9 d  w  y* v8 J: S7 S1 `5 k- Q        if( queue.wrptr == queue.rdptr ) {
) Y2 v% ~# q; g8 T" P7 v2 K7 t                return        FALSE;
- P0 o! S! G/ G6 T) B( i6 E4 U7 S        }: l+ ]5 Q1 u' c1 @2 L# D
        if( queue.data[queue.rdptr].time <= writetime ) {
+ ]% v8 G2 J( P- u) W                ret = queue.data[queue.rdptr];
. ]- C& Y9 `6 n9 M5 f                queue.rdptr++;
. x' j! ~0 q# w( i; R5 f                queue.rdptr&=QUEUE_LENGTH-1;6 Y9 a- q0 }) E0 T  r0 `+ A
                return        TRUE;
) S# c4 O3 y; h! d5 H% D! K- [8 O) ^        }1 z# W9 i3 e# Y3 O: u
        return        FALSE;
) }* a5 }# o; j( b5 W}
. G; v' e1 o5 l: w- L8 j8 y6 T
  {+ `; w* a. N2 Y0 [# Zvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )3 Q  T# x+ _) x% n$ M5 I" o
{
) u; X/ L, o0 v% b0 \# g        exqueue.data[exqueue.wrptr].time = writetime;
2 e$ L" k% ^) K4 n' _        exqueue.data[exqueue.wrptr].addr = addr;
: }; p6 V8 d! o4 I/ `$ Y        exqueue.data[exqueue.wrptr].data = data;
- |# Q' F: R9 @- }$ E7 Q        exqueue.wrptr++;' T2 `9 g! a; L# j3 c0 F
        exqueue.wrptr&=QUEUE_LENGTH-1;
/ c+ B7 q$ l) t5 H' `7 b        if( exqueue.wrptr == exqueue.rdptr ) {
' @3 z- q* u: \: ~5 i; U                DEBUGOUT( "exqueue overflow.\n" );
9 ?6 N% v8 D/ j        }
, h& O( `2 C* T% b+ @1 n3 i}* _. e$ P2 Y# @: l) s) h
0 r1 L* z5 }# `5 `
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
* [; q# U: M) @) T, T! g{+ ?0 ]1 d4 K! x7 k
        if( exqueue.wrptr == exqueue.rdptr ) {( i: B9 \" H! l% A$ i  B" B
                return        FALSE;) X) k/ j% J/ V/ A* M9 }4 j
        }, R$ U  k7 L; a4 |3 n0 J4 s
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
' ^" i( Z! i# [                ret = exqueue.data[exqueue.rdptr];
, V6 L3 F( Y3 {- Q$ ^$ ]+ T4 a* F                exqueue.rdptr++;  y% X/ i, C5 w0 s
                exqueue.rdptr&=QUEUE_LENGTH-1;
; f: O9 ^" L1 T) O; \  {) h                return        TRUE;" d& H1 a& v9 M+ `5 N1 X
        }6 i$ I0 ^& l( i9 v2 o
        return        FALSE;
+ M% Q" j* |; }7 e( Q( ^* U}
) F8 V  t3 e0 ^; u) F4 a% r/ Y3 s0 G2 G3 G' g
void        APU::QueueClear()6 X/ S, {% @$ P( u. _) l
{
/ b6 X) o; k& E' y. D  `9 e        ZEROMEMORY( &queue, sizeof(queue) );6 n* I; Q# j. E: I0 R$ h- a
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
5 I& s9 T1 P5 I}% w* c! V4 e) b) C, \
- M6 K/ `1 s8 y9 z2 T& ]
void        APU::QueueFlush()- k6 U" @, F4 ]* ?
{
$ [7 e/ n1 u$ b- {" h$ o$ z9 W* t        while( queue.wrptr != queue.rdptr ) {
* h' o4 w. y9 K/ G# U, U" h9 p                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
, Z+ K1 v6 W! U# }7 M# E                queue.rdptr++;
- }) l7 d' Z; c6 S  L! S                queue.rdptr&=QUEUE_LENGTH-1;
1 a) r8 q# U* I  w9 Y        }6 s4 a$ z: ?( c1 h% w+ @4 U$ ~
9 v& Z$ p' T# P: C/ B
        while( exqueue.wrptr != exqueue.rdptr ) {+ ?. a5 U/ {4 U# f' G
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
6 r: c! f5 i* }9 g1 x                exqueue.rdptr++;
/ z0 o" G) Y2 P" o( f* C                exqueue.rdptr&=QUEUE_LENGTH-1;
4 p. n4 T0 J  @        }: {# s: c6 `0 B8 i/ W! G: t4 K; O
}
6 @9 Y" R6 W8 n6 L7 t, Z' Y: z7 j
! u3 Y4 v; l5 Kvoid        APU::SoundSetup()
! O" \- J$ q- o% Q/ `' ?6 e{$ r7 S1 |7 K' I; h  Q% F  W* E+ T
        FLOAT        fClock = nes->nescfg->CpuClock;
7 f# W% ]: B# W$ S7 D' {        INT        nRate = (INT)Config.sound.nRate;
+ B* l& q9 A, d4 V3 d2 |        internal.Setup( fClock, nRate );& Z# g6 X& A, W9 p7 Z$ ]- T
        vrc6.Setup( fClock, nRate );
0 v( v# i9 m; q$ ?+ m9 Y        vrc7.Setup( fClock, nRate );
3 n+ n; L0 e# q; b/ h; [+ |7 }        mmc5.Setup( fClock, nRate );8 ]; J. p3 w% F2 u! c: f3 B* P7 D
        fds.Setup ( fClock, nRate );1 W3 J0 g$ O3 P: J8 l# i
        n106.Setup( fClock, nRate );* B8 z; j% p+ H0 {  N, m5 f
        fme7.Setup( fClock, nRate );+ {/ W! t. R, u' x7 Y
}
4 `" o7 R, @0 U$ h4 t  d7 r# ~3 T  Q- x5 {
void        APU::Reset()
1 b% B6 [' F- x" P1 y! R{
2 H4 f  P# u6 H4 ^% C7 r9 h        ZEROMEMORY( &queue, sizeof(queue) );
0 C: I* R6 K6 I4 t( g        ZEROMEMORY( &exqueue, sizeof(exqueue) );: O' v! y8 p" @" B1 r$ F
* e" N# {1 x/ D
        elapsed_time = 0;
1 q/ P4 Y) u# ~3 E( w  S) C5 R5 Z: G& G* \
        FLOAT        fClock = nes->nescfg->CpuClock;; Q2 f/ O% G4 X3 i3 o3 y1 b9 Q
        INT        nRate = (INT)Config.sound.nRate;
9 b+ i- z. }% L        internal.Reset( fClock, nRate );; ^  v* X! j" X, k0 E! P
        vrc6.Reset( fClock, nRate );
" f) E* H" e' P% b( o2 V2 r1 J; m7 V        vrc7.Reset( fClock, nRate );
4 Y# ]  m& u+ v5 J+ i- P        mmc5.Reset( fClock, nRate );& L0 @' w* }- L5 w/ u
        fds.Reset ( fClock, nRate );
9 S3 \' ~! Z' |1 ~) @* H% Q/ h% s        n106.Reset( fClock, nRate );  b8 q! i8 C' C6 T& X5 ~3 w
        fme7.Reset( fClock, nRate );
) z$ H  v- J# v9 s0 m. g, ~: M$ n6 M( u3 T
        SoundSetup();$ C0 O+ @" S$ `& c7 N+ P& |* G6 B
}
" d2 B! c% k. K0 s8 F- x+ {5 O
; _5 l9 N: ^9 n& I0 m9 Wvoid        APU::SelectExSound( BYTE data )
3 c% k7 X  w4 z  K' l{$ s2 E  S$ S) T$ r" M1 |' s2 _
        exsound_select = data;. U. z, I1 r9 ?$ P  s
}
7 Q5 |; j7 |, R8 {( l8 f( S  o9 Q4 E) C5 s: b
BYTE        APU::Read( WORD addr )8 u# L% W3 N+ v4 p
{( }7 w7 o0 X' ?5 V' j! ^  B$ l# |' f
        return        internal.SyncRead( addr );" y0 r1 T7 m8 p7 _- w
}* q$ Y  M- r* @0 v
# j+ D) m; v; O2 z' i% b
void        APU::Write( WORD addr, BYTE data )2 D/ p- Y% p7 N# X1 J, ~
{0 g& X2 Z: a& |; N& J) I5 g( x
        // $4018偼VirtuaNES屌桳億乕僩$ ]9 e( H) }5 c0 m
        if( addr >= 0x4000 && addr <= 0x401F ) {* ]& Y! r! a# o* t4 }( P
                internal.SyncWrite( addr, data );
- z7 k8 J, T- }7 ?# B5 v                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
# q( `: i6 X0 a% w+ [$ G        }, d/ ^, U' l( k; ?" [! x0 l, Y0 |
}# C2 K3 M6 L) ~( ^4 e
( o  q7 N! k4 b3 C! S0 |) E5 j
BYTE        APU::ExRead( WORD addr )9 [, O5 X" V5 Y& W7 ^2 y: V% ^. z
{
& h' ?5 d4 z+ X7 J+ Y* R/ EBYTE        data = 0;4 x% ?+ W- f$ i9 g/ Q

* o2 |4 e; K* j5 J; r+ W+ D        if( exsound_select & 0x10 ) {1 B7 a- H! Y8 t/ }/ _
                if( addr == 0x4800 ) {+ E8 q/ ~" u: g& `
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );" x7 y0 t2 B* |+ H" K  V* n5 M
                }) F( s0 [8 b* f! I8 V
        }
  Q; b) ?( ]/ {% p; y4 t5 ?        if( exsound_select & 0x04 ) {( @7 }- L( Z" e; u- }8 T, _
                if( addr >= 0x4040 && addr < 0x4100 ) {/ P9 y/ ]; ?) {
                        data = fds.SyncRead( addr );
2 `) a( W# _1 O  U                }
. l3 @4 n1 o% X        }
1 q+ [: I/ Q) z! j3 }5 p- U' P        if( exsound_select & 0x08 ) {
2 u% @/ m4 u4 S& A0 {                if( addr >= 0x5000 && addr <= 0x5015 ) {( O3 O1 n* a  e
                        data = mmc5.SyncRead( addr );
  j+ M7 t9 f, e/ U- ]9 \  [3 D                }
! b! b8 T; }  }4 f% \! g        }
3 ~  a6 v, f) B* g( p# u8 C2 w" C1 E5 Z. D8 N1 I# A1 n+ _
        return        data;
5 _1 x. V2 V3 b* M* u( O7 w+ k}. |; B8 U9 V- ^/ H: L9 C9 d& N6 Q" Q
- u2 l7 H4 ]4 v1 u
void        APU::ExWrite( WORD addr, BYTE data )+ J" W5 l! R& Q! d0 {6 S2 m" C
{
0 h+ g6 C, u- l  }+ r% {  }2 a        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
# T% l0 P7 h$ J; T" _  \: Z1 O+ ^1 o
        if( exsound_select & 0x04 ) {7 M, r+ x8 y4 ?! t( t8 E4 X! i
                if( addr >= 0x4040 && addr < 0x4100 ) {
7 K7 f. S" y  R0 a4 V                        fds.SyncWrite( addr, data );
& J0 l! G: U, n7 s# [                }
. _  o: _' M) B8 O        }( a3 h; u5 a6 t3 m: @/ }

3 D7 {( m: H! }3 K8 Y5 @6 F& p        if( exsound_select & 0x08 ) {& N( E/ X  S' }, W0 a% [
                if( addr >= 0x5000 && addr <= 0x5015 ) {+ i- K2 d! H; B! t1 _4 {
                        mmc5.SyncWrite( addr, data );- S' b3 ^+ E" B
                }
2 U- S3 d" G3 M! n# r- Y! j        }( t5 I/ A0 E; ~% q
}
$ _9 p$ c' i  [0 R6 s( D6 r  N: r* @9 @& h9 l
void        APU::Sync()
1 h3 W6 s# v! O6 k{9 V( x& e& R( o6 `" t
}+ w( T- ^% \! c5 ~5 }3 M( Z
1 G, ^4 `+ b% n, }: I4 U5 C
void        APU::SyncDPCM( INT cycles )
0 b# O- a8 U$ ^' M1 i! W  R* i{9 w; L6 S! w# K2 i# w
        internal.Sync( cycles );
" ~8 b$ v3 y0 [) O
# ^+ Q) ~5 H! W- f        if( exsound_select & 0x04 ) {
- P! V! f" K" a: @- E, x                fds.Sync( cycles );) w6 }- H" P: S" l. h8 \
        }
1 m4 ~+ d, m6 u" @4 V4 n        if( exsound_select & 0x08 ) {0 C7 E- u6 B! }3 d; H& ?
                mmc5.Sync( cycles );
2 r" _" k+ L, q        }& h) m& V+ l7 D- f
}
1 G. e% U) j& _) G: P' {1 ]' x6 o$ p. b& I: c
void        APU::WriteProcess( WORD addr, BYTE data )
3 ~! I6 @6 ~- c! S8 G$ Y{' d, n2 Z. q, o; g
        // $4018偼VirtuaNES屌桳億乕僩
% N  Y7 n- O( ^        if( addr >= 0x4000 && addr <= 0x401F ) {
7 {  p9 v- s+ x! z* A( H5 ~                internal.Write( addr, data );( q! W# B( ?( N# d, n, e% |8 ^( g
        }: j1 t( L! r6 r% B/ M
}
" f" V1 g1 r# U6 k( p0 p% g  U. {$ R  ?: q4 l4 r+ @4 q
void        APU::WriteExProcess( WORD addr, BYTE data )' q/ S- w% U/ O3 a2 X
{
' a# _) M' ~; d) {, N        if( exsound_select & 0x01 ) {) a+ P: e& w- ~( Q; y" s1 D% M$ R. B
                vrc6.Write( addr, data );
- F: S$ H% Y, B4 G3 T        }! H3 U( Q% K" ?. a5 I
        if( exsound_select & 0x02 ) {
$ X0 r  {9 M" O+ A2 a- Y; T" N                vrc7.Write( addr, data );
* W9 f4 s5 |3 a1 R) a/ r        }
1 y9 ?$ s. r7 ]+ x' X: n* q$ g        if( exsound_select & 0x04 ) {/ i  P, r5 h# r; c3 @2 R3 @. l
                fds.Write( addr, data );
- y+ q$ s/ k, s3 K; x        }5 }: A" f* `8 Q  {4 T6 f
        if( exsound_select & 0x08 ) {
: D$ B2 a5 c& @1 a; Z7 d8 i7 T                mmc5.Write( addr, data );
, @9 O; _9 m( u- y        }
! i2 t! G* g5 I& @4 p        if( exsound_select & 0x10 ) {
# d% u& ~. w/ A/ X                if( addr == 0x0000 ) {! g4 G5 n7 L8 _5 i# [( i5 f
                        BYTE        dummy = n106.Read( addr );$ ]. ~4 N4 a; `1 X, t  K7 b
                } else {. ?) ]( K- f* i$ X  c* A9 D/ t1 \3 @
                        n106.Write( addr, data );: U4 ~" R6 i9 _  l
                }
- v9 Y/ p4 A- G        }
! Z1 e" L0 P% Z/ T: J4 Y% [        if( exsound_select & 0x20 ) {& F) @2 M3 H# _# H2 ^3 I
                fme7.Write( addr, data );2 P# g3 u: Y% |0 `. ^
        }
  N7 ^$ z3 m7 y3 `}5 G% T' D' {0 ?+ _$ q- Y

( }7 L( t! e; |! I1 k5 rvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize ); y4 x8 b1 O$ u$ V' t
{
% p. ~, l3 i3 ?7 h+ \, zINT        nBits = Config.sound.nBits;" N8 O6 r( k. x( {% l
DWORD        dwLength = dwSize / (nBits/8);1 @" K1 H; a0 h- t' d5 G8 j$ z8 ~
INT        output;* @9 W7 c  v4 f" k5 d" k9 p* ^
QUEUEDATA q;
- p3 n, B  m4 c- [2 i4 O0 sDWORD        writetime;) U6 o0 d2 }# V2 B7 l

" a: f! G* B: o9 Y; |LPSHORT        pSoundBuf = m_SoundBuffer;
) o7 f7 _- J8 L5 K  Z4 AINT        nCcount = 0;* H8 A3 g' T0 l$ x' x, U

* l& ?+ V* {$ n0 O8 VINT        nFilterType = Config.sound.nFilterType;, e# ~* Z' S4 y9 {( ^
8 Z5 F9 f1 @' T& U" n) y5 B
        if( !Config.sound.bEnable ) {
( }- c, ^1 p% N                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
7 O) b3 w  w1 n                return;0 M. y" ?4 z4 y3 G  x( J$ Q4 h3 h
        }
. d4 V; Q# N1 J! E# B  f/ V+ l4 A0 b# ?. U# t7 V
        // Volume setup
8 X2 A6 R( H. d! R        //  0:Master
9 Y, m, K3 }1 z        //  1:Rectangle 1
1 v" {- @% i7 \# `" q7 f+ y        //  2:Rectangle 2& B0 L3 |8 P; h/ Q  h
        //  3:Triangle; A8 H" G+ v6 _1 v; E% J
        //  4:Noise+ Q7 m& p# b4 _' h& v7 [7 v9 g! v) {
        //  5:DPCM
) D! q2 D0 ?5 P; v! k8 Z        //  6:VRC60 O. s# l+ X6 o! i, x
        //  7:VRC7
# J: k$ k% a' F; s3 n        //  8:FDS$ n1 |4 a8 y6 k
        //  9:MMC5
0 Q. J' `3 g# q9 W/ Z5 g/ Z' E        // 10:N1064 M1 V. b: b, O' J/ P* D
        // 11:FME7
; W: H6 `) \; c5 p3 q/ `# v% O        INT        vol[24];- ^; S3 [8 [' ^2 B, J5 C6 r
        BOOL*        bMute = m_bMute;% G+ K; S$ C4 `
        SHORT*        nVolume = Config.sound.nVolume;! Y" }7 e/ u0 l) _% J
. c6 `5 T$ s& b3 ]
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;% c2 k" S  q) ~0 T/ W( i
7 r4 {4 J2 B+ z) [4 p) ?  O
        // Internal" x) ]7 ^9 L4 w2 y' m& b/ ~# j
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
; D1 G& Z2 Q# J+ Y( x' O1 @# y        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
0 w1 G1 F* T0 E. d7 [8 L4 E  ?% U        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;; [" m3 w) @& _& n8 N$ |
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;7 {$ @1 i) L" w* \( x5 E
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;* c& x( n: s2 I& A2 _* ^5 i

( p- {, K& \/ ]# r; \* w8 j        // VRC6: [; h% I2 i" ]5 ^4 a$ @
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
3 p) C% L' n3 l0 L        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;! x" J/ Z! X! ?% I. j, g) c
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
2 r) n4 B8 B! m: M1 f+ Y; z& H3 V. b; J
$ p. s+ O/ \+ V% x3 d6 A' k& @) P        // VRC7" r) |5 P0 \* L, U
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
) @4 S0 ~4 {/ `8 X+ \
3 p- v$ ~1 y& P& G        // FDS
- [( s1 C5 B8 J- B7 a% l        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;1 V/ y0 c2 z6 T5 ?4 |& b2 r

( m! p* ~4 b6 @: h1 @9 B        // MMC5
- w6 e4 x0 t: v  Y/ s9 p! V% \- O        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
+ ?/ y, U6 k7 K9 |9 O, D; t        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;/ W5 W/ U$ g5 M6 O$ ~* f
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
3 o1 x; R+ w; O8 G% W7 E0 T5 K, ?- }. L; B& \/ d% M  y- b
        // N106+ Q6 Q* g0 d' {4 K7 Q$ c* y/ A
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 X: D# w) |- V- e
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 A& u  r( t2 X1 m. q
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
8 ~0 N& Z) o7 c        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;& c, n6 k' r; O1 m+ O
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
: g8 p9 i) T5 A, h! g2 Q3 x7 C7 |        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 ]* C- g2 f( ?( Q1 W0 k$ g        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ D+ Q# b" D# J. ]: W! H7 N
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;; A/ G" a! s' u' A3 @3 p+ ^& O0 ~+ s

/ T) Q0 P. K! ?        // FME7
% L- D1 L8 U, G9 \4 E$ m, J        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;, O/ D, K; p: E; B7 b. D5 F' _6 T
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
& ~" h" q+ h/ R0 j2 b7 \. K        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;% ^" b. c% Q( F: _

, \7 W6 }2 @4 {: Y: {7 ]  I* l- M//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;! ]2 l2 M' m  q+ p2 @8 A) r! l
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;3 ?$ Y6 s7 ]  q8 Q  J

; A. {2 i2 T' X        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟6 D3 U2 z: g+ ~/ r6 b
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {9 u/ _2 s/ ]/ u" v( i+ ?
                QueueFlush();  i. Q6 q& B9 o- j: |) L4 W' C
        }
( r5 ?( E9 m2 L
% e/ }1 X% B" c- |6 G0 D        while( dwLength-- ) {
8 r! ~) \9 K* n; n7 R                writetime = (DWORD)elapsed_time;
- X+ U9 W- y1 u* A# w
' s+ R7 h  O6 x* H+ ~, K                while( GetQueue( writetime, q ) ) {1 J, e0 R4 u5 v2 `
                        WriteProcess( q.addr, q.data );4 q+ e# l* N6 e
                }
" R- O/ B: J% f
& k- y# p' s/ c; t& z) a6 E) M                while( GetExQueue( writetime, q ) ) {
- ?+ Q1 ]/ g& g1 [                        WriteExProcess( q.addr, q.data );0 x/ ^: a" f# ?4 i8 z" d, A' I
                }9 X* o* C3 ?3 {- `6 G, C/ q& A
" Y9 O, a3 j2 p% U1 a
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
, t: C/ A/ b7 _1 s) C5 i                output = 0;7 S+ i; Z$ |# ~: i8 f- s
                output += internal.Process( 0 )*vol[0];
, b' V( F+ D" Y  J( G5 N$ E                output += internal.Process( 1 )*vol[1];. v2 Z& [4 K2 V
                output += internal.Process( 2 )*vol[2];
. o1 L4 p" x% [7 U4 b( i                output += internal.Process( 3 )*vol[3];* O, O/ i+ P  W$ V) w7 e- m2 t7 x
                output += internal.Process( 4 )*vol[4];. x7 u( ?" Q* I/ |8 X6 P
. O. S/ O' Y. A) O
                if( exsound_select & 0x01 ) {
: U/ h) h% u$ ?2 Q0 d: y                        output += vrc6.Process( 0 )*vol[5];- \* W$ `7 \2 w& e$ @. k( [6 S* S
                        output += vrc6.Process( 1 )*vol[6];+ U% J' S/ g/ P) F- |, z# ~0 c
                        output += vrc6.Process( 2 )*vol[7];
/ y. `  g% H# S/ q+ z4 y" g, J                }
) w* }" x0 |" K- o+ a3 v                if( exsound_select & 0x02 ) {) j# Y/ U) z- j& G) b4 N$ u
                        output += vrc7.Process( 0 )*vol[8];( f1 V9 Y( F6 m; z) ~) c
                }0 d& ]  B; `2 f+ t$ s$ m
                if( exsound_select & 0x04 ) {
) ^3 R0 I3 ?, G0 c/ j5 X; P                        output += fds.Process( 0 )*vol[9];
6 ?+ ?: ~  W& b2 l. _                }6 E2 m. C- \! \4 ]' c
                if( exsound_select & 0x08 ) {/ W, ]# d$ S. h2 n2 y
                        output += mmc5.Process( 0 )*vol[10];
3 t) N/ O4 [: k                        output += mmc5.Process( 1 )*vol[11];) z, F4 ^0 Z4 X5 V4 F) L
                        output += mmc5.Process( 2 )*vol[12];
$ Y& t7 W, }5 Y3 t9 |                }
. w" R  Y" n0 X5 m) ]7 Y# u7 b                if( exsound_select & 0x10 ) {6 Y* j- y6 q1 n8 q2 `% m% b
                        output += n106.Process( 0 )*vol[13];0 \) i. M! f( L& `1 b4 {# m/ H
                        output += n106.Process( 1 )*vol[14];8 H* i- _- N' Q& _0 n3 y
                        output += n106.Process( 2 )*vol[15];1 z# E- ~; r% C: X
                        output += n106.Process( 3 )*vol[16];
; ?7 f8 N% M7 d' G                        output += n106.Process( 4 )*vol[17];; ]2 l+ F. z& _% h- K0 n6 o
                        output += n106.Process( 5 )*vol[18];: i9 M3 Q% Z6 }0 Q* n; @* b( ^
                        output += n106.Process( 6 )*vol[19];
6 [4 ~/ u) |, V1 s" Q                        output += n106.Process( 7 )*vol[20];
- f9 g. w6 o" G9 j, }                }
6 ^7 `; z* k; b9 h2 L% k                if( exsound_select & 0x20 ) {" @% _2 `4 x, X, z1 Q
                        fme7.Process( 3 );        // Envelope & Noise
3 k- V- h% y* V                        output += fme7.Process( 0 )*vol[21];, D5 [! B6 c5 {: u6 U6 P4 N
                        output += fme7.Process( 1 )*vol[22];
% E- `$ g3 p; I2 n! Q) \: o) I$ a" R+ \                        output += fme7.Process( 2 )*vol[23];
& {9 G9 @* S% |9 `0 J  |$ v0 c; x                }1 I. L0 t6 V  r9 U7 S- [
+ |8 n/ e8 [8 V/ i6 I  `
                output >>= 8;  x3 Q' d% o2 G3 p( {

: h/ {  d) ~( D                if( nFilterType == 1 ) {
/ A3 h& K2 [) s: x9 R                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
, n3 [4 v' c  D                        output = (lowpass_filter[0]+output)/2;- }# F2 s* `/ o+ N" W1 p
                        lowpass_filter[0] = output;
; F+ w; |1 z' g! D& d# \                } else if( nFilterType == 2 ) {0 t: L9 D. q$ J3 A" N
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)7 {8 ~2 @( ?$ {1 A
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;0 R, q/ Z6 e! l+ Q/ S" ]' ]8 i3 _
                        lowpass_filter[1] = lowpass_filter[0];
9 c9 C4 r* g" Z                        lowpass_filter[0] = output;
0 f" z% I6 u$ M4 f- Q( R                } else if( nFilterType == 3 ) {
9 b6 U' l5 r. I) F) X" e0 ^" ?                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2). y( L3 f2 x* C6 O% w& X- X
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;$ h: j$ O, R7 ]* j( |5 i0 G
                        lowpass_filter[2] = lowpass_filter[1];
, B9 o* i- s! H; L9 ?                        lowpass_filter[1] = lowpass_filter[0];4 ~+ o, t5 k# u  ~: ?2 y2 j# h- F
                        lowpass_filter[0] = output;+ m1 M/ G0 B6 p6 S. k' M
                } else if( nFilterType == 4 ) {* q  i# s5 c% ~1 M: Z9 r: _
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
  l1 M1 |8 O. V4 r) P                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;2 W, m) n" ^6 Q; k5 A5 m
                        lowpass_filter[1] = lowpass_filter[0];5 [- `9 o2 ~. w$ V# O; d& g
                        lowpass_filter[0] = output;8 @) u/ |8 }8 ]" F# T$ y
                }
; x3 f" p( ~/ z; _
2 Y# h( @* k$ _5 W7 \, M) r$ V: Z& e#if        0! q: m+ s0 s1 s  {8 h( F! o
                // DC惉暘偺僇僢僩* E  C2 @4 U+ n; a8 H8 h
                {
, I; |$ c% u8 r& o% `                static double ave = 0.0, max=0.0, min=0.0;
3 V# f( X9 J0 J" _# j9 X/ e, G6 g; e1 G                double delta;
2 {4 G7 b! f2 u: P                delta = (max-min)/32768.0;
/ i6 V* L2 j: b/ r  [0 H. h4 U4 l( J: l                max -= delta;" d' w7 z% k- H
                min += delta;
& \% |4 T4 k4 y, c  ~5 ~                if( output > max ) max = output;2 q# P4 a, a3 l
                if( output < min ) min = output;6 C  @1 o) u$ ~' J
                ave -= ave/1024.0;
* c3 f# B* S; p% }* G                ave += (max+min)/2048.0;4 `% Q( V4 {, D% o% a
                output -= (INT)ave;
) W* ], b9 g, C( K( O) ~# x* k5 b                }* D6 t- ?& [$ q- [% \0 }
#endif
* A" i' f3 p! m4 f* f% @2 t2 |#if        15 D" ?8 d; p4 z1 q* \- |  k& e
                // DC惉暘偺僇僢僩(HPF TEST)
" L5 G! [+ O% Q, p. V. Y                {
1 f6 e; ~# ?& z7 u//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);  \* x% y' p) \
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
; x; S& K) q; u* R$ v/ N                double        cutoff = cutofftemp/(double)Config.sound.nRate;9 x# W/ q+ L6 M! B" J( Z- p
                static        double        tmp = 0.0;& F3 x% G# N; @* L7 \/ {6 q
                double        in, out;
+ F/ [3 ~8 R2 Z. @8 m
6 ^' y' L( }, P: b4 m0 x                in = (double)output;2 W; I/ q' B1 h* d
                out = (in - tmp);+ V# [3 d8 L5 O# Z; @7 z
                tmp = tmp + cutoff * out;" e% H& S- e& a- h2 O9 @: T
; A) U0 D8 d( N4 z. V$ }% {; g( p
                output = (INT)out;
% A$ @. t% N4 I                }8 y5 W5 i: M# @9 q9 u# j+ x! C
#endif
  D" a; O# x- ]. ~#if        0
" T6 o1 l3 P. R( a& m6 Q                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)9 _. M: F9 e. @
                {
3 e" j* U, [% m: h                INT        diff = abs(output-last_data);
9 ~, X# N4 u3 B6 W5 \5 u                if( diff > 0x4000 ) {
9 c" J1 J* ~) n2 B6 i                        output /= 4;
# z% @" i0 G, f& U0 _' r: b  m                } else
- N  x+ J) z/ u. l3 N* }                if( diff > 0x3000 ) {" X3 k" |7 s) Y, V, r4 U. A# K
                        output /= 3;/ O/ M$ T" Z# Z" @; q
                } else# l& s6 u! p+ X$ l! M6 y
                if( diff > 0x2000 ) {
  U. {5 n% K+ V& _# v( b; _- K                        output /= 2;
8 j& z( ?) j/ m( R                }7 x, Z. m: ?1 n$ K6 u8 K: O
                last_data = output;7 O/ O. H; S$ b1 Z9 C* j& t8 R
                }8 j' y) j$ ^% w) D& V
#endif8 M  x# i4 g* y& j
                // Limit
. K$ @) |! T( B3 Y3 K- v                if( output > 0x7FFF ) {6 z; y8 h3 `5 A* q2 s
                        output = 0x7FFF;$ A' p& g" d: |! h
                } else if( output < -0x8000 ) {
9 V2 b( V: Q* ~) G" W5 H                        output = -0x8000;
& S* Y; C# Y0 C" G                }
- o3 f2 P: f0 Y1 u5 g8 Y. M8 [
                if( nBits != 8 ) {
6 P0 u0 t" c$ G' l                        *(SHORT*)lpBuffer = (SHORT)output;
; j5 x  y& K& E  [" G4 f' ~                        lpBuffer += sizeof(SHORT);
7 v7 l; c+ ~9 F" Q! Z, [                } else {
, v# `& R" s7 `' f                        *lpBuffer++ = (output>>8)^0x80;; {* U5 \5 V' }
                }9 G% M9 F- y, J+ J* j  d
, A& o- p0 o& L: U- V; ^( ~7 B
                if( nCcount < 0x0100 ); C+ n8 b. F2 X6 v4 p
                        pSoundBuf[nCcount++] = (SHORT)output;6 W4 U5 W0 W6 I, @( n

1 c, e3 E1 N' v# [) ^% i9 M! f//                elapsedtime += cycle_rate;8 D; Y9 N4 r+ e2 e+ t; ]
                elapsed_time += cycle_rate;; ~+ q: W) X* j  z2 `1 D
        }  M8 V* l9 t/ i% {) X! y
" |* z5 e5 \) ~, L; _
#if        1
  u2 v1 l, e0 [: Y8 X, ~        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {, `  k# [" l) U& X4 {# A* x: r
                elapsed_time = nes->cpu->GetTotalCycles();
+ U/ L' X! j; `8 p& S        }
) b/ n/ R* u, S! v5 V3 @2 S! e        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {- i/ x5 m3 B" x3 B( ^5 ^6 r5 |
                elapsed_time = nes->cpu->GetTotalCycles();( m: e5 p: e5 Q; k1 H$ v
        }
% W1 Y4 v  D2 e% c" M" p: `6 D! b* r#else, ^5 V# n8 C9 s; {% |+ s
        elapsed_time = nes->cpu->GetTotalCycles();
, w% M6 F" U) `#endif" @; L; {; M. `
}
* |4 u  {0 ]. z
5 l# O; U* m5 C3 l1 f// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
/ V- f' ]9 a  WINT        APU::GetChannelFrequency( INT no )
( i9 Z( q2 R1 f: n( K" l4 t( l{1 O3 q$ i# R3 h  }1 X0 K/ v  h! B# \  b
        if( !m_bMute[0] )
! [& U/ z  s; `1 M' ]& R. f0 b* N                return        0;
* Z( ]0 d# g! K. Z. e  w  F* A) v" M2 `
        // Internal
$ M3 B6 D% w7 b( `( X0 [) i        if( no < 5 ) {! J2 r- d0 G0 s8 i5 X
                return        m_bMute[no+1]?internal.GetFreq( no ):0;: J. f- B1 F1 n! L
        }
2 F  F( S5 h4 J1 Z9 |. [        // VRC6
6 U8 \( M! v' S        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
0 h  k, z/ X" Z9 J" C                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
$ t/ D7 p6 g4 ]        }- V$ W  i5 V9 }" D( t
        // FDS
! F! m4 x5 e* [; r: \+ j        if( (exsound_select & 0x04) && no == 0x300 ) {/ [7 d/ J0 m3 `: P/ q. |& b5 m
                return        m_bMute[6]?fds.GetFreq( 0 ):0;/ r$ o6 r# u+ e  q* ?/ h
        }
  w) b: h" y. I8 C) C5 B- T        // MMC5
- b  Q2 n7 U4 o+ d- M  h& h        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {6 Z, `' O! M2 t# V* I
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;6 P2 j# Z8 g- i1 I& j
        }
6 E6 T$ Z) v1 h+ r! m$ v+ D        // N106
4 |+ r# J& [- I        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
. z! O0 _0 h+ y) v& B  m                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;5 w$ I* N" o2 B5 B
        }
/ @4 T- b  |$ U2 n3 \; w4 c        // FME7
" P* b% Y! {9 n) M2 \        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
& f! U; u/ \. l. w                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
3 n4 g- v' o3 a& a        }
! V( C, ~1 I& z0 D: D& B        // VRC7- |7 K- U( I  ]5 K. l3 P% T) L
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
. |# o2 I% l" O' @: ~                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
5 R" ^5 ]% c2 h( P0 S4 u* ]1 l' p  n, h        }
( T- u6 b' V1 J: o1 ]( k- `: P! }0 z( A        return        0;
, D9 J  o8 z6 x% x0 e}
/ O9 g: d- B9 C' H' l/ E+ ~# O5 v) O* X+ r
// State Save/Load# A1 T0 {# e4 c7 S! N0 @% V+ x6 q' _
void        APU::SaveState( LPBYTE p )
! ^  q7 Y3 m8 P8 h{% R: v6 ~4 y8 l
#ifdef        _DEBUG1 {- o/ C" r. M$ L  W  a* D
LPBYTE        pold = p;8 w6 k9 G0 i2 p2 D* D3 ]! q
#endif6 x8 [) h8 |9 M

# |) _% S) \% q5 s2 W        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞) Q, o6 W& [. `% Z1 g  j
        QueueFlush();: l8 Q' D: n" O/ _

  F! C) W, B! E: L! H        internal.SaveState( p );+ V  K9 g3 q/ W- B. K1 ^6 r  S
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding$ e. Y, y- X( _# W

% N5 x6 i6 l5 F: \        // VRC6# Q9 t* k, F- h  G
        if( exsound_select & 0x01 ) {
4 B% |+ l% F& o                vrc6.SaveState( p );  c" Q) E' N; c, X' D# d, B
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding9 J6 X% L4 }$ a* R" P' f& J
        }
- J' {6 y+ u& N& T% V; }  ]  O        // VRC7 (not support)+ C( c: T8 R1 B! m2 w# B
        if( exsound_select & 0x02 ) {. }7 T/ ~3 g' y6 ?
                vrc7.SaveState( p );+ T( ~5 `* S: j$ q1 {
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
+ e; H" K( j7 ]1 N        }+ n4 _% y3 K1 \' k, h3 o; H
        // FDS+ v; H7 f6 Q# |' b1 t
        if( exsound_select & 0x04 ) {' ]9 b% W2 e' J  O4 A' ]$ j# E1 ^
                fds.SaveState( p );
! _! B) N+ }& ?0 Z8 J% C( q                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding* g$ f) [1 S& A2 i# F
        }* M- |7 j2 t  A. v- ?; o
        // MMC5
; m/ b- p2 `4 G5 ^" H        if( exsound_select & 0x08 ) {& T/ X5 d+ t- Z7 h( O
                mmc5.SaveState( p );
% c$ G: ]/ W/ i+ T; j2 q6 H: N                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding  q4 f3 [3 [; r) `1 G8 y' k
        }
  k4 G4 T- D5 E' w        // N106
6 i+ G/ p) J- ]& q" B2 W        if( exsound_select & 0x10 ) {/ ?" d; T: j7 q& Q& ]$ ^
                n106.SaveState( p );" S/ h: _; W- n* @
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding0 b9 ]7 h5 {0 Y; c% R0 G
        }# G7 O; p3 k( }2 P$ j7 |
        // FME7* J( s  C- H! Z2 [
        if( exsound_select & 0x20 ) {& C# u0 n0 l! O- S
                fme7.SaveState( p );5 g' v( d: I; R# V0 A( [
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding$ T! J# ^" W; \# l- z
        }7 J! S/ X3 a/ D" f0 w5 `' n5 b
' E' A7 L. ~! {4 N
#ifdef        _DEBUG" m/ Z) X- [1 Q0 A( _, T9 L
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );4 G; X* o* |0 n: x. K# x
#endif
' ~% ~! z9 R# Z, n+ U* w  m+ ^}
- F7 F7 u) R" W* f/ f; ]- ?: Y  G+ A* S- B* d
void        APU::LoadState( LPBYTE p ), r0 q0 m6 }( d2 ~' _2 S
{
7 _, A& @6 l, }9 K( A7 i5 j        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
' [* k% v( r3 Y4 i- m* j8 G, j        QueueClear();
# x8 U: Y5 k6 D0 D% |2 L6 c3 y
        internal.LoadState( p );
5 N# C  C+ W/ z/ W& t9 v; x/ K! i% v        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding! n9 }( v$ j0 L+ c. l5 v8 X; u

5 p( `+ ?* [. M2 R& l( k        // VRC6
! ~5 [" _1 D7 [* a; k( T& w        if( exsound_select & 0x01 ) {# O4 H6 R, |6 u/ S/ z! P& \
                vrc6.LoadState( p );8 i4 ^; H/ w1 e) R
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
; ~* ^6 z) R6 i; z4 F5 V( M. T        }
/ k5 t9 H( v4 _! H        // VRC7 (not support)% v) l, |( X5 Q& B) V
        if( exsound_select & 0x02 ) {' I1 W. b" _, m6 \9 N8 V( N4 a
                vrc7.LoadState( p );
0 A/ S1 L9 o) u                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding7 n+ k. b4 ~7 a8 ^1 h! v
        }- x3 _% P( r5 i" L1 D% ]
        // FDS5 R5 v& I4 I# x' s1 `
        if( exsound_select & 0x04 ) {
" w; x5 |! D5 P) [+ p$ W( C+ }; p                fds.LoadState( p );
  G* k" q& O+ R8 @7 [7 X                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding$ |; w8 F0 G" `
        }" n5 ]0 \0 b6 n4 Y9 l
        // MMC5
1 O; H- T/ Z& w- \; G: z        if( exsound_select & 0x08 ) {+ u6 ?" l2 @9 U
                mmc5.LoadState( p );
% s) g/ a8 e0 {8 r4 {                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding. K: C  D0 _: E0 M( E2 ]  W2 }
        }
7 }3 g9 t' |" @' i2 a5 Z        // N106
  q; g# l) |; P" B* Q        if( exsound_select & 0x10 ) {5 Y3 j- `6 G  ], Y
                n106.LoadState( p );5 I! x5 T; s+ O( ?# p! w# f
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding% H  @, G4 _" ^
        }
/ B* a$ b: A8 p        // FME7
( B" [. U* k4 ]: }4 q        if( exsound_select & 0x20 ) {. h( u0 D. S( J: j& d
                fme7.LoadState( p );  a, }0 C% K) g2 B
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
7 z: \6 ~1 K& G' I        }
! f# N: X. l) L/ }  q}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 " y8 j# r) D" k$ `, W: z
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
! C9 L: ^7 a* z& c& r感激不尽~~
! v4 N. i- q0 u2 _) ~
恩 我對模擬器不是很有研究,, N* S, F% U3 _: A
雖然要了解源碼內容,可能不是很困難,! f" I. j& D8 ~! o4 V
不過還是要花時間,個人目前蠻忙碌的。
0 k# K, q* M6 r. P4 ?& a7 |
* c, W  i( T; w給你一個朋友的MSN,你可以跟他討論看看,
& `% T( [6 D5 F; G; n他本身是程式設計師,也對FC模擬器很有興趣。1 i) f9 {6 H  L1 a7 f
0 Z+ j6 e2 f! g  h% v0 B
MSN我就PM到你的信箱了。
4 x  S' }+ S4 n/ c8 k% F
) m8 f1 N2 {4 h) y  i希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 ! _$ h! B5 @- O' Q' a; N
呵…… 谢过团长大人~~
( V* J( J2 z* i! C, A, p# s
2 L$ I; ?6 o  T# {* j
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
8 p8 h: ?6 f) i, B% ]团长的朋友都是神,那团长就是神的boss。
- u! b3 d; E" }5 O6 k9 C
哈 不敢當,我只是個平凡人,
) W7 \% I7 T  o9 F; ~1 u. m要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
+ t! ~$ q6 X" v& Y* y% X$ i, wZYH
4 w: {% K' T* Q+ A# TQQ:414734306
! V0 {6 n1 i+ h5 W' m, A  f5 y* RMail:zyh-01@126.com
5 M7 {- c4 P0 z7 l/ g. e' D) Z& g0 @
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 . I; s5 d% @. T% n
再次对团长大人和悠悠哥的无私帮助表示感谢~~
) }$ a' Y8 j9 ~! r
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-11-30 17:32 , Processed in 1.087891 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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