|
|

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