|
|

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