|

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