|

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