|
|

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