|
|

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