|
|

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