EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
% f; G5 [1 H9 {1 D2 n楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
. i' X4 |- \$ h6 e+ `! o. }这里有相应的模拟器源码,就当送给大侠了~~1 {, ]8 g' f( \6 x
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 1 D& G) f+ c# |
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
" k6 R, k! B& e3 |7 O+ n9 [楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
" k% M! y' S  e& y" ^这里有相应的模拟器源码,就当送给大侠 ...

. z% y6 J6 `) Y( v. V& v( b聲音部分(Audoi Process Unit = APU):
5 u  h, @. a5 b  Z1 Z) t: I.\NES\APU.cpp
0 }7 x4 e- `3 v' g2 D.\NES\APU.h' q! E* B( P6 g5 L+ O

& c0 ]' T' ~* Z8 V5 I
" |$ P: d6 o, R0 ?7 ]6 {# z3 Z影像處理部份(Picture Processing Unit = PPU):! X& u) e2 I% s( D, B- m
.\NES\PPU.cpp5 B0 `4 N, h, m0 U9 c8 c
.\NES\PPU.h  R; N# b& N0 U+ j. Y' Y
3 }% y& K0 A5 T3 L$ J" L; n3 J2 m
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
0 J" ]) j+ y6 V: e+ a(由于很多专用术语和算法机理都不明白,所以看不大懂……)2 a' j7 _. R  [0 v; v7 H3 }0 _! c
//////////////////////////////////////////////////////////////////////////7 B" Y7 Y9 g5 p. v  r
//                                                                      //
, I4 f5 V- R$ D6 C  [3 O//      NES APU core                                                    //$ I  _  @: @6 A
//                                                           Norix      //0 Z  I3 R( ]7 H$ @) F3 W
//                                               written     2002/06/27 //- X4 f& ^7 `" a3 m# O2 K- M
//                                               last modify ----/--/-- //9 }/ u5 m4 q/ |5 z* {
//////////////////////////////////////////////////////////////////////////
: B1 ^7 }  ]' }, C3 X#include "DebugOut.h"3 I4 b- _& h" k7 @! Y- S, v
#include "App.h"0 G# N) c4 @  Y: s% M9 N  V
#include "Config.h"
2 l( Z7 S' p: _2 _2 g9 x. {! p5 {+ X9 J8 s2 Q# E
#include "nes.h") n- W. ~2 Y) @/ D& |
#include "mmu.h"
! {" o. W  _' D& i#include "cpu.h"
  ~5 i% J' p* A! ~( d" Y: m  R: l2 z#include "ppu.h"
0 h( c, y3 ?2 _. @. K, E  R: r#include "rom.h"9 Y8 ~- H5 C6 C# W! r' D" j7 I7 t
#include "apu.h"% y' u2 f8 K' Q0 F' k- B: b' Y) U- N
  b6 ?4 u, w0 N$ [6 b+ }. j8 u+ Z5 e
// Volume adjust
4 T/ ~9 w  Z7 u+ i3 V/ k- R// Internal sounds* H9 c. i. a1 X) u* N
#define        RECTANGLE_VOL        (0x0F0)  Y4 Y- h& }7 W
#define        TRIANGLE_VOL        (0x130)
  O1 U9 h4 [, u#define        NOISE_VOL        (0x0C0)3 j9 J$ s- O8 m9 N. P$ t# P: J
#define        DPCM_VOL        (0x0F0)* b  x; L. l! A) `
// Extra sounds
* r3 G- @$ f; ?  e9 p- {$ y#define        VRC6_VOL        (0x0F0)
7 b: R4 t* f5 Q$ G: j  P  J" B5 x#define        VRC7_VOL        (0x130)4 G. K9 M' Q$ d$ |& l
#define        FDS_VOL                (0x0F0)
3 H. o( B1 [1 @, o* ^2 Q; d#define        MMC5_VOL        (0x0F0)% q$ `" |) T6 ^6 T$ H
#define        N106_VOL        (0x088)
; W! ?5 n8 F' t2 R6 A: D7 i+ b! f4 X2 f#define        FME7_VOL        (0x130)
  R1 f3 R+ p: Q" [) w- Y& U" g& `& o6 ^. n/ u1 U; E/ J
APU::APU( NES* parent )
' H5 O6 D+ U6 B$ r$ t7 ^+ T{  k& G6 k  c% m% r5 Y* o
        exsound_select = 0;. M* l1 g! X& j7 X; u0 F

+ Y5 Y+ W: ]2 {        nes = parent;
8 j8 C( @2 |% ^4 g4 {4 e0 u6 T        internal.SetParent( parent );: U" r7 b) N) C8 O9 C. @

+ k$ K, r8 n5 }+ a# T        last_data = last_diff = 0;
# L# \2 L0 k1 Z8 p, @, L  E1 r; M; r
1 x/ k9 Y4 L2 G5 \- n        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
$ G+ D5 c- o  v! G
) x/ I* {$ B- A  A* i" U) a        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
7 U/ m/ }( {: y- b) L5 }        ZEROMEMORY( &queue, sizeof(queue) );
9 p$ _6 I3 m+ m. z4 m) Z: f) z        ZEROMEMORY( &exqueue, sizeof(exqueue) );
9 `% a' J  |& @+ }
& m! ?1 ^, a1 Q        for( INT i = 0; i < 16; i++ ) {
3 t0 ^  o; ]5 _3 N* F) J! N6 T                m_bMute = TRUE;
8 t- \; f  F# \0 H7 U- m        }
& O$ Z0 L# Q  X. ?}5 a9 {+ V$ j3 b( B, X- ~
0 Y5 y4 d+ W4 _
APU::~APU()
7 \6 H0 {6 J3 X1 O/ u, P7 b{5 c6 I# h! |0 K% R% X& c1 W
}
! t0 d2 s0 m# m1 G
( Y$ ^: ?+ U- Q  ?/ l! ~- {void        APU::SetQueue( INT writetime, WORD addr, BYTE data )' U& R9 w: E; K  m( Y3 o% @1 [6 ]
{; h3 j& c! J7 _  O( G
        queue.data[queue.wrptr].time = writetime;
- m3 Q) o( U& k$ i" t7 R4 f. C8 W+ \        queue.data[queue.wrptr].addr = addr;8 Y7 ]8 m3 R* S- w& G" e
        queue.data[queue.wrptr].data = data;
/ q8 d  o- H. [& B: J        queue.wrptr++;
: {/ X- U* \3 n; M, F2 O        queue.wrptr&=QUEUE_LENGTH-1;
/ N: R: C* c( u        if( queue.wrptr == queue.rdptr ) {
8 V! v3 P2 O2 @$ Y9 k                DEBUGOUT( "queue overflow.\n" );
' J, ?3 h+ j- N1 N# J6 _& D7 |2 L- \        }
! S3 f6 Y: s1 C% W9 `8 g& n3 S) f2 W}5 @) @; U1 c8 K  _$ V* _/ L: }

( ^: g0 q( ~& j; B3 kBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
3 Q. ^) s" _. }* H; k) m3 x, I% \{
' i6 Z% s- t6 _8 B3 a        if( queue.wrptr == queue.rdptr ) {
) s  T# ^) c1 Q  i, d; R! O, b                return        FALSE;8 T. g8 r" J7 j7 B( W0 U+ V8 k1 [( `
        }2 f/ C7 B5 o' M! u1 \6 y9 ?
        if( queue.data[queue.rdptr].time <= writetime ) {
$ `4 L8 N0 r7 ^- T# Y/ f                ret = queue.data[queue.rdptr];% O0 J9 M7 H2 e$ p0 P5 A
                queue.rdptr++;
3 ^, r! ]6 g: O5 P( d                queue.rdptr&=QUEUE_LENGTH-1;
/ `0 v' T  Y% \, R( A+ s. d; [                return        TRUE;
; ~# I8 o" A3 e+ D' u( n        }2 R' V2 V5 x8 Z* M  {
        return        FALSE;# A( k8 o7 c, m2 \  ]! p+ M
}: F& [3 K3 B- U7 \8 n

- D% }; X! q8 r/ d# ^void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )2 |4 u7 M* y3 M+ u5 `
{7 D! R( ?8 c5 A) u7 O' q
        exqueue.data[exqueue.wrptr].time = writetime;
" E6 w) a1 Q; C% R6 O5 W# W# s        exqueue.data[exqueue.wrptr].addr = addr;1 _/ m8 z* f. k; e0 m/ q
        exqueue.data[exqueue.wrptr].data = data;
  \5 m' e3 J/ N4 o4 i$ m4 n8 J        exqueue.wrptr++;4 n% z, h7 x: S" Y/ J( J# r
        exqueue.wrptr&=QUEUE_LENGTH-1;
* s8 M$ y6 ?, G# }6 Y) o# {1 n; d) C+ z        if( exqueue.wrptr == exqueue.rdptr ) {
/ x& c0 e" E0 Q                DEBUGOUT( "exqueue overflow.\n" );1 i( N8 @( p) z' y' x
        }
, O4 V0 ?( J; }8 ^+ B1 d* `% x* B}; a. O6 G- X) H3 }" h

0 U  g" x0 H# b2 X& z) IBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )" a; T2 |  m2 [5 o
{
0 @% X- ?4 `( n5 Y6 `        if( exqueue.wrptr == exqueue.rdptr ) {
, E2 v1 N0 O+ ]  l$ B7 W8 C. r" f                return        FALSE;
9 P& ?% `9 U+ A& P; F+ [1 n        }- W2 a8 Z7 {0 m% Q6 Y5 \- j4 W
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {4 ?5 J& @  H7 F) g1 s: s( _; z, l6 b4 U! G
                ret = exqueue.data[exqueue.rdptr];
+ m% c" [5 E2 Y                exqueue.rdptr++;* T' P# J, j4 n
                exqueue.rdptr&=QUEUE_LENGTH-1;6 u& o! N5 H% w
                return        TRUE;
, u4 Q9 Y$ `2 |0 g# w/ ~        }" P! M, I" j/ s& |( u) m
        return        FALSE;/ ^8 a' w- }4 K3 c
}9 H5 N, q- k( C3 E8 p$ p

$ d2 J, k* h: E) p9 B$ ]! N2 svoid        APU::QueueClear()
* q- k7 `7 P! k{
  U- _& ~1 d- I( A# v4 B% G; i/ r        ZEROMEMORY( &queue, sizeof(queue) );. g8 v4 O7 {; u' N& p$ ~" f' q
        ZEROMEMORY( &exqueue, sizeof(exqueue) );" C$ Y3 ]1 Z, {" B0 N3 D% B% t) ^
}5 r, r! w; _  ~  A. l5 Z

, n7 ]/ U+ j8 s4 N, y$ C3 T! }# Yvoid        APU::QueueFlush()
, A. ]3 X8 o$ a! N% q{  U+ [! p6 ?9 s( w
        while( queue.wrptr != queue.rdptr ) {) N" w+ q' O$ w; h4 u3 t
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );% A3 G0 f  x5 s3 ~; ^5 ]; h
                queue.rdptr++;; |* g( t. X' E/ i# Y5 {/ N
                queue.rdptr&=QUEUE_LENGTH-1;
8 y& J3 T, E; o        }: ^$ J1 A/ P; K9 y7 `5 H  |; w7 m
) d) S4 i4 f; @
        while( exqueue.wrptr != exqueue.rdptr ) {4 {3 h, I5 ^# }, N
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
8 N9 i* n7 q' a1 x3 K                exqueue.rdptr++;
. r) T' g* J9 w- R# }7 x1 b) B/ X                exqueue.rdptr&=QUEUE_LENGTH-1;
* H$ z$ D8 `) e) l2 s1 W( a5 D0 X        }' ?/ C/ n" D* `' n  `; U& s
}6 `0 Q% }0 s  d$ @

" x; E& y( R/ @+ ~1 h' gvoid        APU::SoundSetup()
* N" V0 t! X" }& ]3 g{
, J6 a9 p. K2 m& l        FLOAT        fClock = nes->nescfg->CpuClock;& o7 |* M+ `; b2 H9 p5 p
        INT        nRate = (INT)Config.sound.nRate;( q: c' p0 d0 e) r1 k6 {
        internal.Setup( fClock, nRate );! {) B  P( B: }% X$ `% r* m
        vrc6.Setup( fClock, nRate );
5 Q# J( f: P$ P, |1 f/ Z* n        vrc7.Setup( fClock, nRate );
+ v: u  X* T  R. g, e" Z: C# Q        mmc5.Setup( fClock, nRate );7 s; _; {- B: G
        fds.Setup ( fClock, nRate );
8 p- L- f4 Y! g2 l% c/ G  C        n106.Setup( fClock, nRate );' G, \" d! m1 b! P
        fme7.Setup( fClock, nRate );4 f) z* i% y) C2 I
}# _7 S. }9 I; y) W

* i6 f2 I5 N  e  Q" w& Mvoid        APU::Reset()9 |9 v" v# U; W  M
{
: }; J7 t) [! a6 g, X- k$ ^        ZEROMEMORY( &queue, sizeof(queue) );
* K  x7 x: Q( o7 j        ZEROMEMORY( &exqueue, sizeof(exqueue) );
# k/ Q& K+ i- b0 h+ Q- y0 W- V& ?
! N3 t7 d7 I# m2 i" q! a        elapsed_time = 0;
. g# E& q6 K1 S, M8 {
) g! X; L8 X+ A' P+ [        FLOAT        fClock = nes->nescfg->CpuClock;' g8 g$ f2 c; s- z/ D- O9 T
        INT        nRate = (INT)Config.sound.nRate;" @: Q3 `* W0 d& G
        internal.Reset( fClock, nRate );8 i* f8 W6 o2 G  s* ?. [
        vrc6.Reset( fClock, nRate );7 ~+ B6 ?  k# S5 M6 m; P
        vrc7.Reset( fClock, nRate );3 _/ ^& x3 K- X+ o9 O7 z* C
        mmc5.Reset( fClock, nRate );
$ J4 N8 q' z3 L% M4 H        fds.Reset ( fClock, nRate );
  |6 h  Y9 s# X1 d. Y( P2 z/ G        n106.Reset( fClock, nRate );
! c( w: {  ]% M        fme7.Reset( fClock, nRate );
  P% w7 M/ R1 F$ v" a& u. k+ b# ^' ?6 j8 g9 f  o6 @
        SoundSetup();) ^' t0 F, y: L. M8 Q$ Z5 E' u3 k' @! ]
}5 P- g/ b3 V4 q9 K

0 c, y  j3 U  Q. i. ?9 w5 |void        APU::SelectExSound( BYTE data )' e/ q9 I& {0 q' E( @. |" U6 R
{
  s6 c+ }) s4 b+ g0 y+ C/ b$ i        exsound_select = data;
  ]" P' e4 t1 U" K$ b& B}
9 h. X2 [/ n' R! x. ]7 {
) m- h/ t' J- F3 z9 Q5 ABYTE        APU::Read( WORD addr )
& d- |" i7 s+ n# B/ r- p{- }. Q6 j  x; h5 X) W2 c4 j
        return        internal.SyncRead( addr );
6 O" q/ R/ l8 Y2 [}! ~6 V8 n4 s4 f5 o, P
3 \& k, \8 L9 M3 D) q7 p
void        APU::Write( WORD addr, BYTE data )
7 l$ b6 H9 j) t- o: j{4 t* G% Y. C5 C  j- x
        // $4018偼VirtuaNES屌桳億乕僩4 P9 N  h# a  f7 E
        if( addr >= 0x4000 && addr <= 0x401F ) {
% R$ a3 b7 z! n$ [( h/ v" N: a                internal.SyncWrite( addr, data );& e. p/ R+ w% i$ ~
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
% ]8 c+ d9 {3 E" G2 _        }  _/ q. B. {6 b) X
}$ T) c; d" n; o. P1 U3 h2 y( P% `

3 T. `" a, a1 Q0 A% y+ j! bBYTE        APU::ExRead( WORD addr )6 o1 B( x6 e  \
{) o2 \: o" u0 r0 h( b
BYTE        data = 0;
/ u9 }3 ~2 u2 O  q/ w) F+ I: Z1 s5 T- A* t0 s& ?
        if( exsound_select & 0x10 ) {
, Y! [8 C2 t5 u; Y8 O' m                if( addr == 0x4800 ) {
- a  A6 b# n- j- ?$ \5 u( u0 n0 R                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );  F1 L. u4 G4 M) V& [) v2 ?/ W
                }
5 t7 R" R  E4 K        }
* W! L2 }  U# ^        if( exsound_select & 0x04 ) {
7 e& M/ \1 |# l0 [                if( addr >= 0x4040 && addr < 0x4100 ) {
7 l! X6 g) f* x* k, m, j, \                        data = fds.SyncRead( addr );, S4 Y* d$ n5 j) ]( s5 i( L
                }* r% _9 C( a$ i0 @
        }8 K8 ^# a6 y' j: h4 A
        if( exsound_select & 0x08 ) {% Z* x8 `4 Y6 j0 y# k7 ~
                if( addr >= 0x5000 && addr <= 0x5015 ) {
/ F/ ^# f; g$ w% [. h: Z3 H+ U9 w4 T( r                        data = mmc5.SyncRead( addr );
( A  P% a; ~( [( u3 L                }
  c# m( e7 s5 O# p7 Q4 C: B$ K5 w        }" D; }- P* S4 c* r" T4 g
% e3 [6 s* W5 `$ E2 O7 s$ ?8 W- G" I
        return        data;
( B0 a) ]7 P9 \# Y4 M+ x2 c4 O}4 H5 z* n; \. ]2 J' y/ A
" w: _# a" O0 H
void        APU::ExWrite( WORD addr, BYTE data )
6 J2 U+ a. W  [" d! ?. [" D  s{( G3 _5 R7 b" a; k! x) U0 y
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
( e/ r' q7 k) H1 x* H
( \* ^* P8 H& `6 e- t+ r+ B        if( exsound_select & 0x04 ) {
8 }  c. z$ y0 |. N& T                if( addr >= 0x4040 && addr < 0x4100 ) {( w" }, `1 S+ }! {9 O( e! [8 q( k9 i
                        fds.SyncWrite( addr, data );/ n, R/ C4 m9 A6 `0 m
                }' p1 A' w7 |6 m7 [$ A) m
        }. P: y; T3 t" U

( J2 ^( I5 R6 R) u( A* ]9 b/ S        if( exsound_select & 0x08 ) {7 G6 T/ V" `% c. b: c1 {2 b
                if( addr >= 0x5000 && addr <= 0x5015 ) {
* o3 c1 N) Y1 E, i                        mmc5.SyncWrite( addr, data );3 w. g. g. Z; N+ ?" ]: k1 Q6 r& o
                }
- k8 s* \! l3 J; U        }. a/ L# }6 y1 P, V) W: |
}
' B9 B2 B( I$ z8 j% j9 x- c" [3 N. H. k; j  r$ O$ E9 u
void        APU::Sync()4 f0 V" w" T/ O8 B) V
{
' ~, S" t% L. q4 P( q4 s. x}
: P, e: n  p9 X# i' \7 f, ?' v
2 k7 [0 Z) L- ]+ K: k0 K$ `1 Tvoid        APU::SyncDPCM( INT cycles ). N0 w3 K( O0 b! c7 q, [
{
, L+ ^; `, \$ G7 ~        internal.Sync( cycles );
8 o& r" m. E2 i& S& p
( Z; A( q5 c$ ]1 \( a        if( exsound_select & 0x04 ) {/ F; G9 j: Z1 R7 Q' h- q7 A  S
                fds.Sync( cycles );  C8 P2 {4 A& p7 U' h& S/ r6 l. d
        }
: `9 [2 s4 }9 k# {" o        if( exsound_select & 0x08 ) {
# c# c; c! c2 m" a                mmc5.Sync( cycles );
& F  `6 a4 [$ {        }# X2 @5 {$ \0 k1 w' _, a, H
}5 ?- F- U9 y0 ~3 F( v. ?$ t9 _

. @; P' b& D( ?void        APU::WriteProcess( WORD addr, BYTE data )- D7 B4 r) ~/ g
{# x) C. Y# n* n
        // $4018偼VirtuaNES屌桳億乕僩  e: u6 T% u: I
        if( addr >= 0x4000 && addr <= 0x401F ) {
( A$ n) z1 }) F                internal.Write( addr, data );
3 u: N( q. C3 Z% v0 Z/ p$ C        }
& w  _5 \3 G+ ~2 d" E}0 e4 h- |' o3 F  A
) J, M" F: K6 x9 x6 }) V/ e
void        APU::WriteExProcess( WORD addr, BYTE data )- Y7 j+ O. e" f" a% {0 y
{* ]; M2 A1 ~! C& H. A
        if( exsound_select & 0x01 ) {6 X, p, F7 n+ @4 T- P: q
                vrc6.Write( addr, data );
5 f# ]+ _2 d. w8 c        }# v& f& [/ N9 F! b5 V' }4 i
        if( exsound_select & 0x02 ) {. L3 ~- |: u4 t+ Y5 v0 v/ M2 x
                vrc7.Write( addr, data );
: K4 e9 r8 |2 }        }
; q0 c+ v  n4 ^" `* q5 d. \        if( exsound_select & 0x04 ) {
( V( ^, M2 _5 c0 ^' ]0 ~- d                fds.Write( addr, data );% A7 M1 W0 U: G: @( n$ L' k" @
        }4 l  C3 p3 T9 s: n
        if( exsound_select & 0x08 ) {
" X/ t" H5 D; @8 Z2 m- {  }                mmc5.Write( addr, data );; b! z7 |# D& Q( u9 Z
        }: B8 r3 X# c' p* V% q2 J6 j. S
        if( exsound_select & 0x10 ) {2 ?# H. B8 S1 ~: b3 I! B7 z. z6 ], q
                if( addr == 0x0000 ) {7 ~, R3 y: [, u& [. H/ B8 v6 P( l. {
                        BYTE        dummy = n106.Read( addr );
/ a) I3 b* A, o% w: l! i                } else {0 \/ F' q7 B) }' ?
                        n106.Write( addr, data );
4 Y# b; M; A. n; o4 K; w0 F+ R                }
3 k( P0 g: }" M+ \/ t* A        }
1 Q& f; w' ?! E" m        if( exsound_select & 0x20 ) {
9 Z5 N% x% g7 F" c9 V& Z4 k                fme7.Write( addr, data );! P4 O8 ~' P4 M5 Z; f2 R6 C! t; [' D
        }' N5 T. d; j0 l8 B) z+ @4 a
}
2 O& _/ G  w3 r* d( q
# s: U: m0 e: o1 X. }& ]void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
& F' Q( J' ?1 L& x" Z& b{
. c" E' |1 Q  qINT        nBits = Config.sound.nBits;
% |6 \) K5 Z% fDWORD        dwLength = dwSize / (nBits/8);
' O8 z! \: I+ x$ h( AINT        output;
/ @- E- c& E1 U6 V! v4 XQUEUEDATA q;; j! j2 \+ ~/ B1 o$ U
DWORD        writetime;
$ O/ ]( \9 _  d( O% A! z# R( Y8 R8 U- v! d
LPSHORT        pSoundBuf = m_SoundBuffer;6 E5 ~/ O4 l% p+ f, g8 z: m
INT        nCcount = 0;
0 S3 b: d3 u9 ~) b3 S% W5 `2 g6 U$ R) `/ f" ^9 b. G8 u
INT        nFilterType = Config.sound.nFilterType;2 s. W! M$ O: R2 H7 S* a2 u) }
8 i) E4 r% S5 S4 W# S
        if( !Config.sound.bEnable ) {
2 h1 W1 t% }0 J$ o, q                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );; x  N; X. O6 L4 H
                return;
& r: `4 ?2 @9 V) j7 K. C% b        }  o3 E& ~5 Y* g, n2 @6 m

/ J- w/ l  l+ C5 @        // Volume setup
/ M  b) H* P7 Y! ]        //  0:Master1 o( @1 o+ a8 H
        //  1:Rectangle 12 K( r5 y5 K9 y$ h% I) r; K4 l7 x
        //  2:Rectangle 2
7 Y$ `! c8 a" m( B0 n0 y        //  3:Triangle
, e  ~5 `5 P# b. ?3 O# L        //  4:Noise
# J; @4 J% |4 k+ ~: v        //  5:DPCM0 n5 |# s+ r) a
        //  6:VRC6
3 q# ?+ w- F! y  i9 ~; Z; e) K        //  7:VRC7
* k7 r1 H( l! V8 @; n        //  8:FDS
& a  j6 C* y% ?$ X1 f        //  9:MMC5
1 X: C( M, _/ S; f; i- K' G7 f        // 10:N106
+ S# G7 G% L* G) a        // 11:FME7
- v' M; G5 o) U0 w        INT        vol[24];3 j2 H" b# M, H( B6 Z- I& q: ~
        BOOL*        bMute = m_bMute;
! D/ R4 C. W+ ]. d* }( g        SHORT*        nVolume = Config.sound.nVolume;
4 r/ w1 n" G- |% @$ n2 `# E* t+ U# @4 y* r6 y
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;5 F: u/ {2 }! s- E5 t

" u7 A" Y, l8 W# ?! f        // Internal6 f& ~$ s0 A* _  e' O4 S) q7 L
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
6 k- N# {! t* B" T8 t7 r8 v        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
* j' ^  y  T9 p$ U% f+ x        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;+ R. a, a) Z, v7 i: y
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;1 C( ^1 F% s5 Q4 x: G, R
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;8 f7 m' A. ?/ J9 `4 l4 Z
. v1 d4 @6 t* s5 E8 X" M
        // VRC6: m- q: U0 y) K, O2 i1 W
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;4 L( |% y% O# j, z
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
) c0 Q( {0 `! m2 W( I; M. M        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
! Z* l8 R. V2 u, m, j; u$ @% M: [) J5 A
        // VRC7
) G" m& b8 ?, ^, `5 @& t0 O1 x, B7 u        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;  |8 `2 w5 d: J8 o4 J. b

7 Z! k5 B! h' q+ v4 M+ _        // FDS, M6 x* D/ W/ b
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;6 g. V! m0 ^+ B& U1 y, U
: t1 L8 k9 s, w9 _0 _* [" Q
        // MMC5
# a" c5 L* I8 A: ~6 \( x        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
1 x  Z  ]' k- p7 X$ Q: N        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
/ ]8 {% ~) B+ Q7 f; g2 K        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
$ z+ u; G) z1 L/ \. @' M5 s/ U1 j  x
        // N106. ~, s" N7 E5 c3 ^7 g
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;# M6 W+ @( a5 b5 ^
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;4 R1 i7 ^! ]6 w8 W3 l/ ]
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
' q& W* ?5 n; L3 G        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;" S- Y  r# ]$ S3 E( t+ W5 d
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ y  M1 @: w% r
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
2 G* b3 L+ h: _+ t        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
( k6 G/ P" B- X9 s5 l        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 e  d% k7 o* E" s0 u0 w7 `, B7 I6 l7 X7 Q+ p$ j* F) _
        // FME7
# P# C$ v4 s# e0 O        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
  J2 \6 J6 O/ [/ g% e% \8 y, b        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
4 E0 _, S0 h5 t' b+ r        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;6 ~6 r7 U9 N. g* }" H' A
# v7 e7 D  x: T" X( b) |
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;9 ]( z4 x. t/ X7 O) h
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;( ?& N9 p: r( P; t& [: b

3 d+ N& N+ R6 ]+ \; [        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟$ M! p! @0 s  g5 P
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {* m* x3 o+ V7 j9 X. {7 Y9 K
                QueueFlush();# i2 d+ Z& [) Z. }6 Y  u/ q
        }- t- H  n3 g7 Y1 z
! F& n  h4 d7 D
        while( dwLength-- ) {; U' K! O7 X) |% l6 C; d
                writetime = (DWORD)elapsed_time;
" P  O: C) }# V' v0 ?& M0 B1 Y& T' M* @0 r- }
                while( GetQueue( writetime, q ) ) {3 |$ U4 ~) v, R% R4 r5 l6 ~* f/ a
                        WriteProcess( q.addr, q.data );5 V7 O4 l# Z, J4 {! u6 f
                }5 E$ f. L8 S) C5 |

8 ?) o. M/ P( F2 _! c                while( GetExQueue( writetime, q ) ) {
8 f* M. z$ J* u. `6 j( e/ H                        WriteExProcess( q.addr, q.data );
; Q$ |) ]! f8 N, b                }
: j  o) g, J. ~7 s$ ]. i0 N8 l7 F
9 P  ]5 \* F9 ~( l2 v' \# W                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
: e5 Y$ s& b* C' ^                output = 0;: `6 N2 e1 |; F
                output += internal.Process( 0 )*vol[0];
1 P6 e% }; p. _2 K, H6 P5 O                output += internal.Process( 1 )*vol[1];
" k0 d9 M! E  t5 B. S. Q4 ?6 q                output += internal.Process( 2 )*vol[2];
+ g1 f/ u2 t+ d% B                output += internal.Process( 3 )*vol[3];
9 z2 E+ S1 `3 e7 ?* \                output += internal.Process( 4 )*vol[4];
- K! h) C' ^+ E! t: P" L' Q
: G) f+ I0 B, r                if( exsound_select & 0x01 ) {
6 Z, r5 o  W  Z/ G                        output += vrc6.Process( 0 )*vol[5];* L( s/ s! C5 A4 y
                        output += vrc6.Process( 1 )*vol[6];: t1 P6 ?7 G# {7 D
                        output += vrc6.Process( 2 )*vol[7];0 b# x% B- i8 ]# W2 Z
                }: k* V+ a. }+ B- {
                if( exsound_select & 0x02 ) {
4 T& C/ ]* u% V7 h8 m3 n                        output += vrc7.Process( 0 )*vol[8];
. w# D6 R. r6 o, i, n                }! ~3 a1 c  Q( M' `0 H. u
                if( exsound_select & 0x04 ) {, D' C# H  s% B7 w/ ~  ?
                        output += fds.Process( 0 )*vol[9];; y, c9 c4 ^. }/ A; f2 ?2 L6 i
                }
+ x. m& f- O" c5 M3 T                if( exsound_select & 0x08 ) {: D4 R/ V: R, z
                        output += mmc5.Process( 0 )*vol[10];
  D' Q) O# m  c) O+ D7 W' |1 @* r$ N                        output += mmc5.Process( 1 )*vol[11];& v0 d- b* c- M6 ~4 o" C9 [
                        output += mmc5.Process( 2 )*vol[12];+ U' Q; z, B! A! y! p9 q: ^/ C; n
                }9 i# ?8 J; ^0 A! x3 c  c
                if( exsound_select & 0x10 ) {- |6 l( G, S: ~
                        output += n106.Process( 0 )*vol[13];( w, f7 n9 h. M. O  T+ o
                        output += n106.Process( 1 )*vol[14];0 {) }5 v4 t) k0 n
                        output += n106.Process( 2 )*vol[15];$ _( }- R4 R( f6 U5 G/ A3 e
                        output += n106.Process( 3 )*vol[16];
9 n, d# r9 b8 n4 \% g                        output += n106.Process( 4 )*vol[17];) @8 i: o: n- e+ N
                        output += n106.Process( 5 )*vol[18];
+ d8 w. O5 v6 J, f9 D6 K) m                        output += n106.Process( 6 )*vol[19];8 L! l- l1 O4 \! Q, G0 F
                        output += n106.Process( 7 )*vol[20];$ b2 w/ I" o# n! |3 Y! D
                }
' t" W3 ^0 w- o# ?. f; U                if( exsound_select & 0x20 ) {* ?# U8 p; z: h9 {$ n
                        fme7.Process( 3 );        // Envelope & Noise
6 M- I/ L9 ?; T                        output += fme7.Process( 0 )*vol[21];0 B: o, o8 L% E9 W5 P
                        output += fme7.Process( 1 )*vol[22];
/ J2 d2 H6 c: X: i& n0 F7 @- {+ Q$ {                        output += fme7.Process( 2 )*vol[23];7 [& b' Q- j" f7 Y
                }6 h2 Y3 @, g. o

$ I7 G7 c" X' c5 \7 O- M: a                output >>= 8;/ k+ u. l6 C9 q1 Z8 Y

, E; H. I# q9 [' E" K- y  ?. O! E                if( nFilterType == 1 ) {4 y" ^5 A: f5 ^5 N& r
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)& e( p$ G8 \' A
                        output = (lowpass_filter[0]+output)/2;
' R; r/ k+ b# x; Z, y) a, D, O                        lowpass_filter[0] = output;  H) I- b& A2 i
                } else if( nFilterType == 2 ) {
8 S0 b$ v9 T5 f# [" Q% l                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
9 w* |  z0 o6 k5 y& U                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;; m7 B9 H. m; ~& p8 P+ t, ^3 V
                        lowpass_filter[1] = lowpass_filter[0];! P# B" @! e$ ]" p9 Y0 g. b4 ?
                        lowpass_filter[0] = output;
7 w( V( Y+ w: ~: v  z2 C                } else if( nFilterType == 3 ) {- ~+ p% w0 O: h5 K$ M+ a
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)/ L% I: z) }& V5 X8 t: Q" b9 p. f
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
2 H; X4 u) w. v. s6 d" K                        lowpass_filter[2] = lowpass_filter[1];8 C4 x$ t0 b9 B  T2 l( [% O
                        lowpass_filter[1] = lowpass_filter[0];( w% z+ h( j+ p9 W2 g1 @: k4 j
                        lowpass_filter[0] = output;
! f8 m* z5 ]6 G9 W) p/ k* V                } else if( nFilterType == 4 ) {
) S% y( `9 c0 R( L6 M0 U5 F  C$ h                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)- @& C( I5 L& h$ n3 p* m3 P
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;$ j% Y8 P9 k* ?
                        lowpass_filter[1] = lowpass_filter[0];* D6 V& N5 `; r  d: Y4 L; t! G9 `
                        lowpass_filter[0] = output;8 \+ D, N" Z0 e' F
                }
* }, `- N! R3 T) ~% q4 J3 R. ^- S& a. p
#if        0
1 g/ T. l7 s+ r* m, y4 _# m) G) E                // DC惉暘偺僇僢僩
3 W) D2 ]' l, c/ w  m. Z                {8 T! b" s" p: \3 u5 u, K0 e- N
                static double ave = 0.0, max=0.0, min=0.0;
/ z; O. D) ^+ C- u8 }/ _0 b4 D/ t7 l( b                double delta;
( B2 p5 t2 l9 B( f% z+ M                delta = (max-min)/32768.0;
! q" B9 d1 b8 l6 m5 S4 h5 I0 ]0 i                max -= delta;8 h% A0 k4 L) o0 q
                min += delta;; G# o4 [$ s0 `" {. h9 \
                if( output > max ) max = output;1 Y! u+ J" x" c! e% k% c" A% H7 j
                if( output < min ) min = output;
( n8 I' s7 m% l, i, \5 R                ave -= ave/1024.0;! N/ A" A/ J7 u  R! _+ H, T1 w
                ave += (max+min)/2048.0;
3 ~' h8 b1 @! z; _$ X! [/ k                output -= (INT)ave;4 N. c- V9 Z. X% e/ N5 v3 Z
                }2 l/ q6 j( m+ I6 V; e
#endif" @6 z2 w  o+ i$ F6 N& g
#if        1
- E4 s" c2 F9 E2 ?' S$ O4 F                // DC惉暘偺僇僢僩(HPF TEST)
' n% n9 s5 x0 h3 k2 R                {' \+ }: I% j5 @" ^
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);. A3 N% A1 E2 y+ G: I- K# I: A9 p
                static        double        cutofftemp = (2.0*3.141592653579*40.0);/ i3 V0 J  F+ w
                double        cutoff = cutofftemp/(double)Config.sound.nRate;/ `. C( z5 D0 ~/ J$ d* Z
                static        double        tmp = 0.0;
. U/ H4 r, I& O$ J' T                double        in, out;
4 G8 v% Y% z! n" d4 a" O  A! H
% f! D6 E/ V, K7 ^                in = (double)output;7 x4 }0 Q5 q& l! ^' b, d, }/ M$ K
                out = (in - tmp);* P) u1 C! M, ]$ l  q$ \3 a
                tmp = tmp + cutoff * out;
$ S  ?6 n0 i* T7 b# \+ F' N- k- }" W  O) F( `9 L: w8 e/ ]5 ]
                output = (INT)out;
" {/ B7 ^% B1 q3 P( C3 a1 z) j                }
( h4 h4 b* Z8 y- m#endif2 _1 M, u# r7 {, T5 _! I: H
#if        0# Z. A6 \- N4 S
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)# C( S" }7 W% A% g: o" `, B9 |
                {$ i! J' m, y/ n! m3 g0 J1 Z2 w7 v* x! K4 @
                INT        diff = abs(output-last_data);) \/ h$ S0 z9 b! }" B% T
                if( diff > 0x4000 ) {
8 g& A! q6 X; B                        output /= 4;
1 }3 }+ g8 \4 U3 f, i                } else
; w# Z8 b( x! P) w. K" Z                if( diff > 0x3000 ) {
3 h! x& R" e: A4 q* J3 A                        output /= 3;- k5 y7 ]6 o$ y3 H  o
                } else5 j: \! e. f0 N8 r5 h
                if( diff > 0x2000 ) {# x* a' A* ]4 W+ B6 O3 Y
                        output /= 2;2 r/ ~1 E: o3 {& F$ S$ y) T
                }! [0 K) g# u9 Q
                last_data = output;
6 v$ x# ?' S8 M" |- z3 W" x& j                }" {$ y+ J! u+ \
#endif
, A2 ^9 G. `# \/ k4 @                // Limit
6 s9 o8 @9 j& s2 ^- z                if( output > 0x7FFF ) {( E0 S% r" n) }# K
                        output = 0x7FFF;% C6 i4 c5 d0 R! x  B; e
                } else if( output < -0x8000 ) {
1 G0 o5 S* @( j4 K4 s4 L                        output = -0x8000;
3 u$ ?' z& a& i8 ]% i: A                }
- j  ?1 A3 U, y0 e
* b& u3 a  {# n3 }7 R7 ]                if( nBits != 8 ) {) c0 X* W% a% _+ u
                        *(SHORT*)lpBuffer = (SHORT)output;
2 D2 U: _! e* _: O9 |  S3 O                        lpBuffer += sizeof(SHORT);
0 c4 n/ n- h9 d. w                } else {
5 H& C( X  l' _0 B                        *lpBuffer++ = (output>>8)^0x80;
) a* |+ x1 X/ D7 g1 w                }
4 b8 e: t# V0 k# u8 S7 f' N6 r  {; s  ?# i( V& S! Q
                if( nCcount < 0x0100 )
! o0 r7 W) n9 p                        pSoundBuf[nCcount++] = (SHORT)output;$ m2 `% S2 ^% u: v9 `0 c9 u: v8 j7 \

/ z  v  i% q3 v, _9 ?$ ?6 v0 I//                elapsedtime += cycle_rate;
- c6 q7 O, z1 W8 y: @                elapsed_time += cycle_rate;( S) R! \$ f9 ]4 A0 C
        }
$ l: j9 f7 _+ f. C0 o0 R; N2 D! V9 }# x4 u9 K
#if        1
# g3 m4 c' @8 q  T        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {. r# x9 M. R7 M1 c* \  H
                elapsed_time = nes->cpu->GetTotalCycles();1 R, C9 N' }6 M/ h2 u5 d6 @
        }/ T; F+ B/ X* \0 X
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
1 N0 W  p+ a* x; ?" m3 L0 E( O' F                elapsed_time = nes->cpu->GetTotalCycles();2 t" l/ i0 t6 R) t
        }
6 G3 O# \; w! t6 Y- v$ M# m#else
' i/ }" N7 v4 k3 p  |# m        elapsed_time = nes->cpu->GetTotalCycles();1 f' r  Z. }8 v: V( c% I. m% w
#endif, i4 Y  p$ T! u2 h3 r& t+ f( O
}$ j$ X1 g% w% U$ W7 G; b
9 P: y; {; ~, I4 M* w: I$ G, ]
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
$ d9 I2 _7 V  d7 EINT        APU::GetChannelFrequency( INT no )
) E  b8 E: b1 Y; V8 A{) n# C3 A0 h) @
        if( !m_bMute[0] )7 n. q4 G/ ^. {7 S; v% `  v: i) X/ _
                return        0;
: z% d/ w$ n4 B& s1 M" M- g$ _) G; o4 m# ^0 v; ?5 `4 }5 q; `
        // Internal
- W3 A9 c4 }% h, J! S* Q' g; w        if( no < 5 ) {; U- ^; L: q$ c) j" o/ d& B
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
1 \; L4 g: Y% `) o! ?7 x  f        }
7 p: j2 b6 ]" ?, b- ~# m! P        // VRC6
) ^& f7 N) p; S        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
+ C% I: w% P+ U4 a5 L( E& D                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
# A; n$ H" v* H        }# _4 V5 c4 B- Q  I8 U
        // FDS* y6 U- z8 y+ P- L  Z: k! X
        if( (exsound_select & 0x04) && no == 0x300 ) {
3 J  T2 Z' @6 J& q3 B4 f* o                return        m_bMute[6]?fds.GetFreq( 0 ):0;
) H4 V* I1 Y9 h5 O( D4 G0 I        }! D1 U6 X: w$ ^, g
        // MMC5
/ V9 ?% F  j- \* J3 ^2 w) K0 i& a        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
; C, t8 B" u7 G( p2 h                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;5 k0 J5 ^9 d- T" ]# k
        }9 r* a6 {5 I: r0 }
        // N106) E3 {5 |! G9 w! u
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {  f0 g8 k6 s1 Y& b# ^1 j4 A. ^. I; V
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;" k* {" Z" B& C0 p( a" Y$ n
        }
  b7 Q# a2 f, x% Q5 f# |        // FME7* K; D) O9 D! f; U, a4 s
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
! H) x; p* \7 A9 ?, u* Q: l                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;4 I* G1 H! R0 M+ u7 z  w
        }
: L+ C3 u7 S' h9 I& @        // VRC7
0 Q7 g. Y3 W3 M% C, T+ ?( G        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {6 Y/ n* b. g+ A- k
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;- ~4 C* t' }6 _4 ]% j0 n
        }
8 m' W; i( w: Q/ s7 n        return        0;. J: S+ ?5 R8 S
}9 \( W& D/ [- k0 T1 r+ H: e- F
+ l! x! J) M% c
// State Save/Load
6 [7 j- o9 U# f4 a2 f) h! gvoid        APU::SaveState( LPBYTE p )# B  C3 b, V& z4 A2 j/ O3 w
{8 M3 u- b  V2 i% n. a5 I
#ifdef        _DEBUG
$ ?! O/ \; V. nLPBYTE        pold = p;  n7 @  c, G+ L
#endif
; d1 q8 f# f! W2 q; g3 J" |8 t
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞* V6 _" P6 i( D1 u; h6 L* y4 \: m
        QueueFlush();
( D' E* p- b2 p& O+ j
9 C7 h  B0 g( X/ t        internal.SaveState( p );! g- P/ m( W1 A$ u
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding4 e' ^  H) E, ]& R, R* a

0 w+ h! U# P; i. G        // VRC6! q- q% h$ B# S" Q# m; z- ]7 {
        if( exsound_select & 0x01 ) {) k, S! ^  L1 t  B; Y
                vrc6.SaveState( p );
/ C, E7 S' {, @0 Q# J* B  M                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding" t8 U8 ^6 n$ |/ S7 t
        }! k* k3 R6 W5 C7 n, u
        // VRC7 (not support)
. i5 A" Q8 b8 Z* Z* m2 a        if( exsound_select & 0x02 ) {
9 i5 A$ m8 a1 K  T( e. k                vrc7.SaveState( p );6 N5 e& e# Z" l9 ^- e
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding# c* {. _& r" \" n4 K/ N
        }2 e, q: a  T. N9 ^
        // FDS9 {5 h4 J+ t) o
        if( exsound_select & 0x04 ) {6 w& @+ B7 O2 v: u7 n* H! i
                fds.SaveState( p );
9 ?! h; r- p1 x& {( W' ?# Y                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding7 R: ^( M5 ?! ?6 U- `
        }6 c; h! W: F2 P* |% O' W
        // MMC5
8 P! S$ U4 u) [        if( exsound_select & 0x08 ) {
" Q% d- b, h& o' \; \                mmc5.SaveState( p );3 m8 E8 m  _' m/ U
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
+ n4 i- m2 d. O- c1 c) {  H        }
" m7 Z7 Q/ Z) G4 r0 p        // N106+ K- Y9 X+ b$ |1 w
        if( exsound_select & 0x10 ) {
& ?/ c# R* z4 e; X4 x+ I' f3 h                n106.SaveState( p );! M) M' V9 B) a6 @+ {% f9 M* p+ N
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
, g% {( ?+ m2 @! d        }
9 z" Z2 y& u+ S/ d8 \        // FME7
( L; s( a; K8 h# O' w        if( exsound_select & 0x20 ) {$ e: @, ~1 X6 u& W, C& ^6 N0 R  r
                fme7.SaveState( p );' y. z6 ~2 h  v2 E: l* x3 L) R
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
' Y2 u+ ?* G& f! Y& \        }! o4 r. O4 n" m9 ?

7 a; K3 @- N$ s% E2 E#ifdef        _DEBUG
1 E* m, J7 @8 xDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );0 x# I  \6 G  R" V8 w
#endif. ^6 j5 z" S# z
}
# B: L) m" x# _1 U0 I( W/ q9 _
+ Y6 C8 Y* ~; [6 ~void        APU::LoadState( LPBYTE p )
  _# r& Q% h" D# L$ p{
2 ?/ O" k# u5 X1 i( r0 @        // 帪娫幉傪摨婜偝偣傞堊偵徚偡. ~2 j. Y& p* R7 m  ^, K
        QueueClear();  ?$ g) A/ A! M) w& i8 l# O

1 n0 z# b) R+ Y3 b( Y- F9 j        internal.LoadState( p );/ O5 ?( C# G" ], C- A3 A- h9 I
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
( k) U8 ?8 S8 i2 F' |/ S- a' M- d* x# q
        // VRC6% g: N" ~1 C" H5 c. K6 E* L- c
        if( exsound_select & 0x01 ) {
6 O% W* N6 b. O. _# @                vrc6.LoadState( p );, Y/ y& }! l8 w
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding8 m9 C' Q( S% C/ @5 i
        }7 N7 t* }6 a: z/ f- @$ v+ o
        // VRC7 (not support)
7 @& E) w2 g5 g9 q- n2 W+ B        if( exsound_select & 0x02 ) {$ Y$ D5 W: H  ~+ J6 l
                vrc7.LoadState( p );5 P1 b$ u. J; s0 D
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding( c/ C$ R* i' o$ }1 X$ Q% r9 [9 p4 U: f
        }
9 L& p4 d+ N; ?0 g        // FDS4 V0 z# B, g3 N* V* z
        if( exsound_select & 0x04 ) {* m1 |: K$ m/ m( B% Q
                fds.LoadState( p );
; w  N" l, ^1 E4 h, s! n0 {                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
( r! l( N' J% L. I0 n8 C) X        }' Y' u9 o1 q! _" z5 U
        // MMC5$ M0 M- u- R/ c0 X2 o6 @
        if( exsound_select & 0x08 ) {
" k9 u3 T$ g( c; M, u                mmc5.LoadState( p );
6 F+ c0 Q3 I2 _; G3 j5 N                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding/ V/ p8 }7 R/ a' P5 _
        }& ~6 g* |3 ]5 O4 L* ^
        // N1062 N0 w8 `; r8 T) ^0 h# M+ [
        if( exsound_select & 0x10 ) {' m1 Y0 s9 D2 s) B& w9 b4 X
                n106.LoadState( p );0 i* h+ O% D8 B3 z& N5 l) O1 n
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding2 o# d) w1 U# T! o
        }
3 e  L% E2 e: f. I& M; D        // FME7+ k: K4 I0 k" ^# l: G# _% P. K8 X
        if( exsound_select & 0x20 ) {# `4 I' p1 ~7 N# g% c
                fme7.LoadState( p );( r- U: [) R# _" b; P7 i* k+ {0 \
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
5 Q& C# t/ y' @$ {        }
; S( r  b6 f: J  v8 c}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
4 `6 ]. }' Z. Z* g' e可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。" t; R7 Q. v3 l9 C
感激不尽~~
* {0 H2 Q5 X5 y8 V
恩 我對模擬器不是很有研究,
2 j' E6 S! g( }7 X( L- q雖然要了解源碼內容,可能不是很困難,# {8 o1 R" R' Y6 u' g2 Y* W
不過還是要花時間,個人目前蠻忙碌的。6 {0 l/ C+ {( [; ]8 K/ Q  A

7 W$ D+ F2 ~0 r: A3 U% d9 @. O給你一個朋友的MSN,你可以跟他討論看看,7 x" t" L8 w6 P+ Z/ [1 o- d1 s3 ^
他本身是程式設計師,也對FC模擬器很有興趣。% M2 \+ K( w# |  R8 N+ u# B
$ ^% ^& \( r: @, f2 W% `
MSN我就PM到你的信箱了。
2 ~( B+ l; X8 i9 V) ?% M2 u6 B
' s9 V( k3 N! r% x7 o& 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 发表
8 V+ ?/ L* T+ S) f呵…… 谢过团长大人~~

# v% h( `+ f/ h+ j; M
5 H* N3 Y1 F9 E0 z/ |哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 ! A9 L* P+ Q; s
团长的朋友都是神,那团长就是神的boss。

6 t, i! O9 g* [4 g% P1 [6 q哈 不敢當,我只是個平凡人,  A& K" `4 @" \$ ?" D0 X3 i
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙& x- B  q+ _6 `+ Z
ZYH
; t* x( v/ R. B2 |. ]* XQQ:414734306
; u* H& v+ {9 }! G& gMail:zyh-01@126.com6 A$ F* F8 a7 A8 }" X4 }0 g
" w# J2 P+ u9 R: \6 k% j
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 2 |% K% I! b3 a- o% F! ^9 _
再次对团长大人和悠悠哥的无私帮助表示感谢~~
  }1 o: M+ {9 P8 e% z/ h# y
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-1-8 04:21 , Processed in 1.081055 second(s), 18 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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