|
|

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