|
|

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