|
|

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