|
|

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