|
|

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