|
|

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