|
|

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