|
|

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