|
|

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