|

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