|
|

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