|
|

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