|
|

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