|
|

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