|
|

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