|
|

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