|
|

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