|
|

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