|
|

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