|
|

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