|
|

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