|
|

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