|

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