|
|

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