|
|

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