|
|

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