|
|

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