|
|

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