|
|

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