|
|

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