|
|

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