|
|

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