|
|

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