|
|

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