|
|

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