|
|

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