|
|

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