|

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