|
|

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