|
|

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