|
|

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