|

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