|
|

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