|

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