|
|

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