|
|

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