|
|

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