|

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