|
|

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