EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?6 U6 m1 R9 J2 a( F" r, [$ F
PS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
, r0 N, P0 j0 P' z- x4 a- I# _$ u) P楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~; k/ {/ r: Q3 Y1 y
这里有相应的模拟器源码,就当送给大侠了~~1 G' c  n0 e6 a# \8 W& \; v
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
0 X4 D" `! I. J, [能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
% e5 K% }. \+ O8 L8 @' i2 C楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~4 ~4 M# k' k4 s6 J8 B: g- o
这里有相应的模拟器源码,就当送给大侠 ...
* i9 [4 f+ L: Q9 S6 r2 B) I. p
聲音部分(Audoi Process Unit = APU):
2 d$ P& B+ Z0 K! _- c7 J! _.\NES\APU.cpp
) u$ X/ ?* |$ g$ y1 i.\NES\APU.h
. _: F/ B* b( [9 w( s/ Y% _8 v5 u/ f9 t. J7 D1 s) x) ^3 m2 `2 N
* a& O7 W3 B! j' s. p8 q# r
影像處理部份(Picture Processing Unit = PPU):
9 O8 h2 j$ K5 s4 \.\NES\PPU.cpp! y% z' b/ v$ i9 b: o+ Y
.\NES\PPU.h1 j/ _9 z1 ]/ U" b/ N

  c0 T) w0 p8 s' u, s5 Y如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:0 L. v7 K& r$ I1 \7 q# s
(由于很多专用术语和算法机理都不明白,所以看不大懂……)+ Q: T' ^: c5 V* ~' B2 S' R
//////////////////////////////////////////////////////////////////////////, w* K% Z; Z2 s1 v( G; N. I! e
//                                                                      //- d& n8 L( b& H! [7 T. a0 \
//      NES APU core                                                    //+ Q' A+ o0 U0 j3 Y- y0 A
//                                                           Norix      //7 q. }0 V: F; k7 G- e$ \
//                                               written     2002/06/27 //4 P- c# v4 M! Y, T( [3 g9 `
//                                               last modify ----/--/-- //
( g7 U0 u# r& Z3 |, G9 p//////////////////////////////////////////////////////////////////////////6 u6 v: Q4 l# }9 s4 F, M+ `
#include "DebugOut.h"
  M' v/ o% u) x0 Q" ]#include "App.h"" [* z( ?* y  n5 L
#include "Config.h"5 u6 V) C0 [8 b" Y* [

. {4 K1 m) W- q: h$ W#include "nes.h"# b" x" j/ O& a- x7 s+ y
#include "mmu.h"
' R( d' e! S. Y0 h7 a% [" ?#include "cpu.h"
6 m1 i! q6 A% V. t# D$ V: }+ q#include "ppu.h"
) n5 U4 P  N/ U3 E#include "rom.h"
; h% k$ D" k8 ]5 {1 s$ k#include "apu.h"! ?; s0 i3 l/ n& N/ G1 B0 c9 i
  T: r/ q# m3 r5 H1 F
// Volume adjust
2 ~& }) p% t# V* `3 J( t// Internal sounds
9 k0 v. ]1 b. @+ g7 m#define        RECTANGLE_VOL        (0x0F0)
& Q: a. r9 v; M  X! s( e#define        TRIANGLE_VOL        (0x130)2 E1 I( p; l: D+ w, k8 A9 N& W& s# S/ k
#define        NOISE_VOL        (0x0C0)
) A1 y: a; R- J$ W#define        DPCM_VOL        (0x0F0)
! d+ p, ?7 k1 V  T// Extra sounds. C4 k% J+ r2 u9 _  q0 i
#define        VRC6_VOL        (0x0F0)
8 t6 S! _6 O% Q6 [( d: K#define        VRC7_VOL        (0x130)9 F' O' ^5 o$ h- \! {" a3 u
#define        FDS_VOL                (0x0F0)
- k& ?1 A  d0 e2 A" Y#define        MMC5_VOL        (0x0F0)) y; A  l1 K1 ]5 U, Y0 u5 ~
#define        N106_VOL        (0x088)$ `! T$ A' ?4 k
#define        FME7_VOL        (0x130)
# C' ^3 T, ]2 n: @5 p7 A. V1 @) \  Z( }  X; C+ J
APU::APU( NES* parent )0 h4 N  z1 ]5 h0 |) a
{; S5 ^9 W, o& w% i: B8 d8 j9 a" a
        exsound_select = 0;
# X* u3 V3 l7 d' \" ]
8 _8 Y, n; V2 v/ ^, O        nes = parent;5 v4 w' s2 N/ H2 {; D1 m' Z" Y( W
        internal.SetParent( parent );9 ?& e, v' A' ]# `
2 Y% s+ p  q  I* d
        last_data = last_diff = 0;/ {9 a* X, r% x* ]5 E

7 m$ a! E4 y- P        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );" Q0 T- Q& O& Q
; A8 q$ `" @  G0 s. L! ?; E
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );. V8 i) k8 d- s* n6 l# Z" d
        ZEROMEMORY( &queue, sizeof(queue) );( w5 d0 A6 O7 `( n
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
# k5 Y/ v# E! U, c
4 V# c8 q2 C3 ?. x) I: Y        for( INT i = 0; i < 16; i++ ) {
+ N* J2 G4 X! m7 U2 _                m_bMute = TRUE;
! d+ f8 n2 |5 o# f0 S( M5 Y. _        }
7 @) H; d- `* _( }( S}
$ y7 u  Y, _- `( `# \7 e& [+ v9 L* n5 t1 Y! P2 D
APU::~APU()* C3 j5 X  U5 g. O! c8 v1 {# _0 t
{( r' v! G" p( g+ m  {
}6 m) }/ x- _2 L' J
& A) S/ Q" U6 H% O1 O2 T
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )% W0 E# A( s' x" N+ ]  m0 R
{# y, n) t$ U& }: o' V9 e
        queue.data[queue.wrptr].time = writetime;
" p3 K: u) G+ [  v0 G, D        queue.data[queue.wrptr].addr = addr;
! A- D5 b. s, }$ u' k% f        queue.data[queue.wrptr].data = data;
5 S0 t6 ?+ ?9 J9 x        queue.wrptr++;
; _* J4 ?$ w8 {, A        queue.wrptr&=QUEUE_LENGTH-1;/ ?. k7 e1 P+ c, j4 v
        if( queue.wrptr == queue.rdptr ) {* M4 O0 a8 t: e6 U
                DEBUGOUT( "queue overflow.\n" );
, Y1 i; c/ w8 H1 A/ j( s6 `) c! }' n        }4 |% E3 V- g) ~: H7 E
}
0 M" p1 m1 e  ?# a' e2 Z) m/ ~' a% a
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
* N8 i& t; n6 l: s8 W{
' i4 I* s- u  |. ]2 ?1 t0 l8 p) u        if( queue.wrptr == queue.rdptr ) {" X; ^, \( v( O" h( U
                return        FALSE;
' S9 v. f2 w2 E0 ?3 u* `& D# R        }% t# k" [6 H6 h8 y
        if( queue.data[queue.rdptr].time <= writetime ) {* P, y: f; N4 c9 j
                ret = queue.data[queue.rdptr];
, N( `3 A" S9 h* ?6 Q, _                queue.rdptr++;. ~$ H6 }, d% r/ l1 n# a& ^
                queue.rdptr&=QUEUE_LENGTH-1;
+ V: y9 }" H" c! V8 y3 ]                return        TRUE;3 b1 r4 n: A' `, [  |! H8 U
        }  a0 g$ X- `7 _5 ~
        return        FALSE;
, n8 D9 c6 ~6 O' U3 X, B) g% K}
6 k1 s+ U; v8 V4 t- q
) L& y7 O  |1 K9 Z1 N: ?void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
$ K9 w9 n! {; U7 l; m{
: d, R* q0 w6 R5 E' R$ Q        exqueue.data[exqueue.wrptr].time = writetime;
  r' Q! ~, [: _4 {( }        exqueue.data[exqueue.wrptr].addr = addr;
, C7 Q- V0 a3 W        exqueue.data[exqueue.wrptr].data = data;
( `/ K4 M( e# K+ s* B% M0 z        exqueue.wrptr++;
; r$ k& s$ s0 |4 d1 E% S        exqueue.wrptr&=QUEUE_LENGTH-1;
0 {: \0 ?; m; Y        if( exqueue.wrptr == exqueue.rdptr ) {3 H' W# ?# R5 o/ [8 y! `% H
                DEBUGOUT( "exqueue overflow.\n" );
: a$ L( A, T  W' W+ i2 [        }
/ T% U1 S1 h+ I0 S/ m( i5 [}
$ I( U. P" V4 p4 a; M+ T' W7 {" o8 O7 I0 e& d! K; \1 F. g, o
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
  V8 l4 q) I8 n* ^$ W{8 c- v7 `% w+ h; J% _- p
        if( exqueue.wrptr == exqueue.rdptr ) {
# u: j) R$ E9 v- O. J8 [' j% A                return        FALSE;- A- J5 p5 O% X5 v$ l! J9 ?
        }7 G* ?( [' P- H: D
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {) G2 x8 |9 A' _7 c
                ret = exqueue.data[exqueue.rdptr];
5 A# M) I- t# g( l. n                exqueue.rdptr++;
* |/ e1 P' _4 P* n' }; g" g                exqueue.rdptr&=QUEUE_LENGTH-1;( L9 t2 j) |& O' `: g  Z1 ]
                return        TRUE;4 q) v! o' c. e% ]
        }
. n$ m9 i# M0 w6 O+ C; }. Y        return        FALSE;
9 N# g! H$ H: e+ h}4 k2 e* L/ S" t, c" L3 }! Y" N8 i

! h' e: ?, M4 I4 k, N  R  {void        APU::QueueClear()' F+ G) H; ?9 T+ i2 r- w
{. ?  y2 Z5 b  E8 o5 b0 z. h
        ZEROMEMORY( &queue, sizeof(queue) );8 R6 T  A2 R- _
        ZEROMEMORY( &exqueue, sizeof(exqueue) );  e3 c! Z" |7 r. K; ^$ h
}
1 e/ @; a/ l6 c) E  V9 Q- @
7 r, I- J6 n1 D7 `1 Q; uvoid        APU::QueueFlush()
8 f* ?( ~2 z" I$ r8 ~5 C8 s{
1 z5 G9 n, a) U0 f        while( queue.wrptr != queue.rdptr ) {; v' `% o8 d# R* g' j- V; k* V: V
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
. v; K1 ^! U7 H: C5 {                queue.rdptr++;1 g3 l- L6 T4 C3 o
                queue.rdptr&=QUEUE_LENGTH-1;
) U& e- y1 \7 v/ A+ \        }
2 i. F3 U* e9 `2 Q( M2 x
' Q& G' _/ U! @        while( exqueue.wrptr != exqueue.rdptr ) {' E! \; X: W" d! G
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
7 l2 W, _- B! d8 s) \$ C                exqueue.rdptr++;
' J9 x+ |3 t" M; d0 o$ @                exqueue.rdptr&=QUEUE_LENGTH-1;9 h  t1 R0 N  m( ~9 \  M; ]; m6 s. {
        }
/ y& Z1 o$ ]! w% o- u}
! h/ ?5 e( ?! N- {1 o
6 P/ L  S/ @1 l" J7 |" D: j' V. Z" g( wvoid        APU::SoundSetup()
2 r5 [/ g2 |2 T* G, {- u{
/ B. d' P% [7 V2 `3 C        FLOAT        fClock = nes->nescfg->CpuClock;
4 b$ h+ n5 W1 D# F& a        INT        nRate = (INT)Config.sound.nRate;
! {7 W/ M: ~' y" E        internal.Setup( fClock, nRate );7 \" V1 Q) }8 T' Y+ Y7 W
        vrc6.Setup( fClock, nRate );2 ^5 [7 ?1 ~/ c, m2 O
        vrc7.Setup( fClock, nRate );; {+ ]# \( j/ y
        mmc5.Setup( fClock, nRate );
2 F, j- a3 `& h% B& K! U; b: x        fds.Setup ( fClock, nRate );" S  ]$ \2 `( }$ O2 d, w  E" ]5 Q8 O
        n106.Setup( fClock, nRate );9 t+ W, B% \' r
        fme7.Setup( fClock, nRate );
3 V1 K% f. c8 _* s( M/ x}* J4 Z! o  j% `7 _6 B% K

/ j+ ^3 m0 q- o( c/ F: P6 {void        APU::Reset()+ R9 y- a) H; }; o% O
{
& r! M, r" A; t. @2 O/ ?! x        ZEROMEMORY( &queue, sizeof(queue) );6 s+ ]' C5 y- s2 ~; p6 x" B
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
) p0 V: J, z$ V/ U2 c/ M+ R
2 \/ ?" Z5 e; Y7 Q* s% m& ~- w        elapsed_time = 0;
) Q9 U& g5 Z& D. ~
/ S& n5 f; \# T5 ]# V        FLOAT        fClock = nes->nescfg->CpuClock;
7 w" F7 \/ I3 e& Y1 c        INT        nRate = (INT)Config.sound.nRate;' i, K7 Z: A0 |
        internal.Reset( fClock, nRate );
3 l7 I% {3 J2 ~% C7 U: u        vrc6.Reset( fClock, nRate );
# }5 k* c* _- ^& S) D9 Y        vrc7.Reset( fClock, nRate );& ?. F; B2 R' u9 [- R
        mmc5.Reset( fClock, nRate );; _: L, {* X, O7 o
        fds.Reset ( fClock, nRate );( h, M8 Z' f% _( c, u! ~# H
        n106.Reset( fClock, nRate );
6 p: n) Y& D  C" w. A+ X        fme7.Reset( fClock, nRate );
6 A, c3 p$ e' r2 c
' B( b7 M& x! n, z) `        SoundSetup();
6 l: j0 M: z4 z% l}
$ k) n! {3 \( H! b6 e2 m. S
3 {1 P$ M; m% W3 m2 w. q" b0 f4 ~void        APU::SelectExSound( BYTE data )' i+ \3 X' T. ?, n
{5 Z4 h3 U) B: B# x( F! x  T* m6 u; b$ @
        exsound_select = data;1 @# B2 z" t5 c+ q9 y2 k( ~
}9 m4 S. \4 U4 c- T3 G0 ~' i2 m! M: [

8 a* @: E3 Z: p1 x& i! h, bBYTE        APU::Read( WORD addr )
, B9 [- O! h0 x0 M% i1 a{
- h* D/ t9 @5 Z; ?* G        return        internal.SyncRead( addr );  Z) ^# [4 k; m( v
}
& W) s, V  S  D# g/ r6 H3 @" J6 O5 d6 e  L$ E4 ?2 K
void        APU::Write( WORD addr, BYTE data )
% ~2 |$ q8 S* g: }% d: W{
+ B3 `) [6 ?4 E! A: t! {5 V        // $4018偼VirtuaNES屌桳億乕僩, h0 Y/ m7 y+ \
        if( addr >= 0x4000 && addr <= 0x401F ) {
, B, K9 c7 n  q1 L' {- ^) V' l                internal.SyncWrite( addr, data );
- a6 ~- n8 ^/ g" E4 m. T, T, P                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
2 ~: |6 }3 F8 s) G3 O+ y  z        }
9 h% x% t2 z/ o1 {5 j, ]1 h6 W}0 l( N$ x. J1 ^4 a, U* v+ a9 n

) Y% U& Y* ?; k* LBYTE        APU::ExRead( WORD addr )
4 R! ^, b$ w! }) @: L  r1 P{, K( u: l) H9 _  o# q
BYTE        data = 0;4 u# h" W/ d) ~

$ n; m- ]7 y% W" ]$ M: P        if( exsound_select & 0x10 ) {
) [- O- Q4 x# I0 K/ y                if( addr == 0x4800 ) {) f/ T& p2 @4 G, C8 R3 w! a& R' j7 K( q
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
3 a8 X& o9 H9 ^* P4 l6 [# w                }
. q; c8 m. q( t5 a" c, [: m; H        }. a, g0 F' |" @! o" k
        if( exsound_select & 0x04 ) {
* D: |5 ]- n$ l7 w' r                if( addr >= 0x4040 && addr < 0x4100 ) {, l# r' v* }* W1 S) d* ]( J
                        data = fds.SyncRead( addr );
; Y9 X5 S5 q) L: }. I- g+ f% ]                }. d+ \( L8 w2 j$ k, u: u  D/ ]) @
        }3 Z) q" i3 _) Z7 ]
        if( exsound_select & 0x08 ) {
# Y$ ]& x) I$ b1 l% v3 I2 C$ q                if( addr >= 0x5000 && addr <= 0x5015 ) {
5 o+ W8 ?' L) `/ k                        data = mmc5.SyncRead( addr );3 M5 O* E2 ?; S5 n) U2 W
                }  T" I3 Q5 W' g, p7 o" a1 i
        }1 }* Y  |, d; q3 g& w6 Q8 K

+ `1 |' `. O! ~: K: H  Y3 T        return        data;# a( S. j. c; z# L4 M/ T0 q
}" b' s# `# C  H! D  T
8 x6 F- W  Q' E5 f
void        APU::ExWrite( WORD addr, BYTE data )
/ k$ o! B" f6 j1 F' W* r3 n7 F4 D: e{# @5 b0 w; u8 G9 I5 a
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );) b8 f* P* S+ B9 y! O

/ X% N( A! m# L# k- F3 R6 `9 I        if( exsound_select & 0x04 ) {% q4 W" i4 K  b7 W
                if( addr >= 0x4040 && addr < 0x4100 ) {
% q- @: [+ K* A                        fds.SyncWrite( addr, data );
5 U" Q) i9 C4 |                }% m# y+ ^( {9 k& m1 n; b
        }  y, C* f) I6 u% {3 P, \/ x
/ P5 @# q4 s0 o7 k+ ~3 d, N
        if( exsound_select & 0x08 ) {( k) O6 [6 E& I
                if( addr >= 0x5000 && addr <= 0x5015 ) {
) d' \5 m, }8 D4 [/ o                        mmc5.SyncWrite( addr, data );
! j: C: N/ a9 i- f7 r% F                }" B+ B6 B( y; T( @* F# G, a* |, x
        }
/ R% H" n9 k2 t- g3 Y  b/ D}3 r& a2 y: u- A3 k# e

  k  P2 Q) E- h+ U2 Nvoid        APU::Sync()
: U& j" ]* G  X# K& M2 }3 h{/ ?9 u0 w8 S4 W8 g/ l" a, P
}
9 V/ \8 R. B  l+ B. l+ p5 i) g1 w6 p8 _6 `1 V9 g0 [2 U. o0 `. o* A
void        APU::SyncDPCM( INT cycles )6 X) D, Y7 O, s3 e% J
{5 V1 ?7 @4 X7 M- K$ a: t
        internal.Sync( cycles );
6 F2 w* j9 j+ l2 Z( ]( A, ?0 F' ?. s4 H8 L3 B7 C7 ?6 k
        if( exsound_select & 0x04 ) {/ B) W5 k& f& _8 p' ?
                fds.Sync( cycles );9 S: Y$ W- r' K% R8 _0 v1 d
        }
, v% U/ ?6 ?* f        if( exsound_select & 0x08 ) {. t& I+ z% s7 s$ `6 o5 c$ o
                mmc5.Sync( cycles );5 F7 e% C! ~. `. g
        }+ f6 i+ ^  r, V  |" N3 Y$ J
}
, x; C8 [; k* P/ y0 {4 y" ]- @# p: z
void        APU::WriteProcess( WORD addr, BYTE data )/ m/ l" L, _& u
{/ p. x# s; L" g9 o
        // $4018偼VirtuaNES屌桳億乕僩
0 e1 v* n, E/ q3 A" J# E. d& f# }        if( addr >= 0x4000 && addr <= 0x401F ) {, z  F7 j! E7 I- J# O7 L2 k
                internal.Write( addr, data );
+ B6 F+ L1 p6 q' x- v  K        }# y; j; I; n0 ~
}4 R# \% X4 E$ ^# |7 A8 s  _. m/ G/ _
3 q2 d1 N; E( \8 ]
void        APU::WriteExProcess( WORD addr, BYTE data )
+ C) s* E2 }. w. u0 {3 D{
/ F0 q( S: i3 X7 f7 p' D        if( exsound_select & 0x01 ) {4 \3 I6 ~' E; K* Z5 G' [, K
                vrc6.Write( addr, data );! L7 O/ D, q& u+ e! ~% t
        }  i" y. f: f. e: m7 }# V% y+ n
        if( exsound_select & 0x02 ) {2 B: d- A' F3 M( o
                vrc7.Write( addr, data );) a( I( C' t  w
        }" K+ P8 F% b$ P, |6 G
        if( exsound_select & 0x04 ) {
( q+ w) ^3 |7 W8 f0 H4 b' F                fds.Write( addr, data );
4 o4 j+ M) l: e+ Z7 H: J- m5 p( ~        }
/ N1 S2 u: d6 c/ R8 `# B        if( exsound_select & 0x08 ) {- V, T* \0 V- L% `0 B
                mmc5.Write( addr, data );2 I' z: F! n. g0 _* S+ T
        }
" m* d9 t8 G6 |( h2 L        if( exsound_select & 0x10 ) {
1 F, c8 K1 }7 o                if( addr == 0x0000 ) {
# y$ s" c$ @- N2 |                        BYTE        dummy = n106.Read( addr );
1 N3 Z$ e8 A/ v$ x2 [                } else {
1 N1 M9 _: }& m* I; G                        n106.Write( addr, data );
4 f3 M6 G. m- P% g. }                }) B  F. Z0 a- v) o
        }' N( [" J! O9 k- c" q+ {- K# J
        if( exsound_select & 0x20 ) {
4 W# e( u) \9 @! I) F( H                fme7.Write( addr, data );" [. |/ P1 Q$ T$ l
        }
, m* z' H0 Q1 R' ~}: B" |& H* V. l( B/ z3 X

. a1 \& ?( q7 zvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
; p1 U9 ~, f9 p{7 S" t$ w" u1 g8 j0 o
INT        nBits = Config.sound.nBits;5 c; t8 T, w7 U  S3 q' f# }
DWORD        dwLength = dwSize / (nBits/8);
5 d8 |, y2 ^4 ]4 W: jINT        output;: e5 Z& C  J, \1 `; ^/ V
QUEUEDATA q;( x2 Z" W& |  W* a: ^
DWORD        writetime;/ V% r" F" H/ _. u" s- {' h& A
' K% E, _+ g) d- H  a1 B
LPSHORT        pSoundBuf = m_SoundBuffer;
8 v3 o  |& Y+ b' [INT        nCcount = 0;, u% z" B& g3 }# A4 p/ k" y* m

5 E% ]+ s0 I1 B, pINT        nFilterType = Config.sound.nFilterType;! w8 h% c0 J1 U$ O2 Q! ^
- y8 U% q2 H) R/ k3 C+ G+ M% P. P
        if( !Config.sound.bEnable ) {
( f1 O! H- j" i9 ]2 g$ J8 Q* s+ |                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
( i# o. N, J/ S+ j, z                return;5 N& m8 u! R* A% X$ s2 F
        }
" W) Z9 F+ O3 s3 |; x% F
) |$ a7 Q( G. a8 N        // Volume setup9 T6 L6 ~! c2 }4 u/ E1 _0 N9 X
        //  0:Master
) `$ r/ E4 g2 c  }# d! E% j' b        //  1:Rectangle 1
3 w# I7 v) k" l" S        //  2:Rectangle 24 M6 t' X" W6 K% d  H# y8 ^" J
        //  3:Triangle/ T# C4 z7 x+ T8 S
        //  4:Noise
( ]) m. A/ R# b% E8 A8 \        //  5:DPCM" D' o: m# g: ?- h* W; `
        //  6:VRC64 [, j) K) q1 t; o3 d- y
        //  7:VRC7
; r/ A0 Q0 t, U        //  8:FDS
8 N6 Z% y) y- [% q# x5 J        //  9:MMC5' Z6 B% B% R/ Q! m
        // 10:N106. A: C; r2 Z# Y' v  j6 ?& f
        // 11:FME74 }" u7 ?- |$ {& k4 _  E6 W1 L8 L; P- z
        INT        vol[24];! }) X5 F! \" x" F( h! h/ {
        BOOL*        bMute = m_bMute;4 {( j0 K" j+ S5 h
        SHORT*        nVolume = Config.sound.nVolume;, {3 z& b' \1 O$ o: N4 C

; i; F; j7 J, u7 k        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
9 p7 \7 b' X" p, ?" f
; h- Q( a- @! _) f4 J8 n        // Internal
- r5 W2 ?! U* ~4 \        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
& W% w0 J* n3 m- ^& E1 _9 n        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;* c) a: D- L# K: C* s- U" L! A
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
4 ^+ H% ~+ P) {* M* V        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;$ z- U* B) |6 h
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
4 u# O) f+ T# Q* _+ l2 {+ O; ^8 C5 Y. y: X1 a8 `. G
        // VRC61 B# u$ B& S  q, ^& o, ], [
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
/ I' M# r3 _! p; l3 A! [: A6 U        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;8 P5 ^5 O* S, C' x
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
1 i" P& T+ q! T. x1 h
1 w& M: y& q, ~/ h' W* ]$ L        // VRC7$ P3 r, \% h0 l  ]3 ?8 i: R2 @' h7 R
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;$ W0 h7 n7 G; t0 _
1 B: h2 {1 I0 v+ f+ w; z8 g5 [3 d
        // FDS+ H4 A9 C7 l7 X3 D
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
. }* v* E4 @7 g& ^* |
6 a. o# p( \: k  l4 B        // MMC57 \* x1 ^9 |% E5 W  V& h
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
: U$ O  U- ^. z$ P+ a" r        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
5 J1 t2 v8 M$ x9 z2 g        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;, U  X* N1 Q# z# V2 J& }
& G: E" z3 U, }& c* i& E4 j) z% w
        // N106
' U; L' n, @& P* c- q2 f        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 t) T% {2 j9 D+ s6 h0 Z6 t        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 J7 I. _0 m) a# X
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
! E/ [& c. s( T; L- A* n7 X        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
' D! A: N* J+ w6 u- V' [7 {6 m( f        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;9 Z2 M6 D: w+ ^& d( G
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
2 L# R! L% z- f4 u0 A  H        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ w) z2 b4 U4 C2 ~- O% n% g
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 F/ y0 c. b. ^4 D: Q
1 x' k$ X3 i7 N' e6 \* a        // FME70 V* e- T( @+ n( \
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;5 N9 E( c& c9 s/ N: V
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
  K+ n7 z( K3 X2 a' G( @( @/ ~( }        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
# {4 j# w* `1 y& }" w( H( ]
4 ~8 ]% s* k" W9 Z" `2 i//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;, O  v4 x$ o3 u, {, T+ _$ Q! B
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
9 l0 U- \9 Z1 N$ L" Z. U. O( @6 W/ h: O" R5 B' @
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
0 ^# z& m) R: _* ^# x        if( elapsed_time > nes->cpu->GetTotalCycles() ) {. j4 t' K7 N- I4 s$ i0 f2 b
                QueueFlush();! P$ l: `4 H$ S
        }
0 H" i8 f2 }" g! Y* Y# e
3 q% m8 v) I! x* O: V5 O        while( dwLength-- ) {
3 C, S& P& C, s5 p% ], q+ n7 o                writetime = (DWORD)elapsed_time;
$ a! D" P$ Z* u2 t% d* G! t
4 J5 Y" T8 I( T( S1 j                while( GetQueue( writetime, q ) ) {) P! H$ ~1 I# F1 Z3 S, s
                        WriteProcess( q.addr, q.data );0 }6 q! v& `# n# s
                }' B% N% L, C. A% w9 ?7 [  P) ^4 B
3 L( V( j2 `0 U8 |2 t; h
                while( GetExQueue( writetime, q ) ) {3 s* R% e0 ^: [9 s, o) p% I9 v) f
                        WriteExProcess( q.addr, q.data );
4 C( N7 h' R% D8 X. f                }' o4 b8 y2 }' i% O' F8 m% i5 k

" [  g5 J$ ^, V' c( j9 Z                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME73 j: T8 l6 v/ D
                output = 0;, L/ U6 y6 W, U* D1 a  X
                output += internal.Process( 0 )*vol[0];/ \2 c9 d; O' d0 |7 }
                output += internal.Process( 1 )*vol[1];
$ a1 Q2 E+ M9 |! R& _# m6 S                output += internal.Process( 2 )*vol[2];$ M" O5 V: A6 W4 I
                output += internal.Process( 3 )*vol[3];
: h3 p6 f+ k( J" m, L# l  U, m& y                output += internal.Process( 4 )*vol[4];$ Q/ x4 Z' _5 B. K* q: }
! n. L- A. w8 O6 l- @% I- p
                if( exsound_select & 0x01 ) {1 m1 S' r* z1 @8 Z+ F1 u5 H  k* I
                        output += vrc6.Process( 0 )*vol[5];' Y# X# V0 |9 R1 o4 [8 b+ }# {$ T
                        output += vrc6.Process( 1 )*vol[6];
5 n9 }% F+ I6 S8 O: s                        output += vrc6.Process( 2 )*vol[7];
$ \6 P2 r: R2 L" N( ^, b                }
0 r  G. p! H! y$ S                if( exsound_select & 0x02 ) {
6 p% c& m9 F# L& F+ ~" ^* b: n5 C                        output += vrc7.Process( 0 )*vol[8];
, E! S3 \5 @6 f4 r/ Z. k                }
% T  o; `& Z( a3 @! M5 k" l' ]                if( exsound_select & 0x04 ) {  N+ I7 w; r% K
                        output += fds.Process( 0 )*vol[9];
: P- b8 w! B$ ?" a. @) k                }
$ x; p5 |, D1 Z7 p4 o5 D. y2 L) m                if( exsound_select & 0x08 ) {% I: N/ p! u- p4 j1 g+ t9 K
                        output += mmc5.Process( 0 )*vol[10];
/ t$ B4 H- Q+ I5 W& e                        output += mmc5.Process( 1 )*vol[11];
/ A2 u( Y( h2 u                        output += mmc5.Process( 2 )*vol[12];/ v) O- r* [2 m% M& I
                }
. S- j" g3 u* |                if( exsound_select & 0x10 ) {* q) U) g: w3 {+ k
                        output += n106.Process( 0 )*vol[13];0 V) q! ?8 z; \) \5 q# K1 u/ H9 d
                        output += n106.Process( 1 )*vol[14];/ H# j6 E& h) s2 u, L
                        output += n106.Process( 2 )*vol[15];/ y# S' K5 i& u
                        output += n106.Process( 3 )*vol[16];
8 a+ Y. q5 z' W! L( H% h                        output += n106.Process( 4 )*vol[17];
8 i  C: E3 d* S                        output += n106.Process( 5 )*vol[18];$ N: P$ R. u$ K  x
                        output += n106.Process( 6 )*vol[19];, J2 `, G/ X. V+ I4 ]7 ~) t. Y- f. x
                        output += n106.Process( 7 )*vol[20];
+ s# T/ |6 p, Z; H: {/ h                }  N! E2 o! Q6 h
                if( exsound_select & 0x20 ) {
9 [4 T/ l8 N$ a: R9 @( C                        fme7.Process( 3 );        // Envelope & Noise+ v2 T5 t2 X6 Q
                        output += fme7.Process( 0 )*vol[21];
3 Y. b& [* H5 D* M% p; q7 K$ S" j7 q9 H                        output += fme7.Process( 1 )*vol[22];& Q* T- [7 ?. @$ A) f
                        output += fme7.Process( 2 )*vol[23];* r! p; B6 x2 U
                }$ _" r2 o$ ?# d& Z3 F) r
! b1 _- D5 g! O: h  N
                output >>= 8;% _3 m* d. [0 w
# f4 `+ d" x# r1 w  @" K
                if( nFilterType == 1 ) {
7 d; j1 o5 E/ g1 e$ I0 N                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)6 T: E0 M3 o. J3 j# R* V
                        output = (lowpass_filter[0]+output)/2;. {' c9 t# u; O' z' Q7 _
                        lowpass_filter[0] = output;
6 j( |5 |2 ^+ i" B. N( B                } else if( nFilterType == 2 ) {4 I2 T+ \  a8 R: ]! }; F
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
  W$ G. R9 E) M; \                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;( ?# m4 x# O* H$ X, ?( \
                        lowpass_filter[1] = lowpass_filter[0];& n# \7 C# b3 J* P+ z8 k7 {
                        lowpass_filter[0] = output;
) |9 W) o6 g2 s0 c4 P                } else if( nFilterType == 3 ) {
7 V0 Q& F7 C# H+ u  M                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)5 H7 h- A& \9 {- e' e4 G& q! _
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
/ k8 P4 k% U" R                        lowpass_filter[2] = lowpass_filter[1];
* S& x) x7 L* Z# R1 M6 ^                        lowpass_filter[1] = lowpass_filter[0];
) g# }4 ?& K: E$ ~$ n                        lowpass_filter[0] = output;7 w9 Z5 P! z' a  t2 x2 q: L' P
                } else if( nFilterType == 4 ) {& Q  _3 M5 @( @# A8 F  e7 ?4 b
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
- T9 O2 |) N% B0 a% Z                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;' n' z. a1 H$ X0 e7 O/ a# I) y
                        lowpass_filter[1] = lowpass_filter[0];
8 l$ W6 e" ~) G2 @                        lowpass_filter[0] = output;+ A1 v4 f- s0 ?3 D8 V9 l; D
                }
8 s2 R/ H: [  s' d
+ ~; k" K& m& J: p2 ]4 ~) U0 F3 k#if        04 a! h3 i, j% H8 _/ e3 y; c
                // DC惉暘偺僇僢僩+ v6 h' u+ u8 T* n. D
                {
* }) x' }( u8 A! c$ q( v                static double ave = 0.0, max=0.0, min=0.0;
) X, I- H  y+ \( w4 i( p* C                double delta;
5 ?9 D3 h0 N) x                delta = (max-min)/32768.0;8 ~3 _7 G8 Q8 `4 g) ^% o7 Q$ n5 K
                max -= delta;9 m) s/ g  E, X3 O
                min += delta;
9 f% a1 U: ^9 D. V                if( output > max ) max = output;
. w# T: @3 O- M1 l                if( output < min ) min = output;* J6 ]& U. c6 I0 p! ?# w
                ave -= ave/1024.0;. @  }5 L) k; V0 {/ a
                ave += (max+min)/2048.0;
& e, B+ P& ^0 i# I4 b! f                output -= (INT)ave;+ t7 |7 B  z, G0 |0 X3 T! F7 ^
                }2 X+ w. G3 _" ~
#endif
& z# U: i' q7 [; L& i#if        1
5 Y3 f* H7 ~) |7 S                // DC惉暘偺僇僢僩(HPF TEST): H; d0 N( [, ~
                {& E5 Q, h8 y8 w  s9 w8 g
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
$ I( \, G' b! J" o5 N0 q6 F                static        double        cutofftemp = (2.0*3.141592653579*40.0);, U8 S) R* j; p' N, O5 c2 I
                double        cutoff = cutofftemp/(double)Config.sound.nRate;+ v: H5 x: F7 W- c0 {/ H
                static        double        tmp = 0.0;# a# r' Q& e# k2 l* g
                double        in, out;
. I; x9 ^% ~/ d; X. k+ W5 L& B9 G  u( O- Q
                in = (double)output;! ?5 B) K' v4 G6 R  O
                out = (in - tmp);
9 l9 M5 a( A  A. ]& C! x                tmp = tmp + cutoff * out;; g' I; p: X* {( b$ m3 e- u( S2 m$ Z
/ T1 n+ R% x( W# U! t, q" t
                output = (INT)out;' x6 I2 D! \/ o2 @8 Y! v
                }
! q- Y# M- v9 b#endif
' O" R% A2 D7 k( J3 Y- I#if        00 M* p$ E" s1 j
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
6 i, O) f4 H7 [0 W% V                {
% m9 o( q, O+ L# G* r. g$ k' k) x                INT        diff = abs(output-last_data);
& R# Z7 ~& B+ n8 C. y( _- D) j                if( diff > 0x4000 ) {: s2 P+ P8 V. _2 P# m8 c$ H# o( c1 D5 M
                        output /= 4;8 `" T' d: O3 }/ c
                } else
6 I0 Z( S- i" J1 h: \9 p/ Q; N                if( diff > 0x3000 ) {3 N+ \. w5 P% L( f0 w  C
                        output /= 3;( Y( h. }  x% J2 u$ r
                } else& @6 R1 E( H) M2 Y
                if( diff > 0x2000 ) {3 P5 V2 I" l, _" o9 n; I
                        output /= 2;
1 ]4 f5 V* S/ j; }7 H) n% t                }
8 v) E$ u1 r3 b3 C                last_data = output;
- ?. w! n/ p% D! \1 ?                }" p) f" D7 I8 E1 @6 u6 h  m
#endif
- P( Z, G) [4 ]6 t4 Z8 E                // Limit
% A# G: V: |; n. U3 o                if( output > 0x7FFF ) {
8 {: J% o: l' P4 C4 N4 U                        output = 0x7FFF;
; g( w6 V( g! t/ l                } else if( output < -0x8000 ) {
: X* g1 b$ L3 C, w0 h5 p                        output = -0x8000;$ V% ?: I$ u1 w
                }4 H  V! e1 T7 p5 I( J& b3 q
: m& V  V6 O/ @* j  W
                if( nBits != 8 ) {
/ \& T& j& a* m5 M                        *(SHORT*)lpBuffer = (SHORT)output;
$ t$ e. x0 S- E+ t" E* O; L                        lpBuffer += sizeof(SHORT);
' v# q' D+ i; k7 z' ^" E                } else {
6 U# ^' d! l0 Y" g  o                        *lpBuffer++ = (output>>8)^0x80;
; U! Z5 K, J, A! l8 K1 J                }
9 r6 e# O. \7 [0 ^, K6 L* \+ j8 q* J9 [8 S: }- k3 @
                if( nCcount < 0x0100 )& \  L! d, h8 O+ Q
                        pSoundBuf[nCcount++] = (SHORT)output;
9 k7 G  c" M) M* n2 z$ @
: K. N  ~1 `( g, M//                elapsedtime += cycle_rate;
9 z, s% M6 R( P( M5 Q0 E% c& r                elapsed_time += cycle_rate;, I5 Z. f4 x" @7 a: q
        }
6 u% B' j! u8 Z; i5 e7 H6 i6 E: X- o8 |2 }  |6 `" G
#if        1  ?3 ?$ A% _$ B4 u+ H9 i
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
! J* Y; x3 r; j; k  ^( W1 v7 i                elapsed_time = nes->cpu->GetTotalCycles();' i  d4 u$ L! K  l
        }
8 L& s% ~$ ?7 S& H. t8 D) ~        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {8 C% ^2 _1 f  @; |2 H* H
                elapsed_time = nes->cpu->GetTotalCycles();; X- `( A: N5 \7 H5 S
        }  x( w% m( V1 r" |( C$ S/ h
#else
6 r% t' k. S! P* m        elapsed_time = nes->cpu->GetTotalCycles();
* q: I3 t4 W" W7 L0 `( c#endif
/ h+ ~3 q. |% g' r1 i}/ L2 q' g$ V- V" Q  v: B
0 T, G. n/ j/ G7 ]5 N2 r
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
1 ~( [; x, x( O; ?( `; z( ]- t* IINT        APU::GetChannelFrequency( INT no )
' }; b+ X2 \3 b& E4 e8 B{
$ G; v1 w8 m$ I0 I! i- ]        if( !m_bMute[0] )& v$ J* ^; P% m/ G* ?6 V
                return        0;
8 Y& T6 F: o3 q" B+ H7 |" Y; c6 V$ B
        // Internal" r, J) J3 S; `' J2 c4 u" h
        if( no < 5 ) {% x  {! L- q+ t! N. z9 s
                return        m_bMute[no+1]?internal.GetFreq( no ):0;! l7 t0 d/ F) C2 S) s7 l
        }9 ]9 V" o- @$ w0 K2 g2 a: r! D
        // VRC6
+ F6 f* n$ n* C+ h5 i6 x  j, [7 ?        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
2 y$ H7 n9 P6 c; C2 ?. S8 B( c, g                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;5 q: \3 a6 c  c; |
        }
" E% K; l2 C9 {! c5 s) P* ~; _        // FDS
/ q0 G$ G7 c7 F  g        if( (exsound_select & 0x04) && no == 0x300 ) {
  K+ ~# T/ {( R                return        m_bMute[6]?fds.GetFreq( 0 ):0;
- k9 ?& |1 j2 I        }
; i# y6 O/ K) G- P; s: a3 u3 l        // MMC5
2 `2 B- ^; R; X& d        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {; p+ H: A# {! V, f! b5 c5 K
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;" l& z- Y$ o' Q4 n( W' ?
        }
& |# m4 l4 p1 z; l        // N106
! m$ \. c+ r- _. L        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
1 z5 X* ^& ~$ }2 [                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
% R) D+ H1 S1 K& o0 I, a        }# x0 d: H1 i. b6 J
        // FME7
, H- S# r: a. K        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {9 B0 x+ O- W, h7 n# ]
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
! y1 Q) P4 J6 n7 m( _/ V' _: N        }; l/ o4 ]0 c+ `8 K% a" v
        // VRC7
5 i: K# h* ^7 q  s1 ^6 f8 X" R        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {5 @6 D# A. w; x
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;6 I* M# G  o) p$ Y  n
        }
& y0 Q& Z! n) P1 b+ K8 P0 _  K        return        0;
1 e4 \3 ~, u0 M0 Z. |# Z/ T# T}
  t" D8 U+ }7 d* m9 m
, \. O9 P/ T! L// State Save/Load
# \, m3 ~4 m% Y$ |void        APU::SaveState( LPBYTE p )! s9 C8 [& D1 a4 M" p- c
{+ X! w+ c4 K  Q. e
#ifdef        _DEBUG: j. G7 ~2 m, J; i/ r7 G( A
LPBYTE        pold = p;" }6 U( R2 h  W9 i2 a7 _8 U
#endif1 z0 ^8 }4 [2 t$ X0 D: F$ S

  i2 e0 H! O! T) P        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞  L6 w% B7 y/ h$ B- N6 T( u% |
        QueueFlush();" L$ R: n5 Y! [. G& Z0 y* E
' t/ z) X9 ?" k* Z# w3 u
        internal.SaveState( p );; g0 Y' |) W$ x3 [
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding5 l- P6 X3 @0 r/ I1 p) D/ p

) l$ T% ^1 ^& Q, v0 A. L' Q        // VRC6
7 s' Q- h5 L: B" ~+ F        if( exsound_select & 0x01 ) {
$ L! J7 L) _/ ]: W9 e) w1 L                vrc6.SaveState( p );
. L" }" k. c$ b9 j% {, q5 u                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
/ J7 t' |, C% k  ^0 T        }6 e( e' {) T; }' d6 W
        // VRC7 (not support)
- z1 I2 B' ?% h* ]# a* q        if( exsound_select & 0x02 ) {
+ }/ \+ C3 v; Y% R& V0 {8 v+ _# J0 c                vrc7.SaveState( p );
0 L! k" L  O2 j2 {. ~                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding/ i6 `! J& q- D. h
        }/ c2 }# P8 {0 w( P6 f
        // FDS
. ~9 Y2 O' n* s' ^        if( exsound_select & 0x04 ) {
" ^+ @+ y7 ~1 l; j7 v- l/ F; V6 u                fds.SaveState( p );
8 \- s( n: ]* r6 k5 V* ~                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding- C) M  J+ a( M
        }
( N* o- S. H/ ?7 i" F        // MMC5
* h# x. {* o5 w( V$ \        if( exsound_select & 0x08 ) {
; u: S# H. @- T$ N( n                mmc5.SaveState( p );% D1 E6 y$ N7 Z, ^! _: e
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding5 O2 P/ N9 p5 z5 x
        }
0 j* \8 a+ i8 Q        // N106
0 L2 x2 n2 c" P; n        if( exsound_select & 0x10 ) {5 ?% F" D! T# ^9 k! D2 _8 }
                n106.SaveState( p );* z% [( E! u( G8 S4 E
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding  \) e+ ?$ w3 g
        }
, _7 c& q4 b& F1 T; }6 a        // FME7; o  s2 W: s4 s3 N/ A  P
        if( exsound_select & 0x20 ) {2 D1 G. U( e4 l$ d6 k; e; ^9 P
                fme7.SaveState( p );2 j) V1 d# @# s7 K9 o" G0 O  F
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding$ `& @5 B" m6 d! k" v
        }6 x4 p8 I3 [# B- S. F* \0 Q% o

, T$ |* s9 u: O; X#ifdef        _DEBUG
" n. }# l) }& D5 d  q0 [DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
9 D/ j* U' X8 {, M: \9 w% m$ M#endif% Z; U. B1 t. H% @9 I/ r
}
* t' f% z3 S9 n2 E* ]1 F5 n8 Y' C  o) m' l1 F7 c3 Y( x. w
void        APU::LoadState( LPBYTE p )
8 o  s2 E7 e! w4 W% x& u: w{- ^$ L! r0 r* M! @
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
1 O5 G- ]0 |/ e6 b' A5 J# u) [+ I        QueueClear();0 K( j- W' [9 O) p7 L

* Q5 B, d' A2 M% r/ V        internal.LoadState( p );9 s" }8 v7 g" {; p7 k- n, x
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
3 Z* j/ \& W, c+ C9 {6 h5 u4 c0 r* E6 N+ ]6 \8 s- B7 S/ Q+ M; d
        // VRC6# d& i1 h* ]! Z$ C4 u( `& y  @
        if( exsound_select & 0x01 ) {2 ]3 p0 a9 {( W
                vrc6.LoadState( p );5 v& A4 r  k" c& M+ \
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding. \  u: ]0 y+ z+ n
        }
! S5 W8 [$ F) o7 G' [        // VRC7 (not support)% O: N, O/ P$ i& o
        if( exsound_select & 0x02 ) {
( O' @/ U* a1 F* x                vrc7.LoadState( p );
- U. {# [+ w" t0 r                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
4 j! p0 e5 j! [! s& b        }1 {- ^: H& w; j% m7 G
        // FDS
/ T  A3 ]: u3 m6 e% r- r! Q        if( exsound_select & 0x04 ) {
* Q3 p. {( U. J7 n) V                fds.LoadState( p );9 u+ J7 |- j9 N" ^% Q
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
1 \" n7 t8 ^! F( d# P* y        }7 Q; r/ U# }" G" r
        // MMC56 W6 D6 d! J# D
        if( exsound_select & 0x08 ) {
, Q; U4 N) x* U: L. F                mmc5.LoadState( p );
3 P7 k8 F9 ~( G, N; ~7 w6 h                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding+ U, `3 [" I  S# F4 w; y  \4 R1 ~
        }, r1 h% g/ Z- C. C
        // N106
9 j& ]) Z; l7 Z# K        if( exsound_select & 0x10 ) {) M0 Z# q, \1 y8 F! q
                n106.LoadState( p );
. v0 d# G# N6 d$ j1 T                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding6 y+ T+ Y1 G1 Y6 _8 m
        }
1 v* ?0 K& h/ R; O+ @        // FME7
; A( n( w. I( n7 e, ]  G        if( exsound_select & 0x20 ) {  B7 `2 E2 R: C8 O2 ^  l" V
                fme7.LoadState( p );
( {& h+ X: d! g; }( v$ [                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
  w; ?" P9 I1 L/ ^) O3 @        }5 S4 k3 X3 w8 ?: y5 }: W
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
6 M; g* q3 s7 }; d1 [7 d& m可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。! W) B5 M6 {0 W8 B& ]5 k
感激不尽~~
" v% R( j/ O* ^9 w# T  ]
恩 我對模擬器不是很有研究,7 p8 l4 g% N2 s6 H* e- }/ A/ n
雖然要了解源碼內容,可能不是很困難,6 L; \' d! L7 P9 o5 h. h! j9 R0 m
不過還是要花時間,個人目前蠻忙碌的。
0 ~3 f% Z! m1 ]" E% m
& k, B: z! N" i4 L/ w給你一個朋友的MSN,你可以跟他討論看看,
6 A6 L: K) R6 j% d2 @1 Q他本身是程式設計師,也對FC模擬器很有興趣。
! O4 T* U: [& M. x2 |
7 c4 A5 l7 N; H7 kMSN我就PM到你的信箱了。4 [7 ?; O& G3 R: H

- d0 K" v$ X' k* P+ @希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 ' N2 @' Z. U# W1 m' Q
呵…… 谢过团长大人~~
2 m' R: o9 J1 M8 ?2 h0 t( V- M. g
7 _2 k4 ~- l( ]) V# a) R
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
* ?6 U6 w8 C5 n3 U* S团长的朋友都是神,那团长就是神的boss。

5 o2 L) I+ F4 c  y哈 不敢當,我只是個平凡人,4 c7 q! X. `6 }! P4 ?9 U
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
: _7 l2 l, X' V. I" gZYH2 Z$ T$ U/ I2 O+ ~8 N
QQ:414734306* `& }6 J) w' g8 i1 `) g6 _; w
Mail:zyh-01@126.com# ]; n) ~. y* w+ g  b

" }, {4 J* s7 Z) f1 L1 K: ~% a他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 % L: W( [3 f! g, j/ w
再次对团长大人和悠悠哥的无私帮助表示感谢~~
2 L; R' P" b5 r1 k. U
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-9-19 00:52 , Processed in 1.076172 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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