|
|

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