|
|

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