|
|

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