|
|

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