|
|

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