|
|

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