|
|

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