|
|

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