|
|

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