|
|

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