|
|

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