|
|

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