|
|

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