|
|

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