|
|

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