|

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