EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?
+ x9 X' o% }% g6 F6 w  J% HPS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。& V, S) l5 l. I3 a
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~* L5 u0 m/ O5 }: J7 Z
这里有相应的模拟器源码,就当送给大侠了~~
. I$ b7 i, |; b5 g. [2 ?" v7 }1 N" Rhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
3 R5 a% k) G* _; h& ]6 [8 s能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。: _# T% W* d' k; }1 Q8 |1 G, ^
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
6 N+ _! M* l5 I$ w; R5 Y$ H这里有相应的模拟器源码,就当送给大侠 ...
2 E0 z/ t# z6 Q1 n% r& G
聲音部分(Audoi Process Unit = APU):8 R4 ^2 ]8 z" r2 A( Z7 y# u
.\NES\APU.cpp: L( a% s" }: X) z' S" R
.\NES\APU.h
/ o$ |( g  p3 ?) A8 O# I* h8 R5 ?1 i  Q/ `# h4 \4 k5 @
, Y9 n" G& b; v- c- p* e* J* O$ r
影像處理部份(Picture Processing Unit = PPU):
, d$ T4 w3 u( m( p. s.\NES\PPU.cpp% L- C0 S' x7 e. k8 L* H5 Z
.\NES\PPU.h6 H4 h' G, \4 O: Y

1 D! R5 B, s+ X) f( G/ e- e. H% R如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:7 V+ W& F0 h7 @; {1 l
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
: L; F/ x" ^) t" h- e1 D//////////////////////////////////////////////////////////////////////////
5 c& g& ~% `5 c+ Z, V//                                                                      //
! {& ]& I0 J# i8 E6 M' V2 H//      NES APU core                                                    /// c# g* v3 h! }5 r5 ?5 m! ~
//                                                           Norix      //. u& G& a0 L: L) U
//                                               written     2002/06/27 //0 U8 `6 p. \) g8 A" v: _! t
//                                               last modify ----/--/-- //
0 \2 h! m* Q- z5 G/////////////////////////////////////////////////////////////////////////// V" Z6 h( w" _1 _+ H
#include "DebugOut.h"
8 _8 c! x. ]8 q5 k* o0 u#include "App.h"
" |5 {) B- `& _$ b0 Y, H9 S#include "Config.h". L8 {. |& h- E$ }. w

% L' ?9 U; @- ~4 A/ I% b#include "nes.h"
) n+ H( j2 a: g# J/ K#include "mmu.h"; K8 @2 d1 c3 }" q4 q% O" c6 b7 l4 u
#include "cpu.h"$ K; |0 k+ ^8 `* m$ D2 }
#include "ppu.h"6 F- a! P: h% e
#include "rom.h"5 j8 B: M- \1 R% q9 a
#include "apu.h"
) K% V2 w& L& N+ P4 V% H; P* y5 g
3 O, d5 V( k+ T& i* G1 P// Volume adjust  D6 o$ P- j0 H0 r$ r, i- M
// Internal sounds# U. C' {* V. e7 U. y
#define        RECTANGLE_VOL        (0x0F0)
6 }6 A- ?3 w1 R7 b#define        TRIANGLE_VOL        (0x130)
& z/ x' M- d( `" @1 o5 |+ ^: ^1 F  V#define        NOISE_VOL        (0x0C0)* {  K( A9 ]. d& Q6 h- E
#define        DPCM_VOL        (0x0F0)# J# J8 Y4 ], c% S" W& J2 h6 K
// Extra sounds
' |9 f& y3 L9 i* t#define        VRC6_VOL        (0x0F0)
5 h% h; w) B9 S) i3 a! x#define        VRC7_VOL        (0x130)6 v/ f( f& e9 O6 o
#define        FDS_VOL                (0x0F0)$ ^& g5 g& i3 V( O/ w
#define        MMC5_VOL        (0x0F0)- V4 j, z3 ~) H) I+ X3 e# e" e
#define        N106_VOL        (0x088)
3 \5 d# l) s: s2 }8 c/ Z#define        FME7_VOL        (0x130)
8 b( V' l5 ?- {5 P/ H2 v3 g" X0 c  A# a; M/ V; H! A) X! i
APU::APU( NES* parent )  |" k' |$ Z. H
{
6 m" n: D7 u* Z. S* J        exsound_select = 0;
6 Z3 C% j  f" X1 E1 D5 w3 X# T* @  q
        nes = parent;% R+ Y7 J; Y* P8 x. F  J. `
        internal.SetParent( parent );
5 ~  E$ z1 r1 [! G& S3 v
) E* a5 ~% ^2 T. C" g3 z+ }        last_data = last_diff = 0;8 R( w7 `1 g/ p

" e# l* m! n3 T        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );/ E4 @$ Y1 f7 l( i

2 r6 k6 K. i7 I# c  {        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );, o( x1 ^# p$ r* w4 d
        ZEROMEMORY( &queue, sizeof(queue) );& |) }% h% T1 }  K9 ^
        ZEROMEMORY( &exqueue, sizeof(exqueue) );6 w; x5 C6 u1 q/ }. o+ V5 X
4 d% m0 L- I: A5 q& q2 S
        for( INT i = 0; i < 16; i++ ) {( N' J' j7 D6 H8 L' {' r8 f" x
                m_bMute = TRUE;
0 f$ \! `1 D! _0 y, j% S        }( Y, d3 k6 N& z$ i; f
}
& M1 @0 b' c- L- s4 B
1 }4 Q3 E6 K7 ~1 g" eAPU::~APU()+ |, a1 q/ I) s6 Z9 M$ g
{1 o# C1 }- t" W6 D# l
}2 f' g! Z! I" G# |. c& H- v! a

% s" s% p2 ]3 `  Evoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
+ D# O  Y$ _) C; [! j1 K{! f( r; i; x+ _8 i: i
        queue.data[queue.wrptr].time = writetime;/ v5 h/ N) ~8 a7 K; x% J; `/ G
        queue.data[queue.wrptr].addr = addr;" _8 B' f: o5 {( p2 ?
        queue.data[queue.wrptr].data = data;( c5 ~6 ]. J& z1 l/ q6 ~
        queue.wrptr++;
' x0 I8 h# |$ R' z' \        queue.wrptr&=QUEUE_LENGTH-1;
: Y. l) K5 p4 A5 p1 Y3 ]; W# N        if( queue.wrptr == queue.rdptr ) {# w+ x. v) Z5 G3 Z1 I' N  O5 A1 R
                DEBUGOUT( "queue overflow.\n" );
+ J' e, j# i: n/ N( w- Q* y$ g) C) X        }
( o, e" L4 H( T}
, N# C% v% B' o! l6 P( R* c9 B  r% g
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
' m. g; s0 l( ?: l  h! M! u{" P  M, ?, u0 y7 ^6 |
        if( queue.wrptr == queue.rdptr ) {
: M/ Z/ g/ V4 t; b- f7 H8 l' J) d                return        FALSE;
, S( Q* C4 [6 ]. X, r6 q        }* y9 s+ S4 \+ s3 m2 @
        if( queue.data[queue.rdptr].time <= writetime ) {
& I! Y1 j8 W2 z1 a5 ]                ret = queue.data[queue.rdptr];8 w; {8 b+ }$ z3 C
                queue.rdptr++;
  u' E( n9 h: ]/ g$ b1 C# I                queue.rdptr&=QUEUE_LENGTH-1;
+ }* U5 `- R5 a* g$ \; T- v6 \' M' s                return        TRUE;
' o. `& a8 t( v3 z: W, |' m        }
+ N3 J& N" y+ Y4 U9 m        return        FALSE;
9 v+ d1 }* Q2 w) e0 N}- ?# G! F2 G, y3 X8 ^4 i, x' u
6 t# e# ^/ o: |- V! b) N6 j8 I
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )% x% {! {. h9 ~3 h
{; ^4 i1 P$ w* H9 X7 n
        exqueue.data[exqueue.wrptr].time = writetime;4 R9 h# f/ q- g8 r$ c
        exqueue.data[exqueue.wrptr].addr = addr;' ]6 `/ @1 \7 ^$ s7 v1 {* c6 Q
        exqueue.data[exqueue.wrptr].data = data;
/ M$ Z, w/ L! r( E- v        exqueue.wrptr++;
7 k% N3 J4 F& A7 X6 a        exqueue.wrptr&=QUEUE_LENGTH-1;
& E7 H( v) C. l$ v1 }) Y9 j7 ^        if( exqueue.wrptr == exqueue.rdptr ) {0 S! b. P# `. v1 t, z
                DEBUGOUT( "exqueue overflow.\n" );- Y4 z/ C! k; f5 Y" t& X3 U* K% t
        }: Q: d& e5 u: N, E0 t, j
}- B8 h2 _  m8 H
% \# [  @- N8 l: N; x" L
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )7 u1 f2 T9 o6 e# Z  g
{7 F/ ]0 U4 b4 L
        if( exqueue.wrptr == exqueue.rdptr ) {3 y" w" C5 B6 c) u+ w. v
                return        FALSE;
+ _3 n% W+ U& w8 Y: R* ?4 }, @        }0 r# v7 Z  J' k7 s* H
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
8 g' h/ x( B7 W* N5 G                ret = exqueue.data[exqueue.rdptr];
, M* c: c& W5 n                exqueue.rdptr++;
* W( d  t0 p% N0 I7 ~* c& d5 {                exqueue.rdptr&=QUEUE_LENGTH-1;
* ^7 p# X& R) d) d                return        TRUE;
0 F( u9 o" d  w( k2 _* D4 ?        }4 j& A) t3 ~( U) C
        return        FALSE;" [8 o7 f3 a' t* b5 t7 u. E
}, Y# B7 {, r% g  h% z$ S( z! H
; l" q9 B0 H4 L4 X; {/ W
void        APU::QueueClear()3 I' R! s9 f. @5 I4 d. ^9 O
{, r' ~9 ^* N: {0 J2 N6 |( |4 I2 `& W
        ZEROMEMORY( &queue, sizeof(queue) );+ p" |5 E' O  k3 q2 z& G
        ZEROMEMORY( &exqueue, sizeof(exqueue) );7 \4 |; |/ l+ O0 l+ \
}
+ B& A- m$ h7 ?7 B7 ?; f' V0 M0 t1 f4 E
void        APU::QueueFlush()
$ t9 v( K% u) j& \{
( Z( L( G. r# @) D) V        while( queue.wrptr != queue.rdptr ) {
$ s' R; M. U; `7 x+ h" a2 Z                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
" I3 A* F9 c4 h                queue.rdptr++;
  ^+ e/ x# r4 V6 j! B                queue.rdptr&=QUEUE_LENGTH-1;1 h$ s. n9 m# s) c- a9 K0 Q
        }# j& o6 @2 d4 G2 @2 U; U: F& j  B

/ J1 p* W. n$ Q5 x# H5 C        while( exqueue.wrptr != exqueue.rdptr ) {" D. @" d0 B3 n; K5 b+ Q- m
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
' ?2 z) ^% _8 w  U! t: [& O                exqueue.rdptr++;5 `  \5 e8 ]4 Z) G% ~. N
                exqueue.rdptr&=QUEUE_LENGTH-1;
& j5 h0 k  g0 \+ d" |6 D( E5 V4 _        }
, `& G7 j) R# Y' r}
; ^( n( |- H' d9 D  K
' @& z; {0 j! e* Wvoid        APU::SoundSetup()- t( e0 Q$ s/ _- w' o7 Y( U4 S) A
{
/ e3 P3 |9 }5 b' E" w) Q        FLOAT        fClock = nes->nescfg->CpuClock;
9 B, U  H$ ?1 \. g        INT        nRate = (INT)Config.sound.nRate;
# U4 O% w/ v: e8 F+ G        internal.Setup( fClock, nRate );
) ?1 d' w' E, W* `9 w% k2 E) M        vrc6.Setup( fClock, nRate );( N) \: y1 f4 y) F
        vrc7.Setup( fClock, nRate );
' x( n& W* o( i9 e/ G        mmc5.Setup( fClock, nRate );9 o1 O1 a- U5 I" t  t8 T& b% V
        fds.Setup ( fClock, nRate );
1 o7 Q6 r5 d9 k6 Y. P  x8 j        n106.Setup( fClock, nRate );
" b$ n( j5 z$ t( T+ p        fme7.Setup( fClock, nRate );' Q: T0 i2 ]+ O) A& k
}( w5 w$ e1 T) ]

8 o6 V6 _( p7 ^) L* _$ dvoid        APU::Reset(); |, s. l& V# X' i7 f5 C/ M2 s
{# p4 B4 B$ U8 U7 p
        ZEROMEMORY( &queue, sizeof(queue) );
. P' h9 x6 }$ ^7 f        ZEROMEMORY( &exqueue, sizeof(exqueue) );
6 _2 A2 S; s# E; ]' D! ?  X! q' T/ ?- w
        elapsed_time = 0;8 `+ e& ?; o3 K" o# W& \
" E& v* R* R; o; @/ h1 m
        FLOAT        fClock = nes->nescfg->CpuClock;
8 a2 l* n" c! k# m/ P( M) v        INT        nRate = (INT)Config.sound.nRate;" d( p  Q$ \- f
        internal.Reset( fClock, nRate );
4 _% c: d! J- c0 i: P; _        vrc6.Reset( fClock, nRate );6 ]4 j" q& a# G$ G0 y1 X
        vrc7.Reset( fClock, nRate );4 E* s, o/ O) i
        mmc5.Reset( fClock, nRate );
8 J. Y  _$ F. z" Z) q+ t        fds.Reset ( fClock, nRate );/ B) @- {2 ]' D+ A* E
        n106.Reset( fClock, nRate );8 t6 Q" d( ~1 ?) _9 p% ]( X& o  E
        fme7.Reset( fClock, nRate );
6 w0 X+ T0 n0 }- |$ W
% p) K; {+ ]3 k( A+ {, r& D        SoundSetup();
) I7 Y+ P" w8 a}
# ?9 B6 n# @; K; c% Z2 ?( W1 J3 Y9 _
void        APU::SelectExSound( BYTE data )
* i, U) z! L( x+ T{
9 f9 w9 h3 s# q- X1 T        exsound_select = data;
+ }9 b! c8 f; x2 G, U}! f  I2 ~8 ^/ E, h$ x% q# v

3 f  W! o; e! S; C" iBYTE        APU::Read( WORD addr )
# H- f  w" y% P{9 k1 U! U, z+ z
        return        internal.SyncRead( addr );
; S* D. R) j/ I, u$ U1 t& g  D}$ o" C& E6 Y( D/ z& g
8 w5 I$ Y4 }! m: z- J
void        APU::Write( WORD addr, BYTE data )
* Z. H) _& J& G{0 u" \: u: ?, Z
        // $4018偼VirtuaNES屌桳億乕僩
7 s( t& F" Y: m' t! N7 ?! t        if( addr >= 0x4000 && addr <= 0x401F ) {
$ A: ?! g& Z/ Y/ q2 s                internal.SyncWrite( addr, data );
( e% {% O' }; I& k- j" o6 l                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
  Z! T' A- p4 V( m( s# h( f0 B% [        }4 I: T0 N$ ~1 E, A
}
7 z1 c9 @+ d9 k. x% P5 d7 _: X( m8 v3 W. ~0 y
BYTE        APU::ExRead( WORD addr )7 x$ a8 m' a6 r* D: x. I
{4 V& c* q0 h1 H2 ]( i
BYTE        data = 0;
+ X( b5 S+ {" j
9 K0 z: e% |9 y' L9 G( U- E        if( exsound_select & 0x10 ) {" [* d  F1 ?( [! N: C& L
                if( addr == 0x4800 ) {+ B8 v, j/ v. Y" o) I+ e/ g* T( C
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
- Z. l9 q# b/ c7 T                }6 H' A) R2 ?1 x& b1 p, _$ p8 S
        }
, a5 Z2 i/ P7 t5 v        if( exsound_select & 0x04 ) {# c- Y$ }) t' R' d) K1 \* H
                if( addr >= 0x4040 && addr < 0x4100 ) {
/ t% o( ]% i" C4 ^                        data = fds.SyncRead( addr );3 j7 E* v" o# q$ c
                }7 i6 l" I& R+ w0 |6 K
        }
2 {( B, Z" I1 j9 L* u" N  g6 t        if( exsound_select & 0x08 ) {
$ c( m3 i! {9 E6 {# `                if( addr >= 0x5000 && addr <= 0x5015 ) {9 n% P9 ~6 Q, o& U3 t4 v
                        data = mmc5.SyncRead( addr );; |% q! L% B9 \! `0 y0 _
                }7 b. A# Y# \/ p& z3 e
        }
( g; d" ]3 ~1 o; u1 |, I* Y* w4 Y) m9 f& `* V: Z! x
        return        data;
, V0 s3 M) l& V1 i2 d}- u5 B" n* W+ i
' L1 X5 m+ X0 h% v
void        APU::ExWrite( WORD addr, BYTE data )! u* n# B; t' o  f8 K- Q. \7 B
{+ {( O* Z; S3 \( ?7 m3 q" k3 d- V
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
! S* z$ t' n* M& `- f
5 h- k$ w* b$ ^5 z! L# }        if( exsound_select & 0x04 ) {0 C! I, F) u, {' ]" L' t+ Q
                if( addr >= 0x4040 && addr < 0x4100 ) {
& v- e$ ]# a  q2 J                        fds.SyncWrite( addr, data );
: W8 N: ^/ }2 K                }
3 d  J0 Q# ~+ Z$ ~; h        }8 _; L0 b! ^6 A

* q7 r8 @) ?+ j4 J        if( exsound_select & 0x08 ) {7 N# y! E3 ~% `1 ], L& c5 B
                if( addr >= 0x5000 && addr <= 0x5015 ) {
; L) P4 [0 n4 h" {! A' ^8 B                        mmc5.SyncWrite( addr, data );0 ]+ I& ^; K( ]6 X
                }
( _* _3 |0 y7 R        }
$ h  l4 m- ?: C! I* r) y}1 u( c. |6 v+ P/ Q, a* H( A

# x: k/ D6 d$ T/ a; Q( P1 `- Qvoid        APU::Sync()# m) S# X. s( `1 P; J# ]
{
5 V; s% h, Q8 [) k" d}" @  x9 K5 g- E, `# z3 I

) T$ A* \9 l6 B6 Nvoid        APU::SyncDPCM( INT cycles )
& w6 X$ }+ }- }4 @{
# l( a$ g. W9 d        internal.Sync( cycles );
2 Q" b( p% V* ?: E2 ]
' L8 }- O4 Q2 J        if( exsound_select & 0x04 ) {
& g1 N7 q  e" E% ^: e                fds.Sync( cycles );
' \: P& Y# |$ V% j9 F" _        }
  H. s+ C; }& w) U( G, @        if( exsound_select & 0x08 ) {7 N8 H- x1 o9 w8 J, y" z
                mmc5.Sync( cycles );
$ b3 E+ g; B9 Q, w( f$ j2 h6 }* j3 @        }7 Q# T9 P7 R" Y! |2 |
}$ q( q2 K. c' Z. r0 C
( {; }. A/ v. x$ ?
void        APU::WriteProcess( WORD addr, BYTE data )% S: J" R. ]) U; S  ^
{
7 {' f8 ?3 A8 m) u$ t9 t        // $4018偼VirtuaNES屌桳億乕僩
9 r5 f& e/ Z# u0 t1 A1 }        if( addr >= 0x4000 && addr <= 0x401F ) {
% \; \2 p0 ^+ L7 n                internal.Write( addr, data );
* w  s/ F  h7 E* g8 Y4 D* |# q% M; h        }3 y( l- f8 l( X1 y% F
}  b' k: O; d" f4 g8 m" N, o

! Y: }$ H" ~. y! O8 rvoid        APU::WriteExProcess( WORD addr, BYTE data )
- y' I1 f: I. n6 g: m+ `- B: ^{) `2 O* e8 u8 `2 q. G+ S4 s; F
        if( exsound_select & 0x01 ) {. _9 _( C! d; ~% ]) _) e" q
                vrc6.Write( addr, data );! K' b$ b0 ?' M7 p8 C
        }$ B0 y0 a$ l# l
        if( exsound_select & 0x02 ) {  Q  y8 Y8 W4 ~! r
                vrc7.Write( addr, data );* V2 G7 k" d- V' B0 l% [4 D
        }
! R' e5 r0 J( Q- J7 Q        if( exsound_select & 0x04 ) {5 L9 E2 W% @% x. `6 d9 A2 `& W
                fds.Write( addr, data );$ j8 r+ C# L0 P
        }+ u% R. }; w& a* m/ I3 Z
        if( exsound_select & 0x08 ) {
4 I, Q' b; `7 r# k6 ?                mmc5.Write( addr, data );2 b% L2 D7 k9 G, t. m- ^$ {1 r* |
        }$ \& v6 j' a) l* ^: v$ d1 R
        if( exsound_select & 0x10 ) {! ?# C. r4 R! Y
                if( addr == 0x0000 ) {
% n/ M8 B- C1 I/ y! L+ h                        BYTE        dummy = n106.Read( addr );
& v4 `4 ]6 e! o                } else {( H( B; X) D1 ?7 q0 y4 l
                        n106.Write( addr, data );# _! H' v: H5 F+ R& d  M3 K% d0 X
                }
) q6 h9 z  L5 g5 O" F        }
. w& M3 A$ r+ N) [  |        if( exsound_select & 0x20 ) {
* p4 ~3 K8 P5 r" Z# B                fme7.Write( addr, data );9 p% k( y7 a+ M7 q5 f% r
        }7 C3 j* N7 P: k: m
}
/ E% _( U! {8 F1 I/ q: ~! P" T/ L4 T7 S6 d# {2 q3 ~% T: Z
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize ). i1 f9 N; Z0 ?/ e3 R
{
5 w% R2 c: y4 |+ \. O$ d+ wINT        nBits = Config.sound.nBits;8 p9 I1 y* D/ B. S
DWORD        dwLength = dwSize / (nBits/8);
) N+ J6 {* i+ U: `# a6 G/ J' v4 t9 c7 CINT        output;) k! x% [1 z4 c3 }' n  ]1 V
QUEUEDATA q;
0 A& m' o# l% H7 ]1 p  hDWORD        writetime;
! e4 w! k4 t, N
" v5 z  |& @! oLPSHORT        pSoundBuf = m_SoundBuffer;- T; m: i" {( F/ z8 {. ^: D7 X) e
INT        nCcount = 0;! F! @. x  [1 J" M. N2 `
2 l! q! x  K: O- {* o, _
INT        nFilterType = Config.sound.nFilterType;
' k9 G# w3 Q! _; `7 x3 {( T% _7 q6 S% I1 Q- v
        if( !Config.sound.bEnable ) {
( q! A& Z5 A2 E                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );7 E( P+ Z8 z: Y6 u
                return;
9 H2 S7 f$ `5 z) W6 `+ S6 v0 D( F        }
9 |8 |" k2 ]6 b' j  `9 F- Y) H0 V4 n8 N$ X5 p
        // Volume setup
: E, [" L  O* I5 V7 Z& P        //  0:Master
  c$ o0 `; D8 M) e+ g) V3 T        //  1:Rectangle 1
' t& D$ K0 g0 p2 O7 g* m        //  2:Rectangle 2. ^6 ~  q0 r1 u4 _! Y$ F
        //  3:Triangle
' E0 z' f) v. r  ?! x+ C7 O8 G        //  4:Noise
5 n5 k' b6 K5 f1 s0 E$ [' O' W        //  5:DPCM5 O! ^& R' R+ f( ~( W2 |
        //  6:VRC6
& m" p6 G2 i( \$ H& T3 p: X, z        //  7:VRC7
& r) {% a8 k3 B6 M6 q6 F& A        //  8:FDS/ M, g0 g- Z% ?
        //  9:MMC5
$ A0 D7 g! w& F  Y$ f6 N        // 10:N106
+ f8 G7 Y5 A7 s% J' G        // 11:FME7
6 A  [- n; ?8 F/ y9 [        INT        vol[24];
3 \2 k3 z- S/ N  R+ M9 V- @6 o        BOOL*        bMute = m_bMute;
9 R2 t: v! p- X2 O* Q0 f+ H7 [3 ]! A        SHORT*        nVolume = Config.sound.nVolume;
+ M( m! l4 Q( H2 ?3 k& G, ^5 w. o
  X( \9 b2 y" `6 P/ W6 y  {% \) B        INT        nMasterVolume = bMute[0]?nVolume[0]:0;. f# P6 K+ @* \. U1 ]+ @
9 ?( o/ Q! d6 d6 J
        // Internal
! l9 r# Y# ]+ {( p* v! }9 l        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
2 }# W+ P% ~0 N/ w        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
. R9 |8 U% K: Q1 B5 m2 y        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;: e7 u3 Y+ f8 |3 O1 Z9 T
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;) L5 G  }% u& ^  ~% z$ [
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;0 h. K( A/ u+ Q. B9 P" j
2 `/ r8 q8 w& |9 z1 y9 c
        // VRC67 L' V' u  o% ^! {5 x" G
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
/ E$ }" ^/ S# X( d( c        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;8 [7 }  |6 s0 ^0 Y3 f& K; [
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
; R/ N. v  o, d5 d# ~3 Z- I' Q" M# `. C- k
        // VRC73 l9 ^9 S5 N* l; f8 V0 W2 B0 z
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
9 v7 E0 P/ S4 F- k& c5 N4 e3 n
8 u1 _8 o/ n# T: z1 w+ y6 ^( v' t        // FDS% q) i% S  O  @5 M2 A
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;& c- o4 @, g8 ?' x# @9 x( k- `

4 v7 Z3 `' ]9 b+ H7 O) t: d$ x        // MMC52 ^& F! u6 a- N$ x# K" q
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;4 ?8 s' I6 f. I) m% Q
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
0 ?" N5 {, w. S- U' C* |        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;- S: _  _$ W# B5 F

$ v; j( G* g% S/ l: }; k( Z6 O        // N106
! z. o- k4 d- Y" y$ \. z0 U) |        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
! k4 e0 M2 p# j. T        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
: X2 M- N' y, A/ \0 H' B* f5 h% S        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 y. ^5 }) f9 \) v  e5 `; Z
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;4 N/ g* V. l: i4 o8 C
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
9 V% y; V6 q# M$ g$ L        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;5 D, b  A. R/ |9 y9 n% o
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
5 i6 {) m' `- C: v: W) ~7 m% w* N% c        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
& I5 x/ Z+ r9 X
. ?: w/ A4 t3 O0 _7 @        // FME7
- [% u5 c' h2 I. Z4 l% D" K        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
; I0 T1 A; O/ _% Z6 a        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;0 j, S) S6 g& e) z( J7 O% I
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;" C, e9 s0 s1 P- L
- X- b) ^# i* r6 C
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
, ]0 }) r: ~0 A+ `, e( n        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;* s% }4 P. ]6 S3 {) U
& r: Q5 h- X" V6 J+ I) X2 h
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
) v# {2 i3 n; e! W  Z        if( elapsed_time > nes->cpu->GetTotalCycles() ) {5 L) j$ @) P7 _+ i& f/ j' y
                QueueFlush();% ]3 O' m6 f' a# r2 x) e) x
        }
  E4 f7 J% A. A8 ^
. }( }# h* g7 B/ v; f        while( dwLength-- ) {9 B: C3 _, t& G
                writetime = (DWORD)elapsed_time;
% _; T' `; c+ \6 ^$ n
8 O( W; C$ |" O5 D) N9 M9 m                while( GetQueue( writetime, q ) ) {
, b0 v+ m, c6 @" `3 ?  S0 D* j                        WriteProcess( q.addr, q.data );
+ E, `  R4 u* R0 r                }' e! e2 _$ H9 \" w$ \/ w% c: Q

% A1 K) v' I7 y3 n1 q. G                while( GetExQueue( writetime, q ) ) {
% p, x  q, B# F                        WriteExProcess( q.addr, q.data );
  |+ ]$ o! G5 V( u' k" |) }8 v                }1 P3 H" r# T! w0 d- m: |4 _$ v% y0 j

9 k( ]' {* S$ L6 P2 U0 }% I                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
- j$ Z( c: {8 A                output = 0;
, ]$ w9 H' k# `. F2 F                output += internal.Process( 0 )*vol[0];
' t$ j4 z1 k, }7 ~                output += internal.Process( 1 )*vol[1];/ P" S7 [& a5 m5 i$ @+ N& {
                output += internal.Process( 2 )*vol[2];$ q" `3 E7 E. ~; N5 [1 K: I
                output += internal.Process( 3 )*vol[3];
. [$ E6 W7 i7 s3 c& @% S                output += internal.Process( 4 )*vol[4];+ A7 F$ B) d7 U5 O& n& F5 P
) F7 w' R% l5 I5 I  L0 T. b$ M# W
                if( exsound_select & 0x01 ) {3 e% S; U5 c$ o2 m+ l6 x6 ^+ U9 d
                        output += vrc6.Process( 0 )*vol[5];
4 ^, C- n) ^: t& u                        output += vrc6.Process( 1 )*vol[6];( r' `7 K0 `- y) }; o( i
                        output += vrc6.Process( 2 )*vol[7];
" e- }) f' u* A: X( V5 j                }; d7 t- z  _) w7 U
                if( exsound_select & 0x02 ) {# D* k# \4 `( J1 E: n* K
                        output += vrc7.Process( 0 )*vol[8];
# r. g% G/ y+ Z8 C                }( p1 o' C6 V  `& h4 x' z/ S0 Q/ m
                if( exsound_select & 0x04 ) {
: t+ }8 T! j2 p: o3 T) U" m                        output += fds.Process( 0 )*vol[9];
2 N) J6 r4 W8 q                }
  c+ b" g) s. ]3 }5 V- f" ~" c                if( exsound_select & 0x08 ) {6 L* D7 _# t" l# W- o1 V% v
                        output += mmc5.Process( 0 )*vol[10];
6 E8 S+ X$ A  ~5 _                        output += mmc5.Process( 1 )*vol[11];1 |: I- \. Q0 o; ]
                        output += mmc5.Process( 2 )*vol[12];
0 ]7 |9 I# v+ t9 L: f5 }                }
( L3 ?! A; |% s                if( exsound_select & 0x10 ) {0 u; X3 ~+ Q7 n: n6 e
                        output += n106.Process( 0 )*vol[13];2 V$ e! k, p+ J/ O8 _( _6 l
                        output += n106.Process( 1 )*vol[14];
* Y% _: \  E! v( {% a/ ?3 B; C4 w$ d8 Y                        output += n106.Process( 2 )*vol[15];5 s0 M2 J5 S: g- N3 p
                        output += n106.Process( 3 )*vol[16];3 }% i3 q% P2 D/ l, z
                        output += n106.Process( 4 )*vol[17];
  H, V5 k# N4 g0 J( o+ r1 l                        output += n106.Process( 5 )*vol[18];5 N, r# [( n+ T
                        output += n106.Process( 6 )*vol[19];" [3 l# X2 X2 l/ E( J' _
                        output += n106.Process( 7 )*vol[20];
1 q& t( D% E% V0 T" K8 t                }* Z; K  g" Y( [( K1 |
                if( exsound_select & 0x20 ) {, b7 E& N1 n% `  N% ~. V5 l
                        fme7.Process( 3 );        // Envelope & Noise% F3 `. I% m+ q3 T) k
                        output += fme7.Process( 0 )*vol[21];
: V0 O  W. O) ]                        output += fme7.Process( 1 )*vol[22];. P9 }! m: T0 R, t- O5 l. F& J4 n
                        output += fme7.Process( 2 )*vol[23];. E9 x0 u# D, L; a2 m% X: J
                }- f7 d" t, d& T/ M3 P' r

* _+ y8 C1 ~, Q* `/ f: t                output >>= 8;
/ y9 L- b5 R( J7 X- q
5 Y# S0 i' @" y$ `4 C" I                if( nFilterType == 1 ) {
; H# r; @6 x! t0 S; [9 W                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
# q, G- D+ B  V                        output = (lowpass_filter[0]+output)/2;8 [( R! K% V/ a) }# h
                        lowpass_filter[0] = output;
0 X( B4 @) @- O* l1 Z                } else if( nFilterType == 2 ) {' y1 j9 C: l9 i* w$ u! m1 H4 ]/ U
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)" ~/ ?7 k* t( j5 g8 G% v  `+ R$ X
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;3 J/ q0 u+ z2 `/ N' _
                        lowpass_filter[1] = lowpass_filter[0];/ H. V  o4 o# c9 V% }
                        lowpass_filter[0] = output;
3 Q3 _8 V+ i+ m; h                } else if( nFilterType == 3 ) {
/ ~. a* E( [2 k                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
& R; }* u! g/ K' _                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
$ O& o: a0 i9 f$ _4 e) f/ L                        lowpass_filter[2] = lowpass_filter[1];
0 T% N8 V, D" c, m. K                        lowpass_filter[1] = lowpass_filter[0];( |" h+ e, d6 P' @0 }# Y, l3 ^
                        lowpass_filter[0] = output;# t2 Y8 M; v( D. N
                } else if( nFilterType == 4 ) {
' w3 a, ~! s9 f4 @4 N                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
' q1 p' J: \% ~" V                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;8 w' {7 f1 A, J2 `6 e2 L/ a
                        lowpass_filter[1] = lowpass_filter[0];. _% l. o( V. F- m
                        lowpass_filter[0] = output;1 J. }6 {' ~& N. s; }* g0 `: S
                }; L( q" D+ Q- P) D( y. q

/ k9 H$ C; c& L, G: I7 B0 ?#if        0: L  [% _6 _) g) B! Q
                // DC惉暘偺僇僢僩
# `9 ?7 c. \/ y1 L0 e( \                {5 y$ r# n& h% K' o2 [
                static double ave = 0.0, max=0.0, min=0.0;* Y! v5 T* Y& B1 s: N$ b* c
                double delta;
- h  D' T0 p1 _5 o! ~* n$ A; _                delta = (max-min)/32768.0;
# B/ b  h9 k7 M3 Q+ q* g                max -= delta;
! H7 g7 \' y- W: Q: Y* y! W/ o                min += delta;/ y, g7 p9 V3 U2 n: w
                if( output > max ) max = output;( }$ U# d6 W; N& \
                if( output < min ) min = output;
6 e3 H: k! h* J  m                ave -= ave/1024.0;
7 d! T) R7 S1 @  b                ave += (max+min)/2048.0;7 v( Z: E7 v+ j- R1 Q4 u% f
                output -= (INT)ave;3 u& M3 B! Y1 }
                }
& u& y4 M% B) l- F0 b#endif
/ F' [: q1 u2 u#if        1$ ]3 s+ y1 v. z1 h0 U! [
                // DC惉暘偺僇僢僩(HPF TEST)# a  a* q2 g1 R. Y+ K: m( t$ e2 h
                {
# p5 [) T9 T- n& R$ ]$ i  V//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
) y% e, I5 M9 X* S; S% B8 E! l/ F0 M# J                static        double        cutofftemp = (2.0*3.141592653579*40.0);8 t  Q, d! X0 B% M5 L4 I: X
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
/ x4 t' d' W5 H" a, A+ ~' F                static        double        tmp = 0.0;
+ D6 {( p# X5 ]4 u3 v                double        in, out;
1 Z1 `7 v$ b4 \9 M
- S+ |: m0 k6 E6 k9 ~, a5 m                in = (double)output;3 D1 K( u4 ]1 e5 P- M
                out = (in - tmp);
3 ^' f; M8 ]4 U                tmp = tmp + cutoff * out;9 G6 n. D' b- d# e4 b4 j
% z; l& T$ y6 d3 Y0 n( d3 H& k
                output = (INT)out;' a5 Z. W  t; M5 Y% K, P
                }* B% }/ c; q! h5 H
#endif
$ }$ Y5 `6 J8 C5 s#if        0
, ?1 l  C% g. |* U  K0 |                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
  B( a) z. K' T2 d7 A& @                {
- [& Z3 g: ~' \9 e% M8 C4 ?                INT        diff = abs(output-last_data);7 A! Q: `2 z+ C
                if( diff > 0x4000 ) {# c, J. f! z  {+ S, x
                        output /= 4;- n2 c) w$ _! h$ F" u' `$ e
                } else
; j4 u0 F3 k) k  \                if( diff > 0x3000 ) {. G9 D4 l5 R% }8 `- k' K; L5 ?" K
                        output /= 3;- C# C7 O9 ~6 l' y
                } else
2 ~" _& [% }- H* I+ y                if( diff > 0x2000 ) {* h- y. w: I% l5 ^8 C+ |$ Z
                        output /= 2;
* g, W8 T& Z: S                }7 l7 w6 [. Z) F* H# J) b" A* {, i6 Y
                last_data = output;
1 W( {4 w  P& _/ |                }, m5 B* n2 S; ^& S" F6 D
#endif
. d' |  h8 H& J# k+ {5 V! M4 I                // Limit
5 U4 [. X* a9 ]. W4 @                if( output > 0x7FFF ) {
# {: t6 |  n$ [1 f9 c% B                        output = 0x7FFF;
# ^; J, C6 ^+ ]; l                } else if( output < -0x8000 ) {
" ?% _7 ^! Q+ M: I                        output = -0x8000;7 {( T- t- m9 I% F& _6 N8 a# K9 N1 c
                }
, P) @8 r, C, A4 T0 h6 {2 p7 ?+ r+ d- Y* \! b  v
                if( nBits != 8 ) {. G$ s4 J3 W, `6 K/ C
                        *(SHORT*)lpBuffer = (SHORT)output;
  c% O* l7 r. p2 t9 }6 F& J- d                        lpBuffer += sizeof(SHORT);
. Z: M: e3 ?/ [  E- w" X                } else {
8 p2 q/ O9 p- r0 [5 a' g+ h                        *lpBuffer++ = (output>>8)^0x80;
3 s3 S" y+ }! e  j( n                }
. P# W: ]/ s7 |0 k. u* r) H1 m' W% n# E( C1 j% I* z4 Q4 s
                if( nCcount < 0x0100 )
5 y$ Z( k8 {/ d9 w$ b                        pSoundBuf[nCcount++] = (SHORT)output;8 j0 v! D; G, `4 |' m
" e( t" Y; k$ ?( }! n$ k
//                elapsedtime += cycle_rate;0 `: J5 X* \; p# G; b/ [; w1 C
                elapsed_time += cycle_rate;( e. H8 H; X4 \6 u4 e0 Q; Q3 O% s
        }) m2 ?5 N- i4 p2 m
/ Z4 P9 W/ J- n6 x1 R
#if        1/ A. b( G' v& D
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {" R! k" ^0 I- L$ e) p9 `
                elapsed_time = nes->cpu->GetTotalCycles();
' V5 a2 J- ]* F9 t3 `4 l- J        }. s2 U( X0 |8 y7 D8 n9 ]
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {- G" Q+ {9 a; J/ a+ p9 a
                elapsed_time = nes->cpu->GetTotalCycles();8 f9 M8 s4 ^( x/ W, {2 j/ L
        }7 |4 r' u% u7 y! L: s
#else% m( J( @: f4 W% H
        elapsed_time = nes->cpu->GetTotalCycles();2 I8 O* n% w0 j" b0 d
#endif
+ m1 ^/ z# z2 m% x& `/ B}
% Z2 Y8 @$ i7 r- V/ [# U$ z
, [; a, ^; \7 f2 k0 T// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)4 z+ ^# m' r4 _5 I/ C+ x4 M
INT        APU::GetChannelFrequency( INT no )
9 T2 Q9 Q  o' R{3 p( z* b, A. @9 P5 \1 S0 e
        if( !m_bMute[0] )
% W$ m4 d$ k5 j$ x9 |  i4 m) B& c                return        0;
- q2 Y8 p  D/ c
# D' x# X; T- l: t        // Internal
2 p1 x% {1 F) ?3 f        if( no < 5 ) {& Z- L, x1 Q5 g' t5 d
                return        m_bMute[no+1]?internal.GetFreq( no ):0;. [- _$ K$ B$ L
        }6 S1 _5 U* {. Z/ E6 k5 o/ T
        // VRC65 n$ R3 j; A2 e
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {' c8 O- p. T1 T" j: m; D8 o$ E' j1 M3 Q+ R
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;- G# F) x# o6 T8 e3 q- m$ q
        }
/ ^  \- s& E/ `! Z$ x, U" v9 h! Q        // FDS
6 T3 @; P" @5 j% r; l        if( (exsound_select & 0x04) && no == 0x300 ) {4 e9 I; B: n- R+ O- H. f) `. G
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
0 P7 F! K) n7 q! t        }
3 G  `2 s. d( l& z. |2 N7 b' G        // MMC5
0 l2 R$ F3 z$ i# }; p5 b        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
( d/ r1 @6 q( h- I                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
7 Q8 o- n& _9 ?% }4 [, n5 }        }
# b' ?8 B3 h" c1 b! m1 ]: ?        // N106
, o& o* L9 f- N! i        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
8 }# E- T7 H5 E: Z0 ~! l                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
5 t. W8 H  x: h5 r. _3 `' [4 f+ P        }
0 @- P- Z" M2 X9 O7 C4 Z. w7 y& a        // FME7
, N  E! ~! K" H" x        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {* {1 w7 q% y0 t5 w
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;3 {1 h7 v# l0 V2 |$ i
        }
' @% [0 }1 u0 A) [. ~+ p/ G- H        // VRC7- U& W9 J# L- K5 w# U
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
* I! \3 o* T+ O$ j  n                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
- L8 k- d$ ~9 x7 W; @7 N        }' ?" n' {. r! O2 l# v
        return        0;( _6 W2 N. C% F$ m
}
1 n$ ^/ t6 \4 p2 G! l+ i
! z5 F8 a$ a, F' g// State Save/Load
. u: d. x) v" V! q! l. Dvoid        APU::SaveState( LPBYTE p )
; N* f/ \2 ~# {" W6 j7 h+ u{  G6 Z& `+ b- y9 L# u. h8 C
#ifdef        _DEBUG
4 w" A7 X6 h; qLPBYTE        pold = p;6 |; K' W) N! A3 `
#endif
. T* Y. D1 V4 n5 ~* q2 {4 Z8 G0 Q" ]( `8 K) q% j
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞; m' v3 c+ d6 Q4 x6 P* _' x
        QueueFlush();, Z* `+ T* h3 t+ y
) l8 s- S1 Z# @* W# j
        internal.SaveState( p );$ b% F& B' F/ L& l( f4 c
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding* K! s  }! h$ `$ J4 a
3 Q: f4 l7 i- p" W8 B4 C$ Z" ]9 B+ b
        // VRC6
2 M! ^, B+ ^* h: m        if( exsound_select & 0x01 ) {6 B! m( W9 s  f; q% Z
                vrc6.SaveState( p );- q" [) x2 c' V2 _% V: m
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding" n, z' n2 R6 a4 A9 |
        }! K2 @9 v! Y  t0 L( z* z% D& F# a
        // VRC7 (not support)* y$ q; F0 F! o3 _# K: z
        if( exsound_select & 0x02 ) {
) B. W) ]( S5 g" A5 t! R                vrc7.SaveState( p );. }; E. f- \: o$ N( R3 s
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
+ c& W7 R8 x) M) `7 |' e! E        }
" O) S: A1 d3 |* l        // FDS3 N- `$ M, u8 Z3 D3 t
        if( exsound_select & 0x04 ) {: _+ R: C' p4 X8 u
                fds.SaveState( p );
1 C, M$ }4 K% x/ `5 s& I) _                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
  O! F$ p& e* L0 h& Q        }
! R8 @/ x( J. e/ c        // MMC5
& c8 |. i/ Z& z4 Z0 Z        if( exsound_select & 0x08 ) {
0 j! V) n1 p: h# W8 u2 i& i                mmc5.SaveState( p );5 i2 E; ]8 o2 t7 Y; T9 r
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
1 j0 D( D& i6 Y) h' U        }" s3 }$ k8 F* m1 @2 w$ V$ @
        // N1065 j7 A6 d" J: ^
        if( exsound_select & 0x10 ) {- c! K4 i* }" Y! F) o3 ?3 X. _+ K6 o" f
                n106.SaveState( p );( T4 a- }% C- `& \
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
% x8 s# ?3 y9 y& Q9 c# O( v6 H        }6 J5 q/ Z& x. r9 ^
        // FME7
# g! P0 D8 `4 _! {- b; V        if( exsound_select & 0x20 ) {
5 m$ P! I1 b4 S) b3 L- w                fme7.SaveState( p );
2 V0 c" [; J9 H, K6 m                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
. }6 ?( w) V: P3 F! ^2 I4 x  D        }
2 }" I/ z& ]  ?1 a* h
* ?8 F+ _" E  c6 v#ifdef        _DEBUG
% `4 g) A% j; Q+ @# IDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
  k5 Y$ @9 k: {& F/ i#endif
/ _) ~! M8 i, h$ c! h  P}
: X' M4 K5 M+ X0 e3 z0 [6 t% b. G7 q
void        APU::LoadState( LPBYTE p )
7 g, l& c, D$ m+ e5 J0 w{
: J2 Y3 n( N" T* S- Z        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
/ }  Y5 P* ?8 j2 F# m- B7 D0 W        QueueClear();
& D/ Z; I# ^' @+ N
) E% S1 }; ]. g        internal.LoadState( p );
, s4 ?) R1 T! [, L        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
& W3 r* I$ [+ D) ?3 o9 h
$ p* ~( x% @5 t  Y- d  ?        // VRC6
; D: K3 a0 ~2 F( M* y        if( exsound_select & 0x01 ) {
/ H5 P/ s' X6 k4 h                vrc6.LoadState( p );
( G+ o/ T: E9 ~" d/ f                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding/ _3 D7 A8 T8 t9 O$ _
        }
- ^; e0 }' m8 `5 \        // VRC7 (not support)
7 c& s* r: r2 x- H0 ]2 J" e$ D        if( exsound_select & 0x02 ) {$ ]3 W: Z4 u$ z0 ]
                vrc7.LoadState( p );
  w- e  x* R: e1 ~' e7 `9 r3 d4 d                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
- t* K: j, D5 d7 y" u        }" ]6 r) e# L6 `$ y2 E* P, ]+ @% g
        // FDS
( t4 Y' b9 d/ f1 Y' G. v        if( exsound_select & 0x04 ) {
# Q; Y+ e' _: a- [% N* }% U                fds.LoadState( p );
- T. v, p' X; ~+ S% `/ b  N3 T                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding0 ?8 f  E" P% o1 J0 [
        }
  y. Y" `& R0 _, B2 N4 z        // MMC5" @# K& T& i! ?1 X
        if( exsound_select & 0x08 ) {" ?4 Z$ S$ O" K5 d/ S
                mmc5.LoadState( p );
' Y! m3 ]* p" f  Y! J                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
4 w, h1 P: X- j5 j! q* m- A% T        }( N$ B8 S6 t' ]- f0 [2 k6 Y, z, r  N
        // N1063 j0 N: j) [, W9 B8 s
        if( exsound_select & 0x10 ) {
' T9 R; l5 ?1 B: k                n106.LoadState( p );
6 i* Q- y; P2 Q( }7 T9 O$ e+ g% J                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
2 o# E6 g+ D3 S- U$ C6 D        }8 @+ g. r! c1 J! q! m
        // FME7  g: s' l0 R7 n( b) l! N
        if( exsound_select & 0x20 ) {/ X; i+ y  [% M- a
                fme7.LoadState( p );
1 u; c/ T7 f# C) K/ B                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
- C* E7 ~* T; [" |  ~/ r9 ?. s& ^. ~: p        }
1 n9 I9 T- _. @) r  K1 R}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 4 j( P7 H) w8 a. [+ b5 v/ Y8 q
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。& p0 e" y& D$ `5 \# X) e2 q
感激不尽~~

7 O- b* g( |" h* A5 s恩 我對模擬器不是很有研究,
! U, k. K& x& C雖然要了解源碼內容,可能不是很困難,
( H5 n9 b' N# P( r/ F+ a不過還是要花時間,個人目前蠻忙碌的。
7 q5 m3 L2 w% {4 Z: Q; O: m' f+ h% \: {  d4 i
給你一個朋友的MSN,你可以跟他討論看看,6 v. w' w7 n- Q  s, y$ W& {& J- Y
他本身是程式設計師,也對FC模擬器很有興趣。
9 F: S) S7 J  D- o3 g0 G* i% V$ ~# s
MSN我就PM到你的信箱了。
3 V1 o3 K/ @, K. x3 K3 [1 ]2 g4 N1 m% A; H) Q1 A5 r7 R
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 q0 ?; q  k( P- J' R; [6 }/ U
呵…… 谢过团长大人~~
: z. B2 E& x- d2 E6 q
2 _/ i' R( t* `. F/ |0 _* @/ G
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
2 l% a* R8 V- n- K团长的朋友都是神,那团长就是神的boss。

* @7 N4 e" Z5 a( M哈 不敢當,我只是個平凡人,
7 M+ @" b! _  Y' C$ j0 Y* c. z要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
) W# f) W& ^- i: _ZYH# ]8 W% k0 Z  H/ u  Y* N
QQ:414734306
! J+ J4 h' a& s8 ZMail:zyh-01@126.com# d, E- a  S; j, J$ U3 q

, ?. ^1 F6 h0 U- C, S他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 ! `4 @. l% U- w' C
再次对团长大人和悠悠哥的无私帮助表示感谢~~
9 k  b7 k0 L0 ^1 p5 a0 g! Z+ ]$ G; H
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-27 13:56 , Processed in 1.073242 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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