|
|

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