|
|

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