EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
& N  s, k# u3 f0 A楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~$ {4 d5 ~& K9 d3 a4 X6 c* e2 R
这里有相应的模拟器源码,就当送给大侠了~~4 _9 R1 L! n9 T9 z+ y7 d) d
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
. R  @- F# n! V* B& ^能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
, D8 d  o0 J8 @楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~% O2 k5 V/ w9 q+ u; D. }" j, V
这里有相应的模拟器源码,就当送给大侠 ...
' N: K; f+ i. |+ A2 l% m
聲音部分(Audoi Process Unit = APU):
. |+ U, T* V( V7 ?.\NES\APU.cpp3 ?1 {9 \: V3 I( V; u+ W
.\NES\APU.h+ G" y% J8 o+ I7 E2 J. I

! s* z- W0 J& p9 H  e& r- J3 ~1 g$ u- h3 p% h% o
影像處理部份(Picture Processing Unit = PPU):
' B7 `9 Y6 ~# Q.\NES\PPU.cpp
( }( q: }) ^* h- l+ V8 j# r3 F7 O.\NES\PPU.h
* S, R9 Q3 Z/ M, J( L4 B
' _" l" s. k- n& ^, z如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
  o& E' k' \2 c" y% v/ f7 d( \% O感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:+ _0 ]# x# x* `# N0 M% W* a. ^/ K
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
+ b4 q: G9 A/ w- S, G3 A6 K9 g  Q7 W8 X//////////////////////////////////////////////////////////////////////////( k7 v; s" b4 k
//                                                                      //
7 R# _9 k9 `9 X; x( D//      NES APU core                                                    //  x: X9 B" z$ Z7 k
//                                                           Norix      //' o* z* u% m) s* j
//                                               written     2002/06/27 //
/ ]8 M5 I3 H  q$ p0 ~5 P" @//                                               last modify ----/--/-- //
3 e! @7 x$ N! O8 U: t# Z' M* H: B//////////////////////////////////////////////////////////////////////////; r1 ?. P2 c8 f/ \7 x2 p
#include "DebugOut.h"
0 h+ V& i& x' g6 `* [% Z8 ~#include "App.h"% i. j  j0 K5 K: o1 c6 D
#include "Config.h"
, t5 H& m% Z: H9 Y2 x# G! z
7 c8 M6 C! Y" p$ {$ Q: S#include "nes.h") t1 C* f5 s  ^3 X! Q7 ?# p4 ]% v
#include "mmu.h"% p8 f' w; N/ b% M% X( j
#include "cpu.h"
* f9 ?+ w) g' r. s; f4 ^#include "ppu.h") t; e7 z5 o- K' P1 n9 J3 i
#include "rom.h"
8 H1 o4 R5 u( A5 a$ G& c, P#include "apu.h"6 s7 K( t5 l7 ^0 S' b
- |* a/ ~: O  @  ~* o+ m
// Volume adjust% z  `5 O+ |9 S5 i# b# s# X5 [
// Internal sounds
5 ^9 K' V8 `5 `8 P: U% `! b+ y#define        RECTANGLE_VOL        (0x0F0)  x7 z. V7 Q5 b' u' s5 s0 N5 Y
#define        TRIANGLE_VOL        (0x130)- z; k8 V: {  h* i
#define        NOISE_VOL        (0x0C0)
' J3 R" i- H" O3 {% @3 s& J#define        DPCM_VOL        (0x0F0)
5 U6 P. |, r0 I" m; Q* G// Extra sounds0 Y1 p$ o& K1 J" `! X: Y5 s
#define        VRC6_VOL        (0x0F0)
8 z! u$ l7 c, t' {0 O$ b#define        VRC7_VOL        (0x130)- X7 r! K$ O! K: b  i2 h
#define        FDS_VOL                (0x0F0); x# v: H1 L$ y# h( a
#define        MMC5_VOL        (0x0F0)8 F* H- P6 E. e4 g* s6 L- r* d% V
#define        N106_VOL        (0x088)
1 _5 C" q9 G1 e3 x7 W#define        FME7_VOL        (0x130). R1 u2 p! A' B9 e  r) t: \) k
# m! ^  w! \6 Z( k8 y- L, M
APU::APU( NES* parent )7 W$ k3 J  p. K& S( a! c6 ]( q
{; A$ P  B3 x( n* M
        exsound_select = 0;
+ f$ }% H2 \  ^# c1 j& [/ R
/ d8 T. j' C2 z% r) m5 V        nes = parent;* ~+ i) N" j; W
        internal.SetParent( parent );
( j; s6 N7 V% B: v" o+ l% h" d9 b5 e0 q8 k% h# A
        last_data = last_diff = 0;6 x6 X( ~2 u5 |
- m$ b4 k$ c# ]4 D4 ~7 R! |8 L) S' _
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );- G$ D( l% z. K, J
8 ]5 }$ ~/ }# A# H( D
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
9 g- B7 }4 C$ a  l        ZEROMEMORY( &queue, sizeof(queue) );
# A- q, g8 Q+ p4 i* u' \$ q! L        ZEROMEMORY( &exqueue, sizeof(exqueue) );& O+ n# G0 G/ r6 ^$ U& u

8 [0 e, u9 J% O8 Z2 W0 y/ S        for( INT i = 0; i < 16; i++ ) {
' u& ^- ~# U) M; h* J2 q& V                m_bMute = TRUE;
2 X8 }9 C% M' g- S% A9 @! c% j        }" `) }# l, e* K4 B4 P
}
: N: [( m6 Z# Q5 Z2 D
2 ^; j8 y, G9 R* {% s3 W) j) wAPU::~APU()4 ~+ F: ~( R; l: A+ G) A7 {
{! B- `( W3 T) e* j: H  a
}
$ m, |' _+ u0 K/ Q7 @" z3 p
8 j8 J+ ?& F* W$ o/ L( Svoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
9 f7 B& h& w; ?* F, G# K7 v) K" _{
1 A: `) A4 b0 d- v        queue.data[queue.wrptr].time = writetime;. x, j3 `) M" l' ]# t; d
        queue.data[queue.wrptr].addr = addr;0 P8 P6 @3 _, T
        queue.data[queue.wrptr].data = data;9 Y4 S3 X- m) S/ U6 Z, F
        queue.wrptr++;9 v" M0 K6 y: j6 v( S2 A
        queue.wrptr&=QUEUE_LENGTH-1;/ Y, X: t$ w8 M( V  M6 Z
        if( queue.wrptr == queue.rdptr ) {: W$ N+ C3 B' L2 V3 r, w
                DEBUGOUT( "queue overflow.\n" );" u$ c* O3 j" A$ w8 J9 H/ E
        }7 T) G$ l$ J& }9 H9 \
}
8 ~8 `! U) j# [0 R" i) u7 R/ Y! I7 ]+ E; @/ I
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
7 m: i- N4 R! C/ o# }, e9 f6 |{
; q! T# f8 z( t. J2 `: R. r* P0 a        if( queue.wrptr == queue.rdptr ) {3 o9 V) b# p" f6 \- s* s
                return        FALSE;, X% F0 y+ U8 G# [
        }' w5 ~* V# q. H5 }0 y
        if( queue.data[queue.rdptr].time <= writetime ) {
9 A  p  x, Y" @2 z                ret = queue.data[queue.rdptr];- D3 Q$ M" t/ g# k
                queue.rdptr++;' \$ b& F; v! ^# h  k
                queue.rdptr&=QUEUE_LENGTH-1;
, t' L' k' N. R4 y# i                return        TRUE;
# N" g. I0 A$ d4 k. f$ _1 F) [* x        }
3 K& @6 f' O9 T5 I) ~        return        FALSE;
) X  c; M6 s( q+ U}
7 t! {* W- k  y  q6 C4 Q; S9 \$ U& Q% _! A
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )/ P$ N. u. p+ o$ b, Y
{
, F7 d% T* M3 }2 G2 E        exqueue.data[exqueue.wrptr].time = writetime;9 c# ?. o+ _/ H; L& W
        exqueue.data[exqueue.wrptr].addr = addr;
2 s( Z% Y: `% H, l& g: l        exqueue.data[exqueue.wrptr].data = data;3 S" n3 d# J7 t5 {. F9 B' T
        exqueue.wrptr++;
; B# z. u. w2 f* N* \+ B; i        exqueue.wrptr&=QUEUE_LENGTH-1;! x8 ?8 w# f' u0 d+ D0 X
        if( exqueue.wrptr == exqueue.rdptr ) {; y' `: X# |: I9 n
                DEBUGOUT( "exqueue overflow.\n" );
& o% n$ _$ K) A1 C7 H        }
7 N; o  c1 e' K& ^}" g. R% k2 `! ^8 `

  X" r* n  M+ a: ^) O1 hBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )( t# ?( _( F( C5 t
{5 r( M4 q6 k) q) R) \. k# ^
        if( exqueue.wrptr == exqueue.rdptr ) {" }0 Q5 Z( z) S. N8 _( K4 \" q* V  @
                return        FALSE;. ]2 E2 o6 w) k' d. W! r
        }0 _3 M+ k+ h+ p/ Z) j5 ?
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
* V& g- {& O, S+ h                ret = exqueue.data[exqueue.rdptr];
9 C& |( g" w" y; G                exqueue.rdptr++;; J" B* W3 r! N' ~
                exqueue.rdptr&=QUEUE_LENGTH-1;
0 k( r6 _# r- E1 [: E9 D0 L  [                return        TRUE;
4 t; J! [. z  o' W        }
" `2 _# v7 }2 k' v1 D3 v( t8 W" ^        return        FALSE;
7 k3 l/ x0 r  J' d  I1 {2 a' Y}4 A& Z& W' l. C1 A3 Z

& _" m8 s. ]3 Jvoid        APU::QueueClear()
/ S3 e4 p. G( m{
) |! g. M% Q, E4 p' Y. ~4 T& z        ZEROMEMORY( &queue, sizeof(queue) );
8 F  c' k" F0 p6 k' z& L        ZEROMEMORY( &exqueue, sizeof(exqueue) );
, r9 B* u4 S6 {/ P- ~}  u* f* N# N* @! o1 D5 g5 ?

. y' v" E2 ~& s5 O7 Pvoid        APU::QueueFlush()
* _' H( n; p2 w- L+ k, r6 x{; k' I6 m7 \1 E3 G
        while( queue.wrptr != queue.rdptr ) {
' X/ p- ]# k; t7 `, [3 E' _: M                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
; p3 }- r) S8 W: V                queue.rdptr++;3 d! }, A$ ^. K% Z; L* V
                queue.rdptr&=QUEUE_LENGTH-1;
0 f- w0 R- U' F! N        }: s4 Q! j! m$ t: ]2 @; \- {+ t$ s4 d

0 _' z# t0 o3 V* q7 K8 p( X; ^        while( exqueue.wrptr != exqueue.rdptr ) {: i+ S( ?1 R( [
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );% ~4 V3 ]: K6 y. u; v. R* D7 R4 a. k
                exqueue.rdptr++;
9 h% R* a" d$ e. q- v                exqueue.rdptr&=QUEUE_LENGTH-1;4 y7 f( f1 u* ~
        }1 D) Z4 Z3 Y' L4 Y: j
}) e2 J% I, d& F; R  e! x' n

3 N) u8 r, E4 N! \+ l# Cvoid        APU::SoundSetup(); X3 G- _& g5 L4 C8 {
{& K- R+ n8 R; R5 Q
        FLOAT        fClock = nes->nescfg->CpuClock;+ x7 F0 O+ i. R, X; x$ R
        INT        nRate = (INT)Config.sound.nRate;+ X. h( X0 ^+ K+ i
        internal.Setup( fClock, nRate );" O0 ~+ i) S, |5 A% N7 q
        vrc6.Setup( fClock, nRate );$ f/ L& j- l9 [# F) l+ g
        vrc7.Setup( fClock, nRate );2 x/ n8 c  e# }4 n! F5 H5 x1 v
        mmc5.Setup( fClock, nRate );
9 r4 x0 p1 _0 y/ U3 [# ]        fds.Setup ( fClock, nRate );
4 t) G9 U" w* O$ N% [& I) M+ Q9 l2 F        n106.Setup( fClock, nRate );: A% Y' J4 K# Z% }+ J( x* w9 q: X9 B. f
        fme7.Setup( fClock, nRate );8 {; o  R; A' ]. q, h
}! k6 @) j9 o) B3 ~3 [
/ |3 b( w+ v5 I3 |$ F" S
void        APU::Reset()
, w8 R: Z: g% d( H- C, O{' D1 L$ z" V6 Y& K
        ZEROMEMORY( &queue, sizeof(queue) );$ L" P0 Z3 S1 W8 I  @9 q( N4 L
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
! l. X2 N6 n+ n# a3 b: r* i. Q
3 o7 Q( }3 N( @7 m        elapsed_time = 0;
9 N% n  I- j- C3 X7 P; D5 A: B  _5 ^8 {
        FLOAT        fClock = nes->nescfg->CpuClock;
( C! Z7 C4 B  I3 |/ O        INT        nRate = (INT)Config.sound.nRate;
. V# l& \, L" U( m9 g* q: s8 m        internal.Reset( fClock, nRate );4 ^9 U7 G; p  ~/ D1 j$ Y
        vrc6.Reset( fClock, nRate );  J' l" t: S& [2 Z
        vrc7.Reset( fClock, nRate );. y; b0 n5 Q' E$ d- f+ ~) o; m
        mmc5.Reset( fClock, nRate );; _9 }: u4 _6 [4 X* @
        fds.Reset ( fClock, nRate );
# g' i/ t) V" _* M+ J        n106.Reset( fClock, nRate );
7 m/ B( ?( p) n: ^3 q        fme7.Reset( fClock, nRate );
  I8 x( q& k# T# K& I  B; n4 O+ U5 g3 ]* p  I
        SoundSetup();$ |- {, R5 f, \. v2 \
}3 z8 i0 x' Z4 Y) b0 o) G

' G- ?3 K, S" |$ Y5 U- ^void        APU::SelectExSound( BYTE data )* r4 \) a4 R; e1 q
{
, R+ k/ o$ t3 F: w% x* y        exsound_select = data;- A6 `1 n/ C3 I; t& ^
}, Z! M; l0 }! M) w2 V9 O; z" {4 |

) }5 s8 z/ R" Z, x. ABYTE        APU::Read( WORD addr )
( G: t% O' T5 Q{: q" s7 E6 l- T7 Z
        return        internal.SyncRead( addr );
  P% z5 X  \3 ~5 L3 A0 _  y; F}& S' Z& g. N8 E/ p& N' o' ~4 Z

6 a9 q$ [9 H5 Uvoid        APU::Write( WORD addr, BYTE data )
$ |* h+ n% r+ g# ?7 W2 x! g{
  g0 h. Q4 ~" @        // $4018偼VirtuaNES屌桳億乕僩
* Y7 L1 ?3 |0 x2 O1 W! N. X        if( addr >= 0x4000 && addr <= 0x401F ) {
. d& ?, w- W) G                internal.SyncWrite( addr, data );# z4 c  |; ?7 @: f
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );/ c7 f6 B5 ^9 I# F' R7 G
        }
8 E0 ]+ g! j9 H, N! C}
4 @* y5 a7 k0 b" C4 ]( x, s7 @
1 }" L  E8 O/ n/ l/ ~, k  O7 yBYTE        APU::ExRead( WORD addr )+ `2 C7 P% v2 ]2 W* `. ?" U  Z
{
+ s& Z! |' O/ K' S# Q# M. eBYTE        data = 0;+ Y6 X! n9 O$ q5 I( t$ Y* ~
, c8 w0 w, X: R  ?, w& @
        if( exsound_select & 0x10 ) {/ C. n. D; k7 b( u9 q+ c
                if( addr == 0x4800 ) {
! b+ w, v; J, S7 `& A; W3 y' B                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );/ o# _5 m8 v9 }5 e4 ~9 _# {
                }
3 C% A! k2 \/ d# c        }( P' z% q  r: U+ |+ o7 L# t
        if( exsound_select & 0x04 ) {
  U# q3 ~, b. G+ I( T- Z                if( addr >= 0x4040 && addr < 0x4100 ) {8 e6 D' w8 B# R' z! n
                        data = fds.SyncRead( addr );
  v7 s, u7 m5 B& F) H, R- m& }                }
4 ?. d, U6 n' n3 @% j$ u        }" v0 d- i( p* J$ f6 r
        if( exsound_select & 0x08 ) {
, F5 E* N) [- w4 h4 A8 _3 @9 _                if( addr >= 0x5000 && addr <= 0x5015 ) {
5 q$ e- D+ ?- e( a3 T7 i0 y                        data = mmc5.SyncRead( addr );
7 [' y5 B% \& O- V3 \0 X                }
1 G! E3 v/ q) J% I% b# u- U$ u/ f        }$ O5 {, i# _. c4 ^! u) g6 j
6 w1 m" E8 _9 y% m9 `  a
        return        data;# P  F# G( k1 R' ^( ?; c
}" u) O2 \/ y" a7 S$ Z% X4 d. {% W
7 P9 Y  X; r* P5 W! @) G
void        APU::ExWrite( WORD addr, BYTE data ), v# Q6 s/ N9 _, `5 N- g
{
' A6 x  Y& I( R, R2 Q& y        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
# ]- _* n4 O: r7 K7 M4 q( G/ n6 V. D# o4 d5 ^( J  ^* K% F$ `! s
        if( exsound_select & 0x04 ) {
% q  @) z2 ^+ b: x                if( addr >= 0x4040 && addr < 0x4100 ) {
# z1 K% A% _/ |/ T6 n                        fds.SyncWrite( addr, data );6 o' c5 q2 ?  B- S  q4 P
                }' o* I, I* K# l7 s6 ?
        }
- ?$ Y7 c! r8 ~5 b* f6 ]2 n2 `3 P0 i) f/ r0 I# s% M
        if( exsound_select & 0x08 ) {
' k1 \0 o" B! [0 i) [                if( addr >= 0x5000 && addr <= 0x5015 ) {* U+ u! `: G& V: u8 ?
                        mmc5.SyncWrite( addr, data );
$ R1 \" y& q/ p7 b" B4 d. i                }& c( l1 n% z3 T" C+ B: ^
        }; _" G# `& L' I: @% `! w' T6 F
}
- D$ X4 D# K  s( n. ~% i3 P/ m3 h
void        APU::Sync()  s3 S& u  A) A3 l! [: k
{1 U8 ]1 Y& w8 w+ B- Q% _
}2 U" A) p4 ]$ o' ^6 q; z4 o# R
$ J: E) y8 z0 V- U
void        APU::SyncDPCM( INT cycles )
2 Y2 P" @7 D4 y) Y$ r. T4 j{& d& W, r0 U" k* R" t. L+ k
        internal.Sync( cycles );% h- y. j; L. G" E. [. y
- L1 t% T& W4 r) m
        if( exsound_select & 0x04 ) {2 N4 P/ C/ u$ P) [. j# s- G
                fds.Sync( cycles );
" S: }' e7 y. z) K2 P        }, r0 ~: }# s3 Q8 f  c3 `
        if( exsound_select & 0x08 ) {; K- M8 X- |/ Z: n
                mmc5.Sync( cycles );2 R: Y. h& F6 a# b
        }' X" d* a8 _( }6 j* N
}! ?# M0 z# G9 T1 q& I6 Y3 i- B
: q+ B# g6 ?0 {! ]
void        APU::WriteProcess( WORD addr, BYTE data )
) o5 A" s- C8 I{( n& E% v. h8 I3 s+ G
        // $4018偼VirtuaNES屌桳億乕僩% k1 |% P0 c) F! h3 ~
        if( addr >= 0x4000 && addr <= 0x401F ) {
+ y9 ^1 }4 d' k1 l, `' s8 a                internal.Write( addr, data );3 z) l( N( B$ T# z3 K
        }5 x  I" L4 B1 \& w5 a$ H
}
  f$ U6 f2 W& D  n  N: [# X/ q: x4 @9 G
void        APU::WriteExProcess( WORD addr, BYTE data )
2 t) P3 p6 k6 P9 j$ T2 W' v; {7 p{
( n* N4 g& U3 Q        if( exsound_select & 0x01 ) {! \0 @2 w" M5 j0 X& A& R/ V
                vrc6.Write( addr, data );$ J$ _; `; [$ [, I
        }# G# k% ^% |$ O# O
        if( exsound_select & 0x02 ) {6 J8 z/ f5 B' v1 z/ E. p" d# @
                vrc7.Write( addr, data );+ t8 n1 C& g) ]4 a) j; {( p" _
        }- f0 L, s, E6 m
        if( exsound_select & 0x04 ) {
- W# ]* z5 I0 t# o6 R; |. R! g& E                fds.Write( addr, data );9 }% R4 D9 w/ D1 ]
        }  s4 c+ u& u% f+ L0 h6 `6 H
        if( exsound_select & 0x08 ) {# ]/ x7 ^' @* G, X9 }+ Z" E
                mmc5.Write( addr, data );
' X4 j0 @, j" l5 d/ u6 H) W        }
( Q4 v6 {3 {& g% u" G$ A        if( exsound_select & 0x10 ) {
/ p! A. v5 y) S- R% [                if( addr == 0x0000 ) {
: p2 u0 C; R; y4 A5 h                        BYTE        dummy = n106.Read( addr );: i. [- y' V! e& U+ U7 J- P  E4 V6 S
                } else {
9 N- G: X5 G6 T( f- ]& l4 L                        n106.Write( addr, data );
, p; |% [$ m( T" \. k0 p! s                }4 C9 I8 b. b4 _# t) g/ p, A
        }9 w+ }8 F0 a9 {
        if( exsound_select & 0x20 ) {
9 D2 w% H; W9 g6 i' ?$ a                fme7.Write( addr, data );
' j3 Y: R) U: K+ F2 ^3 h  Z+ S        }- }8 ~9 J& k7 [* f) u/ q
}
  N) b" z  s  V! \: h" I9 P; c! h! }: e& I) {0 Y; \; K& n
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )8 i* B$ y/ [5 ?/ q
{5 y+ j3 z# T0 T* Q3 m- r% u: u
INT        nBits = Config.sound.nBits;$ u% X. f0 f5 H0 ^, n: i
DWORD        dwLength = dwSize / (nBits/8);
( I$ v0 C8 A; K) PINT        output;. |$ z3 f" z7 m2 y6 l7 P, ]
QUEUEDATA q;
5 g: \: u3 o- g* m8 }DWORD        writetime;
% z) D0 D; H  e' l1 K, x& K$ ?7 e" @( z- h1 Q
LPSHORT        pSoundBuf = m_SoundBuffer;
4 }: N! m* ?/ `6 wINT        nCcount = 0;  }( m3 g0 w1 \' K# m9 H
- l  {) t- @. X8 N
INT        nFilterType = Config.sound.nFilterType;
5 b8 b" Z. o2 J; u, ?" ^& p( {- c! a! E9 c0 v
        if( !Config.sound.bEnable ) {
/ a: {! g. ]7 b+ b# t! _* G- B1 `                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
2 O" d! l) \; L$ B                return;
1 Q& h# b5 S. |. ]6 D9 Q        }
" i/ c" g% q* j& f2 W: d2 v
( m; n$ w4 {/ o  I" G" }  v# S0 R- d" H        // Volume setup  {! M" R9 P: W% v8 m  G" O6 v
        //  0:Master# r+ y6 f7 H2 ?' h4 P( k
        //  1:Rectangle 1
0 u* W0 I$ H6 r$ F4 b4 L3 a        //  2:Rectangle 2
. u3 w" ^% \8 l0 @! w0 T3 A        //  3:Triangle6 j7 S# v" e* ~: `& [' P
        //  4:Noise5 K& f2 E8 ^- W9 O1 }7 s
        //  5:DPCM
' w! f; N  }7 ]        //  6:VRC6
% ]& @" I6 |4 \% a) [* h+ O        //  7:VRC7  }7 {: L+ H7 h) l& o2 l  S! O
        //  8:FDS! P. @+ Z4 C- E/ y! K  V3 [
        //  9:MMC5
; E& u2 k( z; m. A! m1 O5 ^        // 10:N106! q1 b- K* a- B0 A1 E
        // 11:FME7: g4 j; [8 W' w- v
        INT        vol[24];
- ~  t& K- I$ O/ _        BOOL*        bMute = m_bMute;% X# Y; |# ~, c6 g" x9 I
        SHORT*        nVolume = Config.sound.nVolume;
6 n% E. |! r6 `7 u* k: J& F6 X* g# t- o# |/ f# E0 _. K2 }2 k
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
3 z/ _( E4 N  n8 O, ~) n6 |0 J9 B2 X, @
        // Internal/ t! D( K0 [. Q- {* P
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;/ A6 g! ~' W: H, b4 ]: L
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;: t6 x, ~$ A& ?# w1 G: ~# k3 V
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;5 y" @: N* H2 z, o
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
  p8 ~8 T. L/ c$ k        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
: `# m" c. J" o' {
$ T) \' @9 U  j$ t$ c        // VRC6
& ~  O% m  W' C3 V        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;6 h, U) p, O; K
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
& Y6 |$ f6 ^) s% s8 X  H9 r0 G        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;3 H: ~6 t8 r% e) |4 v! z: U

2 _5 Z3 ?; h) \. i        // VRC7. _! `2 P! r) F+ Z( R4 {0 Y* U
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;  @  D1 B1 C- u. I

& f' B: y7 i* h$ p        // FDS
& [- A5 r7 ]. Z" w7 e        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
. x: P6 A$ y: i8 e! g
) x8 _5 u3 |! Z# N; L. e        // MMC5: }/ Z: i2 T9 h$ r4 M$ T, ]% l
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
# H& g$ G" {$ W6 y        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
$ I8 \& E: v7 `4 ?: }        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;% t4 u% J9 o# X' e

: X* |1 w5 v  j6 n9 O- Y! P9 D        // N106
5 w, a; s+ N" ?# A; X" r$ r( Q        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;8 m" o. V. Q) o
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
2 M6 m& r' G% _4 T        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;, e) F& }1 h9 @7 W; T2 I  W8 M
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;* r  Z5 l6 Y) Y, @  W
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
8 V- r& J0 O: z7 u  k* b        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 y6 {9 T; T9 f/ ~) m* m# k
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
- ~  Q  q% ?8 P        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;& Q7 d2 b1 V* A( L! u4 l1 H
% W+ w7 S4 H. Z/ e- K( K# l- v
        // FME7: ~/ ~. o% M2 Q! f" o) M: }6 V
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
6 Q& w% ~# Z* }, z* e/ z0 y, ]        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;7 D% Y! A1 U9 w; {. }+ c3 M0 @
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
) B& X+ B* ]( N# v* F5 m7 I, x) X' U) b6 I" g
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
' F7 J5 q! X, g8 [% U        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;0 `0 F2 ^. n1 p7 M
8 R2 ]# q- t: m0 G$ ]0 n
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
+ ^; f  M) w* f  r5 `- H        if( elapsed_time > nes->cpu->GetTotalCycles() ) {: k: l8 t2 c; d! G5 M* P- ]
                QueueFlush();' n, r) k& ^4 h
        }
& I* J- _3 e& i
6 x/ C- @1 u0 a# ~0 q: x        while( dwLength-- ) {/ y- @: W2 N+ T# E
                writetime = (DWORD)elapsed_time;: W$ |9 b! @" K  y+ B: H

1 v3 D# t) V) ?* ^8 p3 H4 D                while( GetQueue( writetime, q ) ) {/ R3 s. H2 _; r) H/ ?
                        WriteProcess( q.addr, q.data );
: z; b: M- S! o  M                }5 A" C  u. T! `, v% N

4 x' G/ T( w3 ]4 g0 u  S" a3 @                while( GetExQueue( writetime, q ) ) {
: ~1 N$ d6 f, ?& ~                        WriteExProcess( q.addr, q.data );! @$ Z: R0 J  q3 j& y6 \+ Q
                }
; N/ c! e- w# h% A0 A1 ^& b! \
+ w  W0 l5 u7 f( w* s& V                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
2 ^+ D  _: M- I+ M' G0 [9 R7 m                output = 0;3 j( O8 z; b9 b+ f5 t" C* w4 E
                output += internal.Process( 0 )*vol[0];
$ A' t6 G  S( z$ @                output += internal.Process( 1 )*vol[1];" i: C% ]7 g* i! c2 A- k
                output += internal.Process( 2 )*vol[2];
6 A8 |2 T  t) z. y  Q7 T$ f# l+ H                output += internal.Process( 3 )*vol[3];
$ f" s5 ?% V7 j2 Q4 F( f                output += internal.Process( 4 )*vol[4];1 |( h. O4 A1 W+ ^

6 s3 u. b: ]: M) K1 t5 A, d                if( exsound_select & 0x01 ) {# ~% ^& O0 x! s& ^) Y
                        output += vrc6.Process( 0 )*vol[5];5 z4 C. K2 Z" A- t
                        output += vrc6.Process( 1 )*vol[6];
9 Z3 n5 Y& W0 h4 w7 }" Z                        output += vrc6.Process( 2 )*vol[7];
4 M3 `- M0 R/ p                }
1 ~& ~* t: ~( u: {                if( exsound_select & 0x02 ) {6 v( P- Q7 T, K; [% i. O
                        output += vrc7.Process( 0 )*vol[8];
- m5 q# }- x$ e3 P7 C1 d                }  B; O4 F/ j7 `5 O
                if( exsound_select & 0x04 ) {. z" C  g% G, f; \2 F; w5 {4 ^
                        output += fds.Process( 0 )*vol[9];
2 ^) z' J4 y& n3 I$ G  \$ G+ F/ M& i                }$ O6 D5 s- \$ x! s" b( |8 J5 D
                if( exsound_select & 0x08 ) {* G: ~' {8 A3 O/ C9 \5 f; _. H
                        output += mmc5.Process( 0 )*vol[10];( \1 Y+ u8 H  N& `
                        output += mmc5.Process( 1 )*vol[11];3 s! @: o  Y6 Y( j  R2 n
                        output += mmc5.Process( 2 )*vol[12];
! B! |  [7 i- e" X6 s                }: D+ B  E- \" ?* U3 Q
                if( exsound_select & 0x10 ) {
7 v! V0 K% o) }1 U                        output += n106.Process( 0 )*vol[13];
+ S& ]; v: D0 j) X; `& ?                        output += n106.Process( 1 )*vol[14];
7 ]& |1 D7 e( D5 ~                        output += n106.Process( 2 )*vol[15];7 g* p. b8 Q5 r2 f) O- ^3 y
                        output += n106.Process( 3 )*vol[16];
7 G: X" B. ?# x: j# }. @                        output += n106.Process( 4 )*vol[17];
$ V8 h+ Q2 f) P# ?5 S9 T                        output += n106.Process( 5 )*vol[18];0 y' J) Z0 H/ P4 w, b) E/ G
                        output += n106.Process( 6 )*vol[19];1 r: G$ t8 d" u2 w
                        output += n106.Process( 7 )*vol[20];+ T7 h( g9 P4 g
                }5 Y: n+ Q  I) I  w
                if( exsound_select & 0x20 ) {
6 x( _( c) s" Z" |4 ~2 h0 ~. z                        fme7.Process( 3 );        // Envelope & Noise% ~3 N. ~6 I) i! E: f1 i6 G% h4 S
                        output += fme7.Process( 0 )*vol[21];
5 D8 L0 |! V0 H! r8 h1 c) c                        output += fme7.Process( 1 )*vol[22];  t( `* |8 w4 e% D  L1 o9 o. T
                        output += fme7.Process( 2 )*vol[23];
' h! E6 u; H  }+ J                }
- U, B7 N, `: X+ c! v/ @% S* n3 x5 F5 T4 R
                output >>= 8;1 m" r- [8 p7 v* Z9 j8 w

7 H# h- i/ n- B& F  z. \- e                if( nFilterType == 1 ) {
9 X# Y. v: g. n% K  `( R) z$ E                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)3 }+ j7 b% o+ ^$ O- v. G
                        output = (lowpass_filter[0]+output)/2;" O) S1 N0 j1 j4 t$ _
                        lowpass_filter[0] = output;  T& ?* H: U5 q6 P& @
                } else if( nFilterType == 2 ) {  j) `7 b. y% T$ l8 W- W# {/ e* M
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
9 |( e5 M' ~% y+ z/ S/ W                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;* [) J- Q( E: \
                        lowpass_filter[1] = lowpass_filter[0];# E5 G# r, l, k( N! A; b& V
                        lowpass_filter[0] = output;
+ B: R, @1 E( W6 |                } else if( nFilterType == 3 ) {$ C$ u; y7 a! f* Z$ b' ]. `
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)8 Z6 @( n8 W0 I4 s0 H& j5 e/ k
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
$ l, o9 m4 M+ c: }8 \1 Z                        lowpass_filter[2] = lowpass_filter[1];
7 X( p$ }( L/ ?3 }" J                        lowpass_filter[1] = lowpass_filter[0];# H) F: R' b: d* E9 A1 X
                        lowpass_filter[0] = output;; Y9 X- A$ I6 b4 D
                } else if( nFilterType == 4 ) {
, {+ ~! ?9 N% T" P5 `( \! `                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)9 Q7 Z* l0 Y1 M- a* o" a' d
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;6 E- N# v$ d2 L% g' C. n/ ~$ e& ~7 I
                        lowpass_filter[1] = lowpass_filter[0];
, n1 o, E1 h+ c: k& g2 R9 }                        lowpass_filter[0] = output;
4 e( {3 G4 h7 L# y/ G6 B                }+ f8 s; I& \# S' J; F& i7 @( d

: s) I+ ^9 n" D" W; O! O#if        0
; I  }& O) D& |# K" _% R4 t                // DC惉暘偺僇僢僩% f7 \$ W% P6 m
                {/ C( y; g5 l% E* d5 k5 T% N2 W$ M
                static double ave = 0.0, max=0.0, min=0.0;
9 ]2 _$ q( z' `- b5 ~                double delta;
& k9 l( S1 ^. W4 A                delta = (max-min)/32768.0;' O1 h# E8 ^/ @4 Z
                max -= delta;
1 G, j8 F3 a4 X                min += delta;
8 C. t6 e( [" s/ [( O                if( output > max ) max = output;! \5 ?- D4 v. K9 d' r
                if( output < min ) min = output;' W% f& `& B6 v/ G" v
                ave -= ave/1024.0;0 V" x! G* z3 C2 C. C( Z/ F* i
                ave += (max+min)/2048.0;
5 J' D. i' v! M7 D/ m  Q                output -= (INT)ave;
' Y# n1 F5 d' R; x                }
, l% o" m/ H* d#endif
/ m# ]( s8 ^- A$ a#if        1
7 i# P) X  m' f# s; h7 ?4 ]                // DC惉暘偺僇僢僩(HPF TEST)' Y$ \3 }1 T2 ]% _; b6 y
                {; k! m0 x: U  |& C
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);0 W& {1 k% d  e; p
                static        double        cutofftemp = (2.0*3.141592653579*40.0);9 W! U6 j: ?, Q( P6 \
                double        cutoff = cutofftemp/(double)Config.sound.nRate;" L0 B% o2 K2 Q
                static        double        tmp = 0.0;
" b# S0 Q$ i( j8 N5 S                double        in, out;
/ N. B8 l/ ^1 ^% @* L
9 h3 Y' k% l5 n' q; a+ c                in = (double)output;) h* ^! ^! m; D, h
                out = (in - tmp);" r1 O; J$ |% ?. {+ L/ q$ S! _
                tmp = tmp + cutoff * out;
5 W, Q- C* \1 |( t, H- P+ H0 o& p2 K6 d1 C& u+ M' d% o
                output = (INT)out;2 w& x' \" e4 }# i2 \
                }2 K' `2 z: ?8 Q- h
#endif
! h- W4 e" d, Q. d  D#if        01 [. O. `* y( k( f
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)6 c4 l1 \3 a- ?/ P, |. Z) j" d
                {3 J: C" f8 g. j. a3 z
                INT        diff = abs(output-last_data);4 G' s# ^4 H8 w# A1 V% I
                if( diff > 0x4000 ) {
& L# T: j% P8 v' L" B( ^6 c                        output /= 4;  t! a+ |+ N4 Q% F5 x/ S  S+ }6 \
                } else / T& T: i' {% U2 B
                if( diff > 0x3000 ) {
7 q/ }* G9 @$ X0 r  I                        output /= 3;
0 Y$ q& I7 U& ^; }% o" x* R5 v                } else( F; B0 s# a# U, h2 Z, w" ?
                if( diff > 0x2000 ) {
, M/ i4 B; N0 F/ r: w5 B* C                        output /= 2;
! l% Q6 o* J9 u4 F                }
/ r" @4 t' z' N4 ]( ~                last_data = output;$ c% \% j* |4 ?) s$ }8 k
                }
/ u" [0 V, o0 C, b. O& _8 W" a( y#endif
' V/ c. `( c5 k& W                // Limit7 B. B# `( v7 |" b+ O
                if( output > 0x7FFF ) {
7 r* e' L' Y6 ]- G3 {6 F                        output = 0x7FFF;/ h  Y. |: g& |
                } else if( output < -0x8000 ) {
4 s2 Z  S9 r9 B1 ~3 z  h& ?9 L                        output = -0x8000;( ?, s) Z7 i7 u6 I8 O5 U. U, J- E
                }. P& }, ~- O) y4 `: {; n7 ]
* |2 ]- e9 U5 d: O
                if( nBits != 8 ) {
+ F" _3 C# p+ m3 M, N- p                        *(SHORT*)lpBuffer = (SHORT)output;( X& m" g2 ~9 I% Y' d; g
                        lpBuffer += sizeof(SHORT);5 y) O( d8 f1 r* ], n+ [
                } else {
2 C( g: t8 }, d* C5 l8 f                        *lpBuffer++ = (output>>8)^0x80;
: v+ f. e+ u" r6 M% O4 N                }) K4 Y* y/ F+ ~1 {( R% Z

( G; \' L, `) B# E0 a                if( nCcount < 0x0100 )
% t- p$ w: O# N& T8 L, S) [6 M9 |; L                        pSoundBuf[nCcount++] = (SHORT)output;
/ @- U: L* f' Y3 Z" M; n9 W
0 l: p( `5 @  l: W3 M* x/ K//                elapsedtime += cycle_rate;
4 w. M& t$ t: o% Q: H% w                elapsed_time += cycle_rate;
$ @; R8 ~( w/ S- N        }0 Z: ~) ~! l# H! w

' `' s) p& w2 a5 ?+ L#if        1% u9 {+ I4 o, |
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {! z# i4 z9 Z$ O, W: ^
                elapsed_time = nes->cpu->GetTotalCycles();
. N- }, P4 f& x' w# T        }$ k  I  C. z2 ~; {0 H# |9 h
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {( A  X: c, y. a7 a3 X
                elapsed_time = nes->cpu->GetTotalCycles();7 p0 f7 C1 W1 n, e4 N
        }
' U4 ~- L: `. O- S3 F. N; e) n6 }5 k2 t#else
" S; s- K2 i9 p2 ]* F8 Y        elapsed_time = nes->cpu->GetTotalCycles();+ _3 C8 l8 p/ l: n
#endif5 r# r7 b. {) T' b2 `
}
# {7 C* x; E4 ?4 i  G: p3 ]( E& ]  g3 h( [/ n/ O, ~+ G
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)1 h  c- a# p) `; g
INT        APU::GetChannelFrequency( INT no )
9 N5 i+ }7 J7 p# i{0 w* c: O! r0 s( t
        if( !m_bMute[0] )' s2 Z' D" E! I- T
                return        0;  [) n, T$ P: E

; ~+ T+ X( c- e- ]        // Internal. T) t" E0 `6 o% H* j+ ~" @
        if( no < 5 ) {# A; y6 y, q7 S8 z- g; c
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
! L  s) x! m7 e2 F        }
* R7 x; o; W$ i) x' h! t        // VRC6
' C9 V. ^# i- [$ H. Y4 |6 l        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {9 u% z( Q( n, y1 _2 ?$ g+ T
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;  n4 ~8 f( i9 G3 W0 b
        }* _8 s2 L- P1 F$ Y
        // FDS
. M8 I; {$ X; c8 u" @) K8 ]5 W        if( (exsound_select & 0x04) && no == 0x300 ) {
7 b' ?: b+ t0 p9 h; o                return        m_bMute[6]?fds.GetFreq( 0 ):0;4 i6 l) I9 k! `( k) L& j( {
        }  L/ P: u( e' {9 X+ D- _
        // MMC5
2 i6 _1 y: K3 @5 \( l9 F$ }        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
6 U, \) p& n  y; ~4 t( X4 x                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
4 w- K0 G$ S9 T+ a8 |4 H( `        }
3 {: s. S  h% [$ e9 `8 ^        // N106
5 w8 ]3 Q4 B8 A        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {8 i* K% d% U' G6 p
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;  H4 e& O3 n  n4 J+ M
        }
0 t% Y3 n  b' u        // FME74 M  q& K/ J$ l9 G1 @  G, V
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {- u  Q# \6 `) f" `9 F- r0 o2 S
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;$ }' _1 R) {' P- I& B2 {6 ^
        }! {" B' V. x& H! }
        // VRC7
: @( t. w/ p% z+ ]) F1 B        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
( C: D3 H8 N- {- F1 u) R                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;+ o& K- {# Z% Z' Z2 |* H4 Y& Z9 G
        }2 z$ W; M: w, }% Q/ t. O
        return        0;
+ M2 x7 R+ K0 T! b; Y# T}/ P, G' y: y0 C: m. m4 a7 G% F

2 E& z& e. ^. ^# K! I( K// State Save/Load) M/ n5 h$ Y/ ?  N" p2 f
void        APU::SaveState( LPBYTE p )# m8 y9 Y$ Y0 ^+ I( N: e& d+ t2 ]
{6 X1 r2 q+ z2 V& `5 N& n; P
#ifdef        _DEBUG
5 t8 [  u( {) }( L1 ?1 GLPBYTE        pold = p;
8 `" N; D& W0 z3 d, X+ d' ?#endif
) H2 J( k) j0 K6 K$ n( p8 O  a$ e0 h$ I( _, ^1 @8 g
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞% t4 Z9 F1 X/ l4 \% A& m
        QueueFlush();
8 A) R0 G  d, @) O/ B, ]+ G* t' p) _7 a0 D
        internal.SaveState( p );
. k( {' E2 f" N        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
* Y3 x' l3 g" r3 H/ V: J
- N( x* F- a/ _* n" d% g' r! i4 u% e, C        // VRC6
; |  ^0 W8 i2 m        if( exsound_select & 0x01 ) {
% x) s+ L; r! u( I( t. N6 _                vrc6.SaveState( p );- _5 g) I: e) m3 p6 e: }) g! k
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding( Q1 Z7 j$ F/ o0 X2 m
        }
" C. [6 j: G  N- r: x6 s8 U        // VRC7 (not support)
2 n. O8 }, r. {$ }( R& k        if( exsound_select & 0x02 ) {4 ]6 K4 @; f: a/ d* A* H
                vrc7.SaveState( p );" l5 t9 V% c2 J& F# O% O
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
/ g. q9 d* M0 U# y        }$ `8 @2 \  O# Z) d$ M5 K
        // FDS. t5 B2 `/ l: \/ I0 n% _9 A
        if( exsound_select & 0x04 ) {
/ m0 B7 n; Z9 _, n. s6 f4 X% p                fds.SaveState( p );. F! p: O( V* [/ K% `5 A
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
. b) s( \* I4 G5 o+ p        }5 X, i. ~) D8 l$ j
        // MMC5  M3 T9 S- }( w' m
        if( exsound_select & 0x08 ) {  ~% R" V3 O" z/ v
                mmc5.SaveState( p );
) B- D- `" V, G* M                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
* d) b5 V0 ]& T        }
  p$ z5 B1 ~! o" P1 ~" c/ S: h$ n        // N106
( _6 b: T( p, W9 H% B7 J8 j        if( exsound_select & 0x10 ) {1 @. c, U( n4 h
                n106.SaveState( p );6 p& |; ~* \) ^. j* p9 h
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
4 H0 z4 o2 \+ S4 m        }
( t+ z, h4 m2 J9 R* u$ z        // FME7. |5 ?8 V, A: t. t6 \
        if( exsound_select & 0x20 ) {! e) S* z% u0 c* K
                fme7.SaveState( p );+ s0 N/ |1 v3 w
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding% R1 S% k% X6 m
        }/ ?) p) j) Y" u

6 t: s6 P: y) H) \* R#ifdef        _DEBUG4 L- ^3 ?# R8 H2 H) ^5 S4 g
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
+ @/ T) C) W9 C#endif
2 g) A3 }1 L' A}2 T, `0 ]# F, e5 \% g
4 s4 a* Z5 z/ a' y$ X* Y; o6 E
void        APU::LoadState( LPBYTE p )
4 w7 @! G! s2 }0 W' d" R( u* V0 v{
( `$ N/ N7 ?- w0 V- z( u6 D( h: q' o        // 帪娫幉傪摨婜偝偣傞堊偵徚偡$ P" ~: K& a# }3 I! c8 J8 y
        QueueClear();
8 i) E' B+ Y7 V# ?& g( W% ^0 c2 i2 {5 {# f
        internal.LoadState( p );
6 s8 K/ Q- q8 K5 e' W# F& A        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding/ T! E) Z6 i2 k# d- P9 N

& I/ \5 Q+ Z+ J0 W% |        // VRC6
4 y$ ?* I, ]( {+ a- U: e        if( exsound_select & 0x01 ) {
/ |0 X' q7 F1 h# a                vrc6.LoadState( p );/ T0 }) t' X0 l2 I
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
4 O3 J* a! @  z        }6 B4 X4 O% u  T. [3 v" T" e" B( y
        // VRC7 (not support), r& Y  j0 |# K, P2 ^
        if( exsound_select & 0x02 ) {
* B) W0 k" y" _& D0 B8 }  U                vrc7.LoadState( p );
3 }) z( S3 y3 ]- F) v: p                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding6 f! y2 }/ {# s3 P+ i) X" |5 V
        }+ w; P! b) b) g5 E& E8 C  e9 `" o
        // FDS
9 e- B) ]: Q; V) d        if( exsound_select & 0x04 ) {6 h' {0 |: D' U8 \4 s. O4 I
                fds.LoadState( p );. h% v6 j+ p$ e
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding! P5 ~# O5 g" d# V+ Z6 W8 k, l" t
        }2 W0 t$ P4 ~: I; v$ ]- ~
        // MMC5
  q" @6 c7 `4 e; Y3 c: u1 t        if( exsound_select & 0x08 ) {- T8 _- k/ s, V, M5 d
                mmc5.LoadState( p );
# K8 F2 B2 t! o0 @3 H$ c& ?                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
4 i% @8 ?; r) e) A/ Q8 H& V        }
; r) S0 h+ |/ @( @        // N106
  d/ z5 o1 b. {3 Y. x3 K% x        if( exsound_select & 0x10 ) {' `; x& f$ }& u1 u! ~
                n106.LoadState( p );) L$ q3 c% s$ l+ H$ p9 i' c8 B6 O
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
! n9 f2 Y, `% m7 Z8 B( f8 Y        }$ m* d3 R6 {* `3 R
        // FME7; O5 \( o8 W+ a4 }
        if( exsound_select & 0x20 ) {0 e9 s' ^* t- j/ h' p0 g
                fme7.LoadState( p );: }% F7 o  U  k
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding4 ?: l+ }9 a% ?! u8 k8 [
        }
6 b- s9 L" f% o/ o/ R3 K+ q% m) t}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
5 i3 ~/ S# g9 A4 X# d$ @可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。0 ]  v! d, t( D- M5 A9 ~0 {
感激不尽~~
0 \3 B# o/ D: C- ~" G1 k
恩 我對模擬器不是很有研究," |' ]( m* z8 u, c5 H
雖然要了解源碼內容,可能不是很困難,
  j7 ?7 y2 `7 k; z不過還是要花時間,個人目前蠻忙碌的。
% O+ W; I2 [6 v) p2 n- I
! o: e3 Q# G) o5 [6 A給你一個朋友的MSN,你可以跟他討論看看,
8 {$ |0 S; w- T. X$ @9 k+ N他本身是程式設計師,也對FC模擬器很有興趣。3 k5 z! Q, k7 h/ p

8 g2 c/ h. B) ]* dMSN我就PM到你的信箱了。
+ S- d  K2 ~7 r! J2 o' G  _
  r9 K) }& c) X9 n希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 4 _) V* R! x% ~: n, `9 Y# h* X. E
呵…… 谢过团长大人~~
* z! F7 I% ?! C# `. q2 }

. L+ y* C. Z' Q1 W9 p. s9 I# V5 `哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
# A2 t9 Z8 c$ h团长的朋友都是神,那团长就是神的boss。

9 B6 `4 ]" E7 d) y* v8 P$ z+ _: r哈 不敢當,我只是個平凡人,
% Q% d, L, R: I8 w' I/ G* V0 {4 y要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙8 ?6 g9 B' x/ [! r* l6 S* ~
ZYH
1 Q$ r' v3 R  Q8 A- P4 t9 RQQ:414734306
4 n! ?! v& I2 L( tMail:zyh-01@126.com
! G- I+ I, }* I) F
2 t& E0 L/ O- v1 f% E他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
! x7 L% J$ H$ ]5 `! S- |1 ~' @再次对团长大人和悠悠哥的无私帮助表示感谢~~

( P' d' f, [$ O不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-20 10:11 , Processed in 1.238282 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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