|
|

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