|
|

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