|
|

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