|
|

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