|
|

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