|
|

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