|
|

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