|
|

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