|
|

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