|
|

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