|
|

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