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