|
|

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