|
|

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