|

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