|
|

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