|
|

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