|
|

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