|
|

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