|
|

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