|
|

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