|
|

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