|
|

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