|
|

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