|
|

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