|
|

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