EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?
$ z! V8 `( s* G6 l7 OPS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
" Z& b1 S, ?7 J楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~; p2 o, c2 g7 {  x$ [7 D* n
这里有相应的模拟器源码,就当送给大侠了~~
  V# c) c1 K$ m& e, t% Ahttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
5 `$ T: G, Q7 g# K' h3 E$ O) e8 c能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。( D5 x) t& Q" G. ~
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~# ^  I/ a6 d( B* {0 ~) b+ Y
这里有相应的模拟器源码,就当送给大侠 ...
1 a$ s+ E& W5 [4 E, G- i8 j
聲音部分(Audoi Process Unit = APU):' r$ e: n/ A+ j' d+ M% p8 @
.\NES\APU.cpp& }' V8 E  P; T2 S
.\NES\APU.h3 j/ b* C' U$ }

* b) m6 M% [6 B6 H
0 a  S1 V* f3 w影像處理部份(Picture Processing Unit = PPU):7 S" \# n9 ]5 @3 I- l
.\NES\PPU.cpp
8 }( M  T; d0 }# I5 z.\NES\PPU.h
+ e# z4 Z9 [" R% A6 U# ]; y# Q2 [  _9 C5 R1 O( T& T
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:7 j) O0 B7 M: n7 g" K
(由于很多专用术语和算法机理都不明白,所以看不大懂……)! R; g& X1 H3 @. D
//////////////////////////////////////////////////////////////////////////4 [' r% X+ R7 |  J/ g# j; M
//                                                                      //- Z% L& @6 \  }. Q  o" t4 O! K
//      NES APU core                                                    //# j1 d( ^! k* s5 W
//                                                           Norix      //% J: J5 V" z( B  e6 ?8 G# Z
//                                               written     2002/06/27 //
7 W, F, W2 M$ z* A+ R3 Q; p//                                               last modify ----/--/-- //, U5 q* U7 V/ U3 Z
//////////////////////////////////////////////////////////////////////////$ t6 E, W* e/ E- ?& z, |) f5 ~" S
#include "DebugOut.h"
6 Y& [8 H' |$ h& A7 \#include "App.h"6 V& u  x5 c5 r( i9 X
#include "Config.h"/ ~  g+ l: E+ Q

9 p  O3 L% }$ o6 U8 K& K#include "nes.h"
/ s% L  p0 A% \  f& S#include "mmu.h"; e" ~: S9 }% K2 G3 f
#include "cpu.h"* I1 @& x5 |* p6 b9 L' T3 e! z9 ^
#include "ppu.h"
  v  b9 k1 [9 Y$ L% B" ]; [#include "rom.h"+ {7 u% i9 j% O6 g, S1 _1 L, S
#include "apu.h"
, J! m( N: _7 C) F, Z- D, K2 e" F2 x: |
// Volume adjust( {: N& d; U$ q1 X9 q
// Internal sounds
; K4 A' W) a. j* D. T, v0 ?! T. O  j#define        RECTANGLE_VOL        (0x0F0), q# j1 n. u; y
#define        TRIANGLE_VOL        (0x130)7 c2 J$ L: ?5 R( z1 i
#define        NOISE_VOL        (0x0C0)
0 i9 a. R* i0 O3 D! V8 k#define        DPCM_VOL        (0x0F0)" f7 S  d, _% Y& ?( N# ^
// Extra sounds0 R! F, k' p/ Z# K6 V
#define        VRC6_VOL        (0x0F0)
. M( d8 y3 u; U# D; I" f7 b" J#define        VRC7_VOL        (0x130)
7 r$ B/ f+ ^- R! s( R#define        FDS_VOL                (0x0F0)
& v  P/ N: x# \) h#define        MMC5_VOL        (0x0F0)
' @0 O" ^/ s* E( l; q& g#define        N106_VOL        (0x088)
1 q1 X- y5 e, k' W0 V, ~#define        FME7_VOL        (0x130)
5 j5 A& Z% m7 s% E2 }
) j+ B+ j6 l) f2 S! v) c* FAPU::APU( NES* parent )
$ C8 p9 Q/ A7 \) |: T6 r0 i{1 m  }1 I' C' F1 L, ~
        exsound_select = 0;; h  k8 X5 s: U% a. n
: t/ i- f0 X, R. E( {2 t& Y
        nes = parent;
  q( `! |: j1 B4 [7 V        internal.SetParent( parent );
( U  d4 x: o( o
3 V% k; f( B5 x" E1 V+ v: u) X2 T        last_data = last_diff = 0;
. C0 o( S; w1 V5 g; ^1 C
/ i# {/ A+ o. }& l2 x* P! d$ V        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
. O5 b- s  n( e* g0 t# [) u
1 J. b* e" e- s8 P        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );1 d% r1 {* Z. o0 ?$ q4 d2 F5 Z
        ZEROMEMORY( &queue, sizeof(queue) );
& g9 _* h: ?: Z: t        ZEROMEMORY( &exqueue, sizeof(exqueue) );
7 @7 |4 a/ H; B' i6 k2 u4 p7 t% a0 d* ?
        for( INT i = 0; i < 16; i++ ) {
# m6 a! m& D7 F                m_bMute = TRUE;( Z) b$ x3 [: P0 D
        }  |- s: s" M6 X8 i- G( ~3 P
}/ ]- P( J' J) ^5 }- z' l
9 L0 q* p8 x; J' v3 B0 n) E
APU::~APU()
: @8 }5 ?+ }) p8 A{1 ^8 w0 o& N0 |$ r/ L
}
: m) M) u/ e) m2 [6 J+ R5 H) V1 m" h6 r1 {) z
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )$ a7 j% G" g9 c9 r
{
7 K. A7 T2 P' V, G7 d2 h( h+ Y        queue.data[queue.wrptr].time = writetime;
: q+ ?3 |$ L6 N- C, d  P3 {9 ~        queue.data[queue.wrptr].addr = addr;) i1 p9 B. L& C- ~6 ~% w. ?6 v' Y4 q
        queue.data[queue.wrptr].data = data;3 q/ |5 K  h* P/ I% V2 L: K; Q1 B
        queue.wrptr++;) M4 j" a: _; a9 [
        queue.wrptr&=QUEUE_LENGTH-1;
5 @  l* }" t  O8 ?        if( queue.wrptr == queue.rdptr ) {: G# f5 _+ F5 Q3 B6 ~
                DEBUGOUT( "queue overflow.\n" );! B& l* n( N! x" Y# [2 V
        }
6 I* r. T/ b6 N6 h$ i" `}
; E, u7 `: Q1 @4 M
8 v8 ^( |+ ]$ M$ {3 TBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )% N( N9 j0 C% d* E. w, P
{
" o; |1 F' ]" c9 e# w; V4 l        if( queue.wrptr == queue.rdptr ) {
0 m# _) J: B$ z* ]( }- g, x' \  c                return        FALSE;4 C2 a! E% Y- {: h
        }5 u8 k. l  e6 a7 |
        if( queue.data[queue.rdptr].time <= writetime ) {" O# A+ N5 K" W4 A
                ret = queue.data[queue.rdptr];- }' y% D" \6 s5 B
                queue.rdptr++;9 s! B2 ~' z# O
                queue.rdptr&=QUEUE_LENGTH-1;, N* M0 ~" J, K! P
                return        TRUE;
; }2 |& @' R! [2 Q0 o        }
+ p- v5 j; I) l4 V$ e4 G        return        FALSE;
9 U" h3 J3 l* M( T( p6 m9 n}
# `/ x# j9 s, _- D9 z+ v
  l0 _  ~5 O# C3 I# W. jvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )5 i0 E$ s8 L9 T& Z0 Y% \4 {$ T+ V
{
) `# d& p1 Z# ]) J        exqueue.data[exqueue.wrptr].time = writetime;0 c- }. d2 g$ F& Q% J# g
        exqueue.data[exqueue.wrptr].addr = addr;
: |% j7 @) o! I: \9 _; R        exqueue.data[exqueue.wrptr].data = data;
4 B! ~; ^7 @+ t0 r        exqueue.wrptr++;4 U; {1 f% q5 j: S; @5 D/ Z
        exqueue.wrptr&=QUEUE_LENGTH-1;
- ?$ z4 W) {, c1 |        if( exqueue.wrptr == exqueue.rdptr ) {
& N( {% ~4 s+ y7 d                DEBUGOUT( "exqueue overflow.\n" );- h3 w- \$ g* ?! q+ ^4 s" s
        }, D1 j$ C, g. V% \2 O. V  g
}" P2 a/ o/ B; \  l# j

9 O, f: I5 Q9 w: r1 |" MBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )# x* g! R3 m% }1 Y8 u1 X# i  e
{# h- r2 b  u1 N( E1 l. p) ~
        if( exqueue.wrptr == exqueue.rdptr ) {
; _) `: D- ~3 U' ^9 ^, _) x                return        FALSE;: D8 s3 h) l  a; v. D: a
        }* k2 ^! {( U! G5 A8 a
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {3 Y& d4 {. Z# `9 I  d3 v0 [
                ret = exqueue.data[exqueue.rdptr];8 ?4 i  S5 a" k9 j6 X) ^  N
                exqueue.rdptr++;9 I: d7 @8 @1 t( S* [  ?( G
                exqueue.rdptr&=QUEUE_LENGTH-1;; J. j" P4 f6 I
                return        TRUE;7 f, P* a' z8 w# M
        }
) l6 O3 K4 K5 G: x" {        return        FALSE;
7 M! `7 v5 _% }) I" B# ?}
, i; S: o4 u7 R  U' C" y, r9 W. W! k7 y" s
void        APU::QueueClear()
% f& ]' Y# [  ?1 l. k8 `% P* h+ G{
- D- L" X* u5 u        ZEROMEMORY( &queue, sizeof(queue) );& J; p4 }0 F  ~
        ZEROMEMORY( &exqueue, sizeof(exqueue) );  S( m* ^! X1 v7 J
}# |' L0 N1 }9 P6 g% P$ A, }2 R8 \
3 @8 M9 ^! j! I" _" Q& V
void        APU::QueueFlush()
2 O2 J6 C9 r  l% Z. b) U5 K{6 l2 i# V+ S% l0 _3 J
        while( queue.wrptr != queue.rdptr ) {4 e( _  e; B! P2 Q2 u
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );; R# r" k% N7 O, f" q3 {3 i, W
                queue.rdptr++;( h. [( Y  M% Y
                queue.rdptr&=QUEUE_LENGTH-1;
9 J, t1 c& E  Q* q" X        }0 z! C: M  t" k5 _$ K

  L5 \& i# F1 ^7 S  X: X        while( exqueue.wrptr != exqueue.rdptr ) {4 f) }. K& }0 X' u6 ]9 |( H
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );. }' p4 G' {' D& K2 ^
                exqueue.rdptr++;
: ]2 F' [0 D5 Z  s1 f  I                exqueue.rdptr&=QUEUE_LENGTH-1;. N0 k' `- T1 [$ S  @, ^6 `
        }
* d9 H, m- C& |: S0 J7 R}2 d  F3 n5 z2 D

6 q. t+ n. [: r6 k; u( V% f6 r4 @- ovoid        APU::SoundSetup()# i- p5 s) M0 [  |: r* k
{; E6 `6 G* e. t' L- |% r% U7 b" x
        FLOAT        fClock = nes->nescfg->CpuClock;
3 [" c- ~  I5 k/ X        INT        nRate = (INT)Config.sound.nRate;4 k  N  u, ]7 d4 b7 ?" [
        internal.Setup( fClock, nRate );& e$ a) j) d7 n1 Z7 I% u
        vrc6.Setup( fClock, nRate );
: v* y4 b( b6 h        vrc7.Setup( fClock, nRate );$ s$ b9 U+ B3 w( D
        mmc5.Setup( fClock, nRate );: y/ E* h& _( U6 Z9 q+ M
        fds.Setup ( fClock, nRate );
0 N8 ~0 V3 U! _8 c        n106.Setup( fClock, nRate );; M7 j" g! l! @* Z0 K8 {1 t
        fme7.Setup( fClock, nRate );
, s: E4 _* Q9 ~- x! I}
3 e- g/ I, d; W3 \3 W' g! s' h
8 g: `$ s3 T- }" X& @1 b  Wvoid        APU::Reset()
  J# x' [8 j' E{  _- W* P$ }  F  u5 ~- W
        ZEROMEMORY( &queue, sizeof(queue) );
3 H& h% F9 X0 w        ZEROMEMORY( &exqueue, sizeof(exqueue) );0 K2 ^& |0 D- y8 _  Z! v$ n! F% V
; e0 p) x* C+ r2 D2 E$ u. a: Y+ ?
        elapsed_time = 0;
- D3 @2 s2 D. {% Q$ [1 \9 \' r8 P: ~- F( e% m: L. y/ U
        FLOAT        fClock = nes->nescfg->CpuClock;
  ^9 r$ l4 [! Y        INT        nRate = (INT)Config.sound.nRate;) a, h% H( E+ u; A/ |
        internal.Reset( fClock, nRate );
9 o4 p+ Y  b3 u' x        vrc6.Reset( fClock, nRate );' [* q3 a: h4 F. o# z2 y5 S( y
        vrc7.Reset( fClock, nRate );+ @$ C5 I# q7 p2 L3 ?- Z
        mmc5.Reset( fClock, nRate );
  k2 _9 J7 u9 K& h        fds.Reset ( fClock, nRate );6 E! g+ |* H- D  P5 {; Z
        n106.Reset( fClock, nRate );
) c( A( O- H6 S  v: ^2 K8 T        fme7.Reset( fClock, nRate );
3 Z5 Y6 X+ ]2 [- |2 k+ w
( g* L9 Z& T  p8 N        SoundSetup();
. ^8 c( E; _6 m' E* H3 v/ P3 T}* E& m$ c6 m2 _4 T5 p- {

( t0 W1 J# c' u) O4 W% x- Hvoid        APU::SelectExSound( BYTE data )
$ x8 W- Y# d) ?- R& K& ?{
, M, }8 p$ w. L, t& R9 j$ _. e7 j        exsound_select = data;
, J  `) O! q  A4 y" A% F}( V. J$ T/ ?; d

/ ?- G2 U' O1 |# uBYTE        APU::Read( WORD addr )9 Z9 |5 D0 r" t5 O4 r$ P9 O
{" _: m; N( w" a
        return        internal.SyncRead( addr );
8 f8 ?* E5 D. K& k# s, ~}  }0 m) Z2 x2 [; S8 J% Q3 ^

4 n. @- }& C& D  l7 Lvoid        APU::Write( WORD addr, BYTE data )" v7 c. }# Q/ R' X
{
0 C  B( s, G7 B5 Q' z        // $4018偼VirtuaNES屌桳億乕僩
8 Q; K! |2 t) f, M% c! s8 \5 z9 v" [7 a        if( addr >= 0x4000 && addr <= 0x401F ) {! T1 h/ t9 C: z( M! A' h2 i
                internal.SyncWrite( addr, data );
. V# I# ]: f. G5 _                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
& b$ U8 A8 T" y9 B# W8 @        }
6 D1 ~! F3 C. w) i# i}
6 A  x2 `  \' P8 `4 ~4 e" T) H( \- i: V% \: q4 i
BYTE        APU::ExRead( WORD addr )
  P' E9 k% O8 u, R! O* D9 V{% s6 b+ w8 g4 q0 b1 B* @3 k0 s% N
BYTE        data = 0;% D" ~! _# {8 k9 f# K; {- a* f7 w6 T0 L

1 D1 P3 ^0 ?* e2 I2 M        if( exsound_select & 0x10 ) {
* a$ _! {2 I) S5 O' ]4 V( H0 j7 F                if( addr == 0x4800 ) {+ r+ D2 B9 H6 i! H( d
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
1 E, z1 c% J8 h3 g' R; m9 I                }
6 w# H) }' ?9 I% e. N( ]. f3 {$ o6 A        }% l1 l5 J% ~3 N/ A1 i. W
        if( exsound_select & 0x04 ) {
& r8 _; B! n3 E4 T7 c                if( addr >= 0x4040 && addr < 0x4100 ) {
, _9 W7 ?- U$ E                        data = fds.SyncRead( addr );4 j. S; S2 u7 D0 u$ G
                }, Y4 ?! M+ A8 g% }* y% X7 _: S- {
        }
) o, g) i1 W' T( a6 y- g" Q        if( exsound_select & 0x08 ) {7 b+ C0 _% |& o5 A! d
                if( addr >= 0x5000 && addr <= 0x5015 ) {
0 @" M2 Z! ?: d# L4 Z                        data = mmc5.SyncRead( addr );
) }3 f: B& p5 w* H' Q                }/ O+ }5 l# e* q5 Z
        }- c* h- {( v2 w( @6 W$ I

: k, X) ?/ L1 P) v$ K0 x        return        data;
2 N, O9 t3 L, c2 r) P}* c/ R& O1 ?3 e3 ?) U  M5 G
5 M& p: c6 t& W! `4 T
void        APU::ExWrite( WORD addr, BYTE data )
0 m1 w8 \4 R' K1 `; e* D{5 F+ x/ C3 h. D: F$ a  r
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );! D, ?: T5 [2 s+ e, }! r+ g

& ^$ t! n  V1 }/ x8 G0 o        if( exsound_select & 0x04 ) {0 x2 H! L* j. j7 h( w
                if( addr >= 0x4040 && addr < 0x4100 ) {
3 K! O- H$ s) A6 [+ U. o" `                        fds.SyncWrite( addr, data );
+ ?8 Z& u8 v% Q) e+ B) x$ M                }
0 O9 ]6 z% s6 z0 C4 A        }
' d0 D4 V6 k( [3 K4 ^$ N& K& q8 u
" ^  @$ _( Q( r5 \! ~0 A4 P3 Q        if( exsound_select & 0x08 ) {
# R6 n! L" g2 y" l0 \                if( addr >= 0x5000 && addr <= 0x5015 ) {& t9 _& ~/ i/ ?% }  E1 s
                        mmc5.SyncWrite( addr, data );
5 ^! _' q/ B; W$ m2 d/ G3 Y                }: K+ k5 K) H- F  J$ k& P6 w9 |
        }- _. f  g! g! C% B# w  K
}. o/ o2 X; w) D: L+ k9 s# T2 _
0 b' ]/ F! \. z& a9 v% b$ |
void        APU::Sync()0 ?  M! Z/ P! H& P$ _
{4 D9 a  {7 Y: U' w$ A
}$ @3 v! P; y0 d. Y4 S+ o( K) S5 |* {
. \# `$ m2 S% @" K
void        APU::SyncDPCM( INT cycles )2 l- `% _5 |2 A1 j
{
* z  F# B3 {" k% h; N: q( P        internal.Sync( cycles );
5 m+ X" k6 h2 N9 c% P4 z' }7 g
2 V0 \7 O/ s- ]# F! G: ~        if( exsound_select & 0x04 ) {" j( w& l: i' }5 T1 ]$ l) t: C4 b
                fds.Sync( cycles );
: `, j9 _- G; N8 \: t. K+ ^6 c        }
8 V& {# `% P) D7 k% B! W        if( exsound_select & 0x08 ) {
5 t1 h* o' c4 Q! M1 c                mmc5.Sync( cycles );# m/ z& Y' ~. H  }; H
        }
" H/ l8 W# ^: J}5 ^+ q+ P/ O( r2 [6 Y5 g
) M+ G8 k( c' W
void        APU::WriteProcess( WORD addr, BYTE data )
* H/ z) L% X; ]6 b& E6 ?* q{
6 u7 ^& v! }+ x9 h0 M* Z# D4 ~' Q        // $4018偼VirtuaNES屌桳億乕僩
) g2 \3 X" x1 e2 s        if( addr >= 0x4000 && addr <= 0x401F ) {, `( J7 U$ T' A
                internal.Write( addr, data );1 Y+ l) s+ k/ F6 q0 }0 C- R/ w
        }
+ e, d% c. k2 x}8 g1 w  y8 S4 _' j

1 g  b1 W9 {8 a; j$ x% ^8 Jvoid        APU::WriteExProcess( WORD addr, BYTE data )
$ X4 e8 {; E4 r- F! f% R{
# i8 l& d+ `4 @3 v( U4 G        if( exsound_select & 0x01 ) {
& k* A' c; u! I7 ^% }# X3 y                vrc6.Write( addr, data );
0 m  s& k8 G; M; `8 }4 o0 o        }
$ |0 L* @4 N& p4 W        if( exsound_select & 0x02 ) {
6 x1 C# m; @* ?7 @6 M* h& [                vrc7.Write( addr, data );3 z6 }: I; Y1 e1 L/ m: g/ N
        }# M0 q; C6 A1 k0 w1 l
        if( exsound_select & 0x04 ) {# G* n! b9 ^0 F* j
                fds.Write( addr, data );, Y4 r: N/ k$ {7 \* q# J; }8 k# m1 E
        }
$ G3 P0 Z  ]1 R# b: \        if( exsound_select & 0x08 ) {1 [8 q( O+ E# T( k/ u8 {
                mmc5.Write( addr, data );* h* g! c$ e' b& R
        }
& n, i; u+ W2 T! g4 ~        if( exsound_select & 0x10 ) {4 l& ^. L( p; r$ L
                if( addr == 0x0000 ) {0 C) e, U8 I9 V* Z" @
                        BYTE        dummy = n106.Read( addr );
+ ^' @' P  G- |" v; k6 `- V                } else {" _' N: g! E% a
                        n106.Write( addr, data );
: g4 E: A. U. J                }' B3 U3 b! z3 A& R* A# J' J7 T
        }, r- g9 Z* u: q4 Y
        if( exsound_select & 0x20 ) {
* n0 ]2 H* |1 ]                fme7.Write( addr, data );
+ E# A6 l% E/ U+ Z' B/ s        }: n3 b7 e+ H1 G- Z  x+ e3 v0 o
}
3 l8 C1 P; G' k; p1 `$ Z/ E8 x; a% y
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
$ v+ x4 N* D  P$ H1 |/ O$ R$ ?{0 o8 C' T+ ?; _1 I- y1 C! H
INT        nBits = Config.sound.nBits;
/ l9 ^7 d* n6 @DWORD        dwLength = dwSize / (nBits/8);
7 ?- w7 C! `/ f" o" yINT        output;4 x" m3 P" Y" v& j) S
QUEUEDATA q;
+ d6 R: Y3 @0 S; C8 g" t* UDWORD        writetime;5 y" n" ^" j5 r6 X7 }

0 X7 j. ~- i( r; i5 j7 KLPSHORT        pSoundBuf = m_SoundBuffer;) }0 Q& P- T2 p2 i9 O
INT        nCcount = 0;
. O2 U9 M0 F" S9 t4 @  Q" B$ z; j% `1 B
INT        nFilterType = Config.sound.nFilterType;
4 h* b" s/ m3 s' i8 ]7 y/ A9 f4 P* g8 L1 l7 f% C: O
        if( !Config.sound.bEnable ) {
! ?0 w% H- ^) p) J- A                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
3 d9 G% }/ j/ C+ _( n( S. n4 }% D                return;
: Y* x  W; q) o$ M) H        }
: Q! S7 d- s5 O) }# g3 o# s% P3 s4 p4 R# D) S( h2 M! N
        // Volume setup) I$ w8 v* L' K5 E8 J2 m/ c4 J
        //  0:Master
# g% V3 [$ d; A* v: X        //  1:Rectangle 1& a! |/ D% f$ O5 _9 Y( n% r
        //  2:Rectangle 2/ g$ T3 }- c7 o9 h  N
        //  3:Triangle+ E3 k+ ^, _9 v1 Y4 {  O
        //  4:Noise! u4 ~; x9 e! c: i" p
        //  5:DPCM# h, q5 T! r0 T/ L
        //  6:VRC6
" h; k/ u! n( W8 ^        //  7:VRC7
* K! a2 S* a9 T# |2 E7 |" V        //  8:FDS5 n. y/ o2 L9 u
        //  9:MMC59 ?5 T3 y, M0 B1 F- R& x
        // 10:N1062 v4 B# o% g( `$ a2 r$ D5 n
        // 11:FME7
2 T) L' j! U3 l, d( G; N. A1 g        INT        vol[24];+ |: p0 j0 W1 z8 x! ~4 F
        BOOL*        bMute = m_bMute;+ i% g( S8 p$ Y' H
        SHORT*        nVolume = Config.sound.nVolume;7 B6 x) G) i0 W  g9 Q

* t( e) _, ^8 n$ {5 T        INT        nMasterVolume = bMute[0]?nVolume[0]:0;  M0 Q' Q$ K( `. y5 Q( ], A& b

, t) H# G! F) b: `+ A2 `        // Internal: l5 q2 h# n! [* R
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;: E& |, H( t+ s5 Q4 ]
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
# K0 p% ]$ g* c2 Y0 ^9 E1 }" R2 B3 i        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
4 E0 W& ?. }1 \" u" v% k0 y" n        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
# r# D  b6 ?: P        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
6 C9 `2 n: X3 N& e4 X$ O1 m! c* K: u- Q' d2 f+ ^! F
        // VRC6
8 u2 M# W( t5 B1 r# H: m5 y        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;8 [: M1 |- `( @8 n
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
6 _0 J5 B6 i0 ?2 J% t8 e, b        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;4 v! V( U0 a! C  w# N$ A3 ?
# @! d2 }* H8 `0 {; \
        // VRC7% {& ?! x3 H  u0 R
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
: |* V: q9 r. n' F. j( h1 t3 V
: `, r8 n- E1 @" M6 L        // FDS) P. h1 h, u9 G9 l' @% L# H- \
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
" t: Y& r0 {0 ~
6 A% F4 g# W) d7 g        // MMC5
) O7 W, u! `2 N        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
  ^5 T  i- w% C# ]* ?. Z% m4 O3 e        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
+ z3 U# \& s; s* w' K& m1 G        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;/ z+ q6 S/ A. w$ M- x' C4 t2 e
+ v; V2 a' e7 C. j9 s! ]6 G* d
        // N1067 Z. \/ X0 O, k: E
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 ?1 K0 z4 u: K# C2 ^& g+ _/ c
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;4 q) m0 t3 [# q; L4 G
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
$ ~% ]4 f! G9 p/ v+ v        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;6 K8 {+ |. g( P9 z: Y3 t, A3 ?
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
  F  S2 \. \9 ]* [) J" q        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;& X' O2 n/ g* w
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 k- e+ N  [+ W/ x
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 @6 {: @& }" O" u: H) p! k3 M
& `  o/ Q- D/ L+ @2 a- b
        // FME7, c. b) d1 l6 O5 Q
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;& ?2 z0 V; T6 n$ z! O# m2 y" j
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;+ S9 A* D1 k: U3 a4 ~; }5 p" S2 G, I
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
; `8 r# p0 I& y5 S' d+ T  K6 J  w' z6 a% g4 |1 T
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;, n9 m' E% K* b& W7 v
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
* Q9 |$ P; t. v" D  H: G. A
. }. c2 E5 B8 X: N        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟  \3 l# O( F8 j$ I( ^
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
: E" {; t$ z7 \! q                QueueFlush();/ R- t0 u4 }3 }/ N* Z+ o2 D; J8 @0 S
        }/ Z* |% t& ~$ d5 w
2 W3 I' f8 _! L
        while( dwLength-- ) {2 d" w2 Q2 V( t  _( |, y3 n
                writetime = (DWORD)elapsed_time;
: v5 R: g4 f- i% U! N2 b4 B0 j5 S+ y, P8 s/ ~
                while( GetQueue( writetime, q ) ) {
$ w5 n+ T* g+ a$ o( @/ s7 |7 e                        WriteProcess( q.addr, q.data );
: V4 j: J9 A0 T                }
9 `+ Y& Y$ r2 m
9 _  {2 ^. L- R2 \                while( GetExQueue( writetime, q ) ) {
% ]& E' K& o4 k& I' Y. W                        WriteExProcess( q.addr, q.data );& s; d1 u5 b7 E% O# m! k
                }8 [7 m2 a# z; B8 t8 v& V1 c1 _% U
8 R+ f" ~6 H# j
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
/ t) A) j  s7 [  R7 F1 ]$ i( H                output = 0;
$ L# U; d8 N; I7 t0 H4 W                output += internal.Process( 0 )*vol[0];+ i/ x) V( C) l! m+ d0 U
                output += internal.Process( 1 )*vol[1];
% ?! h' z3 U9 A% ~& ]: V# S) A# E                output += internal.Process( 2 )*vol[2];9 x8 [( o$ L- z1 T' v
                output += internal.Process( 3 )*vol[3];
$ M4 J  @! W5 B8 _8 {0 J                output += internal.Process( 4 )*vol[4];% k$ C+ P! w6 ~' O2 X- p. w
% g! e: G+ K' |5 ~2 x
                if( exsound_select & 0x01 ) {
$ g8 z) J7 F& a& ]* t' k                        output += vrc6.Process( 0 )*vol[5];/ @' v2 O1 @0 r+ S
                        output += vrc6.Process( 1 )*vol[6];
1 k+ S9 n8 m- j/ v                        output += vrc6.Process( 2 )*vol[7];
* A! n& \# h. r2 S) D4 K                }3 H- x/ l$ f; V2 h
                if( exsound_select & 0x02 ) {
5 ?+ T2 k, u+ I& X                        output += vrc7.Process( 0 )*vol[8];
% N: S$ x' b8 I0 U2 Q                }6 x  \, F0 I. ^+ Q, |: N$ F
                if( exsound_select & 0x04 ) {
1 N( D$ M; W6 T6 Q, @* @                        output += fds.Process( 0 )*vol[9];% z% k/ c; G$ |& n0 Y; e; L
                }
, X9 J$ T' W8 ?" W& p( s) P                if( exsound_select & 0x08 ) {
& m" y) a$ N, I* l: r$ b                        output += mmc5.Process( 0 )*vol[10];
( ]7 {5 s" d. T& A/ P                        output += mmc5.Process( 1 )*vol[11];
/ y8 O9 y% F$ ^                        output += mmc5.Process( 2 )*vol[12];
& v3 h7 x7 F- j" W# U( V1 k& U0 s8 u                }
. E# o4 i! e0 O6 O' p) ?9 r                if( exsound_select & 0x10 ) {
" x4 d" [  C/ P3 z                        output += n106.Process( 0 )*vol[13];$ ]& x) m# ?0 f" h! h) j
                        output += n106.Process( 1 )*vol[14];
+ X' @' `* ?8 `  {                        output += n106.Process( 2 )*vol[15];7 E( y$ x3 W: k. S& v8 N. X
                        output += n106.Process( 3 )*vol[16];4 g8 j$ }9 }% Y+ ~# W
                        output += n106.Process( 4 )*vol[17];: c/ G( s8 p$ M
                        output += n106.Process( 5 )*vol[18];( O# D+ }$ F/ n8 Y( X& N
                        output += n106.Process( 6 )*vol[19];& y2 E- ]+ @" D9 X6 j. [: ^
                        output += n106.Process( 7 )*vol[20];
4 N$ x- \$ V/ x; h                }; @' N# V2 `8 g" x9 a, S
                if( exsound_select & 0x20 ) {# U3 b- O! M( @  u" v9 v- X1 r
                        fme7.Process( 3 );        // Envelope & Noise
! ^, E7 j/ J  E5 X8 f                        output += fme7.Process( 0 )*vol[21];
6 U( h* l5 u3 X# z# b& Y, _                        output += fme7.Process( 1 )*vol[22];
1 t4 V5 |! Z& ]2 `                        output += fme7.Process( 2 )*vol[23];- Q9 u. B4 ^+ U# L! c0 Q+ \
                }1 l( H% v5 z( M3 U

5 ~9 m+ I& V* D* q! @& y% v                output >>= 8;
+ ?, C3 h7 w. r7 k; [. T. g* j0 M9 v/ I( o
                if( nFilterType == 1 ) {
7 W6 }% h0 T0 K1 q                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)$ J) S  m7 I) ?# b# H: q
                        output = (lowpass_filter[0]+output)/2;
4 ]. S* w1 j$ b. o8 J9 d                        lowpass_filter[0] = output;% w9 \, `" R' L0 |5 u( _8 n
                } else if( nFilterType == 2 ) {
6 H  F$ R8 a' f1 P; k+ n                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
4 v5 R7 g, x2 W9 {/ r2 Y9 y, [                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;4 V0 I9 O/ l+ X5 R$ }+ d, M' Z
                        lowpass_filter[1] = lowpass_filter[0];
6 p0 ~8 g4 l8 F- v) f                        lowpass_filter[0] = output;
9 {1 l% @$ [8 ^                } else if( nFilterType == 3 ) {  O: i2 g" X% ~+ U7 v8 P
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)  Z: A/ J$ M# F! Z* {7 R- A/ j
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;9 t' R* Y0 l- l( @' X- c
                        lowpass_filter[2] = lowpass_filter[1];  c' X% \" \$ c9 N  J3 o5 }& E& s7 W
                        lowpass_filter[1] = lowpass_filter[0];
, E3 X  M* |8 |' m- U                        lowpass_filter[0] = output;
/ M2 V% g. V5 W, I4 P4 m) c( y                } else if( nFilterType == 4 ) {+ d5 S" V9 Z, f+ j( J- Y
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)) b/ n$ j8 O' U9 N" A
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
( T* u0 I1 ?* p$ \# {. h+ h3 s                        lowpass_filter[1] = lowpass_filter[0];9 Z5 |: n* b; N( L
                        lowpass_filter[0] = output;
* e3 v5 w$ a* F( E, t7 h. @                }9 h/ M4 A/ E0 V& n7 ]% E7 s( Z

1 F. B+ H' L( q& m& ^3 {1 S$ h#if        0
. \) X. U0 N4 \' i* Q                // DC惉暘偺僇僢僩
2 D- P& e& {* X                {
0 c; I' R/ m$ s; {' ~5 I  V                static double ave = 0.0, max=0.0, min=0.0;6 b9 e; @/ j2 N
                double delta;! h. I: [) k+ o
                delta = (max-min)/32768.0;" C3 l% m9 e% ~( I  B
                max -= delta;; m! \- n/ A0 _/ f0 V% j( f
                min += delta;
9 b. A& h- v9 b                if( output > max ) max = output;1 z8 ?# M( E- {1 a& k  o  G
                if( output < min ) min = output;
0 j6 R# d! C) K0 Q6 M# f5 U                ave -= ave/1024.0;
2 E) b1 a3 n  m$ w                ave += (max+min)/2048.0;8 J! B: }) [+ J3 t
                output -= (INT)ave;* g5 T8 Q. V; y& j& g
                }! l/ d; O& y0 f. W! j
#endif; h& Y2 q/ R* O* }( U5 O
#if        1, q' }" G5 E* ?# g
                // DC惉暘偺僇僢僩(HPF TEST)( V- Y4 ~( r& ~7 T  w% f8 F; B2 |
                {6 z9 `$ V- F* {( a
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
: Y: g* L; {' K3 |% X                static        double        cutofftemp = (2.0*3.141592653579*40.0);
9 G4 y$ \4 B3 E                double        cutoff = cutofftemp/(double)Config.sound.nRate;2 {9 }7 @0 R8 k6 B
                static        double        tmp = 0.0;
* Z# ]2 t  V; K: w  {: u/ ^: X                double        in, out;
. ~7 Q% u4 G( w+ c% R1 g5 c! p: k- Z* Q
                in = (double)output;4 p' ^2 [$ B+ F. J3 |$ H. A
                out = (in - tmp);; z; Z, N! o- _  e4 u2 X
                tmp = tmp + cutoff * out;) P9 E* Q& S+ z) b

8 `/ G8 p6 ]% [6 |+ q# O                output = (INT)out;  X# X& M* l. ~' |$ \4 I/ ~
                }/ K; f, ^! P: [8 h- P, k
#endif/ t) Q1 ^' |9 L$ v7 U6 u2 E( C
#if        0
6 M! Q' H' }. |$ m" P3 V+ ]' }                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST), U$ U  g  R# Y& k$ S1 n
                {2 X1 F& C1 c; r7 h
                INT        diff = abs(output-last_data);, j% j$ j4 `8 _5 q! ^/ B8 e/ z
                if( diff > 0x4000 ) {7 w6 A( V( A2 Y( C; o0 f
                        output /= 4;, M$ {3 b% \6 z' n
                } else # q2 k  s" r, W( ?8 f, W
                if( diff > 0x3000 ) {2 a% y/ A) M3 _/ S
                        output /= 3;
+ j# S) e2 P/ p- Q8 r7 b                } else5 h6 @  p6 k, Q8 |
                if( diff > 0x2000 ) {% \% I4 |8 _- R5 r7 t0 a
                        output /= 2;
& K# Q% S9 l* c( S                }) \; \2 P4 w: k$ L. v
                last_data = output;  G9 K8 e! z- f' N& H2 w. q$ }& [
                }
. g6 T4 G, D* k1 A" M5 z#endif8 X. s) S  n% d
                // Limit
& l; b4 q6 }7 u! g% _                if( output > 0x7FFF ) {- @/ Z2 y7 K! z
                        output = 0x7FFF;
& ]3 d3 i1 O1 |, u+ J. K: B                } else if( output < -0x8000 ) {
+ S) v/ N0 g2 t  j0 k8 q* W                        output = -0x8000;
! {& a- H: F. T                }3 G, q0 ]& G( d+ A

& D  f7 o1 t8 M' I8 m+ e                if( nBits != 8 ) {: E; r2 y& }* R; T1 y
                        *(SHORT*)lpBuffer = (SHORT)output;
$ u) F0 t: L! z- n; M1 K& S                        lpBuffer += sizeof(SHORT);! T4 T! L5 X0 e; A  q: b5 `
                } else {
9 R) E* w4 d1 O7 T+ ^0 q                        *lpBuffer++ = (output>>8)^0x80;
. S6 b7 i: F" D                }
' F1 T  K- ?( G  [8 Y* s+ w, I5 s  ~( G" E# g% W3 K
                if( nCcount < 0x0100 )
$ Q' m2 c: B  e4 ]                        pSoundBuf[nCcount++] = (SHORT)output;; a1 S; R* |  [. o
) N' s8 Y1 o! ^/ j5 k- ?4 P- _
//                elapsedtime += cycle_rate;
, g5 V( \% ]2 W! s& q+ a0 O; j                elapsed_time += cycle_rate;
0 J, z8 w8 G4 U" w/ B4 W! g        }9 u0 p) P! H, x& X, L
6 o) t( N' I# f4 d7 O9 I: I9 s
#if        1
" B1 N5 i: D3 [$ v        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {# O) C# ]8 E4 t$ `, a! P
                elapsed_time = nes->cpu->GetTotalCycles();
0 W- m2 }( P" c        }
8 V/ v2 ]- o* a9 M1 N        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
3 a) f: N. ]0 m3 r7 @' E; S7 e                elapsed_time = nes->cpu->GetTotalCycles();, o0 Q( m, U- T6 g) Y' W
        }2 G0 A  S; l$ A
#else# z# O4 v$ [" U4 K
        elapsed_time = nes->cpu->GetTotalCycles();
6 Y5 d2 ]4 Y+ I: ~1 i$ I! g# l; t7 \#endif
' J- u1 F5 @4 [! p! O}
, A. D. D4 @7 B# G2 J) M
$ L# E7 t3 J- ^# K( y, h/ f// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)% I, Q! L" J, d8 g4 g0 N+ ?8 ]0 [
INT        APU::GetChannelFrequency( INT no )% S# n- D% T# S! l/ A0 x$ i
{
: U. Z& t7 e; s1 m5 H        if( !m_bMute[0] )+ `! x4 n/ w7 y8 O6 t0 q1 m- m
                return        0;$ J; @5 W7 W6 \# \) a7 r
) E3 O6 S# p/ X9 L" ?: i2 h& ~
        // Internal
' |% b& \- B& H0 b) j  J* `# b        if( no < 5 ) {
. M2 Z7 Q( g$ q( L                return        m_bMute[no+1]?internal.GetFreq( no ):0;7 n( C. Y* W8 Q: x; c+ a
        }
/ t: q! T1 q& P1 {8 e) d5 r) [        // VRC6) I8 v: O2 I' ]' `7 i
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
8 \2 W/ F8 Q. v" b/ V. H  A0 s. a                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
3 e$ p9 p5 n; u+ A7 \4 S3 P9 }        }9 X2 m! `7 v2 T' V+ c5 @
        // FDS
( Y8 ^3 E1 \5 D# F; t1 Y& k3 |        if( (exsound_select & 0x04) && no == 0x300 ) {; A  k, D( b" @5 i# w0 M
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
. W7 t: D  s0 I( I        }
$ q) s7 D( n+ T2 t        // MMC5
1 ~; M9 a1 T3 s$ t& ^. Y! \6 g        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
% s7 Z7 F) E% N1 f% s                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;8 Q' {% x% {6 Q$ F. @0 L4 k- t
        }
: i! {3 N; s- t9 a9 v        // N106* r5 E# \6 M4 J9 n9 a4 g. }
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
6 @4 A& q4 W3 v( T6 P                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
/ a5 c& b+ X* O# m0 l* F- D        }
7 P  f; f; a+ W; X3 M# R        // FME70 Y4 e9 h; y$ r! l/ V7 S) K; x
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {8 G/ d% k* b$ L0 Z
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
1 n6 V) t0 ~+ y        }9 j9 a  b6 D6 i; \, R4 L
        // VRC71 n* n9 X4 ~( `, {# N
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {2 @# m# E, W0 x( S  J
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
- z* g% Z9 _2 c        }$ V3 I* J" u& @1 F% b
        return        0;
  t7 X/ F+ N8 e3 q5 \: S. d}- ]8 F; w1 X* x" Q4 X

- A0 u  q' U" ?// State Save/Load
# F9 V+ x- l6 f' z9 Evoid        APU::SaveState( LPBYTE p )
9 e8 `( g) ~6 c{
8 w# B' g5 x9 T: Q( Z#ifdef        _DEBUG
" B; E# \  m- {  A2 k" U/ w8 I6 o4 R) nLPBYTE        pold = p;
& Q: e0 w& Z' i; ^8 A#endif
4 |/ t8 Z2 q3 I" ~% r/ Y/ Z$ _
- j  X1 `, r% ~! a" v3 i        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞$ \* ]  b; ~3 x% a- N
        QueueFlush();  {! W( X# N2 d- P+ N+ G. p+ m
) t! J6 b* j8 z6 n( n, [
        internal.SaveState( p );( I& \* h! `5 L. P7 e/ i% {/ |
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
3 I4 t6 d$ J0 ?; U+ P/ ~& Z- {3 _$ Z' v6 h1 ~. ^# Y
        // VRC61 \  Q( G. u' I5 k3 e
        if( exsound_select & 0x01 ) {
4 m8 u2 \" ]( J* p) f                vrc6.SaveState( p );
# W) |4 |# S: v0 H# e! ^- t+ _8 `                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
7 A4 L7 ]& m$ F. i! o8 l        }* f$ i. d. N; H- T: g
        // VRC7 (not support)
! Y* U  ]8 [  m/ c- U) y( A* @        if( exsound_select & 0x02 ) {
* m" D9 d. Q, P                vrc7.SaveState( p );  k3 q5 {1 x( r+ C' Q
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding. h. y; b* n- k- s8 J& F3 j. C
        }
7 T" C* s% j1 N. J$ w4 a        // FDS
! {0 p; b: u5 ~1 n        if( exsound_select & 0x04 ) {1 a. Q, F/ X1 T0 }: Q  a
                fds.SaveState( p );' N: X4 C+ a: ~" l& Y) |) h
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding6 A6 g; X( n# l" Y
        }% t! O) \4 ^8 ]+ |6 {
        // MMC5
8 [7 Z# s$ H, A) p6 a        if( exsound_select & 0x08 ) {+ v( ^* c( S& y& B2 M( K/ M
                mmc5.SaveState( p );0 H  u- X1 z, L# p4 [' l: W" e
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding* o) W# N. a- e+ Q; N3 u- S
        }0 R/ L1 e9 J$ d- X$ `
        // N106
! k2 G  V9 g; x+ D' l3 a" p3 c        if( exsound_select & 0x10 ) {
) _/ _8 L1 q: e  X) A                n106.SaveState( p );! O; @/ P) K! z1 n0 C
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
/ p) x5 C* {* y1 V- K        }# T+ p) I4 L& m: q  J
        // FME7* ]; Q4 a( L8 m/ Z+ D8 }
        if( exsound_select & 0x20 ) {' _. Q1 N0 ?3 l1 j: z6 Z: ?
                fme7.SaveState( p );1 C' V( U. I" Z
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding' {! Q' u& r. i. _
        }! B/ Z. _8 @4 C
5 e9 F! ]4 M- s8 P3 _3 p8 e. D
#ifdef        _DEBUG/ c+ p0 i" b7 ~+ k% l7 u
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );" p9 G  J. F+ u3 k8 O' o2 M
#endif; K) G, i5 {* ]3 e) D
}' f0 A; g# {5 f4 m) ]6 A0 v

# F# @. b6 N$ N1 X1 G# vvoid        APU::LoadState( LPBYTE p )
( K) A! b( f- }* Z; J{
4 p5 i* V, Z# l4 l        // 帪娫幉傪摨婜偝偣傞堊偵徚偡7 y( f) @: t# ]5 j+ v
        QueueClear();; d$ p1 Y0 o5 f$ c( p

4 @2 D/ p+ U, m  c$ f5 P+ m        internal.LoadState( p );
/ E: U. Z2 F" e        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding! G$ \0 L* t% r3 I5 O' B7 ?6 }8 ^

  F5 U$ V4 Q' h) V' t        // VRC62 D9 r9 n& m  H4 k- L
        if( exsound_select & 0x01 ) {
$ K& w$ w  _$ r# J7 C+ l                vrc6.LoadState( p );  A" A# T# D* _1 L3 _5 M' |
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
' |* z# F# g# X+ f& K' r5 S        }5 r1 H; r, D" d/ [# x8 Y9 n
        // VRC7 (not support)
; k+ U3 H, }0 b7 p        if( exsound_select & 0x02 ) {
3 M% I1 t9 `( N4 l0 C8 J. v                vrc7.LoadState( p );
9 T7 q% k9 n& U; z9 y+ k3 ?                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
( P$ F2 l  O8 P0 o        }
: N. T8 N1 r1 B- S: x! J        // FDS' B9 a3 ~$ y/ d
        if( exsound_select & 0x04 ) {0 p: M4 J' [6 q
                fds.LoadState( p );0 L: V$ k4 ^! ?! G+ n- ?
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding; _( f* i) w* Y( Y% G# O7 \$ ]
        }# u, ]* f5 w; V" e& X8 ~/ D& S
        // MMC5
1 N  [& m) [3 e( g% ]: {. F        if( exsound_select & 0x08 ) {
. W# O3 n- B  q" w$ A# t2 q7 g                mmc5.LoadState( p );$ {! ]5 L2 o/ v3 M0 \+ Y
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
' ~+ y+ N; @5 d) S7 ]& N& y5 @* k        }
- h2 K: {: v& ]+ W. G1 A        // N106
+ U' {1 O- G( f/ k6 F* U- v: c3 f        if( exsound_select & 0x10 ) {  M: v( w" Y9 ?, |: Q. R) G! j
                n106.LoadState( p );
2 \/ r8 {5 A- z3 O' Q0 o" x                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
; A/ k2 G* e* g2 \% p  W7 u! l        }
  m$ {4 ]! q% ?7 }/ |" X; c        // FME7
5 ^# P; q( P2 X1 d. o        if( exsound_select & 0x20 ) {, X4 f$ A* Q5 }$ A8 s3 F
                fme7.LoadState( p );
: W1 L6 Z: p6 K                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding: y! i' H6 k8 L" S% E
        }* E( U6 \$ p! P
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
' K+ P0 e- E: {可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。" D) E8 E6 c% K* P0 U0 _- @/ X
感激不尽~~
4 `7 M( p8 P& z! {
恩 我對模擬器不是很有研究,
: u+ R- S; {1 M) |3 t1 z雖然要了解源碼內容,可能不是很困難,
6 Z  [4 F, N5 O不過還是要花時間,個人目前蠻忙碌的。$ i8 f6 `" i8 a8 F

, Q% S: K, G& q2 k# y8 f7 ]給你一個朋友的MSN,你可以跟他討論看看,# P$ H/ J* ?; }- n
他本身是程式設計師,也對FC模擬器很有興趣。
' J8 K. ~$ n9 T+ P
1 A- }$ ]5 v* a+ lMSN我就PM到你的信箱了。3 r& B' `1 v: @) Y
0 S: S; V; _9 c
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
- z6 c0 A) X! F  x8 p呵…… 谢过团长大人~~

0 C+ ^: C: q' T2 \$ C: c3 y# Z2 m4 v( F% g
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
; h* B: E! z8 S. K# N团长的朋友都是神,那团长就是神的boss。
; W. p" h5 W% j4 q$ a* r6 r
哈 不敢當,我只是個平凡人,/ B0 w: y2 |  M
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙- b! R0 f5 H' L7 m
ZYH
( B. ~8 G9 r2 E5 vQQ:414734306' s5 P& y4 F0 ]+ \% D7 {
Mail:zyh-01@126.com. G. `1 E- B' E9 s
  f! B5 F  f' P: K
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
0 R$ ?1 X' J. G' K" B8 u, u再次对团长大人和悠悠哥的无私帮助表示感谢~~

0 \# v2 r# v: \& v+ L不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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