|
|

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