|
|

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