|

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