|
|

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