|
|

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