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