|
|

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