|
|

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