|
|

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