|
|

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