|
|

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