|
|

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