|
|

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