|
|

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