|
|

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