|
|

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