|
|

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