|
|

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