|
|

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