|
|

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