|
|

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