|
|

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