|
|

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