|
|

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