|
|

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