|
|

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