|

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