|
|

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