|
|

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