|
|

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