|
|

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