EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?
( c% y+ `! {0 Z$ T5 N! B4 W. v3 TPS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。  Q! R/ p- q/ l0 P9 f9 w( ^) S2 h
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
+ |9 [& l, `6 X' r& c# n4 f这里有相应的模拟器源码,就当送给大侠了~~
7 c% s. I8 C& M5 a9 jhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
+ N& e% X: J4 R: A/ y' j能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
( \1 n  l; p' W* o; Y0 E楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~8 x* j' D0 z7 }5 a9 V1 i2 ^
这里有相应的模拟器源码,就当送给大侠 ...
2 d. S' {9 h  ~
聲音部分(Audoi Process Unit = APU):1 ^: e+ A9 N, U2 B
.\NES\APU.cpp0 Y7 ?5 D" g) y) s0 D" X/ z: b
.\NES\APU.h0 R3 ?. D3 s# i! \7 C

: [- _9 z; `- A/ j
/ {1 b- ^( I3 n影像處理部份(Picture Processing Unit = PPU):, N$ ^" t, S  {/ a1 q1 t
.\NES\PPU.cpp1 a, {/ q2 o6 y! C. j
.\NES\PPU.h
' w2 _6 A9 ]/ Y) N0 v6 Y- b$ h. v, ^- [8 o& U! H
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:% H3 m0 ?* j8 p6 Z* r8 ]+ ?
(由于很多专用术语和算法机理都不明白,所以看不大懂……)' b8 Q& h  _( {
//////////////////////////////////////////////////////////////////////////! S3 V: K) N# r; Y8 R' \
//                                                                      //& d7 B: J' R0 D) |, ^
//      NES APU core                                                    //3 }) N* N! @, g. R) T$ K
//                                                           Norix      //1 d! n8 y7 `: w. \6 c# R% |4 O
//                                               written     2002/06/27 //
( y. C5 M: o( p; U/ E$ K: C//                                               last modify ----/--/-- //1 P2 m8 x% `0 _0 v1 t: J6 i+ v
//////////////////////////////////////////////////////////////////////////$ |/ `# `5 g5 ?& z. t' `* X
#include "DebugOut.h"# L2 D5 W+ a7 ~2 ]
#include "App.h"" H' h' X/ Y) A7 ^
#include "Config.h"
. @' ?) p8 R6 r
8 {4 b+ I  Z1 f% s: S# D# }- R7 Z4 |#include "nes.h"% E: z, P. B. |! T. K6 b. v( l
#include "mmu.h"2 }8 ~0 I% S2 s5 R8 c2 v! ^( G+ l
#include "cpu.h"
) ]" V0 g1 S& X$ w# N& s#include "ppu.h"/ }3 f* t/ K0 Y8 Y8 j0 p) w. g
#include "rom.h"  K3 t4 \4 |& S# W
#include "apu.h"  R- C& u( X& y& L9 ^

5 W6 p7 X+ k% D2 v3 \// Volume adjust; q7 y# [5 k! e/ q, g: f3 u
// Internal sounds, s( _$ s1 l; f7 v/ g; S
#define        RECTANGLE_VOL        (0x0F0)4 a% D- @. i$ d5 y; Z8 s3 c3 L0 ]
#define        TRIANGLE_VOL        (0x130)# y$ R, }- f5 h( ~  p$ e
#define        NOISE_VOL        (0x0C0)
8 ]  \( Q+ @3 Q) n' Y#define        DPCM_VOL        (0x0F0)$ i# v7 M8 V9 Z; }8 t
// Extra sounds, p. m5 K2 v  r: v7 v) c' Q3 f
#define        VRC6_VOL        (0x0F0)
, J. z! W" D+ y& a#define        VRC7_VOL        (0x130)' o; ^+ Z: }/ B0 Y; }
#define        FDS_VOL                (0x0F0)
8 T* q& F3 ]  `#define        MMC5_VOL        (0x0F0)
6 E* V1 M' i* U+ \6 y#define        N106_VOL        (0x088)
) {# z. K. U) J1 L# k#define        FME7_VOL        (0x130)
) x% U5 P  d- R5 _4 q+ E3 U
; W+ y% Q( d3 v1 d/ C* Q6 }APU::APU( NES* parent )  g" B/ u. @$ x& x" j1 z4 @4 D
{
' i* S4 V1 {6 q/ O$ t        exsound_select = 0;
1 z9 b# i1 p1 U$ h) _2 J' ^0 ], v" `7 I* w3 \
        nes = parent;' a( @: [: e5 n" S" H8 E
        internal.SetParent( parent );
0 @3 [8 J4 d/ S8 Q3 o5 ~, X8 m) n
) u* s3 G+ G. _" m- T* o        last_data = last_diff = 0;
  D% A8 G7 V, `
  n; Z0 a- R: N$ u# w        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );0 U/ e3 @: ?% k

  n- M; h* [+ C+ v/ q+ ^/ o        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
& h6 H1 Y8 O9 N& \. X        ZEROMEMORY( &queue, sizeof(queue) );
1 t: |6 R' V5 y9 ?# Y" y; F        ZEROMEMORY( &exqueue, sizeof(exqueue) );$ ?: C1 A0 T# u0 f1 U* t% r3 e9 M
( I" w5 \4 N! R% u/ E$ [
        for( INT i = 0; i < 16; i++ ) {
" ]$ Q5 u4 R+ G( `7 S                m_bMute = TRUE;7 ?& q6 z2 d+ r8 C  A: L
        }
% y& G- g% X! L% s}
% a' F. \9 z3 m2 _9 X& q# h2 u3 r
APU::~APU()2 P/ G' y( Z' _( R. |
{! @3 H" _, h9 }2 t' [
}
: t$ U# I& ^/ ~* A
; ~6 F( F$ i$ W- L7 w) n. ^7 a; n2 {$ qvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )% B" x8 q; @3 N' ^! Z
{
! J7 |8 P9 z9 q8 }4 z        queue.data[queue.wrptr].time = writetime;$ s) d4 [& d2 p0 z9 I
        queue.data[queue.wrptr].addr = addr;; u$ s9 o$ H7 K7 h4 p" X0 W( W# E9 ~
        queue.data[queue.wrptr].data = data;
: g; g, E$ N0 C2 D7 v        queue.wrptr++;
; Z" _6 S2 M6 y+ x! V        queue.wrptr&=QUEUE_LENGTH-1;
! G  q; `* ~* u' F        if( queue.wrptr == queue.rdptr ) {
2 b1 M5 V& ^3 R                DEBUGOUT( "queue overflow.\n" );( C2 c2 \7 A9 d2 z% D6 Z1 ^- g$ V
        }
8 j8 f% }9 f2 m  |}* A. M5 y# o& o, C0 _2 Y
8 n: v2 g3 d; p5 [. ~1 O
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )% z9 c% M; J3 N  b
{
" Y# C  w! B/ B7 F2 b        if( queue.wrptr == queue.rdptr ) {
# J) p& u' \5 _                return        FALSE;2 G# W- {3 N- m0 O
        }9 I* H- G$ E) h8 z( H
        if( queue.data[queue.rdptr].time <= writetime ) {4 J, R( L3 g9 H: q8 m6 O
                ret = queue.data[queue.rdptr];
1 w2 _" Z# K( a" c                queue.rdptr++;$ x7 v- ?0 g2 {2 b
                queue.rdptr&=QUEUE_LENGTH-1;: D: @/ o5 ?) v" ^$ H3 ^
                return        TRUE;
# A2 o1 d1 [  A" {0 D2 u+ u        }
( O$ W1 `' z' v3 o        return        FALSE;8 h& O5 p, u0 h9 a2 B
}
. Y7 u2 S; A) d) @8 s3 _  B' E& t" F2 Y( y) f3 }
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
4 O* X0 G! {) e# n& {{
* D  C( N9 V5 U$ v. y        exqueue.data[exqueue.wrptr].time = writetime;
( b5 `3 q, n6 D* S$ }0 x2 u        exqueue.data[exqueue.wrptr].addr = addr;7 `# D8 C( ^9 E* l6 z0 `7 t
        exqueue.data[exqueue.wrptr].data = data;1 X9 ?+ Z2 |8 }  H( E8 z- \
        exqueue.wrptr++;( j, l* @/ e3 I
        exqueue.wrptr&=QUEUE_LENGTH-1;
  w( H" \3 [0 Y+ T2 o6 \( z& N        if( exqueue.wrptr == exqueue.rdptr ) {. E* h8 f* L0 @% x8 @
                DEBUGOUT( "exqueue overflow.\n" );6 j% N. ], Y& S1 s* o4 f
        }& c# l+ s2 a- n
}
  r% [* \, ?/ a, K- ]& ?4 N0 Y5 k7 u: H
: m$ H* H: k: Q  {% s8 WBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
8 a# V; o7 M( r$ p- x6 i{. A! K" `% `* K: q5 b) E
        if( exqueue.wrptr == exqueue.rdptr ) {
: }. m6 }' z  |                return        FALSE;
8 B$ T$ b' [* t- ^; E! G        }( v0 ]) X. P6 p' n: `
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {' c. n% k3 C2 V7 F: U, \' R
                ret = exqueue.data[exqueue.rdptr];! m% C* E" Y( T
                exqueue.rdptr++;$ U3 F/ y+ V/ f1 Y
                exqueue.rdptr&=QUEUE_LENGTH-1;
) L& X9 ^( r/ Y% t+ J                return        TRUE;
, f) E& A' ~5 [" @( u        }
: h9 C& `  T7 e- F& l. b7 _        return        FALSE;
! X' `1 E* A7 v% I8 w- y}
- `! Z0 \% E+ h" I. }! q: w4 O$ U( u. t! K
void        APU::QueueClear()
9 m9 {/ n5 b8 b( G" e$ N6 Q$ F{
5 l! Y5 w( N0 ^" e        ZEROMEMORY( &queue, sizeof(queue) );
- I8 T: z4 ?* Z  @+ }* v        ZEROMEMORY( &exqueue, sizeof(exqueue) );& D' g1 _) Z' @# z) I! C- V
}$ g( i( ?  g  c( w$ p
; @) c( X: A: [* c. l3 H% A' Z! n
void        APU::QueueFlush()
+ |6 A, b2 g+ A% n# j, S- j/ R{6 ^' ^- g. S6 ?9 w; N
        while( queue.wrptr != queue.rdptr ) {
( w4 d3 P. {( |2 q; A0 ~. D9 J. ?                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
" T  d  _8 B$ L+ T  j# C0 }1 a                queue.rdptr++;
- J" j) K; o7 E! ~6 ?                queue.rdptr&=QUEUE_LENGTH-1;6 w, G% `$ @4 k
        }
) e/ R2 u  y5 S% M/ f- L3 D
7 E( _9 |2 z" p* h2 B2 w& }        while( exqueue.wrptr != exqueue.rdptr ) {0 X9 @* j; j# g8 C% G& {% ]. ?# S) J& e
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );! E) v  ]# r" W8 g! K3 o/ v) ?' V0 E
                exqueue.rdptr++;- S" a9 \1 `! \# @# z
                exqueue.rdptr&=QUEUE_LENGTH-1;
% u- r6 ]0 I  z/ J# Z        }* V* [. ?+ p9 I
}
4 v. }/ \7 c& o+ r- t, `% w! k& I) h; m! S! K2 n
void        APU::SoundSetup()2 I3 x0 \" X" \2 L
{8 J) x* `/ n( ^- M2 A
        FLOAT        fClock = nes->nescfg->CpuClock;' ?6 u$ o, a) ^5 Y* i/ g
        INT        nRate = (INT)Config.sound.nRate;- [% P7 v; L, B+ F
        internal.Setup( fClock, nRate );& g7 @, h/ D- b; h4 _
        vrc6.Setup( fClock, nRate );8 O4 ]9 J& @  p0 s
        vrc7.Setup( fClock, nRate );2 f& G6 @+ R% S6 Q; z; ~- U0 Q  ~
        mmc5.Setup( fClock, nRate );
# x2 b: R5 A; [' j        fds.Setup ( fClock, nRate );
" X9 i8 N2 _0 H9 M" Q# p. L# F1 x        n106.Setup( fClock, nRate );5 i$ H3 A1 C! E4 {5 S4 X8 ]0 S6 R8 D1 D2 b
        fme7.Setup( fClock, nRate );
7 m: ~3 Z5 P* O- C' E  k}; g* [) ~8 \; Z8 t
4 h6 j# w; C1 J; p( |
void        APU::Reset()% H' ~% \6 s- M; X
{
- t0 I- g" c+ F/ H        ZEROMEMORY( &queue, sizeof(queue) );8 ]' X* }, Y" U) k2 w& M
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
' e, F/ O" A) y  \* ~! n; P$ ~& `1 h0 e$ I: }6 [9 ^
        elapsed_time = 0;
; z2 a$ k, {, \5 d
0 e2 r( n+ x: w) J9 |' o        FLOAT        fClock = nes->nescfg->CpuClock;8 F; h( r9 y$ x+ \% \9 r- c
        INT        nRate = (INT)Config.sound.nRate;
* W+ a+ \8 E% E8 L8 q, l. N) ~        internal.Reset( fClock, nRate );8 Y; B& q, C5 E$ L
        vrc6.Reset( fClock, nRate );# c. s( y# o" v0 y  ?% k! b
        vrc7.Reset( fClock, nRate );( L  C4 u% m9 ^
        mmc5.Reset( fClock, nRate );9 [3 B* P/ i$ b) ?
        fds.Reset ( fClock, nRate );" ~( s8 D8 P; h/ ?5 V* q
        n106.Reset( fClock, nRate );
. |) d( o2 d8 I2 q5 |+ M        fme7.Reset( fClock, nRate );0 w# I6 r6 P% t, `
3 b/ c5 W/ K2 c( T. \: ?, J
        SoundSetup();- p7 p" j8 ~7 ]! o
}
: Y& ]* V( j3 c6 A8 ?; h% V8 i& Y2 I: i  o: `9 k2 x; X/ a
void        APU::SelectExSound( BYTE data )3 t( }" j0 F5 d. y5 U/ ^! r
{
. D9 f( Y" o/ e7 q0 a+ U6 Y  s% q        exsound_select = data;8 e5 W# Q0 Q: b5 X
}+ {% J  R3 V9 n  N, I
- m% u/ i2 q! W& |0 k' O/ l4 P) Q
BYTE        APU::Read( WORD addr )
3 q1 c! Y1 f+ `4 a$ k# W{, d! P, u" R4 o2 k
        return        internal.SyncRead( addr );
1 z5 S% u. Z; y+ o5 `( P9 z}
( [# [( F/ ^" w6 _3 Z& _6 Q3 Y! U% v+ z% f. \
void        APU::Write( WORD addr, BYTE data )2 c6 L% S; P! c# a3 Y3 B
{
3 f( A- J" S% T) ?        // $4018偼VirtuaNES屌桳億乕僩' m8 _3 z" ?) z  g) D0 S
        if( addr >= 0x4000 && addr <= 0x401F ) {* f" q2 P+ g( Q  }
                internal.SyncWrite( addr, data );% f9 f7 C- d+ m; Z5 T* J  ~8 E
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
; Y4 U3 X! |6 {, H        }# o' a5 r0 r, O9 Y2 |- b
}6 H) s" I8 v* f& u
, u" i$ _5 P; u6 f0 ^) q
BYTE        APU::ExRead( WORD addr )% _8 y( A, V7 G" |
{. n2 t- C0 p8 U& k: A, S
BYTE        data = 0;
6 {2 A6 L: c0 q( b  \1 C7 w, s/ _, K5 e( u7 s
        if( exsound_select & 0x10 ) {
8 C" L7 i, ?0 o; q3 G                if( addr == 0x4800 ) {
  b$ n; t$ ^; a) Y' W- n; e/ _: G                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
2 q. ]/ I6 B6 t                }$ c( g) n% l- N3 C3 J) x$ i8 V
        }: `* p& m6 _/ @: o7 t7 m
        if( exsound_select & 0x04 ) {5 @3 |5 ?( T5 e1 J) L  J
                if( addr >= 0x4040 && addr < 0x4100 ) {
% ]: b3 w- |& x2 I7 J! M$ G- y# H                        data = fds.SyncRead( addr );/ J  ~. v, `* v0 s, N
                }
  |2 Z6 @; |1 ~# U& |; k+ B+ _& v' _        }
3 v/ }5 P: e4 I# M1 O        if( exsound_select & 0x08 ) {
4 Y, l  _* {6 I4 j                if( addr >= 0x5000 && addr <= 0x5015 ) {6 y) F5 S- \; R! ^
                        data = mmc5.SyncRead( addr );
3 e' |" A* x# F; Q8 g6 R                }
3 F6 m! F- u: _- j        }
4 t, f, f' _* P& k4 t5 [3 M' h0 Q
0 U! j, R3 _+ }0 [% M        return        data;* N; r; _1 E: I% T: _7 q: C# ?9 U
}( _# R2 C& v. w! T4 R
# k2 k6 n+ \, Q- I
void        APU::ExWrite( WORD addr, BYTE data )
0 r( g! Q6 y9 y4 t5 @{
3 A0 l  T. }" C# |% a/ O: ^        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );' |6 q  L1 p. J7 `) E0 p; I
3 g: G5 p1 d2 Y4 g
        if( exsound_select & 0x04 ) {
' C1 @. W" l* j                if( addr >= 0x4040 && addr < 0x4100 ) {
& d/ z7 V' Y8 p) e2 y                        fds.SyncWrite( addr, data );
+ q: q# A4 r( j                }
& O, o. }7 h0 j3 T4 m- L1 D        }
3 Q+ H% H( R9 q1 z  g7 |+ J6 j
        if( exsound_select & 0x08 ) {
  }. d/ ~, O8 c* J% Y' x                if( addr >= 0x5000 && addr <= 0x5015 ) {
; y) i8 Z2 G1 p4 Q  Y5 b4 C                        mmc5.SyncWrite( addr, data );
# ~' b% k$ Y4 F+ P% ?5 [. w# V                }
7 ?! c2 U. I6 r! n: z5 s% _, G        }
+ @/ C3 O! p7 A5 U}
5 A) i) ^2 B3 ]5 l2 Y  _( |" n. U
" T/ }* f  u" b4 s- Wvoid        APU::Sync()
! M4 Q8 d( g4 M, p4 k{3 \/ o+ r5 i" d$ r. U& `3 @
}$ e0 x3 @; A* W- O

; C. g6 c6 u2 m7 u  uvoid        APU::SyncDPCM( INT cycles )
1 s# m% C+ a) T% u2 s: n{! i: m, m. Z5 j$ {2 ~/ ?
        internal.Sync( cycles );$ E# |& j& W7 i. J" O2 {

' x# [: w4 b% e1 D" Q' Y$ l        if( exsound_select & 0x04 ) {: D/ O  U" ?7 J& `$ J
                fds.Sync( cycles );+ K8 \8 n  q9 j6 e+ R( u
        }
; L1 q) F4 \( t0 z$ |        if( exsound_select & 0x08 ) {
( R: s  I: @& {5 K/ T5 V3 G                mmc5.Sync( cycles );; X3 d1 _7 _2 v- _& O; I7 `
        }9 A( A7 o5 k8 t
}8 T: I3 K" A- T8 ?+ ~9 h

) S9 C5 o2 {2 {2 I" Uvoid        APU::WriteProcess( WORD addr, BYTE data )
+ C/ g: a# V6 W  D. Q& w% d' B{/ v' N  G) S# |  n1 I
        // $4018偼VirtuaNES屌桳億乕僩3 Y" G( C/ a) b
        if( addr >= 0x4000 && addr <= 0x401F ) {
8 m- F2 v- X6 P, d  [                internal.Write( addr, data );4 \% ~- `3 d, ~1 }: y
        }
% A+ {  o7 J) w4 k}
) D3 R4 F. j* a4 u( o. A% g8 G) J* |7 I# c; I* d* r4 t! n3 m
void        APU::WriteExProcess( WORD addr, BYTE data )& p' _/ m& c" `  r( W
{
/ i7 Y/ i7 v  h1 ^$ Y: A0 t; Y        if( exsound_select & 0x01 ) {( D; @$ g0 |0 Z9 G% U! |0 Z. M" K6 M
                vrc6.Write( addr, data );4 e# G# G- f; I1 l7 z; C( I; e
        }7 k. q0 J0 b, z" v4 g; I
        if( exsound_select & 0x02 ) {' f2 ~$ p2 s- n% b* |) O! N8 v& ?
                vrc7.Write( addr, data );
5 `- ~9 O& o  p        }
5 U- `$ c; a3 i3 `  x, i        if( exsound_select & 0x04 ) {' k$ V% E! X4 R5 q, c
                fds.Write( addr, data );
0 `/ V! ]0 h, e  F        }2 D8 H- M( L' T% p, E5 i/ s& X' n
        if( exsound_select & 0x08 ) {' P( _5 l* t* ~% H
                mmc5.Write( addr, data );
5 a# r) q0 ?# f5 \$ W, I        }2 x3 A8 ]6 ?+ d' r
        if( exsound_select & 0x10 ) {7 A% o, U% `7 K0 k  l' N# K, x
                if( addr == 0x0000 ) {
# \  n6 R( U/ {                        BYTE        dummy = n106.Read( addr );4 D; f1 y/ O7 [
                } else {
# J+ ]6 C* d1 }+ ]8 `                        n106.Write( addr, data );
# U8 S/ D6 e# i- a7 K3 ?                }: H  S$ p% t+ }0 a
        }% k5 Q1 Q) @# c( \
        if( exsound_select & 0x20 ) {0 o% t0 v3 a2 Y
                fme7.Write( addr, data );
7 B' O; a7 T- F        }1 r) r) m) g* e2 x
}
1 I( @0 b( n3 T5 d( S/ w
0 g- p/ \9 D" Y8 F8 c6 l; o- ovoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
- ]$ k2 o: k2 K: X- [& |8 [{
; H" m2 U! q$ c  u# L0 I6 IINT        nBits = Config.sound.nBits;$ U& i$ f( o9 u5 x! m5 r
DWORD        dwLength = dwSize / (nBits/8);
; [5 o* o* V5 `4 m( E: gINT        output;
  R2 }1 H7 B3 x; w+ p* F( bQUEUEDATA q;+ b/ d7 [+ C9 V$ @3 G7 Y
DWORD        writetime;& X% E0 A( Z& E1 E. X* m
7 U0 i% [1 ^9 u0 G
LPSHORT        pSoundBuf = m_SoundBuffer;. T, C7 D, B! N
INT        nCcount = 0;4 G& T" a7 r2 Q1 X; c8 z* f) ~

8 l! h$ \/ M+ \2 }! a2 cINT        nFilterType = Config.sound.nFilterType;
/ S& E/ o/ e( s$ q- S8 ^4 L/ B! ?
4 f! ~7 }& ?7 v  k1 z" f        if( !Config.sound.bEnable ) {( x- T/ P  {9 N
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );8 e: g2 n9 ]0 i; f  o1 Z6 y
                return;" i4 j9 u% H# k6 S6 U* ]
        }) n: f2 u, x0 W) z- B
* ^( F: s' ?1 T! I
        // Volume setup1 ^" h0 Z4 V; K4 c7 Y
        //  0:Master
- T  [/ k( p. ?! z1 y        //  1:Rectangle 14 a# r0 T* L6 _0 {5 i2 }5 s' [
        //  2:Rectangle 2
" }+ V0 R6 C, C0 o* f        //  3:Triangle: j0 @/ c, H4 G/ ~
        //  4:Noise4 [' s6 i9 e/ l2 u( Q, S) [
        //  5:DPCM
+ Y% B5 P2 U- N/ m+ n% t        //  6:VRC6
  s4 H+ a4 e8 t! H* b        //  7:VRC7
4 ?; N$ \2 L" B4 N6 p! t        //  8:FDS
. q0 l6 w1 x7 p* k: V        //  9:MMC5
- i$ C6 c2 I8 b2 d        // 10:N106
5 T+ P9 m8 u. V1 M+ H8 a( j7 C        // 11:FME70 Z  M; z+ q- j  r# d' D
        INT        vol[24];
  V4 V6 p8 d; J; Y% w        BOOL*        bMute = m_bMute;0 L# f8 F) C( H5 x
        SHORT*        nVolume = Config.sound.nVolume;
2 x# j+ D, e& n& [0 v; n6 w
1 ~6 l5 H! ?6 k* z4 S9 B        INT        nMasterVolume = bMute[0]?nVolume[0]:0;: @- f2 L& |1 A/ r5 u  A
# t" s/ j/ D' S9 w# Y
        // Internal
! Z6 w4 w# u6 ]: r        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;' T: e5 u; Y% C; g- ~1 ~* _+ f
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;# c& Y  ~( Y3 m
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
0 o$ Z" ~2 t7 M        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
$ Z! [( c7 V; q6 }        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;% K  C0 V+ d+ b  e$ {9 A

, Q' P/ @; F' B        // VRC6
! M( e( x: |% o# I& H) ~- Y        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
7 w0 W4 |6 a9 E& }7 d# p        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;8 M$ ^( I* v" f; p; B
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;3 N8 j! T" V6 E* W. `/ ^

2 }7 a6 T* M& r" q        // VRC72 }; }7 ~* j4 k
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;8 U" ]- N& P9 v. u- Q5 V! ]" B( J

" H/ p4 i1 h( q( Z: C& k  w" z        // FDS2 |# _/ h' n5 r: f
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
: ~2 r1 @( F, K  ?  z
" f( j) t) w1 G3 `7 {0 g        // MMC5
6 U4 ]& q4 G: o. ?& [! F        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;, d5 E6 b8 x+ b9 R: ?4 J4 j1 ~2 g" G
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
  z( k! ?) Y1 K, _        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
( A) e4 L- K1 X* a  V- W0 ]5 m) j0 Y
        // N106* @$ U/ e5 r( O; o7 q! |0 r
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
. Y& Z$ w' ]; b; l        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
! B/ x0 f3 A: R) `1 X        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
( F% ~/ c, m% C! x3 R8 Y  w8 _        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
9 C! p% n& y  `9 H" ~        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;- H9 z$ N7 J1 e$ u; t& S
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 f: N5 z0 j; l& V  n; u! z
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;8 e) G  l9 L( c" X* Z& m
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;' b! F/ K: k8 u7 ?/ X
4 q: \6 ~) h  x$ |
        // FME7$ J/ D, f9 o: F; e& K
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
# t2 f' y, D- F/ Q1 d        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
5 y/ g& c- m! Z        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;  `9 |  `" j6 `- i  @

/ u2 z9 F: K  y& p//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;; T* Q8 C2 E, u+ p) y; w
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;3 W- M2 H) r" V, \
# r0 S0 \( C6 E1 a, Z9 x9 y( f0 D
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
9 L! t/ D. _. v4 U+ U8 O        if( elapsed_time > nes->cpu->GetTotalCycles() ) {6 i& h6 N9 _3 G& N
                QueueFlush();& U6 p% w- Y. }
        }9 Z' ^0 D, @  B% q9 a( H+ v  J

8 l$ |1 U8 J& R5 b1 p        while( dwLength-- ) {4 Y5 t! l3 M0 v; I' X' t
                writetime = (DWORD)elapsed_time;
; S: Q5 {4 B7 l: U$ Y5 r/ I# f# F1 A; _+ M: j8 Q, v; z# c
                while( GetQueue( writetime, q ) ) {0 `. h; Z8 j  B6 h5 A* m) u
                        WriteProcess( q.addr, q.data );
' R* }8 ?- j; H. H* O& f                }
. c  C* k, s# Y. G
& r7 F6 A  G. w; `                while( GetExQueue( writetime, q ) ) {
" t# l. m4 O8 q# N+ Q3 M                        WriteExProcess( q.addr, q.data );
% U. q1 H! u$ e                }
) F6 Y- q+ V0 V! R  ^& N; V4 w) E& u  _8 Q5 _+ p* c4 C7 @
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7& E* r, j5 `) d' m
                output = 0;, ^% S0 q5 Z4 @" I+ u
                output += internal.Process( 0 )*vol[0];
4 K; g8 G8 p' d6 U4 N0 D                output += internal.Process( 1 )*vol[1];
" ~% O+ q1 w8 O! M+ ^. @7 H                output += internal.Process( 2 )*vol[2];4 p, [" J) U; t& p4 e
                output += internal.Process( 3 )*vol[3];( i9 u1 x% U/ Z3 ], i
                output += internal.Process( 4 )*vol[4];
# ]& ^6 c7 [& ~* U
5 @/ x# B/ t' Q5 t5 x# l2 b                if( exsound_select & 0x01 ) {
2 [2 F  q% r2 \8 K+ L                        output += vrc6.Process( 0 )*vol[5];' w7 H0 F' {9 [, o9 }/ [! A( t# u
                        output += vrc6.Process( 1 )*vol[6];- O3 R- y* G% {: W
                        output += vrc6.Process( 2 )*vol[7];
7 b) u3 O. ]+ A                }: i. d+ `' s9 d7 B% R$ ]
                if( exsound_select & 0x02 ) {
1 J7 ~: v5 D0 D6 B                        output += vrc7.Process( 0 )*vol[8];8 K% k$ D5 d4 |" t& l
                }
+ h# t9 K& L, e/ k+ j. e0 y                if( exsound_select & 0x04 ) {: i' r: \, X* n9 ]% o
                        output += fds.Process( 0 )*vol[9];
; \4 q$ n/ ?: M                }- I# s% ~* V6 j1 A1 Z
                if( exsound_select & 0x08 ) {: X/ P" C, b9 |- z% U+ J0 d% D
                        output += mmc5.Process( 0 )*vol[10];/ |% E5 x/ p3 R+ R
                        output += mmc5.Process( 1 )*vol[11];* ]! ?' e; q1 F7 F8 g
                        output += mmc5.Process( 2 )*vol[12];
/ A4 y* U% S0 U1 c# K+ K                }
; k) L( o+ ]. ]                if( exsound_select & 0x10 ) {
7 z7 @5 y9 Z- k/ c, m& M8 C                        output += n106.Process( 0 )*vol[13];
# Q7 G# Z& _$ A) X* y' G9 |5 }& X                        output += n106.Process( 1 )*vol[14];0 c" ~  R0 H. I+ M5 a; s2 l0 q
                        output += n106.Process( 2 )*vol[15];
; T: S: U* M% a1 T  H# l  M                        output += n106.Process( 3 )*vol[16];* q" r) d, u5 }% x0 T- v$ R7 {
                        output += n106.Process( 4 )*vol[17];
6 s4 i$ {* j, n0 V                        output += n106.Process( 5 )*vol[18];
9 N3 Q3 P2 G3 w2 P* W7 o) F                        output += n106.Process( 6 )*vol[19];
. g  l2 {7 q8 @, h% \+ Z                        output += n106.Process( 7 )*vol[20];& A& p% Q0 a# k6 e* f: z, A2 P2 _
                }
& f% P: \' R) j8 }" r7 ?                if( exsound_select & 0x20 ) {
0 d9 j5 }! v: o+ q  R                        fme7.Process( 3 );        // Envelope & Noise- {% F: D; D# ^% G9 J9 g, X8 r
                        output += fme7.Process( 0 )*vol[21];
% F! d+ V1 g6 B# k( h0 a                        output += fme7.Process( 1 )*vol[22];
2 b; P5 A) }; [% {                        output += fme7.Process( 2 )*vol[23];
! U" m0 T, Y  ~! ^& Z7 ~) y                }0 Z8 G* T2 V8 _+ Y+ W
* M* m2 P  j0 K5 H( y+ F  Y
                output >>= 8;
; {/ e1 ?# X8 G8 n& H& \7 h5 J3 M* ]; Q% A
                if( nFilterType == 1 ) {
/ r5 W! M+ o1 e7 D                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
7 i* v0 @: q% L% k% a7 I0 ~                        output = (lowpass_filter[0]+output)/2;) ~) q& k4 L' T( p
                        lowpass_filter[0] = output;3 C0 p( C( w& ^/ n
                } else if( nFilterType == 2 ) {! O! \& U- L0 w4 a$ g# S5 k
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
: V3 ^, x  t0 `, [* v                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;* ~4 c" z5 v2 G! \2 e
                        lowpass_filter[1] = lowpass_filter[0];
8 h* _; z' d' U0 [8 H0 m- s8 ^                        lowpass_filter[0] = output;
$ D* E. C, W' R6 k/ f6 d                } else if( nFilterType == 3 ) {
* h" l: e6 P% Q                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)/ K/ a+ k3 g# _, [% `3 }+ h$ m
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
* z  s* A" E0 Z- {: s4 W+ U                        lowpass_filter[2] = lowpass_filter[1];* y" s; X" ?% t7 o. E' P" Q+ C
                        lowpass_filter[1] = lowpass_filter[0];/ e/ B% @5 U9 Z
                        lowpass_filter[0] = output;0 m# S  \; \$ A- ?9 L6 a( Y" ^+ w
                } else if( nFilterType == 4 ) {
8 |  |. }3 |: B- {* R4 W/ ~$ {                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)" F) p8 s2 h! A) w/ V( A) R$ ^$ b
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;) b$ E2 X' }- @6 M% X4 Y; F9 C7 K6 G
                        lowpass_filter[1] = lowpass_filter[0];8 \( n5 p6 {$ B
                        lowpass_filter[0] = output;; X$ c) j( ^6 @' Y
                }
+ a$ H# Q% W5 `, o' e# N& R! s
0 m4 e( N1 m1 L. m" `$ o#if        0
( C0 V* m) i) x  L. w2 L3 o                // DC惉暘偺僇僢僩* H8 f2 I% z  d, @. ^+ [
                {: T8 j/ [+ H, M0 v/ i" C4 H, U
                static double ave = 0.0, max=0.0, min=0.0;  k+ z  z3 X+ E" Q  w. Y' O/ v
                double delta;
1 ?4 I& p) L, w4 _                delta = (max-min)/32768.0;
+ P0 x  p# I& K                max -= delta;
. @2 x$ T. m0 Y& D/ s                min += delta;
# n  }- |6 O  Z/ e                if( output > max ) max = output;
2 Z4 p0 m* }: u! G8 @8 {                if( output < min ) min = output;
) `/ C* o6 x, U- \/ J/ ]! m                ave -= ave/1024.0;
- ]* ~" V2 X& }                ave += (max+min)/2048.0;
4 U1 l6 k0 w% J. L) i$ H. V+ Z                output -= (INT)ave;
% I6 I7 _; D: @1 x! \$ o: K: ]' @                }
6 E, ^/ {" S1 m+ B$ ]! J/ v#endif
) c/ o2 C4 R; n; W' D# I% h  k" U% Q#if        18 ?- `# Z+ ~. b; i# a" ?
                // DC惉暘偺僇僢僩(HPF TEST). T: M) j" a9 s. f6 _
                {1 r# t* Z$ _7 ~. Y
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);- D) T7 v9 y# ^$ G  M+ [$ M% w
                static        double        cutofftemp = (2.0*3.141592653579*40.0);  z  ^* m- {, t* H, O( m! G
                double        cutoff = cutofftemp/(double)Config.sound.nRate;& e7 x  h$ M4 n* F& m
                static        double        tmp = 0.0;
3 v" y$ w! ~0 a                double        in, out;  Z) `& t% b+ ^$ K/ l

) X$ ]1 i4 G# l                in = (double)output;
" s" i% H* @6 i1 t' O6 n                out = (in - tmp);
0 P' C* V( B) H. s" R7 \# m! |                tmp = tmp + cutoff * out;
) a% H& Z4 y; b. w4 r* I9 Y
0 I6 i& b- C7 ~8 m$ G! r                output = (INT)out;$ s2 w4 R' I7 ~7 M- N" t
                }
8 Y$ |2 k. K8 T; V# t+ _7 i: @9 b$ Q#endif" T& a' L2 A2 F2 }* _
#if        0
6 H% `4 N0 j* x                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
" j8 a( [. ?# q8 g3 `                {
' p1 ]( Y7 X5 M% }% e' \' r& X% Z' y                INT        diff = abs(output-last_data);) J  V! U8 g( T: ~) k0 E' e
                if( diff > 0x4000 ) {
" T) E4 q1 I1 f( ^- _. i                        output /= 4;7 R, b5 C8 L# o% C
                } else $ ^! C& s/ d" u  s! @
                if( diff > 0x3000 ) {* }% E' q- O4 C" q5 g3 T
                        output /= 3;
4 T& m0 k0 o& |. k$ B; c                } else
& F: N4 o. U, ^$ B7 N9 @5 r                if( diff > 0x2000 ) {' I4 K% I' D8 C0 f5 X9 S
                        output /= 2;9 z3 o3 ^; H# [* w' G3 b
                }
! }" u0 ?) J) E8 L/ D9 b" n9 O- Y                last_data = output;
; ~& F1 {6 N5 S/ Y& z                }% v" _. r/ U4 e4 q$ H
#endif/ c0 J6 o3 W  d. @
                // Limit
; @+ y8 P& W$ u0 _5 {                if( output > 0x7FFF ) {0 P/ o6 p( k% a
                        output = 0x7FFF;
+ H/ l5 h: M1 ]. M. R* \                } else if( output < -0x8000 ) {
5 P" c: I2 ]" s1 `# Q) s) y                        output = -0x8000;2 O" y9 B! D9 L# R9 a
                }4 S8 r, ^; R- n- m' E& G/ _7 i7 Z

/ u0 n( q  F3 `% ?8 d/ n( P- c                if( nBits != 8 ) {8 t6 }( _& w4 C# B( a0 f) w* |
                        *(SHORT*)lpBuffer = (SHORT)output;
4 Z% B! J9 {) q; V3 {/ \                        lpBuffer += sizeof(SHORT);' W  v' g+ e) B  v' e$ c4 M- l
                } else {4 C5 m% A/ A! z3 t. u
                        *lpBuffer++ = (output>>8)^0x80;
4 G1 [% x$ J& G2 W# b9 e3 Y) E                }
7 n& L' H5 L$ F( `- e- ^( ], ^2 A0 v+ }% {! F& L) o+ ^# v9 J
                if( nCcount < 0x0100 )
; b# G; v) q0 n% [& N1 S                        pSoundBuf[nCcount++] = (SHORT)output;+ F6 [8 E3 l" R! I) U. d6 E$ \" _6 v

0 o" ~0 Q, z0 m9 ^) A//                elapsedtime += cycle_rate;
5 P% {) r% W, ?0 s, b                elapsed_time += cycle_rate;' [4 c" y, A. X" P6 s& Z: j" v
        }2 n( a( r2 ?( x% P+ y

( R$ b2 T0 v8 Q7 v) ]& r- r  `#if        1" d9 _' {& Y, F3 ]+ g- O8 g
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
% V9 R9 G* z2 u( t8 W6 @& [( k                elapsed_time = nes->cpu->GetTotalCycles();
) J5 i8 Q& m+ b6 M( p        }
! P) U) Y5 P) F        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
4 ?) u7 G4 q8 X+ E4 u$ B6 |  v                elapsed_time = nes->cpu->GetTotalCycles();
- M! H) B/ a9 ?/ y- C7 s        }
6 e* \0 A( z, |  _( D#else- s- j) o, [8 E' G; G
        elapsed_time = nes->cpu->GetTotalCycles();5 M0 v: P" X/ z& F; J
#endif
! w- ?. W/ F8 H: k* c3 Q}: `1 j& B9 `5 i/ u

/ C' q/ Q! C5 Q' R# n// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
. j, k6 f; B, r! A4 @6 p% mINT        APU::GetChannelFrequency( INT no )
6 \- a* D7 F4 H) c9 i" b{. F( e' T1 o+ R; q: `$ O
        if( !m_bMute[0] )
1 j7 c  C/ J6 H5 m2 Q* R                return        0;7 W! `2 ~7 R2 T3 z6 {

2 J( s  `! H' s$ B4 r5 P/ U9 l        // Internal
/ k% u% N2 h. E$ z& D        if( no < 5 ) {
: g: ?- {# j$ d1 K- G  I                return        m_bMute[no+1]?internal.GetFreq( no ):0;" e. P; ]- b0 j9 f0 B, A
        }5 s/ }$ e1 `: a
        // VRC6( W9 H2 j/ u; W8 Y" c; n
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
$ J  y0 z( S: I; N' [+ x                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
% l- k- p. T: r        }, p6 Y4 f- N; [( M2 O9 a
        // FDS( f3 I# f4 Y- I0 ]" Q/ Z
        if( (exsound_select & 0x04) && no == 0x300 ) {0 o6 E! j8 d" f" t* a
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
5 q6 \( v$ P% d; d        }( x! H4 P8 v# K2 j' Z& Z% o
        // MMC5! `* i+ }- j- b6 g, e9 [
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
- B$ D/ N. j$ E" W9 z* K                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
7 p6 n, }" G3 [; O  r        }
$ q+ t* C0 ~) X# o        // N106
' j3 M- T$ E$ n* r; c        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {* r( c. f) X/ @, n8 ]' D; Y
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
2 K, x6 `; I: p9 k6 d        }$ V6 N) Y0 \6 U3 |) S0 C
        // FME7
- |  [- C$ `+ d7 q        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
' ]6 ], D9 w/ {  o+ B& v                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
9 l" d/ }4 R4 F0 S        }# K- R  @) E0 N$ I+ a1 b
        // VRC7, s9 u% s! a' L( G$ I. W
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
& @9 _5 m/ N& s$ q+ U: o                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;- \# F- D( O7 o- Z9 k3 {
        }4 _4 S# o9 q8 a) j( n0 C
        return        0;+ R6 ]1 `# n7 S6 m  m5 ]; u- v
}
. o9 N) y- T) T  J& R0 L. C; U+ q2 E
// State Save/Load
- K: o* d3 W* K' zvoid        APU::SaveState( LPBYTE p )
3 k8 X( t# ^( R& w% c4 t{
& x& B( h2 `* x4 A$ G7 Q#ifdef        _DEBUG
+ a6 \- O1 O' j; o1 N" G; p3 \LPBYTE        pold = p;
* c! Y/ ^& m2 X7 T2 f#endif
* `+ D% [/ }. G7 g$ k5 @) ^. g6 ~+ B- ^
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞+ x* ^8 S3 A3 b! [- v6 N
        QueueFlush();
. k+ W, x' J, x+ q
5 K7 }7 S; s" w) b. V1 ~; |. z        internal.SaveState( p );) L4 N4 P9 Z' E; t9 F  S8 B( K( ^. {3 g
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
$ m/ Q% E: }1 Z, G( \1 O4 ?) r, ?* q0 H* r) X- j3 u. Y
        // VRC6; y+ H3 j, O; T6 H& c
        if( exsound_select & 0x01 ) {8 y0 s" C2 h- z# T" C, B# G
                vrc6.SaveState( p );
9 G: ~1 r$ N( Z( T( D' _3 S                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding6 d3 R" y9 Y8 L; ~: b  j
        }
' H4 {. `7 e' C        // VRC7 (not support)
# l- d& d) U" L* B* H/ T        if( exsound_select & 0x02 ) {% o( Y3 W0 o+ j& \; R9 X
                vrc7.SaveState( p );
0 I- o' g$ N! S7 j: i, z                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
" L# @' T- w" t+ m/ ~# O( S' `0 I3 D        }
" G9 ]6 J: [( m1 Y% _# E        // FDS
. p( R  O- _+ v4 Q        if( exsound_select & 0x04 ) {/ i' K. S$ k# [/ B9 G
                fds.SaveState( p );
  r9 [0 \- G+ W+ E- o2 e                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
& D, o% i2 V2 m; q& Z        }6 y& g; O. s) T( L4 J! j* `, d
        // MMC52 _) m. i) G5 z
        if( exsound_select & 0x08 ) {4 h2 F( f6 P2 C4 c* l
                mmc5.SaveState( p );0 u! p+ y: d; o( i
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
7 D+ z/ L4 y4 x" t        }
4 a9 T) r; ]7 y        // N1065 L" A4 e8 H& q, t4 ?9 j% B1 v. m8 o
        if( exsound_select & 0x10 ) {  a" ]3 \0 ]) T3 s& y8 v# w7 J
                n106.SaveState( p );
" E+ j% f+ n  i) W5 J                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
- g6 k+ v' C7 z  ^, x. n        }+ i2 `; R# g' n. r) E/ c" V# p0 B
        // FME7
3 G* U8 Q5 t3 ?: Q$ M8 d        if( exsound_select & 0x20 ) {$ D% `+ b8 N  f0 `
                fme7.SaveState( p );+ E6 g4 ~% d5 ~5 ?* P5 J
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
1 c: g( ~& u" ^% _" b        }
+ g. m$ n, \/ s
+ x* M& B2 u0 S& q#ifdef        _DEBUG0 U1 [3 {* L8 b5 G. ?- b
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
5 }0 X. I9 T- Y, Z0 q#endif
) _  H- F# k- ]- ^3 @7 o" [}6 R" g7 o& ^# X3 `: q3 s

' @1 [: p0 W2 Q) F: y3 }2 Hvoid        APU::LoadState( LPBYTE p ): `) W5 ~1 t' m5 Y  Z6 Q2 G
{8 \% k' W: ?9 ^. Y
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
/ d) j5 \6 f$ \( f        QueueClear();
& L# ^7 t# O( y0 R9 S/ E1 k7 y% A. W
        internal.LoadState( p );* m) ]/ R" a. }# H4 H( d
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding/ l/ M+ B% D8 h( N1 {1 X9 Q
3 ~% A7 z1 ~+ H+ R9 A  T
        // VRC6! p; E  Q2 r" h. Z0 n. w/ S' v
        if( exsound_select & 0x01 ) {. @  a9 s* \! m2 u/ ?* _
                vrc6.LoadState( p );, A' X" |$ o% `) G
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding' b6 G4 c' D& l! Y. ]' k0 x& O" p; i, E
        }
4 V: C( P) n5 ?  m: i5 i  G! Y        // VRC7 (not support)) v) [7 ?* ?/ z( }
        if( exsound_select & 0x02 ) {; U  H" }! n2 F6 p1 o
                vrc7.LoadState( p );
& ]& a; G3 t* [                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding( {7 ~1 }/ s' ?
        }2 R+ B$ l+ i9 r' Q3 z8 P
        // FDS
! X% V  m( x  j- H0 Z. {/ V        if( exsound_select & 0x04 ) {
9 c) |1 Y# q* b; ?9 x                fds.LoadState( p );* B& s* N( u6 U. p( l4 V1 V
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding$ o1 P$ j# @3 Q, f; [9 d! F
        }0 e/ E- @$ E. a" j
        // MMC57 z+ R% \) p; m" s
        if( exsound_select & 0x08 ) {
: k* t$ U; @% w. `* G; h) R                mmc5.LoadState( p );
; w' |/ j9 ~: c, y                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding/ B, |6 l6 @/ m8 K  Y
        }! _& S$ G- n4 U( x% T& n* U
        // N106) t# v6 [& U0 _! g. f" F8 E8 H
        if( exsound_select & 0x10 ) {
/ g9 |2 F. B2 N4 ?+ b                n106.LoadState( p );
3 {7 X; C/ i* {9 l8 e$ g8 f% n                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
2 q6 I4 D" [; M/ X- n        }7 G, ]) h1 F  g4 e
        // FME7- Q# q. @! ]  d1 q
        if( exsound_select & 0x20 ) {
# {5 N7 a; D  n                fme7.LoadState( p );. P7 N/ Y$ R0 q" J( u' ~5 l
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding- e5 J- h' r0 N9 p  {; o/ c4 E
        }0 I6 X5 a8 @4 T# A; j7 T0 n0 h
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
7 A9 |9 Q: g: v可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
" L; b; s) x0 ~: j9 r6 ^8 y感激不尽~~
2 l& d9 O0 D( ]$ H( }8 w
恩 我對模擬器不是很有研究,
8 c! a. x  j* D雖然要了解源碼內容,可能不是很困難,; s6 n! ^. [% ~6 O8 K5 V9 c
不過還是要花時間,個人目前蠻忙碌的。
( _; }* q6 H7 I. D
* }: p/ H) j( r  \* D2 J9 p% E給你一個朋友的MSN,你可以跟他討論看看,$ c8 I' W! s, s* A4 E8 L" N0 E) H* E
他本身是程式設計師,也對FC模擬器很有興趣。
$ Y  [! `, S7 y, Z8 q; J) s6 o3 Z5 Y
MSN我就PM到你的信箱了。& o0 g$ n5 l9 F6 d- ^# T

! u* v, Q3 P# C' x& E希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 3 T) }- F3 ^( H6 A( g! c
呵…… 谢过团长大人~~
2 _+ {0 N: M0 Y

  z$ F1 j: y7 w6 j/ _% K5 O3 ]哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 6 L% M/ ?! ^: p$ K
团长的朋友都是神,那团长就是神的boss。

  t2 O" |+ P2 F0 L- Z8 q哈 不敢當,我只是個平凡人,
! r  Z/ U  l2 n- U2 |要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
$ t( H& B7 |# J! jZYH. I$ d( v0 f- k0 j0 u
QQ:414734306
$ F1 U6 c0 K) J/ h% J9 v# zMail:zyh-01@126.com- E4 @& o' s- M3 l# a

" q; X% p8 I& L+ d他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 5 a3 u6 @) s, a1 \# @7 q6 P
再次对团长大人和悠悠哥的无私帮助表示感谢~~

6 q# n8 ^' J. {不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-2-9 14:17 , Processed in 1.096680 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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