|
|

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