|

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