|
|

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