|

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