|
|

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