|
|

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