|
|

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