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