|
|

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