|
|

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