|
|

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