|
|

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