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