|
|

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