|
|

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