|
|

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