|
|

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