|
|

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