|
|

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