|

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