|
|

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