|
|

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