|
|

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