|
|

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