|
|

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