|
|

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