|
|

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