|
|

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