|
|

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