|
|

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