|
|

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