|
|

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