EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?. i' M: l+ v, Q! F5 R+ ?9 k
PS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。2 _+ J7 M) N7 t
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
. O7 i7 Z& N5 S( M5 n: O这里有相应的模拟器源码,就当送给大侠了~~
! p1 \" d+ m9 @) _8 phttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
% u+ X5 N6 |4 Q% G5 U6 `) b能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。6 T/ Q3 k1 V6 V' S- [# V4 i
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
, i" W( t1 `8 Z+ k% m这里有相应的模拟器源码,就当送给大侠 ...
- V% a( j! [7 k2 `; S% l, H$ |+ v
聲音部分(Audoi Process Unit = APU):; t' }/ H0 O# R6 |1 ]( d
.\NES\APU.cpp5 R' |7 W6 F# a6 x( Y
.\NES\APU.h) b! w7 \) e3 H# r- W9 p

% d6 g3 x6 w( u% @# n0 L  ]
# G5 o# a' Z% |) H影像處理部份(Picture Processing Unit = PPU):# O8 z- B+ |7 _: d0 M
.\NES\PPU.cpp2 F6 X# T, u8 b3 N4 y' m
.\NES\PPU.h0 H: g2 `( c7 H5 Q7 h; ~* F

& a' ?7 i# W$ }, Z' B* E! i7 y如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:2 a) q- S9 q# I# U. A
(由于很多专用术语和算法机理都不明白,所以看不大懂……). N1 z5 L4 h9 r/ I0 N7 n
//////////////////////////////////////////////////////////////////////////
. G- y) Z5 p; u7 p//                                                                      //
# p! w" X1 g4 Y0 R/ Y//      NES APU core                                                    //& ~3 u" h0 X; Z4 Y# _7 x
//                                                           Norix      //
8 z. @: W+ l8 b+ Y) _0 w. u+ b# V2 }//                                               written     2002/06/27 //
! e* \8 J: N2 l% t//                                               last modify ----/--/-- //8 s3 j! x+ r$ ?& {
//////////////////////////////////////////////////////////////////////////  p5 w) ?7 X, R! I9 T! Q
#include "DebugOut.h"7 Z7 B; y% L! |. D
#include "App.h"
' o9 u$ V1 s4 {, v! m, `#include "Config.h"5 M3 _( ^9 v; Y, O, E. H  w

+ |- u% ]* w8 M" l/ o+ I$ e: a6 s#include "nes.h"" m/ l0 b7 s% `) l- @. V
#include "mmu.h"
: J9 w; F! o* t8 a#include "cpu.h"
7 d; Y0 X4 A' P" w5 z3 \#include "ppu.h"
& f) }8 j. I  H% z#include "rom.h"- \6 m: G7 e1 l, q* q; J* b/ v
#include "apu.h"
" r# Y- w6 S# T# T' j1 x
9 ?; T7 t3 ^% e$ E// Volume adjust
7 ?5 M! O' K: o- A+ x: Z$ ^& Z// Internal sounds7 G8 y& g, @! A2 K7 i
#define        RECTANGLE_VOL        (0x0F0)6 M  Y1 Q5 ]* b9 j' E7 @
#define        TRIANGLE_VOL        (0x130)" l' J3 z. P$ ^& }+ J- S7 n( ~- e8 `' S
#define        NOISE_VOL        (0x0C0)$ c+ V5 C# R6 n! t& J
#define        DPCM_VOL        (0x0F0)
5 p$ u; ]' i/ Y% R6 G7 J4 Y// Extra sounds6 v* s! ~( N+ n# y- D% q& B
#define        VRC6_VOL        (0x0F0). P7 t$ l: H4 n) I
#define        VRC7_VOL        (0x130): R* h! r2 E8 J9 c  O
#define        FDS_VOL                (0x0F0)
4 ?$ `; ^# j& L#define        MMC5_VOL        (0x0F0)
, k! F$ b* d) b! u3 m#define        N106_VOL        (0x088)
. K  P: P% j- P3 B, p4 Z5 c1 y#define        FME7_VOL        (0x130)
4 K' q/ W/ U5 b: v- _
/ k% H. M. u1 {' J, m2 ~APU::APU( NES* parent )
# n7 x6 K  @, m{
: L# X: ?2 X' r% h2 P        exsound_select = 0;
' a: J( p% |) m* W2 }/ C
  Z  f3 z. X5 ^8 S3 A7 N0 k        nes = parent;# U' p( o+ ?, e0 P
        internal.SetParent( parent );
. e& D* E+ l, q) d( A0 a! o+ k( \. z0 P; P, j* p5 G% |
        last_data = last_diff = 0;
2 h5 z' k0 b5 W9 s9 G' L
* D% R+ {4 o" h% u; j+ U        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
2 }8 H3 J2 O; S
/ {6 ?* {( N, T3 A5 n' ^' a, Q# K/ A" r        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
. r8 X# r* J) f/ W% k" b        ZEROMEMORY( &queue, sizeof(queue) );5 @' D; ~, i8 Y; P$ e
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
# l8 S* {, ]/ O; m/ d' `# M' d* A/ h1 j
        for( INT i = 0; i < 16; i++ ) {
9 ]; h% x5 O3 {7 B- l& v% q# t- h                m_bMute = TRUE;
' z# x  g1 ?& f( l0 @* Y  O        }
0 O: z& M$ h; X! P& `$ H}
9 w: W( G; ]- L, x) P: J- |! ]% x( c+ ^
APU::~APU()
* l$ y& c% Q- Y' k- h{. v4 w2 i8 d) C# T9 `8 x! t, \% g
}/ b( y' p. \7 b/ {, X
6 V) n: N# l# `6 V; Z
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
# P" Q5 l5 v  t) H: m7 b' |* D" e{! C8 z1 h  u1 {  T
        queue.data[queue.wrptr].time = writetime;& w6 I+ Y5 J* S
        queue.data[queue.wrptr].addr = addr;
5 m" O; _. f/ q! i        queue.data[queue.wrptr].data = data;* B" {* M6 Z& Y' z- p
        queue.wrptr++;/ Q9 {3 M! ]  |. L5 r: T! x
        queue.wrptr&=QUEUE_LENGTH-1;" A3 Q, E  j/ t  h" a
        if( queue.wrptr == queue.rdptr ) {( M, A3 c& j' }, I
                DEBUGOUT( "queue overflow.\n" );
' @. J: i6 j% T% O' G0 y        }5 A- }; t+ t& ]. j
}
% Y  d, ]' g$ Y% {3 F: F" ]# j
9 V; T  P  I! v2 xBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )7 V5 u+ h- D% w9 _! ~
{4 b5 ?; Q) u1 ^7 z; e
        if( queue.wrptr == queue.rdptr ) {
( n. f9 x& j, f, g8 T# t" ?( l                return        FALSE;
( E& o% u- _0 Y6 K( G7 _        }/ L* d0 Q- B$ Y
        if( queue.data[queue.rdptr].time <= writetime ) {+ x5 w, C! r* u% ^, `  h) m( N# H
                ret = queue.data[queue.rdptr];
  f, Y; y& I, R8 j                queue.rdptr++;
$ s2 ~( v: Q! z6 k                queue.rdptr&=QUEUE_LENGTH-1;
8 R# g$ C! m' E: F% A1 c$ \1 O$ E                return        TRUE;
' g, l. Y# ~* e) H+ g6 H        }
% z$ Y3 |. U6 l: l& `1 L5 T        return        FALSE;
5 _( @3 s; x" e% s) [  Z}/ ?" X# S9 S4 B- X+ ~
( K. q/ Y9 [3 [$ r" |' H$ j) w/ r
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )2 ~8 U2 b2 Z. p- j- l$ Z, p% p
{5 z$ p) I2 s; p, D- w! V* Z4 o
        exqueue.data[exqueue.wrptr].time = writetime;
: R; \# y( w- {) Q5 c. w8 D6 P        exqueue.data[exqueue.wrptr].addr = addr;
* x5 S3 o) A, U0 G0 ~        exqueue.data[exqueue.wrptr].data = data;$ ?0 H1 u# e. C3 T" X7 w9 F
        exqueue.wrptr++;; t! h& `$ i) k! |* f  O% \: o4 c
        exqueue.wrptr&=QUEUE_LENGTH-1;7 u  B5 t; h! e6 |9 Q
        if( exqueue.wrptr == exqueue.rdptr ) {
4 ~; b7 s! ~6 x7 j                DEBUGOUT( "exqueue overflow.\n" );
! j/ q$ R* X* r7 i4 g        }+ k. O9 ?- }2 Q2 T
}! l+ ]" w# i& k

$ m9 U, k8 N' b. v0 YBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
. Q$ C" h2 m/ l7 w{
% N( B7 s- I( ^6 h        if( exqueue.wrptr == exqueue.rdptr ) {, X$ H% [# H' @
                return        FALSE;
+ l" C# d! g; t; z6 d        }: F! l, u. R$ R3 ~- b9 x
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {/ A7 }, H7 W' H" S
                ret = exqueue.data[exqueue.rdptr];
9 s& t4 D$ k; Y! f  }                exqueue.rdptr++;
6 x0 K, B4 k( y9 G( ?) c9 y' u                exqueue.rdptr&=QUEUE_LENGTH-1;
; `$ x' t2 b) O( x2 X                return        TRUE;
+ k7 |8 A/ Q+ j6 m% c        }9 ^6 C) W& s! l9 X
        return        FALSE;
( }# q2 }; `8 C}
+ J+ O' d& v1 J1 c
1 e) x( w* H! Q- c) H' F* wvoid        APU::QueueClear()
+ N/ C4 Q: m( m1 Q$ I( R0 h{
4 Y; ?( B# _( z% M        ZEROMEMORY( &queue, sizeof(queue) );! n2 C; I, t2 I: M" V7 ^1 A( D
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
9 x  F3 Y1 j6 Q* s2 h/ s0 Z}
4 L6 e& [- B! p. t2 Y1 X
7 M% D; h; l9 J  p/ Evoid        APU::QueueFlush()
' f, B! l( G8 a{; F4 O4 S  E* R
        while( queue.wrptr != queue.rdptr ) {6 G% O) b# [3 M8 P3 F) H
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
8 d, J0 T1 J& y                queue.rdptr++;
4 J. V" N9 e; ~. L$ z# L8 c+ `- N6 t                queue.rdptr&=QUEUE_LENGTH-1;. X: s8 k  e1 {8 v! E6 `
        }
6 D6 B" c2 e- `* N+ L! b; B1 n; O( \4 S" K# G+ x+ J
        while( exqueue.wrptr != exqueue.rdptr ) {
4 |& I& k7 e% Z7 T5 `! f1 {1 L% @                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );* f4 R( c1 G* d/ v9 A! \& P+ z6 U. t
                exqueue.rdptr++;" [6 y- N" O7 O. ?/ i3 P
                exqueue.rdptr&=QUEUE_LENGTH-1;+ n( U3 }5 |$ E3 \' t! ]( n# l
        }
( S5 z; T# {( _) h; Z}
" h# _% X! s6 F/ ?% p$ l1 ~' E
# e- F! v3 q6 W' {+ h: Z) {void        APU::SoundSetup()
9 |0 }" ~5 a; C{) M$ S" G) Z( R8 t
        FLOAT        fClock = nes->nescfg->CpuClock;; Y5 m3 X! E# d. h8 Z" T
        INT        nRate = (INT)Config.sound.nRate;
, z; U5 l# S+ ]  `+ _        internal.Setup( fClock, nRate );8 r$ V. Y/ g7 Z8 r/ }4 u3 m  g" }
        vrc6.Setup( fClock, nRate );& B6 u# C7 B4 a
        vrc7.Setup( fClock, nRate );" W' _* c! c  K! @! w1 O* W
        mmc5.Setup( fClock, nRate );" Z2 I" D; o! p' F) _/ k
        fds.Setup ( fClock, nRate );  A# D" K1 {7 J& e0 w! c
        n106.Setup( fClock, nRate );; d4 y, g) m6 h( p
        fme7.Setup( fClock, nRate );
) Q$ b) R6 x4 O" J}
; {9 C2 G- B+ b) o. ~7 L8 W4 r
  M& R& A' B+ L+ T/ v+ Q! Ovoid        APU::Reset()
: x% K& Q3 O6 A. L{/ F# Y: o* @( x) }1 }: c* \
        ZEROMEMORY( &queue, sizeof(queue) );+ x' r+ Y& s2 V9 @, B* a
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
7 q6 ]. `" `4 y% Q5 `+ @% B0 N# g5 v) @7 `
        elapsed_time = 0;
/ g) e- h  E, e+ ?% r1 Q5 a: B. c, i: \
        FLOAT        fClock = nes->nescfg->CpuClock;
3 v( N5 C  Y* O% [( L        INT        nRate = (INT)Config.sound.nRate;; f( [# T9 [$ |! [/ C3 D
        internal.Reset( fClock, nRate );
9 G3 V, e& l2 D' Y        vrc6.Reset( fClock, nRate );
* w* v* X+ K8 Y        vrc7.Reset( fClock, nRate );
) M' u+ _/ _; k# o( x+ a* B        mmc5.Reset( fClock, nRate );
8 V% Z% q( T( r3 w6 m# Q, P4 m5 G        fds.Reset ( fClock, nRate );) P+ s) x, e% a) G* |7 J- c* e
        n106.Reset( fClock, nRate );
# F! K5 B. f- p2 F8 z  [        fme7.Reset( fClock, nRate );
$ N) q, A; C2 H
) z; Q( X2 @" F# h        SoundSetup();# f& B& X+ u7 @" o' i! A. z
}
, {1 p  C  }1 D4 S1 D+ c2 U9 B8 E/ t, A" Y$ h
void        APU::SelectExSound( BYTE data )7 T& Z# X. r* Q/ x. C' K! P
{
% h0 j* p& q  ?- }( L! H        exsound_select = data;1 v) |3 h3 ~; K
}) @$ G" e+ J6 e3 o8 f

6 `- Y& f  I0 bBYTE        APU::Read( WORD addr )
1 H8 @! _7 a3 \# k5 r6 o: a{
* s9 ?9 {; K4 R5 t6 V7 n5 S& N        return        internal.SyncRead( addr );. G$ T! K) h; |5 S# B" x
}
) L* m! i: Y- F, @/ m1 s
' W4 j+ l$ ]. o& U5 x3 J: bvoid        APU::Write( WORD addr, BYTE data )4 {2 V4 K$ N" }3 Q6 l0 L; T
{& r1 Q7 j7 ^! f. K2 u+ h( f) |7 T
        // $4018偼VirtuaNES屌桳億乕僩
7 G: p/ w, I7 E7 D2 ]- z        if( addr >= 0x4000 && addr <= 0x401F ) {( |4 |: w" S8 U
                internal.SyncWrite( addr, data );' w  F" z: `5 z- h9 l# O! C
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
8 I! ~% ?& O9 R        }! }% }, L8 m3 b& J( L3 Q8 K4 D. m0 w
}
$ a  _7 p+ }6 q
3 L: A8 Z" O  s- yBYTE        APU::ExRead( WORD addr )9 i. ]9 V+ t4 Z8 t% F# J
{
  o6 n# f* l" S. w- C) iBYTE        data = 0;1 S4 A7 u# N# p
) X% s8 o5 n: c: _- [& [
        if( exsound_select & 0x10 ) {9 a3 x, \5 y  g( S
                if( addr == 0x4800 ) {
1 D% e3 t  k# @, ], U, r/ O$ w                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );2 C* L! T) \, s1 E6 o4 y4 m
                }0 w1 d5 g. ?0 B9 ~
        }8 l5 ]5 E4 L  K8 I9 J
        if( exsound_select & 0x04 ) {
! u6 t4 a3 {% _& V3 a9 a9 E                if( addr >= 0x4040 && addr < 0x4100 ) {
; i8 [. I1 n# j0 s                        data = fds.SyncRead( addr );
+ o, f$ }- T; {! }" i                }
4 P1 i/ U6 k/ G4 I5 `5 |+ k$ c9 E        }
. d* r* J3 \! C9 z# f        if( exsound_select & 0x08 ) {0 B# e8 Y- e* K* R. W6 _! R
                if( addr >= 0x5000 && addr <= 0x5015 ) {0 C3 h1 _) ?3 W6 w: K# \- P
                        data = mmc5.SyncRead( addr );
' \$ K9 v& t- i: e                }
0 n  Y3 ]/ T! z, \+ m: o" B$ Z% {8 w# @( M        }' W5 r8 |4 K% q, M( Y, D7 {' Z

* m  x9 b. }- ?% i        return        data;
  ^2 r6 X0 k5 q. c4 O; {! \! \) f}
! a, |% o: n9 T. p; y
) u- ~# \3 z! o& N" E, kvoid        APU::ExWrite( WORD addr, BYTE data )- t: _( J3 m0 K9 p' R4 J
{, L- ]; Y( j. ]6 ^0 u$ Z5 W/ D) x
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
0 i+ U* k! c; H/ G1 i9 y/ Q- h' W2 P  U: R0 p7 [$ R
        if( exsound_select & 0x04 ) {9 g1 S3 Z( y* ^
                if( addr >= 0x4040 && addr < 0x4100 ) {
; ]% |4 _6 k& ]" p5 v; m8 a                        fds.SyncWrite( addr, data );' u% s4 L  `$ ~7 J6 q" g5 s6 H" d3 b
                }
* K$ O/ }" c. I/ ~0 _+ S; T        }( z3 K) I! n2 ~
; c9 ?2 p/ O6 m& A6 D/ [
        if( exsound_select & 0x08 ) {
0 c0 d2 v% y% ~3 v! P8 c; L7 k                if( addr >= 0x5000 && addr <= 0x5015 ) {* {9 O* \3 b! t1 E7 _( r( ^; ?
                        mmc5.SyncWrite( addr, data );; L/ X5 _! @  o, _' X; b
                }
* B  N% j1 }# w  c1 A        }. p  ?9 ^% p3 y6 c
}
2 [# W6 E, B5 S2 F) f" c( J  ]0 W4 \3 {* F$ I
void        APU::Sync()8 H  D6 q4 }- Y7 e+ j* I! U
{
3 [1 l( \3 S4 d* _" J; j}% O( o5 K( C9 g# V6 P8 t  @) ]0 Y
$ h) B: X0 A( i% G+ M! }3 T- ?' T
void        APU::SyncDPCM( INT cycles )0 k' k# p" m$ H! P! J
{9 i# y  Z- \% C
        internal.Sync( cycles );
$ P0 Q& M5 I7 O  L5 U- f# D$ \/ ~/ S. i# J5 C+ P9 o3 I/ T3 C+ X7 C
        if( exsound_select & 0x04 ) {7 ^) {( Q* D/ z+ r3 s! z/ x
                fds.Sync( cycles );1 P# r% Y2 E* I7 p' _
        }0 O4 H/ f4 j/ B8 ^
        if( exsound_select & 0x08 ) {4 U, U8 ]9 f& K7 d1 R* |
                mmc5.Sync( cycles );
: H# T8 V( f1 T9 I        }& x. ]6 i' C5 H, t. {& v" \( I$ K
}6 b! r) F. `0 ~

* h. Q% ?% Y& [1 gvoid        APU::WriteProcess( WORD addr, BYTE data ): H2 R! t% {0 w& s8 D$ o
{
. o: B( T( T0 `6 M. m0 ?! g6 b        // $4018偼VirtuaNES屌桳億乕僩* j+ R0 V0 x% }* o9 x: t' o- y
        if( addr >= 0x4000 && addr <= 0x401F ) {
7 o5 n8 r8 X9 p& F/ z6 V                internal.Write( addr, data );
) K' W: A( C9 r1 l' N) t        }7 `1 {( z' H5 V/ ~4 Q! g% E+ Q
}+ f3 j. p% l/ F- s* D, U7 a# R
+ x4 v6 b1 T" K8 u) F9 D1 N
void        APU::WriteExProcess( WORD addr, BYTE data )
9 m7 Y4 B& X& n5 o  J{
- t1 K3 E! D7 t* D  y+ U6 `# O        if( exsound_select & 0x01 ) {0 r  f) t: \* u3 [
                vrc6.Write( addr, data );$ @$ ]7 k0 L2 v* U
        }7 e  }7 R( y! y; @# I
        if( exsound_select & 0x02 ) {
* ?' D2 ?, @  V: E! `* `                vrc7.Write( addr, data );
0 B3 M9 A# V9 |  c3 f) Q0 ]        }
" ~; _8 Y% m' ~& w0 i& e- v        if( exsound_select & 0x04 ) {
4 B; p7 W+ x5 v                fds.Write( addr, data );! r% y  R0 n! N
        }
/ Q1 Y% {: ~; y, p" ^        if( exsound_select & 0x08 ) {8 z+ I0 @  _6 y( D) h' B
                mmc5.Write( addr, data );
5 E+ Z$ w+ K, R: p3 w        }
$ t" J7 O9 T, i8 r) h2 E        if( exsound_select & 0x10 ) {
+ k& k: P. T! H                if( addr == 0x0000 ) {' a6 K- P+ l" [( L5 C  y, |
                        BYTE        dummy = n106.Read( addr );
7 K( O1 X- E- D' J6 a1 }' i                } else {& o+ _: w0 O8 k: y& s  n1 [* W
                        n106.Write( addr, data );
* E% T% }( ]! x9 T                }
9 _6 Q) b! [9 K( I0 m        }
& X$ c, O% w$ A3 r        if( exsound_select & 0x20 ) {2 Z. f% h9 u5 n' h4 Y2 \
                fme7.Write( addr, data );% x* N3 `0 u* `) u8 [
        }
# m4 G; y/ j4 V' n2 T" W}
: \  r2 O& d0 Y9 O0 w5 U
9 d8 Q2 J5 e* {2 Kvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )' {1 L# `3 @5 Z, y8 F, J
{
: z1 l/ e# {5 E2 UINT        nBits = Config.sound.nBits;
( k, g; U; |9 ^! z6 X' `0 }DWORD        dwLength = dwSize / (nBits/8);8 n' N' O& r* h& e) W
INT        output;
6 K3 w. S- P( s9 a! n; y5 ]QUEUEDATA q;; H( F. b8 G* z' V
DWORD        writetime;
. e3 v8 ^# e$ [; ?2 j8 C& N
+ X+ f* o$ d  ~+ I; h6 ~LPSHORT        pSoundBuf = m_SoundBuffer;
. ]# F; S6 D% x  m4 g" o/ mINT        nCcount = 0;
. f0 @5 w* K1 W* D% i( h" h2 ]
8 }" I4 W* T, m7 o- U2 V0 nINT        nFilterType = Config.sound.nFilterType;
# S- [5 i. p. q( a+ I+ |
' }' s# [9 c0 o# F; h        if( !Config.sound.bEnable ) {
. n( _3 o* D4 v2 ^- V" z                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
1 x/ S' g0 ^" B7 a) A; ?                return;9 @0 T+ i$ Q$ f! j
        }
/ y/ p/ W1 L: j5 ?0 J
! d$ ~3 C0 P) G- Z. v        // Volume setup
: J0 }1 I. u0 Q7 n+ i        //  0:Master! m) s7 J/ {% ~' W
        //  1:Rectangle 12 ^8 F5 b- T, t8 t
        //  2:Rectangle 2
; h9 `0 Q8 G2 y) P0 B* F3 K        //  3:Triangle* {! f. n9 R0 j) T& {
        //  4:Noise
) B$ k+ \) Q% F  k1 ^0 Y# I5 v        //  5:DPCM4 e" h* Z3 J& U6 o6 b7 t, n6 `* @8 g2 p
        //  6:VRC67 A+ s5 A! x7 [) z7 b
        //  7:VRC75 x8 N+ D# C# K3 B
        //  8:FDS
) T3 O/ Q1 l4 W, E% T        //  9:MMC5
9 p. H. A5 |, {        // 10:N106! Z& L3 X1 C7 m7 b& ~' ?$ b3 P
        // 11:FME7
  h: }0 n4 |4 j* y: d" v        INT        vol[24];1 E8 U- {( y3 ~( d: H
        BOOL*        bMute = m_bMute;
: j4 F8 X" V- C" I$ {' o        SHORT*        nVolume = Config.sound.nVolume;) T$ B" n# Z! ]; l+ A( G

8 A* Y$ I' L; y        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
/ ]5 I4 p: j6 |$ q0 g% B; B
3 `- ~; i4 w: Y3 P  y8 ~        // Internal) @0 {1 g; ?1 r( g
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
7 x1 B  k4 G6 I, ]2 i/ m        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;; v' j+ I& R/ m! {8 x$ I+ d
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
+ {  C. i( @  n2 i+ i/ f" b' p' {        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
# Q' j: ~, ~" F$ Z5 H4 o; T        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;  l# M! g* E/ s

7 d# k" O6 R. I( Y2 g  \) X        // VRC6+ ]& ?, x1 Z0 R
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;+ T! z, P! N# d0 X" Q; }, H
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;  k$ l$ |+ N. l6 T
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
7 g& }6 H$ d. B0 B: o4 g+ E* |  g; S5 {
        // VRC72 ]' L# [( p2 y- ]5 _# F; u5 y9 [
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
. J/ }8 r& |6 H' {6 ?" K7 b
4 m! y3 J7 X9 P) p* ]! j        // FDS
( U$ }" q* ?# H; ^' Y        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
3 Q# [! s" ~/ y- R
2 J* `# n4 q8 W# k; z        // MMC53 A2 N# o$ O" b/ W$ o
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;5 x+ f$ D0 K" l& \  O+ C
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;- [1 Y2 E1 ^+ R) n' _
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
1 F. e) O* [9 j" j
/ e: }  K# a  N! j5 x        // N106
6 L( r2 i/ o+ M" A& O        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 \4 [8 ~; Q9 J) O# `9 w        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
' v. ^& L1 k0 q- c8 V        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
/ i4 X, f* l/ e. ]% X/ ]: i1 U: n( ^        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
7 B) N; [7 B; y' L# x8 {2 D        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;) y( U1 L* x! c! {, U
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 W5 C& M$ Z& w6 h4 m( _
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
( J( s/ @( ~2 n" y! G# E        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;. O( u9 K9 T& h& m2 J, R; \1 ~
% |: c$ u" B8 R9 e3 ^% f) h
        // FME7/ X$ l) Z- O5 }" b
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;# g. b1 }2 _3 x/ A* j% U
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
% @) ~) M5 F) M8 U        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
3 `+ ?" i' h5 l/ L) n7 A% d
% q1 d4 }" s- z//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;$ l+ M! R. L! o; v& e
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;& F! T# ?- Q9 d6 K5 k4 G& G8 V9 X4 [3 P
# K. ?1 F4 g$ l
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟# H8 c. B2 [( [  Q8 y+ r9 w
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
& c. u$ L/ u; P- g: \  u                QueueFlush();2 C) y: H3 x3 a0 ~6 _
        }7 l7 N' Q% k+ Q

5 ?0 P0 ?: _; `1 h5 U) t$ G        while( dwLength-- ) {1 q' d& v  L7 ~
                writetime = (DWORD)elapsed_time;
8 B+ r6 m% s9 W. \1 s0 b2 B% W  q( y6 W( z- C! z& \0 M( [
                while( GetQueue( writetime, q ) ) {& L/ J, ?7 Y) f; u; r) j
                        WriteProcess( q.addr, q.data );
. D  y" f" F0 B6 ]0 y& z) ^                }; W5 o8 o# h6 r; W. R* }! f0 C% P

, V7 `: t$ a6 W! ^7 I/ }                while( GetExQueue( writetime, q ) ) {5 `6 a# p, f% S
                        WriteExProcess( q.addr, q.data );
& E7 B$ I* _0 M. C* O, g                }; Y; U$ a2 s$ D( h: j3 ?

* Q! @% g; H! H                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
! ]/ o% Y& v. {! X, l) _' m- T6 |                output = 0;
+ r# W& D. a# x- {; |                output += internal.Process( 0 )*vol[0];4 a$ Z3 _, Z& x( I5 J
                output += internal.Process( 1 )*vol[1];& k9 }- P- l8 u% p  w* d
                output += internal.Process( 2 )*vol[2];+ t/ \2 N( p( u, E. a( h: ?
                output += internal.Process( 3 )*vol[3];
, T1 o# M4 x& E9 u6 w# `0 J                output += internal.Process( 4 )*vol[4];  l, `' F9 `2 ]/ h

: O7 M3 T0 @$ M9 c                if( exsound_select & 0x01 ) {* t1 }7 Z! f& d9 p3 `2 v
                        output += vrc6.Process( 0 )*vol[5];
2 g, \0 _. s/ `' `                        output += vrc6.Process( 1 )*vol[6];  C% D4 ^! C& T# K1 \' b- Y
                        output += vrc6.Process( 2 )*vol[7];
3 ?4 o. G. R, t. v+ e/ J: y                }$ t, U: ~# u" w9 A$ V
                if( exsound_select & 0x02 ) {0 u8 s- e  N) `" S4 z% S. @; ?% W: ^
                        output += vrc7.Process( 0 )*vol[8];( o* a. [& D; v( B8 ?4 `8 v
                }
) z' a, d$ V4 W) z0 _                if( exsound_select & 0x04 ) {
* L# m4 W* U3 ~/ |' C9 U& k0 c# m                        output += fds.Process( 0 )*vol[9];
  a- M. z  g( _" h0 w                }
; ]# G$ `+ K) J6 D# X, a                if( exsound_select & 0x08 ) {
& @6 B4 K9 W; v2 U) j3 V+ V6 B! L                        output += mmc5.Process( 0 )*vol[10];
9 L' [+ R" r0 t" d  a                        output += mmc5.Process( 1 )*vol[11];" y- W1 f4 e; f9 d" A
                        output += mmc5.Process( 2 )*vol[12];* C9 t: R# q) v! \& w- G- U
                }
* h: D) L# b% _5 t8 i                if( exsound_select & 0x10 ) {
% m3 V/ \) ]7 v! [6 O; ~, c                        output += n106.Process( 0 )*vol[13];
6 n0 [1 e/ i( r- \$ K6 E* @                        output += n106.Process( 1 )*vol[14];
: X# p; ?5 l# k- ^* u! z                        output += n106.Process( 2 )*vol[15];
6 Z1 ]* E) ]7 Y! v/ ^, C+ V                        output += n106.Process( 3 )*vol[16];
5 u5 a3 o' i  ]3 G- ?& o7 ^9 P: z                        output += n106.Process( 4 )*vol[17];" c! |8 e9 H  M; O; C$ D  T
                        output += n106.Process( 5 )*vol[18];
& e6 v6 h) _* V; p6 h                        output += n106.Process( 6 )*vol[19];
! @6 B: T- y0 M8 R1 I2 \# p: |                        output += n106.Process( 7 )*vol[20];
2 I  L- P$ {% ?& S) a                }! W$ j7 w1 h" ^  Y) U
                if( exsound_select & 0x20 ) {
5 ]1 Q% S6 `& [/ e1 G0 r                        fme7.Process( 3 );        // Envelope & Noise
, {  ]0 x9 F$ a# E+ I# T. l                        output += fme7.Process( 0 )*vol[21];
* s# u" g, e- L' A# {* _                        output += fme7.Process( 1 )*vol[22];; @# e# T2 E6 j
                        output += fme7.Process( 2 )*vol[23];9 w3 L  E0 X. ]* {) w. t: i
                }
9 H8 x+ g6 L' Q5 ^2 e/ t7 j& F
1 y% m5 G2 h7 U& o, u/ K                output >>= 8;; r# b" }5 a6 N7 |$ _/ `" @
" w+ U+ ~/ K  |6 _
                if( nFilterType == 1 ) {. G9 y2 I9 B1 j$ H1 a
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)9 \; b4 r0 l8 M- s3 Q$ G* q; V1 }
                        output = (lowpass_filter[0]+output)/2;% F! h, k# I9 w9 s- v9 I
                        lowpass_filter[0] = output;
8 O7 q* g& d. g+ x9 o! |( G# z2 Q                } else if( nFilterType == 2 ) {
% F6 ~+ a2 [) \. G! l! E' f: F                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
- b* ]6 L5 D/ ~: O: m                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;* i/ K& B2 M; i1 a% f% H
                        lowpass_filter[1] = lowpass_filter[0];3 x+ f3 T, p4 ?* X% k6 u4 Y: T) t
                        lowpass_filter[0] = output;
( f6 \. f% M5 N4 T                } else if( nFilterType == 3 ) {+ t% C6 L: Y6 ]
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
; c9 a0 H, s1 p                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
5 H, E5 H8 D3 h                        lowpass_filter[2] = lowpass_filter[1];
* J& v' ?( J2 j                        lowpass_filter[1] = lowpass_filter[0];( y& y% ]6 R# D; S% S% R" s' ?
                        lowpass_filter[0] = output;
, b; i9 u5 z: [                } else if( nFilterType == 4 ) {
. q" ~! r* F) y3 u7 ]                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
; q: @6 u- c! X8 r                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
8 x" b9 P4 v3 `) d/ p                        lowpass_filter[1] = lowpass_filter[0];7 p( C: V3 ?  i; D; f. b
                        lowpass_filter[0] = output;
  u' X# G# h$ X; {( a9 f. P2 ^0 S! G* s                }' P: Y) R$ i, C# x  R8 `3 `$ z% S

; _( }; c9 J. R1 |#if        0
" o3 V  E! v( s( T; K+ u" t                // DC惉暘偺僇僢僩
! X; v1 z* w# ]2 k8 [                {/ X& o8 y/ n: J3 ?8 ^
                static double ave = 0.0, max=0.0, min=0.0;+ _6 m$ r6 b" y" C
                double delta;' j; l8 {2 F  s0 x% e# T& @% T
                delta = (max-min)/32768.0;3 j- _( ]7 M+ u8 |! U/ B0 u
                max -= delta;! L/ v0 L+ |6 n% b$ X9 y
                min += delta;( ~3 d# a# r' \; f
                if( output > max ) max = output;
+ ]8 @1 G0 I8 m) W3 Q$ F8 ]: a                if( output < min ) min = output;
: v. j9 C: f7 r                ave -= ave/1024.0;5 |/ v' M( }. }. V; H$ n
                ave += (max+min)/2048.0;& |( b" J) K) ~. F* j% ]) s
                output -= (INT)ave;: I0 `  M: Y5 b% J$ Z  a
                }8 b( Z- L: P% k
#endif, v# |0 R3 F' {/ X5 m! A( X, {
#if        1% _0 K$ h% Y' R' r  l" l, A" h
                // DC惉暘偺僇僢僩(HPF TEST)
0 F, N( f, u: Y2 q+ p& @: c- f1 V                {2 K, X  D" e) O4 |4 q& \* z, L
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);2 e% L- s& X2 w1 n; W3 F
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
- E& B6 [* L* I6 d$ g, A! w9 t. j                double        cutoff = cutofftemp/(double)Config.sound.nRate;
9 _% S& X  D) h$ x! n9 F9 R' z- {                static        double        tmp = 0.0;( [6 `  q; X3 c7 c3 D) ?
                double        in, out;
( f; K  z3 w# K6 N8 F9 z" x0 d
3 ^+ p: h% s2 Z8 a) e; f5 @% s                in = (double)output;; O, C$ Y  O) P, s: R/ t- l
                out = (in - tmp);- X8 {- p8 z( n  H) I
                tmp = tmp + cutoff * out;
0 p# s5 h3 w3 N# c. O2 H- t
3 B! @  X! o. `7 X- E                output = (INT)out;
# ]- j* z% f- t3 a, ]2 S) s+ E                }
) Q3 m+ }& \2 q" G#endif: X1 L* z+ U2 P* p5 @! b
#if        0
0 M5 G! w/ {9 \" C* d- }                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)% Z8 d; d2 A* F# y
                {) J$ g. I7 m* B: D& j1 O
                INT        diff = abs(output-last_data);
# ?7 n- j# W; U2 G" p                if( diff > 0x4000 ) {1 R. ]! L9 ~# m5 L& w
                        output /= 4;' p$ M+ T$ g* v
                } else 8 K" {* p# C; t/ s  ]2 o7 F0 x
                if( diff > 0x3000 ) {( U$ ^! o3 ?4 Y, l6 D; ]
                        output /= 3;7 b: u  ]8 V; C: ~1 ~
                } else* ], p) ]/ G# d! T- g
                if( diff > 0x2000 ) {
) K: }! D. B- D" V: s                        output /= 2;
, M* V6 K$ T& P$ a9 G                }( m  J8 l. Q+ `2 N" x( q
                last_data = output;0 K; x5 L/ Q3 O5 [7 c2 I: F& G
                }) U, @! Q; G# D9 u7 \
#endif& [" R3 M- Q5 X5 |, n' N
                // Limit
. A/ s- @0 e7 Q2 |3 J                if( output > 0x7FFF ) {
0 g5 o2 A4 l  ?8 _2 I                        output = 0x7FFF;0 r4 E7 r+ P7 g8 C
                } else if( output < -0x8000 ) {4 F# q/ C- s# c* h2 k
                        output = -0x8000;
& i* ~' x( H4 f                }6 f$ m4 J8 [1 v6 _0 @

- s+ w: }* m7 |( L/ T                if( nBits != 8 ) {% A2 m* i  I0 t+ e4 y
                        *(SHORT*)lpBuffer = (SHORT)output;$ z7 t, i- {8 P, X, d" c
                        lpBuffer += sizeof(SHORT);
# m0 ~# I8 Q, w7 U) ?- z                } else {9 d4 g' Z* g( M: K
                        *lpBuffer++ = (output>>8)^0x80;6 Q6 X5 U. P( S1 \- v! g8 Z1 V8 @; H
                }
; z8 B% L4 O$ [" G' L5 e- q& p: c! q5 z- K' X+ _( n% ^. ^( T: x
                if( nCcount < 0x0100 )
0 f" N4 ]# I( h                        pSoundBuf[nCcount++] = (SHORT)output;
# P  D4 N9 G2 ]* P% @1 N2 _3 k4 A) E; O5 u" @, t  z! h: G
//                elapsedtime += cycle_rate;
2 i3 b" b5 A2 T4 @3 d& I  U- k% Y                elapsed_time += cycle_rate;. Y1 [8 [. U/ B6 c, @( j& H- d
        }
4 r7 t% ?; ~: c* {2 V2 x0 h$ _4 d% e5 {3 P; m
#if        1. I3 I/ F" {( _3 K5 D: E5 H( b; ^
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {% Y+ ]7 w, d1 Z1 a5 A
                elapsed_time = nes->cpu->GetTotalCycles();$ ?' E9 F4 D1 \$ V* K# k9 i6 `3 l
        }
0 c7 k' d$ w6 M) o        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
. }& k) z* V0 S! X9 {9 r$ X2 k                elapsed_time = nes->cpu->GetTotalCycles();
2 R; _, V' k/ e+ V1 W        }
2 Z* v) u0 M/ _7 |; j3 G5 }8 [9 d6 a#else) K4 S% y: I& R: e( s
        elapsed_time = nes->cpu->GetTotalCycles();3 ^5 ~/ H- k! J0 w* o# h
#endif* E' G& y6 ~8 M' h1 i' B
}4 ~) Q4 A2 C+ Y2 y) h3 R6 A- f

, M1 m2 p2 n  p% K7 v// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
$ B! `+ s( }7 G- @4 d" p1 H2 i0 aINT        APU::GetChannelFrequency( INT no )
5 O. W8 S8 h, t{) a5 n6 F6 F8 r9 t" X
        if( !m_bMute[0] )" I' o* R" s/ R, f
                return        0;# S( V% ]# O# x. c% v( B
9 S6 `# X! y4 r8 T$ c( k
        // Internal
; h  R  [: e8 T, K4 u        if( no < 5 ) {
  g- x& U" S! u) T& s                return        m_bMute[no+1]?internal.GetFreq( no ):0;5 J/ q3 R: ]" H2 a5 J. y, B, k2 r
        }
$ B- E+ X3 M; K7 R- S        // VRC6) i& N2 b/ Z/ m" [# c
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
, m+ {5 ~  }! v3 L, l& y7 r                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;) F/ q) b! c; ]8 |. H( T
        }
. a4 a. V2 r' H3 Z7 J- m6 u        // FDS6 H7 U/ ~) |6 X. b, b) w& }8 g' s
        if( (exsound_select & 0x04) && no == 0x300 ) {
/ G6 r& b: [* B, E/ P) g                return        m_bMute[6]?fds.GetFreq( 0 ):0;
  a6 A5 u" j/ f: B, Q8 B        }3 p1 R9 F/ P) ]: z
        // MMC5( F- v% F% @* e/ Y
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
6 g9 X) \* v- D: ]# ]6 E5 l                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
# [- G: B8 M  \* h' Q0 y        }. x* G( h9 u, Y. l, W
        // N106# }9 K: M" A' M
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
2 M) t% R" {- F                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
" G+ N- H% y! p$ l        }. D8 C# k  J- J' h. P% L
        // FME7
$ r$ E1 F: r. ^        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {' {0 Q1 `5 i4 H: \: w
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
$ Q& r: d9 b8 A$ N        }
5 P0 X2 t$ n& t6 k& U- h        // VRC74 x& Q$ Z! l; F5 R
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
) G5 d+ Q/ M' P4 c' G, @                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;4 Q  W! f  R0 B0 e1 K* n) `
        }
* u# p3 c+ w' S. ?0 l& R        return        0;
1 \8 n* G4 R0 r: |1 t5 e6 b) T% v}) i& n# y8 _5 ?+ i8 F

8 O3 X7 a: M% C/ s; L// State Save/Load  T% D0 ~5 }6 T2 ]
void        APU::SaveState( LPBYTE p )
) a# p; @% F# A: e+ i/ r( D{
7 i0 V9 j7 W+ U9 I7 a- I3 [#ifdef        _DEBUG1 l, q* g# h8 q' T
LPBYTE        pold = p;
3 b  h, m- c+ U/ y#endif
( R8 K+ c& |  f! a2 ]1 t/ m' B3 L" Z" A# y' ?/ p
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
- R! V7 y5 f+ X2 L1 k0 W' A. w        QueueFlush();
* {1 |4 ^- ~; L8 M/ Y+ ]- k
0 p, |; @7 k6 A) a) F        internal.SaveState( p );$ _. ~( _7 _* B/ V( H
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding0 F# t) ]$ e5 n6 l1 r% s0 Y. s# g% g

' |( E+ k8 B8 ]7 U        // VRC6
0 I( [; P/ C2 d( c, C( M        if( exsound_select & 0x01 ) {
+ |7 H, c0 G' D+ y: o. k, W                vrc6.SaveState( p );
2 z( b$ Q" I4 N- X9 t, S                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
$ ?6 V' k0 t6 n        }
# R+ r  w0 J" C/ k# W/ T        // VRC7 (not support)
- r) S1 w% d2 H8 m        if( exsound_select & 0x02 ) {. q/ M: K# i7 {$ q! _/ p' G
                vrc7.SaveState( p );9 D' k) q1 W" q- Z8 D
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding! [% `  v& ]; m1 Y, w9 M& `1 h
        }
3 w4 \  s. q$ ]- M) C        // FDS8 B0 ?7 R+ ?' O4 V  \! N
        if( exsound_select & 0x04 ) {. N: |  I$ T( B. W- O' z5 N
                fds.SaveState( p );
+ C/ b+ [; _! f6 X% U* u                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
: U* }( `# o9 G0 i        }
+ `8 r% k6 Y8 V& A: m* D        // MMC5
& V% l% ~. V, L4 L        if( exsound_select & 0x08 ) {4 u9 u! b9 l- t7 M* A4 S
                mmc5.SaveState( p );9 Q5 b; k5 a3 v% R* ^4 _
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
9 c; A: j+ G9 Y        }
6 n! o- e- z; W        // N106; j* U1 `) z& i+ v& `
        if( exsound_select & 0x10 ) {
# P9 H' A1 k$ ~: T                n106.SaveState( p );
* w! B; Q! E8 p7 B* {' H                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding* }7 d, q; \3 z% t4 I0 ]
        }
+ T2 ?! p5 M: A% ^, h' w        // FME7' E- o0 @: a$ y) ^
        if( exsound_select & 0x20 ) {2 A; b, v) G0 q' T
                fme7.SaveState( p );# a" b  u9 e7 W% G( e
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding+ H! c) S- S" y/ L6 o! I
        }; G6 C! r& ]" Y9 N4 r5 r
5 g4 o8 Q+ g1 M1 i" _, N6 i& l
#ifdef        _DEBUG/ |0 P0 D& U$ u" d
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
( A! S  u& c, ^# ]- |#endif8 T/ z; o* K- x3 E
}6 {4 J: K3 e% T3 E2 N

. ^9 G# Y7 r7 J# h' A4 l9 Fvoid        APU::LoadState( LPBYTE p )
, m9 t# V; E& F* y' X{( O. k8 h6 d/ _6 E: D8 ]
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
. ~$ p& S6 @4 C* ]        QueueClear();) X+ h- z2 j- l7 N9 R& }' Q
+ Y+ {6 M( V$ c; y; r
        internal.LoadState( p );2 ~) v' b% c, X0 j) p( \4 j, }8 }
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding* i9 T2 H! [( m+ J1 j- E

$ Z+ Z) L! V1 U4 m3 E        // VRC6& G. j9 p1 C* \; t# Z) T4 l4 [
        if( exsound_select & 0x01 ) {
+ a3 r! D5 i. ~# g                vrc6.LoadState( p );0 j, K- [) W, E& [2 n. n3 T
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding. p2 [) S; e: X+ X& t. z% h* G
        }
$ ?+ |  P. w: m  F1 t  Z        // VRC7 (not support)
; l% a( J1 ]" C: B        if( exsound_select & 0x02 ) {
1 ~9 U& l! q$ {8 A. G                vrc7.LoadState( p );) b8 r5 P0 b! O4 M" p' ^
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding" @: Z; K! b0 K$ @- B
        }
" t1 k" [* F! x8 O  i) N        // FDS
/ x  H% T. n6 \1 {4 s* N        if( exsound_select & 0x04 ) {
! W) t6 \. H; D3 L1 N                fds.LoadState( p );
8 U0 W- i  _" `) a                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding3 A: c2 o9 P6 f, O
        }
5 C/ l/ o9 {: p; B; l0 Q. x3 ^$ l        // MMC5
) q7 y" D( ~9 g) l        if( exsound_select & 0x08 ) {
& E9 p* p9 w: ^" h% e) w' _; g- v$ c                mmc5.LoadState( p );
0 K' C7 o0 Z& s: r( ?2 J                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding# H) E8 m% R5 ^; g4 v3 e, L
        }0 f) ?! J# i- |
        // N106
5 V" F- T  a  j# C6 p) V/ \/ z        if( exsound_select & 0x10 ) {5 {# R1 q- I, g+ `, z; k; w" n
                n106.LoadState( p );
/ q9 H+ A4 [7 C% K2 b% \/ A7 l                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
3 P( `- ~6 C  |; Q1 C+ }" n, C: s        }
9 t$ J3 s" Y0 _        // FME7
' D- x6 G6 |$ |0 M        if( exsound_select & 0x20 ) {
: k5 n5 W  [- }5 O3 x/ z                fme7.LoadState( p );
2 t3 M8 H  a1 x4 H- {" Q# E: B                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
: @7 {7 q# \9 X, K) ^        }
* M  [0 k, Q" j( N  h2 J. R' \+ t}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
7 N  y% s: [- s可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。: T$ g6 K# P7 |& r7 Z3 {" @+ y( i- }3 g
感激不尽~~

3 @1 c6 D0 u, W- T; S* U* r" x; }恩 我對模擬器不是很有研究,+ @" Q: x4 d" M
雖然要了解源碼內容,可能不是很困難,
  e! l! ?" S7 e4 }& q  Y不過還是要花時間,個人目前蠻忙碌的。( g9 Q. b* v$ V3 r: k

. |5 t9 w7 o, w$ b9 g給你一個朋友的MSN,你可以跟他討論看看,4 f9 `' d/ h' G
他本身是程式設計師,也對FC模擬器很有興趣。
5 x( s6 l) @5 F" i- ?9 U4 P7 R' _# C& ~& h0 i0 Z
MSN我就PM到你的信箱了。; b8 E! t6 @) y6 `$ {6 z
  S8 h  [' p) p% A
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
6 D: R8 E/ B8 L呵…… 谢过团长大人~~
2 i8 z8 u8 i3 v1 D( i8 r0 [% |( `1 C) I( @

* n, y0 }7 u; L; e' D" F: b! i哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
# |9 v; U! P0 l团长的朋友都是神,那团长就是神的boss。

  N* S' E$ T: X5 A7 y, J  ~哈 不敢當,我只是個平凡人,, Y3 G5 {# z, I! y: V
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙+ N# M* W" j) x6 S& ?9 `/ J  N
ZYH
0 u  S& o$ E/ J2 I, O/ XQQ:4147343064 d" c  f3 ~" K7 A4 ]0 b9 m
Mail:zyh-01@126.com, S# q# E9 J7 X6 z2 Z4 I! k" a4 J; O

9 ~  p3 l' u' k, i他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 3 N0 l6 }; h; r
再次对团长大人和悠悠哥的无私帮助表示感谢~~

# E8 B; b$ a; R! t( D不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-11-25 12:32 , Processed in 1.081055 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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