|
|

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