|
|

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