|
|

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