|
|

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