|
|

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