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