|
|

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