|
|

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