|
|

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