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