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