|
|

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