|
|

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