|
|

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