|
|

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