|
|

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