|
|

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