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