|
|

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