|
|

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