|
|

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