|
|

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