|
|

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