|
|

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