|
|

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