|
|

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