|
|

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