|
|

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