|
|

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