|
|

楼主 |
发表于 2009-11-8 14:47:50
|
显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
1 Y( g2 s4 g. K- f(由于很多专用术语和算法机理都不明白,所以看不大懂……)0 K/ G$ F) K7 K! F8 {" D( F) B
//////////////////////////////////////////////////////////////////////////( J9 p# O( T; V( W/ C6 ]
// //4 J6 k" E9 K! k; o
// NES APU core //* G+ V- E- y! T6 I& P* v& S
// Norix //: C x7 F& \5 n0 R% Z% p! ~
// written 2002/06/27 //% e2 ]& ^6 l. j! N- r/ H/ |7 O
// last modify ----/--/-- //
! L3 M5 \9 o" z0 x0 @//////////////////////////////////////////////////////////////////////////
* l6 @, d; i& `# Z#include "DebugOut.h"6 ^0 D/ @" I8 ^" A7 o
#include "App.h"
- n4 T5 ^7 ?% D+ m2 Y8 L+ `#include "Config.h"
5 h1 W8 r5 Z7 ^
5 z$ e. c4 f$ [7 Y#include "nes.h"9 }7 z8 b' \, o1 D2 K
#include "mmu.h") s( }5 G( v" T$ ~
#include "cpu.h"
9 d" V" P4 `: m6 {. n+ p: l0 a#include "ppu.h"
! ~- f4 f% [5 @4 q* O7 o1 V" O#include "rom.h"$ I; @& s- |2 W% m- U+ P* W
#include "apu.h"7 r! u. G7 U3 N* C: X9 l
) o! e) |3 S$ B$ F1 `% }
// Volume adjust
& ~: @% a8 A0 _9 g) [! k$ c// Internal sounds
1 S+ f$ d- E$ i: [! I#define RECTANGLE_VOL (0x0F0)
3 `; y" Y, Q3 C3 Q! @#define TRIANGLE_VOL (0x130)
7 @1 n' ~& P# f) L5 r L( V#define NOISE_VOL (0x0C0)3 P2 ?+ `) E: a& [! K4 Y
#define DPCM_VOL (0x0F0) ^5 G+ Q ^' |3 ~* h! |, _
// Extra sounds1 A0 a" \8 k8 `/ e- x/ f- [3 R0 j+ \
#define VRC6_VOL (0x0F0)0 [- {4 o1 k8 `3 ~9 S2 M
#define VRC7_VOL (0x130) B/ Q; `- e. V* U' B! A% r
#define FDS_VOL (0x0F0)
" _, I0 q# t: b4 b#define MMC5_VOL (0x0F0); n# ~& w X% V0 N% G7 t, j: a% g
#define N106_VOL (0x088)
5 Z% o. u8 N3 l$ \6 N#define FME7_VOL (0x130)
! a" D4 y# K- `5 X* I1 P+ p+ d4 |+ U* v/ P0 p
APU::APU( NES* parent )
) v7 n% T. U( \- v{
g1 R% E' u5 @4 L exsound_select = 0;9 b- t' P1 M% t$ q# n3 v9 u
9 w6 Q' K( a1 k1 U' K' T, o nes = parent;1 j8 {. w* R C! ^5 }1 e) ^1 l* ]
internal.SetParent( parent );
- K% V+ C& x+ w$ @$ _2 y' n, O4 P2 p5 V! V' q
last_data = last_diff = 0;
3 K9 N5 Q8 {( T" A6 F+ U/ ~" t
. a! a& g0 _! y: Z# j ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );$ g: J4 o. L& h/ I( _
( {7 Z) I& f. N% r n2 N N7 r ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );6 B( ?/ y* }0 K( B4 V# ?7 Z6 y
ZEROMEMORY( &queue, sizeof(queue) );2 {( k- w5 u: ?* j! `( o, l& T
ZEROMEMORY( &exqueue, sizeof(exqueue) );* [: g+ w7 d: M% h9 |# _
1 r& J; Q3 H/ a4 k; Z% H* B \( z! E for( INT i = 0; i < 16; i++ ) {
5 p9 x- P) N' r1 H. l; l6 H4 o m_bMute = TRUE;3 ], c( C2 g) i9 Y
}
h1 B4 G4 ]+ e}' ^5 S* O, x# Z S f! f; P; ^
( l/ r, M5 h1 N5 {3 J
APU::~APU(). D5 U4 B6 ]+ x% V+ d3 j( ^0 T
{' y8 R! d3 N; F" T4 n4 j
}, ^6 l0 L, C) e8 l3 ]
B1 f+ ^* k' R2 c2 n( L" x" rvoid APU::SetQueue( INT writetime, WORD addr, BYTE data )
& \" A0 U2 D" W{
; J$ p% C- l1 m& ^ queue.data[queue.wrptr].time = writetime;% M5 W" V) z/ R% H9 }
queue.data[queue.wrptr].addr = addr;! B( q/ H: Y( b' n6 f/ h/ K' D
queue.data[queue.wrptr].data = data;2 Q* U- r. M4 B" U
queue.wrptr++;" W# X3 g% n5 j; ^! u' ]6 W
queue.wrptr&=QUEUE_LENGTH-1;
5 k6 p% Y' P( u. M' R2 \" D# N if( queue.wrptr == queue.rdptr ) {
5 E" a( b% D2 ?- ] DEBUGOUT( "queue overflow.\n" );
, ~2 Q( \4 Z9 c# V2 L }2 l5 s8 F0 Q6 i& v+ m( `% e( u" K
}
2 f) |5 I! e D2 H
5 J0 P0 d- ?# J" {& gBOOL APU::GetQueue( INT writetime, QUEUEDATA& ret ), @; |7 s' W. d
{6 Q" _! ?% b, R9 p3 k% g" X/ x9 T
if( queue.wrptr == queue.rdptr ) {
% n/ C( C2 u4 T. p0 I r return FALSE;0 C q" |2 ?/ J: ^0 D
}
! j) l" p3 }# v: W, H; Q) L if( queue.data[queue.rdptr].time <= writetime ) {
8 f. @. y! A+ s+ O( r ret = queue.data[queue.rdptr];
5 ]2 |/ w% V* ?/ v$ h: p7 r3 n7 v queue.rdptr++;
3 ]( F* V' F. B0 h2 M5 ? queue.rdptr&=QUEUE_LENGTH-1;
1 n$ Z$ X( M$ e4 Y! w return TRUE;6 ?1 b6 ~# G- f* B* f3 n
}
* j p6 c1 M& M' _: C8 Z# v1 p) [& s return FALSE;
8 \- b" f# x- _- ?6 u}
1 o: g% D( H$ e5 L6 {& I# G& g3 `+ x1 v+ j. \0 C
void APU::SetExQueue( INT writetime, WORD addr, BYTE data )
- j5 }9 I7 N, e{
9 e9 i4 }" R$ k% A4 C* u( Q exqueue.data[exqueue.wrptr].time = writetime;) C7 y/ ~, I4 D2 C! ^8 s: a
exqueue.data[exqueue.wrptr].addr = addr;
4 y2 v/ d5 f W) Q: F. y" u exqueue.data[exqueue.wrptr].data = data;
$ |+ C* h) y: l2 i exqueue.wrptr++;
: f& u @+ v1 V) F+ G exqueue.wrptr&=QUEUE_LENGTH-1;" I3 R$ L" W% G
if( exqueue.wrptr == exqueue.rdptr ) {
2 ]2 ~0 g. s- A# M m DEBUGOUT( "exqueue overflow.\n" );
$ h7 _% E8 \! X [7 S+ A/ Q1 ? }! I9 c& a4 v0 }7 f
}
& s* g' X- d8 n+ I% p9 ^
$ ?: M. z! b3 |4 S/ B/ p8 `! EBOOL APU::GetExQueue( INT writetime, QUEUEDATA& ret )
& Y) l! E7 n. x{
, D- ~6 n) G& E* b' } if( exqueue.wrptr == exqueue.rdptr ) {
, i: j% f* @9 S- ~* B4 c- t$ B return FALSE;2 H2 _: {. O2 n2 x" i3 m0 p
}3 \" w7 B) z- ]1 i# R! `" `
if( exqueue.data[exqueue.rdptr].time <= writetime ) {
. [7 k _* p m; H- h ret = exqueue.data[exqueue.rdptr];" o' x' s' s" ~- A0 U/ B$ M
exqueue.rdptr++;& V8 s' _' N- v+ a8 |
exqueue.rdptr&=QUEUE_LENGTH-1;8 N) W7 `4 P1 }5 ~# m4 d4 l
return TRUE;
' k' L0 ^3 O9 s2 g7 f }
$ p1 F) |7 a/ \ X) q0 M3 l2 j return FALSE;
4 V( n$ n9 [, p l* k}! f. T& {5 ]0 J; x7 `5 m
0 M" X) o4 z3 |+ s4 R8 Q! rvoid APU::QueueClear()( r# c' G- j9 `6 F* c+ g
{4 l/ p3 U' B8 h- q+ u# n
ZEROMEMORY( &queue, sizeof(queue) );- d& _6 E5 q7 l9 `; O9 ]; T
ZEROMEMORY( &exqueue, sizeof(exqueue) );
2 ^8 H- D/ \1 ]1 H/ r}; A) h* P8 b8 l$ r$ a
) Z1 ~9 E% U2 r: ~ x l( e& S- @void APU::QueueFlush()
- J% {2 p0 H0 w3 g+ X{
! u% ^0 h3 n) c9 `% x7 c3 o* G while( queue.wrptr != queue.rdptr ) {
9 _& g! |8 k- t# t& Q. {+ T& E B WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
; D: S; h( _. I1 X* U' ] queue.rdptr++;
/ m# I" z0 k8 c, m# H9 I G queue.rdptr&=QUEUE_LENGTH-1;: h+ G3 t! A4 F8 p# l9 E
}
: k) |1 j: z! y# l! |5 V
& {$ G3 a. e$ d! N- ~ while( exqueue.wrptr != exqueue.rdptr ) {, a& f9 |4 Z* K1 A# O( t6 s
WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
2 t" r% L8 X2 l2 x N1 o/ y, T exqueue.rdptr++;
8 }8 W( ^# D3 g$ C# x8 G exqueue.rdptr&=QUEUE_LENGTH-1;' a# d5 t, `" d0 ~1 Z3 {
}
% L3 r( @9 n1 a' \}
5 t+ a0 ?" E J' y. D; p- L! A7 v. \4 y) K: h
void APU::SoundSetup()
$ [6 Y1 s( v% ]{
( N4 K5 j5 W. P$ h% e1 D" z1 u FLOAT fClock = nes->nescfg->CpuClock;' \! B2 e/ e& b H$ s+ G# Z
INT nRate = (INT)Config.sound.nRate;9 f% m: {9 u3 M" M2 V5 l
internal.Setup( fClock, nRate );( J: F! j& h+ U7 P9 v
vrc6.Setup( fClock, nRate );/ E: V' F5 P1 t7 i+ Y
vrc7.Setup( fClock, nRate );, L+ }9 ^$ h& L
mmc5.Setup( fClock, nRate );
* B2 I0 W) w* Z fds.Setup ( fClock, nRate );; l: e# A( d& y, Y
n106.Setup( fClock, nRate );
1 {0 f! g3 O/ f9 @ fme7.Setup( fClock, nRate );% I. Y% z1 j5 C1 D8 c) V
}0 {+ ?- Y& n9 X! R: U; [5 R5 a4 ?
$ X, [) Y. F: |' [! T6 f+ d
void APU::Reset()* e$ C7 W- k! G$ ^. J
{3 w' M9 |( V+ N9 ]9 ?9 ]' z9 j
ZEROMEMORY( &queue, sizeof(queue) );
% }% L5 K: \5 q3 W7 z% k! O5 H2 m; ^ ZEROMEMORY( &exqueue, sizeof(exqueue) );
3 v) }8 D& n, I: C% d8 q, h7 n1 m0 T7 C& h( c. D
elapsed_time = 0;
& C7 q8 a8 B6 Y8 x! L' W x7 f
( N: j9 D3 d' T" J& u8 U* w FLOAT fClock = nes->nescfg->CpuClock;% O0 w9 M; w1 G, T
INT nRate = (INT)Config.sound.nRate;
' F1 _1 Z9 l. A& Y6 k0 | internal.Reset( fClock, nRate );( Z" G3 m# @! `' k' _8 j9 e( @4 D
vrc6.Reset( fClock, nRate );" m0 n/ _, w& Z8 A
vrc7.Reset( fClock, nRate );/ f7 E$ W5 d$ m( o0 v9 f+ M2 h$ B. d$ r' \
mmc5.Reset( fClock, nRate );
( j! A* t$ H8 Z fds.Reset ( fClock, nRate );
6 O3 ~ n/ C% r8 d( F( M4 l( f n106.Reset( fClock, nRate );; b" z- R: m k+ m N8 x% m% \
fme7.Reset( fClock, nRate ); T# V* f$ u# ]' w+ v
7 R1 ~6 i5 P" T SoundSetup();
5 j* C' _& e% S0 k- p}6 [9 q9 [' [$ k2 q1 v
]0 t/ Z% N; y+ v
void APU::SelectExSound( BYTE data )2 v$ e- I% D3 B( k
{8 W* t6 G7 c( P# a1 e# l3 {8 m
exsound_select = data;
. h3 n4 x( v8 j6 R' P6 x4 t3 O}
1 n* M4 q1 H) J1 T& h& y1 D: \4 W5 Y( V( k( X) d8 H/ L
BYTE APU::Read( WORD addr )
8 D/ j$ X8 i' t `{
+ k2 u+ K; Q( P6 r0 T return internal.SyncRead( addr );. S* M. B/ u8 i9 x! x& c+ S
}7 S _! r+ O8 w7 e9 l( q+ M3 H4 o' j
8 `! ?7 `' T1 f3 Rvoid APU::Write( WORD addr, BYTE data )3 g$ `7 C x- L$ X( y: _
{3 _9 p: w# e1 E+ Q% ]- ]
// $4018偼VirtuaNES屌桳億乕僩% \' d/ y) X- S* K* W
if( addr >= 0x4000 && addr <= 0x401F ) {
- } u, S1 F" h$ w& O( C5 K" h internal.SyncWrite( addr, data );
# G( Z8 _: `9 }! K5 N7 x5 }, d+ h SetQueue( nes->cpu->GetTotalCycles(), addr, data );4 m; ]4 l5 ?' [* c
}
\# h6 `4 Y2 @% X6 q: o( F}
# s6 m% Y: U% x7 ^) n7 y4 N2 Y( \( ~$ s& ?
BYTE APU::ExRead( WORD addr )5 p& N6 n: L/ }/ W: d/ T
{
{ F0 i! i! G& zBYTE data = 0;0 q* }! V& Q# I+ f
7 e+ c* \ o' b, V' w if( exsound_select & 0x10 ) {
4 d8 u, r9 u3 Q9 u if( addr == 0x4800 ) {; n& K" N" [- {2 f
SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );- m8 }: a% D a6 K; b8 o* ~1 F" v
}
5 K. a: B. o1 J+ Q* J9 P% ~$ j }
/ V5 V( ^& F3 L" `9 g if( exsound_select & 0x04 ) {& v( l7 m6 x- w# b+ A
if( addr >= 0x4040 && addr < 0x4100 ) {$ k* [7 A, ]) b' R+ P& _
data = fds.SyncRead( addr );
( Y( Q$ E4 h# h# D$ e }
/ z' ^2 N0 j! r8 o }9 `' r7 ~- z$ ?# h) q, I4 S$ M
if( exsound_select & 0x08 ) {
; ^2 b" f% G7 |6 x if( addr >= 0x5000 && addr <= 0x5015 ) {
8 C! S2 g( G& t9 l& j$ ^4 `9 Q i data = mmc5.SyncRead( addr );$ a( \. Y" }4 l( I- v0 }% S$ |
}
3 y) C! }: l o& I0 s' a }4 V( ~6 G q2 O. V! t) ?/ L
# V T" b. I8 B
return data;
# ^+ Q% u. i5 S6 }4 N! l2 ]; e}
. x6 P8 U1 l+ o, d4 O I
/ S& s; H/ O0 I2 k. \$ Hvoid APU::ExWrite( WORD addr, BYTE data )
8 v* E+ ]% S) c. ?5 X{
3 c2 z7 }; m7 S6 l0 |6 Q" T1 ^ SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
" G0 t# t* x: d* k& G; w8 ^7 q0 R% R3 T" ^' E! C' ^5 ^, a |
if( exsound_select & 0x04 ) {3 G1 L: ]! D5 O3 ~
if( addr >= 0x4040 && addr < 0x4100 ) {( q. `4 ^, Y0 P6 ^ v+ _
fds.SyncWrite( addr, data );
+ |2 r8 l( [2 n. u" W: W }$ z( w( v; I: _9 i9 f# _" _* v" h6 G
}, H, k& g: W2 {, L7 p
- X) Y, A% f1 q2 O- f if( exsound_select & 0x08 ) {
% m. W" v2 h( ^# A7 N, ] if( addr >= 0x5000 && addr <= 0x5015 ) {+ f. m/ ~" }. g/ E/ C# ^+ B) B
mmc5.SyncWrite( addr, data );
+ Q4 ^4 ]0 ?* E/ D2 N }: w6 b& g- m: d( ?' {& G( U
}/ w! n$ Z% r9 N; n+ L2 q; }
}
9 W. j$ G) w9 A3 J- y6 L
' X) e2 y8 h$ \/ q! Qvoid APU::Sync()
' m5 m" _4 O7 h/ m. `{
, y# y8 t9 }8 a* H}1 ~ c' X# R2 ?
" ~) u" O; r5 s. y* U) |
void APU::SyncDPCM( INT cycles )$ }2 N) G1 x8 F/ Z% a6 v
{
" {5 g i, M' V0 r internal.Sync( cycles );: F; x$ K( _8 ~6 W& N+ p$ J. \
' X% j8 i+ s9 X, K$ T if( exsound_select & 0x04 ) {
- b- e1 w% M4 W; _/ G3 k: B fds.Sync( cycles );! v% h9 z% `9 x: o2 C) j ?8 ?3 u: ^/ @' b
}
* R, D; o1 ?$ Y) B0 S if( exsound_select & 0x08 ) {
# k5 u) k7 z; t& {: D mmc5.Sync( cycles );
. C _: g5 h) |& R }
% J" W- B$ j8 b) P' E}" f7 H1 d$ p* F5 m% t F
. j* A0 r) D# `- f- ~9 l
void APU::WriteProcess( WORD addr, BYTE data )
1 C5 b" F7 q1 T6 i2 p2 u{; N g0 Z3 Z1 H
// $4018偼VirtuaNES屌桳億乕僩1 }3 } d/ i) }9 n
if( addr >= 0x4000 && addr <= 0x401F ) {
- i( o3 o2 l' t& l' b3 ^ S$ @& ^ internal.Write( addr, data );
' K$ Z2 \2 k! [ }1 c0 h5 T4 r2 h% v- F' p2 C
}! j* u, p1 G c$ e' w
1 h: v! `! M* Z& b, H& Ovoid APU::WriteExProcess( WORD addr, BYTE data )
`& h* F" Z4 H" w7 U- ~( z: d6 n) T{
# o0 G& S: Z3 l( }0 j9 e) A if( exsound_select & 0x01 ) {/ |1 p( c, H/ H8 O) @: _- N
vrc6.Write( addr, data );
( h" I0 ?' M d }
' H. v1 ^, `7 V; g# Z if( exsound_select & 0x02 ) {
$ L, J* o9 l% [6 F: e: u c* X vrc7.Write( addr, data );
9 L8 F; P" ], s8 {# B9 N* x }9 a }1 W2 N/ }2 }. K" h7 K1 D
if( exsound_select & 0x04 ) {$ H& E9 r: X8 \. [4 T
fds.Write( addr, data );
7 s2 u6 i* w# ?8 s8 Q1 s) Z }
0 w! X2 T1 b C! ~4 G" r" c [ if( exsound_select & 0x08 ) {
+ o/ a& O, c# A w mmc5.Write( addr, data );
+ o6 F, c9 h4 k6 K: ]# N/ L9 R# c }
6 ~3 P( G. }" K if( exsound_select & 0x10 ) {8 G/ i! n4 x+ Z2 {; r6 ^
if( addr == 0x0000 ) {! T- Z) Q* H" ?! b
BYTE dummy = n106.Read( addr );. h3 z/ Y5 X4 o( X! B. g' U
} else {
4 w3 z; U1 e' j4 L( U" ~4 T$ ?# B n106.Write( addr, data );
1 r) `+ A+ j3 e& i* }! D$ M+ i }4 d* a' X5 {8 h
}
. ? P# G9 E8 Y9 u f. T% w if( exsound_select & 0x20 ) {! k' a- h5 s. e' C3 r$ H
fme7.Write( addr, data );2 l2 n: `2 }: n
}
' P* f" \5 I4 a: F}1 L1 t# i& \+ \0 {
% L4 I) h8 u/ E# n+ wvoid APU::Process( LPBYTE lpBuffer, DWORD dwSize )
0 z6 }6 ]5 q2 X0 m3 [{! Q2 Q7 D. E( P; F( R7 F. K
INT nBits = Config.sound.nBits;
! f" Z& d6 N. V7 DDWORD dwLength = dwSize / (nBits/8);6 l( X. \) W% f5 T$ o. v
INT output;
4 w" j0 I% f; P9 {0 I/ {" [QUEUEDATA q;, e4 l4 X: Z# W. e8 {' ^
DWORD writetime;3 x& e, D9 _$ n1 H* Y/ L0 J) N
# @2 k# q, `) E: c7 |. bLPSHORT pSoundBuf = m_SoundBuffer;
; @! W# N* t# r3 J& B1 \5 t" bINT nCcount = 0;6 W0 _% G- ?( b( U8 V
4 Y' ^$ l4 g' m/ P9 E( G( u* i
INT nFilterType = Config.sound.nFilterType;
1 `0 H" z4 d# y" f8 B+ r) ~& N, |+ `2 P2 w8 f4 |8 `3 g1 `
if( !Config.sound.bEnable ) {
! q7 g g6 m6 f6 \1 `+ k r* F5 v" c ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );) n9 [0 f( h* J8 R
return;
1 F$ D* p3 I/ F }
: V h, w5 |4 \: D* p! S! N' c8 f: m" D: r* V2 y A, N
// Volume setup( J+ M- s3 g _* P% ?5 K
// 0:Master
/ @; w& j0 ?6 u2 E9 t- u6 W // 1:Rectangle 1
' b0 r) ~# L) x8 @& X // 2:Rectangle 2' f, L1 s, `6 L+ d1 G
// 3:Triangle
. ?5 U4 J6 O2 p // 4:Noise
; N; }, p! {2 f# R, m' X // 5:DPCM. W! s2 \1 T( }) G8 [
// 6:VRC6 E7 N$ S; t. b- k3 `9 [+ t2 m
// 7:VRC7
- L! W( m* ?& v // 8:FDS
7 l! ?& R7 k) u! q // 9:MMC5
$ ^6 K9 o+ |" K6 @) R- L' K // 10:N106
% P. @2 f2 y6 j: t5 y // 11:FME7
+ N) Z7 A7 X8 ?3 k2 E" a INT vol[24];+ X6 t, [; ]. ^) p$ U
BOOL* bMute = m_bMute;& |4 n: V% G# e3 x; u9 C3 ^, Y
SHORT* nVolume = Config.sound.nVolume;
9 d) g+ p; ^* J# c3 N. i6 Z+ i# r( e8 Y+ }9 c8 I
INT nMasterVolume = bMute[0]?nVolume[0]:0; p) m# n& ]4 B9 M$ G' y" x! N
, p! l/ O0 T% V& B( i' x // Internal, k- E" I2 j p* o) A, D
vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;1 X- _, I/ p# l. j1 \; f
vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
* ?$ N, g+ l/ H5 y% Y( R vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;2 }3 \0 R: v1 O
vol[ 3] = bMute[4]?(NOISE_VOL *nVolume[4]*nMasterVolume)/(100*100):0;
& ^0 F# y# o$ i vol[ 4] = bMute[5]?(DPCM_VOL *nVolume[5]*nMasterVolume)/(100*100):0;; q+ O" F8 \- I9 A( X3 x7 J* H
. I+ |3 b& @7 f$ r' P$ k! v" b4 {
// VRC60 n5 \9 I- H% g
vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
; f% o- h& g3 H) N0 F( Y; [0 D vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;+ ~; C0 B% E( X7 L$ P% @3 l! m
vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;) ~& x" Z" x( i$ U
6 U/ V k: ^3 A# M
// VRC7! K: v1 U# g7 j4 C
vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;. R0 Y8 C4 t9 T8 M! `
0 H! R. \# k+ q! |7 Q // FDS3 V6 F- q+ v, M5 v
vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;8 O2 b2 p& K& }' j8 T2 W: o& g- X" K
f7 ` N% \$ W- z7 \ // MMC5
/ j& H# ]8 P$ y: f vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;5 {2 u& S* w. j. O9 Y
vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
- l" Y4 Z; }5 ] vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
! {# K7 \- l0 I2 H
, _' w8 b3 a& r+ i5 p // N106* x6 K5 ~( I( h+ G+ R |! p; X
vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;' |# i! E" o& [5 U
vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 F8 m$ p- {5 W
vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
" f' K" Q5 U: c, V; Y vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 j2 s0 f* M9 o6 C, F/ U# a' p
vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
W0 p! M. L, _( J. X vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 p3 W# T7 l( b1 ~
vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
& _' O7 v& D# k( Z4 h3 g: i vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 w" C4 Y3 y1 ?( \! O* K
1 r2 r& A+ [7 h5 w4 I5 H) w0 O // FME76 X( I' A) |! o' M6 P' W
vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;/ ~8 j9 l. P8 _/ V* c+ \' x, Q
vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
z0 m' ~0 X, |/ {) A$ M* p vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
/ X6 f) M3 m- N
# J7 a, t* R1 b/ R7 i// double cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
! h, {- Q* _: P, R- |3 ? double cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
8 Y: ~" B" A" O
# A/ K9 s! M. l+ C! @$ C) r% M // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
9 Q( s6 q6 ]' G% d4 G/ ~* u! x7 Y if( elapsed_time > nes->cpu->GetTotalCycles() ) {
$ J2 J7 m* @5 v# B QueueFlush();. \3 S+ i" v/ O1 o2 W" D4 u# B
}& u0 f. R/ i9 S; F
" M/ ~: }4 y; l1 X: N. o8 ` while( dwLength-- ) {7 |3 Z* F1 ^9 O' K
writetime = (DWORD)elapsed_time;5 g+ m/ p* G! ]' ]
. I# \9 t8 ~1 a( f
while( GetQueue( writetime, q ) ) {( T+ @& B' N, v! [# p4 y' G
WriteProcess( q.addr, q.data );
. F k9 [2 e% ^1 D! X5 v6 [9 a }5 J" C+ ]2 }& e, `3 k
) P v( f- @7 @ while( GetExQueue( writetime, q ) ) {
8 |3 x4 S# s) c, ^$ I WriteExProcess( q.addr, q.data );* c0 P8 f) O5 z
}
0 O1 W [& d A6 w6 b
5 s4 B! ^+ `9 x& f7 d; A- Q // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
+ X* s1 i! Z# l1 e" G, G output = 0;
/ ` \. _4 ?0 W/ G0 [ output += internal.Process( 0 )*vol[0];
5 E ]( [/ B7 e output += internal.Process( 1 )*vol[1];% \. i' ~( J5 F6 ~) @
output += internal.Process( 2 )*vol[2];
" u3 s' Y! u' }! n9 Z8 R5 ^1 R8 h6 H output += internal.Process( 3 )*vol[3];
9 I6 W1 @# {9 ^* c& l0 f- c/ { output += internal.Process( 4 )*vol[4];+ Z/ t2 O8 U5 A! H- J
- d- }: V0 D5 h
if( exsound_select & 0x01 ) {
9 L/ _, U9 ]' G% D output += vrc6.Process( 0 )*vol[5]; h, L7 h6 o* D5 n9 ~& }
output += vrc6.Process( 1 )*vol[6];* x- [' s5 ?6 |' b
output += vrc6.Process( 2 )*vol[7];* G) {9 a0 W2 J! i; a
}
7 A7 ^- ] t9 p& b b6 q; Z if( exsound_select & 0x02 ) {
$ k# ~% I8 N) j2 V8 f output += vrc7.Process( 0 )*vol[8];) x' }& ^( L, K
}
+ Y! z9 w0 V5 a+ e! `4 u if( exsound_select & 0x04 ) {, O) a* m' }! B' Y
output += fds.Process( 0 )*vol[9];
. w5 s! a. v' B }% T& N! M/ B" j- Y0 v2 ^" Z
if( exsound_select & 0x08 ) {, e3 l4 o: u7 d/ A7 h! u7 C
output += mmc5.Process( 0 )*vol[10];/ Z" a4 g$ n2 | v% ]
output += mmc5.Process( 1 )*vol[11];6 Y' n; K9 M5 O" ^6 n* ^) C
output += mmc5.Process( 2 )*vol[12];+ x8 T" h0 z- o2 N
}# z4 \! }$ r: l0 ?
if( exsound_select & 0x10 ) {
" y6 ^ b. ], a* o( q9 f' u output += n106.Process( 0 )*vol[13];
& h5 R- _) V3 ^8 A: s output += n106.Process( 1 )*vol[14];
8 t8 q1 m6 ?* Z/ k: n output += n106.Process( 2 )*vol[15];0 ^* `" F& H( g' }5 s
output += n106.Process( 3 )*vol[16];
% N) _0 ?* Y6 } output += n106.Process( 4 )*vol[17];
$ ?9 A; z3 @7 W output += n106.Process( 5 )*vol[18];# N5 o3 F/ o; l: |1 F7 {5 k
output += n106.Process( 6 )*vol[19];4 ?, q& n1 o$ ^* W
output += n106.Process( 7 )*vol[20];2 r& N& ^5 P. j3 l6 f
}/ R: ` m8 _* F
if( exsound_select & 0x20 ) {
8 l4 P' S1 N q# g9 x8 w1 O fme7.Process( 3 ); // Envelope & Noise
3 h! K" {% e. [8 m output += fme7.Process( 0 )*vol[21];
; L7 Z4 ]8 T+ m3 [. T1 `$ | output += fme7.Process( 1 )*vol[22];
, [% a# f6 z: Z& z& Q output += fme7.Process( 2 )*vol[23];2 g* \7 n4 s$ x& G- D K
}
+ c! m1 I: `5 c. P T6 |/ ~ _3 c
& ?* H9 I; v3 u3 ~. x output >>= 8;
% ?( V% [- ~! b7 c) F: u. B( U+ {, C$ O( U& z5 o& o
if( nFilterType == 1 ) {% I- q5 O$ V# N, M
//儘乕僷僗僼傿儖僞乕TYPE 1(Simple)& e" g9 j' f: \- a3 {+ ^6 e
output = (lowpass_filter[0]+output)/2;
% ^: c8 r: g- f8 c1 t# w5 H- z lowpass_filter[0] = output;
- {0 P( z% o$ o; ~ N! m. c! a3 _ } else if( nFilterType == 2 ) {
" L7 ^" y% e- R/ G6 a/ k //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
2 K3 v- m- b1 L+ q9 u output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;; L4 q3 f- G" D" ~
lowpass_filter[1] = lowpass_filter[0];% z7 ~; G( J' m5 A% h ^
lowpass_filter[0] = output;
9 _( E$ F1 R) o3 H } else if( nFilterType == 3 ) {: H6 } C6 e( m! l8 B8 L; e/ D- z
//儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
. P% N+ f* Z- f( B/ M1 U" r$ F output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
( H/ Z, J; @6 k+ t- t. C( e lowpass_filter[2] = lowpass_filter[1];
0 F x8 s* V% Y6 v; r lowpass_filter[1] = lowpass_filter[0];. Q. f0 h7 f0 \$ [/ T# v
lowpass_filter[0] = output;
3 x8 F0 y$ G/ B- @ L/ _9 p) u } else if( nFilterType == 4 ) {# K" T: p* g5 o1 ^& @# _
//儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)4 u3 o x& j1 T! k* C
output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
7 Q3 k4 t4 r: J( m lowpass_filter[1] = lowpass_filter[0];
[: U; I4 [+ E; \ lowpass_filter[0] = output;
# L9 r. i3 `" H7 o8 { }
' v/ A) l# u) r/ g3 L. T+ Q# g i4 f# l$ x9 {5 P
#if 0
2 F- s( C2 z8 C7 o/ f // DC惉暘偺僇僢僩4 l* u* U% p( ]8 C
{3 s* ]; k$ c; d
static double ave = 0.0, max=0.0, min=0.0;( e1 t& C: U- ~4 C0 {: v( M
double delta;! ^5 ~: x; Q# M9 O6 e, L W6 i% l
delta = (max-min)/32768.0;
" t) r5 U# b C! I1 \ E max -= delta;
* d" [: [: p6 }; L. i( s! f min += delta;
# i5 h2 X* D) @6 K6 v# _5 t/ J6 \ if( output > max ) max = output;; K' F0 l2 d M6 z5 a
if( output < min ) min = output;
% y6 e' g6 _5 w# i# ? ave -= ave/1024.0;
# Z1 g% _& }/ I# A ave += (max+min)/2048.0;- y3 Y7 W9 n( v
output -= (INT)ave;1 d" ]% a' m2 T4 G
}. W) \3 r* _/ `; h/ L3 `
#endif q7 B' }( o4 I' Z
#if 1
4 Q+ L1 a D) n: E# \+ P; n // DC惉暘偺僇僢僩(HPF TEST)1 w7 ?( C. `. p+ U5 e
{: {' e. B3 ^* H! p; w5 o k, }% N/ x
// static double cutoff = (2.0*3.141592653579*40.0/44100.0);
6 V# \2 t6 [2 Q- g static double cutofftemp = (2.0*3.141592653579*40.0);
0 r, a1 G. B+ M double cutoff = cutofftemp/(double)Config.sound.nRate;
! y+ P* O0 F: K$ q8 X5 h5 D static double tmp = 0.0;' ^$ e( u4 _. I/ E7 @
double in, out;
4 u0 Q3 V; U: D X8 c. L
* s$ r# u" e0 ~" w in = (double)output;
/ K0 h; I- l, U3 L; K out = (in - tmp);
1 n% m# G9 w' I5 O; U tmp = tmp + cutoff * out;
* \# X9 l( u/ M3 u O; M
5 J7 p- \# l6 G O. q' s output = (INT)out;" K4 x- a3 D, J6 k1 x
}
# `, v" r* _/ N& n: T/ J- o9 I$ y#endif
, ?# X) x% r. M; p! Y& U0 \#if 0) X! [0 t1 k2 Q6 O1 q) |+ s
// 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
+ d7 M3 o6 e! ^/ Y9 q- Q% j {
) E( |6 v& b3 ~! f3 }# u INT diff = abs(output-last_data);8 `. _7 `" O% \, W
if( diff > 0x4000 ) {
9 u% ~# _$ n7 P/ f output /= 4;
6 D$ S3 s4 Y2 r4 r$ W- l } else # R2 l% U. p4 T/ f( v$ |
if( diff > 0x3000 ) {
' h4 A% J9 r6 G7 x( R9 C% k/ z output /= 3;
' y: N0 R3 ]; K) |7 l' Q3 z$ r, z } else
. r. e* X1 k! o5 k& s- x* D7 H if( diff > 0x2000 ) {. O( c& O; t/ U$ U
output /= 2;
8 z+ R9 `' y4 Y }1 W$ f7 O, p, B4 C% I. A8 f
last_data = output;
1 h$ g( C$ D$ T. x' S I) T }
3 v2 i1 i% ~& }: D#endif* R4 F, O' J1 ?& n( L
// Limit
$ l( K+ I1 d+ N! S% O6 g+ A if( output > 0x7FFF ) {
1 O, G7 L& i u" o9 k! O output = 0x7FFF;
- x# @- @4 b% ]9 v6 V# f; P } else if( output < -0x8000 ) {
4 c# l2 [0 L1 W4 w7 H' m6 q u output = -0x8000;5 [4 q) o" j* r5 I* J! m$ B: t
}
5 r1 ~# S; w7 t" {7 \: H3 R$ |# `$ ~- C7 A( z
if( nBits != 8 ) {0 b3 i& A$ j8 L9 B2 v
*(SHORT*)lpBuffer = (SHORT)output;% @: @1 W( ] i2 Y, h
lpBuffer += sizeof(SHORT);
' x! B4 ^0 p Y3 w3 D! @ M } else {, H( q: J2 ]1 y! f2 C
*lpBuffer++ = (output>>8)^0x80;
# l8 t' L1 t0 ?& |% V }
! G! l, d9 I+ g. H( Y9 g
( _+ P+ U2 {+ ~: y; s; ~ if( nCcount < 0x0100 )
+ [( c! b+ _5 L% u7 f6 \3 b pSoundBuf[nCcount++] = (SHORT)output;
9 }- g' I+ X" u! l1 f5 ^% J
- ?' Z/ n9 r) J3 Y+ J3 k0 J' I// elapsedtime += cycle_rate;
8 c4 U, n. g) z) ^5 j8 J6 z+ a elapsed_time += cycle_rate;) o ~/ z/ L1 i; G* b( A1 C
}, r! Z4 [+ {) Z5 ?/ H% ^
( j: ?) \( N1 I$ B#if 1 ^, v A" x; r) N$ J5 }
if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {: B# d5 O6 W! A/ U2 d: u
elapsed_time = nes->cpu->GetTotalCycles();
: \9 a2 @3 y0 |- f }2 Z0 K$ K2 s0 A; B. |% l! R4 _
if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
5 y; z8 O" a- q& A+ a elapsed_time = nes->cpu->GetTotalCycles();
2 X0 x* E4 ]% i% A& G( ?: h, g9 B }
" O( n" x: }. D#else& S9 d/ N8 R$ y5 o. j% r O
elapsed_time = nes->cpu->GetTotalCycles();7 C% q& k- e8 l. c5 H+ P5 M
#endif
P7 z d3 x/ `6 L3 ?}
& T( _) h0 I( Y* R8 x. [) h6 V5 L/ }$ f' j; O. l
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)' j8 x0 u3 ~4 @6 N; E- j
INT APU::GetChannelFrequency( INT no )
% V& M2 O+ w/ {! t9 [/ B/ I0 E{
, m- u$ i2 i; e8 i2 R# Y! u0 U if( !m_bMute[0] )
8 @* ^( f& h& M- r1 d- y. F return 0;
; o4 N+ J c: j( k3 @: I8 j7 Q! q- B! }5 z o
// Internal
# K c9 I" D1 K9 O% q; z if( no < 5 ) {$ @5 n& q' I3 v% x; K
return m_bMute[no+1]?internal.GetFreq( no ):0;
5 @# `; p4 S$ k6 [1 X9 A2 {) _ }
/ G3 y' [" I2 f7 ]! h1 W // VRC6
' a6 i) N8 i+ c7 h+ E if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
^' M6 @" w- T$ s6 F9 X return m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
6 t9 m; W+ V H2 [ l( ^8 h) ]: z4 x }+ O% d m$ m3 R: w2 W' ^- V$ v* s! H7 B
// FDS
3 }/ X4 ~3 g5 k [. k if( (exsound_select & 0x04) && no == 0x300 ) {# }, r8 [. ?( d
return m_bMute[6]?fds.GetFreq( 0 ):0;2 t7 }, i" _+ e# ^5 M
}! d- d$ x0 V' M/ ^4 b
// MMC5
2 R+ E) Y. _& \" ?3 q$ l if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
# s/ p/ P( Q+ p1 D7 d4 w7 M return m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;" \ y- S- }" j6 q' a/ V1 R
}
4 d& Z/ v$ D0 o( X" ]( P U // N106
4 _/ L( c% w) J1 o$ w- y0 R if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {1 K6 J. W& ^4 X3 J/ B7 S% Y
return m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;+ x d, ^: }* f# J$ R. K
}
; M# e0 I" i8 A% E- a1 G // FME7! B. B; I0 l7 E3 S8 D! K) N
if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {" A9 K/ P, ^8 Z2 |" F( r4 ~- l4 z( D
return m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
$ z& e; w' ]& b/ { }
8 ?6 o- N) W! s' {, X // VRC7
2 c! x& T4 y1 \$ Y if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
+ l$ Z" Y2 u) ^9 s% w return m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
+ \8 Q. E) S! n6 ]# x1 o: |0 T }
. B3 E# m4 L) O2 n2 S$ t9 B return 0;
8 T7 b; s. p) y9 O: l}3 j! j. [8 j# j; [0 s4 E
7 Z6 W& K% A5 r" T! N/ y5 J
// State Save/Load
) q2 ^1 [- `4 S0 h7 }void APU::SaveState( LPBYTE p )
7 B+ Y1 K/ q+ e9 H{( d4 e" o6 t) B, i
#ifdef _DEBUG
, P: j3 Z0 e( `0 {9 j* s* @$ iLPBYTE pold = p;
, S/ @8 P( `8 A. |, M) ]#endif/ J0 S: H! u' b. y/ m) u0 ?0 q* C1 s4 M
( x# U& c4 B0 R5 I
// 帪娫幉傪摨婜偝偣傞堊Flush偡傞* O5 E/ Q2 }( Y/ T! I7 W
QueueFlush();; { Z2 D! s# b9 e
0 Y, P& Y, s4 y/ V
internal.SaveState( p );+ R, G: B( t% l3 A! u) i
p += (internal.GetStateSize()+15)&(~0x0F); // Padding
$ I) V5 j* V. Y7 P7 `/ S x2 M m ^! T" ~/ e- P
// VRC6
' n# ~& m1 J7 x/ d! j+ n if( exsound_select & 0x01 ) {" H% [, c9 r) `" {
vrc6.SaveState( p );' p2 Z% m. [7 r7 x0 |& R& z# F
p += (vrc6.GetStateSize()+15)&(~0x0F); // Padding
! \% x3 U) S& I0 L$ f; U }
+ b& m& M. E3 B& n1 ?; E/ p; ^ // VRC7 (not support)3 f) ]+ J3 O* a% V, h1 a
if( exsound_select & 0x02 ) {- W, ?: V o- [$ c
vrc7.SaveState( p );
7 r! w* w3 ^5 f% L p += (vrc7.GetStateSize()+15)&(~0x0F); // Padding
2 V" A1 B: i( u }
& [. r+ j7 A& j4 a; ` // FDS
7 r$ [3 F/ f- B2 o+ ?- J if( exsound_select & 0x04 ) {, I* e( O/ z: e, G) a9 f6 w! e# F
fds.SaveState( p );4 D" J' i' s' X0 ?5 ~/ m/ y' Z7 y' Z. Q
p += (fds.GetStateSize()+15)&(~0x0F); // Padding! C" O- c+ p" }7 m$ P( ]% Z7 ~4 Q) a
}
/ a4 a2 L# T( x$ I) w5 ^9 l( O // MMC58 v+ L4 V9 @/ W/ E/ e
if( exsound_select & 0x08 ) {
" ^5 |5 a, x2 g, g' m mmc5.SaveState( p );
, q0 S* e9 f; X4 | p += (mmc5.GetStateSize()+15)&(~0x0F); // Padding
R0 q2 z; t8 q3 i' i+ {+ | }4 F7 R; J# j$ _* G
// N106
- i5 y7 M! i7 h2 B if( exsound_select & 0x10 ) {
1 v! L! ]+ b4 v n106.SaveState( p );, r; p; h0 D/ m# s
p += (n106.GetStateSize()+15)&(~0x0F); // Padding
+ R+ D8 h( U% ] U2 w# X, J0 b }
( h4 W3 ^, p4 E" E" J // FME7; F) S$ y* x) ]2 x [- Q g
if( exsound_select & 0x20 ) {
; n, V4 U f$ c: {2 h- ?: { fme7.SaveState( p );
# q$ t p5 o0 r; V p += (fme7.GetStateSize()+15)&(~0x0F); // Padding
7 R/ g( W% c5 U* k# ` | }- H6 L6 O" ?( d
4 M6 F# G7 h; R. c1 E/ I# ~
#ifdef _DEBUG
8 p6 L' I( Y- EDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
% i( c6 \ m; s+ u: P#endif
$ `: q4 H D5 E/ D! E1 |}4 |% y5 e, b$ ]; ^3 `
$ r& m% b/ Z' I6 Uvoid APU::LoadState( LPBYTE p )
' Q& f) E. t2 y- I{
1 I0 |, g' J! I+ K9 h0 T // 帪娫幉傪摨婜偝偣傞堊偵徚偡
! c& g( P- d2 o2 s7 w+ L ] QueueClear();+ q5 j" s9 [# T' w; `" B
! o5 s! N$ S, G& i/ M internal.LoadState( p );
5 ]9 {# S0 ?% ^# V p += (internal.GetStateSize()+15)&(~0x0F); // Padding T3 X& R/ f6 w
5 d; a A/ H' Y9 t: C // VRC6
) j5 j" N- X2 x: x8 F if( exsound_select & 0x01 ) {
9 T; H: w+ U3 v* b* U vrc6.LoadState( p );
6 Y( {( _) v$ v5 h; ?! X* P: w8 B9 I p += (vrc6.GetStateSize()+15)&(~0x0F); // Padding
; M: F% k% ?7 h" a. O7 d }
' }# _& w% g; N2 y* g3 w // VRC7 (not support)
4 P7 {5 t* }6 K4 U# X" V7 J; N' ? if( exsound_select & 0x02 ) {5 x& Q* {& L5 C F8 J1 w2 i4 S! n
vrc7.LoadState( p );& P$ S1 X3 a: `6 W
p += (vrc7.GetStateSize()+15)&(~0x0F); // Padding+ Y# i4 T/ N% R8 ]4 m4 K/ j
}
4 g' K6 P; S+ [ // FDS
4 Q0 _5 L6 f, o( W7 Q5 R8 N if( exsound_select & 0x04 ) {
) q; k8 n* `# p$ b' H( F. N fds.LoadState( p );4 a6 [/ W. \, e% f6 N0 l8 ?7 j
p += (fds.GetStateSize()+15)&(~0x0F); // Padding
+ ]; `4 ^" F! }( \ }" ~- l) q) ^) w0 g
// MMC5
' X( P( Y' X/ W1 _4 A if( exsound_select & 0x08 ) {9 A4 F' O' }+ y1 c3 P+ d
mmc5.LoadState( p );
) x' Q: G2 e/ m+ e p += (mmc5.GetStateSize()+15)&(~0x0F); // Padding
. g' r1 `6 [! [) N } n) e: g& L- i3 {
// N106 _% A" J$ n$ ]- |8 j
if( exsound_select & 0x10 ) {' Q6 ]+ d- F; \, q( n) \' J
n106.LoadState( p );
* c6 X6 v& o0 h3 N+ O p += (n106.GetStateSize()+15)&(~0x0F); // Padding* L1 Q: U' b* z0 F& M
}. d) |/ _9 T& F9 j' r
// FME76 H! L% E9 V' [6 n6 e; ?& w5 ]
if( exsound_select & 0x20 ) {
$ Y: W5 Q+ g' U4 N$ s2 ^4 Y; X fme7.LoadState( p );) w. t4 r6 E" V1 B8 @: H
p += (fme7.GetStateSize()+15)&(~0x0F); // Padding
0 x7 C. z6 B& m; {0 d( F) Q, b }% p# {- t% p5 L- t% R* J/ Y. b
} |
|