|
|

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