|
|

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