|
|

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