|
|

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