|
|

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