|
|

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