|
|

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