|
|

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