|
|

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