|
|

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