|
|

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