|
|

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