|

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