|
|

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