|
|

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