|
|

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