|
|

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