|

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