|
|

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