EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。* [9 T: c8 f6 j9 ^/ R; A: f* q
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~9 R7 P; u# K2 s: H9 p
这里有相应的模拟器源码,就当送给大侠了~~
! g$ ^8 Z1 t3 E, P/ b% j  yhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 ' K4 U5 u( A7 n# j9 f
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。& r2 o+ t& O* d. R+ |2 ?
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~7 H5 a* t" K9 K2 D. V- M8 O& Z
这里有相应的模拟器源码,就当送给大侠 ...

4 d' S8 J3 i) @' h聲音部分(Audoi Process Unit = APU):
# z  L# p1 N, t9 q/ c  o& Y.\NES\APU.cpp* M2 d. b' i5 z2 w+ S8 W, b- m
.\NES\APU.h: ]# p' W& R% o. n/ j+ O

! ~- H7 @" _3 d0 B% r( t; T' s; @- [8 D5 K
影像處理部份(Picture Processing Unit = PPU):% L1 d$ ^8 _1 j! m+ f
.\NES\PPU.cpp3 |$ d( ~7 [+ S. E9 M; J1 U
.\NES\PPU.h
) U" ^% K, x6 M7 ]" m' L
5 H+ T0 m8 _5 X  |* G如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。3 u, j& H- r$ Z7 K8 w2 c
感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:% @- E3 [9 k8 i# P+ Y: Y: V
(由于很多专用术语和算法机理都不明白,所以看不大懂……)* v% A5 `1 M7 i1 Q0 W
//////////////////////////////////////////////////////////////////////////
- h' C4 l2 r3 {# j# J//                                                                      //. J0 @+ h3 q5 q) k7 w8 q; h
//      NES APU core                                                    //7 m. y! K4 s1 x; D# d
//                                                           Norix      //
; w4 s5 \# U9 O. K8 r- R+ L- x( C//                                               written     2002/06/27 //
# A6 F+ \: k9 m( k//                                               last modify ----/--/-- //
; ~$ A7 ^( y  I" D//////////////////////////////////////////////////////////////////////////
+ f+ }1 r# G. w4 v3 a7 W#include "DebugOut.h"( B. G5 E( q1 V* X! ~3 n
#include "App.h"
1 m- h$ Q8 d/ K#include "Config.h"
0 P' w/ B5 W- {* \
/ V. [/ m) W5 Y9 t9 x4 a& _2 D#include "nes.h"
9 Y2 d/ v( M" U$ I# C#include "mmu.h"
* [/ r2 k% E0 j. @5 F) ~0 J#include "cpu.h"
0 `9 H- u# u. Z6 T- S: @! [* `#include "ppu.h"1 U5 j4 O$ q3 K) n3 J5 S
#include "rom.h"; P" c7 K& L4 V. H4 I/ ^. m# e  h7 q
#include "apu.h"
' q3 {) m; m  Y7 p% W
3 e% A$ {) ]. m* X* L! }// Volume adjust" Y. ^( `; p0 P* o6 `
// Internal sounds, r" ^4 m# `6 T
#define        RECTANGLE_VOL        (0x0F0)  v, [8 k- D# j& q  s9 u) \2 p
#define        TRIANGLE_VOL        (0x130)
( C! `/ E" x1 p- Z#define        NOISE_VOL        (0x0C0)
& J7 m' K+ r, n7 l#define        DPCM_VOL        (0x0F0). e. s1 T$ h5 s
// Extra sounds
7 i: {) q5 r: ], W0 B$ U3 v#define        VRC6_VOL        (0x0F0)
3 Y, O$ o* j  G0 m8 C( R#define        VRC7_VOL        (0x130)
$ z! b$ k1 c" e$ f3 l* X#define        FDS_VOL                (0x0F0)
- f; {! [4 a9 g4 r4 `$ P#define        MMC5_VOL        (0x0F0)
7 w5 m* q" G7 h#define        N106_VOL        (0x088)
. O1 C0 P! }% r% c+ s+ Q6 t#define        FME7_VOL        (0x130)
) |! n3 p; L" k9 c' C2 ?- q' V4 t! c3 j% r8 \, M- L$ y/ R% Z9 Z$ ~
APU::APU( NES* parent )# S( \# r+ Q+ V6 Z. G
{
1 c# H$ F  s$ ]2 S8 K7 {- b  m        exsound_select = 0;2 @9 d) w( I  C8 Y
7 u4 z1 z( H; m4 s% M
        nes = parent;
$ R* J9 D) V7 ^        internal.SetParent( parent );
9 H0 z6 i/ k7 Y# S- _) d# Y# O
        last_data = last_diff = 0;) w' I$ V0 a0 v* p: [3 Z6 Z

! @! k- G2 X' W        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );7 d& O8 |/ w" S0 L4 o

6 V( Q5 y( r3 e- A  x& p$ M! L$ H2 B; {' M        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );8 O2 c; @, D" k6 R' `9 {- O
        ZEROMEMORY( &queue, sizeof(queue) );7 U# U& ^* ?( M2 ~
        ZEROMEMORY( &exqueue, sizeof(exqueue) );/ r) i6 Y, b2 i# d* @

8 N4 S2 D8 d$ y  U6 N9 L6 v        for( INT i = 0; i < 16; i++ ) {
- n  k3 v% j6 j3 g- `9 ?# O9 ]( t                m_bMute = TRUE;
$ o0 C  l* |" [! z, D        }" }3 c" s1 I" V$ W; R! D. r
}
: f1 o5 p# q" N$ t
% N( d! V% a9 M* }1 sAPU::~APU()8 G* v$ }: m1 i+ R
{3 q. n) f1 P- _& H) j+ o. m& H  r
}2 g1 r' C* u: E5 i+ E4 U

3 D0 c+ `. n5 q) l) f' Mvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
# e8 @0 Y" n2 t" W' E{
5 [2 z8 f; E  b        queue.data[queue.wrptr].time = writetime;
8 V# {6 d; z$ v7 N( h. G8 E        queue.data[queue.wrptr].addr = addr;/ n1 ]6 g% V9 U& b3 |, B
        queue.data[queue.wrptr].data = data;
2 {" [, o8 t+ Z        queue.wrptr++;8 t8 W( {. q5 w% ]: \
        queue.wrptr&=QUEUE_LENGTH-1;
. ?6 Y# P6 K! Z9 o3 [        if( queue.wrptr == queue.rdptr ) {
/ Z0 ]! E3 y$ J* {  E                DEBUGOUT( "queue overflow.\n" );
) f- k- W# U! Y        }
, Z+ V0 Q) J: w1 `( K5 D7 S}
# n/ N+ G+ D$ Z0 G
) x! q, J+ g1 bBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret ). o3 B5 b8 F. n% L+ w( K
{
* q4 I! Y5 e  h& b" {  ]        if( queue.wrptr == queue.rdptr ) {
" B2 R1 h& W9 w9 C& y. z                return        FALSE;" l( t5 y* N7 D" t
        }
) A1 S( |5 }+ b/ D$ R        if( queue.data[queue.rdptr].time <= writetime ) {
' b4 O: s; r( P7 T                ret = queue.data[queue.rdptr];
1 S! j6 F$ F- W/ t                queue.rdptr++;
6 x/ O  R- z0 u- ~1 R9 P3 x                queue.rdptr&=QUEUE_LENGTH-1;# U# a+ B( c' W( u7 P
                return        TRUE;. F# ^# n: K+ ]. P, K
        }3 w. K+ t% ^2 O4 V* u. n& I
        return        FALSE;
( s5 B- b* i! E# O0 [/ u}
) ?$ y/ C9 ]1 @; g
2 A" b$ M  \9 R' e. Rvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
; l) V* [" e3 E3 h5 D: Z  P{
% J+ D3 a+ K- z1 I        exqueue.data[exqueue.wrptr].time = writetime;
- x/ t, R6 W8 J( z$ A        exqueue.data[exqueue.wrptr].addr = addr;
* V; Z( v6 N+ M/ z4 n* \$ V( s        exqueue.data[exqueue.wrptr].data = data;
1 q3 q5 Y- M- g2 `  o$ e4 _* ]        exqueue.wrptr++;
/ k' ^/ l9 ?+ j        exqueue.wrptr&=QUEUE_LENGTH-1;
8 i7 w5 t5 R3 q" {/ e2 m6 s  F        if( exqueue.wrptr == exqueue.rdptr ) {1 r) {$ P9 Q9 A
                DEBUGOUT( "exqueue overflow.\n" );, m. a  Z: [+ J" V7 ~; [
        }" e) e1 H: h' y
}
" h. X( J) N1 `) T( J
2 B; A8 I( g, S* a0 q2 A8 ~+ }BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret ): ~# ~; r' C8 W
{' U3 |3 a2 G% e/ |& `5 A. W
        if( exqueue.wrptr == exqueue.rdptr ) {
' ^5 q. x/ @4 T$ h; v/ g                return        FALSE;
7 W5 N; `  y+ `" X        }
% y! V4 F9 R& `! R: m; l8 E        if( exqueue.data[exqueue.rdptr].time <= writetime ) {& Q' K3 o$ I( n" g% ]) {/ K4 M
                ret = exqueue.data[exqueue.rdptr];# }* o; W8 Y9 m7 x7 @# V6 T
                exqueue.rdptr++;
1 v+ A. }5 {2 S( y                exqueue.rdptr&=QUEUE_LENGTH-1;# c1 B' J3 w" M3 |& S; O- J5 l% w
                return        TRUE;
& ~( z3 W3 l- B+ d  ?% F/ b0 B& n        }4 D# F0 J, m, [; r9 J0 R, M/ @) h
        return        FALSE;6 s) }) d7 @% v, N& L5 ^
}
" y! t# J& f! |' X0 @* E+ K0 Y+ o+ o% J: r# y! J/ s. W
void        APU::QueueClear()
  ?' V+ I  x* B3 c{
7 @8 v! G1 h% ]: z        ZEROMEMORY( &queue, sizeof(queue) );
, }' I0 }1 g9 n3 ?        ZEROMEMORY( &exqueue, sizeof(exqueue) );8 P6 P! |- ]3 z5 b! f1 O4 Q
}) b! t5 i- o" ^9 I3 D. `: v

2 Z" q* T& ]! ^$ T+ ]void        APU::QueueFlush()
, }- F) C. b5 O8 a1 w3 n' M/ c7 C{/ r6 d5 p3 U( M  r
        while( queue.wrptr != queue.rdptr ) {2 L( v* W/ |# H
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
% f- O% \1 |8 R+ a: M                queue.rdptr++;, H, G) ?$ Y/ X2 H' Y! Z: r5 h' ]1 ]
                queue.rdptr&=QUEUE_LENGTH-1;% ~$ J, U; X; M' y. t
        }
! G5 F* z+ I+ |- J- ^8 l& _4 M- E9 R, ]) [$ v% M
        while( exqueue.wrptr != exqueue.rdptr ) {
" D. ]; p" ~, z) v) @                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
8 ?4 [6 m. _  _* Z3 [) N6 c: B, [                exqueue.rdptr++;
* J. T* Y0 u6 n1 R8 S* l/ q                exqueue.rdptr&=QUEUE_LENGTH-1;
4 q( Z) F/ `, J; q% y$ m+ W5 W% ^        }
1 q( I. E0 q/ m0 z& X4 ^}! t% C3 B' I$ X2 H$ H' J1 [8 z
" z. N$ {( i5 N0 t' V& s3 }
void        APU::SoundSetup()2 K/ [' O8 a2 \7 N! `5 K
{
# ^: w& `) V1 i& u/ l( z        FLOAT        fClock = nes->nescfg->CpuClock;1 e2 y6 q, X& {8 [: d, P% R$ W
        INT        nRate = (INT)Config.sound.nRate;# v  r) H' I' P; O) i
        internal.Setup( fClock, nRate );2 [: @, r- K  ]8 F
        vrc6.Setup( fClock, nRate );7 Y6 b; `' N9 }
        vrc7.Setup( fClock, nRate );
2 Y: M2 |4 Z7 ~  H' h        mmc5.Setup( fClock, nRate );. F2 x0 F6 @/ s/ ?. @
        fds.Setup ( fClock, nRate );
, `, |) k* j) v+ O        n106.Setup( fClock, nRate );
0 m1 q2 a9 C! j+ [3 l  ~        fme7.Setup( fClock, nRate );
* M! l; V+ m8 q4 m5 D% M: M}
$ d9 ~0 ~; V; ?* X' |
: f  c0 H8 p0 Y7 d! C+ evoid        APU::Reset()
( E% O) v5 o/ |, j; h5 {{: g1 t- K* y$ j" C3 h
        ZEROMEMORY( &queue, sizeof(queue) );' B4 K- K0 H! E4 f5 Z* r5 V
        ZEROMEMORY( &exqueue, sizeof(exqueue) );% J- d/ y; p" h: L0 o# y9 n

# C. C/ \  e4 {6 ^% u  p/ Y        elapsed_time = 0;/ Q, d6 e$ ~+ n
( ~* y& {$ d6 v; ^. C, Y0 ]0 E
        FLOAT        fClock = nes->nescfg->CpuClock;7 O! P1 `( z/ D. |
        INT        nRate = (INT)Config.sound.nRate;# N7 p8 @- S. a- U- m
        internal.Reset( fClock, nRate );# F& _8 H" P6 Y- i) f- ?
        vrc6.Reset( fClock, nRate );
! Z: b) A, S2 }6 E        vrc7.Reset( fClock, nRate );
) F- r+ {4 Y, N& i" Z; T        mmc5.Reset( fClock, nRate );- o( r9 ^2 K' t! |# }
        fds.Reset ( fClock, nRate );3 D0 [9 \" }) U& Z- [: e' L
        n106.Reset( fClock, nRate );
# d9 M' I" _9 v7 r% }- R! h        fme7.Reset( fClock, nRate );
  d" F0 k7 T* L1 b4 n# Z6 l# O) _/ S. w6 d& A( I, r8 g
        SoundSetup();
- C) D1 H0 Q8 A; T6 V. o* @}6 F' l, Z0 B: a/ V) q

( x5 ~1 [! ^/ _4 d' D- R% Evoid        APU::SelectExSound( BYTE data )
) B  T/ m1 [- M( ~; \" c{
- X8 @% g/ u  X3 `- F        exsound_select = data;
( U7 D" v! [  x, v  c2 `) Y}4 Y3 R% _: {2 S+ j- g+ F( n
3 c1 y" p& n( O. a4 B4 E
BYTE        APU::Read( WORD addr )" K& K- x' r/ D, E0 [
{4 q6 I' j0 ?( h6 R. X4 ?5 C
        return        internal.SyncRead( addr );" V# M" e4 y3 e4 u" @
}' Y* x# L( n/ e3 r' |/ x7 }

# {5 J9 g' ~$ w# Evoid        APU::Write( WORD addr, BYTE data )
) h( V7 z3 W* H5 J0 T{
+ U- g( P3 v- H9 w$ [# X6 r7 G/ Y        // $4018偼VirtuaNES屌桳億乕僩
. t9 u& K: Z) D        if( addr >= 0x4000 && addr <= 0x401F ) {- o/ r8 a: t: L( P
                internal.SyncWrite( addr, data );2 Q8 t, v; [  \- q
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );9 a! ?7 `* R3 T
        }
$ O# x. C3 H% p" D}
) u6 u: s  y7 X+ N& e! D1 f5 y( w1 G) F3 e& f/ C1 ~
BYTE        APU::ExRead( WORD addr )
* I; ?! r; x' l) S{; s7 T% Z2 w0 l+ f
BYTE        data = 0;* @8 L/ @) N  ^8 N

+ ^. O+ R1 t& `% l2 A1 y        if( exsound_select & 0x10 ) {
( N, r( r2 G0 `5 Q* D                if( addr == 0x4800 ) {
+ X' n& _4 A, z3 Y* Z8 l& C                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );, K7 ~2 B) U0 u  T/ d
                }
$ V/ T0 y- h# U0 f        }# z: k5 e! h- S: F7 v" j
        if( exsound_select & 0x04 ) {
6 @( `" c6 m4 d3 v* J: `0 g* \, j                if( addr >= 0x4040 && addr < 0x4100 ) {
' j7 l/ f, X# ^4 D" E4 o' H                        data = fds.SyncRead( addr );' ]" X4 C2 V( r4 ]
                }/ w; v: q! N7 J2 l9 P9 l3 X
        }9 Q5 U1 I# v6 N2 Q
        if( exsound_select & 0x08 ) {
( @+ {" Y6 t+ ^/ R                if( addr >= 0x5000 && addr <= 0x5015 ) {
2 x  j4 t% x- i7 ?9 O8 H                        data = mmc5.SyncRead( addr );
: v" C, p( z1 C0 X' f2 t5 `: L) f' v2 R                }- b5 [" l# w5 c/ R
        }: F; S% X) t) {+ `# F
- x& h9 G& ^0 S9 y  Y* h
        return        data;
3 q: ]: d9 G6 \}
4 W: M* T! ]1 h2 o3 V
+ K  ^3 s- ]. Q! `- y: A1 i& zvoid        APU::ExWrite( WORD addr, BYTE data )' r" X( }' A1 p% h* N
{" I: y' P2 P% R2 w: b
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
1 W- d8 l7 r0 f' {$ D$ W1 Z$ n. O' b$ G2 O, u, }5 [
        if( exsound_select & 0x04 ) {
/ E7 T5 L- h, E. N  V                if( addr >= 0x4040 && addr < 0x4100 ) {
$ T) G( l: Y4 K+ r                        fds.SyncWrite( addr, data );
+ K9 V5 }0 q% J# }0 N0 `                }  x5 I( b! e5 O" k- m, I
        }% C* A  X8 i" W3 P5 ?1 s% I3 Y6 Q# H- T

6 q  q# a+ D( ^* `& ^        if( exsound_select & 0x08 ) {
: m: F! Y+ V$ ]                if( addr >= 0x5000 && addr <= 0x5015 ) {
! D% W- A" }! ]6 r5 l1 f  C8 j                        mmc5.SyncWrite( addr, data );
$ W8 A5 A2 p" h; ?9 _9 L9 y# c                }
) a! L; ~9 |7 K+ e8 T        }
1 G5 A/ `) x7 [8 l. [8 M4 G& c}
0 S2 d" o# p) ^, ~/ A* x& i4 ^: M. t/ c
void        APU::Sync()
, V9 `  k5 E% l{/ ]# t4 |6 r7 U5 _$ R6 K; Y
}
& Y7 K" b' j& M, Q- y+ r! Y$ v8 ^6 y0 ^$ }& n2 L! G* Z
void        APU::SyncDPCM( INT cycles )
3 Y" d% E0 M; N& \5 B2 U+ ^! v+ ?{
3 f( H+ M; f/ t        internal.Sync( cycles );
% g7 U2 U3 J9 D" Z9 _/ b2 ^: @8 i) @- @! R4 k. ]; T
        if( exsound_select & 0x04 ) {
/ b1 j$ W, h- q% m2 d                fds.Sync( cycles );
6 ^! J, j. o( [6 K2 n6 `        }, j9 j/ G; Y7 w# ~8 P" t; D
        if( exsound_select & 0x08 ) {" r4 I3 X8 U6 ?# ]8 j' [$ a
                mmc5.Sync( cycles );
3 {) [( u3 z1 W6 A# C        }
: a: K; d9 z$ ^6 v7 X; T+ I- }, T}, [7 h* y4 D4 f! j* \8 z) h% d4 G

: z6 c# f) Z; }6 {1 f4 `void        APU::WriteProcess( WORD addr, BYTE data )
! v9 e  f0 z' Q{+ J, [- K  L) J- f" K: Z1 _  _
        // $4018偼VirtuaNES屌桳億乕僩
* I7 t* {2 _" C% k" y6 H8 z        if( addr >= 0x4000 && addr <= 0x401F ) {
6 k# P& q& ]5 y9 x                internal.Write( addr, data );, ]$ D5 @6 i* v% Z$ N
        }  g9 m" @- [1 q* t% k" q) j
}
, Y& ^; ~9 W# S" C2 u4 m* h, U3 f2 W* q( `, R
void        APU::WriteExProcess( WORD addr, BYTE data )) K8 N5 r/ i, _% p, E( L$ U- f3 z
{( r3 s2 q) H0 A* G3 g
        if( exsound_select & 0x01 ) {
) R# G; y) ]0 M% x, G  q                vrc6.Write( addr, data );
: {$ H1 u- H6 P/ i" ~6 q# B: }" d        }
$ t3 J+ Z" `! r$ R7 N. z        if( exsound_select & 0x02 ) {8 a; {$ u! |; U1 ?+ f: j: j  U
                vrc7.Write( addr, data );! ]7 v/ W- d' _  h( A! r) }
        }
0 x% D' P2 e/ ^+ w0 P        if( exsound_select & 0x04 ) {
, O9 E  D  r, M, B: h& \                fds.Write( addr, data );; _0 a+ [- `3 t: j2 E( ^1 X) r
        }% W8 r& U1 k, D/ y1 e* C5 |4 _# n
        if( exsound_select & 0x08 ) {
! y5 T& _6 W2 S3 S. s                mmc5.Write( addr, data );* `4 M& O  X. }5 j1 p
        }( s% F( v- U) h
        if( exsound_select & 0x10 ) {6 p6 l3 f( J6 r
                if( addr == 0x0000 ) {- Y) C" i8 x. [
                        BYTE        dummy = n106.Read( addr );# Z4 a- x$ O0 V3 Z0 Z0 l
                } else {
' V& s  o1 W1 e# k                        n106.Write( addr, data );3 {3 ^6 V: ?; N# ^5 Y
                }" g4 \3 r, X/ ?2 K
        }: u0 l$ E: L7 Y4 q1 N% ^
        if( exsound_select & 0x20 ) {8 l2 j2 [1 F6 \
                fme7.Write( addr, data );+ h2 d5 ^1 R* s
        }
) S+ }8 z+ {; ~" B$ `}
; q  b( E/ j- S$ [8 B( D! d, d
1 ^& L3 f: [: I- s4 K, @void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )  h  d# i9 u5 b" [
{2 ^5 X4 @+ a' R3 t8 z4 E& ?7 x) Y! ^
INT        nBits = Config.sound.nBits;% v- x0 w: u! Y% _+ y+ a  U; S
DWORD        dwLength = dwSize / (nBits/8);
2 o! C2 @  X) M; q; VINT        output;# \6 |# c0 O" ^/ B4 R# S5 W
QUEUEDATA q;& v! i- k% k1 H
DWORD        writetime;
7 ^2 y0 |9 r+ n) e6 _: i0 V/ i$ H. x; |  ~* I1 p
LPSHORT        pSoundBuf = m_SoundBuffer;
2 V* O  _) h) ~! q9 x1 x  g  BINT        nCcount = 0;  d5 h1 F# P9 x: }5 l( q4 M: V

8 x7 f. U1 Q+ G$ n1 i+ t. ]INT        nFilterType = Config.sound.nFilterType;
3 o. \8 H) e9 s3 B, b" _
% T1 }! u- D6 d5 S        if( !Config.sound.bEnable ) {1 Z6 ~! \8 h6 ~" A0 d+ R$ E
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );( \- q0 C* R6 G7 o
                return;
- u( u& P: B8 n0 o/ Z$ B  V9 h4 W        }& T& `' g  G! }0 o( c
2 a, |3 _' G2 G
        // Volume setup+ U  d( P6 G, @( n+ B6 j0 X5 {
        //  0:Master9 f5 T+ l7 z+ A1 w9 h( F
        //  1:Rectangle 13 y4 z3 y$ u% x
        //  2:Rectangle 21 t+ f+ i4 f( `% j2 x2 i3 z; {
        //  3:Triangle2 {% i0 L3 S: E+ L
        //  4:Noise
$ I2 R5 y# \& V+ {5 ^        //  5:DPCM* s4 m" q) Y8 N
        //  6:VRC6& B1 y. g0 E& X5 C) e
        //  7:VRC73 r6 |& }, q2 p: @7 ^9 X
        //  8:FDS7 C# v: J- B5 n$ l# P0 y
        //  9:MMC5
; b4 N2 v! W9 i' N        // 10:N106
! ~) I4 G; H6 K: z; X1 F) M' E        // 11:FME7# ^8 y7 }$ W4 F! u% Z! d
        INT        vol[24];
' t' M1 w3 X& j        BOOL*        bMute = m_bMute;- {, K7 s2 U, U8 {% X: P2 Z
        SHORT*        nVolume = Config.sound.nVolume;9 x4 N4 _7 T# u5 m6 v5 l% E7 @* _
2 S: P+ J0 f8 C' d; Q
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
: H/ M% f+ _2 I: [
# e- J' [: m! d2 @- E1 ~: @6 j        // Internal( X! _. s5 P0 B# W
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
4 g" f% e' J3 q( v6 }, ]9 u        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
, F% Y! l6 e. x* ?5 C        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;( B, ?9 Z5 d% q; D1 h4 Z  N
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;4 W$ _) [- z8 \  S4 ~
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
$ E5 z" ]4 Z3 \+ C# ~1 p: T' U0 p5 g) ?+ b
        // VRC6
5 w$ \1 B- I2 }+ F7 H        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;% Z& _% t0 w1 s* t; R* q$ N1 R
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
, V, j3 H# K0 ~+ B' s; W# |        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
+ K$ w8 \* P- I" o
1 G7 e  V9 K& ?& C0 d! m2 T        // VRC7
  Z. B* b( `) }3 d0 y% z1 |8 l1 z6 b        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;( c$ N; J- }9 q! d. |8 o& o+ @) K( V

. @& S  F. r& a2 }! w        // FDS
6 x& `0 X: [1 f0 k) k3 }3 e) g9 R+ w        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;$ ]4 |1 U+ O& R2 Q+ l* t4 E8 {- b  c
# K$ N! R  C8 Q9 q( E5 w, G
        // MMC5
* v% A0 a3 }/ V& S; g; ?% H, {        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;; r3 `- [& K$ z: |( R8 ^
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;0 z6 J7 a" M$ h" e3 I2 S8 T
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;6 {+ Q5 ^; [3 E) X% q

" m8 Y. N' k. G' f8 A3 R$ ~        // N106
( E) l+ O  V  F        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
, L. m3 w* h4 [6 l7 v# ^  k6 x+ M        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;8 q4 R  b% J) K- X
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;- |- h/ `4 N- M% h4 v: E4 T
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
8 F, G  }  R8 \  v: v' \2 ~        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 `) u$ E) e  H# l: T" q  i
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
5 x: ?( E6 [3 P7 K1 Z2 X: A/ U9 j! O        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
4 A# `: M( ^: ]8 t' D        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
7 P* e/ a% C; H9 q
! @* m, T- E  R5 X1 G8 a        // FME7
6 d& Z/ ~% a" G        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;) j1 d, p3 _% _5 ~  s$ O- P: g
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
0 e* h  {& c1 K5 k        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
3 x; s) |. |5 G/ X7 n  S" _- l, r5 s: c* W' [( R$ T, d
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
3 f; N  w& K; A4 ]        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;: d$ G" C0 ~" D; ^

$ m& c, I: y9 y8 p$ ~        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟/ h' k5 ?' s( B* C; ?4 Q: h' G
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
! A/ O! C5 W4 ~( Y% Q                QueueFlush();' y* l- F& F! {' g' f
        }
6 J/ L% t4 f& ], V5 D# z9 K* i# C5 i- H, ^( Z4 K
        while( dwLength-- ) {5 V0 d# ?. g4 B
                writetime = (DWORD)elapsed_time;! L- W) g3 K! h$ \
, t9 P2 ^* L6 m+ c1 z$ f3 ]: E: S
                while( GetQueue( writetime, q ) ) {
/ b  ~) b: L/ v1 O4 z                        WriteProcess( q.addr, q.data );
2 x( h# M+ @! ~' j' N( q/ ?4 l( }                }
5 b3 v' S1 H4 J, }2 A* p2 f; ~* L
                while( GetExQueue( writetime, q ) ) {
3 @0 ?: O* D4 j5 O                        WriteExProcess( q.addr, q.data );
" ?/ u6 D3 I- X: _; Q$ V3 \8 j8 R                }
3 w$ F" K. Z6 ^5 ~; W7 m: r2 j' ?* b
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
" w- i1 C9 r" k! n                output = 0;
2 i; V. x4 b  Z7 q& \                output += internal.Process( 0 )*vol[0];  z% ~% o6 R" }/ L5 X8 e9 L
                output += internal.Process( 1 )*vol[1];
7 e( ~5 p5 y: j7 {                output += internal.Process( 2 )*vol[2];
2 k- v, i* a7 P5 x$ L0 ^. ^  j                output += internal.Process( 3 )*vol[3];
9 n3 c0 a1 K: X: A7 c/ Q* E                output += internal.Process( 4 )*vol[4];2 q4 h3 Z, z. w/ O% c+ M% b7 }- K: @
) d6 C2 A0 P: N) x7 e* `
                if( exsound_select & 0x01 ) {  R! |- A5 A  f$ q
                        output += vrc6.Process( 0 )*vol[5];$ T/ M) |* g+ H  ?
                        output += vrc6.Process( 1 )*vol[6];9 i0 l7 j3 @' [( K$ s' @
                        output += vrc6.Process( 2 )*vol[7];1 t6 x$ h, L) b. p0 n7 i2 q  O
                }- ]4 M, ^! s# n8 [
                if( exsound_select & 0x02 ) {$ }/ M7 o* r/ r' L0 c  A4 [
                        output += vrc7.Process( 0 )*vol[8];
# I  }$ [0 f  y                }. [1 h: Q- w* {7 v  L/ m& p
                if( exsound_select & 0x04 ) {
4 q8 ]6 t5 V$ d! c, ]( P0 H) }( k3 J                        output += fds.Process( 0 )*vol[9];1 Q, @6 _9 z' J# y
                }
! u9 s; u& A, d+ [                if( exsound_select & 0x08 ) {4 o& a  u' X9 x( o' h
                        output += mmc5.Process( 0 )*vol[10];
" E, r& b" [- ]                        output += mmc5.Process( 1 )*vol[11];0 Z4 V* W% d  W
                        output += mmc5.Process( 2 )*vol[12];, q% N1 z+ X1 g) H
                }
! o- G5 s* z# q9 p. ]                if( exsound_select & 0x10 ) {
' j2 n# v5 \4 z' ]: Z# ~                        output += n106.Process( 0 )*vol[13];
4 A2 m  j. S& ]6 V& Q" m' X1 e                        output += n106.Process( 1 )*vol[14];
1 |9 e6 L, _- ?7 r  s) a) |                        output += n106.Process( 2 )*vol[15];, e% c2 |- U' U
                        output += n106.Process( 3 )*vol[16];
% Y! C/ i  m0 y                        output += n106.Process( 4 )*vol[17];
/ R/ V. Q* u, j  t  H! l, }                        output += n106.Process( 5 )*vol[18];
1 [! f7 M. ?; P, ?! k& q. G                        output += n106.Process( 6 )*vol[19];
# j; o, V1 [! _+ m) V/ B- ~                        output += n106.Process( 7 )*vol[20];
5 t$ u: O/ Z# q" s* h" p1 J                }
/ P3 r' H4 p5 Y( d# |                if( exsound_select & 0x20 ) {
( h$ K4 b  O* Y; [, ?" J. P: ?; r7 r( x                        fme7.Process( 3 );        // Envelope & Noise' {' Y* q# W( k' ]; q2 D$ _: F9 c
                        output += fme7.Process( 0 )*vol[21];
' U: i( p& i" f4 J                        output += fme7.Process( 1 )*vol[22];" a" u8 `* l& X/ ~8 x' r
                        output += fme7.Process( 2 )*vol[23];* |+ Q3 o& ?6 C6 M+ ]
                }
# h7 ^& l0 E! j, g
) |( W& N( G" \+ N                output >>= 8;
: S  |% ~4 T* ^3 P3 R6 K, c! Q/ X8 E" s
                if( nFilterType == 1 ) {
- d! [- h! x) W4 `! D                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)# I* A5 g  x' F' E
                        output = (lowpass_filter[0]+output)/2;
7 X3 Z# _5 `# r) q                        lowpass_filter[0] = output;+ V9 K, l4 C; J2 _; b5 n
                } else if( nFilterType == 2 ) {$ V, s3 D0 Q8 {) N3 h
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)( L2 z& t1 d" I# l
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;* U$ a1 _# t* A, J6 `+ d
                        lowpass_filter[1] = lowpass_filter[0];$ u& G' Z2 Z6 C/ j3 Z0 j
                        lowpass_filter[0] = output;
. _8 d2 z% P( `# Q  [' i- e5 |                } else if( nFilterType == 3 ) {8 \4 |: E7 d' T9 s, j( v( ~  H0 b
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)( T) \, y, G& l( L' D. W$ \' t% L
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
% _  `# l7 S3 k; J+ J/ E0 o8 V. k                        lowpass_filter[2] = lowpass_filter[1];
) X. x5 l1 E4 H5 Z" s6 x                        lowpass_filter[1] = lowpass_filter[0];+ \7 y; K; d8 ~# c+ O
                        lowpass_filter[0] = output;6 W9 {- F2 ]! H, B
                } else if( nFilterType == 4 ) {! s  R. S" I/ }  y
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
  C6 F3 d! g6 s: q+ A                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;' [8 A4 [8 \' T( ]" T
                        lowpass_filter[1] = lowpass_filter[0];
- _' Q! ]& x/ P) K" ?4 T" V7 w                        lowpass_filter[0] = output;
5 v- B; k  S! K- A: i) i) ?                }
, m. j2 f1 w3 Z' n) b* }
' {7 r3 F( p. r; _/ y) ^4 V#if        0/ O2 Y! D+ W8 w. a+ Q
                // DC惉暘偺僇僢僩
2 c( ]3 V% ^7 g" {                {& Q0 b1 R' g5 l  @: V0 _
                static double ave = 0.0, max=0.0, min=0.0;1 C$ B* K% h9 B" z
                double delta;$ y/ \: }$ n7 v" d1 F* o# R
                delta = (max-min)/32768.0;1 m8 I: R8 y( F+ g# t) x4 V
                max -= delta;
. ?0 j3 N6 W; E                min += delta;
& f. n9 ]! e" R                if( output > max ) max = output;
, l2 ~2 F3 M( `% h- o4 N                if( output < min ) min = output;7 I% T0 }  J1 V4 R8 j- c2 Q( q/ @
                ave -= ave/1024.0;
8 }2 e' r( C1 D1 W9 W: w: J) n                ave += (max+min)/2048.0;* @& N- s8 E3 l7 f
                output -= (INT)ave;: r$ e. s, f& \' I8 S" U' m$ h
                }
7 C  z4 [5 U" s#endif
& z' K: n2 M8 {$ O$ c% R6 Z4 D) V#if        1- Y; e! n" w5 r$ M
                // DC惉暘偺僇僢僩(HPF TEST)6 f' G) u. x9 Z' ]
                {0 G2 ~# v/ g- j+ n. `# U3 W, ^
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
, O' V' D8 ~) Y0 i+ E                static        double        cutofftemp = (2.0*3.141592653579*40.0);$ n( m& d6 J) O9 v
                double        cutoff = cutofftemp/(double)Config.sound.nRate;# j- {+ R0 V7 T5 {, T1 H
                static        double        tmp = 0.0;; r  ~" S/ r" K. {" u- z
                double        in, out;
( T5 b# I7 y, `) o# S; ?- y' T6 q" F6 G5 w8 v0 N
                in = (double)output;/ \- X3 W. `' ~# w5 \" n' I
                out = (in - tmp);
- F/ Z: A$ N4 H                tmp = tmp + cutoff * out;5 `+ x4 @7 x- v

0 N! @! F* G& H1 u3 o0 L                output = (INT)out;
' f0 m+ P* R. u5 U6 e  P                }
. F/ @1 q' }: F( c6 C#endif
2 n5 e7 m) Q5 f- B# S" \4 ]#if        0, P0 Q3 i3 d# D- s! X  w( u/ D
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)* R# c4 B# c: k$ F9 l
                {
1 s- O: ]* k; d" ]1 M# R                INT        diff = abs(output-last_data);
& o. M+ ?. S9 h' x8 `' a9 v, P* {                if( diff > 0x4000 ) {" {; o, u; v) C5 g4 o6 x
                        output /= 4;3 }( l7 R2 L6 q8 g! T
                } else
% m1 P1 ?2 T8 r4 r( U* `                if( diff > 0x3000 ) {
0 ?8 }* Y) ^4 u' z+ a* F                        output /= 3;
& e7 g% t  t8 o/ Q( K2 T                } else
. i: c+ P3 x: R0 v5 q5 t                if( diff > 0x2000 ) {
( Q6 R. q2 r4 B% {8 U# x                        output /= 2;" K7 j* Z0 l2 z2 y" {
                }& j# H3 M: t3 S5 ]6 F+ J% x7 o
                last_data = output;
2 k9 |, Y. _  U+ {9 v& y                }
+ G  f% f+ X! p% C#endif1 J% }# X& N( w& e0 B
                // Limit
! r6 z$ A9 E' a( Y                if( output > 0x7FFF ) {9 h1 [( `  B6 V. [0 q; G
                        output = 0x7FFF;
8 h9 v! G( S+ C* E+ R" T5 Y                } else if( output < -0x8000 ) {$ W$ o4 M% ~  D: U( m! o- Y( k' `5 L
                        output = -0x8000;$ `& M* h- p5 x" O  f: O9 a$ J: q
                }
. y( y' L5 k" G, b6 i9 q8 n, B
$ X- f1 w9 \9 E' n+ }/ g1 ^+ p                if( nBits != 8 ) {
# V, L6 l# {5 O7 G" d. c/ c                        *(SHORT*)lpBuffer = (SHORT)output;* }( f6 \. X0 b
                        lpBuffer += sizeof(SHORT);* Y0 {: g, M" T7 m
                } else {' G9 z8 [" }9 c5 Q( P6 D: i6 b2 D
                        *lpBuffer++ = (output>>8)^0x80;
( C7 [9 Y; j6 t! W: b                }
, R# F# [. x. d- m4 f9 S) j3 ~
6 ^0 b- Y7 J! C' J) }+ V/ n                if( nCcount < 0x0100 )5 M* M" p3 X0 W4 O# L& ^: m2 X
                        pSoundBuf[nCcount++] = (SHORT)output;' K" P- f* M) X8 v% C
' t# {" B# @* n
//                elapsedtime += cycle_rate;
7 Z" J3 t$ O" G                elapsed_time += cycle_rate;
6 a1 d4 _5 s; j: H/ K) o$ d, B        }
( `9 ?! J) y9 {) c6 O3 Q6 ~, q% m' a8 y$ A
#if        1
! |0 w) ]; S& m        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {5 a1 m/ j3 l$ A2 I
                elapsed_time = nes->cpu->GetTotalCycles();
7 }" N" Z8 o4 b% H        }
8 j, ?2 R# V+ ~/ r* K4 ]9 K+ ^# ?        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {, o$ @3 u2 w8 S( p( I
                elapsed_time = nes->cpu->GetTotalCycles();
5 f% {# C9 V3 `( M3 d5 t8 o        }8 p/ A% @& n4 G1 h6 W
#else
1 L3 W6 t5 ~: [# a        elapsed_time = nes->cpu->GetTotalCycles();
+ v7 ]2 }- Q% t8 T" X#endif5 d# X* O9 V- r5 U/ f; K
}$ k8 H' x- i% ]: F9 ^

  w6 P+ l# I: F$ M' f; E8 t// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
" P: ^1 D( {5 h& h$ dINT        APU::GetChannelFrequency( INT no )
5 L- p( I/ x+ ^  X{! ^! `6 A4 H4 v/ f$ ?
        if( !m_bMute[0] )4 i2 w5 C* W" E: Q3 o3 |% R7 I* Z
                return        0;. R& p, d. r9 L" C: z) T/ r
) A$ W4 F/ U6 d: u
        // Internal
5 I& G9 S* d# `# K2 h/ r3 ]        if( no < 5 ) {* x! ?# e% }1 t
                return        m_bMute[no+1]?internal.GetFreq( no ):0;3 |: R  l7 d% }
        }
  \$ U8 W  v* }1 s* D+ ?        // VRC6
9 p9 `0 W9 e6 X6 H2 A2 C8 q- Z. X        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {+ `3 B/ ^( e6 P1 ?( P+ T
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;2 s1 A1 o$ K( |, [1 m4 ?" f
        }. k/ d& ?' {% P4 w8 {. J& P# n  V6 T
        // FDS, M8 j$ c3 z* A& y8 N
        if( (exsound_select & 0x04) && no == 0x300 ) {
7 I$ @5 j3 k) o, j                return        m_bMute[6]?fds.GetFreq( 0 ):0;
% ?; ]2 U5 S" S* G4 v        }
% `* i1 q( R* K; K2 X; L4 K        // MMC52 D2 C8 y/ }  Q" o  T6 g. f( M1 R: X
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {9 s) N1 R" ]/ T% S4 z3 M( U( D
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
3 D8 V6 _1 o- V# k/ q: ~' x        }# D5 j* r- N/ I0 B9 p
        // N106* _$ \8 m! ^7 \, {9 H! `
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {9 @' D4 J% A# x; S# Z
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
" j' c0 Q7 W, G  A" u        }
% U  z9 j7 i0 |3 u( O        // FME7% ?. s) w2 `) V
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {* _4 u  w* b  w4 P, O+ _: ^# H+ b
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
4 i* f3 x" Y" B6 v* h+ |# r5 i1 j        }5 O& _, j8 M8 Y  c
        // VRC7
3 b2 D, R4 |4 y/ q        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
* q" M7 D4 S; M% s# T2 o" W9 y% |                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
* k8 w0 K$ q7 ~+ d        }1 ?! y1 k6 B$ S+ c
        return        0;# D8 |& |/ y' z+ s: n2 ~
}0 Q" W: u0 [" ~/ p" M2 I9 h+ _

: O& Q7 B# c4 A3 g// State Save/Load0 G! d- A: E. y' D2 W+ Y; Q: O% a
void        APU::SaveState( LPBYTE p )6 Y, K" {( ^! X' e- @: O
{9 {0 N- O6 M2 J  W% T& T
#ifdef        _DEBUG
! r3 R3 Z* B: m4 d/ v3 |LPBYTE        pold = p;
' p4 Z( H0 U/ W, N. Y6 `8 j6 E' S; A#endif" \2 W  O' s& v3 ]; o

2 X/ E6 r# y2 {" ~        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞  r5 Y  g% f! J* D- z
        QueueFlush();' `5 f& X  G2 K: Z  H
4 ^7 T. T  N7 x5 e$ b, H8 S
        internal.SaveState( p );
" P+ p- e9 ^7 n) I3 F: D' E        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
& h" t) i- C( ?  m* w7 M  v: n; y7 T7 x0 P4 ~
        // VRC6
* ]3 k+ Z. y4 X0 ~& U. j* r        if( exsound_select & 0x01 ) {, j' a4 o% W5 z8 @* l
                vrc6.SaveState( p );7 o# p+ }- p9 |2 o
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding( o# u. @# q0 w  o
        }
" N0 ~; Z5 r  d* _& q2 _  ~4 n        // VRC7 (not support)
2 n. A3 e1 g5 c3 z        if( exsound_select & 0x02 ) {* @) s  ~+ q: a, \
                vrc7.SaveState( p );
8 F/ t6 Y2 y3 p2 E* F( \                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding+ N  @8 D- B7 t4 ?4 m! Q% G7 u
        }8 b. ]1 g& J: Y: r
        // FDS: [: k& {; j3 U
        if( exsound_select & 0x04 ) {
' z. n: J. G3 D  g$ B; F: _                fds.SaveState( p );
* Y9 Z% }# Y; ~3 C& @                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
8 r0 L! @7 j* @2 \& e; B        }' t9 X) G$ w5 u' v4 D# [7 M4 Q
        // MMC5: M: a# A5 i+ f" n* p2 p) |: f
        if( exsound_select & 0x08 ) {* ?7 U+ ~! w- C  C: H1 e1 N" {
                mmc5.SaveState( p );- K$ T' G2 P# V$ O' Z
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
! _' n: D( @% y8 d/ y6 n1 `' m' n3 a        }( J3 p* u8 _4 ?& w
        // N106; p# G8 {! h, `+ Q% _
        if( exsound_select & 0x10 ) {/ a9 t) w8 _5 ^  ~" H" U! f8 E/ i  g
                n106.SaveState( p );, o  m: i0 G7 S: X
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding4 X* k5 g- t( T, ?4 C
        }
% Y0 \" a5 r' B1 b- @( E. Y+ s        // FME7
* l) z! Y' m. r        if( exsound_select & 0x20 ) {
/ x1 P" W* `2 j' q& h                fme7.SaveState( p );
4 B! J1 e+ ^' u( z  ~/ a                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
( m& K8 `6 [+ n+ q0 M        }
( G. t- N% P$ u" `! r5 _
2 O  {6 L5 Q+ K9 W+ z1 j0 W#ifdef        _DEBUG7 ]* {" n0 ^: ~( R& q$ `/ y
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
6 S3 D& u  x1 {- ~( f. E#endif7 h  c0 [; \7 m0 a2 Q! Y2 @$ L% t
}
* w% r) D1 P8 r  ?5 d& Z& s
6 a* J8 c) }4 f7 H2 {& l( Bvoid        APU::LoadState( LPBYTE p )
9 r: W0 l5 O. \1 u( |+ ], b{
0 G( p" H) L3 P4 {$ b/ C' N        // 帪娫幉傪摨婜偝偣傞堊偵徚偡1 Z& P- x& M. w, j& w5 t; S
        QueueClear();
+ H+ ^! X6 G: Q1 Z  o6 w# _5 U
: c6 D4 [, B' Y7 S/ J0 j        internal.LoadState( p );
9 _' V$ j! u, V1 N6 \0 c0 G        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding' ~8 Z9 h5 F9 F: k$ t6 A9 c
0 D# i8 K7 A, v% p
        // VRC6
1 S$ h0 p  w) D  e. W- H+ K        if( exsound_select & 0x01 ) {/ \' N' n- ]5 y5 Q+ K4 s
                vrc6.LoadState( p );
; |* Z) n6 z  g% t# b% G4 Z                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding  H! y& d( _  w7 T0 u8 G9 p
        }; S: Q# g) m/ Y/ ~% d- i. i
        // VRC7 (not support)
* N* t% J# d/ D2 _        if( exsound_select & 0x02 ) {8 Y& ^  E' t) X
                vrc7.LoadState( p );
: o- t* J3 I3 G% @                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding1 J+ t- \, G0 A2 W& [
        }
% i% L0 W$ o3 L- F% W" T9 V0 v        // FDS  `" F! r! H9 i5 v& T/ N
        if( exsound_select & 0x04 ) {
" ^4 L/ @9 u0 x. P1 M$ j& Q, k                fds.LoadState( p );- j6 R) v; X2 h/ d5 |9 h7 Z% }
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
6 b2 Z0 G" _: S! j  H; a        }
3 w& I. L6 K5 V9 A7 N* c        // MMC52 K; X2 T# b% R. t. R
        if( exsound_select & 0x08 ) {' G2 D1 ?  I' ^/ t* j" O
                mmc5.LoadState( p );- J6 ]$ r- \- N
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding' z* _# S* g8 b. ]2 v; \4 U
        }% B! _% J6 k( e& ~8 ?' t# t/ Z
        // N106
! A+ z% Y; n8 s        if( exsound_select & 0x10 ) {! v7 B; o0 L5 a$ Q4 Z6 U! [
                n106.LoadState( p );8 y: T5 E8 p+ F* ^
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding+ o4 W8 y5 Q1 s
        }
4 A( g: `6 d' U: Y/ [7 q        // FME78 o  J* w+ i% s) z) i; @" ?+ {
        if( exsound_select & 0x20 ) {
% O3 b! L  b0 W% X9 j' Z' M4 Y                fme7.LoadState( p );9 H5 L4 ?9 C7 s. _( ^
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
! |! L1 j0 x, _! q( _# {        }& N) ~" R( W. m# D" x" B# x! S
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
% P9 E. R( K3 `3 Z3 u: b% A可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。" B0 O0 F6 c0 M$ F
感激不尽~~

8 F" O5 O/ W7 T$ b- b恩 我對模擬器不是很有研究,% j$ E+ s3 w  m; v% w* R6 R4 M
雖然要了解源碼內容,可能不是很困難,
" g( \  c( P2 D' {, f3 ~不過還是要花時間,個人目前蠻忙碌的。4 J2 [5 g$ e; _

3 Y- n) b& Z/ u給你一個朋友的MSN,你可以跟他討論看看,& j. C- w+ V: U, l
他本身是程式設計師,也對FC模擬器很有興趣。$ @; D/ }, F/ g, k+ I
$ F5 A3 u* U# l# p4 ^
MSN我就PM到你的信箱了。
; Y0 M7 \. C: z2 Y
! C( `2 o- K' T希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 - X5 X5 n% X7 N* k
呵…… 谢过团长大人~~
& ]( ?( b7 w8 p& y( {
1 ?* J( z; [0 o( a! l% p# y
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 9 C# _+ U' N# f) e: _
团长的朋友都是神,那团长就是神的boss。
. [5 h" H* Y& W* R, S. R& ~2 B8 s
哈 不敢當,我只是個平凡人,8 o$ C. T/ S) n
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
$ T7 ?6 w: \; @6 w$ j5 ]; u) _ZYH3 O9 D7 J$ ?) R: C6 y
QQ:414734306% `# C, }* Q" Y3 ?4 }  t: I9 c2 N
Mail:zyh-01@126.com1 f! x: E8 _0 Z( u. J% e& |
* l) p' U: ?' p- b
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
5 U/ |# Q4 \$ C& D1 j再次对团长大人和悠悠哥的无私帮助表示感谢~~
. H2 f. y+ y, g. L* f" g, f# M
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-11 06:36 , Processed in 1.099609 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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