|
|

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