|
|

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