|
|

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