|
|

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