|
|

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