|
|

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