|
|

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