|

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