|
|

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