|
|

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