|
|

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