|
|

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