|
|

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