|
|

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