EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?/ J" O5 T; ]* u+ l# ^! w
PS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
  ~8 l( O' ?3 ], w1 m楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
) U- |) m0 }5 j0 b" O6 Q4 U这里有相应的模拟器源码,就当送给大侠了~~7 F( y+ h/ t6 P5 ^# o1 u! V. e
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
6 x  ?( s; N9 V/ C能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。0 i, B: l2 Y4 c9 x; i
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
" p! C& N0 k% f/ Z) B这里有相应的模拟器源码,就当送给大侠 ...

+ K7 B$ e( s: E- X0 ]- _# V聲音部分(Audoi Process Unit = APU):: Y$ F9 F4 {) d; ^/ v
.\NES\APU.cpp' e! E: e5 Y# f: e, Z3 l
.\NES\APU.h' j. U( Y7 |8 a9 g3 e
' u+ D" {, F% k% y9 j
" H+ [6 t) \1 }* e
影像處理部份(Picture Processing Unit = PPU):6 Z- s4 Z7 {1 A2 P+ W( H! Y4 L. j: K
.\NES\PPU.cpp
0 _( S: g3 h( X8 e% B- I! }( \9 l.\NES\PPU.h. G# }3 f7 x6 L

* ^* o& Z/ O" L8 r如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:; c5 u1 G1 Y: H0 J/ C' O6 |. A
(由于很多专用术语和算法机理都不明白,所以看不大懂……)5 \8 w9 s8 o" |1 Y4 Z
//////////////////////////////////////////////////////////////////////////4 J. m+ e1 y/ z1 a3 Q
//                                                                      //
4 g4 d8 B' B% k( k. a# Q% \//      NES APU core                                                    //
) k7 p6 J# L. W2 }- }//                                                           Norix      //+ Y' y/ G) s! i* |5 b  |8 s
//                                               written     2002/06/27 //0 K1 ]( g% ~# Z
//                                               last modify ----/--/-- //
. J. G, l9 z/ K4 M. O, N) R//////////////////////////////////////////////////////////////////////////1 Y- J$ \" Y; f; t  g; c
#include "DebugOut.h"
; i) k) M: g' r2 v#include "App.h"( k; o) a" e. j/ N1 x  U
#include "Config.h"
2 {, {" w2 S5 W3 U7 H1 |2 X9 d7 J5 [
#include "nes.h"
5 v# t' H6 A. W) P3 P3 g6 p* D#include "mmu.h"
4 J# Z0 W/ I4 x0 N% y#include "cpu.h"
: F5 R* M$ A( ^! z: f#include "ppu.h". m  [0 I$ `3 t% e( {/ d
#include "rom.h"
  d# w, o, v" n& K  J& D5 u& u#include "apu.h"9 l2 s- ^: i# X" B' M! Z* D/ I% |

! y0 ]! \5 ?' F7 r  n' H// Volume adjust
# W/ `; ~4 p- R( w  e: H: J0 ]// Internal sounds' y1 Q4 G2 C9 e" |8 G# w9 A
#define        RECTANGLE_VOL        (0x0F0): G9 `$ \/ G3 Y! ?; R
#define        TRIANGLE_VOL        (0x130)
1 F/ z* t8 U5 J& ^' ~#define        NOISE_VOL        (0x0C0)
. x3 S; J/ ?& w1 H#define        DPCM_VOL        (0x0F0)
& f8 D8 u4 N# A6 Z7 \// Extra sounds
8 J( \/ C, p  R" ]! l% |! f#define        VRC6_VOL        (0x0F0)
. M7 @  f& ]$ K6 [: o#define        VRC7_VOL        (0x130)& \* _/ [$ _9 h' P- t( u9 {
#define        FDS_VOL                (0x0F0)
4 F5 G$ q2 H" O) N#define        MMC5_VOL        (0x0F0)
# p* F& }% N" i4 H" u) G#define        N106_VOL        (0x088)5 e) L6 |0 [. L+ b: T1 j3 f
#define        FME7_VOL        (0x130)
7 ]- J* G1 d  u# \  `$ w5 e, G+ @' ^* R
APU::APU( NES* parent )
' o) [2 @$ P  _{  O/ A4 b" }- c2 ^- `, r
        exsound_select = 0;" k6 }6 z1 Q) d3 t4 Q

9 J# h: r6 Q- Q6 O        nes = parent;
" a! y3 A4 j; i' q" Q        internal.SetParent( parent );, g5 s$ m' F- H! b

: _# g, s$ n: f9 x4 r: o3 G! i        last_data = last_diff = 0;
% H' B2 u  q& M7 V5 t% m
. h) s4 G7 m4 B) P# {* s" A: [+ P        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
. K( l3 J; {9 n2 V% [' C
; ~6 Q0 F$ P9 W0 P; ~        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );) V' [6 f1 d3 r; i0 k% |* M4 d/ w( b
        ZEROMEMORY( &queue, sizeof(queue) );& `& G# [& Z* ]2 F: @0 ]9 s
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
& Y0 o* P. N1 Z1 Z* T
) Z4 A' E) G+ z9 @, m$ l        for( INT i = 0; i < 16; i++ ) {
( a% ]9 ^  ]# ]8 {; i7 m* x                m_bMute = TRUE;- }3 N. @0 b8 q/ t% V6 b/ W) S
        }+ D+ A# z3 K4 {  B# k
}
; S- S, ~+ A4 f$ C
9 y! z( A" g# J. [0 T# S% Z( uAPU::~APU()3 X3 B8 t6 Z( d' a1 [% v+ W  i
{$ `6 @& y& q# w( L, y, n; l0 p6 ~) k
}
3 s' L& U+ q. t8 I! Q3 h5 G& R; S( ]5 R  `: U& H: {
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )2 }! x- _6 w0 Y3 l# Z. E
{( n- k- `3 x, `" j+ z) c, n& t
        queue.data[queue.wrptr].time = writetime;  K, N& T8 A$ w3 q  L
        queue.data[queue.wrptr].addr = addr;" G! t% z1 U  q/ Y1 w/ ?
        queue.data[queue.wrptr].data = data;2 L* g( B2 M6 o, B& y" i
        queue.wrptr++;! V0 o# J6 s$ K! @5 h
        queue.wrptr&=QUEUE_LENGTH-1;- F& \0 j" b; W* z1 ^$ D+ I/ t7 n9 Y
        if( queue.wrptr == queue.rdptr ) {
) T, G- h3 p8 \                DEBUGOUT( "queue overflow.\n" );' o4 }+ h! K, V7 L" Y, b
        }
6 G$ h# j6 s" @+ i5 z}
9 _4 @0 ]! D' @) k4 L; i$ Z  h1 Z- J" D$ |7 v4 f$ y8 T7 \/ s
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
  k7 Z2 J6 X/ L3 o{& V  }3 v6 `% R
        if( queue.wrptr == queue.rdptr ) {9 p  o# s- y- h& q7 @
                return        FALSE;" S3 L" }/ L- F1 p1 w% f
        }3 m- I# V( J$ K" S+ B
        if( queue.data[queue.rdptr].time <= writetime ) {2 G+ n9 g( l# I( s8 W7 y$ g
                ret = queue.data[queue.rdptr];
) x4 L. b) J  P  _* d  R! a6 W                queue.rdptr++;
! e5 p8 e: v0 {) I                queue.rdptr&=QUEUE_LENGTH-1;# I4 H/ x0 i4 r: U, L# @, Y6 ]# r
                return        TRUE;
3 z: |0 d  ^' F; r, ~( H        }
8 P2 y% O/ \2 m, n( }1 w" B) X        return        FALSE;6 b! p, k9 Z% n
}8 V. o2 i( X! ?7 c: R+ }- O
+ D7 l4 N3 @7 Z  L: Z8 |7 H
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data ); g, P8 P2 u2 E5 v( e- k
{
$ \$ ^1 }) p, R        exqueue.data[exqueue.wrptr].time = writetime;7 _+ R* \+ a; g6 |" K! U" {3 h+ O
        exqueue.data[exqueue.wrptr].addr = addr;1 Z5 s* `- l1 Y2 m0 a+ \
        exqueue.data[exqueue.wrptr].data = data;
5 [" A. p, e* n" j5 I6 R" _7 n8 n5 c# d% A        exqueue.wrptr++;8 B! y, j) f/ P9 [/ M/ N' T. K
        exqueue.wrptr&=QUEUE_LENGTH-1;5 f% R6 ^# u; _. x
        if( exqueue.wrptr == exqueue.rdptr ) {1 I: Y# y9 W; D4 C: p% y$ |
                DEBUGOUT( "exqueue overflow.\n" );5 u% Z; h4 l, M% ^. r
        }: q' p/ |" M+ h! j1 [5 M% K
}# O" o% w8 ?1 ]& ^# B
5 l2 Z5 s, G3 p( x3 [
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
) L) N2 y- ^" x{
/ G/ y3 s3 ], a4 v2 w! ?! X        if( exqueue.wrptr == exqueue.rdptr ) {
# X; {2 i# _; t; ]& C3 u                return        FALSE;8 _. {$ S, b; b
        }
7 f% m. N. `0 Q- l        if( exqueue.data[exqueue.rdptr].time <= writetime ) {+ Q* d- {* U% p; g( W! Z
                ret = exqueue.data[exqueue.rdptr];
2 K) Y4 d( ^2 |' }+ Y, ]6 L                exqueue.rdptr++;4 m) P* g( [  z
                exqueue.rdptr&=QUEUE_LENGTH-1;
7 T# P9 @$ D  n& Q7 v                return        TRUE;8 k" q- q# U4 a3 @5 t$ U/ {4 B4 Q
        }9 c( K9 D; r, L9 j; h
        return        FALSE;7 M( |8 d4 H' E# S0 F5 S! h3 p
}9 p$ q- q; R" ]/ L) O
4 l. U* Z  b7 [4 N  C# z
void        APU::QueueClear()
2 U1 L8 t/ }0 v7 k1 H{
+ K9 v% Z9 [* a, Z3 I        ZEROMEMORY( &queue, sizeof(queue) );- n: N+ z$ Q% z- |  o7 H6 m1 x
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
" b# N' Z$ U! n2 L}( k( V0 W+ d* v6 O1 Y! M
7 d! W1 c5 K9 [1 t
void        APU::QueueFlush()
& F/ O/ R9 k8 f/ _3 ]" B6 |{7 f1 m; t. D9 P
        while( queue.wrptr != queue.rdptr ) {$ L9 g* T/ V, u+ F3 q
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );6 w; R1 v  `1 J' b8 h8 {
                queue.rdptr++;
$ l! I! J9 E2 P0 p4 K5 |6 F; f8 I                queue.rdptr&=QUEUE_LENGTH-1;+ \( V4 `# H, L, u6 B. ?
        }
* a7 f7 G+ a" [* ?- a( V( A' K+ o7 {$ a9 B/ Y
        while( exqueue.wrptr != exqueue.rdptr ) {! i: j: H( u) `0 {
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
& f6 M* Z& T& a8 D. u5 K2 [                exqueue.rdptr++;( C2 O' |( y$ U
                exqueue.rdptr&=QUEUE_LENGTH-1;+ L# z$ ?: ?3 Z- I: A2 m" a
        }& Q+ \) {  h4 \
}
2 m! W' `  I# }. b+ z: h
. K- b1 \2 B5 ]0 E; s; \  ^+ Vvoid        APU::SoundSetup()5 s7 L9 `# o5 \8 F  s# \& |
{2 Y' N6 d% o: g! {
        FLOAT        fClock = nes->nescfg->CpuClock;* v) h! d" H# D: c9 x9 X! }
        INT        nRate = (INT)Config.sound.nRate;
3 H* v# _' V9 i9 D& h        internal.Setup( fClock, nRate );- ^3 z3 ?6 o# R) ^+ g. ~$ Z
        vrc6.Setup( fClock, nRate );' o  }. n" ?3 e
        vrc7.Setup( fClock, nRate );9 Q' j5 M2 M$ M1 w$ C; o, ?
        mmc5.Setup( fClock, nRate );
$ Z/ w% v  j# K9 I* ?! r        fds.Setup ( fClock, nRate );
" ?/ o# ?/ X( O- {9 R4 k        n106.Setup( fClock, nRate );! E: q% {% {, D  R3 E* y
        fme7.Setup( fClock, nRate );
/ L: \1 m% ^  Q$ i* G1 E* s}  t4 d' Y# m, Y
" W7 y, ~2 `6 U3 S6 s
void        APU::Reset()% Y- ~- I5 V- h3 k9 T
{" {  n) n/ C( ]
        ZEROMEMORY( &queue, sizeof(queue) );0 I  f* X; B7 P- V( d/ U5 S
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
, X) D# @/ w' V8 g
5 X3 J  i1 |! A9 N- G        elapsed_time = 0;
9 Z0 V: d. ^, l5 J$ ~! ?3 t+ r
9 f# h: E6 i4 g4 m) S0 ]$ w  X9 ^        FLOAT        fClock = nes->nescfg->CpuClock;
# a. p+ Z% ]. T# R. s        INT        nRate = (INT)Config.sound.nRate;
" c  q3 F% I- X& v9 x: c. [        internal.Reset( fClock, nRate );7 Q+ I' U* a: [* P8 d) h+ N- Y+ N
        vrc6.Reset( fClock, nRate );% ~+ L  s- F, i; w- k9 p
        vrc7.Reset( fClock, nRate );
( M7 f2 O0 M' B1 s0 r1 \        mmc5.Reset( fClock, nRate );1 ^: a$ r; m* \3 Y; S+ f
        fds.Reset ( fClock, nRate );
& M+ U2 E) F0 T* U! B1 z9 o        n106.Reset( fClock, nRate );3 a* v7 W& S6 I# _1 K
        fme7.Reset( fClock, nRate );) G- x9 J3 L9 O

  G+ m, ^( {$ k) E        SoundSetup();
1 I! K1 n: l& V( x: x/ A8 n}
- z9 X: {4 a- k. t3 D+ L4 Q. C' d6 z' y3 b# J4 e' ?
void        APU::SelectExSound( BYTE data )! K8 D- b, t1 T7 |7 p; Q8 M
{1 u* D6 O/ r* z+ c! l! o1 d
        exsound_select = data;
8 d9 \. E7 t/ K! t}6 [3 m) b. C8 s1 r! o0 e" h

& L+ n7 u" Y3 Z# x& OBYTE        APU::Read( WORD addr )1 T& U4 s6 l( q( N
{% g, c& V1 K6 A7 p& \7 }
        return        internal.SyncRead( addr );
/ s7 Y7 Y" D- ]: U) J% x% s$ l5 C}
) t, {: K; m4 ^) M) f  {+ D
( @! p) X+ q3 fvoid        APU::Write( WORD addr, BYTE data )" j8 g3 g' j9 p& v6 y
{( E9 Q) ?- y% t0 H, ^5 b& o0 L
        // $4018偼VirtuaNES屌桳億乕僩, `7 Z1 U2 w$ F) a: c7 \8 d+ c
        if( addr >= 0x4000 && addr <= 0x401F ) {5 {& B( D% u* ^" Y7 u  K/ y( I
                internal.SyncWrite( addr, data );* g8 n: k4 i5 ^/ R
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
3 P& W/ Z: A( v        }9 H) V2 r" z# |- T7 d% q
}/ p6 X7 p# r2 U& q3 F" @9 P
4 v( [( ]. _: c+ g. ]
BYTE        APU::ExRead( WORD addr )/ ^# [! U* _3 q
{2 a. p" q# {2 L3 G+ _' A% e
BYTE        data = 0;6 P9 @" d: L& f3 }- C) `( g/ Z1 W

* j- _, T0 p! u1 I. G) v5 c+ N        if( exsound_select & 0x10 ) {
& n& Y+ a5 X1 O, x( a                if( addr == 0x4800 ) {& ^$ M& O3 F& ~' {% k/ ^
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );( Q% z$ z( r4 O& L3 K
                }
$ \: Y3 T/ ~3 Y        }$ a, x: k; w' T/ x) w
        if( exsound_select & 0x04 ) {
$ Y; u3 I. Q1 C5 C% d                if( addr >= 0x4040 && addr < 0x4100 ) {! [5 s6 z7 D* u! O. d- _
                        data = fds.SyncRead( addr );
8 ?9 c/ Y# M% q& J9 M! j6 e1 F, h                }) a7 A! P5 i; J+ i! m6 E) W
        }
0 V& @& g& `/ q  S& G6 w$ {        if( exsound_select & 0x08 ) {
$ H. W, o" H2 C! ~$ R5 j6 j                if( addr >= 0x5000 && addr <= 0x5015 ) {% X# O/ d+ F( t) e0 d+ ?9 y
                        data = mmc5.SyncRead( addr );; k6 j; ?. M8 a7 K
                }
; e. a+ h( R) c  t. J        }
, x& B/ Q) `* W% \5 M9 f. M( l, x4 k; Q/ b
        return        data;
' G; X; o+ n% [- p4 V}
* l: d, X$ C# L7 R6 i1 c; _6 w4 @' w& O* q
void        APU::ExWrite( WORD addr, BYTE data )
8 K' U! B  u1 {1 I6 I{& S8 O9 D8 ?, _+ r& ^6 r& n$ P
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );$ U1 e. O) O, R5 ^

- H/ l( Q, |1 q! e        if( exsound_select & 0x04 ) {6 l* d* y! V7 i9 [
                if( addr >= 0x4040 && addr < 0x4100 ) {
4 ]$ j/ s$ F# g) T  d( j                        fds.SyncWrite( addr, data );
3 O6 K) ^5 y9 L                }/ K) K+ k- n. Y! i4 x& Y/ u* E2 U. z
        }& F+ a- d6 V6 M* a; |9 L* y
/ G' @% {9 A' h; g$ ^+ S) O
        if( exsound_select & 0x08 ) {
, x1 V' |; Y! J5 X* R' W4 X# f% y                if( addr >= 0x5000 && addr <= 0x5015 ) {
. y8 E5 W2 y4 j; D                        mmc5.SyncWrite( addr, data );- K- }) z5 }5 y8 ]
                }
0 Y3 l" C" z% u$ a* ^# w        }, O) _* B3 X. K7 x, u( M0 ^
}
/ @) i, u# o' p1 L' A+ T
/ E( y$ y% T. R2 T& a: [) Lvoid        APU::Sync()2 R: d; l% q/ ^
{
5 `# k) i: Z# \8 J& V0 E) C}4 F/ o' d2 ?0 O5 x' ?% r
+ l1 G1 ~7 l1 \' A
void        APU::SyncDPCM( INT cycles )6 G* X  [8 R* z3 T
{
5 a& N" i8 Z5 l( [5 J- F        internal.Sync( cycles );7 p/ L7 E: t1 Q. x
8 e+ Q; S$ s& E; D1 l; i
        if( exsound_select & 0x04 ) {  [# H4 r( G- ?0 E
                fds.Sync( cycles );
3 `( I% `3 A- f3 q/ p7 J        }
7 v' Z( u8 k* V% I  z        if( exsound_select & 0x08 ) {( w0 E. |; N6 W: e: N  @% ]
                mmc5.Sync( cycles );6 d9 r- j, S* a+ c6 n( B, q- A9 L
        }
, R9 |( I( s1 y6 w/ J% a}
( q% K+ u( m3 I5 L
% H. |/ Z1 H$ J3 }5 }/ S/ Bvoid        APU::WriteProcess( WORD addr, BYTE data )
$ J7 |% I% n% O$ V$ G+ s1 Q1 \{9 n- v7 u: z- a& J
        // $4018偼VirtuaNES屌桳億乕僩  i7 f" Q7 M) T/ U1 ]6 q$ G
        if( addr >= 0x4000 && addr <= 0x401F ) {
9 a) P% Q, M$ ]                internal.Write( addr, data );9 q( \4 X4 E6 s" U# u' W5 s
        }
3 H* T- \* N* O0 M8 [6 s}  O0 q( F9 }3 M  Q8 T; D) p
" a( k& N4 t9 R, L
void        APU::WriteExProcess( WORD addr, BYTE data )
0 F$ T% \$ b: K/ q9 z{% l, ]4 D- D% M9 z* H) o
        if( exsound_select & 0x01 ) {* a' [& ?; J$ R
                vrc6.Write( addr, data );9 c4 Q. Z& b+ d8 \0 X* r) {+ I
        }
* A; z) i7 B- ]( ?        if( exsound_select & 0x02 ) {
5 q. Z6 `! w$ f$ [                vrc7.Write( addr, data );
/ c) K: e& {0 s3 b: |% ~: p        }
5 H( n5 |0 O7 G1 P1 `        if( exsound_select & 0x04 ) {
" Y0 l; H! [$ q3 U, A8 A7 K4 c9 \                fds.Write( addr, data );: L0 E8 B; _7 {; C
        }* E6 k- K9 ^/ s$ A6 \' U' I' P* a  [
        if( exsound_select & 0x08 ) {
9 h6 i/ R" g; ^& r% X& V  m- y1 J$ x8 x                mmc5.Write( addr, data );
- v" G9 F0 R& y; |9 U- r7 n        }
4 z  A7 X4 M* l        if( exsound_select & 0x10 ) {8 E" O  ?- S+ G0 E6 v% v4 S
                if( addr == 0x0000 ) {
% w" g. ]. |" x3 h                        BYTE        dummy = n106.Read( addr );% i' L4 Q+ H! h/ o: Q- c
                } else {
7 {2 V3 B  Z: q3 V                        n106.Write( addr, data );, X4 n7 H/ ^  k" i9 ]. p' |2 E
                }* d+ ?7 C6 d% Q* i( G# n
        }6 Z: t- [1 s. b8 J) g) H5 E( p
        if( exsound_select & 0x20 ) {4 T% {5 |' l5 j8 W$ T
                fme7.Write( addr, data );
4 |) y: L! Q# m8 W1 A3 ~        }
2 _: h: D- m* [2 C2 O3 b}6 n6 y' Z/ ^7 E5 v6 X

( D' b2 a/ x7 S  n% @+ g$ Uvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
& B( k: Z/ C* v5 o) |5 F# j. ^/ u{
% Q$ k# r+ }" U& h" v! T2 v: S# NINT        nBits = Config.sound.nBits;
7 b2 g" ]* H, X- g/ g  A9 @DWORD        dwLength = dwSize / (nBits/8);
. g, c/ C" ~5 ~, c+ X: q$ AINT        output;
% X- x1 l" W; B- d, B9 h: oQUEUEDATA q;
# E) J+ D' X3 S' H5 T) J' C( s7 yDWORD        writetime;
7 }: X; T$ x5 v
5 i% V5 b6 }  f7 a5 U. f; ^) A- zLPSHORT        pSoundBuf = m_SoundBuffer;
6 k5 c! c' u# i) M+ o! NINT        nCcount = 0;
. i7 N+ Y/ P! ]9 T
) y2 i% F$ D: t4 uINT        nFilterType = Config.sound.nFilterType;. D6 j  N4 ~8 p7 a6 @/ u
5 E6 y) ^  k3 Z! F' K: W
        if( !Config.sound.bEnable ) {
& |9 e- A* v) q$ U- ~                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
( O$ i! t) q) A$ K- z, k5 j) Q1 l                return;; S7 Y& `3 T/ e
        }# _, P" U6 h$ Q

! \* W- P7 J  S" P+ N- A4 @* i! o. Z        // Volume setup
/ U7 d) v5 I, }0 R+ i        //  0:Master# Y& z4 w1 ^& T
        //  1:Rectangle 1
) x  h1 R2 j' C) U) S* m        //  2:Rectangle 22 Y9 r% F1 M& f6 H9 {1 F
        //  3:Triangle
4 E# D3 T1 O2 c0 d+ c# X        //  4:Noise
, Y  r# `/ \* i- ?4 I( M        //  5:DPCM6 f& k4 C2 H: H& e& E, Z# I
        //  6:VRC6
$ f% Q! n( A0 ~0 O& ?9 G7 f        //  7:VRC7
5 h9 e' u+ F7 c9 Q        //  8:FDS
, Q( }5 y! t- f        //  9:MMC5% l4 O8 k) u  P: A6 W+ C% N7 Q* f# A
        // 10:N106; Y3 L# f9 s; ]" C4 t
        // 11:FME7
4 b+ W- I8 v6 v6 d8 b3 n        INT        vol[24];, U' R9 z5 A: Y" Q: Y% X
        BOOL*        bMute = m_bMute;
! v% E8 h: \, f& h. A; t5 S' H        SHORT*        nVolume = Config.sound.nVolume;. s# L2 r8 d0 D0 M9 o$ t- [
8 T  O  r8 M# A9 @2 u9 v, @; [
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
" h8 F' ]+ P4 R- A
! {# ^- b' c8 d$ v. T- b, _        // Internal
0 l" W: {& i- _9 S$ f7 G" f        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;) F' q: Y  y4 W( P
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
# X9 G% a2 F0 {        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;& w* {$ w# o  E/ O& \( n3 q: L
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
0 A4 {* J: D- B$ d! q8 z- Q& f        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
$ K- h1 d; ?- d2 p8 G; W
0 Q) J2 }/ o( w' ]6 I  _! g        // VRC6
- G- V' ?: Q2 }( O4 q& H        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
! p7 u" Y$ g( z        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
% L# u2 D8 ~$ P1 {* N" D        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
$ o. I) Q( V6 U* H7 D& p9 P8 o
  n2 S* D- X. s        // VRC7
/ \2 V: ]) U5 r8 k        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
& U1 i# u$ [8 N0 {: g- k) Y4 N* ?5 C" p3 l' x
        // FDS* O3 B9 v1 ?; ~/ P& s1 q. }
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
2 r# c& M) k; Y: \9 b4 C
' U/ B9 o4 }3 A4 l  ]        // MMC5
" u* p5 {: B; o2 J* U  `5 o        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
) T! z$ z/ Z, }' ^$ z4 l% W' G        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;$ H+ m0 M& u5 x7 A7 ]
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;7 @  X. |, {$ |4 x% @

) ^7 z+ b. R6 F8 W7 s4 J! l        // N106
3 a: D) r5 k% M& C+ q* E5 [8 o( E        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;. A( y, X# Q1 i" s6 A; `) r% ?
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 V; a1 I! a( e+ K        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;- V9 A/ N. ?7 x
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
8 V9 w2 o1 @! s        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
! i+ s0 F3 \. B$ ]1 `        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
$ {& i- q+ ^. P5 b  `        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
2 b. z8 g& ^5 U0 k- w6 u        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
* ^3 ~$ W: x6 A# G# q* m8 J% ~, h. e9 e1 ^, q, }( s! X5 x
        // FME7
/ F/ g' D+ a6 P+ Y! q( X7 w7 g        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
' L1 g& A1 p' n        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
  b' Q9 G4 C' x: V" q) P6 B8 V        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
! [3 U8 r7 O# ^5 I* Q, B
9 v( B; H) t8 m7 L//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
% b  F, C1 i# S2 _3 [        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
: O3 g% m( A  g* A" N5 Q/ b2 G0 o3 y4 H2 I; @, Q3 T0 D# I  O
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
7 S3 C. [; x" ]$ P        if( elapsed_time > nes->cpu->GetTotalCycles() ) {% V5 J- m, U& O. v
                QueueFlush();- T. G" Q, K) d4 Q# N; e
        }
# O, I3 f" M5 u1 o' r' m
* l- P( [& e" H8 M, e2 B        while( dwLength-- ) {
2 \+ {" Y9 u% H) [5 H8 ?5 ]. x                writetime = (DWORD)elapsed_time;
$ p2 V5 O5 X) `" \8 @# G8 q- Z+ {2 h" n5 x) c" n
                while( GetQueue( writetime, q ) ) {; j8 c7 m1 i6 B- O  I: T( V
                        WriteProcess( q.addr, q.data );* h' ~) Y- n. i+ d+ i: I
                }
; G* j0 K. c9 l" v/ \+ D3 B, ?. {$ N5 ^& t4 t4 u' n8 ?4 L
                while( GetExQueue( writetime, q ) ) {
+ x1 \# {* V, z( O  r                        WriteExProcess( q.addr, q.data );
3 }, \: ~" \9 C, R1 }2 _1 @, j$ E                }4 X8 ]( q5 Q$ S
4 ?: \! [' D2 j( z+ o# G  P
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
  n2 q/ n' u& V                output = 0;6 Z- c) u3 C7 ^2 J# X1 |& j7 n9 R' R* x
                output += internal.Process( 0 )*vol[0];- l! k4 Q' n9 t8 F- ]/ v5 W5 x
                output += internal.Process( 1 )*vol[1];
$ \* z3 @0 d% [, {% e                output += internal.Process( 2 )*vol[2];  F* }+ k: r3 T* W) u  g: ^1 b" Z. v, _
                output += internal.Process( 3 )*vol[3];* l% h. @/ Q, O" V3 U
                output += internal.Process( 4 )*vol[4];
# Y: f/ Z( q4 l' w# j; s
- b5 z3 w; o5 b* b0 c" U                if( exsound_select & 0x01 ) {
6 C2 k; Z: v: v6 H; m4 b7 Z! s                        output += vrc6.Process( 0 )*vol[5];
2 u* H5 D" {' ?                        output += vrc6.Process( 1 )*vol[6];
6 J+ R4 R. E! W( N6 V8 w" j                        output += vrc6.Process( 2 )*vol[7];+ g4 i+ T: r& a# {* r9 }+ M
                }
% I  |1 U9 z/ n4 p2 d- _% s                if( exsound_select & 0x02 ) {
- N* L! U$ m# \2 S0 \                        output += vrc7.Process( 0 )*vol[8];. J3 A* ^2 p8 l1 M1 h' w0 Y# |- _( ]  [
                }
0 x  a; [" Y8 [, F  y! d- h2 W& ~                if( exsound_select & 0x04 ) {
+ g" K% E- y8 u                        output += fds.Process( 0 )*vol[9];
1 Q' [: }) Q4 Q; i$ G                }
1 U$ N% i3 {' o8 e                if( exsound_select & 0x08 ) {& W# N9 B, U# v( _/ O# N
                        output += mmc5.Process( 0 )*vol[10];# S+ t5 _) ?+ J  J( R+ r
                        output += mmc5.Process( 1 )*vol[11];
* Y3 k- s5 Y3 k                        output += mmc5.Process( 2 )*vol[12];
4 g7 w+ r6 W# i9 B. u                }
* ]' y% \: r5 a" Z                if( exsound_select & 0x10 ) {% H3 R5 `) z% b& J& e
                        output += n106.Process( 0 )*vol[13];
' W4 F& p0 X, s7 u6 R0 Z                        output += n106.Process( 1 )*vol[14];) j7 ^/ ^8 S1 p: q7 @
                        output += n106.Process( 2 )*vol[15];& p  B4 S. {7 {% Z. K
                        output += n106.Process( 3 )*vol[16];
2 |2 e( y1 E" k; t9 z) [, K                        output += n106.Process( 4 )*vol[17];
* B9 A4 s: A4 d2 M$ ~                        output += n106.Process( 5 )*vol[18];1 X. E. [! {' Y$ K5 y9 I* J0 O
                        output += n106.Process( 6 )*vol[19];. Q+ N$ I; |5 Q5 P  I
                        output += n106.Process( 7 )*vol[20];
1 q( ~  L7 F8 M& `                }
/ V! }" }4 C) K7 \- {                if( exsound_select & 0x20 ) {
) u% \+ s( [1 a" ^0 N3 ?  A$ m                        fme7.Process( 3 );        // Envelope & Noise
( }  d* I2 h: S( q- m# J4 m# H                        output += fme7.Process( 0 )*vol[21];
" h$ T! _" a' T, Q                        output += fme7.Process( 1 )*vol[22];
6 \* T1 I+ Y$ Y4 Y. F) w( A                        output += fme7.Process( 2 )*vol[23];( G7 s! Q# W9 j  Y3 @$ k
                }
' F  K4 Y! N0 ]+ P: `
: L9 o) @; L; S/ s5 E                output >>= 8;
2 i1 t; [  {% ^. N" g* }$ o' f0 G$ z& W9 F9 {" h$ T5 k# U* n6 n
                if( nFilterType == 1 ) {
% x8 b* t7 X! `5 E* e8 j6 m, z                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
. g7 B# g, C4 K# I$ z; j. o, o2 i                        output = (lowpass_filter[0]+output)/2;
7 z0 w! x$ j5 Z  U8 D+ A! ]3 Y                        lowpass_filter[0] = output;
3 r( Z7 i! r- M1 F; `( `- y                } else if( nFilterType == 2 ) {* A/ D# O5 ]6 \; e
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
. v  y- |; X: W/ E  i                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
8 t4 c1 O- R0 x                        lowpass_filter[1] = lowpass_filter[0];
6 T! M  J: N* U) L; t                        lowpass_filter[0] = output;% i& W6 s9 G* k! c- Y9 Y
                } else if( nFilterType == 3 ) {; M# W7 z- n; L" z
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
, [# i  }( }0 u1 L% C                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
6 H( u# f( |" k. S                        lowpass_filter[2] = lowpass_filter[1];+ |/ n! T5 u, Q1 D; ?
                        lowpass_filter[1] = lowpass_filter[0];/ T" ?6 [' h! A( v9 _
                        lowpass_filter[0] = output;
6 C3 {+ D- k& {' U. x  ]                } else if( nFilterType == 4 ) {5 G7 a7 e  J/ M% W
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
6 f3 A* k, j( ]' B: a                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;+ y( F) t7 T5 b: M( {  L0 H
                        lowpass_filter[1] = lowpass_filter[0];2 V" c9 N  {6 I" [- _
                        lowpass_filter[0] = output;1 W6 u7 A2 G) ^: v$ z
                }0 D9 g: J/ ~3 W" O0 t$ p
  l% r$ j% Q0 N
#if        0, R% i: I0 K& ]0 x" c/ u$ i
                // DC惉暘偺僇僢僩' s) T* K7 s( ]/ N( @4 ~. V- d
                {9 C. Y* t7 b. L6 D
                static double ave = 0.0, max=0.0, min=0.0;4 z' {/ s+ C4 W& E3 {8 {
                double delta;
2 x4 K5 ]% {0 D2 L1 j- P1 ^: x! ]) @                delta = (max-min)/32768.0;
3 r! z& |/ i8 b% h6 }/ l" L, b. ]                max -= delta;
: l$ |* w, S8 A% V" w; P1 B* k                min += delta;
0 G0 B- }9 [& p# d: X7 `                if( output > max ) max = output;
1 F* Q( T5 ~! n0 M, \9 y# a                if( output < min ) min = output;
/ {: u* r6 O3 V6 [. ^                ave -= ave/1024.0;7 ?. h9 d# h& \% X% W& `: h
                ave += (max+min)/2048.0;
) I, g6 F8 j; T                output -= (INT)ave;
- ]) f. L# c# D$ h                }
# z2 j. D( }, A/ a#endif" h8 u9 w* J7 z2 c! H
#if        1
2 k6 M6 P/ |" E! \$ C5 \6 T                // DC惉暘偺僇僢僩(HPF TEST)
3 S, w( d/ X1 x3 g5 z5 d                {
# |' x! f( c& I8 g. Q# V$ T//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);* t! q! i5 G4 d
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
# U% T4 @4 Z) Q                double        cutoff = cutofftemp/(double)Config.sound.nRate;3 w- z% K. [1 w) ~! p* l+ Y
                static        double        tmp = 0.0;
# @/ a' v& G4 u- G; n                double        in, out;- D) r" u1 n  ^9 a3 f9 _
! B2 P/ ~. n' j9 m% g6 ~
                in = (double)output;
0 V8 [- Q  T1 }                out = (in - tmp);. Y, o1 V, o2 b9 o* C" G4 R
                tmp = tmp + cutoff * out;
" M/ E  F* A! V) C  C) Q; G: ?9 ^
* j9 k1 ~" X; e7 W$ {9 P8 a3 j                output = (INT)out;! J: m- H5 u/ X
                }
* w& g$ I. H& H5 R: z! E/ t#endif
* e8 S. t8 D2 Z#if        0
+ R* W+ f* f- g+ B6 j. D                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
: s/ \9 B3 Y1 O                {
. c; J" b8 [2 P' e                INT        diff = abs(output-last_data);
7 l/ D; L; K, x! k1 O1 x                if( diff > 0x4000 ) {
/ X8 @" S0 W3 m* l( @                        output /= 4;
3 L* Y8 m' }( t# o0 V                } else 4 y+ N0 M4 u- \& {) D; R* P
                if( diff > 0x3000 ) {
# c. W2 U) y# }) {* H  v                        output /= 3;& c" x. O1 I; l+ [8 ~
                } else; {% y$ X4 q4 a
                if( diff > 0x2000 ) {# s" n8 o% [/ Q) Y" ]  S5 }- Z
                        output /= 2;& C: ~7 J% k; K+ i
                }$ z. W% C$ l0 `" F0 e& {, G/ |* Y4 S1 y
                last_data = output;3 ]& \8 h% S: ]
                }
, v2 _+ A' ~% ~+ y. h#endif
" g0 |4 P. e( Y0 P$ K                // Limit
' t* o( T. M3 x4 o) r                if( output > 0x7FFF ) {  \/ Z; A1 S2 U6 R# N) R
                        output = 0x7FFF;
& ~# k' R. _8 j) T                } else if( output < -0x8000 ) {
6 J% k9 m/ Y8 Z: u" p% W' {                        output = -0x8000;
7 S, K: v( T- r) V3 h                }
8 V7 Z, U: c0 Z
( Z# y; m" C* U1 l5 ^3 S+ U$ M9 `                if( nBits != 8 ) {+ e2 W/ y. c) j- [  \4 _1 H
                        *(SHORT*)lpBuffer = (SHORT)output;
) I+ X3 h+ ^- S                        lpBuffer += sizeof(SHORT);
1 R( p8 L4 Z) }                } else {
* d1 ]& i5 E0 n# V# G                        *lpBuffer++ = (output>>8)^0x80;# Y2 ~2 C! x' T' y8 }
                }4 ^  [5 t; {- z% o, w+ Z+ z: i
; r) I! v1 Z8 C1 Q
                if( nCcount < 0x0100 )
, X' D9 c' K: u* L9 E0 [                        pSoundBuf[nCcount++] = (SHORT)output;
. D% B1 [8 y. _+ \4 A4 Y& i& R# ^
9 h' k! c7 k% ?% a; @//                elapsedtime += cycle_rate;
' W; }6 v2 C9 _8 t: J                elapsed_time += cycle_rate;2 _' \5 b5 x! x7 I% X1 l. F
        }
/ V. d; B: G: X7 x  V
" F8 h" Q. u' W. M2 N#if        1
1 s; m5 m& k$ Y0 }0 O7 V# q2 ]% e8 c) M        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
( t/ P) f. q( g                elapsed_time = nes->cpu->GetTotalCycles();
! t8 I+ P, ~! m: F* d  n        }  {/ ]" e- a9 }) G( o
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {/ c  Z7 R2 r; O# S$ u$ h, f$ t
                elapsed_time = nes->cpu->GetTotalCycles();
/ `: o- V- r" y6 r        }
- z* M' o+ \* b9 v0 n6 t#else
) z. F0 Y+ R. K5 `* J# N# i        elapsed_time = nes->cpu->GetTotalCycles();; P; f2 p9 T. d4 \
#endif
2 B# k4 A5 Z3 i- Z3 O7 o6 S}% Y. L7 N$ l4 A9 |7 e/ A& F) ^

# ]  x  T9 W" X// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
3 m) o" |& l6 q* {$ Q: x0 E0 P6 ZINT        APU::GetChannelFrequency( INT no )) o# I3 n9 r4 B% `7 P
{/ i) ^8 X* j4 ]$ L- |% S7 c4 O
        if( !m_bMute[0] )- r) {( f% Z! s( k: c$ a8 W( z
                return        0;
" Q, u) I- @, M1 Z0 F- h
8 r- O' h  q+ h; Q2 w0 ?' o        // Internal. }+ J/ V9 `5 r
        if( no < 5 ) {
3 Y4 C/ U% d  r, Z                return        m_bMute[no+1]?internal.GetFreq( no ):0;
# \/ P0 k9 t4 u6 j        }
/ i* \+ x* x& C$ V8 z        // VRC65 u, T/ ^, j' l+ O: I
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
  A  r! e. m9 K+ C. p                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;: N" L' @) v. B, a6 X
        }! K8 v8 U' ?9 z, Z# }' ~+ c
        // FDS
; D9 F4 o0 |, A" `7 t. u9 O( ]        if( (exsound_select & 0x04) && no == 0x300 ) {
/ d3 K- T: K7 P# A1 S                return        m_bMute[6]?fds.GetFreq( 0 ):0;, t; o# ^( R& q6 ~, z
        }( d6 O( L5 O: P) J8 L( M
        // MMC58 B% Y: \% \& Q! U& [& `6 [, g
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
# e* n: T& ^8 I                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
8 S6 b: u; o5 w5 P+ t8 E        }
" P5 Y+ Q5 {2 m6 W( W" U4 M+ Y4 N4 C        // N106
) @. n$ k: t+ B* F' Q7 K6 f8 m        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
9 i* x& t) M5 ?: G                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;: Q% T' N% z- J6 c4 P. c
        }9 d5 N9 k1 K6 l% k
        // FME7
3 ~( P3 {% T# o- p/ G$ t3 t        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
" _" o1 ?: Z; x0 |                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;, _+ h) \* x' _, o  r( I
        }
+ I2 F  F& P5 j        // VRC7* w' M( |4 @) I* r5 Y4 U- E$ W
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
2 g3 h+ H! s' m                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
: q" z( C- U. E" |( t+ [$ W0 e        }7 r# i4 t8 ~, g& U" R
        return        0;$ |7 F! y& `2 k
}% ^1 o& H& ?& [& ]1 j5 F0 @

; N+ K' u7 S, c& C. d6 J. L// State Save/Load
. ]( R3 m& y! _4 C) Svoid        APU::SaveState( LPBYTE p )
4 o% E# u: z  G, c- L7 G6 U{) I8 ?% \$ r3 X' N0 c$ F) O
#ifdef        _DEBUG
' B6 U& ?. X7 h* ]6 r- jLPBYTE        pold = p;% H/ Y5 t9 X$ O& y/ `4 t
#endif3 i/ n6 d/ l4 r  n0 K
0 Q. g1 ?, `2 {$ I3 G5 s! h( R$ X( n
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞7 a" A5 T' o1 M
        QueueFlush();+ P, K" Y0 e" p/ J6 _6 [

5 F' O  d' E  \! R$ ]5 R5 v8 u7 n        internal.SaveState( p );! x4 o' D- O1 s
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
) i5 y+ o2 W: w+ F6 p! l! G
: Z6 u/ Q$ T% M8 [, d6 j) j( u        // VRC6: R: {- Z8 d5 {/ g) S
        if( exsound_select & 0x01 ) {
$ M* q3 X3 `8 ~) i; R/ s                vrc6.SaveState( p );
# m/ W7 f, |% P# w5 K                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding2 q* p8 P9 ]! E0 E7 b  g
        }
3 L1 O7 ?7 T; v% F$ M- o        // VRC7 (not support); v* D  B, b- S0 R4 Q6 q& c
        if( exsound_select & 0x02 ) {$ I9 I1 O: K: y7 P4 `) ~
                vrc7.SaveState( p );* ]5 ^5 \& ?( V# }! q/ r$ B& H
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding. Z6 N& o9 P) e/ E- J
        }
- n0 j+ W; s" I4 g. J7 z  i1 p# ~! u        // FDS) f1 P- X' T9 ~  s" _) u- z! m0 c
        if( exsound_select & 0x04 ) {  f" `# L2 K, z2 t  H/ p
                fds.SaveState( p );" ~$ D6 l! L7 Q% P# [
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
; B4 d! @: |1 Z1 G        }1 d3 @, |- T2 D2 K  m1 c
        // MMC5& d2 I, G8 i( U" U
        if( exsound_select & 0x08 ) {2 x, s7 ~, D' G. t" ]
                mmc5.SaveState( p );
' q4 Y' F) u# j7 s( s9 _& r0 S) p                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
( b/ j1 [# E- E$ n; R7 k        }/ a3 J8 X  C% n) r
        // N106( B3 Z  _! y/ ^& Q3 ?5 }6 o
        if( exsound_select & 0x10 ) {; t, ~/ x7 ^. G! W2 d
                n106.SaveState( p );' Z. B' \6 V5 O+ _3 _
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding5 W7 c4 y) L: B
        }+ U0 f1 m& A& X: f
        // FME7
7 Q4 o0 T# A+ Y" K' T. ?1 v/ ?        if( exsound_select & 0x20 ) {
6 C. ?' u% b# d5 l* s' b3 |                fme7.SaveState( p );
" c. @8 Q. u! U* a                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
& o" l8 _  Y7 L        }
- @8 [3 r9 f6 c9 Y' t* L
3 I- K0 [4 z/ ?! m8 ~' G* O  o#ifdef        _DEBUG9 l+ V  Y0 J: i
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
0 a$ x* i, y2 F  B. H( a! Y8 Q#endif$ z  x& L, V$ L/ {" w
}9 Z$ c( F2 C3 b" B

5 z4 k) U: F$ bvoid        APU::LoadState( LPBYTE p )" i- G) _4 D( y9 ~' }
{7 H4 T4 C! _+ F: b/ F  i
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
. B, Z8 G# a' [, I# V6 F        QueueClear();" ~9 Z' U; z1 z5 T, @
* q) P7 _+ S3 ?( w( y
        internal.LoadState( p );/ Y* f) ]: z$ M% L
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
, j, |* i# a) R4 T" Z0 ^5 o% e8 K: X' {
        // VRC6/ b+ o( x. i( V! [9 [* D
        if( exsound_select & 0x01 ) {8 J/ ^) }4 q7 p. f* z
                vrc6.LoadState( p );
, O, V" a% {! Q( B3 \2 `0 g  T                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
9 w' @2 c. Y4 X9 c        }
- U( ?  j# A' e8 b* P        // VRC7 (not support)# ?8 x$ C% Z: G$ v4 i2 r( g  x" t+ L
        if( exsound_select & 0x02 ) {
* N$ d, x0 y4 i) q/ H9 d                vrc7.LoadState( p );5 w) P) y$ ]& {! f1 _
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding, q4 W0 p) h6 O8 R0 ]/ |
        }
: D2 k! Z& I1 e; F4 a        // FDS  O( A, u! ^3 x, j3 l( i  B" Z
        if( exsound_select & 0x04 ) {1 }, Y( \0 Q2 T, v4 @
                fds.LoadState( p );! X# A: B& G, O; a% z
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding. L; j; V1 d/ m  [+ ?( s
        }, o% }4 }7 J# M' J, T9 |
        // MMC5
7 k5 C/ r3 H4 T. y" F- p$ z        if( exsound_select & 0x08 ) {" W) ~" I2 G2 ^& j! G( j
                mmc5.LoadState( p );$ g' j3 H9 F" W
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding' U* g, G" W) [3 G
        }
( y" ^0 P1 {& ~+ P( L; B6 p" H, w        // N106( n) |- N5 c) j: t: Y+ c# o, n
        if( exsound_select & 0x10 ) {
9 w; q/ y- {. T5 {) G                n106.LoadState( p );
7 u- O0 E) u6 {5 ^9 B$ a+ g                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
. v" d# L& B! ?" g5 H; s  t        }
* K& @8 E) F% x) X- U        // FME7
3 n1 s3 ^2 K8 B2 ~* r- ?+ v        if( exsound_select & 0x20 ) {  _" h4 i2 l& c2 }! a
                fme7.LoadState( p );, z1 _: x% ]+ O- _; f
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding) H- s0 s: B/ n/ s+ G! X7 \
        }& k. z: `% \# X) k7 d
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 / w& J( C: I  `. v) E5 U& H; A
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。# i; J* z0 S& ^" B8 P1 r" N
感激不尽~~
' q) A% i. Q! ?6 p' _# W, f
恩 我對模擬器不是很有研究,- t4 p9 {; ~: O8 s
雖然要了解源碼內容,可能不是很困難,
/ m. |6 }( \8 b% }不過還是要花時間,個人目前蠻忙碌的。
1 O$ g9 y" i5 V$ G6 _
6 \1 K$ c2 J. y1 f& V給你一個朋友的MSN,你可以跟他討論看看,
: A0 h$ A3 m) a7 I# A! |他本身是程式設計師,也對FC模擬器很有興趣。- S1 g$ Q. B: ~3 W& _

6 ^: o" s' |, ^7 U6 i, X1 BMSN我就PM到你的信箱了。
$ p; o7 a) |3 M; z5 @+ F5 e7 h4 Y/ A$ L: ?; u8 u: e, Z) [
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
' [  T& A9 p( L5 F! q4 f+ T呵…… 谢过团长大人~~
0 s+ @& ?' g7 s
) c  O: Y, F  p& g
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 + f  s( ~: K( J" ]
团长的朋友都是神,那团长就是神的boss。
* W: y* X8 h6 Q  B1 m) N
哈 不敢當,我只是個平凡人,
) k3 G, f4 \  ?3 ?$ Z& `要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙: M4 m0 u* ]! h* q/ n
ZYH$ W# D: G# k+ R' N3 m- `
QQ:414734306
7 F  N) @9 @3 O% sMail:zyh-01@126.com
" o3 e1 X- M: B$ K  f- J- ], D
; X3 w4 C5 l9 ?8 G# l2 f他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
, f: [1 B& q4 S8 g* M/ I) ^再次对团长大人和悠悠哥的无私帮助表示感谢~~
! X" H% }' J$ Y$ m$ V
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-11-26 11:56 , Processed in 1.101562 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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