|
|

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