|
|

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