|
|

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