EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?
+ @0 D! \5 u& q. Y* R6 S$ h& _# y2 |, cPS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
' u. q0 f1 x9 `& u# H1 G楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~7 H! G" i9 R, P: L" _6 t% s. T7 D
这里有相应的模拟器源码,就当送给大侠了~~& x5 b; |1 T" z7 q
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 5 Y' V7 t9 J. I" Z  `
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
, p9 N# |! S7 Y楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~* k  o% h' \2 W. V
这里有相应的模拟器源码,就当送给大侠 ...

1 w- I9 f. p9 s4 p  ]- Z6 m聲音部分(Audoi Process Unit = APU):" O4 u3 X$ T2 @6 m; [4 t6 L
.\NES\APU.cpp
* c, U. |5 P' p0 q7 R/ h+ g.\NES\APU.h" _7 \) h( ~8 z* z* z. o

4 v5 Z' a9 x- `% b/ ~3 Z
0 f( y9 \* I) l" m影像處理部份(Picture Processing Unit = PPU):
+ Q+ k" u& B* X) ]1 }0 K& ?4 Y.\NES\PPU.cpp; t2 m3 t0 h& ~
.\NES\PPU.h' k" l' O4 n8 C; S
5 H5 @7 N$ q* T
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:  I5 `& ]$ f, u- i7 ~4 K4 ~
(由于很多专用术语和算法机理都不明白,所以看不大懂……)3 ^" Z8 t+ M5 W: M6 C
//////////////////////////////////////////////////////////////////////////
2 y$ ]- @- y) ?' Q! v//                                                                      //
; r( q: n4 a5 u- N" {2 c0 d//      NES APU core                                                    //
) K4 D9 S. l8 A: j5 F- X//                                                           Norix      //
+ U% z  B" d0 ~! D  s//                                               written     2002/06/27 //4 x/ o7 W0 t% ]6 t+ b
//                                               last modify ----/--/-- //+ U, g. s8 g% y9 H" L) T  F' J
//////////////////////////////////////////////////////////////////////////* D1 q4 `) {7 W$ d* Y, y% v# \. S3 r
#include "DebugOut.h"
- v$ M: X# t$ _: ?2 I$ u#include "App.h"% M( k2 Z. ?( W. z# v
#include "Config.h"
  C+ r" v+ I( w, m) H0 c5 h
9 f2 m+ M$ O3 y( I6 n6 b#include "nes.h"$ B7 i& ]8 r" K: l$ K! y, `2 m: Z5 R
#include "mmu.h"( D( q/ ^. ]' N9 l' \% r1 @# g
#include "cpu.h"
4 D9 f% c0 }* v0 ]( a9 d( r8 ]% F#include "ppu.h"
8 |! ^6 j$ G  {- |0 X/ I#include "rom.h". }) y% V' {" ~7 l* V1 g+ `) {2 m
#include "apu.h"
4 j3 A+ r3 v# A2 _  ^: F# X" ^. |2 r! d2 n# `' B. }8 _: T% p
// Volume adjust
! \7 H1 ~0 X# Y$ w) x3 n1 P// Internal sounds0 x) |7 l+ F$ z; A& y5 O5 B5 b
#define        RECTANGLE_VOL        (0x0F0)
; M0 H+ Q9 l  v. N+ u9 B#define        TRIANGLE_VOL        (0x130)
8 `/ x+ M3 }" J! ?5 n2 p2 g#define        NOISE_VOL        (0x0C0)
4 J0 Z2 Y* M7 D: S, P( Q2 H#define        DPCM_VOL        (0x0F0). s) A1 w6 d$ J1 _6 R
// Extra sounds) u$ k1 e: t0 }8 C( Y
#define        VRC6_VOL        (0x0F0)6 |0 h* i8 D- p2 o. @2 _
#define        VRC7_VOL        (0x130)9 a! M  n5 r6 L; P
#define        FDS_VOL                (0x0F0)) E, ?" h2 y3 d) X6 s$ `$ i
#define        MMC5_VOL        (0x0F0)& `! [$ X2 O! U0 c( k
#define        N106_VOL        (0x088)6 S  p7 i& M. u2 z+ @/ I
#define        FME7_VOL        (0x130)
% Y* b0 E2 e; M  {0 z" a4 ?7 @% w6 S* o' J' Y5 q5 Y
APU::APU( NES* parent )
/ K' y1 o: o7 [2 V{
  M. I1 v: G; O) j$ U9 ]5 [: Z        exsound_select = 0;
8 z' P6 \, i' A' j# G
/ V1 t/ I- u  d& z        nes = parent;) m$ R) O4 @. F  b+ v' g9 j8 X
        internal.SetParent( parent );
4 m5 ]8 u" [0 J! u+ A2 o, L  q1 I# Y- d! D% V5 w
        last_data = last_diff = 0;
2 N. I8 M% |( A( t3 @, |$ n. Y' W% F
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
3 q& {! [7 y* s
( C" O% J$ H) K& t        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
& a/ H( p5 Y% F0 W# C        ZEROMEMORY( &queue, sizeof(queue) );
; K  L0 M" P, P! k6 p        ZEROMEMORY( &exqueue, sizeof(exqueue) );
" Q. A: v- l% m9 ~  @7 s& I
. t4 c( \4 Q' u3 `% }0 w% Y/ u        for( INT i = 0; i < 16; i++ ) {4 }- K- ^$ u( P4 k6 N! V# U
                m_bMute = TRUE;
) G3 w5 M( k. w5 u& J3 |        }9 H! @3 S% `; ~9 \
}$ a2 L/ R* }' u( b8 A; p- r5 l
7 A9 d) C. F$ l
APU::~APU(); o0 `+ ^. {* H3 N+ G
{
0 w! j, ?+ k9 `# i% ?9 X}
2 A4 J  }% m4 ?6 z/ e$ a- R! h5 U2 P6 J/ E, X
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
4 i- f6 x  a2 p) @2 t{
: N2 l0 k- t4 N" j  e6 E! G        queue.data[queue.wrptr].time = writetime;
8 l! u  |5 M5 K$ @3 {% d        queue.data[queue.wrptr].addr = addr;
/ B+ v- X5 l  L        queue.data[queue.wrptr].data = data;$ A6 H- A! O% \- O; {
        queue.wrptr++;& ^5 n+ h/ i9 m. {! Q: a
        queue.wrptr&=QUEUE_LENGTH-1;
% b+ y3 w. }# t# u6 o        if( queue.wrptr == queue.rdptr ) {% n6 d* S2 ^1 {4 X- y0 C4 l
                DEBUGOUT( "queue overflow.\n" );# O$ e- S1 Y' x0 ?
        }5 r0 k" P& a& |8 T- j* Z$ k/ l, \  D
}) H- S/ e5 Q# d- a
+ p* ^$ s* d2 D( z
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )7 K% f3 g* `: S3 v+ X1 L$ S, M
{2 ^% n* B% M8 G% r$ v; p3 d6 Q* U/ Q( z" P
        if( queue.wrptr == queue.rdptr ) {2 s* j* h& [6 O# \
                return        FALSE;4 n' j" l6 p5 O" B' i
        }; `( n, b+ w! Y
        if( queue.data[queue.rdptr].time <= writetime ) {
  e$ A" V$ B) Q4 x% P                ret = queue.data[queue.rdptr];
" N6 m: n0 ]3 G9 o                queue.rdptr++;
. O5 B0 X: I% u( ]. J5 i. B4 C5 T                queue.rdptr&=QUEUE_LENGTH-1;* L( k! b$ C7 q1 z
                return        TRUE;( x2 c2 y' x" @
        }! x, t; S8 z( T' n* a; I
        return        FALSE;
0 B/ L. g) N$ l3 t! ^}- \' b+ ~4 A" _& `) |5 ^  Y
6 ~6 U1 A3 K+ s9 n
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )  ~$ C* [+ n' r* W$ F
{& Y$ i. z2 p+ w( Z
        exqueue.data[exqueue.wrptr].time = writetime;. m9 p! c/ t9 h. O% O# c9 E
        exqueue.data[exqueue.wrptr].addr = addr;
. |3 `6 _% E; l1 F2 V( y; G# `        exqueue.data[exqueue.wrptr].data = data;' g" `, Z/ w/ R. O! y
        exqueue.wrptr++;! j! A; T+ e' \) O; J: X
        exqueue.wrptr&=QUEUE_LENGTH-1;2 ]; O5 n9 J8 O5 W5 O& |+ P
        if( exqueue.wrptr == exqueue.rdptr ) {
, T. {  H8 V/ D; x, L                DEBUGOUT( "exqueue overflow.\n" );, _* p  h3 _/ {# @3 B& m  b
        }3 W' d2 y+ u  i/ }, N0 J" c9 l# m
}6 Q+ e( O! n& ?6 X: I% H
8 ]$ Q- [+ K. A7 G( i0 S: W
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
/ Z% U! X+ g  |; ?# x" X# S' F4 x{, @8 r9 K; r6 L6 {! `
        if( exqueue.wrptr == exqueue.rdptr ) {5 {. O6 f1 E" j3 S  x
                return        FALSE;4 Y- ~+ ~. l" v3 W
        }7 z! p+ r- p( J* r' Z
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {, e# \& g1 Z0 T! X# a) A
                ret = exqueue.data[exqueue.rdptr];
1 w% _# r" R+ e+ V& d4 q% A& Q- v! P                exqueue.rdptr++;- r/ |8 z) w% j5 `. V
                exqueue.rdptr&=QUEUE_LENGTH-1;# }" s% y3 s1 Z6 m+ M' o
                return        TRUE;
7 b5 r3 e& H: w2 H4 E4 u        }
. G0 D1 G. I3 ^9 I        return        FALSE;
7 L& d: b8 K( F+ h' W}
# C5 @8 u; H0 Q- ?& n. \7 @: n! m1 N7 x. C0 E
void        APU::QueueClear()
2 M+ i/ C/ a0 `{  @+ y/ w' @5 ?; I- J. R/ c+ E- q
        ZEROMEMORY( &queue, sizeof(queue) );
* a$ N- a- c8 i! ?$ @        ZEROMEMORY( &exqueue, sizeof(exqueue) );
. U* _& k/ d  x! t6 |* o}
- W* U+ j1 O$ E( E! r( Y6 l  w; P. F& o- {; B1 D8 e, Z
void        APU::QueueFlush()
$ x+ Q6 k/ J, e$ I! H" ?{
3 f- ]: l4 m0 ^% j9 p8 q, f& x        while( queue.wrptr != queue.rdptr ) {( I: M" a2 ?( E
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );* A1 U& X) B0 S) g
                queue.rdptr++;
" J5 j, q  j/ `                queue.rdptr&=QUEUE_LENGTH-1;
# I* K# \/ O7 C        }6 i! a) O  Q" y3 D: O3 n
; Y. U& [$ z# |8 p9 [0 F  I0 C$ {2 @
        while( exqueue.wrptr != exqueue.rdptr ) {
: e, C2 {9 s3 w# b/ N3 Y                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );2 V* H8 @) l1 s8 b& w
                exqueue.rdptr++;( M8 A: C& e( m9 f. j  ?) j$ Z7 S
                exqueue.rdptr&=QUEUE_LENGTH-1;
$ W6 n) D9 A  b/ Z( w* w        }4 `- F' Y) @! m* q
}
7 h! a9 S3 a; M& ?
% _% H4 A. K! E& a& {  ~& nvoid        APU::SoundSetup()- F! S/ E  w. T6 B: b
{
0 t2 ]( B1 o! l; t4 i; q        FLOAT        fClock = nes->nescfg->CpuClock;' d, H4 l1 B: X1 Y7 D
        INT        nRate = (INT)Config.sound.nRate;' z) K+ c- @, |* ]
        internal.Setup( fClock, nRate );3 C3 W7 {5 ^5 k3 ~+ K& [$ h
        vrc6.Setup( fClock, nRate );$ C! B" d+ p1 @( y& S
        vrc7.Setup( fClock, nRate );& k# m" _) w* {, r% @
        mmc5.Setup( fClock, nRate );
+ w7 h! F+ @$ ?$ S        fds.Setup ( fClock, nRate );
" _) d' ^- v$ f+ f+ L        n106.Setup( fClock, nRate );' D0 |0 `3 E2 _/ d$ f
        fme7.Setup( fClock, nRate );
2 ]- [7 R- Q: @  h( R% k}/ n  A5 |$ C% }/ d
: ?9 E$ _, r- O# z4 B. G! e" l* ?! E
void        APU::Reset()
9 p$ g7 }! [# o' b2 i" F7 W+ w{$ @% J! \& V% t2 H# t, e
        ZEROMEMORY( &queue, sizeof(queue) );* P& s+ Y& V2 p% J1 }- i
        ZEROMEMORY( &exqueue, sizeof(exqueue) );- @7 ?, i2 y$ d1 N4 y# F
; S( p$ Z! g4 h3 C8 X8 @0 m
        elapsed_time = 0;7 T. R  j. Z" R. n
! @. c' S9 k" l7 ~' y
        FLOAT        fClock = nes->nescfg->CpuClock;9 m+ U1 a2 E5 T
        INT        nRate = (INT)Config.sound.nRate;+ e. B. F, f3 T
        internal.Reset( fClock, nRate );/ W& W0 H" ~% P  \% Y
        vrc6.Reset( fClock, nRate );
. q7 k# U8 H. X8 f/ w        vrc7.Reset( fClock, nRate );* d1 B3 {( q, O0 j" ^# L2 f# z! M2 n
        mmc5.Reset( fClock, nRate );, g7 W$ F( T; y  Z8 K/ T8 x/ [0 F' l
        fds.Reset ( fClock, nRate );
5 j% [. u" A% U$ k8 J; J7 ?        n106.Reset( fClock, nRate );
% y1 Z* `/ V( u2 ?7 t        fme7.Reset( fClock, nRate );
4 H: ^1 n9 Z1 ^& u, W+ M0 r2 _& p* ~+ T0 ]7 ~
        SoundSetup();. v: V2 @3 q/ W4 Z" m4 o, L" Q* o$ o
}  K! g$ p6 Z5 s  e/ I/ J
" P7 E' i2 f, D) V) E! Q& l
void        APU::SelectExSound( BYTE data )
$ n$ b5 G: k2 e; y% ?9 u- G+ B{/ j  Z7 M- r) H$ M% K' C
        exsound_select = data;
8 d8 z, ~) R; \5 I0 T}
+ v$ d% _$ s( r: O' K( p; L! z9 j. t+ ~
BYTE        APU::Read( WORD addr )
9 e  Y8 ]/ d: ^+ P5 H1 o# H: G# e5 l+ c{4 W7 {  U% `. ]! ^2 q! M$ x: Z* e; d
        return        internal.SyncRead( addr );" K, Y9 |' D8 A8 d8 \0 Q
}& W4 B' l. u6 x# X9 S$ {& A

. d* M  }5 N( s: }' Qvoid        APU::Write( WORD addr, BYTE data )
& R( r$ @8 a( ~+ c% w) u{
3 N6 o* O. w0 V$ `        // $4018偼VirtuaNES屌桳億乕僩
. ?5 _5 x% N9 l+ A' T9 a& K        if( addr >= 0x4000 && addr <= 0x401F ) {
  C( d& e: J+ @                internal.SyncWrite( addr, data );. ?/ k% u2 O4 s/ `1 `
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
3 N/ p: ^' `8 {$ Y; I$ Q/ o        }. J2 r; u: }0 S" G7 @8 E
}% r  k/ ^2 e' v$ z9 ^
5 ?6 F# _- {& y3 Z
BYTE        APU::ExRead( WORD addr )+ a7 `; d9 r- r* [; y2 w5 q! g: p
{+ u" ]+ }. \+ ]2 w3 U0 i
BYTE        data = 0;8 D* ?# k# J; u+ W! i& B- i

2 v( F$ I. A( L& b$ y0 b        if( exsound_select & 0x10 ) {
- b; {% D* [$ @' {% o- q# Q5 i$ g* m                if( addr == 0x4800 ) {& o7 k/ ?7 d  j- @3 I
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );6 _6 l9 G5 [1 q
                }  a7 v+ d3 c, f( I4 ]
        }4 t4 u/ I' ]. a& J1 i
        if( exsound_select & 0x04 ) {
  g. m, R3 ~% g# D# x                if( addr >= 0x4040 && addr < 0x4100 ) {
2 M0 h) M5 X  i# }                        data = fds.SyncRead( addr );
4 E6 ?- X' Q1 k" a+ ^/ [                }+ J; b2 O) ?5 R1 \1 M$ J
        }
9 v0 ^1 }8 R$ F6 Z, k4 K  l        if( exsound_select & 0x08 ) {& |. `* e5 H7 C/ b! T) Q" w
                if( addr >= 0x5000 && addr <= 0x5015 ) {
# D- }0 q  T+ n8 ^% `                        data = mmc5.SyncRead( addr );
, O( k! K6 }( L  ^. y: Y                }% T$ E1 ~( B; h7 y0 M& G  V0 f
        }
: y$ }# R' o- v7 B8 `# o! ?6 V7 Q+ |& G5 U  e  }
        return        data;! K% E" c' j6 [" m
}
0 g3 `: b2 H- q& ~9 u" p- r, y
9 `6 G& y" n5 y5 vvoid        APU::ExWrite( WORD addr, BYTE data )
( @; `# {1 s( ~# ~5 l{
7 ~4 A+ p$ Q) N3 Y$ c/ X        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
" l* D6 l3 r  u5 K7 Y! z3 U6 E; ?
        if( exsound_select & 0x04 ) {4 {: }4 X5 |- l& I* w- H9 Z
                if( addr >= 0x4040 && addr < 0x4100 ) {
% _1 o: N& ~* g9 J; l7 v) q                        fds.SyncWrite( addr, data );* a$ U2 B8 y2 Y; k# |# r
                }
4 Q) x' U" F2 ]& U        }+ S! v- z, R2 ?5 y: f0 k" z' x
2 H* v7 _5 }8 W! I+ x; d4 ?
        if( exsound_select & 0x08 ) {. I/ E- C0 Z, E" n4 ]
                if( addr >= 0x5000 && addr <= 0x5015 ) {) w( i4 O, a* u: s9 T
                        mmc5.SyncWrite( addr, data );# F1 q4 M; S, j
                }- l8 {4 R- u, J
        }' }$ d" C- c( A# d
}+ X2 o9 `, ]: n+ ~  `$ e9 b

9 H3 j1 C& E. j3 j: {! x9 Dvoid        APU::Sync(). x! F7 E( h9 k
{/ Y0 W+ G7 b1 \+ b+ T
}
9 a8 V6 ]+ q, u- a6 `" b& V7 t; C0 H1 k  i  j* v
void        APU::SyncDPCM( INT cycles )
7 W' z- Y- b( Q3 G, Y{
- E2 {: ]. ]) ^6 E- K        internal.Sync( cycles );: g0 Q' ?9 h7 n% \( N5 d  B

+ o4 ]' z, J0 k- n/ `        if( exsound_select & 0x04 ) {4 |% I7 q9 o# v2 @( [6 J+ \% n3 b
                fds.Sync( cycles );
% n7 {( P. H2 a$ T        }
. g9 `. V' ?& @1 Q        if( exsound_select & 0x08 ) {; b+ e0 a; \8 w' [# S3 v# n' `
                mmc5.Sync( cycles );8 N; l6 `2 H8 o
        }
0 ?' [" T$ L0 H4 B6 Y1 L}
# [; l1 d1 f5 }4 H1 H% |+ A& M$ Q( H) k# A- N
void        APU::WriteProcess( WORD addr, BYTE data ): U7 X2 X; M# b5 j5 I+ J
{
: r- W, T& \  Y  p        // $4018偼VirtuaNES屌桳億乕僩
+ K% ^& m6 O$ N$ C1 r2 t  ?        if( addr >= 0x4000 && addr <= 0x401F ) {
& I$ M- M" J4 J9 P* y                internal.Write( addr, data );
$ q$ ]: u+ n9 [, F# V6 d# @" z        }
) S. l, U5 e% I1 _9 Z' }# c2 ]}
; B/ ^8 Y2 p( @( Y0 L# j% ^! u, V& q- z, S& i
void        APU::WriteExProcess( WORD addr, BYTE data )3 z; ?( l6 }- x" g5 x( N- q
{" b7 f- m" f6 v8 a8 q: C3 X  A
        if( exsound_select & 0x01 ) {$ {5 A9 j9 y6 }$ R0 C8 `2 s0 ?$ x, C
                vrc6.Write( addr, data );9 P5 l9 Q- D: j0 Y; {
        }
6 ?1 `; m! k5 z# r        if( exsound_select & 0x02 ) {
! D  G5 Y" |; d3 }* `+ f                vrc7.Write( addr, data );' E1 f# q* X6 e. k. w3 j2 v- h
        }
; N. G7 ~- x& S. X        if( exsound_select & 0x04 ) {4 L2 q+ Z- _3 x. R
                fds.Write( addr, data );
2 {) E" k: e4 V7 V. Z) `7 S        }
% Z: A7 ?- g. F0 F/ d/ m. m: s        if( exsound_select & 0x08 ) {
$ t7 T& a4 w; c1 n                mmc5.Write( addr, data );; P3 X, ]; Z/ E* H/ C' \
        }: L" ~# R" S: M3 l4 k( D
        if( exsound_select & 0x10 ) {
5 W9 ~3 r; t9 f$ ~" Q/ n! J7 C; V                if( addr == 0x0000 ) {
; T6 V& _. P0 l8 p0 k                        BYTE        dummy = n106.Read( addr );( I* X. h- @# Q6 F
                } else {
, M& y% c: f; }: N+ c0 H% o                        n106.Write( addr, data );
3 U* a3 ~* _6 J' T, J; ^                }2 Q2 ^' O' A+ I: y3 j; x' U
        }
$ y) F  b0 W6 \# k2 j$ E        if( exsound_select & 0x20 ) {
, A# o* M' L2 C" e4 I3 I                fme7.Write( addr, data );
/ j4 H2 g* R. n        }$ b& a2 \+ X8 M( Q
}
6 W7 e9 h5 t, s" {2 W  A
& Y- b6 F7 ?; U$ M) ?5 lvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
+ L) ~( O( C( W1 y0 i' z{4 N! R4 d6 T# g/ q$ G3 h2 u
INT        nBits = Config.sound.nBits;
* {8 d9 x7 U6 o" o( F- Z" C) R; ^1 MDWORD        dwLength = dwSize / (nBits/8);
8 Z. j/ v9 Z& \$ JINT        output;6 a& ?% }" W) u  h
QUEUEDATA q;
$ d# D$ i& F$ W" ?( \DWORD        writetime;
* m5 X7 L: W1 X9 F. k/ x+ I. A. O" Z2 a0 z4 i
LPSHORT        pSoundBuf = m_SoundBuffer;3 F* |% E( r5 p8 W4 d+ T
INT        nCcount = 0;
8 ]: {  V  l# S1 d$ D3 L8 M
/ y  ~9 G' d) S* r% `. JINT        nFilterType = Config.sound.nFilterType;. c% P2 M5 b$ V. l

/ F. p0 I$ @! e/ I' V8 Z* ?9 Q        if( !Config.sound.bEnable ) {
# B& x1 a; r% n0 S# s" G2 }% i" o% P- B                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );$ X9 s" s( n+ V+ V! }
                return;- g& v8 ]7 o  ]7 k3 `2 q4 J
        }) v$ ^3 w! J8 H( x5 ?! N! Z( _% w
8 s9 o6 {' C. |
        // Volume setup
6 Z( a7 w" R) q0 S/ b3 _5 Q        //  0:Master
: C" @2 t! u% X2 a        //  1:Rectangle 1
$ y4 z4 g( O" P1 K        //  2:Rectangle 2
* ~( ?! ^. c5 ?        //  3:Triangle
3 U. D9 ]* n% u  w        //  4:Noise0 o4 n" E* a$ B# q" x  v
        //  5:DPCM1 g  f( _) {! J! @. ?9 r8 N
        //  6:VRC6, ]  y4 u+ @5 g  W$ K/ z! Z* N/ H
        //  7:VRC7
: X" `) R% l$ N. F9 ~, g        //  8:FDS% u& g1 o. K5 f( _. P
        //  9:MMC5" {! j$ k# ?( @0 x/ \
        // 10:N106
$ A# ^3 m9 t6 H' N        // 11:FME7
! P. y. I5 }" W3 ?        INT        vol[24];
2 P* s5 k' D* i. K; V  T6 \        BOOL*        bMute = m_bMute;( [! V. G5 S. C1 p' n" N8 w
        SHORT*        nVolume = Config.sound.nVolume;. u" V4 N) s# j8 v% p
- i# u7 o9 O/ m8 X$ |5 m0 Z, V* e, H9 W
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
% T( @; ?! m# b' ?  z
% _/ W; f6 r) p$ O  B        // Internal
4 W1 {; u/ T# ^& m6 s, P        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
4 ~) }" l$ z- {: n% w        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
* g: h7 M5 F4 X; T8 j1 i        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
4 Q* b& b7 x2 b9 {! t, D9 V# B        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;' ~' Z6 P; h2 V, Q6 H
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;" J7 |6 f2 L6 v
9 Y4 G5 K* _7 F
        // VRC6) ?: i0 Z  x5 f
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
2 W& h4 Y' W# p, C5 {1 d' k        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;  Y  v* J& f0 k2 `% `1 P
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
0 {6 c. s1 t/ N2 j* X1 N- t
4 `$ I) V; L7 `2 T        // VRC78 A& o% H4 m$ U- h
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
, o) C3 ^4 z$ {6 S0 Z& I6 k& x) r" k% Q0 l  ^8 {9 U# Q# Y4 E. r0 t0 D
        // FDS/ O2 |) S- J* |: \" B
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;4 H% r- _( A: o6 y. H
+ f' ]  }4 [; ?' D0 F
        // MMC5
: d0 G: ?5 f& C# |; r8 C        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
4 L8 _9 s1 A" L" B8 K$ W        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
+ M' R0 H* N! f% k2 {        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
" p2 P/ o/ h9 C+ J3 x
! K1 A6 v; R9 u        // N106
0 `! V* h& u- E2 @+ n        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
, l: @1 v6 a8 z( ^# K5 j8 S8 @        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;+ k1 r  q% I; x! }1 m
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 ?& ^( c: N5 s2 g        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
9 e9 B% S4 h6 N        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;2 e2 s' G# I5 U% s3 J! T
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
+ K# I/ I& l- m        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 A4 D" r) W+ x. H9 h1 T- E' h
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
3 y9 d. J( v% {' V. _1 ?1 g" N! r, u+ o7 b) D% ]+ Q. v$ p) b- \
        // FME7$ Z- r, w: m1 x
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
6 x6 ]& [) F9 z& O        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
4 K( T$ Z2 `  J7 p1 u% D/ M        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;5 f# \- j1 c5 o$ y$ i' V6 |5 ]. e

% Z2 Q+ Y" U% i" o9 E1 C//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
6 E) Z# r- q4 ^, B5 j0 e        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;. [! A" X" @! K9 z

) }; c% B2 H3 h8 o        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
" d1 k, b! c% ?% W! f) C$ R        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
4 |' O, i: X' Z5 O/ s                QueueFlush();5 P2 b, g% R0 P! \! E
        }4 C* i8 W  T: |0 z* d
% q& E4 D2 b; m/ g& ~. T
        while( dwLength-- ) {! m' x, Y* R6 M# F1 H% I& P4 U3 J
                writetime = (DWORD)elapsed_time;. J7 }3 G3 n7 t( F

' b" u8 M8 |! i6 B                while( GetQueue( writetime, q ) ) {
  w' b4 a, I& g# q# k4 @                        WriteProcess( q.addr, q.data );9 \  V2 D5 N/ V9 d
                }
, O" X) e" {& Z$ n$ {2 p: Q6 J0 M' W  @0 P
                while( GetExQueue( writetime, q ) ) {
( w  O9 z' p( p9 V9 \1 O  v  f2 Z                        WriteExProcess( q.addr, q.data );
& [6 w) i% c9 P5 d, w8 U% \% P                }/ ?. {- j# C7 F0 H, [& s" g

- \, t! R) ?, c% S0 ?% Z1 {                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
9 _! Y8 g. t! N4 ~8 W% @/ Q- r" t" E                output = 0;
8 s! e( y" z  L: L7 `' ~                output += internal.Process( 0 )*vol[0];
7 I5 k: {$ B- n( o2 f. A                output += internal.Process( 1 )*vol[1];# v% g; R7 v' m- O. _
                output += internal.Process( 2 )*vol[2];
/ v6 f; L) }0 W+ M+ Z                output += internal.Process( 3 )*vol[3];  N# x4 C4 C/ D& x/ }& c
                output += internal.Process( 4 )*vol[4];
& O) Q9 T% f) O" x9 b: l
3 v  H# U; Q; V, B  m7 V                if( exsound_select & 0x01 ) {1 e6 K/ z1 V* z1 ?1 p9 e: W
                        output += vrc6.Process( 0 )*vol[5];# E$ b4 F) h8 u9 O7 p
                        output += vrc6.Process( 1 )*vol[6];
2 T/ k: }$ J# F                        output += vrc6.Process( 2 )*vol[7];
, ~1 |5 ~: Y$ I4 e                }
# w. @- K4 u/ p' B                if( exsound_select & 0x02 ) {' ^9 \& }. E) ~
                        output += vrc7.Process( 0 )*vol[8];
/ B. M9 V' B! c3 }0 l                }6 v: r4 P. ?9 `6 j, n& Q3 b
                if( exsound_select & 0x04 ) {0 `. d; t) N2 f+ P- \' i
                        output += fds.Process( 0 )*vol[9];
% {$ l+ Y/ v2 |; L                }7 ]1 a1 L. A- t7 Q
                if( exsound_select & 0x08 ) {
7 \& k* q: K! R1 y- q                        output += mmc5.Process( 0 )*vol[10];& f. q  t+ }/ y$ W. M8 N0 J. J, ]
                        output += mmc5.Process( 1 )*vol[11];5 {- i. O" z( P9 _' ~+ ?2 F6 e" S
                        output += mmc5.Process( 2 )*vol[12];
) x9 u! l% @7 O                }* G  F8 h' T; ?* d* v! q: Z( q. }
                if( exsound_select & 0x10 ) {: B2 @" X5 W" v7 h- N$ M0 T
                        output += n106.Process( 0 )*vol[13];
6 H4 ^1 b& R# Z0 n* S" D$ c( w5 i                        output += n106.Process( 1 )*vol[14];6 J* b4 ~5 a( l! i; N6 l1 x
                        output += n106.Process( 2 )*vol[15];
- ~8 i$ |% w7 W& s                        output += n106.Process( 3 )*vol[16];
+ T  o# k! g: v0 k0 n. O                        output += n106.Process( 4 )*vol[17];
$ @4 Z& A& ?6 B+ @  j2 |% X" E' ?                        output += n106.Process( 5 )*vol[18];$ ]' c7 u; `6 Z* ?3 G
                        output += n106.Process( 6 )*vol[19];: ~$ G- n$ p2 \* l! o- ~, O5 _+ b. m
                        output += n106.Process( 7 )*vol[20];
- L3 ]9 p! M6 _/ b                }
# x, c0 A+ m3 s, S3 k5 j                if( exsound_select & 0x20 ) {2 y# j7 }5 J8 g/ e
                        fme7.Process( 3 );        // Envelope & Noise
" a) |% n1 u8 ^9 r                        output += fme7.Process( 0 )*vol[21];4 w9 W# L- H+ ~  M/ k. z
                        output += fme7.Process( 1 )*vol[22];. j" b) ~8 |* a
                        output += fme7.Process( 2 )*vol[23];
) G8 g9 g- V/ J3 V8 c                }/ c- `3 O$ o" f) y) ~7 a3 w

5 ?/ }5 _+ E6 Y8 D                output >>= 8;6 s- q, e' X" `) \- s& U' M$ v
# S( c& u! L* d2 ?- c
                if( nFilterType == 1 ) {
; i! U5 I$ c! g( {' M( W( y6 ~                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)* C& p) r, C1 j
                        output = (lowpass_filter[0]+output)/2;8 H7 O) \6 G- f" \  s0 }
                        lowpass_filter[0] = output;
' C: @/ Z6 D7 Y) {1 e7 L' A                } else if( nFilterType == 2 ) {4 |9 T! l! `' ~) W( F
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)3 k4 ~* F, E6 C: b* r7 E. g* Z0 M
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
+ r) t1 z; n, u/ a                        lowpass_filter[1] = lowpass_filter[0];
) v7 }, E, V$ P( s0 |+ j7 ^9 s                        lowpass_filter[0] = output;; M. T$ W6 _5 J, P
                } else if( nFilterType == 3 ) {
" f6 j( w* [; a1 l% h% J                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
: C  b& v# t0 H8 C* l                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;" K; p2 j, R3 e% t; f( o2 I2 o
                        lowpass_filter[2] = lowpass_filter[1];' X& `, W7 B% ^4 ~# h  q
                        lowpass_filter[1] = lowpass_filter[0];
( y, n  c8 ?- b, O                        lowpass_filter[0] = output;5 |7 Q4 \) J% t
                } else if( nFilterType == 4 ) {: W1 E; G  `- S2 x2 C2 B
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
' f3 F+ p4 }$ l5 p& p& a- ]                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;+ [, a1 T& Y% y, L3 T
                        lowpass_filter[1] = lowpass_filter[0];# e4 B" ?% F) @
                        lowpass_filter[0] = output;
8 R3 d7 `5 x0 G6 ^3 T8 T                }
9 [+ `/ L- Z+ Q% L  [6 X( [! \* a% \8 q! R% I! O' Z0 h
#if        0! k0 E" t. |' y! ]! U' j: q
                // DC惉暘偺僇僢僩8 ~, L3 T: o! R7 Q! M1 A# |
                {
. H3 R% w, f$ r, [; g) s& h2 x/ j                static double ave = 0.0, max=0.0, min=0.0;
+ Y& x3 a5 C: Y" ^" L$ h8 M                double delta;8 z4 K, f/ F* h$ |8 a+ R$ c
                delta = (max-min)/32768.0;
2 W+ _# e8 c3 M! f* v/ Z                max -= delta;
! H  {+ j% `! @" {0 z3 d                min += delta;
; ?% Y8 R! n( m* T5 r- q                if( output > max ) max = output;
  V. h  H& s' Y" B, f4 o                if( output < min ) min = output;
( V/ G' t  S6 i1 ~; B3 b  w                ave -= ave/1024.0;! n4 J* I: G0 T9 d7 a
                ave += (max+min)/2048.0;
' |# l( s% Y5 |4 h: ^0 c( H                output -= (INT)ave;! ^5 p9 X* M! e
                }1 n4 @* y) e: v/ g8 U
#endif. ^5 P7 B; ~* h) T+ C
#if        1
9 k8 r3 q  W9 J& m  N                // DC惉暘偺僇僢僩(HPF TEST): S6 ^$ j* p1 W! `2 o
                {
& M+ b! _4 A: @7 ?! ~$ ]9 k//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
. H! s7 m! T" Q& |6 G                static        double        cutofftemp = (2.0*3.141592653579*40.0);
! G" W9 D1 w7 C! v$ ]; Y; R! d% B                double        cutoff = cutofftemp/(double)Config.sound.nRate;
+ |8 n* V9 I4 J# y! ]                static        double        tmp = 0.0;
, j, C& C1 n5 Q: X: {- c                double        in, out;
3 z4 C( _$ t9 g/ x' I( L( S# _( n" U4 k+ k! ]( H9 ^
                in = (double)output;9 }* |7 u0 C/ H8 g* s) ~
                out = (in - tmp);
% u/ x3 U* W' g* [3 d4 p) `                tmp = tmp + cutoff * out;
0 n) `$ J5 {5 b
5 R/ [9 A6 O( t+ C8 v+ @                output = (INT)out;
) L- r3 ]7 V  m                }
' J7 D" s0 i( B/ g. B#endif, S, h2 Z# l8 |* K" p8 A& p0 Q, T
#if        0; G* l% g) M* c0 @0 u1 w  p3 {, ~
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
+ W, n6 M2 \+ e" ]7 ?; ^, m                {
; k- V# f- C1 g! h- M                INT        diff = abs(output-last_data);
  J' [, [, N4 |/ X3 J9 o9 R                if( diff > 0x4000 ) {
6 m3 c; k0 D/ F4 H% ^: g0 \                        output /= 4;
6 F: l% j: D+ e' W                } else 9 H$ T' o+ A) Z; F7 K
                if( diff > 0x3000 ) {4 [, z4 R( Z6 B6 G
                        output /= 3;
/ D" T( v# Z6 _+ f% j" u# A9 M5 T! i                } else2 e6 }& C. X. A; D# K3 o3 ~2 ^, {
                if( diff > 0x2000 ) {
: }/ D+ S5 e+ Y3 s; U1 f                        output /= 2;
# r- I2 p: C7 K3 H/ Z* Z. H2 E                }) q' e" ]6 S# r, B' r2 H5 d/ @
                last_data = output;1 [+ |% T% k4 V$ a% r
                }
  s+ E: Z7 W3 ]* C5 o/ o! ~#endif) C2 U  `$ V% ^! x, V0 s: f
                // Limit
& v$ j$ }2 I4 b0 ?5 J                if( output > 0x7FFF ) {
: \. G" W. F& O0 ?/ i. e* x                        output = 0x7FFF;
6 X3 v+ V! h8 f2 G( U" n  y- v4 W! O                } else if( output < -0x8000 ) {+ |" [' e8 b- ?8 M0 H
                        output = -0x8000;' Q; |% V# |: c. L. e  T" h( O
                }6 `5 u0 y6 _! r, \/ d9 t, z

" P/ _# b- l* l3 \$ i! G8 U* t& P                if( nBits != 8 ) {
8 n9 [5 @6 X$ @9 C# a, e( ^: U                        *(SHORT*)lpBuffer = (SHORT)output;
; O+ R5 K5 q1 O* ?9 o: v& O                        lpBuffer += sizeof(SHORT);
, ~* X" o4 Q1 \  c1 W                } else {: ^/ i# B; B, g- N7 ?
                        *lpBuffer++ = (output>>8)^0x80;* @+ k. v/ T( F& U) g
                }1 e2 E2 p# D; a( u
& C% X5 B7 |0 O% y. t4 z6 i  h: u
                if( nCcount < 0x0100 )# K+ r. O3 q/ w8 T; k
                        pSoundBuf[nCcount++] = (SHORT)output;
' Y/ r! q& g4 K* g, L  A- f) r4 W, [4 ?$ z: G& n
//                elapsedtime += cycle_rate;9 g5 \+ {6 B/ L5 t
                elapsed_time += cycle_rate;8 U1 K6 u0 _5 Q6 C1 O
        }
$ y, j0 _& d$ c$ ~/ `" |3 _
* }6 I* n. Y  q, f1 c# c/ z6 \#if        13 m) q& v- Q6 X& l. G6 T  G- }1 z
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {$ d9 x$ b% S! s# v  b
                elapsed_time = nes->cpu->GetTotalCycles();
/ K8 d: C# o+ l. p) e# @, r        }6 p/ W+ F; C2 ]8 O( q; I5 G
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
) V) \6 o! K2 {0 P: n8 T3 ^- N                elapsed_time = nes->cpu->GetTotalCycles();
0 g/ j: d5 y: Y& f' w        }  Z( d2 S: e' `9 `5 s& c  U, E; s: \
#else' F6 I' Z/ B3 ^  A7 k
        elapsed_time = nes->cpu->GetTotalCycles();
& J! Z9 d# A' ?/ ~/ W#endif( R* v  m% u7 j: g0 ?+ H/ k
}, G, M# \7 h7 {) m8 `( a
5 N! k! M9 B' F2 t
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
7 D/ A, h  E$ e! N9 w4 z8 C1 c# HINT        APU::GetChannelFrequency( INT no )
1 r0 V/ e5 a1 N. U- c9 ?{( U# x+ q( O% L" A" g  I
        if( !m_bMute[0] )% N0 L  u4 k1 l1 |. p
                return        0;
9 N9 \" @. [+ c9 R- R
' ?' f. p2 T) ?        // Internal2 g3 `6 p) X' J; C/ F. \
        if( no < 5 ) {6 b$ V- Y- L. N; w9 i4 `! W
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
' k* K: s4 z* {/ \4 W; G        }
5 v0 O! i9 N! w5 H- y  Y! R        // VRC6
9 P3 R% w# L4 c  I8 F        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {: i6 Z8 h5 j* u/ [' c2 Y
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;. A+ Y' o! J$ o9 A5 J
        }- O) y& j! ^7 P4 Q2 a2 g* q: I) D
        // FDS
6 O% I& g. F, }% S& B. L7 x        if( (exsound_select & 0x04) && no == 0x300 ) {. J2 G3 B7 g' W( d5 h( W& G
                return        m_bMute[6]?fds.GetFreq( 0 ):0;5 E/ B) o. G0 B5 z  z( T( Z8 L* v
        }
$ u* C1 B. W- Z& f" R. ?        // MMC5
  P! d! c$ x: o8 M: N+ E        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
- o" `/ o1 }& A4 f1 v! ~6 h                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
( Q; e& M/ Q+ g7 o, T+ a        }2 o2 Q# m+ ~$ S! V. Z& s
        // N106
" I0 }% ^$ s) d) c        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {  C9 h3 }2 Y8 {" g# }( N. l
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;7 Y. h/ G" x- _3 s" D  @# V) c
        }; u9 a1 i2 g. f; y2 }
        // FME7, I* `8 [) `# |: H0 l* k! v4 f
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {5 ?. T8 W- [/ b6 q4 Y  K9 g! I
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
$ Q) i' H4 j" s8 F, J+ p: \        }0 u( e$ ?: w6 S+ ?! i$ g) p
        // VRC7+ ]  D+ L) c5 [3 i* a( t& n
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
3 {3 U- N! l( Q+ h  b* Q                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
) Y3 h, d5 X2 a# ?$ u0 X8 E        }
. c. c) g) ^0 \( W$ V4 Z& q7 Z' p        return        0;: H+ u1 T+ l& ?+ ^6 \9 |$ D5 A4 y
}
( g3 D" K6 Q5 U$ a' N7 I
$ p; ?7 l/ b  [* ^* J, u// State Save/Load
: F1 X) [8 o+ M2 H. y9 _void        APU::SaveState( LPBYTE p )
/ V( x0 V2 _5 j6 O0 Y& b- p  o{0 A# d# K5 C6 z/ Q+ c# o0 Q$ G
#ifdef        _DEBUG, z' E3 I0 Y$ o5 o
LPBYTE        pold = p;/ f% @; W1 E8 n6 ~, o
#endif9 ?5 I4 Z7 V! e- }: L' m

  z' C( W2 A1 O2 t4 R        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
* r* F1 `# K- U. x5 R. g        QueueFlush();0 h9 A  O6 S& U/ g+ {7 ~
' g5 z6 @, j. W' O" u0 f
        internal.SaveState( p );
/ {' r4 t8 R* M        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding% h4 q0 g! b  N! \: c

0 a/ x0 P" q- B# F6 N( U        // VRC6
/ X. {; N' K9 g, ^) m6 q        if( exsound_select & 0x01 ) {. D- W" l, G0 X( h
                vrc6.SaveState( p );  [8 f& r! V* Q- h0 T; S; R
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding5 E( V4 {  Y7 }! ?+ G) Q. P: z
        }) E0 d4 Y( y1 T6 I' i4 E+ Y
        // VRC7 (not support)
3 x# ^# W1 w$ }' C        if( exsound_select & 0x02 ) {3 h8 H- i* w9 B! K3 M# l- Z
                vrc7.SaveState( p );1 D  Q9 p) P: B/ p& _  z5 R7 X
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding7 f2 K' B" z" Y8 c2 X, \  e
        }
5 c, R% Q0 a3 _. ^        // FDS6 Y6 ~" L( B/ n
        if( exsound_select & 0x04 ) {
+ o' ~- b8 R, x+ ?0 |/ r: g                fds.SaveState( p );
  i) U' S" n6 e8 C% L                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding. h: @$ W4 m8 d) C. L
        }0 n. \# T1 \: p# d1 s4 M
        // MMC5
& |4 X) I3 a8 f3 h# m% H        if( exsound_select & 0x08 ) {
: p- a% o; N$ @! r8 f# |" y                mmc5.SaveState( p );; K( T; F2 ?1 N9 @# p5 O
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding8 s( ]! w2 N; B* r' \2 h
        }
; s6 n" w9 L5 D/ X: Q        // N106$ B& Y# r6 @5 A, k$ X  I: A
        if( exsound_select & 0x10 ) {# i& U  g% R4 Q4 m' V5 S7 c
                n106.SaveState( p );
% B  d  Z* x9 D: {0 ~4 R                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
/ _7 y# a0 x- `        }
! ^+ Z7 x+ _" Y# m* u        // FME76 K( L, C- X5 Q2 X+ o
        if( exsound_select & 0x20 ) {; F' `0 }! @: x6 r' T
                fme7.SaveState( p );
! s0 |$ x; o# J+ ^8 J6 F+ K                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding  r& W  [+ e' j5 W! D: z5 G
        }! p5 p0 ?8 z- s
0 o+ ?; v9 O& ^3 G' [
#ifdef        _DEBUG
5 |9 v/ G. A& k1 W3 S% _3 K! k$ O4 WDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
% x* U3 J+ f5 ~( y5 ?  H#endif
6 [$ `! w! n5 c}9 l) [. }% k- a% D

9 r& _/ H5 }9 j0 h' ^void        APU::LoadState( LPBYTE p )3 v& M" J. G* J, u  B7 R5 q: }8 v
{/ h" m/ e+ J2 q  X: T" z* U
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡6 J' E- e3 p# w7 r2 D# r: r4 U
        QueueClear();
! H5 C$ C$ e1 q! B1 q7 l
1 X; n$ R7 X5 _9 B0 q+ u; p% Y        internal.LoadState( p );
" `; t4 A! P7 B/ @$ }- Q        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
2 U' X& o$ m, Q- A6 J- y
" M8 i' l0 C" a* ?        // VRC6
0 T$ }# m6 H  y  c$ `. c/ |9 T        if( exsound_select & 0x01 ) {6 O1 d6 s0 j% |: n
                vrc6.LoadState( p );! h( c  j" [9 Q( B$ W: Y7 |. m; z8 D
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding1 ~" v7 E" @! q. H2 h3 u
        }: ^( e  d' t. T: \2 R/ w' |  ?
        // VRC7 (not support)7 B9 H! G9 t; n7 A1 X, K$ V" d) v/ J( l
        if( exsound_select & 0x02 ) {
: L# Z( w0 R  I4 K/ q0 C                vrc7.LoadState( p );2 x3 V, R$ `8 x; B
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
8 `' S0 }) A7 e: U3 G& e        }) H4 F- `. P3 r7 Y
        // FDS
: Z: E% v9 i5 r! F; p: f        if( exsound_select & 0x04 ) {/ _, P% G; s* J; o. y; g" R. K
                fds.LoadState( p );
0 n+ C' d" ]; y7 g8 z) a                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
1 Q, d% j9 n8 K        }
$ V7 P* a' K$ N4 f        // MMC5& d, \" j' J6 {, s9 l
        if( exsound_select & 0x08 ) {( o0 M3 [: t2 k) R$ C; w
                mmc5.LoadState( p );( M/ ^/ W: M+ w* K8 x
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding( g- `4 e& G6 ^" M% q
        }4 g4 M: M; U3 e& v/ {
        // N106
* ]$ `' m4 W; `5 l' c. O( a        if( exsound_select & 0x10 ) {
/ {" l4 j  T) v3 g9 t. x% S/ a                n106.LoadState( p );
% w* S$ t1 j1 G9 }: {                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding; z0 b  f8 Q% ]+ h0 `
        }
% c5 ]" @& l7 g  [/ N0 q/ j        // FME7
; Q1 @: ?& f6 m* _        if( exsound_select & 0x20 ) {
, z, A5 `( _  o# r, L                fme7.LoadState( p );
2 `1 h) O9 L. A+ W1 C4 \- x5 [% F0 N. u                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding1 B3 B# Q; _% ~* @
        }: ]! ^# `3 W6 s, O: F
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
! W& [6 R3 I2 ^8 v  y可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。- H; r  {- l6 r* G0 }6 b
感激不尽~~
& y" y& p; u* a
恩 我對模擬器不是很有研究,; D3 {9 o4 u3 C& }
雖然要了解源碼內容,可能不是很困難,
! i/ {- I  V$ R# F0 N不過還是要花時間,個人目前蠻忙碌的。' b% K+ x8 m, ^& Z/ b  X5 G
4 K$ {( C# y; C# ?( b( i* v8 B* e
給你一個朋友的MSN,你可以跟他討論看看,9 ]5 B$ S& p7 Y( a5 V+ L# h( R1 y
他本身是程式設計師,也對FC模擬器很有興趣。
  p" H3 I6 U7 n# j) |7 b/ z' T3 l/ I& d" G; O
MSN我就PM到你的信箱了。  J. H2 E0 p# F7 v7 l) H; U- S$ y
) R  X0 u+ L- J5 N$ P3 K
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
( Z9 G7 ~! `( k5 `4 B4 P5 {0 N7 I3 w呵…… 谢过团长大人~~
" p7 l- h$ g( U2 w: S* C

+ F5 m# k0 z& A% Q) O6 k, h  @! ?4 f哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 3 M% {$ M9 V5 ^7 l) E# C" Z& _- k# V
团长的朋友都是神,那团长就是神的boss。

; a! c, T  u7 e5 r7 @4 j/ c哈 不敢當,我只是個平凡人,
& v! F3 u5 ]: o( L要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙9 D# V: i2 i+ Y6 h" j: s
ZYH5 D* Y0 @) a% C# ~
QQ:414734306" p4 n2 F# ^' z4 O" v) R1 v. b
Mail:zyh-01@126.com
3 r; e# }. q4 D1 `  T
9 u- T# j+ M* v+ V他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 ; V$ f1 g. G; v# ]* e1 ?/ [0 t7 q
再次对团长大人和悠悠哥的无私帮助表示感谢~~
4 t# b" s  [+ ]+ X, v# Q
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-13 01:10 , Processed in 1.105468 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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