|
|

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