|
|

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