|
|

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