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