|
|

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