|
|

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