|
|

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