|
|

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