|
|

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