|
|

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