|
|

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