|
|

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