|
|

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