|
|

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