|
|

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