|
|

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