|
|

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