|
|

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