|
|

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