|
|

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