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