|
|

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