|
|

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