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