|
|

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