|
|

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