|
|

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