Updated Game_Music_Emu to latest VGMPlay branch

This commit is contained in:
Chris Moeller 2015-11-27 02:02:41 -08:00
parent 9020667054
commit 09e546591a
342 changed files with 90075 additions and 39784 deletions

File diff suppressed because it is too large Load diff

View file

@ -1,77 +0,0 @@
// Game_Music_Emu $vers. http://www.slack.net/~ant/
#include "C140_Emu.h"
#include "c140.h"
C140_Emu::C140_Emu() { chip = 0; }
C140_Emu::~C140_Emu()
{
if ( chip ) device_stop_c140( chip );
}
int C140_Emu::set_rate( int type, double sample_rate, double clock_rate )
{
if ( chip )
{
device_stop_c140( chip );
chip = 0;
}
chip = device_start_c140( sample_rate, clock_rate, type );
if ( !chip )
return 1;
reset();
return 0;
}
void C140_Emu::reset()
{
device_reset_c140( chip );
c140_set_mute_mask( chip, 0 );
}
void C140_Emu::write( int addr, int data )
{
c140_w( chip, addr, data );
}
void C140_Emu::write_rom( int size, int start, int length, void * data )
{
c140_write_rom( chip, size, start, length, (const UINT8 *) data );
}
void C140_Emu::mute_voices( int mask )
{
c140_set_mute_mask( chip, mask );
}
void C140_Emu::run( int pair_count, sample_t* out )
{
stream_sample_t bufL[ 1024 ];
stream_sample_t bufR[ 1024 ];
stream_sample_t * buffers[2] = { bufL, bufR };
while (pair_count > 0)
{
int todo = pair_count;
if (todo > 1024) todo = 1024;
c140_update( chip, buffers, todo );
for (int i = 0; i < todo; i++)
{
int output_l = bufL [i];
int output_r = bufR [i];
output_l += out [0];
output_r += out [1];
if ( (short)output_l != output_l ) output_l = 0x7FFF ^ ( output_l >> 31 );
if ( (short)output_r != output_r ) output_r = 0x7FFF ^ ( output_r >> 31 );
out [0] = output_l;
out [1] = output_r;
out += 2;
}
pair_count -= todo;
}
}

View file

@ -1,36 +0,0 @@
// C140 sound chip emulator interface
// Game_Music_Emu $vers
#ifndef C140_EMU_H
#define C140_EMU_H
class C140_Emu {
void* chip;
public:
C140_Emu();
~C140_Emu();
// Sets output sample rate and chip clock rates, in Hz. Returns non-zero
// if error.
int set_rate( int type, double sample_rate, double clock_rate );
// Resets to power-up state
void reset();
// Mutes voice n if bit n (1 << n) of mask is set
enum { channel_count = 24 };
void mute_voices( int mask );
// Writes data to addr
void write( int addr, int data );
// Scales ROM size, then writes length bytes from data at start offset
void write_rom( int size, int start, int length, void * data );
// Runs and writes pair_count*2 samples to output
typedef short sample_t;
enum { out_chan_count = 2 }; // stereo
void run( int pair_count, sample_t* out );
};
#endif

View file

@ -1,147 +0,0 @@
// Fir_Resampler chip emulator container that mixes into the output buffer
// Game_Music_Emu $vers
#ifndef CHIP_RESAMPLER_H
#define CHIP_RESAMPLER_H
#include "blargg_source.h"
#include "Fir_Resampler.h"
typedef Fir_Resampler_Norm Chip_Resampler_Downsampler;
int const resampler_extra = 0; //34;
template<class Emu>
class Chip_Resampler_Emu : public Emu {
int last_time;
short* out;
typedef short dsample_t;
enum { disabled_time = -1 };
enum { gain_bits = 14 };
blargg_vector<dsample_t> sample_buf;
int sample_buf_size;
int oversamples_per_frame;
int buf_pos;
int buffered;
int resampler_size;
int gain_;
Chip_Resampler_Downsampler resampler;
void mix_samples( short * buf, int count )
{
dsample_t * inptr = sample_buf.begin();
for ( unsigned i = 0; i < count * 2; i++ )
{
int sample = inptr[i];
sample += buf[i];
if ((short)sample != sample) sample = 0x7FFF ^ (sample >> 31);
buf[i] = sample;
}
}
public:
Chip_Resampler_Emu() { last_time = disabled_time; out = NULL; }
blargg_err_t setup( double oversample, double rolloff, double gain )
{
gain_ = (int) ((1 << gain_bits) * gain);
RETURN_ERR( resampler.set_rate( oversample ) );
return reset_resampler();
}
blargg_err_t reset()
{
Emu::reset();
resampler.clear();
return blargg_ok;
}
blargg_err_t reset_resampler()
{
unsigned int pairs;
double rate = resampler.rate();
if ( rate >= 1.0 ) pairs = 64.0 * rate;
else pairs = 64.0 / rate;
RETURN_ERR( sample_buf.resize( (pairs + (pairs >> 2)) * 2 ) );
resize( pairs );
resampler_size = oversamples_per_frame + (oversamples_per_frame >> 2);
RETURN_ERR( resampler.resize_buffer( resampler_size ) );
return blargg_ok;
}
void resize( int pairs )
{
int new_sample_buf_size = pairs * 2;
//new_sample_buf_size = new_sample_buf_size / 4 * 4; // TODO: needed only for 3:2 downsampler
if ( sample_buf_size != new_sample_buf_size )
{
if ( (unsigned) new_sample_buf_size > sample_buf.size() )
{
check( false );
return;
}
sample_buf_size = new_sample_buf_size;
oversamples_per_frame = int (pairs * resampler.rate()) * 2 + 2;
clear();
}
}
void clear()
{
buf_pos = buffered = 0;
resampler.clear();
}
void enable( bool b = true ) { last_time = b ? 0 : disabled_time; }
bool enabled() const { return last_time != disabled_time; }
void begin_frame( short* buf ) { out = buf; last_time = 0; }
int run_until( int time )
{
int count = time - last_time;
while ( count > 0 )
{
if ( last_time < 0 )
return false;
last_time = time;
if ( buffered )
{
int samples_to_copy = buffered;
if ( samples_to_copy > count ) samples_to_copy = count;
memcpy( out, sample_buf.begin(), samples_to_copy * sizeof(short) * 2 );
memcpy( sample_buf.begin(), sample_buf.begin() + samples_to_copy * 2, ( buffered - samples_to_copy ) * 2 * sizeof(short) );
buffered -= samples_to_copy;
count -= samples_to_copy;
continue;
}
int sample_count = oversamples_per_frame - resampler.written() + resampler_extra;
memset( resampler.buffer(), 0, sample_count * sizeof(*resampler.buffer()) );
Emu::run( sample_count >> 1, resampler.buffer() );
for ( unsigned i = 0; i < sample_count; i++ )
{
dsample_t * ptr = resampler.buffer() + i;
*ptr = ( *ptr * gain_ ) >> gain_bits;
}
short* p = out;
resampler.write( sample_count );
sample_count = resampler.read( sample_buf.begin(), count * 2 > sample_buf_size ? sample_buf_size : count * 2 ) >> 1;
if ( sample_count > count )
{
out += count * Emu::out_chan_count;
mix_samples( p, count );
memmove( sample_buf.begin(), sample_buf.begin() + count * 2, (sample_count - count) * 2 * sizeof(short) );
buffered = sample_count - count;
return true;
}
else if (!sample_count) return true;
out += sample_count * Emu::out_chan_count;
mix_samples( p, sample_count );
count -= sample_count;
}
return true;
}
};
#endif

View file

@ -1,73 +0,0 @@
// Game_Music_Emu $vers. http://www.slack.net/~ant/
#include "K051649_Emu.h"
#include "k051649.h"
K051649_Emu::K051649_Emu() { SCC = 0; }
K051649_Emu::~K051649_Emu()
{
if ( SCC ) device_stop_k051649( SCC );
}
int K051649_Emu::set_rate( int clock_rate )
{
if ( SCC )
{
device_stop_k051649( SCC );
SCC = 0;
}
SCC = device_start_k051649( clock_rate );
if ( !SCC )
return 1;
reset();
return 0;
}
void K051649_Emu::reset()
{
device_reset_k051649( SCC );
k051649_set_mute_mask( SCC, 0 );
}
void K051649_Emu::write( int port, int offset, int data )
{
k051649_w( SCC, (port << 1) | 0x00, offset);
k051649_w( SCC, (port << 1) | 0x01, data);
}
void K051649_Emu::mute_voices( int mask )
{
k051649_set_mute_mask( SCC, mask );
}
void K051649_Emu::run( int pair_count, sample_t* out )
{
stream_sample_t bufL[ 1024 ];
stream_sample_t bufR[ 1024 ];
stream_sample_t * buffers[2] = { bufL, bufR };
while (pair_count > 0)
{
int todo = pair_count;
if (todo > 1024) todo = 1024;
k051649_update( SCC, buffers, todo );
for (int i = 0; i < todo; i++)
{
int output_l = bufL [i];
int output_r = bufR [i];
output_l += out [0];
output_r += out [1];
if ( (short)output_l != output_l ) output_l = 0x7FFF ^ ( output_l >> 31 );
if ( (short)output_r != output_r ) output_r = 0x7FFF ^ ( output_r >> 31 );
out [0] = output_l;
out [1] = output_r;
out += 2;
}
pair_count -= todo;
}
}

View file

@ -1,33 +0,0 @@
// K051649 sound chip emulator interface
// Game_Music_Emu $vers
#ifndef K051649_EMU_H
#define K051649_EMU_H
class K051649_Emu {
void* SCC;
public:
K051649_Emu();
~K051649_Emu();
// Sets output sample rate and chip clock rates, in Hz. Returns non-zero
// if error.
int set_rate( int clock_rate );
// Resets to power-up state
void reset();
// Mutes voice n if bit n (1 << n) of mask is set
enum { channel_count = 5 };
void mute_voices( int mask );
// Writes data to addr
void write( int port, int offset, int data );
// Runs and writes pair_count*2 samples to output
typedef short sample_t;
enum { out_chan_count = 2 }; // stereo
void run( int pair_count, sample_t* out );
};
#endif

View file

@ -1,77 +0,0 @@
// Game_Music_Emu $vers. http://www.slack.net/~ant/
#include "K053260_Emu.h"
#include "k053260.h"
K053260_Emu::K053260_Emu() { chip = 0; }
K053260_Emu::~K053260_Emu()
{
if ( chip ) device_stop_k053260( chip );
}
int K053260_Emu::set_rate( int clock_rate )
{
if ( chip )
{
device_stop_k053260( chip );
chip = 0;
}
chip = device_start_k053260( clock_rate );
if ( !chip )
return 1;
reset();
return 0;
}
void K053260_Emu::reset()
{
device_reset_k053260( chip );
k053260_set_mute_mask( chip, 0 );
}
void K053260_Emu::write( int addr, int data )
{
k053260_w( chip, addr, data);
}
void K053260_Emu::write_rom( int size, int start, int length, void * data )
{
k053260_write_rom( chip, size, start, length, (const UINT8 *) data );
}
void K053260_Emu::mute_voices( int mask )
{
k053260_set_mute_mask( chip, mask );
}
void K053260_Emu::run( int pair_count, sample_t* out )
{
stream_sample_t bufL[ 1024 ];
stream_sample_t bufR[ 1024 ];
stream_sample_t * buffers[2] = { bufL, bufR };
while (pair_count > 0)
{
int todo = pair_count;
if (todo > 1024) todo = 1024;
k053260_update( chip, buffers, todo );
for (int i = 0; i < todo; i++)
{
int output_l = bufL [i];
int output_r = bufR [i];
output_l += out [0];
output_r += out [1];
if ( (short)output_l != output_l ) output_l = 0x7FFF ^ ( output_l >> 31 );
if ( (short)output_r != output_r ) output_r = 0x7FFF ^ ( output_r >> 31 );
out [0] = output_l;
out [1] = output_r;
out += 2;
}
pair_count -= todo;
}
}

View file

@ -1,36 +0,0 @@
// K053260 sound chip emulator interface
// Game_Music_Emu $vers
#ifndef K053260_EMU_H
#define K053260_EMU_H
class K053260_Emu {
void* chip;
public:
K053260_Emu();
~K053260_Emu();
// Sets output sample rate and chip clock rates, in Hz. Returns non-zero
// if error.
int set_rate( int clock_rate );
// Resets to power-up state
void reset();
// Mutes voice n if bit n (1 << n) of mask is set
enum { channel_count = 5 };
void mute_voices( int mask );
// Writes data to addr
void write( int addr, int data );
// Scales ROM size, then writes length bytes from data at start offset
void write_rom( int size, int start, int length, void * data );
// Runs and writes pair_count*2 samples to output
typedef short sample_t;
enum { out_chan_count = 2 }; // stereo
void run( int pair_count, sample_t* out );
};
#endif

View file

@ -1,79 +0,0 @@
// Game_Music_Emu $vers. http://www.slack.net/~ant/
#include "K054539_Emu.h"
#include "k054539.h"
K054539_Emu::K054539_Emu() { chip = 0; }
K054539_Emu::~K054539_Emu()
{
if ( chip ) device_stop_k054539( chip );
}
int K054539_Emu::set_rate( int clock_rate, int flags )
{
if ( chip )
{
device_stop_k054539( chip );
chip = 0;
}
chip = device_start_k054539( clock_rate );
if ( !chip )
return 1;
k054539_init_flags( chip, flags );
reset();
return 0;
}
void K054539_Emu::reset()
{
device_reset_k054539( chip );
k054539_set_mute_mask( chip, 0 );
}
void K054539_Emu::write( int addr, int data )
{
k054539_w( chip, addr, data);
}
void K054539_Emu::write_rom( int size, int start, int length, void * data )
{
k054539_write_rom( chip, size, start, length, (const UINT8 *) data );
}
void K054539_Emu::mute_voices( int mask )
{
k054539_set_mute_mask( chip, mask );
}
void K054539_Emu::run( int pair_count, sample_t* out )
{
stream_sample_t bufL[ 1024 ];
stream_sample_t bufR[ 1024 ];
stream_sample_t * buffers[2] = { bufL, bufR };
while (pair_count > 0)
{
int todo = pair_count;
if (todo > 1024) todo = 1024;
k054539_update( chip, buffers, todo );
for (int i = 0; i < todo; i++)
{
int output_l = bufL [i];
int output_r = bufR [i];
output_l += out [0];
output_r += out [1];
if ( (short)output_l != output_l ) output_l = 0x7FFF ^ ( output_l >> 31 );
if ( (short)output_r != output_r ) output_r = 0x7FFF ^ ( output_r >> 31 );
out [0] = output_l;
out [1] = output_r;
out += 2;
}
pair_count -= todo;
}
}

View file

@ -1,36 +0,0 @@
// K054539 sound chip emulator interface
// Game_Music_Emu $vers
#ifndef K054539_EMU_H
#define K054539_EMU_H
class K054539_Emu {
void* chip;
public:
K054539_Emu();
~K054539_Emu();
// Sets output sample rate and chip clock rates, in Hz. Returns non-zero
// if error.
int set_rate( int clock_rate, int flags );
// Resets to power-up state
void reset();
// Mutes voice n if bit n (1 << n) of mask is set
enum { channel_count = 5 };
void mute_voices( int mask );
// Writes data to addr
void write( int addr, int data );
// Scales ROM size, then writes length bytes from data at start offset
void write_rom( int size, int start, int length, void * data );
// Runs and writes pair_count*2 samples to output
typedef short sample_t;
enum { out_chan_count = 2 }; // stereo
void run( int pair_count, sample_t* out );
};
#endif

View file

@ -220,7 +220,7 @@ void Music_Emu::set_fade( int start_msec, int length_msec )
fade_set = true;
this->length_msec = start_msec;
this->fade_msec = length_msec;
track_filter.set_fade( msec_to_samples( start_msec ),
track_filter.set_fade( start_msec < 0 ? Track_Filter::indefinite_count : msec_to_samples( start_msec ),
length_msec * sample_rate() / (1000 / stereo) );
}

View file

@ -1,10 +1,18 @@
#include "Nes_Vrc7_Apu.h"
#include "ym2413.h"
extern "C" {
#include "../vgmplay/chips/emu2413.h"
}
#include <string.h>
#include "blargg_source.h"
static unsigned char vrc7_inst[(16 + 3) * 8] =
{
#include "../vgmplay/chips/vrc7tone.h"
};
int const period = 36; // NES CPU clocks per FM clock
Nes_Vrc7_Apu::Nes_Vrc7_Apu()
@ -14,7 +22,9 @@ Nes_Vrc7_Apu::Nes_Vrc7_Apu()
blargg_err_t Nes_Vrc7_Apu::init()
{
CHECK_ALLOC( opll = ym2413_init( 3579545, 3579545 / 72, 1 ) );
CHECK_ALLOC( opll = OPLL_new( 3579545, 3579545 / 72 ) );
OPLL_SetChipMode((OPLL *) opll, 1);
OPLL_setPatch((OPLL *) opll, vrc7_inst);
set_output( 0 );
volume( 1.0 );
@ -25,7 +35,7 @@ blargg_err_t Nes_Vrc7_Apu::init()
Nes_Vrc7_Apu::~Nes_Vrc7_Apu()
{
if ( opll )
ym2413_shutdown( opll );
OPLL_delete( (OPLL *) opll );
}
void Nes_Vrc7_Apu::set_output( Blip_Buffer* buf )
@ -71,7 +81,7 @@ void Nes_Vrc7_Apu::reset()
osc.regs [j] = 0;
}
ym2413_reset_chip( opll );
OPLL_reset( (OPLL *) opll );
}
void Nes_Vrc7_Apu::write_reg( int data )
@ -85,11 +95,13 @@ void Nes_Vrc7_Apu::write_data( blip_time_t time, int data )
int chan = addr & 15;
if ( (unsigned) type < 3 && chan < osc_count )
oscs [chan].regs [type] = data;
if ( addr < 0x08 )
inst [addr] = data;
if ( time > next_time )
run_until( time );
ym2413_write( opll, 0, addr );
ym2413_write( opll, 1, data );
OPLL_writeIO( (OPLL *) opll, 0, addr );
OPLL_writeIO( (OPLL *) opll, 1, data );
}
void Nes_Vrc7_Apu::end_frame( blip_time_t time )
@ -117,7 +129,7 @@ void Nes_Vrc7_Apu::save_snapshot( vrc7_snapshot_t* out ) const
for ( int j = 0; j < 3; ++j )
out->regs [i] [j] = oscs [i].regs [j];
}
memcpy( out->inst, ym2413_get_inst0( opll ), 8 );
memcpy( out->inst, inst, 8 );
}
void Nes_Vrc7_Apu::load_snapshot( vrc7_snapshot_t const& in )
@ -134,18 +146,19 @@ void Nes_Vrc7_Apu::load_snapshot( vrc7_snapshot_t const& in )
oscs [i].regs [j] = in.regs [i] [j];
}
memcpy( inst, in.inst, 8 );
for ( i = 0; i < 8; ++i )
{
ym2413_write( opll, 0, i );
ym2413_write( opll, 1, in.inst [i] );
OPLL_writeIO( (OPLL *) opll, 0, i );
OPLL_writeIO( (OPLL *) opll, 1, in.inst [i] );
}
for ( i = 0; i < 3; ++i )
{
for ( int j = 0; j < 6; ++j )
{
ym2413_write( opll, 0, 0x10 + i * 0x10 + j );
ym2413_write( opll, 1, oscs [j].regs [i] );
OPLL_writeIO( (OPLL *) opll, 0, 0x10 + i * 0x10 + j );
OPLL_writeIO( (OPLL *) opll, 1, oscs [j].regs [i] );
}
}
}
@ -157,16 +170,15 @@ void Nes_Vrc7_Apu::run_until( blip_time_t end_time )
blip_time_t time = next_time;
void* opll = this->opll; // cache
Blip_Buffer* const mono_output = mono.output;
e_int32 buffer [2];
e_int32* buffers[2] = {&buffer[0], &buffer[1]};
if ( mono_output )
{
// optimal case
do
{
ym2413_advance_lfo( opll );
int amp = 0;
for ( int i = 0; i < osc_count; i++ )
amp += ym2413_calcch( opll, i );
ym2413_advance( opll );
OPLL_calc_stereo( (OPLL *) opll, buffers, 1, -1 );
int amp = buffer [0] + buffer [1];
int delta = amp - mono.last_amp;
if ( delta )
{
@ -182,13 +194,14 @@ void Nes_Vrc7_Apu::run_until( blip_time_t end_time )
mono.last_amp = 0;
do
{
ym2413_advance_lfo( opll );
OPLL_advance( (OPLL *) opll );
for ( int i = 0; i < osc_count; ++i )
{
Vrc7_Osc& osc = oscs [i];
if ( osc.output )
{
int amp = ym2413_calcch( opll, i );
OPLL_calc_stereo( (OPLL *) opll, buffers, 1, i );
int amp = buffer [0] + buffer [1];
int delta = amp - osc.last_amp;
if ( delta )
{
@ -197,7 +210,6 @@ void Nes_Vrc7_Apu::run_until( blip_time_t end_time )
}
}
}
ym2413_advance( opll );
time += period;
}
while ( time < end_time );

View file

@ -43,6 +43,8 @@ private:
};
Vrc7_Osc oscs [osc_count];
BOOST::uint8_t kon;
BOOST::uint8_t inst [8];
void* opll;
int addr;
blip_time_t next_time;

View file

@ -1,71 +0,0 @@
// Game_Music_Emu $vers. http://www.slack.net/~ant/
#include "Okim6258_Emu.h"
#include "okim6258.h"
Okim6258_Emu::Okim6258_Emu() { chip = 0; }
Okim6258_Emu::~Okim6258_Emu()
{
if ( chip ) device_stop_okim6258( chip );
}
int Okim6258_Emu::set_rate( int clock, int divider, int adpcm_type, int output_12bits )
{
if ( chip )
{
device_stop_okim6258( chip );
chip = 0;
}
chip = device_start_okim6258( clock, divider, adpcm_type, output_12bits );
if ( !chip )
return 0;
reset();
return okim6258_get_vclk( chip );
}
void Okim6258_Emu::reset()
{
device_reset_okim6258( chip );
}
void Okim6258_Emu::write( int addr, int data )
{
okim6258_write( chip, addr, data );
}
int Okim6258_Emu::get_clock()
{
return okim6258_get_vclk( chip );
}
void Okim6258_Emu::run( int pair_count, sample_t* out )
{
stream_sample_t bufL[ 1024 ];
stream_sample_t bufR[ 1024 ];
stream_sample_t * buffers[2] = { bufL, bufR };
while (pair_count > 0)
{
int todo = pair_count;
if (todo > 1024) todo = 1024;
okim6258_update( chip, buffers, todo );
for (int i = 0; i < todo; i++)
{
int output_l = bufL [i];
int output_r = bufR [i];
output_l += out [0];
output_r += out [1];
if ( (short)output_l != output_l ) output_l = 0x7FFF ^ ( output_l >> 31 );
if ( (short)output_r != output_r ) output_r = 0x7FFF ^ ( output_r >> 31 );
out [0] = output_l;
out [1] = output_r;
out += 2;
}
pair_count -= todo;
}
}

View file

@ -1,32 +0,0 @@
// OKIM6258 sound chip emulator interface
// Game_Music_Emu $vers
#ifndef OKIM6258_EMU_H
#define OKIM6258_EMU_H
class Okim6258_Emu {
void* chip;
public:
Okim6258_Emu();
~Okim6258_Emu();
// Sets output sample rate and chip clock rates, in Hz. Returns non-zero
// if error.
int set_rate( int clock, int divider, int adpcm_type, int output_12bits );
// Resets to power-up state
void reset();
// Returns current sample rate of the chip
int get_clock();
// Writes data to addr
void write( int addr, int data );
// Runs and writes pair_count*2 samples to output
typedef short sample_t;
enum { out_chan_count = 2 }; // stereo
void run( int pair_count, sample_t* out );
};
#endif

View file

@ -1,77 +0,0 @@
// Game_Music_Emu $vers. http://www.slack.net/~ant/
#include "Okim6295_Emu.h"
#include "okim6295.h"
Okim6295_Emu::Okim6295_Emu() { chip = 0; }
Okim6295_Emu::~Okim6295_Emu()
{
if ( chip ) device_stop_okim6295( chip );
}
int Okim6295_Emu::set_rate( int clock_rate )
{
if ( chip )
{
device_stop_okim6295( chip );
chip = 0;
}
chip = device_start_okim6295( clock_rate );
if ( !chip )
return 0;
reset();
return (clock_rate & 0x7FFFFFFF) / ((clock_rate & 0x80000000) ? 132 : 165);
}
void Okim6295_Emu::reset()
{
device_reset_okim6295( chip );
okim6295_set_mute_mask( chip, 0 );
}
void Okim6295_Emu::write( int addr, int data )
{
okim6295_w( chip, addr, data );
}
void Okim6295_Emu::write_rom( int size, int start, int length, void * data )
{
okim6295_write_rom( chip, size, start, length, (const UINT8 *) data );
}
void Okim6295_Emu::mute_voices( int mask )
{
okim6295_set_mute_mask( chip, mask );
}
void Okim6295_Emu::run( int pair_count, sample_t* out )
{
stream_sample_t bufL[ 1024 ];
stream_sample_t bufR[ 1024 ];
stream_sample_t * buffers[2] = { bufL, bufR };
while (pair_count > 0)
{
int todo = pair_count;
if (todo > 1024) todo = 1024;
okim6295_update( chip, buffers, todo );
for (int i = 0; i < todo; i++)
{
int output_l = bufL [i];
int output_r = bufR [i];
output_l += out [0];
output_r += out [1];
if ( (short)output_l != output_l ) output_l = 0x7FFF ^ ( output_l >> 31 );
if ( (short)output_r != output_r ) output_r = 0x7FFF ^ ( output_r >> 31 );
out [0] = output_l;
out [1] = output_r;
out += 2;
}
pair_count -= todo;
}
}

View file

@ -1,36 +0,0 @@
// OKIM6295 sound chip emulator interface
// Game_Music_Emu $vers
#ifndef OKIM6295_EMU_H
#define OKIM6295_EMU_H
class Okim6295_Emu {
void* chip;
public:
Okim6295_Emu();
~Okim6295_Emu();
// Sets output sample rate and chip clock rates, in Hz. Returns non-zero
// if error.
int set_rate( int clock_rate );
// Resets to power-up state
void reset();
// Mutes voice n if bit n (1 << n) of mask is set
enum { channel_count = 4 };
void mute_voices( int mask );
// Writes data to addr
void write( int addr, int data );
// Scales ROM size, then writes length bytes from data at start offset
void write_rom( int size, int start, int length, void * data );
// Runs and writes pair_count*2 samples to output
typedef short sample_t;
enum { out_chan_count = 2 }; // stereo
void run( int pair_count, sample_t* out );
};
#endif

View file

@ -2,8 +2,16 @@
#include "blargg_source.h"
#include "ym2413.h"
#include "fmopl.h"
extern "C" {
#include "../vgmplay/chips/mamedef.h"
#include "../vgmplay/chips/emu2413.h"
#include "../vgmplay/chips/fmopl.h"
}
static unsigned char vrc7_inst[(16 + 3) * 8] =
{
#include "../vgmplay/chips/vrc7tone.h"
};
Opl_Apu::Opl_Apu() { opl = 0; opl_memory = 0; }
@ -20,26 +28,29 @@ blargg_err_t Opl_Apu::init( long clock, long rate, blip_time_t period, type_t ty
case type_opll:
case type_msxmusic:
case type_smsfmunit:
opl = ym2413_init( clock, rate, 0 );
opl = OPLL_new( (BOOST::uint32_t) clock, (BOOST::uint32_t) rate );
OPLL_SetChipMode( (OPLL *) opl, 0);
break;
case type_vrc7:
opl = ym2413_init( clock, rate, 1 );
opl = OPLL_new( (BOOST::uint32_t) clock, (BOOST::uint32_t) rate );
OPLL_SetChipMode((OPLL *) opl, 1 );
OPLL_setPatch((OPLL *) opl, vrc7_inst);
break;
case type_opl:
opl = ym3526_init( clock, rate );
opl = ym3526_init( (BOOST::uint32_t) clock, (BOOST::uint32_t) rate );
break;
case type_msxaudio:
//logfile = fopen("c:\\temp\\msxaudio.log", "wb");
opl = y8950_init( clock, rate );
opl = y8950_init( (BOOST::uint32_t) clock, (BOOST::uint32_t) rate );
opl_memory = malloc( 32768 );
y8950_set_delta_t_memory( opl, opl_memory, 32768 );
break;
case type_opl2:
opl = ym3812_init( clock, rate );
opl = ym3812_init( (BOOST::uint32_t) clock, (BOOST::uint32_t) rate );
break;
}
reset();
@ -56,7 +67,7 @@ Opl_Apu::~Opl_Apu()
case type_msxmusic:
case type_smsfmunit:
case type_vrc7:
ym2413_shutdown( opl );
OPLL_delete( (OPLL *) opl );
break;
case type_opl:
@ -88,7 +99,7 @@ void Opl_Apu::reset()
case type_msxmusic:
case type_smsfmunit:
case type_vrc7:
ym2413_reset_chip( opl );
OPLL_reset( (OPLL *) opl );
break;
case type_opl:
@ -114,8 +125,8 @@ void Opl_Apu::write_data( blip_time_t time, int data )
case type_msxmusic:
case type_smsfmunit:
case type_vrc7:
ym2413_write( opl, 0, addr );
ym2413_write( opl, 1, data );
OPLL_writeIO( (OPLL *) opl, 0, addr );
OPLL_writeIO( (OPLL *) opl, 1, data );
break;
case type_opl:
@ -149,7 +160,7 @@ int Opl_Apu::read( blip_time_t time, int port )
case type_msxmusic:
case type_smsfmunit:
case type_vrc7:
return ym2413_read( opl, port );
return port ? 0xFF : 0;
case type_opl:
return ym3526_read( opl, port );
@ -192,15 +203,15 @@ void Opl_Apu::run_until( blip_time_t end_time )
case type_smsfmunit:
case type_vrc7:
{
SAMP bufMO[ 1024 ];
SAMP bufRO[ 1024 ];
SAMP * buffers[2] = { bufMO, bufRO };
e_int32 bufMO[ 1024 ];
e_int32 bufRO[ 1024 ];
e_int32 * buffers[2] = { bufMO, bufRO };
while ( count > 0 )
{
unsigned todo = count;
if ( todo > 1024 ) todo = 1024;
ym2413_update_one( opl, buffers, todo );
OPLL_calc_stereo( (OPLL *) opl, buffers, todo, -1 );
if ( output_ )
{
@ -229,7 +240,9 @@ void Opl_Apu::run_until( blip_time_t end_time )
case type_msxaudio:
case type_opl2:
{
OPLSAMPLE buffer[ 1024 ];
OPLSAMPLE bufL[ 1024 ];
OPLSAMPLE bufR[ 1024 ];
OPLSAMPLE* buffers[2] = {bufL, bufR};
while ( count > 0 )
{
@ -237,9 +250,9 @@ void Opl_Apu::run_until( blip_time_t end_time )
if ( todo > 1024 ) todo = 1024;
switch (type_)
{
case type_opl: ym3526_update_one( opl, buffer, todo ); break;
case type_msxaudio: y8950_update_one( opl, buffer, todo ); break;
case type_opl2: ym3812_update_one( opl, buffer, todo ); break;
case type_opl: ym3526_update_one( opl, buffers, todo ); break;
case type_msxaudio: y8950_update_one( opl, buffers, todo ); break;
case type_opl2: ym3812_update_one( opl, buffers, todo ); break;
default: break;
}
@ -248,7 +261,7 @@ void Opl_Apu::run_until( blip_time_t end_time )
int last_amp = this->last_amp;
for ( unsigned i = 0; i < todo; i++ )
{
int amp = buffer [i];
int amp = bufL [i] + bufR [i];
int delta = amp - last_amp;
if ( delta )
{

View file

@ -1,66 +0,0 @@
// Game_Music_Emu $vers. http://www.slack.net/~ant/
#include "Pwm_Emu.h"
#include "pwm.h"
Pwm_Emu::Pwm_Emu() { chip = 0; }
Pwm_Emu::~Pwm_Emu()
{
if ( chip ) device_stop_pwm( chip );
}
int Pwm_Emu::set_rate( int clock )
{
if ( chip )
{
device_stop_pwm( chip );
chip = 0;
}
chip = device_start_pwm( clock );
if ( !chip )
return 1;
reset();
return 0;
}
void Pwm_Emu::reset()
{
device_reset_pwm( chip );
}
void Pwm_Emu::write( int channel, int data )
{
pwm_chn_w( chip, channel, data );
}
void Pwm_Emu::run( int pair_count, sample_t* out )
{
stream_sample_t bufL[ 1024 ];
stream_sample_t bufR[ 1024 ];
stream_sample_t * buffers[2] = { bufL, bufR };
while (pair_count > 0)
{
int todo = pair_count;
if (todo > 1024) todo = 1024;
pwm_update( chip, buffers, todo );
for (int i = 0; i < todo; i++)
{
int output_l = bufL [i];
int output_r = bufR [i];
output_l += out [0];
output_r += out [1];
if ( (short)output_l != output_l ) output_l = 0x7FFF ^ ( output_l >> 31 );
if ( (short)output_r != output_r ) output_r = 0x7FFF ^ ( output_r >> 31 );
out [0] = output_l;
out [1] = output_r;
out += 2;
}
pair_count -= todo;
}
}

View file

@ -1,33 +0,0 @@
// PWM sound chip emulator interface
// Game_Music_Emu $vers
#ifndef PWM_EMU_H
#define PWM_EMU_H
class Pwm_Emu {
void* chip;
public:
Pwm_Emu();
~Pwm_Emu();
// Sets output sample rate and chip clock rates, in Hz. Returns non-zero
// if error.
int set_rate( int clock );
// Resets to power-up state
void reset();
// Mutes voice n if bit n (1 << n) of mask is set
enum { channel_count = 24 };
void mute_voices( int mask );
// Writes data to channel
void write( int channel, int data );
// Runs and writes pair_count*2 samples to output
typedef short sample_t;
enum { out_chan_count = 2 }; // stereo
void run( int pair_count, sample_t* out );
};
#endif

View file

@ -1,83 +0,0 @@
// Game_Music_Emu $vers. http://www.slack.net/~ant/
#include "Qsound_Apu.h"
#include "qmix.h"
Qsound_Apu::Qsound_Apu() { chip = 0; rom = 0; rom_size = 0; sample_rate = 0; }
Qsound_Apu::~Qsound_Apu()
{
if ( chip ) free( chip );
if ( rom ) free( rom );
}
int Qsound_Apu::set_rate( int clock_rate )
{
if ( chip )
{
free( chip );
chip = 0;
}
chip = malloc( _qmix_get_state_size() );
if ( !chip )
return 0;
reset();
return clock_rate / 166;
}
void Qsound_Apu::set_sample_rate( int sample_rate )
{
this->sample_rate = sample_rate;
if ( chip ) _qmix_set_sample_rate( chip, sample_rate );
}
void Qsound_Apu::reset()
{
_qmix_clear_state( chip );
_qmix_set_sample_rate( chip, sample_rate );
if ( rom ) _qmix_set_sample_rom( chip, rom, rom_size );
}
void Qsound_Apu::write( int addr, int data )
{
_qmix_command( chip, addr, data );
}
void Qsound_Apu::write_rom( int size, int start, int length, void const* data )
{
if ( size > rom_size )
{
rom_size = size;
rom = realloc( rom, size );
}
if ( start > size ) start = size;
if ( start + length > size ) length = size - start;
memcpy( (uint8*)rom + start, data, length );
if ( chip ) _qmix_set_sample_rom( chip, rom, rom_size );
}
void Qsound_Apu::run( int pair_count, sample_t* out )
{
sint16 buf[ 1024 * 2 ];
while (pair_count > 0)
{
int todo = pair_count;
if (todo > 1024) todo = 1024;
_qmix_render( chip, buf, todo );
for (int i = 0; i < todo * 2; i++)
{
int output = buf [i];
output += out [0];
if ( (short)output != output ) output = 0x7FFF ^ ( output >> 31 );
out [0] = output;
out++;
}
pair_count -= todo;
}
}

View file

@ -1,36 +0,0 @@
// Capcom QSound sound chip emulator interface
// Game_Music_Emu $vers
#ifndef QSOUND_APU_H
#define QSOUND_APU_H
class Qsound_Apu {
void* chip;
void* rom;
int rom_size;
int sample_rate;
public:
Qsound_Apu();
~Qsound_Apu();
// Sets output sample rate and chip clock rates, in Hz. Returns non-zero
// if error.
int set_rate( int clock_rate );
void set_sample_rate( int sample_rate );
// Resets to power-up state
void reset();
// Writes data to addr
void write( int addr, int data );
// Scales ROM size, then writes length bytes from data at start offset
void write_rom( int size, int start, int length, void const* data );
// Runs and writes pair_count*2 samples to output
typedef short sample_t;
enum { out_chan_count = 2 }; // stereo
void run( int pair_count, sample_t* out );
};
#endif

View file

@ -1,82 +0,0 @@
// Game_Music_Emu $vers. http://www.slack.net/~ant/
#include "Rf5C164_Emu.h"
#include "scd_pcm.h"
Rf5C164_Emu::Rf5C164_Emu() { chip = 0; }
Rf5C164_Emu::~Rf5C164_Emu()
{
if ( chip ) device_stop_rf5c164( chip );
}
int Rf5C164_Emu::set_rate( int clock )
{
if ( chip )
{
device_stop_rf5c164( chip );
chip = 0;
}
chip = device_start_rf5c164( clock );
if ( !chip )
return 1;
reset();
return 0;
}
void Rf5C164_Emu::reset()
{
device_reset_rf5c164( chip );
rf5c164_set_mute_mask( chip, 0 );
}
void Rf5C164_Emu::write( int addr, int data )
{
rf5c164_w( chip, addr, data );
}
void Rf5C164_Emu::write_mem( int addr, int data )
{
rf5c164_mem_w( chip, addr, data );
}
void Rf5C164_Emu::write_ram( int start, int length, void * data )
{
rf5c164_write_ram( chip, start, length, (const UINT8 *) data );
}
void Rf5C164_Emu::mute_voices( int mask )
{
rf5c164_set_mute_mask( chip, mask );
}
void Rf5C164_Emu::run( int pair_count, sample_t* out )
{
stream_sample_t bufL[ 1024 ];
stream_sample_t bufR[ 1024 ];
stream_sample_t * buffers[2] = { bufL, bufR };
while (pair_count > 0)
{
int todo = pair_count;
if (todo > 1024) todo = 1024;
rf5c164_update( chip, buffers, todo );
for (int i = 0; i < todo; i++)
{
int output_l = bufL [i];
int output_r = bufR [i];
output_l += out [0];
output_r += out [1];
if ( (short)output_l != output_l ) output_l = 0x7FFF ^ ( output_l >> 31 );
if ( (short)output_r != output_r ) output_r = 0x7FFF ^ ( output_r >> 31 );
out [0] = output_l;
out [1] = output_r;
out += 2;
}
pair_count -= todo;
}
}

View file

@ -1,39 +0,0 @@
// RF5C164 sound chip emulator interface
// Game_Music_Emu $vers
#ifndef RF5C164_EMU_H
#define RF5C164_EMU_H
class Rf5C164_Emu {
void* chip;
public:
Rf5C164_Emu();
~Rf5C164_Emu();
// Sets output sample rate and chip clock rates, in Hz. Returns non-zero
// if error.
int set_rate( int clock );
// Resets to power-up state
void reset();
// Mutes voice n if bit n (1 << n) of mask is set
enum { channel_count = 8 };
void mute_voices( int mask );
// Writes data to addr
void write( int addr, int data );
// Writes to memory
void write_mem( int addr, int data );
// Writes length bytes from data at start offset in RAM
void write_ram( int start, int length, void * data );
// Runs and writes pair_count*2 samples to output
typedef short sample_t;
enum { out_chan_count = 2 }; // stereo
void run( int pair_count, sample_t* out );
};
#endif

View file

@ -1,82 +0,0 @@
// Game_Music_Emu $vers. http://www.slack.net/~ant/
#include "Rf5C68_Emu.h"
#include "rf5c68.h"
Rf5C68_Emu::Rf5C68_Emu() { chip = 0; }
Rf5C68_Emu::~Rf5C68_Emu()
{
if ( chip ) device_stop_rf5c68( chip );
}
int Rf5C68_Emu::set_rate()
{
if ( chip )
{
device_stop_rf5c68( chip );
chip = 0;
}
chip = device_start_rf5c68();
if ( !chip )
return 1;
reset();
return 0;
}
void Rf5C68_Emu::reset()
{
device_reset_rf5c68( chip );
rf5c68_set_mute_mask( chip, 0 );
}
void Rf5C68_Emu::write( int addr, int data )
{
rf5c68_w( chip, addr, data );
}
void Rf5C68_Emu::write_mem( int addr, int data )
{
rf5c68_mem_w( chip, addr, data );
}
void Rf5C68_Emu::write_ram( int start, int length, void * data )
{
rf5c68_write_ram( chip, start, length, (const UINT8 *) data );
}
void Rf5C68_Emu::mute_voices( int mask )
{
rf5c68_set_mute_mask( chip, mask );
}
void Rf5C68_Emu::run( int pair_count, sample_t* out )
{
stream_sample_t bufL[ 1024 ];
stream_sample_t bufR[ 1024 ];
stream_sample_t * buffers[2] = { bufL, bufR };
while (pair_count > 0)
{
int todo = pair_count;
if (todo > 1024) todo = 1024;
rf5c68_update( chip, buffers, todo );
for (int i = 0; i < todo; i++)
{
int output_l = bufL [i];
int output_r = bufR [i];
output_l += out [0];
output_r += out [1];
if ( (short)output_l != output_l ) output_l = 0x7FFF ^ ( output_l >> 31 );
if ( (short)output_r != output_r ) output_r = 0x7FFF ^ ( output_r >> 31 );
out [0] = output_l;
out [1] = output_r;
out += 2;
}
pair_count -= todo;
}
}

View file

@ -1,39 +0,0 @@
// RF5C68 sound chip emulator interface
// Game_Music_Emu $vers
#ifndef RF5C68_EMU_H
#define RF5C68_EMU_H
class Rf5C68_Emu {
void* chip;
public:
Rf5C68_Emu();
~Rf5C68_Emu();
// Sets output sample rate and chip clock rates, in Hz. Returns non-zero
// if error.
int set_rate();
// Resets to power-up state
void reset();
// Mutes voice n if bit n (1 << n) of mask is set
enum { channel_count = 8 };
void mute_voices( int mask );
// Writes data to addr
void write( int addr, int data );
// Writes to memory
void write_mem( int addr, int data );
// Writes length bytes from data at start offset in RAM
void write_ram( int start, int length, void * data );
// Runs and writes pair_count*2 samples to output
typedef short sample_t;
enum { out_chan_count = 2 }; // stereo
void run( int pair_count, sample_t* out );
};
#endif

View file

@ -1,77 +0,0 @@
// Game_Music_Emu $vers. http://www.slack.net/~ant/
#include "SegaPcm_Emu.h"
#include "segapcm.h"
SegaPcm_Emu::SegaPcm_Emu() { chip = 0; }
SegaPcm_Emu::~SegaPcm_Emu()
{
if ( chip ) device_stop_segapcm( chip );
}
int SegaPcm_Emu::set_rate( int intf_type )
{
if ( chip )
{
device_stop_segapcm( chip );
chip = 0;
}
chip = device_start_segapcm( intf_type );
if ( !chip )
return 1;
reset();
return 0;
}
void SegaPcm_Emu::reset()
{
device_reset_segapcm( chip );
segapcm_set_mute_mask( chip, 0 );
}
void SegaPcm_Emu::write( int addr, int data )
{
sega_pcm_w( chip, addr, data );
}
void SegaPcm_Emu::write_rom( int size, int start, int length, void * data )
{
sega_pcm_write_rom( chip, size, start, length, (const UINT8 *) data );
}
void SegaPcm_Emu::mute_voices( int mask )
{
segapcm_set_mute_mask( chip, mask );
}
void SegaPcm_Emu::run( int pair_count, sample_t* out )
{
stream_sample_t bufL[ 1024 ];
stream_sample_t bufR[ 1024 ];
stream_sample_t * buffers[2] = { bufL, bufR };
while (pair_count > 0)
{
int todo = pair_count;
if (todo > 1024) todo = 1024;
SEGAPCM_update( chip, buffers, todo );
for (int i = 0; i < todo; i++)
{
int output_l = bufL [i];
int output_r = bufR [i];
output_l += out [0];
output_r += out [1];
if ( (short)output_l != output_l ) output_l = 0x7FFF ^ ( output_l >> 31 );
if ( (short)output_r != output_r ) output_r = 0x7FFF ^ ( output_r >> 31 );
out [0] = output_l;
out [1] = output_r;
out += 2;
}
pair_count -= todo;
}
}

View file

@ -1,36 +0,0 @@
// Sega PCM sound chip emulator interface
// Game_Music_Emu $vers
#ifndef SEGAPCM_EMU_H
#define SEGAPCM_EMU_H
class SegaPcm_Emu {
void* chip;
public:
SegaPcm_Emu();
~SegaPcm_Emu();
// Sets output sample rate and chip clock rates, in Hz. Returns non-zero
// if error.
int set_rate( int intf_type );
// Resets to power-up state
void reset();
// Mutes voice n if bit n (1 << n) of mask is set
enum { channel_count = 16 };
void mute_voices( int mask );
// Writes data to addr
void write( int addr, int data );
// Scales ROM size, then writes length bytes from data at start offset
void write_rom( int size, int start, int length, void * data );
// Runs and writes pair_count*2 samples to output
typedef short sample_t;
enum { out_chan_count = 2 }; // stereo
void run( int pair_count, sample_t* out );
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -5,136 +5,14 @@
#define VGM_CORE_H
#include "Gme_Loader.h"
#include "Ymz280b_Emu.h"
#include "Ymf262_Emu.h"
#include "Ym2612_Emu.h"
#include "Ym2610b_Emu.h"
#include "Ym2608_Emu.h"
#include "Ym3812_Emu.h"
#include "Ym2413_Emu.h"
#include "Ym2151_Emu.h"
#include "C140_Emu.h"
#include "SegaPcm_Emu.h"
#include "Rf5C68_Emu.h"
#include "Rf5C164_Emu.h"
#include "Pwm_Emu.h"
#include "Okim6258_Emu.h"
#include "Okim6295_Emu.h"
#include "K051649_Emu.h"
#include "K053260_Emu.h"
#include "K054539_Emu.h"
#include "Qsound_Apu.h"
#include "Ym2203_Emu.h"
#include "Ay_Apu.h"
#include "Gb_Apu.h"
#include "Hes_Apu.h"
#include "Sms_Apu.h"
#include "Multi_Buffer.h"
#include "Chip_Resampler.h"
template<class Emu>
class Chip_Emu : public Emu {
int last_time;
short* out;
enum { disabled_time = -1 };
public:
Chip_Emu() { last_time = disabled_time; out = NULL; }
void enable( bool b = true ) { last_time = b ? 0 : disabled_time; }
bool enabled() const { return last_time != disabled_time; }
void begin_frame( short* buf ) { out = buf; last_time = 0; }
int run_until( int time )
{
int count = time - last_time;
if ( count > 0 )
{
if ( last_time < 0 )
return false;
last_time = time;
short* p = out;
out += count * Emu::out_chan_count;
Emu::run( count, p );
}
return true;
}
};
#include "../vgmplay/VGMPlay.h"
class Vgm_Core : public Gme_Loader {
public:
typedef VGM_HEADER header_t;
// VGM file header
struct header_t
{
enum { size_min = 0x40 };
enum { size_151 = 0x80 };
enum { size_max = 0xC0 };
char tag [4]; // 0x00
byte data_size [4]; // 0x04
byte version [4]; // 0x08
byte psg_rate [4]; // 0x0C
byte ym2413_rate [4]; // 0x10
byte gd3_offset [4]; // 0x14
byte track_duration [4]; // 0x18
byte loop_offset [4]; // 0x1C
byte loop_duration [4]; // 0x20
byte frame_rate [4]; // 0x24 v1.01 V
byte noise_feedback [2]; // 0x28 v1.10 V
byte noise_width; // 0x2A
byte sn76489_flags; // 0x2B v1.51 <
byte ym2612_rate [4]; // 0x2C v1.10 V
byte ym2151_rate [4]; // 0x30
byte data_offset [4]; // 0x34 v1.50 V
byte segapcm_rate [4]; // 0x38 v1.51 V
byte segapcm_reg [4]; // 0x3C
byte rf5c68_rate [4]; // 0x40
byte ym2203_rate [4]; // 0x44
byte ym2608_rate [4]; // 0x48
byte ym2610_rate [4]; // 0x4C
byte ym3812_rate [4]; // 0x50
byte ym3526_rate [4]; // 0x54
byte y8950_rate [4]; // 0x58
byte ymf262_rate [4]; // 0x5C
byte ymf278b_rate [4]; // 0x60
byte ymf271_rate [4]; // 0x64
byte ymz280b_rate [4]; // 0x68
byte rf5c164_rate [4]; // 0x6C
byte pwm_rate [4]; // 0x70
byte ay8910_rate [4]; // 0x74
byte ay8910_type; // 0x78
byte ay8910_flags; // 0x79
byte ym2203_ay8910_flags;// 0x7A
byte ym2608_ay8910_flags;// 0x7B
byte volume_modifier; // 0x7C v1.60 V
byte reserved; // 0x7D
byte loop_base; // 0x7E
byte loop_modifier; // 0x7F v1.51 <
byte gbdmg_rate [4]; // 0x80 v1.61 V
byte nesapu_rate [4]; // 0x84
byte multipcm_rate [4]; // 0x88
byte upd7759_rate [4]; // 0x8C
byte okim6258_rate [4]; // 0x90
byte okim6258_flags; // 0x94
byte k054539_flags; // 0x95
byte c140_type; // 0x96
byte reserved_flags; // 0x97
byte okim6295_rate [4]; // 0x98
byte k051649_rate [4]; // 0x9C
byte k054539_rate [4]; // 0xA0
byte huc6280_rate [4]; // 0xA4
byte c140_rate [4]; // 0xA8
byte k053260_rate [4]; // 0xAC
byte pokey_rate [4]; // 0xB0
byte qsound_rate [4]; // 0xB4
byte reserved2 [4]; // 0xB8
byte extra_offset [4]; // 0xBC
// True if header has valid file signature
bool valid_tag() const;
int size() const;
void cleanup();
};
// Header for currently loaded file
header_t const& header() const { return _header; }
@ -142,22 +20,6 @@ public:
byte const* file_begin() const { return Gme_Loader::file_begin(); }
byte const* file_end () const { return Gme_Loader::file_end(); }
// If file uses FM, initializes FM sound emulator using *sample_rate. If
// *sample_rate is zero, sets *sample_rate to the proper accurate rate and
// uses that. The output of the FM sound emulator is resampled to the
// final sampling rate.
blargg_err_t init_chips( double* fm_rate, bool reinit = false );
// True if any FM chips are used by file. Always false until init_fm()
// is called.
bool uses_fm() const { return ym2612[0].enabled() || ym2413[0].enabled() || ym2151[0].enabled() || c140.enabled() ||
segapcm.enabled() || rf5c68.enabled() || rf5c164.enabled() || pwm.enabled() || okim6258[0].enabled() || okim6295[0].enabled() ||
k051649.enabled() || k053260.enabled() || k054539.enabled() || ym2203[0].enabled() || ym3812[0].enabled() || ymf262[0].enabled() ||
ymz280b.enabled() || ym2610[0].enabled() || ym2608[0].enabled() || qsound[0].enabled() ||
(header().ay8910_rate[0] | header().ay8910_rate[1] | header().ay8910_rate[2] | header().ay8910_rate[3]) ||
(header().huc6280_rate[0] | header().huc6280_rate[1] | header().huc6280_rate[2] | header().huc6280_rate[3]) ||
(header().gbdmg_rate[0] | header().gbdmg_rate[1] | header().gbdmg_rate[2] | header().gbdmg_rate[3]); }
// Adjusts music tempo, where 1.0 is normal. Can be changed while playing.
// Loading a file resets tempo to 1.0.
void set_tempo( double );
@ -167,77 +29,15 @@ public:
// Starts track
void start_track();
// Runs PSG-only VGM for msec and returns number of clocks it ran for
blip_time_t run_psg( int msec );
// Plays FM for at most count samples into *out, and returns number of
// samples actually generated (always even). Also runs PSG for blip_time.
int play_frame( blip_time_t blip_time, int count, blip_sample_t out [] );
// samples actually generated (always even).
int play_( int count, short out [] );
// True if all of file data has been played
bool track_ended() const { return pos >= file_end(); }
bool track_ended() const { return !!vgmp->VGMEnd; }
// 0 for PSG and YM2612 DAC, 1 for AY, 2 for HuC6280, 3 for GB DMG
Stereo_Buffer stereo_buf[4];
// PCM sound is always generated here
Blip_Buffer * blip_buf[2];
// PSG sound chips, for assigning to Blip_Buffer, and setting volume and EQ
Sms_Apu psg[2];
Ay_Apu ay[2];
Hes_Apu huc6280[2];
Gb_Apu gbdmg[2];
// PCM synth, for setting volume and EQ
Blip_Synth_Fast pcm;
// FM sound chips
Chip_Resampler_Emu<Ymf262_Emu> ymf262[2];
Chip_Resampler_Emu<Ym3812_Emu> ym3812[2];
Chip_Resampler_Emu<Ym2612_Emu> ym2612[2];
Chip_Resampler_Emu<Ym2610b_Emu> ym2610[2];
Chip_Resampler_Emu<Ym2608_Emu> ym2608[2];
Chip_Resampler_Emu<Ym2413_Emu> ym2413[2];
Chip_Resampler_Emu<Ym2151_Emu> ym2151[2];
Chip_Resampler_Emu<Ym2203_Emu> ym2203[2];
// PCM sound chips
Chip_Resampler_Emu<C140_Emu> c140;
Chip_Resampler_Emu<SegaPcm_Emu> segapcm;
Chip_Resampler_Emu<Rf5C68_Emu> rf5c68;
Chip_Resampler_Emu<Rf5C164_Emu> rf5c164;
Chip_Resampler_Emu<Pwm_Emu> pwm;
Chip_Resampler_Emu<Okim6258_Emu> okim6258[2]; int okim6258_hz[2];
Chip_Resampler_Emu<Okim6295_Emu> okim6295[2]; int okim6295_hz;
Chip_Resampler_Emu<K051649_Emu> k051649;
Chip_Resampler_Emu<K053260_Emu> k053260;
Chip_Resampler_Emu<K054539_Emu> k054539;
Chip_Resampler_Emu<Ymz280b_Emu> ymz280b; int ymz280b_hz;
Chip_Resampler_Emu<Qsound_Apu> qsound[2];
// DAC control
typedef struct daccontrol_data
{
bool Enable;
byte Bank;
} DACCTRL_DATA;
byte DacCtrlUsed;
byte DacCtrlUsg[0xFF];
DACCTRL_DATA DacCtrl[0xFF];
byte DacCtrlMap[0xFF];
int DacCtrlTime[0xFF];
void ** dac_control;
void dac_control_grow(byte chip_id);
int dac_control_recursion;
int run_dac_control( int time );
public:
void chip_reg_write(unsigned Sample, byte ChipType, byte ChipID, byte Port, byte Offset, byte Data);
// Skips the specified number of samples
void skip_( int count );
// Implementation
public:
@ -248,106 +48,11 @@ protected:
virtual blargg_err_t load_mem_( byte const [], int );
private:
// blip_time_t // PSG clocks
typedef int vgm_time_t; // 44100 per second, REGARDLESS of sample rate
typedef int fm_time_t; // FM sample count
int sample_rate;
int vgm_rate; // rate of log, 44100 normally, adjusted by tempo
double fm_rate; // FM samples per second
header_t _header;
// VGM to FM time
int fm_time_factor;
int fm_time_offset;
fm_time_t to_fm_time( vgm_time_t ) const;
// VGM to PSG time
int blip_time_factor;
blip_time_t to_psg_time( vgm_time_t ) const;
int blip_ay_time_factor;
int ay_time_offset;
blip_time_t to_ay_time( vgm_time_t ) const;
int blip_huc6280_time_factor;
int huc6280_time_offset;
blip_time_t to_huc6280_time( vgm_time_t ) const;
int blip_gbdmg_time_factor;
int gbdmg_time_offset;
blip_time_t to_gbdmg_time( vgm_time_t ) const;
// Current time and position in log
vgm_time_t vgm_time;
byte const* pos;
byte const* loop_begin;
bool has_looped;
// PCM
enum { PCM_BANK_COUNT = 0x40 };
typedef struct _vgm_pcm_bank_data
{
unsigned DataSize;
byte* Data;
unsigned DataStart;
} VGM_PCM_DATA;
typedef struct _vgm_pcm_bank
{
unsigned BankCount;
VGM_PCM_DATA* Bank;
unsigned DataSize;
byte* Data;
unsigned DataPos;
unsigned BnkPos;
} VGM_PCM_BANK;
typedef struct pcmbank_table
{
byte ComprType;
byte CmpSubType;
byte BitDec;
byte BitCmp;
unsigned EntryCount;
void* Entries;
} PCMBANK_TBL;
VGM_PCM_BANK PCMBank[PCM_BANK_COUNT];
PCMBANK_TBL PCMTbl;
void ReadPCMTable(unsigned DataSize, const byte* Data);
void AddPCMData(byte Type, unsigned DataSize, const byte* Data);
bool DecompressDataBlk(VGM_PCM_DATA* Bank, unsigned DataSize, const byte* Data);
const byte* GetPointerFromPCMBank(byte Type, unsigned DataPos);
byte const* pcm_pos; // current position in PCM data
int dac_amp[2];
int dac_disabled[2]; // -1 if disabled
void write_pcm( vgm_time_t, int chip, int amp );
blip_time_t run( vgm_time_t );
int run_ym2151( int chip, int time );
int run_ym2203( int chip, int time );
int run_ym2413( int chip, int time );
int run_ym2612( int chip, int time );
int run_ym3812( int chip, int time );
int run_ymf262( int chip, int time );
int run_ym2610( int chip, int time );
int run_ym2608( int chip, int time );
int run_ymz280b( int time );
int run_c140( int time );
int run_segapcm( int time );
int run_rf5c68( int time );
int run_rf5c164( int time );
int run_pwm( int time );
int run_okim6258( int chip, int time );
int run_okim6295( int chip, int time );
int run_k051649( int time );
int run_k053260( int time );
int run_k054539( int time );
int run_qsound( int chip, int time );
void update_fm_rates( int* ym2151_rate, int* ym2413_rate, int* ym2612_rate ) const;
VGM_PLAYER* vgmp;
};
#endif

View file

@ -3,6 +3,7 @@
#include "Vgm_Emu.h"
#include "blargg_endian.h"
#include "blargg_common.h"
/* Copyright (C) 2003-2008 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser
@ -24,15 +25,10 @@ double const oversample_factor = 1.5;
Vgm_Emu::Vgm_Emu()
{
resampler.set_callback( play_frame_, this );
disable_oversampling_ = false;
muted_voices = 0;
set_type( gme_vgm_type );
set_max_initial_silence( 1 );
set_silence_lookahead( 1 ); // tracks should already be trimmed
static equalizer_t const eq = { -14.0, 80 , 0,0,0,0,0,0,0,0 };
set_equalizer( eq );
}
Vgm_Emu::~Vgm_Emu() { }
@ -40,7 +36,6 @@ Vgm_Emu::~Vgm_Emu() { }
void Vgm_Emu::unload()
{
core.unload();
Classic_Emu::unload();
}
// Track info
@ -59,33 +54,85 @@ static byte const* skip_gd3_str( byte const in [], byte const* end )
static byte const* get_gd3_str( byte const* in, byte const* end, char field [] )
{
byte const* mid = skip_gd3_str( in, end );
int len = (mid - in) / 2 - 1;
int len = (int)((mid - in) / 2) - 1;
if ( len > 0 )
{
char * in_utf8 = blargg_to_utf8( (blargg_wchar_t *) in );
len = min( len, (int) Gme_File::max_field_ );
field [len] = 0;
for ( int i = 0; i < len; i++ )
field [i] = (in [i * 2 + 1] ? '?' : in [i * 2]); // TODO: convert to utf-8
field [i] = in_utf8 [i];
free(in_utf8);
}
return mid;
}
static byte const* get_gd3_pair( byte const* in, byte const* end, char field [] )
static byte const* get_gd3_pair( byte const* in, byte const* end, char field [], char field_j [] )
{
return skip_gd3_str( get_gd3_str( in, end, field ), end );
return get_gd3_str( get_gd3_str( in, end, field ), end, field_j );
}
static void parse_gd3( byte const in [], byte const* end, track_info_t* out )
static void parse_gd3( byte const in [], byte const* end, track_info_t* out, track_info_t* out_j )
{
in = get_gd3_pair( in, end, out->song );
in = get_gd3_pair( in, end, out->game );
in = get_gd3_pair( in, end, out->system );
in = get_gd3_pair( in, end, out->author );
in = get_gd3_pair( in, end, out->song , out_j->song );
in = get_gd3_pair( in, end, out->game , out_j->game );
in = get_gd3_pair( in, end, out->system , out_j->system );
in = get_gd3_pair( in, end, out->author , out_j->author );
in = get_gd3_str ( in, end, out->copyright );
in = get_gd3_pair( in, end, out->dumper );
in = get_gd3_pair( in, end, out->dumper , out_j->dumper );
in = get_gd3_str ( in, end, out->comment );
}
static blargg_err_t write_gd3_str( gme_writer_t writer, void* your_data, const char field [] )
{
blargg_wchar_t * wstring = blargg_to_wide( field );
if (!wstring)
return "Out of memory";
blargg_err_t err = writer( your_data, wstring, blargg_wcslen( wstring ) * 2 + 2 );
free( wstring );
return err;
}
static blargg_err_t write_gd3_pair( gme_writer_t writer, void* your_data, const char field [], const char field_j [] )
{
RETURN_ERR(write_gd3_str( writer, your_data, field ));
RETURN_ERR(write_gd3_str( writer, your_data, field ));
return blargg_ok;
}
static blargg_err_t write_gd3_strings( gme_writer_t writer, void* your_data, const track_info_t* in, const track_info_t* in_j )
{
RETURN_ERR(write_gd3_pair( writer, your_data, in->song , in_j->song ));
RETURN_ERR(write_gd3_pair( writer, your_data, in->game , in_j->game ));
RETURN_ERR(write_gd3_pair( writer, your_data, in->system , in_j->system ));
RETURN_ERR(write_gd3_pair( writer, your_data, in->author , in_j->author ));
RETURN_ERR(write_gd3_str ( writer, your_data, in->copyright ));
RETURN_ERR(write_gd3_pair( writer, your_data, in->dumper , in_j->dumper ));
RETURN_ERR(write_gd3_str ( writer, your_data, in->comment ));
return blargg_ok;
}
static gme_err_t writer_calc_size(void* param, const void* ptr, long count)
{
*(long *)param += count;
return blargg_ok;
}
static blargg_err_t write_gd3( gme_writer_t writer, void* your_data, const track_info_t* in, const track_info_t* in_j )
{
long string_size = 0;
byte version[4];
RETURN_ERR(writer( your_data, "Gd3 ", 4 ));
set_le32(version, 0x100);
RETURN_ERR(writer( your_data, version, 4 ));
write_gd3_strings( &writer_calc_size, &string_size, in, in_j );
if ( string_size > 1000000000 )
return "GD3 tag too large";
set_le32(version, (int)string_size);
RETURN_ERR(writer( your_data, version, 4));
return write_gd3_strings( writer, your_data, in, in_j );
}
int const gd3_header_size = 12;
static int check_gd3_header( byte const h [], int remain )
@ -102,11 +149,11 @@ static int check_gd3_header( byte const h [], int remain )
static void get_vgm_length( Vgm_Emu::header_t const& h, track_info_t* out )
{
int length = get_le32( h.track_duration ) * 10 / 441; // 1000 / 44100
int length = get_le32( &h.lngTotalSamples ) * 10 / 441; // 1000 / 44100
if ( length > 0 )
{
int loop = get_le32( h.loop_duration );
if ( loop > 0 && get_le32( h.loop_offset ) )
int loop = get_le32( &h.lngLoopSamples );
if ( loop > 0 && get_le32( &h.lngLoopOffset ) )
{
out->loop_length = loop * 10 / 441;
out->intro_length = length - out->loop_length;
@ -124,19 +171,6 @@ static void get_vgm_length( Vgm_Emu::header_t const& h, track_info_t* out )
blargg_err_t Vgm_Emu::track_info_( track_info_t* out, int ) const
{
get_vgm_length( header(), out );
int gd3_offset = get_le32( header().gd3_offset );
if ( gd3_offset <= 0 )
return blargg_ok;
byte const* gd3 = core.file_begin() + gd3_offset + offsetof( header_t, gd3_offset );
int gd3_size = check_gd3_header( gd3, core.file_end() - gd3 );
if ( gd3_size )
{
byte const* gd3_data = gd3 + gd3_header_size;
parse_gd3( gd3_data, gd3_data + gd3_size, out );
}
return blargg_ok;
}
@ -146,12 +180,12 @@ blargg_err_t Vgm_Emu::gd3_data( const unsigned char ** data, int * size )
*data = 0;
*size = 0;
int gd3_offset = get_le32( header().gd3_offset );
int gd3_offset = header().lngGD3Offset;
if ( gd3_offset <= 0 )
return blargg_ok;
byte const* gd3 = core.file_begin() + gd3_offset + offsetof( header_t, gd3_offset );
int gd3_size = check_gd3_header( gd3, core.file_end() - gd3 );
byte const* gd3 = core.file_begin() + gd3_offset;
int gd3_size = check_gd3_header( gd3, (int)(core.file_end() - gd3) );
if ( gd3_size )
{
*data = gd3;
@ -163,149 +197,221 @@ blargg_err_t Vgm_Emu::gd3_data( const unsigned char ** data, int * size )
static void hash_vgm_file( Vgm_Emu::header_t const& h, byte const* data, int data_size, Music_Emu::Hash_Function& out )
{
out.hash_( &h.data_size[0], sizeof(h.data_size) );
out.hash_( &h.version[0], sizeof(h.version) );
out.hash_( &h.psg_rate[0], sizeof(h.psg_rate) );
out.hash_( &h.ym2413_rate[0], sizeof(h.ym2413_rate) );
out.hash_( &h.track_duration[0], sizeof(h.track_duration) );
out.hash_( &h.loop_offset[0], sizeof(h.loop_offset) );
out.hash_( &h.loop_duration[0], sizeof(h.loop_duration) );
out.hash_( &h.frame_rate[0], sizeof(h.frame_rate) );
out.hash_( &h.noise_feedback[0], sizeof(h.noise_feedback) );
out.hash_( &h.noise_width, sizeof(h.noise_width) );
out.hash_( &h.sn76489_flags, sizeof(h.sn76489_flags) );
out.hash_( &h.ym2612_rate[0], sizeof(h.ym2612_rate) );
out.hash_( &h.ym2151_rate[0], sizeof(h.ym2151_rate) );
out.hash_( &h.data_offset[0], sizeof(h.data_offset) );
out.hash_( &h.segapcm_rate[0], sizeof(h.segapcm_rate) );
out.hash_( &h.segapcm_reg[0], sizeof(h.segapcm_reg) );
out.hash_( &h.rf5c68_rate[0], sizeof(h.rf5c68_rate) );
out.hash_( &h.ym2203_rate[0], sizeof(h.ym2203_rate) );
out.hash_( &h.ym2608_rate[0], sizeof(h.ym2608_rate) );
out.hash_( &h.ym2610_rate[0], sizeof(h.ym2610_rate) );
out.hash_( &h.ym3812_rate[0], sizeof(h.ym3812_rate) );
out.hash_( &h.ym3526_rate[0], sizeof(h.ym3526_rate) );
out.hash_( &h.y8950_rate[0], sizeof(h.y8950_rate) );
out.hash_( &h.ymf262_rate[0], sizeof(h.ymf262_rate) );
out.hash_( &h.ymf278b_rate[0], sizeof(h.ymf278b_rate) );
out.hash_( &h.ymf271_rate[0], sizeof(h.ymf271_rate) );
out.hash_( &h.ymz280b_rate[0], sizeof(h.ymz280b_rate) );
out.hash_( &h.rf5c164_rate[0], sizeof(h.rf5c164_rate) );
out.hash_( &h.pwm_rate[0], sizeof(h.pwm_rate) );
out.hash_( &h.ay8910_rate[0], sizeof(h.ay8910_rate) );
out.hash_( &h.ay8910_type, sizeof(h.ay8910_type) );
out.hash_( &h.ay8910_flags, sizeof(h.ay8910_flags) );
out.hash_( &h.ym2203_ay8910_flags, sizeof(h.ym2203_ay8910_flags) );
out.hash_( &h.ym2608_ay8910_flags, sizeof(h.ym2608_ay8910_flags) );
out.hash_( &h.reserved, sizeof(h.reserved) );
out.hash_( &h.gbdmg_rate[0], sizeof(h.gbdmg_rate) );
out.hash_( &h.nesapu_rate[0], sizeof(h.nesapu_rate) );
out.hash_( &h.multipcm_rate[0], sizeof(h.multipcm_rate) );
out.hash_( &h.upd7759_rate[0], sizeof(h.upd7759_rate) );
out.hash_( &h.okim6258_rate[0], sizeof(h.okim6258_rate) );
out.hash_( &h.okim6258_flags, sizeof(h.okim6258_flags) );
out.hash_( &h.k054539_flags, sizeof(h.k054539_flags) );
out.hash_( &h.c140_type, sizeof(h.c140_type) );
out.hash_( &h.reserved_flags, sizeof(h.reserved_flags) );
out.hash_( &h.okim6295_rate[0], sizeof(h.okim6295_rate) );
out.hash_( &h.k051649_rate[0], sizeof(h.k051649_rate) );
out.hash_( &h.k054539_rate[0], sizeof(h.k054539_rate) );
out.hash_( &h.huc6280_rate[0], sizeof(h.huc6280_rate) );
out.hash_( &h.c140_rate[0], sizeof(h.c140_rate) );
out.hash_( &h.k053260_rate[0], sizeof(h.k053260_rate) );
out.hash_( &h.pokey_rate[0], sizeof(h.pokey_rate) );
out.hash_( &h.qsound_rate[0], sizeof(h.qsound_rate) );
out.hash_( &h.reserved2[0], sizeof(h.reserved2) );
out.hash_( &h.extra_offset[0], sizeof(h.extra_offset) );
out.hash_( (const byte *) &h.lngEOFOffset, sizeof(h.lngEOFOffset) );
out.hash_( (const byte *) &h.lngVersion, sizeof(h.lngVersion) );
out.hash_( (const byte *) &h.lngHzPSG, sizeof(h.lngHzPSG) );
out.hash_( (const byte *) &h.lngHzYM2413, sizeof(h.lngHzYM2413) );
out.hash_( (const byte *) &h.lngTotalSamples, sizeof(h.lngTotalSamples) );
out.hash_( (const byte *) &h.lngLoopOffset, sizeof(h.lngLoopOffset) );
out.hash_( (const byte *) &h.lngLoopSamples, sizeof(h.lngLoopSamples) );
out.hash_( (const byte *) &h.lngRate, sizeof(h.lngRate) );
out.hash_( (const byte *) &h.shtPSG_Feedback, sizeof(h.shtPSG_Feedback) );
out.hash_( (const byte *) &h.bytPSG_SRWidth, sizeof(h.bytPSG_SRWidth) );
out.hash_( (const byte *) &h.bytPSG_Flags, sizeof(h.bytPSG_Flags) );
out.hash_( (const byte *) &h.lngHzYM2612, sizeof(h.lngHzYM2612) );
out.hash_( (const byte *) &h.lngHzYM2151, sizeof(h.lngHzYM2151) );
out.hash_( (const byte *) &h.lngDataOffset, sizeof(h.lngDataOffset) );
out.hash_( (const byte *) &h.lngHzSPCM, sizeof(h.lngHzSPCM) );
out.hash_( (const byte *) &h.lngSPCMIntf, sizeof(h.lngSPCMIntf) );
out.hash_( (const byte *) &h.lngHzRF5C68, sizeof(h.lngHzRF5C68) );
out.hash_( (const byte *) &h.lngHzYM2203, sizeof(h.lngHzYM2203) );
out.hash_( (const byte *) &h.lngHzYM2608, sizeof(h.lngHzYM2608) );
out.hash_( (const byte *) &h.lngHzYM2610, sizeof(h.lngHzYM2610) );
out.hash_( (const byte *) &h.lngHzYM3812, sizeof(h.lngHzYM3812) );
out.hash_( (const byte *) &h.lngHzYM3526, sizeof(h.lngHzYM3526) );
out.hash_( (const byte *) &h.lngHzY8950, sizeof(h.lngHzY8950) );
out.hash_( (const byte *) &h.lngHzYMF262, sizeof(h.lngHzYMF262) );
out.hash_( (const byte *) &h.lngHzYMF278B, sizeof(h.lngHzYMF278B) );
out.hash_( (const byte *) &h.lngHzYMF271, sizeof(h.lngHzYMF271) );
out.hash_( (const byte *) &h.lngHzYMZ280B, sizeof(h.lngHzYMZ280B) );
out.hash_( (const byte *) &h.lngHzRF5C164, sizeof(h.lngHzRF5C164) );
out.hash_( (const byte *) &h.lngHzPWM, sizeof(h.lngHzPWM) );
out.hash_( (const byte *) &h.lngHzAY8910, sizeof(h.lngHzAY8910) );
out.hash_( (const byte *) &h.bytAYType, sizeof(h.bytAYType) );
out.hash_( (const byte *) &h.bytAYFlag, sizeof(h.bytAYFlag) );
out.hash_( (const byte *) &h.bytAYFlagYM2203, sizeof(h.bytAYFlagYM2203) );
out.hash_( (const byte *) &h.bytAYFlagYM2608, sizeof(h.bytAYFlagYM2608) );
out.hash_( (const byte *) &h.bytReserved2, sizeof(h.bytReserved2) );
out.hash_( (const byte *) &h.lngHzGBDMG, sizeof(h.lngHzGBDMG) );
out.hash_( (const byte *) &h.lngHzNESAPU, sizeof(h.lngHzNESAPU) );
out.hash_( (const byte *) &h.lngHzMultiPCM, sizeof(h.lngHzMultiPCM) );
out.hash_( (const byte *) &h.lngHzUPD7759, sizeof(h.lngHzUPD7759) );
out.hash_( (const byte *) &h.lngHzOKIM6258, sizeof(h.lngHzOKIM6258) );
out.hash_( (const byte *) &h.bytOKI6258Flags, sizeof(h.bytOKI6258Flags) );
out.hash_( (const byte *) &h.bytK054539Flags, sizeof(h.bytK054539Flags) );
out.hash_( (const byte *) &h.bytC140Type, sizeof(h.bytC140Type) );
out.hash_( (const byte *) &h.bytReservedFlags, sizeof(h.bytReservedFlags) );
out.hash_( (const byte *) &h.lngHzOKIM6295, sizeof(h.lngHzOKIM6295) );
out.hash_( (const byte *) &h.lngHzK051649, sizeof(h.lngHzK051649) );
out.hash_( (const byte *) &h.lngHzK054539, sizeof(h.lngHzK054539) );
out.hash_( (const byte *) &h.lngHzHuC6280, sizeof(h.lngHzHuC6280) );
out.hash_( (const byte *) &h.lngHzC140, sizeof(h.lngHzC140) );
out.hash_( (const byte *) &h.lngHzK053260, sizeof(h.lngHzK053260) );
out.hash_( (const byte *) &h.lngHzPokey, sizeof(h.lngHzPokey) );
out.hash_( (const byte *) &h.lngHzQSound, sizeof(h.lngHzQSound) );
out.hash_( (const byte *) &h.lngHzSCSP, sizeof(h.lngHzSCSP) );
// out.hash_( (const byte *) &h.lngExtraOffset, sizeof(h.lngExtraOffset) );
out.hash_( (const byte *) &h.lngHzWSwan, sizeof(h.lngHzWSwan) );
out.hash_( (const byte *) &h.lngHzVSU, sizeof(h.lngHzVSU) );
out.hash_( (const byte *) &h.lngHzSAA1099, sizeof(h.lngHzSAA1099) );
out.hash_( (const byte *) &h.lngHzES5503, sizeof(h.lngHzES5503) );
out.hash_( (const byte *) &h.lngHzES5506, sizeof(h.lngHzES5506) );
out.hash_( (const byte *) &h.bytES5503Chns, sizeof(h.bytES5503Chns) );
out.hash_( (const byte *) &h.bytES5506Chns, sizeof(h.bytES5506Chns) );
out.hash_( (const byte *) &h.bytC352ClkDiv, sizeof(h.bytC352ClkDiv) );
out.hash_( (const byte *) &h.bytESReserved, sizeof(h.bytESReserved) );
out.hash_( (const byte *) &h.lngHzX1_010, sizeof(h.lngHzX1_010) );
out.hash_( (const byte *) &h.lngHzC352, sizeof(h.lngHzC352) );
out.hash_( (const byte *) &h.lngHzGA20, sizeof(h.lngHzGA20) );
out.hash_( data, data_size );
}
struct VGM_FILE_mem
{
VGM_FILE vf;
const BOOST::uint8_t* buffer;
UINT32 ptr;
UINT32 size;
};
static int VGMF_mem_Read(VGM_FILE* f, void* out, UINT32 count)
{
VGM_FILE_mem* mf = (VGM_FILE_mem *) f;
if (count + mf->ptr > mf->size)
count = mf->size - mf->ptr;
memcpy(out, mf->buffer + mf->ptr, count);
mf->ptr += count;
return count;
}
static int VGMF_mem_Seek(VGM_FILE* f, UINT32 offset)
{
VGM_FILE_mem* mf = (VGM_FILE_mem *) f;
if (offset > mf->size)
offset = mf->size;
mf->ptr = offset;
return 0;
}
static UINT32 VGMF_mem_GetSize(VGM_FILE* f)
{
VGM_FILE_mem* mf = (VGM_FILE_mem *) f;
return mf->size;
}
struct Vgm_File : Gme_Info_
{
Vgm_Emu::header_t h;
blargg_vector<byte> original_header;
blargg_vector<byte> data;
blargg_vector<byte> gd3;
track_info_t metadata;
track_info_t metadata_j;
Vgm_File() { set_type( gme_vgm_type ); }
blargg_err_t load_( Data_Reader& in )
blargg_err_t load_mem_( const byte* in, int file_size )
{
int file_size = in.remain();
if ( file_size <= h.size_min )
VGM_FILE_mem memFile;
memFile.vf.Read = &VGMF_mem_Read;
memFile.vf.Seek = &VGMF_mem_Seek;
memFile.vf.GetSize = &VGMF_mem_GetSize;
memFile.buffer = in;
memFile.ptr = 0;
memFile.size = file_size;
if (!GetVGMFileInfo_Handle((VGM_FILE *) &memFile, &h, 0))
return blargg_err_file_type;
RETURN_ERR( in.read( &h, h.size_min ) );
if ( !h.valid_tag() )
return blargg_err_file_type;
if ( h.size() > h.size_min )
RETURN_ERR( in.read( &h.rf5c68_rate, h.size() - h.size_min ) );
h.cleanup();
int data_offset = get_le32( h.data_offset ) + offsetof( Vgm_Core::header_t, data_offset );
int data_size = file_size - offsetof( Vgm_Core::header_t, data_offset ) - data_offset;
int gd3_offset = get_le32( h.gd3_offset );
if ( gd3_offset > 0 )
gd3_offset += offsetof( Vgm_Core::header_t, gd3_offset );
int amount_to_skip = gd3_offset - h.size();
int data_offset = get_le32( &h.lngDataOffset );
int data_size = file_size - data_offset;
int gd3_offset = get_le32( &h.lngGD3Offset );
if ( gd3_offset > 0 && gd3_offset > data_offset )
{
data_size = gd3_offset - data_offset;
amount_to_skip = 0;
RETURN_ERR( data.resize( data_size ) );
RETURN_ERR( in.skip( data_offset - h.size() ) );
RETURN_ERR( in.read( data.begin(), data_size ) );
memcpy( data.begin(), in + data_offset, data_size );
}
int remain = file_size - gd3_offset;
byte gd3_h [gd3_header_size];
if ( gd3_offset > 0 && remain >= gd3_header_size )
{
RETURN_ERR( in.skip( amount_to_skip ) );
RETURN_ERR( in.read( gd3_h, sizeof gd3_h ) );
memcpy( gd3_h, in + gd3_offset, sizeof gd3_h );
int gd3_size = check_gd3_header( gd3_h, remain );
if ( gd3_size )
{
RETURN_ERR( gd3.resize( gd3_size ) );
RETURN_ERR( in.read( gd3.begin(), gd3.size() ) );
memcpy( gd3.begin(), in + sizeof gd3_h + gd3_offset, gd3.size() );
}
if ( data_offset > gd3_offset )
{
RETURN_ERR( data.resize( data_size ) );
RETURN_ERR( in.skip( data_offset - gd3_offset - sizeof gd3_h - gd3.size() ) );
RETURN_ERR( in.read( data.begin(), data.end() - data.begin() ) );
memcpy( data.begin(), in + data_offset, data_size );
}
}
return blargg_ok;
int header_size = data_offset;
if ( gd3_offset && data_offset > gd3_offset )
header_size = gd3_offset;
RETURN_ERR( original_header.resize( header_size ) );
memcpy( original_header.begin(), in, header_size );
memset( &metadata, 0, sizeof(metadata) );
memset( &metadata_j, 0, sizeof(metadata_j) );
get_vgm_length( h, &metadata );
if ( gd3.size() )
parse_gd3( gd3.begin(), gd3.end(), &metadata, &metadata_j );
return blargg_ok;
}
blargg_err_t track_info_( track_info_t* out, int ) const
{
get_vgm_length( h, out );
if ( gd3.size() )
parse_gd3( gd3.begin(), gd3.end(), out );
*out = metadata;
return blargg_ok;
}
blargg_err_t hash_( Hash_Function& out ) const
{
hash_vgm_file( h, data.begin(), data.end() - data.begin(), out );
hash_vgm_file( h, data.begin(), (int)(data.end() - data.begin()), out );
return blargg_ok;
}
blargg_err_t set_track_info_( const track_info_t* in, int )
{
metadata = *in;
return blargg_ok;
}
blargg_err_t save_( gme_writer_t writer, void* your_data ) const
{
byte buffer[4];
int data_size = (int)(data.end() - data.begin());
int gd3_offset = (int)(original_header.end() - original_header.begin()) + data_size;
RETURN_ERR( writer( your_data, original_header.begin(), 0x14 ) );
set_le32(buffer, gd3_offset - 0x14);
RETURN_ERR( writer( your_data, buffer, 4 ) );
RETURN_ERR( writer( your_data, original_header.begin() + 0x18, original_header.end() - original_header.begin() - 0x18 ) );
RETURN_ERR( writer( your_data, data.begin(), data_size ) );
return write_gd3( writer, your_data, &metadata, &metadata_j );
}
};
static Music_Emu* new_vgm_emu () { return BLARGG_NEW Vgm_Emu ; }
static Music_Emu* new_vgm_file() { return BLARGG_NEW Vgm_File; }
gme_type_t_ const gme_vgm_type [1] = {{ "Sega SMS/Genesis", 1, &new_vgm_emu, &new_vgm_file, "VGM", 1 }};
gme_type_t_ const gme_vgm_type [1] = {{ "Sega SMS/Genesis", 1, &new_vgm_emu, &new_vgm_file, "VGM", 0 }};
gme_type_t_ const gme_vgz_type [1] = {{ "Sega SMS/Genesis", 1, &new_vgm_emu, &new_vgm_file, "VGZ", 1 }};
gme_type_t_ const gme_vgz_type [1] = {{ "Sega SMS/Genesis", 1, &new_vgm_emu, &new_vgm_file, "VGZ", 0 }};
// Setup
@ -316,179 +422,23 @@ void Vgm_Emu::set_tempo_( double t )
blargg_err_t Vgm_Emu::set_sample_rate_( int sample_rate )
{
RETURN_ERR( core.stereo_buf[0].set_sample_rate( sample_rate, 1000 / 30 ) );
RETURN_ERR( core.stereo_buf[1].set_sample_rate( sample_rate, 1000 / 30 ) );
RETURN_ERR( core.stereo_buf[2].set_sample_rate( sample_rate, 1000 / 30 ) );
RETURN_ERR( core.stereo_buf[3].set_sample_rate( sample_rate, 1000 / 30 ) );
core.set_sample_rate(sample_rate);
return Classic_Emu::set_sample_rate_( sample_rate );
}
void Vgm_Emu::update_eq( blip_eq_t const& eq )
{
core.psg[0].treble_eq( eq );
core.psg[1].treble_eq( eq );
core.ay[0].treble_eq( eq );
core.ay[1].treble_eq( eq );
core.huc6280[0].treble_eq( eq );
core.huc6280[1].treble_eq( eq );
core.gbdmg[0].treble_eq( eq );
core.gbdmg[1].treble_eq( eq );
core.pcm.treble_eq( eq );
}
void Vgm_Emu::set_voice( int i, Blip_Buffer* c, Blip_Buffer* l, Blip_Buffer* r )
{
if ( i < core.psg[0].osc_count )
{
core.psg[0].set_output( i, c, l, r );
core.psg[1].set_output( i, c, l, r );
}
return blargg_ok;
}
void Vgm_Emu::mute_voices_( int mask )
{
muted_voices = mask;
Classic_Emu::mute_voices_( mask );
// TODO: what was this for?
//core.pcm.output( &core.blip_buf );
// TODO: silence PCM if FM isn't used?
if ( core.uses_fm() )
{
core.psg[0].set_output( ( mask & 0x80 ) ? 0 : core.stereo_buf[0].center() );
core.psg[1].set_output( ( mask & 0x80 ) ? 0 : core.stereo_buf[0].center() );
core.ay[0].set_output( ( mask & 0x80 ) ? 0 : core.stereo_buf[1].center() );
core.ay[1].set_output( ( mask & 0x80 ) ? 0 : core.stereo_buf[1].center() );
for ( unsigned i = 0, j = 1; i < core.huc6280[0].osc_count; i++, j <<= 1)
{
Blip_Buffer * center = ( mask & j ) ? 0 : core.stereo_buf[2].center();
Blip_Buffer * left = ( mask & j ) ? 0 : core.stereo_buf[2].left();
Blip_Buffer * right = ( mask & j ) ? 0 : core.stereo_buf[2].right();
core.huc6280[0].set_output( i, center, left, right );
core.huc6280[1].set_output( i, center, left, right );
}
for (unsigned i = 0, j = 1; i < core.gbdmg[0].osc_count; i++, j <<= 1)
{
Blip_Buffer * center = (mask & j) ? 0 : core.stereo_buf[3].center();
Blip_Buffer * left = (mask & j) ? 0 : core.stereo_buf[3].left();
Blip_Buffer * right = (mask & j) ? 0 : core.stereo_buf[3].right();
core.gbdmg[0].set_output(i, center, left, right);
core.gbdmg[1].set_output(i, center, left, right);
}
if (core.ym2612[0].enabled())
{
core.pcm.volume( (mask & 0x40) ? 0.0 : 0.1115 / 256 * fm_gain * gain() );
core.ym2612[0].mute_voices( mask );
if ( core.ym2612[1].enabled() )
core.ym2612[1].mute_voices( mask );
}
if ( core.ym2413[0].enabled() )
{
int m = mask & 0x3F;
if ( mask & 0x20 )
m |= 0x01E0; // channels 5-8
if ( mask & 0x40 )
m |= 0x3E00;
core.ym2413[0].mute_voices( m );
if ( core.ym2413[1].enabled() )
core.ym2413[1].mute_voices( m );
}
if ( core.ym2151[0].enabled() )
{
core.ym2151[0].mute_voices( mask );
if ( core.ym2151[1].enabled() )
core.ym2151[1].mute_voices( mask );
}
if ( core.c140.enabled() )
{
int m = 0;
int m_add = 7;
for ( unsigned i = 0; i < 8; i++, m_add <<= 3 )
{
if ( mask & ( 1 << i ) ) m += m_add;
}
core.c140.mute_voices( m );
}
if ( core.rf5c68.enabled() )
{
core.rf5c68.mute_voices( mask );
}
if ( core.rf5c164.enabled() )
{
core.rf5c164.mute_voices( mask );
}
}
}
blargg_err_t Vgm_Emu::load_mem_( byte const data [], int size )
{
RETURN_ERR( core.load_mem( data, size ) );
set_voice_count( core.psg[0].osc_count );
double fm_rate = 0.0;
if ( !disable_oversampling_ )
fm_rate = sample_rate() * oversample_factor;
RETURN_ERR( core.init_chips( &fm_rate ) );
double psg_gain = ( ( core.header().psg_rate[3] & 0xC0 ) == 0x40 ) ? 0.5 : 1.0;
if ( core.uses_fm() )
{
set_voice_count( 8 );
RETURN_ERR( resampler.setup( fm_rate / sample_rate(), rolloff, gain() ) );
RETURN_ERR( resampler.reset( core.stereo_buf[0].length() * sample_rate() / 1000 ) );
core.psg[0].volume( 0.135 * fm_gain * psg_gain * gain() );
core.psg[1].volume( 0.135 * fm_gain * psg_gain * gain() );
core.ay[0].volume( 0.135 * fm_gain * gain() );
core.ay[1].volume( 0.135 * fm_gain * gain() );
core.huc6280[0].volume( 0.135 * fm_gain * gain() );
core.huc6280[1].volume( 0.135 * fm_gain * gain() );
core.gbdmg[0].volume( 0.135 * fm_gain * gain() );
core.gbdmg[1].volume( 0.135 * fm_gain * gain() );
}
else
{
core.psg[0].volume( psg_gain * gain() );
core.psg[1].volume( psg_gain * gain() );
}
static const char* const fm_names [] = {
"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "PCM", "PSG"
};
static const char* const psg_names [] = { "Square 1", "Square 2", "Square 3", "Noise" };
set_voice_names( core.uses_fm() ? fm_names : psg_names );
static int const types [8] = {
wave_type+1, wave_type+2, wave_type+3, noise_type+1,
0, 0, 0, 0
};
set_voice_types( types );
return Classic_Emu::setup_buffer( core.stereo_buf[0].center()->clock_rate() );
}
// Emulation
blargg_err_t Vgm_Emu::start_track_( int track )
{
RETURN_ERR( Classic_Emu::start_track_( track ) );
core.start_track();
mute_voices_(muted_voices);
if ( core.uses_fm() )
resampler.clear();
return blargg_ok;
}
@ -498,54 +448,86 @@ inline void Vgm_Emu::check_end()
set_track_ended();
}
inline void Vgm_Emu::check_warning()
{
const char* w = core.warning();
if ( w )
set_warning( w );
}
blargg_err_t Vgm_Emu::run_clocks( blip_time_t& time_io, int msec )
{
check_end();
time_io = core.run_psg( msec );
check_warning();
return blargg_ok;
}
inline int Vgm_Emu::play_frame( blip_time_t blip_time, int sample_count, sample_t buf [] )
{
check_end();
int result = core.play_frame( blip_time, sample_count, buf );
check_warning();
return result;
}
int Vgm_Emu::play_frame_( void* p, blip_time_t a, int b, sample_t c [] )
{
return STATIC_CAST(Vgm_Emu*,p)->play_frame( a, b, c );
}
blargg_err_t Vgm_Emu::play_( int count, sample_t out [] )
{
if ( !core.uses_fm() )
return Classic_Emu::play_( count, out );
Stereo_Buffer * secondaries[] = { &core.stereo_buf[1], &core.stereo_buf[2], &core.stereo_buf[3] };
resampler.dual_play( count, out, core.stereo_buf[0], secondaries, 3 );
return blargg_ok;
core.play_(count, out);
check_end();
return blargg_ok;
}
blargg_err_t Vgm_Emu::hash_( Hash_Function& out ) const
{
byte const* p = file_begin() + header().size();
byte const* p = file_begin();
byte const* e = file_end();
int data_offset = get_le32( header().data_offset );
int data_offset = header().lngDataOffset;
if ( data_offset )
p += data_offset + offsetof( header_t, data_offset ) - header().size();
int gd3_offset = get_le32( header().gd3_offset );
if ( gd3_offset > 0 && gd3_offset + offsetof( header_t, gd3_offset ) > data_offset + offsetof( header_t, data_offset ) )
e = file_begin() + gd3_offset + offsetof( header_t, gd3_offset );
hash_vgm_file( header(), p, e - p, out );
p += data_offset;
int gd3_offset = header().lngGD3Offset;
if ( gd3_offset > 0 && gd3_offset > data_offset )
e = file_begin() + gd3_offset;
hash_vgm_file( header(), p, (int)(e - p), out );
return blargg_ok;
}
blargg_err_t Vgm_Emu::load_mem_( const byte* in, int file_size )
{
RETURN_ERR( core.load_mem(in, file_size) );
get_vgm_length( header(), &metadata );
int data_offset = header().lngDataOffset;
int gd3_offset = header().lngGD3Offset;
int data_size = file_size - data_offset;
if (gd3_offset > 0)
{
if (gd3_offset > data_offset)
data_size = gd3_offset - data_offset;
byte const* gd3 = core.file_begin() + gd3_offset;
int gd3_size = check_gd3_header( gd3, (int)(core.file_end() - gd3) );
if ( gd3_size )
{
byte const* gd3_data = gd3 + gd3_header_size;
parse_gd3( gd3_data, gd3_data + gd3_size, &metadata, &metadata_j );
}
}
int header_size = data_offset;
if ( gd3_offset && data_offset > gd3_offset )
header_size = gd3_offset;
RETURN_ERR( original_header.resize( header_size ) );
memcpy( original_header.begin(), in, header_size );
RETURN_ERR( data.resize(data_size) );
memcpy( data.begin(), in + data_offset, data_size );
return blargg_ok;
}
blargg_err_t Vgm_Emu::skip_( int count )
{
core.skip_(count);
return blargg_ok;
}
blargg_err_t Vgm_Emu::set_track_info_( const track_info_t* in, int )
{
metadata = *in;
return blargg_ok;
}
blargg_err_t Vgm_Emu::save_(gme_writer_t writer, void* your_data)
{
byte buffer[4];
int data_size = (int)(data.end() - data.begin());
int gd3_offset = (int)(original_header.end() - original_header.begin()) + data_size;
RETURN_ERR( writer( your_data, original_header.begin(), 0x14 ) );
set_le32(buffer, gd3_offset - 0x14);
RETURN_ERR( writer( your_data, buffer, 4 ) );
RETURN_ERR( writer( your_data, original_header.begin() + 0x18, original_header.end() - original_header.begin() - 0x18 ) );
RETURN_ERR( writer( your_data, data.begin(), data_size ) );
return write_gd3( writer, your_data, &metadata, &metadata_j );
}

View file

@ -12,17 +12,9 @@
Supports custom sound buffer and frequency equalization when VGM uses just the PSG. FM
sound chips can be run at their proper rates, or slightly higher to reduce aliasing on
high notes. A YM2413 is supported but not provided separately from the library. */
class Vgm_Emu : public Classic_Emu {
class Vgm_Emu : public Music_Emu {
public:
// True if custom buffer and custom equalization are supported
// TODO: move into Music_Emu and rename to something like supports_custom_buffer()
bool is_classic_emu() const { return !core.uses_fm(); }
// Disables running FM chips at higher than normal rate. Will result in slightly
// more aliasing of high notes.
void disable_oversampling( bool disable = true ) { disable_oversampling_ = disable; }
// VGM file header (see Vgm_Core.h)
typedef Vgm_Core::header_t header_t;
@ -43,27 +35,27 @@ public:
protected:
blargg_err_t track_info_( track_info_t*, int track ) const;
blargg_err_t set_track_info_( const track_info_t*, int track );
blargg_err_t load_mem_( byte const [], int );
blargg_err_t set_sample_rate_( int sample_rate );
blargg_err_t start_track_( int );
blargg_err_t play_( int count, sample_t []);
blargg_err_t run_clocks( blip_time_t&, int );
blargg_err_t skip_( int count );
blargg_err_t save_( gme_writer_t, void* );
virtual void set_tempo_( double );
virtual void mute_voices_( int mask );
virtual void set_voice( int, Blip_Buffer*, Blip_Buffer*, Blip_Buffer* );
virtual void update_eq( blip_eq_t const& );
virtual void unload();
private:
bool disable_oversampling_;
unsigned muted_voices;
Dual_Resampler resampler;
Vgm_Core core;
blargg_vector<byte> original_header;
blargg_vector<byte> data;
track_info_t metadata;
track_info_t metadata_j;
void check_end();
void check_warning();
int play_frame( blip_time_t blip_time, int sample_count, sample_t buf [] );
static int play_frame_( void*, blip_time_t, int, sample_t [] );
};
#endif

View file

@ -1,75 +0,0 @@
// Game_Music_Emu $vers. http://www.slack.net/~ant/
#include "Ym2151_Emu.h"
#include "ym2151.h"
Ym2151_Emu::Ym2151_Emu() { PSG = 0; }
Ym2151_Emu::~Ym2151_Emu()
{
if ( PSG ) ym2151_shutdown( PSG );
}
int Ym2151_Emu::set_rate( double sample_rate, double clock_rate )
{
if ( PSG )
{
ym2151_shutdown( PSG );
PSG = 0;
}
PSG = ym2151_init( clock_rate, sample_rate );
if ( !PSG )
return 1;
reset();
return 0;
}
void Ym2151_Emu::reset()
{
ym2151_reset_chip( PSG );
ym2151_set_mask( PSG, 0 );
}
static stream_sample_t* DUMMYBUF[0x02] = {(stream_sample_t*)NULL, (stream_sample_t*)NULL};
void Ym2151_Emu::write( int addr, int data )
{
ym2151_update_one( PSG, DUMMYBUF, 0 );
ym2151_write_reg( PSG, addr, data );
}
void Ym2151_Emu::mute_voices( int mask )
{
ym2151_set_mask( PSG, mask );
}
void Ym2151_Emu::run( int pair_count, sample_t* out )
{
SAMP bufL[ 1024 ];
SAMP bufR[ 1024 ];
SAMP * buffers[2] = { bufL, bufR };
while (pair_count > 0)
{
int todo = pair_count;
if (todo > 1024) todo = 1024;
ym2151_update_one( PSG, buffers, todo );
for (int i = 0; i < todo; i++)
{
int output_l = bufL [i];
int output_r = bufR [i];
output_l += out [0];
output_r += out [1];
if ( (short)output_l != output_l ) output_l = 0x7FFF ^ ( output_l >> 31 );
if ( (short)output_r != output_r ) output_r = 0x7FFF ^ ( output_r >> 31 );
out [0] = output_l;
out [1] = output_r;
out += 2;
}
pair_count -= todo;
}
}

View file

@ -1,33 +0,0 @@
// YM2151 FM sound chip emulator interface
// Game_Music_Emu $vers
#ifndef YM2151_EMU_H
#define YM2151_EMU_H
class Ym2151_Emu {
void* PSG;
public:
Ym2151_Emu();
~Ym2151_Emu();
// Sets output sample rate and chip clock rates, in Hz. Returns non-zero
// if error.
int set_rate( double sample_rate, double clock_rate );
// Resets to power-up state
void reset();
// Mutes voice n if bit n (1 << n) of mask is set
enum { channel_count = 8 };
void mute_voices( int mask );
// Writes data to addr
void write( int addr, int data );
// Runs and writes pair_count*2 samples to output
typedef short sample_t;
enum { out_chan_count = 2 }; // stereo
void run( int pair_count, sample_t* out );
};
#endif

View file

@ -1,155 +0,0 @@
// Game_Music_Emu $vers. http://www.slack.net/~ant/
#include "Ym2203_Emu.h"
#include "fm.h"
#include <string.h>
static void psg_set_clock(void *param, int clock)
{
Ym2203_Emu *info = (Ym2203_Emu *)param;
info->psg_set_clock( clock );
}
static void psg_write(void *param, int address, int data)
{
Ym2203_Emu *info = (Ym2203_Emu *)param;
info->psg_write( address, data );
}
static int psg_read(void *param)
{
Ym2203_Emu *info = (Ym2203_Emu *)param;
return info->psg_read();
}
static void psg_reset(void *param)
{
Ym2203_Emu *info = (Ym2203_Emu *)param;
info->psg_reset();
}
static const ssg_callbacks psgintf =
{
psg_set_clock,
psg_write,
psg_read,
psg_reset
};
Ym2203_Emu::Ym2203_Emu() { opn = 0; psg.set_type( Ay_Apu::Ym2203 ); }
Ym2203_Emu::~Ym2203_Emu()
{
if ( opn ) ym2203_shutdown( opn );
}
int Ym2203_Emu::set_rate( int sample_rate, int clock_rate )
{
if ( opn )
{
ym2203_shutdown( opn );
opn = 0;
}
opn = ym2203_init( this, clock_rate, sample_rate, &psgintf );
if ( !opn )
return 1;
this->sample_rate = sample_rate;
psg_clock = clock_rate * 2;
buffer.set_sample_rate( sample_rate );
buffer.clock_rate( psg_clock );
psg.volume( 1.0 );
reset();
return 0;
}
void Ym2203_Emu::reset()
{
psg.reset();
ym2203_reset_chip( opn );
mute_voices( 0 );
}
static stream_sample_t* DUMMYBUF[0x02] = {(stream_sample_t*)NULL, (stream_sample_t*)NULL};
void Ym2203_Emu::write( int addr, int data )
{
ym2203_update_one( opn, DUMMYBUF, 0 );
ym2203_write( opn, 0, addr );
ym2203_write( opn, 1, data );
}
void Ym2203_Emu::mute_voices( int mask )
{
ym2203_set_mutemask( opn, mask );
for ( unsigned i = 0, j = 1 << 3; i < 3; i++, j <<= 1)
{
Blip_Buffer * buf = ( mask & j ) ? NULL : &buffer;
psg.set_output( i, buf );
}
}
void Ym2203_Emu::run( int pair_count, sample_t* out )
{
blip_sample_t buf[ 1024 ];
FMSAMPLE bufL[ 1024 ];
FMSAMPLE bufR[ 1024 ];
FMSAMPLE * buffers[2] = { bufL, bufR };
blip_time_t psg_end_time = pair_count * psg_clock / sample_rate;
psg.end_frame( psg_end_time );
buffer.end_frame( psg_end_time );
while (pair_count > 0)
{
int todo = pair_count;
if (todo > 1024) todo = 1024;
ym2203_update_one( opn, buffers, todo );
int sample_count = buffer.read_samples( buf, todo );
memset( buf + sample_count, 0, ( todo - sample_count ) * sizeof( blip_sample_t ) );
for (int i = 0; i < todo; i++)
{
int output_l, output_r;
int output = buf [i];
output_l = output + bufL [i];
output_r = output + bufR [i];
output_l += out [0];
output_r += out [1];
if ( (short)output_l != output_l ) output_l = 0x7FFF ^ ( output_l >> 31 );
if ( (short)output_r != output_r ) output_r = 0x7FFF ^ ( output_r >> 31 );
out [0] = output_l;
out [1] = output_r;
out += 2;
}
pair_count -= todo;
}
}
void Ym2203_Emu::psg_set_clock( int clock )
{
psg_clock = clock * 2;
buffer.clock_rate( psg_clock );
}
void Ym2203_Emu::psg_write( int addr, int data )
{
if ( !(addr & 1) ) psg.write_addr( data );
else psg.write_data( 0, data );
}
int Ym2203_Emu::psg_read()
{
return psg.read();
}
void Ym2203_Emu::psg_reset()
{
psg.reset();
}

View file

@ -1,45 +0,0 @@
// YM2203 FM sound chip emulator interface
// Game_Music_Emu $vers
#ifndef YM2203_EMU_H
#define YM2203_EMU_H
#include "Ay_Apu.h"
class Ym2203_Emu {
void* opn;
Ay_Apu psg;
Blip_Buffer buffer;
unsigned sample_rate;
unsigned psg_clock;
public:
Ym2203_Emu();
~Ym2203_Emu();
// Sets output chip clock rate, in Hz. Returns non-zero
// if error.
int set_rate( int sample_rate, int clock_rate );
// Resets to power-up state
void reset();
// Mutes voice n if bit n (1 << n) of mask is set
enum { channel_count = 6 };
void mute_voices( int mask );
// Writes data to addr
void write( int addr, int data );
// Runs and writes pair_count*2 samples to output
typedef short sample_t;
enum { out_chan_count = 2 }; // stereo
void run( int pair_count, sample_t* out );
// SSG interface
inline void psg_set_clock( int clock );
inline void psg_write( int addr, int data );
inline int psg_read();
inline void psg_reset();
};
#endif

View file

@ -1,62 +1,64 @@
// Game_Music_Emu $vers. http://www.slack.net/~ant/
#include "Ym2413_Emu.h"
#include "ym2413.h"
extern "C" {
#include "../vgmplay/chips/emu2413.h"
}
Ym2413_Emu::Ym2413_Emu() { opll = 0; }
Ym2413_Emu::~Ym2413_Emu()
{
if ( opll ) ym2413_shutdown( opll );
if ( opll ) OPLL_delete( (OPLL *) opll );
}
int Ym2413_Emu::set_rate( int sample_rate, int clock_rate )
{
if ( opll )
{
ym2413_shutdown( opll );
OPLL_delete( (OPLL *) opll );
opll = 0;
}
opll = ym2413_init( clock_rate, sample_rate, 0 );
opll = OPLL_new( clock_rate, sample_rate );
if ( !opll )
return 1;
OPLL_SetChipMode( (OPLL *) opll, 0 );
reset();
return 0;
}
void Ym2413_Emu::reset()
{
ym2413_reset_chip( opll );
ym2413_set_mask( opll, 0 );
OPLL_reset( (OPLL *) opll );
OPLL_SetMuteMask( (OPLL *) opll, 0 );
}
static stream_sample_t* DUMMYBUF[0x02] = {(stream_sample_t*)NULL, (stream_sample_t*)NULL};
void Ym2413_Emu::write( int addr, int data )
{
ym2413_update_one( opll, DUMMYBUF, 0 );
ym2413_write( opll, 0, addr );
ym2413_write( opll, 1, data );
OPLL_writeIO( (OPLL *) opll, 0, addr );
OPLL_writeIO( (OPLL *) opll, 1, data );
}
void Ym2413_Emu::mute_voices( int mask )
{
ym2413_set_mask( opll, mask );
OPLL_SetMuteMask( (OPLL *) opll, mask );
}
void Ym2413_Emu::run( int pair_count, sample_t* out )
{
SAMP bufMO[ 1024 ];
SAMP bufRO[ 1024 ];
SAMP * buffers[2] = { bufMO, bufRO };
e_int32 bufMO[ 1024 ];
e_int32 bufRO[ 1024 ];
e_int32 * buffers[2] = { bufMO, bufRO };
while (pair_count > 0)
{
int todo = pair_count;
if (todo > 1024) todo = 1024;
ym2413_update_one( opll, buffers, todo );
OPLL_calc_stereo( (OPLL *) opll, buffers, todo, -1 );
for (int i = 0; i < todo; i++)
{

View file

@ -4,8 +4,6 @@
#ifndef YM2413_EMU_H
#define YM2413_EMU_H
struct OPLL;
class Ym2413_Emu {
void* opll;
public:

View file

@ -1,167 +0,0 @@
// Game_Music_Emu $vers. http://www.slack.net/~ant/
#include "Ym2608_Emu.h"
#include "fm.h"
#include <string.h>
static void psg_set_clock(void *param, int clock)
{
Ym2608_Emu *info = (Ym2608_Emu *)param;
info->psg_set_clock( clock );
}
static void psg_write(void *param, int address, int data)
{
Ym2608_Emu *info = (Ym2608_Emu *)param;
info->psg_write( address, data );
}
static int psg_read(void *param)
{
Ym2608_Emu *info = (Ym2608_Emu *)param;
return info->psg_read();
}
static void psg_reset(void *param)
{
Ym2608_Emu *info = (Ym2608_Emu *)param;
info->psg_reset();
}
static const ssg_callbacks psgintf =
{
psg_set_clock,
psg_write,
psg_read,
psg_reset
};
Ym2608_Emu::Ym2608_Emu() { opn = 0; psg.set_type( Ay_Apu::Ym2608 ); }
Ym2608_Emu::~Ym2608_Emu()
{
if ( opn ) ym2608_shutdown( opn );
}
int Ym2608_Emu::set_rate( int sample_rate, int clock_rate )
{
if ( opn )
{
ym2608_shutdown( opn );
opn = 0;
}
opn = ym2608_init( this, clock_rate, sample_rate, &psgintf );
if ( !opn )
return 1;
this->sample_rate = sample_rate;
psg_clock = clock_rate * 2;
buffer.set_sample_rate( sample_rate );
buffer.clock_rate( psg_clock );
psg.volume( 1.0 );
reset();
return 0;
}
void Ym2608_Emu::reset()
{
psg.reset();
ym2608_reset_chip( opn );
mute_voices( 0 );
}
static stream_sample_t* DUMMYBUF[0x02] = {(stream_sample_t*)NULL, (stream_sample_t*)NULL};
void Ym2608_Emu::write0( int addr, int data )
{
ym2608_update_one( opn, DUMMYBUF, 0 );
ym2608_write( opn, 0, addr );
ym2608_write( opn, 1, data );
}
void Ym2608_Emu::write1( int addr, int data )
{
ym2608_update_one( opn, DUMMYBUF, 0 );
ym2608_write( opn, 2, addr );
ym2608_write( opn, 3, data );
}
void Ym2608_Emu::write_rom( int rom_id, int size, int start, int length, void * data )
{
ym2608_write_pcmrom( opn, rom_id, size, start, length, (const UINT8 *) data );
}
void Ym2608_Emu::mute_voices( int mask )
{
ym2608_set_mutemask( opn, mask );
for ( unsigned i = 0, j = 1 << 6; i < 3; i++, j <<= 1)
{
Blip_Buffer * buf = ( mask & j ) ? NULL : &buffer;
psg.set_output( i, buf );
}
}
void Ym2608_Emu::run( int pair_count, sample_t* out )
{
blip_sample_t buf[ 1024 ];
FMSAMPLE bufL[ 1024 ];
FMSAMPLE bufR[ 1024 ];
FMSAMPLE * buffers[2] = { bufL, bufR };
blip_time_t psg_end_time = pair_count * psg_clock / sample_rate;
psg.end_frame( psg_end_time );
buffer.end_frame( psg_end_time );
while (pair_count > 0)
{
int todo = pair_count;
if (todo > 1024) todo = 1024;
ym2608_update_one( opn, buffers, todo );
int sample_count = buffer.read_samples( buf, todo );
memset( buf + sample_count, 0, ( todo - sample_count ) * sizeof( blip_sample_t ) );
for (int i = 0; i < todo; i++)
{
int output_l, output_r;
int output = buf [i];
output_l = output + bufL [i];
output_r = output + bufR [i];
output_l += out [0];
output_r += out [1];
if ( (short)output_l != output_l ) output_l = 0x7FFF ^ ( output_l >> 31 );
if ( (short)output_r != output_r ) output_r = 0x7FFF ^ ( output_r >> 31 );
out [0] = output_l;
out [1] = output_r;
out += 2;
}
pair_count -= todo;
}
}
void Ym2608_Emu::psg_set_clock( int clock )
{
psg_clock = clock * 2;
buffer.clock_rate( psg_clock );
}
void Ym2608_Emu::psg_write( int addr, int data )
{
if ( !(addr & 1) ) psg.write_addr( data );
else psg.write_data( 0, data );
}
int Ym2608_Emu::psg_read()
{
return psg.read();
}
void Ym2608_Emu::psg_reset()
{
psg.reset();
}

View file

@ -1,49 +0,0 @@
// YM2608 FM sound chip emulator interface
// Game_Music_Emu $vers
#ifndef YM2608_EMU_H
#define YM2608_EMU_H
#include "Ay_Apu.h"
class Ym2608_Emu {
void* opn;
Ay_Apu psg;
Blip_Buffer buffer;
unsigned sample_rate;
unsigned psg_clock;
public:
Ym2608_Emu();
~Ym2608_Emu();
// Sets output chip clock rate, in Hz. Returns non-zero
// if error.
int set_rate( int sample_rate, int clock_rate );
// Resets to power-up state
void reset();
// Mutes voice n if bit n (1 << n) of mask is set
enum { channel_count = 9 };
void mute_voices( int mask );
// Writes data to addr
void write0( int addr, int data );
void write1( int addr, int data );
// Sets ROM type, scales ROM size, then writes length bytes from data at start offset
void write_rom( int rom_id, int size, int start, int length, void * data );
// Runs and writes pair_count*2 samples to output
typedef short sample_t;
enum { out_chan_count = 2 }; // stereo
void run( int pair_count, sample_t* out );
// SSG interface
inline void psg_set_clock( int clock );
inline void psg_write( int addr, int data );
inline int psg_read();
inline void psg_reset();
};
#endif

View file

@ -1,173 +0,0 @@
// Game_Music_Emu $vers. http://www.slack.net/~ant/
#include "Ym2610b_Emu.h"
#include "fm.h"
#include <string.h>
static void psg_set_clock(void *param, int clock)
{
Ym2610b_Emu *info = (Ym2610b_Emu *)param;
info->psg_set_clock( clock );
}
static void psg_write(void *param, int address, int data)
{
Ym2610b_Emu *info = (Ym2610b_Emu *)param;
info->psg_write( address, data );
}
static int psg_read(void *param)
{
Ym2610b_Emu *info = (Ym2610b_Emu *)param;
return info->psg_read();
}
static void psg_reset(void *param)
{
Ym2610b_Emu *info = (Ym2610b_Emu *)param;
info->psg_reset();
}
static const ssg_callbacks psgintf =
{
psg_set_clock,
psg_write,
psg_read,
psg_reset
};
Ym2610b_Emu::Ym2610b_Emu() { opn = 0; }
Ym2610b_Emu::~Ym2610b_Emu()
{
if ( opn ) ym2610_shutdown( opn );
}
int Ym2610b_Emu::set_rate( int sample_rate, int clock_rate, bool is_2610b )
{
if ( opn )
{
ym2610_shutdown( opn );
opn = 0;
}
psg.set_type( is_2610b ? Ay_Apu::Ym2610b : Ay_Apu::Ym2610 );
opn = ym2610_init( this, clock_rate, sample_rate, &psgintf );
if ( !opn )
return 1;
this->sample_rate = sample_rate;
psg_clock = clock_rate * 2;
this->is_2610b = is_2610b;
buffer.set_sample_rate( sample_rate );
buffer.clock_rate( psg_clock );
psg.volume( 1.0 );
reset();
return 0;
}
void Ym2610b_Emu::reset()
{
psg.reset();
ym2610_reset_chip( opn );
mute_voices( 0 );
}
static stream_sample_t* DUMMYBUF[0x02] = {(stream_sample_t*)NULL, (stream_sample_t*)NULL};
void Ym2610b_Emu::write0( int addr, int data )
{
if ( is_2610b ) ym2610b_update_one( opn, DUMMYBUF, 0 );
else ym2610_update_one( opn, DUMMYBUF, 0 );
ym2610_write( opn, 0, addr );
ym2610_write( opn, 1, data );
}
void Ym2610b_Emu::write1( int addr, int data )
{
if ( is_2610b ) ym2610b_update_one( opn, DUMMYBUF, 0 );
else ym2610_update_one( opn, DUMMYBUF, 0 );
ym2610_write( opn, 2, addr );
ym2610_write( opn, 3, data );
}
void Ym2610b_Emu::write_rom( int rom_id, int size, int start, int length, void * data )
{
ym2610_write_pcmrom( opn, rom_id, size, start, length, (const UINT8 *) data );
}
void Ym2610b_Emu::mute_voices( int mask )
{
ym2610_set_mutemask( opn, mask );
for ( unsigned i = 0, j = 1 << 6; i < 3; i++, j <<= 1)
{
Blip_Buffer * buf = ( mask & j ) ? NULL : &buffer;
psg.set_output( i, buf );
}
}
void Ym2610b_Emu::run( int pair_count, sample_t* out )
{
blip_sample_t buf[ 1024 ];
FMSAMPLE bufL[ 1024 ];
FMSAMPLE bufR[ 1024 ];
FMSAMPLE * buffers[2] = { bufL, bufR };
blip_time_t psg_end_time = pair_count * psg_clock / sample_rate;
psg.end_frame( psg_end_time );
buffer.end_frame( psg_end_time );
while (pair_count > 0)
{
int todo = pair_count;
if (todo > 1024) todo = 1024;
if ( is_2610b ) ym2610b_update_one( opn, buffers, todo );
else ym2610_update_one( opn, buffers, todo );
int sample_count = buffer.read_samples( buf, todo );
memset( buf + sample_count, 0, ( todo - sample_count ) * sizeof( blip_sample_t ) );
for (int i = 0; i < todo; i++)
{
int output_l, output_r;
int output = buf [i];
output_l = output + bufL [i];
output_r = output + bufR [i];
output_l += out [0];
output_r += out [1];
if ( (short)output_l != output_l ) output_l = 0x7FFF ^ ( output_l >> 31 );
if ( (short)output_r != output_r ) output_r = 0x7FFF ^ ( output_r >> 31 );
out [0] = output_l;
out [1] = output_r;
out += 2;
}
pair_count -= todo;
}
}
void Ym2610b_Emu::psg_set_clock( int clock )
{
psg_clock = clock * 2;
buffer.clock_rate( psg_clock );
}
void Ym2610b_Emu::psg_write( int addr, int data )
{
if ( !(addr & 1) ) psg.write_addr( data );
else psg.write_data( 0, data );
}
int Ym2610b_Emu::psg_read()
{
return psg.read();
}
void Ym2610b_Emu::psg_reset()
{
psg.reset();
}

View file

@ -1,50 +0,0 @@
// YM2610B FM sound chip emulator interface
// Game_Music_Emu $vers
#ifndef YM2610B_EMU_H
#define YM2610B_EMU_H
#include "Ay_Apu.h"
class Ym2610b_Emu {
void* opn;
Ay_Apu psg;
Blip_Buffer buffer;
unsigned sample_rate;
unsigned psg_clock;
bool is_2610b;
public:
Ym2610b_Emu();
~Ym2610b_Emu();
// Sets output chip clock rate, in Hz. Returns non-zero
// if error.
int set_rate( int sample_rate, int clock_rate, bool is_2610b );
// Resets to power-up state
void reset();
// Mutes voice n if bit n (1 << n) of mask is set
enum { channel_count = 9 };
void mute_voices( int mask );
// Writes data to addr
void write0( int addr, int data );
void write1( int addr, int data );
// Sets ROM type, scales ROM size, then writes length bytes from data at start offset
void write_rom( int rom_id, int size, int start, int length, void * data );
// Runs and writes pair_count*2 samples to output
typedef short sample_t;
enum { out_chan_count = 2 }; // stereo
void run( int pair_count, sample_t* out );
// SSG interface
inline void psg_set_clock( int clock );
inline void psg_write( int addr, int data );
inline int psg_read();
inline void psg_reset();
};
#endif

View file

@ -1,5 +1,6 @@
#include "Ym2612_Emu.h"
#define YM2612_EMU_CPP
#ifdef USE_GENS
#include "Ym2612_Emu_Gens.cpp"
#else

View file

@ -2,6 +2,8 @@
// Based on Gens 2.10 ym2612.c
#ifdef YM2612_EMU_CPP
#include "Ym2612_Emu.h"
#include <assert.h>
@ -1297,3 +1299,5 @@ void Ym2612_Impl::run( int pair_count, Ym2612_Emu::sample_t out [] )
}
void Ym2612_Emu::run( int pair_count, sample_t out [] ) { impl->run( pair_count, out ); }
#endif

View file

@ -1,7 +1,13 @@
// Game_Music_Emu $vers. http://www.slack.net/~ant/
#ifdef YM2612_EMU_CPP
#include "Ym2612_Emu.h"
#include "fm.h"
extern "C" {
#include "../vgmplay/chips/mamedef.h"
#include "../vgmplay/chips/fm.h"
}
#include "blargg_errors.h"
@ -13,6 +19,8 @@ Ym2612_Emu::~Ym2612_Emu()
ym2612_shutdown( impl );
}
static BOOST::uint8_t dummy = 0;
const char* Ym2612_Emu::set_rate( double sample_rate, double clock_rate )
{
if ( impl )
@ -24,7 +32,7 @@ const char* Ym2612_Emu::set_rate( double sample_rate, double clock_rate )
if ( !clock_rate )
clock_rate = sample_rate * 144.;
impl = ym2612_init( (long) (clock_rate + 0.5), (long) (sample_rate + 0.5) );
impl = ym2612_init( 0, (int) (clock_rate + 0.5), (int) (sample_rate + 0.5), 0, 0, &dummy, 0 );
if ( !impl )
return blargg_err_memory;
@ -85,3 +93,5 @@ void Ym2612_Emu::run( int pair_count, sample_t* out )
pair_count -= todo;
}
}
#endif

View file

@ -1,66 +0,0 @@
// Game_Music_Emu $vers. http://www.slack.net/~ant/
#include "Ym3812_Emu.h"
#include <math.h>
#include "dbopl.h"
Ym3812_Emu::Ym3812_Emu() { opl = 0; }
Ym3812_Emu::~Ym3812_Emu()
{
delete opl;
}
int Ym3812_Emu::set_rate( int sample_rate, int clock_rate )
{
delete opl;
opl = 0;
opl = new DBOPL::Chip;
if ( !opl )
return 1;
this->sample_rate = sample_rate;
this->clock_rate = clock_rate * 4;
reset();
return 0;
}
void Ym3812_Emu::reset()
{
opl->Setup( clock_rate, sample_rate );
}
void Ym3812_Emu::write( int addr, int data )
{
opl->WriteReg( addr, data );
}
void Ym3812_Emu::run( int pair_count, sample_t* out )
{
Bit32s buf[ 1024 ];
while (pair_count > 0)
{
int todo = pair_count;
if (todo > 1024) todo = 1024;
opl->GenerateBlock2( todo, buf );
for (int i = 0; i < todo; i++)
{
int output_l, output_r;
int output = buf [i];
output_l = output + out [0];
output_r = output + out [1];
if ( (short)output_l != output_l ) output_l = 0x7FFF ^ ( output_l >> 31 );
if ( (short)output_r != output_r ) output_r = 0x7FFF ^ ( output_r >> 31 );
out [0] = output_l;
out [1] = output_r;
out += 2;
}
pair_count -= todo;
}
}

View file

@ -1,35 +0,0 @@
// YM3812 FM sound chip emulator interface
// Game_Music_Emu $vers
#ifndef YM3812_EMU_H
#define YM3812_EMU_H
namespace DBOPL {
struct Chip;
}
class Ym3812_Emu {
DBOPL::Chip * opl;
unsigned sample_rate;
unsigned clock_rate;
public:
Ym3812_Emu();
~Ym3812_Emu();
// Sets output sample rate and chip clock rates, in Hz. Returns non-zero
// if error.
int set_rate( int sample_rate, int clock_rate );
// Resets to power-up state
void reset();
// Writes data to addr
void write( int addr, int data );
// Runs and writes pair_count*2 samples to output
typedef short sample_t;
enum { out_chan_count = 2 }; // stereo
void run( int pair_count, sample_t* out );
};
#endif

View file

@ -1,93 +0,0 @@
// Game_Music_Emu $vers. http://www.slack.net/~ant/
#include "Ymf262_Emu.h"
#include <math.h>
#include "dbopl.h"
Ymf262_Emu::Ymf262_Emu() { opl = 0; }
Ymf262_Emu::~Ymf262_Emu()
{
delete opl;
}
int Ymf262_Emu::set_rate( int sample_rate, int clock_rate )
{
delete opl;
opl = 0;
opl = new DBOPL::Chip;
if ( !opl )
return 1;
this->sample_rate = sample_rate;
this->clock_rate = clock_rate;
reset();
return 0;
}
void Ymf262_Emu::reset()
{
opl->Setup( clock_rate, sample_rate );
}
void Ymf262_Emu::write0( int addr, int data )
{
opl->WriteReg( addr, data );
}
void Ymf262_Emu::write1( int addr, int data )
{
opl->WriteReg( 0x100 + addr, data );
}
void Ymf262_Emu::run( int pair_count, sample_t* out )
{
Bit32s buf[ 2048 ];
while (pair_count > 0)
{
int todo = pair_count;
if (todo > 1024) todo = 1024;
if ( opl->opl3Active )
{
opl->GenerateBlock3( todo, buf );
for (int i = 0; i < todo; i++)
{
int output_l, output_r;
output_l = buf [i * 2];
output_r = buf [i * 2 + 1];
output_l += out [0];
output_r += out [1];
if ( (short)output_l != output_l ) output_l = 0x7FFF ^ ( output_l >> 31 );
if ( (short)output_r != output_r ) output_r = 0x7FFF ^ ( output_r >> 31 );
out [0] = output_l;
out [1] = output_r;
out += 2;
}
}
else
{
opl->GenerateBlock2( todo, buf );
for (int i = 0; i < todo; i++)
{
int output_l, output_r;
int output = buf [i];
output_l = output + out [0];
output_r = output + out [1];
if ( (short)output_l != output_l ) output_l = 0x7FFF ^ ( output_l >> 31 );
if ( (short)output_r != output_r ) output_r = 0x7FFF ^ ( output_r >> 31 );
out [0] = output_l;
out [1] = output_r;
out += 2;
}
}
pair_count -= todo;
}
}

View file

@ -1,36 +0,0 @@
// YMF262 FM sound chip emulator interface
// Game_Music_Emu $vers
#ifndef YMF262_EMU_H
#define YMF262_EMU_H
namespace DBOPL {
struct Chip;
}
class Ymf262_Emu {
DBOPL::Chip * opl;
unsigned sample_rate;
unsigned clock_rate;
public:
Ymf262_Emu();
~Ymf262_Emu();
// Sets output sample rate and chip clock rates, in Hz. Returns non-zero
// if error.
int set_rate( int sample_rate, int clock_rate );
// Resets to power-up state
void reset();
// Writes data to addr
void write0( int addr, int data );
void write1( int addr, int data );
// Runs and writes pair_count*2 samples to output
typedef short sample_t;
enum { out_chan_count = 2 }; // stereo
void run( int pair_count, sample_t* out );
};
#endif

View file

@ -1,78 +0,0 @@
// Game_Music_Emu $vers. http://www.slack.net/~ant/
#include "Ymz280b_Emu.h"
#include "ymz280b.h"
Ymz280b_Emu::Ymz280b_Emu() { chip = 0; }
Ymz280b_Emu::~Ymz280b_Emu()
{
if ( chip ) device_stop_ymz280b( chip );
}
int Ymz280b_Emu::set_rate( int clock_rate )
{
if ( chip )
{
device_stop_ymz280b( chip );
chip = 0;
}
chip = device_start_ymz280b( clock_rate );
if ( !chip )
return 0;
reset();
return clock_rate * 2 / 384;
}
void Ymz280b_Emu::reset()
{
device_reset_ymz280b( chip );
ymz280b_set_mute_mask( chip, 0 );
}
void Ymz280b_Emu::write( int addr, int data )
{
ymz280b_w( chip, 0, addr );
ymz280b_w( chip, 1, data );
}
void Ymz280b_Emu::write_rom( int size, int start, int length, void * data )
{
ymz280b_write_rom( chip, size, start, length, (const UINT8 *) data );
}
void Ymz280b_Emu::mute_voices( int mask )
{
ymz280b_set_mute_mask( chip, mask );
}
void Ymz280b_Emu::run( int pair_count, sample_t* out )
{
stream_sample_t bufL[ 1024 ];
stream_sample_t bufR[ 1024 ];
stream_sample_t * buffers[2] = { bufL, bufR };
while (pair_count > 0)
{
int todo = pair_count;
if (todo > 1024) todo = 1024;
ymz280b_update( chip, buffers, todo );
for (int i = 0; i < todo; i++)
{
int output_l = bufL [i];
int output_r = bufR [i];
output_l += out [0];
output_r += out [1];
if ( (short)output_l != output_l ) output_l = 0x7FFF ^ ( output_l >> 31 );
if ( (short)output_r != output_r ) output_r = 0x7FFF ^ ( output_r >> 31 );
out [0] = output_l;
out [1] = output_r;
out += 2;
}
pair_count -= todo;
}
}

View file

@ -1,36 +0,0 @@
// YMZ280B sound chip emulator interface
// Game_Music_Emu $vers
#ifndef YMZ280B_EMU_H
#define YMZ280B_EMU_H
class Ymz280b_Emu {
void* chip;
public:
Ymz280b_Emu();
~Ymz280b_Emu();
// Sets output sample rate and chip clock rates, in Hz. Returns non-zero
// if error.
int set_rate( int clock_rate );
// Resets to power-up state
void reset();
// Mutes voice n if bit n (1 << n) of mask is set
enum { channel_count = 8 };
void mute_voices( int mask );
// Writes data to addr
void write( int addr, int data );
// Scales ROM size, then writes length bytes from data at start offset
void write_rom( int size, int start, int length, void * data );
// Runs and writes pair_count*2 samples to output
typedef short sample_t;
enum { out_chan_count = 2 }; // stereo
void run( int pair_count, sample_t* out );
};
#endif

View file

@ -1,154 +0,0 @@
/*
* Copyright (C) 2002-2009 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: adlib.h,v 1.4 2009/04/26 10:33:53 harekiet Exp $ */
#ifndef DOSBOX_ADLIB_H
#define DOSBOX_ADLIB_H
/*#include "dosbox.h"
#include "mixer.h"
#include "inout.h"
#include "mixer.h"
#include "setup.h"
#include "pic.h"
#include "hardware.h"*/
namespace Adlib {
struct Timer {
double start;
double delay;
bool enabled, overflow, masked;
Bit8u counter;
Timer() {
masked = false;
overflow = false;
enabled = false;
counter = 0;
delay = 0;
}
//Call update before making any further changes
void Update( double time ) {
if ( !enabled || !delay )
return;
double deltaStart = time - start;
//Only set the overflow flag when not masked
if ( deltaStart >= 0 && !masked ) {
overflow = 1;
}
}
//On a reset make sure the start is in sync with the next cycle
void Reset(const double& time ) {
overflow = false;
if ( !delay || !enabled )
return;
double delta = (time - start);
double rem = fmod( delta, delay );
double next = delay - rem;
start = time + next;
}
void Stop( ) {
enabled = false;
}
void Start( const double& time, Bits scale ) {
//Don't enable again
if ( enabled ) {
return;
}
enabled = true;
delay = 0.001 * (256 - counter ) * scale;
start = time + delay;
}
};
struct Chip {
//Last selected register
Timer timer[2];
//Check for it being a write to the timer
bool Write( Bit32u addr, Bit8u val );
//Read the current timer state, will use current double
Bit8u Read( );
};
//The type of handler this is
typedef enum {
MODE_OPL2,
MODE_DUALOPL2,
MODE_OPL3
} Mode;
/*class Handler {
public:
//Write an address to a chip, returns the address the chip sets
virtual Bit32u WriteAddr( Bit32u port, Bit8u val ) = 0;
//Write to a specific register in the chip
virtual void WriteReg( Bit32u addr, Bit8u val ) = 0;
//Generate a certain amount of samples
virtual void Generate( MixerChannel* chan, Bitu samples ) = 0;
//Initialize at a specific sample rate and mode
virtual void Init( Bitu rate ) = 0;
virtual ~Handler() {
}
};*/
//The cache for 2 chips or an opl3
typedef Bit8u RegisterCache[512];
//Internal class used for dro capturing
class Capture;
/*class Module: public Module_base {
IO_ReadHandleObject ReadHandler[3];
IO_WriteHandleObject WriteHandler[3];
MixerObject mixerObject;
//Mode we're running in
Mode mode;
//Last selected address in the chip for the different modes
union {
Bit32u normal;
Bit8u dual[2];
} reg;
void CacheWrite( Bit32u reg, Bit8u val );
void DualWrite( Bit8u index, Bit8u reg, Bit8u val );
public:
static OPL_Mode oplmode;
MixerChannel* mixerChan;
Bit32u lastUsed; //Ticks when adlib was last used to turn of mixing after a few second
Handler* handler; //Handler that will generate the sound
RegisterCache cache;
Capture* capture;
Chip chip[2];
//Handle port writes
void PortWrite( Bitu port, Bitu val, Bitu iolen );
Bitu PortRead( Bitu port, Bitu iolen );
void Init( Mode m );
Module( Section* configuration);
~Module();
};*/
} //Adlib namespace
#endif

View file

@ -55,4 +55,270 @@ blargg_err_t blargg_vector_::resize_( size_t n, size_t elem_size )
return blargg_ok;
}
static const BOOST::uint8_t mask_tab[6]={0x80,0xE0,0xF0,0xF8,0xFC,0xFE};
static const BOOST::uint8_t val_tab[6]={0,0xC0,0xE0,0xF0,0xF8,0xFC};
size_t utf8_char_len_from_header( char p_c )
{
size_t cnt = 0;
for(;;)
{
if ( ( p_c & mask_tab[cnt] ) == val_tab[cnt] ) break;
if ( ++cnt >= 6 ) return 0;
}
return cnt + 1;
}
size_t utf8_decode_char( const char *p_utf8, unsigned & wide, size_t mmax )
{
const BOOST::uint8_t * utf8 = ( const BOOST::uint8_t* )p_utf8;
if ( mmax == 0 )
{
wide = 0;
return 0;
}
if ( utf8[0] < 0x80 )
{
wide = utf8[0];
return utf8[0]>0 ? 1 : 0;
}
if ( mmax > 6 ) mmax = 6;
wide = 0;
unsigned res=0;
unsigned n;
unsigned cnt=0;
for(;;)
{
if ( ( *utf8 & mask_tab[cnt] ) == val_tab[cnt] ) break;
if ( ++cnt >= mmax ) return 0;
}
cnt++;
if ( cnt==2 && !( *utf8 & 0x1E ) ) return 0;
if ( cnt == 1 )
res = *utf8;
else
res = ( 0xFF >> ( cnt + 1 ) ) & *utf8;
for ( n = 1; n < cnt; n++ )
{
if ( ( utf8[n] & 0xC0 ) != 0x80 )
return 0;
if ( !res && n == 2 && !( ( utf8[n] & 0x7F ) >> ( 7 - cnt ) ) )
return 0;
res = ( res << 6 ) | ( utf8[n] & 0x3F );
}
wide = res;
return cnt;
}
size_t utf8_encode_char( unsigned wide, char * target )
{
size_t count;
if ( wide < 0x80 )
count = 1;
else if ( wide < 0x800 )
count = 2;
else if ( wide < 0x10000 )
count = 3;
else if ( wide < 0x200000 )
count = 4;
else if ( wide < 0x4000000 )
count = 5;
else if ( wide <= 0x7FFFFFFF )
count = 6;
else
return 0;
if ( target == 0 )
return count;
switch ( count )
{
case 6:
target[5] = 0x80 | ( wide & 0x3F );
wide = wide >> 6;
wide |= 0x4000000;
case 5:
target[4] = 0x80 | ( wide & 0x3F );
wide = wide >> 6;
wide |= 0x200000;
case 4:
target[3] = 0x80 | ( wide & 0x3F );
wide = wide >> 6;
wide |= 0x10000;
case 3:
target[2] = 0x80 | ( wide & 0x3F );
wide = wide >> 6;
wide |= 0x800;
case 2:
target[1] = 0x80 | ( wide & 0x3F );
wide = wide >> 6;
wide |= 0xC0;
case 1:
target[0] = wide;
}
return count;
}
size_t utf16_encode_char( unsigned cur_wchar, blargg_wchar_t * out )
{
if ( cur_wchar < 0x10000 )
{
if ( out ) *out = (blargg_wchar_t) cur_wchar; return 1;
}
else if ( cur_wchar < ( 1 << 20 ) )
{
unsigned c = cur_wchar - 0x10000;
//MSDN:
//The first (high) surrogate is a 16-bit code value in the range U+D800 to U+DBFF. The second (low) surrogate is a 16-bit code value in the range U+DC00 to U+DFFF. Using surrogates, Unicode can support over one million characters. For more details about surrogates, refer to The Unicode Standard, version 2.0.
if ( out )
{
out[0] = ( blargg_wchar_t )( 0xD800 | ( 0x3FF & ( c >> 10 ) ) );
out[1] = ( blargg_wchar_t )( 0xDC00 | ( 0x3FF & c ) ) ;
}
return 2;
}
else
{
if ( out ) *out = '?'; return 1;
}
}
size_t utf16_decode_char( const blargg_wchar_t * p_source, unsigned * p_out, size_t p_source_length )
{
if ( p_source_length == 0 ) return 0;
else if ( p_source_length == 1 )
{
*p_out = p_source[0];
return 1;
}
else
{
size_t retval = 0;
unsigned decoded = p_source[0];
if ( decoded != 0 )
{
retval = 1;
if ( ( decoded & 0xFC00 ) == 0xD800 )
{
unsigned low = p_source[1];
if ( ( low & 0xFC00 ) == 0xDC00 )
{
decoded = 0x10000 + ( ( ( decoded & 0x3FF ) << 10 ) | ( low & 0x3FF ) );
retval = 2;
}
}
}
*p_out = decoded;
return retval;
}
}
// Converts wide-character path to UTF-8. Free result with free(). Only supported on Windows.
char* blargg_to_utf8( const blargg_wchar_t* wpath )
{
if ( wpath == NULL )
return NULL;
size_t needed = 0;
size_t mmax = blargg_wcslen( wpath );
if ( mmax <= 0 )
return NULL;
size_t ptr = 0;
while ( ptr < mmax )
{
unsigned wide = 0;
size_t char_len = utf16_decode_char( wpath + ptr, &wide, mmax - ptr );
if ( !char_len ) break;
ptr += char_len;
needed += utf8_encode_char( wide, 0 );
}
if ( needed <= 0 )
return NULL;
char* path = (char*) calloc( needed + 1, 1 );
if ( path == NULL )
return NULL;
ptr = 0;
size_t actual = 0;
while ( ptr < mmax && actual < needed )
{
unsigned wide = 0;
size_t char_len = utf16_decode_char( wpath + ptr, &wide, mmax - ptr );
if ( !char_len ) break;
ptr += char_len;
actual += utf8_encode_char( wide, path + actual );
}
if ( actual == 0 )
{
free( path );
return NULL;
}
assert( actual == needed );
return path;
}
// Converts UTF-8 path to wide-character. Free result with free() Only supported on Windows.
blargg_wchar_t* blargg_to_wide( const char* path )
{
if ( path == NULL )
return NULL;
size_t mmax = strlen( path );
if ( mmax <= 0 )
return NULL;
size_t needed = 0;
size_t ptr = 0;
while ( ptr < mmax )
{
unsigned wide = 0;
size_t char_len = utf8_decode_char( path + ptr, wide, mmax - ptr );
if ( !char_len ) break;
ptr += char_len;
needed += utf16_encode_char( wide, 0 );
}
if ( needed <= 0 )
return NULL;
blargg_wchar_t* wpath = (blargg_wchar_t*) calloc( needed + 1, sizeof *wpath );
if ( wpath == NULL )
return NULL;
ptr = 0;
size_t actual = 0;
while ( ptr < mmax && actual < needed )
{
unsigned wide = 0;
size_t char_len = utf8_decode_char( path + ptr, wide, mmax - ptr );
if ( !char_len ) break;
ptr += char_len;
actual += utf16_encode_char( wide, wpath + actual );
}
if ( actual == 0 )
{
free( wpath );
return NULL;
}
assert( actual == needed );
return wpath;
}
BLARGG_NAMESPACE_END

View file

@ -219,6 +219,25 @@ BLARGG_DEPRECATED( typedef unsigned int blargg_ulong; )
#define BOOST_STATIC_ASSERT BLARGG_STATIC_ASSERT
#endif
#ifdef _WIN32
typedef wchar_t blargg_wchar_t;
#elif defined(HAVE_STDINT_H)
#include <stdint.h>
typedef uint16_t blargg_wchar_t;
#else
typedef unsigned short blargg_wchar_t;
#endif
inline size_t blargg_wcslen( const blargg_wchar_t* str )
{
size_t length = 0;
while ( *str++ ) length++;
return length;
}
char* blargg_to_utf8( const blargg_wchar_t* );
blargg_wchar_t* blargg_to_wide( const char* );
BLARGG_NAMESPACE_END
#endif

View file

@ -130,6 +130,8 @@ BLARGG_DEF_MIN_MAX( int )
BLARGG_DEF_MIN_MAX( unsigned )
BLARGG_DEF_MIN_MAX( long )
BLARGG_DEF_MIN_MAX( unsigned long )
BLARGG_DEF_MIN_MAX( BOOST::int64_t )
BLARGG_DEF_MIN_MAX( BOOST::uint64_t )
BLARGG_DEF_MIN_MAX( float )
BLARGG_DEF_MIN_MAX( double )

View file

@ -1,58 +0,0 @@
/* C140.h */
#pragma once
#ifndef __OSDCOMM_H__
#define __OSDCOMM_H__
typedef unsigned char UINT8; /* unsigned 8bit */
typedef unsigned short UINT16; /* unsigned 16bit */
typedef unsigned int UINT32; /* unsigned 32bit */
typedef signed char INT8; /* signed 8bit */
typedef signed short INT16; /* signed 16bit */
typedef signed int INT32; /* signed 32bit */
typedef INT32 stream_sample_t;
typedef UINT32 offs_t;
#endif
#ifdef __cplusplus
extern "C" {
#endif
void c140_update(void * chip, stream_sample_t **outputs, int samples);
void * device_start_c140(int sample_rate, int clock, int banking_type);
void device_stop_c140(void * chip);
void device_reset_c140(void * chip);
//READ8_DEVICE_HANDLER( c140_r );
//WRITE8_DEVICE_HANDLER( c140_w );
UINT8 c140_r(void * chip, offs_t offset);
void c140_w(void * chip, offs_t offset, UINT8 data);
//void c140_set_base(device_t *device, void *base);
void c140_set_base(void *chip, void *base);
enum
{
C140_TYPE_SYSTEM2,
C140_TYPE_SYSTEM21_A,
C140_TYPE_SYSTEM21_B,
C140_TYPE_ASIC219
};
/*typedef struct _c140_interface c140_interface;
struct _c140_interface {
int banking_type;
};*/
void c140_write_rom(void * chip, offs_t ROMSize, offs_t DataStart, offs_t DataLength,
const UINT8* ROMData);
void c140_set_mute_mask(void * chip, UINT32 MuteMask);
#ifdef __cplusplus
}
#endif
//DECLARE_LEGACY_SOUND_DEVICE(C140, c140);

View file

@ -1,44 +0,0 @@
#ifndef _DAC_CONTROL_H_
#define _DAC_CONTROL_H_
#ifndef __OSDCOMM_H__
#define __OSDCOMM_H__
typedef unsigned char UINT8; /* unsigned 8bit */
typedef unsigned short UINT16; /* unsigned 16bit */
typedef unsigned int UINT32; /* unsigned 32bit */
typedef unsigned long long UINT64; /* unsigned 64bit */
typedef signed char INT8; /* signed 8bit */
typedef signed short INT16; /* signed 16bit */
typedef signed int INT32; /* signed 32bit */
typedef signed long long INT64; /* signed 64bit */
typedef INT32 stream_sample_t;
typedef UINT32 offs_t;
#endif
#ifdef __cplusplus
extern "C" {
#endif
void * device_start_daccontrol(UINT32 samplerate, void *context);
void device_stop_daccontrol(void * chip);
void daccontrol_update(void * chip, UINT32 base_clock, UINT32 samples);
void device_reset_daccontrol(void * chip);
void daccontrol_setup_chip(void * chip, UINT8 ChType, UINT8 ChNum, UINT16 Command);
void daccontrol_set_data(void *chip, const UINT8* Data, UINT32 DataLen, UINT8 StepSize, UINT8 StepBase);
void daccontrol_set_frequency(void *chip, UINT32 Frequency);
void daccontrol_start(void *chip, UINT32 DataPos, UINT8 LenMode, UINT32 Length);
void daccontrol_stop(void *chip);
#define DCTRL_LMODE_IGNORE 0x00
#define DCTRL_LMODE_CMDS 0x01
#define DCTRL_LMODE_MSEC 0x02
#define DCTRL_LMODE_TOEND 0x03
#define DCTRL_LMODE_BYTES 0x0F
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,292 +0,0 @@
/*
* Copyright (C) 2002-2009 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef _WIN32
#define INLINE __forceinline
#define DB_FASTCALL __fastcall
#else
#define INLINE inline
#define DB_FASTCALL __attribute__((fastcall))
#endif
typedef double Real64;
/* The internal types */
#ifdef HAVE_STDINT_H
#include <stdint.h>
typedef uint8_t Bit8u;
typedef int8_t Bit8s;
typedef uint16_t Bit16u;
typedef int16_t Bit16s;
typedef uint32_t Bit32u;
typedef int32_t Bit32s;
typedef uint64_t Bit64u;
typedef int64_t Bit64s;
#else
typedef unsigned char Bit8u;
typedef signed char Bit8s;
typedef unsigned short Bit16u;
typedef signed short Bit16s;
typedef unsigned long Bit32u;
typedef signed long Bit32s;
typedef unsigned __int64 Bit64u;
typedef signed __int64 Bit64s;
#endif
typedef unsigned int Bitu;
typedef signed int Bits;
#include "adlib.h"
//#include "dosbox.h"
//Use 8 handlers based on a small logatirmic wavetabe and an exponential table for volume
#define WAVE_HANDLER 10
//Use a logarithmic wavetable with an exponential table for volume
#define WAVE_TABLELOG 11
//Use a linear wavetable with a multiply table for volume
#define WAVE_TABLEMUL 12
//Select the type of wave generator routine
#define DBOPL_WAVE WAVE_TABLEMUL
namespace DBOPL {
struct Chip;
struct Operator;
struct Channel;
#if (DBOPL_WAVE == WAVE_HANDLER)
typedef Bits ( DB_FASTCALL *WaveHandler) ( Bitu i, Bitu volume );
#endif
typedef Bits ( DBOPL::Operator::*VolumeHandler) ( );
typedef Channel* ( DBOPL::Channel::*SynthHandler) ( Chip* chip, Bit32u samples, Bit32s* output );
//Different synth modes that can generate blocks of data
typedef enum {
sm2AM,
sm2FM,
sm3AM,
sm3FM,
sm4Start,
sm3FMFM,
sm3AMFM,
sm3FMAM,
sm3AMAM,
sm6Start,
sm2Percussion,
sm3Percussion
} SynthMode;
//Shifts for the values contained in chandata variable
enum {
SHIFT_KSLBASE = 16,
SHIFT_KEYCODE = 24
};
struct Operator {
public:
//Masks for operator 20 values
enum {
MASK_KSR = 0x10,
MASK_SUSTAIN = 0x20,
MASK_VIBRATO = 0x40,
MASK_TREMOLO = 0x80
};
typedef enum {
OFF,
RELEASE,
SUSTAIN,
DECAY,
ATTACK
} State;
VolumeHandler volHandler;
#if (DBOPL_WAVE == WAVE_HANDLER)
WaveHandler waveHandler; //Routine that generate a wave
#else
Bit16s* waveBase;
Bit32u waveMask;
Bit32u waveStart;
#endif
Bit32u waveIndex; //WAVE_BITS shifted counter of the frequency index
Bit32u waveAdd; //The base frequency without vibrato
Bit32u waveCurrent; //waveAdd + vibratao
Bit32u chanData; //Frequency/octave and derived data coming from whatever channel controls this
Bit32u freqMul; //Scale channel frequency with this, TODO maybe remove?
Bit32u vibrato; //Scaled up vibrato strength
Bit32s sustainLevel; //When stopping at sustain level stop here
Bit32s totalLevel; //totalLevel is added to every generated volume
Bit32u currentLevel; //totalLevel + tremolo
Bit32s volume; //The currently active volume
Bit32u attackAdd; //Timers for the different states of the envelope
Bit32u decayAdd;
Bit32u releaseAdd;
Bit32u rateIndex; //Current position of the evenlope
Bit8u rateZero; //Bits for the different states of the envelope having no changes
Bit8u keyOn; //Bitmask of different values that can generate keyon
//Registers, also used to check for changes
Bit8u reg20, reg40, reg60, reg80, regE0;
//Active part of the envelope we're in
Bit8u state;
//0xff when tremolo is enabled
Bit8u tremoloMask;
//Strength of the vibrato
Bit8u vibStrength;
//Keep track of the calculated KSR so we can check for changes
Bit8u ksr;
private:
void SetState( Bit8u s );
void UpdateAttack( const Chip* chip );
void UpdateRelease( const Chip* chip );
void UpdateDecay( const Chip* chip );
public:
void UpdateAttenuation();
void UpdateRates( const Chip* chip );
void UpdateFrequency( );
void Write20( const Chip* chip, Bit8u val );
void Write40( const Chip* chip, Bit8u val );
void Write60( const Chip* chip, Bit8u val );
void Write80( const Chip* chip, Bit8u val );
void WriteE0( const Chip* chip, Bit8u val );
bool Silent() const;
void Prepare( const Chip* chip );
void KeyOn( Bit8u mask);
void KeyOff( Bit8u mask);
template< State state>
Bits TemplateVolume( );
Bit32s RateForward( Bit32u add );
Bitu ForwardWave();
Bitu ForwardVolume();
Bits GetSample( Bits modulation );
Bits GetWave( Bitu index, Bitu vol );
public:
Operator();
};
struct Channel {
Operator op[2];
inline Operator* Op( Bitu index ) {
return &( ( this + (index >> 1) )->op[ index & 1 ]);
}
SynthHandler synthHandler;
Bit32u chanData; //Frequency/octave and derived values
Bit32s old[2]; //Old data for feedback
Bit8u feedback; //Feedback shift
Bit8u regB0; //Register values to check for changes
Bit8u regC0;
//This should correspond with reg104, bit 6 indicates a Percussion channel, bit 7 indicates a silent channel
Bit8u fourMask;
Bit8s maskLeft; //Sign extended values for both channel's panning
Bit8s maskRight;
//Forward the channel data to the operators of the channel
void SetChanData( const Chip* chip, Bit32u data );
//Change in the chandata, check for new values and if we have to forward to operators
void UpdateFrequency( const Chip* chip, Bit8u fourOp );
void WriteA0( const Chip* chip, Bit8u val );
void WriteB0( const Chip* chip, Bit8u val );
void WriteC0( const Chip* chip, Bit8u val );
void ResetC0( const Chip* chip );
//call this for the first channel
template< bool opl3Mode >
void GeneratePercussion( Chip* chip, Bit32s* output );
//Generate blocks of data in specific modes
template<SynthMode mode>
Channel* BlockTemplate( Chip* chip, Bit32u samples, Bit32s* output );
Channel();
};
struct Chip {
//This is used as the base counter for vibrato and tremolo
Bit32u lfoCounter;
Bit32u lfoAdd;
Bit32u noiseCounter;
Bit32u noiseAdd;
Bit32u noiseValue;
//Frequency scales for the different multiplications
Bit32u freqMul[16];
//Rates for decay and release for rate of this chip
Bit32u linearRates[76];
//Best match attack rates for the rate of this chip
Bit32u attackRates[76];
//18 channels with 2 operators each
Channel chan[18];
Bit8u reg104;
Bit8u reg08;
Bit8u reg04;
Bit8u regBD;
Bit8u vibratoIndex;
Bit8u tremoloIndex;
Bit8s vibratoSign;
Bit8u vibratoShift;
Bit8u tremoloValue;
Bit8u vibratoStrength;
Bit8u tremoloStrength;
//Mask for allowed wave forms
Bit8u waveFormMask;
//0 or -1 when enabled
Bit8s opl3Active;
//Return the maximum amount of samples before and LFO change
Bit32u ForwardLFO( Bit32u samples );
Bit32u ForwardNoise();
void WriteBD( Bit8u val );
void WriteReg(Bit32u reg, Bit8u val );
Bit32u WriteAddr( Bit32u port, Bit8u val );
void GenerateBlock2( Bitu samples, Bit32s* output );
void GenerateBlock3( Bitu samples, Bit32s* output );
void Setup( Bit32u c, Bit32u r );
Chip();
};
/*struct Handler : public Adlib::Handler {
DBOPL::Chip chip;
virtual Bit32u WriteAddr( Bit32u port, Bit8u val );
virtual void WriteReg( Bit32u addr, Bit8u val );
virtual void Generate( MixerChannel* chan, Bitu samples );
virtual void Init( Bitu rate );
};*/
} //Namespace

View file

@ -1,18 +0,0 @@
static Uint32 DivFix(Uint32 p1, Uint32 p2, Uint32 fix)
{
Uint32 ret;
ret = p1 / p2;
p1 = p1 % p2;/* p1 = p1 - p2 * ret; */
while (fix--)
{
p1 += p1;
ret += ret;
if (p1 >= p2)
{
p1 -= p2;
ret++;
}
}
return ret;
}

View file

@ -1,78 +0,0 @@
/////////////////////////////////////////////////////////////////////////////
//
// Configuration for emulation libraries
//
/////////////////////////////////////////////////////////////////////////////
#ifndef __EMUCONFIG_H__
#define __EMUCONFIG_H__
/////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
/////////////////////////////////////////////////////////////////////////////
//
// WIN32 native project definitions
//
/////////////////////////////////////////////////////////////////////////////
#if defined(WIN32) && !defined(__GNUC__)
#define EMU_CALL __fastcall
#define EMU_CALL_ __cdecl
#define EMU_INLINE __inline
#define uint8 unsigned char
#define uint16 unsigned short
#define uint32 unsigned int
#define uint64 unsigned __int64
#define sint8 signed char
#define sint16 signed short
#define sint32 signed int
#define sint64 signed __int64
/////////////////////////////////////////////////////////////////////////////
//
// LINUX / other platform definitions
//
/////////////////////////////////////////////////////////////////////////////
#else
//#if defined(__GNUC__) && defined(__i386__)
//#define EMU_CALL __attribute__((__regparm__(2)))
//#else
#define EMU_CALL
//#endif
#define EMU_CALL_
#define EMU_INLINE __inline
#ifdef HAVE_STDINT_H
#include <stdint.h>
#define uint8 uint8_t
#define uint16 uint16_t
#define uint32 uint32_t
#define uint64 uint64_t
#define sint8 int8_t
#define sint16 int16_t
#define sint32 int32_t
#define sint64 int64_t
#else
#define uint8 unsigned char
#define uint16 unsigned short
#define uint32 unsigned int
#define uint64 unsigned long long
#define sint8 signed char
#define sint16 signed short
#define sint32 signed int
#define sint64 signed long long
#endif
#endif
/////////////////////////////////////////////////////////////////////////////
#endif

View file

@ -1,38 +0,0 @@
0x49, 0x4C, 0x4C, 0x32, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x33, 0x21, 0x09, 0x0E, 0x94, 0x90, 0x48, 0xF8,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x13, 0x41, 0x0F, 0x0D, 0xCE, 0xD3, 0x43, 0x13,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x12, 0x1B, 0x06, 0xFF, 0xD2, 0x00, 0x32,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x61, 0x61, 0x1B, 0x07, 0xAF, 0x63, 0x20, 0x28,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x22, 0x21, 0x1E, 0x06, 0xF0, 0x76, 0x08, 0x28,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x66, 0x21, 0x15, 0x00, 0x93, 0x94, 0x20, 0xF8,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x21, 0x61, 0x1C, 0x07, 0x82, 0x81, 0x10, 0x17,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x23, 0x21, 0x20, 0x1F, 0xC0, 0x71, 0x07, 0x47,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x25, 0x31, 0x26, 0x05, 0x64, 0x41, 0x18, 0xF8,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x17, 0x21, 0x28, 0x07, 0xFF, 0x83, 0x02, 0xF8,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x97, 0x81, 0x25, 0x07, 0xCF, 0xC8, 0x02, 0x14,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x21, 0x21, 0x54, 0x0F, 0x80, 0x7F, 0x07, 0x07,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x01, 0x56, 0x03, 0xD3, 0xB2, 0x43, 0x58,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x31, 0x21, 0x0C, 0x03, 0x82, 0xC0, 0x40, 0x07,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x21, 0x01, 0x0C, 0x03, 0xD4, 0xD3, 0x40, 0x84,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x04, 0x21, 0x28, 0x00, 0xDF, 0xF8, 0xFF, 0xF8,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x23, 0x22, 0x00, 0x00, 0xA8, 0xF8, 0xF8, 0xF8,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x25, 0x18, 0x00, 0x00, 0xF8, 0xA9, 0xF8, 0x55,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

View file

@ -1,38 +0,0 @@
0x49, 0x4C, 0x4C, 0x32, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x61, 0x61, 0x1E, 0x07, 0xF0, 0x7E, 0x07, 0x17,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x13, 0x41, 0x0F, 0x1D, 0xCE, 0xD2, 0x43, 0x13,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0x01, 0x99, 0x04, 0xFF, 0xC3, 0x03, 0x73,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x21, 0x61, 0x1B, 0x07, 0xAF, 0x63, 0x40, 0x28,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x22, 0x21, 0x1E, 0x06, 0xF0, 0x76, 0x08, 0x28,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x31, 0x22, 0x16, 0x05, 0x90, 0x71, 0x00, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x31, 0x61, 0x1D, 0x07, 0x32, 0x81, 0x10, 0x17,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x23, 0x21, 0x2D, 0x16, 0xC0, 0x70, 0x07, 0x07,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x61, 0x21, 0x1B, 0x06, 0x64, 0x65, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x61, 0x61, 0x0C, 0x18, 0x85, 0xA0, 0x79, 0x07,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x23, 0x21, 0x87, 0x11, 0xF0, 0xA4, 0x00, 0xF7,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x97, 0xE1, 0x28, 0x07, 0xFF, 0xF3, 0x02, 0xF8,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x61, 0x10, 0x0C, 0x05, 0xF2, 0xC4, 0x40, 0xC8,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x01, 0x56, 0x03, 0xB4, 0xB2, 0x23, 0x58,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x61, 0x41, 0x89, 0x03, 0xF1, 0xF4, 0xF0, 0x13,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x04, 0x21, 0x28, 0x00, 0xDF, 0xF8, 0xFF, 0xF8,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0F, 0x02, 0x00, 0x00, 0xA7, 0xF7, 0x07, 0x07,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x04, 0x1F, 0x00, 0x00, 0xF8, 0xA9, 0x08, 0x05,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

View file

@ -1,38 +0,0 @@
0x49, 0x4C, 0x4C, 0x32, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x61, 0x61, 0x1E, 0x07, 0xF0, 0x7E, 0x07, 0x17,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x13, 0x41, 0x0F, 0x1D, 0xCE, 0xD2, 0x43, 0x13,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0x01, 0x99, 0x04, 0xFF, 0xC3, 0x03, 0x73,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x21, 0x61, 0x1B, 0x07, 0xAF, 0x63, 0x40, 0x28,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x22, 0x21, 0x1E, 0x06, 0xF0, 0x76, 0x08, 0x28,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x31, 0x22, 0x16, 0x05, 0x90, 0x71, 0x00, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x31, 0x61, 0x1D, 0x07, 0x32, 0x81, 0x10, 0x17,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x23, 0x21, 0x2D, 0x16, 0xC0, 0x70, 0x07, 0x07,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x61, 0x21, 0x1B, 0x06, 0x64, 0x65, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x61, 0x61, 0x0C, 0x18, 0x85, 0xA0, 0x79, 0x07,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x23, 0x21, 0x87, 0x11, 0xF0, 0xA4, 0x00, 0xF7,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x97, 0xE1, 0x28, 0x07, 0xFF, 0xF3, 0x02, 0xF8,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x61, 0x10, 0x0C, 0x05, 0xF2, 0xC4, 0x40, 0xC8,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x01, 0x56, 0x03, 0xB4, 0xB2, 0x23, 0x58,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x61, 0x41, 0x89, 0x03, 0xF1, 0xF4, 0xF0, 0x13,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x04, 0x21, 0x28, 0x00, 0xDF, 0xF8, 0xFF, 0xF8,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x28, 0x21, 0x00, 0x00, 0xA8, 0xF8, 0xF8, 0xF8,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x25, 0x18, 0x00, 0x00, 0xF8, 0xA9, 0xF8, 0x55,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

View file

@ -1,298 +0,0 @@
/***************************************************************************
Konami 051649 - SCC1 sound as used in Haunted Castle, City Bomber
This file is pieced together by Bryan McPhail from a combination of
Namco Sound, Amuse by Cab, Haunted Castle schematics and whoever first
figured out SCC!
The 051649 is a 5 channel sound generator, each channel gets it's
waveform from RAM (32 bytes per waveform, 8 bit signed data).
This sound chip is the same as the sound chip in some Konami
megaROM cartridges for the MSX. It is actually well researched
and documented:
http://www.msxnet.org/tech/scc
Thanks to Sean Young (sean@mess.org) for some bugfixes.
K052539 is equivalent to this chip except channel 5 does not share
waveforms with channel 4.
***************************************************************************/
#include "mamedef.h"
#include <stdlib.h>
#include <memory.h>
//#include "emu.h"
//#include "streams.h"
#include "k051649.h"
#define FREQBASEBITS 16
/* this structure defines the parameters for a channel */
typedef struct
{
unsigned long counter;
int frequency;
int volume;
int key;
signed char waveform[32]; /* 19991207.CAB */
UINT8 Muted;
} k051649_sound_channel;
typedef struct _k051649_state k051649_state;
struct _k051649_state
{
k051649_sound_channel channel_list[5];
/* global sound parameters */
//sound_stream * stream;
int mclock,rate;
/* mixer tables and internal buffers */
INT16 *mixer_table;
INT16 *mixer_lookup;
short *mixer_buffer;
int f[10];
int cur_reg;
};
/*INLINE k051649_state *get_safe_token(running_device *device)
{
assert(device != NULL);
assert(device->type() == K051649);
return (k051649_state *)downcast<legacy_device_base *>(device)->token();
}*/
/* build a table to divide by the number of voices */
static void make_mixer_table(/*running_machine *machine,*/ k051649_state *info, int voices)
{
int count = voices * 256;
int i;
int gain = 8;
/* allocate memory */
//info->mixer_table = auto_alloc_array(machine, INT16, 512 * voices);
info->mixer_table = (INT16*)malloc(sizeof(INT16) * 512 * voices);
/* find the middle of the table */
info->mixer_lookup = info->mixer_table + (256 * voices);
/* fill in the table - 16 bit case */
for (i = 0; i < count; i++)
{
int val = i * gain * 16 / voices;
if (val > 32767) val = 32767;
info->mixer_lookup[ i] = val;
info->mixer_lookup[-i] = -val;
}
}
/* generate sound to the mix buffer */
//static STREAM_UPDATE( k051649_update )
void k051649_update(void *chip, stream_sample_t **outputs, int samples)
{
k051649_state *info = (k051649_state *) chip;
k051649_sound_channel *voice=info->channel_list;
stream_sample_t *buffer = outputs[0];
stream_sample_t *buffer2 = outputs[1];
short *mix;
int i,v,f,j,k;
/* zap the contents of the mixer buffer */
memset(info->mixer_buffer, 0, samples * sizeof(short));
for (j=0; j<5; j++) {
v=voice[j].volume;
f=voice[j].frequency;
k=voice[j].key;
/* SY 20040109: the SCC produces no sound for freq < 9 */
if (v && f > 8 && k && ! voice[j].Muted)
{
const signed char *w = voice[j].waveform; /* 19991207.CAB */
int c=voice[j].counter;
mix = info->mixer_buffer;
/* add our contribution */
for (i = 0; i < samples; i++)
{
int offs;
/* Amuse source: Cab suggests this method gives greater resolution */
/* Sean Young 20010417: the formula is really: f = clock/(16*(f+1))*/
c+=(long)((((float)info->mclock / (float)((f+1) * 16))*(float)(1<<FREQBASEBITS)) / (float)(info->rate / 32));
offs = (c >> 16) & 0x1f;
*mix++ += (w[offs] * v)>>3;
}
/* update the counter for this voice */
voice[j].counter = c;
}
}
/* mix it down */
mix = info->mixer_buffer;
for (i = 0; i < samples; i++)
*buffer++ = *buffer2++ = info->mixer_lookup[*mix++];
}
//static DEVICE_START( k051649 )
void * device_start_k051649(int clock)
{
//k051649_state *info = get_safe_token(device);
k051649_state *info;
UINT8 CurChn;
info = (k051649_state *) calloc(1, sizeof(k051649_state));
/* get stream channels */
//info->rate = device->clock()/16;
info->rate = clock/16;
//info->stream = stream_create(device, 0, 1, info->rate, info, k051649_update);
//info->mclock = device->clock();
info->mclock = clock;
/* allocate a buffer to mix into - 1 second's worth should be more than enough */
//info->mixer_buffer = auto_alloc_array(device->machine, short, 2 * info->rate);
info->mixer_buffer = (short*)malloc(sizeof(short) * info->rate);
/* build the mixer table */
//make_mixer_table(device->machine, info, 5);
make_mixer_table(info, 5);
for (CurChn = 0; CurChn < 5; CurChn ++)
info->channel_list[CurChn].Muted = 0x00;
return info; //return info->rate;
}
void device_stop_k051649(void *chip)
{
k051649_state *info = (k051649_state *) chip;
free(info->mixer_buffer);
free(info->mixer_table);
free(info);
}
//static DEVICE_RESET( k051649 )
void device_reset_k051649(void *chip)
{
k051649_state *info = (k051649_state *) chip;
k051649_sound_channel *voice = info->channel_list;
int i;
/* reset all the voices */
for (i = 0; i < 5; i++) {
voice[i].frequency = 0;
voice[i].volume = 0;
voice[i].counter = 0;
}
}
/********************************************************************************/
//WRITE8_DEVICE_HANDLER( k051649_waveform_w )
void k051649_waveform_w(void *chip, offs_t offset, UINT8 data)
{
k051649_state *info = (k051649_state *) chip;
//stream_update(info->stream);
info->channel_list[offset>>5].waveform[offset&0x1f]=data;
/* SY 20001114: Channel 5 shares the waveform with channel 4 */
if (offset >= 0x60)
info->channel_list[4].waveform[offset&0x1f]=data;
}
//READ8_DEVICE_HANDLER ( k051649_waveform_r )
UINT8 k051649_waveform_r(void *chip, offs_t offset)
{
k051649_state *info = (k051649_state *) chip;
return info->channel_list[offset>>5].waveform[offset&0x1f];
}
/* SY 20001114: Channel 5 doesn't share the waveform with channel 4 on this chip */
//WRITE8_DEVICE_HANDLER( k052539_waveform_w )
void k052539_waveform_w(void *chip, offs_t offset, UINT8 data)
{
k051649_state *info = (k051649_state *) chip;
//stream_update(info->stream);
info->channel_list[offset>>5].waveform[offset&0x1f]=data;
}
//WRITE8_DEVICE_HANDLER( k051649_volume_w )
void k051649_volume_w(void *chip, offs_t offset, UINT8 data)
{
k051649_state *info = (k051649_state *) chip;
//stream_update(info->stream);
info->channel_list[offset&0x7].volume=data&0xf;
}
//WRITE8_DEVICE_HANDLER( k051649_frequency_w )
void k051649_frequency_w(void *chip, offs_t offset, UINT8 data)
{
k051649_state *info = (k051649_state *) chip;
info->f[offset]=data;
//stream_update(info->stream);
info->channel_list[offset>>1].frequency=(info->f[offset&0xe] + (info->f[offset|1]<<8))&0xfff;
}
//WRITE8_DEVICE_HANDLER( k051649_keyonoff_w )
void k051649_keyonoff_w(void *chip, offs_t offset, UINT8 data)
{
k051649_state *info = (k051649_state *) chip;
//stream_update(info->stream);
info->channel_list[0].key=data&1;
info->channel_list[1].key=data&2;
info->channel_list[2].key=data&4;
info->channel_list[3].key=data&8;
info->channel_list[4].key=data&16;
}
void k051649_w(void *chip, offs_t offset, UINT8 data)
{
k051649_state *info = (k051649_state *) chip;
switch(offset & 1)
{
case 0x00:
info->cur_reg = data;
break;
case 0x01:
switch(offset >> 1)
{
case 0x00:
k051649_waveform_w(info, info->cur_reg, data);
break;
case 0x01:
k051649_frequency_w(info, info->cur_reg, data);
break;
case 0x02:
k051649_volume_w(info, info->cur_reg, data);
break;
case 0x03:
k051649_keyonoff_w(info, info->cur_reg, data);
break;
case 0x04:
k052539_waveform_w(info, info->cur_reg, data);
break;
}
break;
}
return;
}
void k051649_set_mute_mask(void *chip, UINT32 MuteMask)
{
k051649_state *info = (k051649_state *) chip;
UINT8 CurChn;
for (CurChn = 0; CurChn < 5; CurChn ++)
info->channel_list[CurChn].Muted = (MuteMask >> CurChn) & 0x01;
}

View file

@ -1,45 +0,0 @@
#pragma once
#include "mamedef.h"
#ifdef __cplusplus
extern "C" {
#endif
//#ifndef __K051649_H__
//#define __K051649_H__
//#include "devlegcy.h"
/*WRITE8_DEVICE_HANDLER( k051649_waveform_w );
READ8_DEVICE_HANDLER( k051649_waveform_r );
WRITE8_DEVICE_HANDLER( k051649_volume_w );
WRITE8_DEVICE_HANDLER( k051649_frequency_w );
WRITE8_DEVICE_HANDLER( k051649_keyonoff_w );
WRITE8_DEVICE_HANDLER( k052539_waveform_w );
DECLARE_LEGACY_SOUND_DEVICE(K051649, k051649);*/
void k051649_update(void *, stream_sample_t **outputs, int samples);
void * device_start_k051649(int clock);
void device_stop_k051649(void *);
void device_reset_k051649(void *);
void k051649_waveform_w(void *, offs_t offset, UINT8 data);
UINT8 k051649_waveform_r(void *, offs_t offset);
void k051649_volume_w(void *, offs_t offset, UINT8 data);
void k051649_frequency_w(void *, offs_t offset, UINT8 data);
void k051649_keyonoff_w(void *, offs_t offset, UINT8 data);
void k052539_waveform_w(void *, offs_t offset, UINT8 data);
void k051649_w(void *, offs_t offset, UINT8 data);
void k051649_set_mute_mask(void *, UINT32 MuteMask);
//#endif /* __K051649_H__ */
#ifdef __cplusplus
};
#endif

View file

@ -1,31 +0,0 @@
/* libnezp by Mamiya */
#ifndef KMSNDDEV_H__
#define KMSNDDEV_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "nestypes.h"
typedef struct KMIF_SOUND_DEVICE {
void *ctx;
void (*release)(void *ctx);
void (*reset)(void *ctx, Uint32 clock, Uint32 freq);
int (*synth)(void *ctx);
void (*volume)(void *ctx, Int32 v);
void (*write)(void *ctx, Uint32 a, Uint32 v);
Uint32 (*read)(void *ctx, Uint32 a);
void (*setinst)(void *ctx, Uint32 n, void *p, Uint32 l);
#if 0
void (*setrate)(void *ctx, Uint32 clock, Uint32 freq);
void (*getinfo)(void *ctx, KMCH_INFO *cip, );
void (*volume2)(void *ctx, Uint8 *volp, Uint32 numch);
/* 0x00(mute),0x70(x1/2),0x80(x1),0x90(x2) */
#endif
} KMIF_SOUND_DEVICE;
#ifdef __cplusplus
}
#endif
#endif /* KMSNDDEV_H__ */

View file

@ -1,15 +0,0 @@
#ifndef MATHDEFS_H
#define MATHDEFS_H
#ifndef _USE_MATH_DEFINES
#define _USE_MATH_DEFINES
#endif
#include <math.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#endif

View file

@ -1,39 +0,0 @@
#ifndef NESTYPES_H__
#define NESTYPES_H__
#if defined(_MSC_VER)
#define NEVER_REACH __assume(0);
#define inline __inline
#elif defined(__BORLANDC__)
#define __fastcall __msfastcall
#elif defined(__GNUC__)
#define __inline __inline__
#define __fastcall
#else
#define __inline
#define __fastcall
#endif
#ifndef NEVER_REACH
#define NEVER_REACH
#endif
typedef int Int;
typedef unsigned int Uint;
typedef signed int Int32;
typedef unsigned int Uint32;
typedef signed short Int16;
typedef unsigned short Uint16;
typedef signed char Int8;
typedef unsigned char Uint8;
typedef char Char;
#include <stdlib.h>
#define XSLEEP(n) ((void)0)
#define XMALLOC(s) malloc(s)
#define XREALLOC(p,s) realloc(p,s)
#define XFREE(p) free(p)
#define XMEMCPY(d,s,n) memcpy(d,s,n)
#define XMEMSET(d,c,n) memset(d,c,n)
#endif /* NESTYPES_H__ */

View file

@ -1,462 +0,0 @@
/////////////////////////////////////////////////////////////////////////////
//
// qmix - QSound mixer
//
/////////////////////////////////////////////////////////////////////////////
#include "qmix.h"
/////////////////////////////////////////////////////////////////////////////
#define ANTICLICK_TIME (64)
#define ANTICLICK_THRESHHOLD (32)
/////////////////////////////////////////////////////////////////////////////
#define RENDERMAX (200)
/////////////////////////////////////////////////////////////////////////////
static const sint32 gauss_shuffled_reverse_table[1024] = {
366,1305, 374, 0, 362,1304, 378, 0, 358,1304, 381, 0, 354,1304, 385, 0, 351,1304, 389, 0, 347,1304, 393, 0, 343,1303, 397, 0, 339,1303, 401, 0,
336,1303, 405, 0, 332,1302, 410, 0, 328,1302, 414, 0, 325,1301, 418, 0, 321,1300, 422, 0, 318,1300, 426, 0, 314,1299, 430, 0, 311,1298, 434, 0,
307,1297, 439, 1, 304,1297, 443, 1, 300,1296, 447, 1, 297,1295, 451, 1, 293,1294, 456, 1, 290,1293, 460, 1, 286,1292, 464, 1, 283,1291, 469, 1,
280,1290, 473, 1, 276,1288, 477, 1, 273,1287, 482, 1, 270,1286, 486, 2, 267,1284, 491, 2, 263,1283, 495, 2, 260,1282, 499, 2, 257,1280, 504, 2,
254,1279, 508, 2, 251,1277, 513, 2, 248,1275, 517, 3, 245,1274, 522, 3, 242,1272, 527, 3, 239,1270, 531, 3, 236,1269, 536, 3, 233,1267, 540, 4,
230,1265, 545, 4, 227,1263, 550, 4, 224,1261, 554, 4, 221,1259, 559, 4, 218,1257, 563, 5, 215,1255, 568, 5, 212,1253, 573, 5, 210,1251, 577, 5,
207,1248, 582, 6, 204,1246, 587, 6, 201,1244, 592, 6, 199,1241, 596, 6, 196,1239, 601, 7, 193,1237, 606, 7, 191,1234, 611, 7, 188,1232, 615, 8,
186,1229, 620, 8, 183,1227, 625, 8, 180,1224, 630, 9, 178,1221, 635, 9, 175,1219, 640, 9, 173,1216, 644, 10, 171,1213, 649, 10, 168,1210, 654, 10,
166,1207, 659, 11, 163,1205, 664, 11, 161,1202, 669, 11, 159,1199, 674, 12, 156,1196, 678, 12, 154,1193, 683, 13, 152,1190, 688, 13, 150,1186, 693, 14,
147,1183, 698, 14, 145,1180, 703, 15, 143,1177, 708, 15, 141,1174, 713, 15, 139,1170, 718, 16, 137,1167, 723, 16, 134,1164, 728, 17, 132,1160, 732, 17,
130,1157, 737, 18, 128,1153, 742, 19, 126,1150, 747, 19, 124,1146, 752, 20, 122,1143, 757, 20, 120,1139, 762, 21, 118,1136, 767, 21, 117,1132, 772, 22,
115,1128, 777, 23, 113,1125, 782, 23, 111,1121, 787, 24, 109,1117, 792, 24, 107,1113, 797, 25, 106,1109, 802, 26, 104,1106, 806, 27, 102,1102, 811, 27,
100,1098, 816, 28, 99,1094, 821, 29, 97,1090, 826, 29, 95,1086, 831, 30, 94,1082, 836, 31, 92,1078, 841, 32, 90,1074, 846, 32, 89,1070, 851, 33,
87,1066, 855, 34, 86,1061, 860, 35, 84,1057, 865, 36, 83,1053, 870, 36, 81,1049, 875, 37, 80,1045, 880, 38, 78,1040, 884, 39, 77,1036, 889, 40,
76,1032, 894, 41, 74,1027, 899, 42, 73,1023, 904, 43, 71,1019, 908, 44, 70,1014, 913, 45, 69,1010, 918, 46, 67,1005, 923, 47, 66,1001, 927, 48,
65, 997, 932, 49, 64, 992, 937, 50, 62, 988, 941, 51, 61, 983, 946, 52, 60, 978, 951, 53, 59, 974, 955, 54, 58, 969, 960, 55, 56, 965, 965, 56,
55, 960, 969, 58, 54, 955, 974, 59, 53, 951, 978, 60, 52, 946, 983, 61, 51, 941, 988, 62, 50, 937, 992, 64, 49, 932, 997, 65, 48, 927,1001, 66,
47, 923,1005, 67, 46, 918,1010, 69, 45, 913,1014, 70, 44, 908,1019, 71, 43, 904,1023, 73, 42, 899,1027, 74, 41, 894,1032, 76, 40, 889,1036, 77,
39, 884,1040, 78, 38, 880,1045, 80, 37, 875,1049, 81, 36, 870,1053, 83, 36, 865,1057, 84, 35, 860,1061, 86, 34, 855,1066, 87, 33, 851,1070, 89,
32, 846,1074, 90, 32, 841,1078, 92, 31, 836,1082, 94, 30, 831,1086, 95, 29, 826,1090, 97, 29, 821,1094, 99, 28, 816,1098, 100, 27, 811,1102, 102,
27, 806,1106, 104, 26, 802,1109, 106, 25, 797,1113, 107, 24, 792,1117, 109, 24, 787,1121, 111, 23, 782,1125, 113, 23, 777,1128, 115, 22, 772,1132, 117,
21, 767,1136, 118, 21, 762,1139, 120, 20, 757,1143, 122, 20, 752,1146, 124, 19, 747,1150, 126, 19, 742,1153, 128, 18, 737,1157, 130, 17, 732,1160, 132,
17, 728,1164, 134, 16, 723,1167, 137, 16, 718,1170, 139, 15, 713,1174, 141, 15, 708,1177, 143, 15, 703,1180, 145, 14, 698,1183, 147, 14, 693,1186, 150,
13, 688,1190, 152, 13, 683,1193, 154, 12, 678,1196, 156, 12, 674,1199, 159, 11, 669,1202, 161, 11, 664,1205, 163, 11, 659,1207, 166, 10, 654,1210, 168,
10, 649,1213, 171, 10, 644,1216, 173, 9, 640,1219, 175, 9, 635,1221, 178, 9, 630,1224, 180, 8, 625,1227, 183, 8, 620,1229, 186, 8, 615,1232, 188,
7, 611,1234, 191, 7, 606,1237, 193, 7, 601,1239, 196, 6, 596,1241, 199, 6, 592,1244, 201, 6, 587,1246, 204, 6, 582,1248, 207, 5, 577,1251, 210,
5, 573,1253, 212, 5, 568,1255, 215, 5, 563,1257, 218, 4, 559,1259, 221, 4, 554,1261, 224, 4, 550,1263, 227, 4, 545,1265, 230, 4, 540,1267, 233,
3, 536,1269, 236, 3, 531,1270, 239, 3, 527,1272, 242, 3, 522,1274, 245, 3, 517,1275, 248, 2, 513,1277, 251, 2, 508,1279, 254, 2, 504,1280, 257,
2, 499,1282, 260, 2, 495,1283, 263, 2, 491,1284, 267, 2, 486,1286, 270, 1, 482,1287, 273, 1, 477,1288, 276, 1, 473,1290, 280, 1, 469,1291, 283,
1, 464,1292, 286, 1, 460,1293, 290, 1, 456,1294, 293, 1, 451,1295, 297, 1, 447,1296, 300, 1, 443,1297, 304, 1, 439,1297, 307, 0, 434,1298, 311,
0, 430,1299, 314, 0, 426,1300, 318, 0, 422,1300, 321, 0, 418,1301, 325, 0, 414,1302, 328, 0, 410,1302, 332, 0, 405,1303, 336, 0, 401,1303, 339,
0, 397,1303, 343, 0, 393,1304, 347, 0, 389,1304, 351, 0, 385,1304, 354, 0, 381,1304, 358, 0, 378,1304, 362, 0, 374,1305, 366, 0, 370,1305, 370,
};
static const sint32 pan_table[33] = {
0, 724,1024,1254,1448,1619,1774,1916,
2048,2172,2290,2401,2508,2611,2709,2804,
2896,2985,3072,3156,3238,3318,3396,3473,
3547,3620,3692,3762,3831,3899,3966,4031,
4096};
/////////////////////////////////////////////////////////////////////////////
//
// Static information
//
sint32 EMU_CALL _qmix_init(void) { return 0; }
/////////////////////////////////////////////////////////////////////////////
//
// State information
//
#define QMIXSTATE ((struct QMIX_STATE*)(state))
struct QMIX_CHAN {
uint32 on;
uint32 startbank;
uint32 startaddr;
uint32 curbank;
uint32 curaddr;
uint32 startloop;
uint32 startend;
uint32 curloop;
uint32 curend;
uint32 phase;
uint32 pitch;
uint32 vol;
uint32 pan;
sint32 current_mix_l;
sint32 current_mix_r;
sint32 sample[4];
sint32 sample_last_l;
sint32 sample_last_r;
sint32 sample_anticlick_l;
sint32 sample_anticlick_r;
sint32 sample_anticlick_remaining_l;
sint32 sample_anticlick_remaining_r;
};
/////////////////////////////////////////////////////////////////////////////
static EMU_INLINE void get_anticlicked_samples(
struct QMIX_CHAN *chan, sint32 *l, sint32 *r
) {
sint32 out, remain;
remain = chan->sample_anticlick_remaining_l;
if(remain) {
sint32 diff = chan->sample_last_l - chan->sample_anticlick_l;
if(diff < 0) { diff = -diff; }
if(diff < ANTICLICK_THRESHHOLD) {
out = chan->sample_last_l;
chan->sample_anticlick_remaining_l = 0;
} else {
out = (
chan->sample_last_l * (ANTICLICK_TIME-remain) +
chan->sample_anticlick_l * (remain)
) / ANTICLICK_TIME;
chan->sample_anticlick_remaining_l--;
}
} else {
out = chan->sample_last_l;
}
*l = out;
remain = chan->sample_anticlick_remaining_r;
if(remain) {
sint32 diff = chan->sample_last_r - chan->sample_anticlick_r;
if(diff < 0) { diff = -diff; }
if(diff < ANTICLICK_THRESHHOLD) {
out = chan->sample_last_r;
chan->sample_anticlick_remaining_r = 0;
} else {
out = (
chan->sample_last_r * (ANTICLICK_TIME-remain) +
chan->sample_anticlick_r * (remain)
) / ANTICLICK_TIME;
chan->sample_anticlick_remaining_r--;
}
} else {
out = chan->sample_last_r;
}
*r = out;
}
/////////////////////////////////////////////////////////////////////////////
static EMU_INLINE void anticlick(struct QMIX_CHAN *chan) {
sint32 l, r;
get_anticlicked_samples(chan, &l, &r);
chan->sample_anticlick_l = l;
chan->sample_anticlick_r = r;
chan->sample_anticlick_remaining_l = ANTICLICK_TIME;
chan->sample_anticlick_remaining_r = ANTICLICK_TIME;
}
/////////////////////////////////////////////////////////////////////////////
struct QMIX_STATE {
uint8 *sample_rom;
uint32 sample_rom_size;
uint32 pitchscaler;
struct QMIX_CHAN chan[16];
sint32 last_in_l;
sint32 last_in_r;
sint32 last_out_l;
sint32 last_out_r;
sint32 acc_l;
sint32 acc_r;
};
uint32 EMU_CALL _qmix_get_state_size(void) {
return sizeof(struct QMIX_STATE);
}
void EMU_CALL _qmix_clear_state(void *state) {
memset(state, 0, sizeof(struct QMIX_STATE));
}
void EMU_CALL _qmix_set_sample_rom(void *state, void *rom, uint32 size) {
QMIXSTATE->sample_rom = rom;
QMIXSTATE->sample_rom_size = size;
}
/////////////////////////////////////////////////////////////////////////////
static EMU_INLINE void chan_advance(
struct QMIX_STATE *state,
struct QMIX_CHAN *chan
) {
uint32 rom_addr = chan->curbank + chan->curaddr;
if(rom_addr >= state->sample_rom_size) rom_addr = 0;
chan->sample[0] = chan->sample[1];
chan->sample[1] = chan->sample[2];
chan->sample[2] = chan->sample[3];
chan->sample[3] = (sint32)((sint8)(state->sample_rom[rom_addr]));
chan->curaddr++;
// FIXME: MAME thinks this is >=, but is it > ?
if(chan->curaddr >= chan->curend) {
// if(!chan->curloop) {
// chan->on = 0;
// chan->curaddr--;
// } else {
chan->curaddr = chan->curend - chan->curloop;
// chan->curaddr -= 1 + chan->curloop;
// }
}
chan->curaddr &= 0xFFFF;
}
/////////////////////////////////////////////////////////////////////////////
static EMU_INLINE sint32 chan_get_resampled(
struct QMIX_STATE *state,
struct QMIX_CHAN *chan
) {
sint32 sum;
sint32 phase = chan->phase & 0xFFF;
// sum = chan->sample[2];
// sum <<= 8;
const sint32 *gauss = (sint32*)
(((sint8*)gauss_shuffled_reverse_table) + (phase & 0x0FF0));
sum = chan->sample[0] * gauss[0];
sum += chan->sample[1] * gauss[1];
sum += chan->sample[2] * gauss[2];
sum += chan->sample[3] * gauss[3];
sum /= 8;
// sum = chan->sample[1] * (0x1000-phase);
// sum += chan->sample[2] * ( phase);
// sum >>= 4;
chan->phase += chan->pitch;
while(chan->phase >= 0x1000) {
chan_advance(state, chan);
chan->phase -= 0x1000;
}
return sum;
}
static EMU_INLINE void chan_get_stereo_anticlicked(
struct QMIX_STATE *state,
struct QMIX_CHAN *chan,
sint32 *l,
sint32 *r
) {
if(!chan->on) {
chan->sample_last_l = 0;
chan->sample_last_r = 0;
} else {
sint32 out = chan_get_resampled(state, chan);
chan->sample_last_l = (out * chan->current_mix_l) / 0x8000;
chan->sample_last_r = (out * chan->current_mix_r) / 0x8000;
// if we suddenly keyed off, perform an anticlick here
if(!chan->on) { anticlick(chan); }
}
get_anticlicked_samples(chan, l, r);
}
/////////////////////////////////////////////////////////////////////////////
static void recalc_mix(struct QMIX_CHAN *chan) {
sint32 realpan = (chan->pan & 0x3F) - 0x10;
sint32 realvol = chan->vol & 0xFFFF;
if(realpan < 0x00) realpan = 0x00;
if(realpan > 0x20) realpan = 0x20;
// chan->current_mix_l = realvol << 3;
// chan->current_mix_r = realvol << 3;
// if(realpan < 0x10) {
// chan->current_mix_r *= realpan;
// chan->current_mix_r >>= 4;
// }
// if(realpan > 0x10) {
// chan->current_mix_l *= (0x20-realpan);
// chan->current_mix_l >>= 4;
// }
// chan->current_mix_l = ((0x20-realpan) * realvol) >> 1;
// chan->current_mix_r = (( realpan) * realvol) >> 1;
chan->current_mix_l = (realvol * pan_table[0x20-realpan]) / 0x2000;
chan->current_mix_r = (realvol * pan_table[ realpan]) / 0x2000;
// perform anticlick
//anticlick(chan);
}
/////////////////////////////////////////////////////////////////////////////
//
// Command handling
//
//#include <stdio.h>
void EMU_CALL _qmix_command(void *state, uint8 cmd, uint16 data) {
struct QMIX_CHAN *chan;
uint32 ch = 0;
uint32 reg = 99;
//printf("qmix command 0x%02X:0x%04X\n",cmd,data);
if(cmd < 0x80) {
reg = cmd & 7;
ch = cmd >> 3;
} else if(cmd < 0x90) {
reg = 8;
ch = cmd - 0x80;
} else if(cmd >= 0xBA && cmd < 0xCA) {
reg = 9;
ch = cmd - 0xBA;
} else {
reg = 99;
ch = 0;
}
chan = QMIXSTATE->chan + ch;
switch(reg) {
case 0: // bank
ch = (ch+1) & 0xF; chan = QMIXSTATE->chan + ch;
//printf("qmix: bank ch%X = %04X\n",ch,data);
chan->startbank = (((uint32)data) & 0x7F) << 16;
break;
case 1: // start
//printf("qmix: start ch%X = %04X\n",ch,data);
chan->startaddr = ((uint32)data) & 0xFFFF;
break;
case 2: // pitch
//printf("qmix: pitch ch%X = %04X\n",ch,data);
chan->pitch = (((uint32)(data & 0xFFFF)) * QMIXSTATE->pitchscaler) / 0x10000;
if (chan->pitch == 0) {
chan->on = 0;
anticlick(chan);
}
break;
case 3: // unknown
break;
case 4: // loop start
//printf("qmix: loop ch%X = %04X\n",ch,data);
chan->startloop = data;
break;
case 5: // end
//printf("qmix: end ch%X = %04X\n",ch,data);
chan->startend = data;
break;
case 6: // volume
//printf("qmix: vol ch%X = %04X\n",ch,data);
//printf("volume=%04X\n",data);
// if(!data) {
// chan->on = 0;
// } else {
// chan->on = 1;
// chan->address = chan->start;
// chan->phase = 0;
// }
//printf("qmix: unknown reg3 ch%X = %04X\n",ch,data);
if(data == 0) {
chan->on = 0;
anticlick(chan);
} else if (chan->on == 0) {
chan->on = 1;
chan->curbank = chan->startbank;
chan->curaddr = chan->startaddr;
chan->curloop = chan->startloop;
chan->curend = chan->startend;
chan->phase = 0;
chan->sample[0] = 0;
chan->sample[1] = 0;
chan->sample[2] = 0;
chan->sample[3] = 0;
anticlick(chan);
}
chan->vol = data;
recalc_mix(chan);
break;
case 7: // unknown
//printf("qmix: unknown reg7 ch%X = %04X\n",ch,data);
break;
case 8: // pan (0x110-0x130)
//printf("qmix: pan ch%X = %04X\n",ch,data);
//printf("pan=%04X\n",data);
chan->pan = data;
recalc_mix(chan);
break;
case 9: // ADSR?
//printf("qmix: unknown reg9 ch%X = %04X\n",ch,data);
break;
default:
//printf("qmix: unknown reg %02X = %04X\n",cmd,data);
break;
}
}
/////////////////////////////////////////////////////////////////////////////
//
// Rendering
//
static void render(
struct QMIX_STATE *state,
sint16 *buf,
uint32 samples
) {
sint32 buf_l[RENDERMAX];
sint32 buf_r[RENDERMAX];
sint32 l, r;
uint32 s;
int ch;
memset(buf_l, 0, 4 * samples);
memset(buf_r, 0, 4 * samples);
for(ch = 0; ch < 16; ch++) {
struct QMIX_CHAN *chan = state->chan + ch;
for(s = 0; s < samples; s++) {
chan_get_stereo_anticlicked(state, chan, &l, &r);
buf_l[s] += l;
buf_r[s] += r;
}
}
if(!buf) return;
for(s = 0; s < samples; s++) {
sint32 diff_l = buf_l[s] - state->last_in_l;
sint32 diff_r = buf_r[s] - state->last_in_r;
state->last_in_l = buf_l[s];
state->last_in_r = buf_r[s];
l = ((state->last_out_l * 255) / 256) + diff_l;
r = ((state->last_out_r * 255) / 256) + diff_r;
state->last_out_l = l;
state->last_out_r = r;
// l /= 2;
// r /= 2;
l *= 8;
r *= 8;
if(l > ( 32767)) l = ( 32767);
if(l < (-32768)) l = (-32768);
if(r > ( 32767)) r = ( 32767);
if(r < (-32768)) r = (-32768);
*buf++ = l;
*buf++ = r;
}
}
/////////////////////////////////////////////////////////////////////////////
void EMU_CALL _qmix_render(void *state, sint16 *buf, uint32 samples) {
//printf("qmix render %u samples\n",samples);
for(; samples >= RENDERMAX; samples -= RENDERMAX) {
render(QMIXSTATE, buf, RENDERMAX);
if(buf) buf += 2 * RENDERMAX;
}
if(samples) {
render(QMIXSTATE, buf, samples);
}
}
/////////////////////////////////////////////////////////////////////////////
void EMU_CALL _qmix_set_sample_rate(void *state, uint32 rate) {
if(rate < 1) rate = 1;
QMIXSTATE->pitchscaler = (65536 * 24000) / rate;
}
/////////////////////////////////////////////////////////////////////////////

View file

@ -1,29 +0,0 @@
/////////////////////////////////////////////////////////////////////////////
//
// qmix - QSound mixer
//
/////////////////////////////////////////////////////////////////////////////
#ifndef __Q_QMIX_H__
#define __Q_QMIX_H__
#include "emuconfig.h"
#ifdef __cplusplus
extern "C" {
#endif
sint32 EMU_CALL _qmix_init(void);
uint32 EMU_CALL _qmix_get_state_size(void);
void EMU_CALL _qmix_clear_state(void *state);
void EMU_CALL _qmix_set_sample_rate(void *state, uint32 rate);
void EMU_CALL _qmix_set_sample_rom(void *state, void *rom, uint32 size);
void EMU_CALL _qmix_command(void *state, uint8 cmd, uint16 data);
void EMU_CALL _qmix_render(void *state, sint16 *buf, uint32 samples);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -1,281 +0,0 @@
#include "kmsnddev.h"
#include "divfix.h"
#include "s_logtbl.h"
#include "s_deltat.h"
#include <string.h>
#define CPS_SHIFT 16
#define PHASE_SHIFT 16 /* 16(fix) */
typedef struct {
KMIF_SOUND_DEVICE kmif;
KMIF_LOGTABLE *logtbl;
struct YMDELTATPCMSOUND_COMMON_TAG {
Int32 mastervolume;
Int32 step;
Int32 output;
Uint32 cnt;
Uint32 cps;
Uint32 phase;
Uint32 deltan;
Uint32 scale;
Uint32 mem;
Uint32 play;
Uint32 start;
Uint32 stop;
Int32 level32;
Uint8 key;
Uint8 level;
Uint8 granuality;
Uint8 pad4_3;
Uint8 regs[0x10];
} common;
Uint8 *romrambuf;
Uint32 romrammask;
Uint8 *rambuf;
Uint32 rammask;
Uint8 *rombuf;
Uint32 rommask;
Uint8 ymdeltatpcm_type;
Uint8 memshift;
} YMDELTATPCMSOUND;
static Uint8 const table_step[8] =
{
1, 3, 5, 7, 9, 11, 13, 15,
};
static Uint8 const table_scale[16] =
{
57, 57, 57, 57, 77, 102, 128, 153,
57, 57, 57, 57, 77, 102, 128, 153,
};
__inline static void writeram(YMDELTATPCMSOUND *sndp, Uint32 v)
{
sndp->rambuf[(sndp->common.mem >> 1) & sndp->rammask] = v;
sndp->common.mem += 1 << 1;
}
__inline static Uint32 readram(YMDELTATPCMSOUND *sndp)
{
Uint32 v;
v = sndp->romrambuf[(sndp->common.play >> 1) & sndp->romrammask];
if (sndp->common.play & 1)
v &= 0x0F;
else
v >>= 4;
sndp->common.play += 1;
if (sndp->common.play >= sndp->common.stop)
{
if (sndp->common.regs[0] & 0x10)
{
sndp->common.play = sndp->common.start;
sndp->common.step = 0;
sndp->common.scale = 127;
}
else
{
sndp->common.key = 0;
}
}
return v;
}
__inline static void DelrtatStep(YMDELTATPCMSOUND *sndp, Uint32 data)
{
if (data & 8)
sndp->common.step -= (table_step[data & 7] * sndp->common.scale) >> 3;
else
sndp->common.step += (table_step[data & 7] * sndp->common.scale) >> 3;
if (sndp->common.step > ((1 << 15) - 1)) sndp->common.step = ((1 << 15) - 1);
if (sndp->common.step < -(1 << 15)) sndp->common.step = -(1 << 15);
sndp->common.scale = (sndp->common.scale * table_scale[data]) >> 6;
if (sndp->common.scale > 24576) sndp->common.scale = 24576;
if (sndp->common.scale < 127) sndp->common.scale = 127;
}
#if (((-1) >> 1) == -1)
#define SSR(x, y) (((Int32)x) >> (y))
#else
#define SSR(x, y) (((x) >= 0) ? ((x) >> (y)) : (-((-(x) - 1) >> (y)) - 1))
#endif
static int sndsynth(YMDELTATPCMSOUND *sndp )
{
if (!sndp->common.key)
return 0;
{
Uint32 step;
sndp->common.cnt += sndp->common.cps;
step = sndp->common.cnt >> CPS_SHIFT;
sndp->common.cnt &= (1 << CPS_SHIFT) - 1;
sndp->common.phase += step * sndp->common.deltan;
step = sndp->common.phase >> PHASE_SHIFT;
sndp->common.phase &= (1 << PHASE_SHIFT) - 1;
if (step)
{
do
{
DelrtatStep(sndp, readram(sndp));
} while (--step);
sndp->common.output = sndp->common.step * sndp->common.level32;
sndp->common.output = SSR(sndp->common.output, 8 + 2);
}
}
return sndp->common.output;
}
static void sndwrite(YMDELTATPCMSOUND *sndp, Uint32 a, Uint32 v)
{
sndp->common.regs[a] = v;
switch (a)
{
/* START,REC,MEMDATA,REPEAT,SPOFF,--,--,RESET */
case 0x00: /* Control Register 1 */
if ((v & 0x80) && !sndp->common.key)
{
sndp->common.key = 1;
sndp->common.play = sndp->common.start;
sndp->common.step = 0;
sndp->common.scale = 127;
}
if (v & 1) sndp->common.key = 0;
break;
/* L,R,-,-,SAMPLE,DA/AD,RAMTYPE,ROM */
case 0x01: /* Control Register 2 */
sndp->romrambuf = (sndp->common.regs[1] & 1) ? sndp->rombuf : sndp->rambuf;
sndp->romrammask = (sndp->common.regs[1] & 1) ? sndp->rommask : sndp->rammask;
break;
case 0x02: /* Start Address L */
case 0x03: /* Start Address H */
sndp->common.granuality = (v & 2) ? 1 : 4;
sndp->common.start = ((sndp->common.regs[3] << 8) + sndp->common.regs[2]) << (sndp->memshift + 1);
sndp->common.mem = sndp->common.start;
break;
case 0x04: /* Stop Address L */
case 0x05: /* Stop Address H */
sndp->common.stop = ((sndp->common.regs[5] << 8) + sndp->common.regs[4]) << (sndp->memshift + 1);
break;
case 0x06: /* Prescale L */
case 0x07: /* Prescale H */
break;
case 0x08: /* Data */
if ((sndp->common.regs[0] & 0x60) == 0x60) writeram(sndp, v);
break;
case 0x09: /* Delta-N L */
case 0x0A: /* Delta-N H */
sndp->common.deltan = (sndp->common.regs[0xA] << 8) + sndp->common.regs[0x9];
if (sndp->common.deltan < 0x100) sndp->common.deltan = 0x100;
break;
case 0x0B: /* Level Control */
sndp->common.level = v;
sndp->common.level32 = ((Int32)(sndp->common.level * LogToLin(sndp->logtbl, sndp->common.mastervolume, LOG_LIN_BITS - 15))) >> 7;
sndp->common.output = sndp->common.step * sndp->common.level32;
sndp->common.output = SSR(sndp->common.output, 8 + 2);
break;
}
}
static Uint32 sndread(YMDELTATPCMSOUND *sndp, Uint32 a)
{
return 0;
}
static void sndreset(YMDELTATPCMSOUND *sndp, Uint32 clock, Uint32 freq)
{
XMEMSET(&sndp->common, 0, sizeof(sndp->common));
sndp->common.cps = DivFix(clock, 72 * freq, CPS_SHIFT);
sndp->romrambuf = (sndp->common.regs[1] & 1) ? sndp->rombuf : sndp->rambuf;
sndp->romrammask = (sndp->common.regs[1] & 1) ? sndp->rommask : sndp->rammask;
sndp->common.granuality = 4;
}
static void sndvolume(YMDELTATPCMSOUND *sndp, Int32 volume)
{
volume = (volume << (LOG_BITS - 8)) << 1;
sndp->common.mastervolume = volume;
sndp->common.level32 = ((Int32)(sndp->common.level * LogToLin(sndp->logtbl, sndp->common.mastervolume, LOG_LIN_BITS - 15))) >> 7;
sndp->common.output = sndp->common.step * sndp->common.level32;
sndp->common.output = SSR(sndp->common.output, 8 + 2);
}
static void sndrelease(YMDELTATPCMSOUND *sndp)
{
if (sndp->logtbl) sndp->logtbl->release(sndp->logtbl->ctx);
XFREE(sndp);
}
static void setinst(YMDELTATPCMSOUND *sndp, Uint32 n, void *p, Uint32 l)
{
if (n) return;
if (p)
{
sndp->rombuf = (Uint8*) p;
sndp->rommask = l - 1;
sndp->romrambuf = (sndp->common.regs[1] & 1) ? sndp->rombuf : sndp->rambuf;
sndp->romrammask = (sndp->common.regs[1] & 1) ? sndp->rommask : sndp->rammask;
}
else
{
sndp->rombuf = 0;
sndp->rommask = 0;
}
}
KMIF_SOUND_DEVICE *YMDELTATPCMSoundAlloc(Uint32 ymdeltatpcm_type)
{
Uint32 ram_size;
YMDELTATPCMSOUND *sndp;
switch (ymdeltatpcm_type)
{
case YMDELTATPCM_TYPE_Y8950:
ram_size = 32 * 1024;
break;
case YMDELTATPCM_TYPE_YM2608:
ram_size = 256 * 1024;
break;
default:
ram_size = 0;
break;
}
sndp = (YMDELTATPCMSOUND*) XMALLOC(sizeof(YMDELTATPCMSOUND) + ram_size);
if (!sndp) return 0;
sndp->ymdeltatpcm_type = ymdeltatpcm_type;
switch (ymdeltatpcm_type)
{
case YMDELTATPCM_TYPE_Y8950:
sndp->memshift = 2;
break;
case YMDELTATPCM_TYPE_YM2608:
/* OPNA */
sndp->memshift = 6;
break;
case YMDELTATPCM_TYPE_YM2610:
sndp->memshift = 9;
break;
}
sndp->kmif.ctx = sndp;
sndp->kmif.release = (void (*)( void* )) sndrelease;
sndp->kmif.synth = (int (*)( void* )) sndsynth;
sndp->kmif.volume = (void (*)( void*, int )) sndvolume;
sndp->kmif.reset = (void (*)( void*, Uint32, Uint32 )) sndreset;
sndp->kmif.write = (void (*)( void*, Uint32, Uint32 )) sndwrite;
sndp->kmif.read = (Uint32 (*)( void*, Uint32 )) sndread;
sndp->kmif.setinst = (void (*)( void*, Uint32, void*, Uint32 )) setinst;
/* RAM */
sndp->rambuf = ram_size ? (Uint8 *)(sndp + 1) : 0;
sndp->rammask = ram_size ? (ram_size - 1) : 0;
/* ROM */
sndp->rombuf = 0;
sndp->rommask = 0;
sndp->logtbl = LogTableAddRef();
if (!sndp->logtbl)
{
sndrelease(sndp);
return 0;
}
return &sndp->kmif;
}

View file

@ -1,23 +0,0 @@
#ifndef S_DELTAT_H__
#define S_DELTAT_H__
#include "kmsnddev.h"
#ifdef __cplusplus
extern "C" {
#endif
enum {
/* MSX-AUDIO */ YMDELTATPCM_TYPE_Y8950,
/* OPNA ADPCM */ YMDELTATPCM_TYPE_YM2608,
/* OPNB ADPCMB */ YMDELTATPCM_TYPE_YM2610
};
KMIF_SOUND_DEVICE *YMDELTATPCMSoundAlloc(Uint32 ymdeltatpcm_type);
#ifdef __cplusplus
}
#endif
#endif /* S_DELTAT_H__ */

View file

@ -1,88 +0,0 @@
#include "nestypes.h"
#include "s_logtbl.h"
#if STATIC_TABLES
static void LogTableRelease(void *ctx)
{
}
static KMIF_LOGTABLE log_static_tables = {
&log_static_tables;
LogTableRelease,
#include "s_logt.h"
};
KMIF_LOGTABLE *LogTableAddRef(void)
{
log_static_tables.release = LogTableRelease;
return &log_static_tables;
}
#else
#include <math.h>
static volatile Uint32 log_tables_mutex = 0;
static Uint32 log_tables_refcount = 0;
static KMIF_LOGTABLE *log_tables = 0;
static void LogTableRelease(void *ctx)
{
++log_tables_mutex;
while (log_tables_mutex != 1)
{
XSLEEP(0);
}
log_tables_refcount--;
if (!log_tables_refcount)
{
XFREE(ctx);
log_tables = 0;
}
--log_tables_mutex;
}
static void LogTableCalc(KMIF_LOGTABLE *kmif_lt)
{
Uint32 i;
double a;
for (i = 0; i < (1 << LOG_BITS); i++)
{
a = (1 << LOG_LIN_BITS) / pow(2, i / (double)(1 << LOG_BITS));
kmif_lt->logtbl[i] = (Uint32)a;
}
kmif_lt->lineartbl[0] = LOG_LIN_BITS << LOG_BITS;
for (i = 1; i < (1 << LIN_BITS) + 1; i++)
{
Uint32 ua;
a = i << (LOG_LIN_BITS - LIN_BITS);
ua = (Uint32)((LOG_LIN_BITS - (log(a) / log(2))) * (1 << LOG_BITS));
kmif_lt->lineartbl[i] = ua << 1;
}
}
KMIF_LOGTABLE *LogTableAddRef(void)
{
++log_tables_mutex;
while (log_tables_mutex != 1)
{
XSLEEP(0);
}
if (!log_tables_refcount)
{
log_tables = (KMIF_LOGTABLE*) XMALLOC(sizeof(KMIF_LOGTABLE));
if (log_tables)
{
log_tables->ctx = log_tables;
log_tables->release = LogTableRelease;
LogTableCalc(log_tables);
}
}
if (log_tables) log_tables_refcount++;
--log_tables_mutex;
return log_tables;
}
#endif

View file

@ -1,43 +0,0 @@
#ifndef S_LOGTBL_H__
#define S_LOGTBL_H__
#ifdef __cplusplus
extern "C" {
#endif
#define LOG_BITS 12
#define LIN_BITS 7
#define LOG_LIN_BITS 30
typedef struct
{
void *ctx;
void (*release)(void *ctx);
Uint32 lineartbl[(1 << LIN_BITS) + 1];
Uint32 logtbl[1 << LOG_BITS];
} KMIF_LOGTABLE;
KMIF_LOGTABLE *LogTableAddRef(void);
__inline static Uint32 LinToLog(KMIF_LOGTABLE *kmif_lt, Int32 l)
{
return (l < 0) ? (kmif_lt->lineartbl[-l] + 1) : kmif_lt->lineartbl[l];
}
__inline static Int32 LogToLin(KMIF_LOGTABLE *kmif_lt, Int32 l, Uint32 sft)
{
Int32 ret;
Uint32 ofs;
ofs = l + (sft << (LOG_BITS + 1));
sft = ofs >> (LOG_BITS + 1);
if (sft >= LOG_LIN_BITS) return 0;
ofs = (ofs >> 1) & ((1 << LOG_BITS) - 1);
ret = kmif_lt->logtbl[ofs] >> sft;
return (l & 1) ? -ret : ret;
}
#ifdef __cplusplus
}
#endif
#endif /* S_LOGTBL_H__ */

File diff suppressed because it is too large Load diff

View file

@ -1,26 +0,0 @@
#ifndef S_OPL_H__
#define S_OPL_H__
#include "kmsnddev.h"
#ifdef __cplusplus
extern "C" {
#endif
enum {
OPL_TYPE_OPLL = 0x10, /* YAMAHA YM2413 */
OPL_TYPE_MSXMUSIC = 0x11, /* YAMAHA YM2413 */
OPL_TYPE_SMSFMUNIT = 0x12, /* YAMAHA YM2413? */
OPL_TYPE_VRC7 = 0x13, /* KONAMI 053982 VRV VII */
OPL_TYPE_OPL = 0x20, /* YAMAHA YM3526 */
OPL_TYPE_MSXAUDIO = 0x21, /* YAMAHA Y8950 */
OPL_TYPE_OPL2 = 0x22 /* YAMAHA YM3812 */
};
KMIF_SOUND_DEVICE *OPLSoundAlloc(Uint32 opl_type);
#ifdef __cplusplus
}
#endif
#endif /* S_OPL_H__ */

View file

@ -1,136 +0,0 @@
#include "nestypes.h"
#include "s_logtbl.h"
#include "s_opltbl.h"
#if STATIC_TABLES
static void OplTableRelease(void *ctx)
{
}
static KMIF_OPLTABLE opl_static_tables = {
&opl_static_tables;
OplTableRelease,
#include "s_oplt.h"
};
KMIF_OPLTABLE *OplTableAddRef(void)
{
opl_static_tables.release = OplTableRelease;
return &opl_static_tables;
}
#else
#include <math.h>
#ifndef M_PI
#ifdef PI
#define M_PI PI
#else
#define M_PI 3.14159265358979323846
#endif
#endif
#define AM_DEPTH1 4.8 /* dB */
#define AM_DEPTH2 1.0 /* dB */
#define PM_DEPTH1 14.0 /* cent */
#define PM_DEPTH2 7.0 /* cent */
#define LOG_KEYOFF (15 << (LOG_BITS + 1))
#define DB0375_TO_LOG(x) ((Uint32)(0.375 * (1 << (LOG_BITS + x)) / 10))
#define AR_OFF (128 << ARTBL_SHIFT)
#define AR_MAX (127 << ARTBL_SHIFT)
static volatile Uint32 opl_tables_mutex = 0;
static Uint32 opl_tables_refcount = 0;
static KMIF_OPLTABLE *opl_tables = 0;
static void OplTableRelease(void *ctx)
{
++opl_tables_mutex;
while (opl_tables_mutex != 1)
{
XSLEEP(0);
}
opl_tables_refcount--;
if (!opl_tables_refcount)
{
XFREE(ctx);
opl_tables = 0;
}
--opl_tables_mutex;
}
static void OplTableCalc(KMIF_OPLTABLE *tbl)
{
Uint32 u, u2, i;
tbl->sin_table[0][0] = tbl->sin_table[0][1 << (SINTBL_BITS - 1)] = LOG_KEYOFF;
for (i = 1 ;i < (1 << (SINTBL_BITS - 1)); i++)
{
double d;
d = (1 << LOG_BITS) * -(log(sin(2.0 * M_PI * ((double)i) / (1 << SINTBL_BITS))) / log(2));
if (d > (LOG_KEYOFF >> 1)) d = (LOG_KEYOFF >> 1);
tbl->sin_table[0][i] = ((Uint32)d) << 1;
tbl->sin_table[0][i + (1 << (SINTBL_BITS - 1))] = (((Uint32)d) << 1) + 1;
}
for (i = 0 ;i < (1 << SINTBL_BITS); i++)
{
tbl->sin_table[1][i] = (tbl->sin_table[0][i] & 1) ? tbl->sin_table[0][0] : tbl->sin_table[0][i];
tbl->sin_table[2][i] = tbl->sin_table[0][i] & ~1;
tbl->sin_table[3][i] = (i & (1 << (SINTBL_BITS - 2))) ? LOG_KEYOFF : tbl->sin_table[2][i];
}
for (i = 0; i < (1 << TLLTBL_BITS); i++)
{
tbl->tll2log_table[i] = (i * DB0375_TO_LOG(0)) << 1;
}
for (i = 0; i < (1 << AMTBL_BITS); i++)
{
u = (Uint32)((1 + sin(2 * M_PI * ((double)i) / (1 << AMTBL_BITS))) * ((1 << LOG_BITS) * AM_DEPTH1 / 20.0));
u2 = (Uint32)((1 + sin(2 * M_PI * ((double)i) / (1 << AMTBL_BITS))) * ((1 << LOG_BITS) * AM_DEPTH2 / 20.0));
tbl->am_table1[i] = u << 1;
tbl->am_table2[i] = u2 << 1;
}
for (i = 0; i < (1 << PMTBL_BITS); i++)
{
u = (Uint32)((1 << PM_SHIFT) * pow(2, sin(2 * M_PI * ((double)i) / (1 << PMTBL_BITS)) * PM_DEPTH1 / 1200.0));
u2 = (Uint32)((1 << PM_SHIFT) * pow(2, sin(2 * M_PI * ((double)i) / (1 << PMTBL_BITS)) * PM_DEPTH2 / 1200.0));
tbl->pm_table1[i] = u;
tbl->pm_table2[i] = u2;
}
for (i = 0; i < (1 << ARTBL_BITS); i++)
{
u = (Uint32)(((double)AR_MAX) * (1 - log(1 + i) / log(1 << ARTBL_BITS)));
tbl->ar_tablelog[i] = u;
#if 1
u = (Uint32)(((double)AR_MAX) * (pow(1 - i / (double)(1 << ARTBL_BITS), 8)));
tbl->ar_tablepow[i] = u;
#endif
}
}
KMIF_OPLTABLE *OplTableAddRef(void)
{
++opl_tables_mutex;
while (opl_tables_mutex != 1)
{
XSLEEP(0);
}
if (!opl_tables_refcount)
{
opl_tables = (KMIF_OPLTABLE*) XMALLOC(sizeof(KMIF_OPLTABLE));
if (opl_tables)
{
opl_tables->ctx = opl_tables;
opl_tables->release = OplTableRelease;
OplTableCalc(opl_tables);
}
}
if (opl_tables) opl_tables_refcount++;
--opl_tables_mutex;
return opl_tables;
}
#endif

View file

@ -1,38 +0,0 @@
#ifndef S_OPLTBL_H__
#define S_OPLTBL_H__
#ifdef __cplusplus
extern "C" {
#endif
#define SINTBL_BITS 11
#define AMTBL_BITS 8
#define PMTBL_BITS 8
#define PM_SHIFT 9
#define ARTBL_BITS 7
#define ARTBL_SHIFT 20
#define TLLTBL_BITS 7
typedef struct
{
void *ctx;
void (*release)(void *ctx);
Uint32 sin_table[4][1 << SINTBL_BITS];
Uint32 tll2log_table[1 << TLLTBL_BITS];
Uint32 ar_tablelog[1 << ARTBL_BITS];
Uint32 am_table1[1 << AMTBL_BITS];
Uint32 pm_table1[1 << PMTBL_BITS];
#if 1
Uint32 ar_tablepow[1 << ARTBL_BITS];
#endif
Uint32 am_table2[1 << AMTBL_BITS];
Uint32 pm_table2[1 << PMTBL_BITS];
} KMIF_OPLTABLE;
KMIF_OPLTABLE *OplTableAddRef(void);
#ifdef __cplusplus
}
#endif
#endif /* S_OPLTBL_H__ */

View file

@ -1,50 +0,0 @@
#pragma once
#ifndef __YM2413_H__
#define __YM2413_H__
#ifdef __cplusplus
extern "C" {
#endif
/* select output bits size of output : 8 or 16 */
#define SAMPLE_BITS 16
#include "mamedef.h"
typedef stream_sample_t SAMP;
/*
#if (SAMPLE_BITS==16)
typedef INT16 SAMP;
#endif
#if (SAMPLE_BITS==8)
typedef INT8 SAMP;
#endif
*/
void *ym2413_init(int clock, int rate, int type);
void ym2413_shutdown(void *chip);
void ym2413_reset_chip(void *chip);
void ym2413_write(void *chip, int a, int v);
unsigned char ym2413_read(void *chip, int a);
void ym2413_update_one(void *chip, SAMP **buffers, int length);
void ym2413_advance_lfo(void *chip); /* call this once */
SAMP ym2413_calcch(void *chip, int ch); /* then call this for each channel */
void ym2413_advance(void *chip); /* then call this */
void * ym2413_get_inst0(void *chip);
void ym2413_set_mask(void *chip, UINT32 mask);
typedef void (*OPLL_UPDATEHANDLER)(void *param,int min_interval_us);
void ym2413_set_update_handler(void *chip, OPLL_UPDATEHANDLER UpdateHandler, void *param);
#ifdef __cplusplus
}
#endif
#endif /*__YM2413_H__*/

3
Frameworks/GME/vgmplay/.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
/obj
/vgm2pcm
/vgmplay

View file

@ -0,0 +1,170 @@
// ChipMapper.c - Handles Chip Write (including OPL Hardware Support)
#include <stdio.h>
#include <memory.h>
#include <math.h>
#include <wchar.h>
#include "stdbool.h"
#include "chips/mamedef.h"
#include "chips/ChipIncl.h"
#include "VGMPlay.h"
#include "ChipMapper.h"
void chip_reg_write(void *param, UINT8 ChipType, UINT8 ChipID,
UINT8 Port, UINT8 Offset, UINT8 Data)
{
VGM_PLAYER* p = (VGM_PLAYER *) param;
switch(ChipType)
{
case 0x00: // SN76496
sn764xx_w(p->sn764xx[ChipID], Port, Data);
break;
case 0x01: // YM2413
ym2413_w(p->ym2413[ChipID], 0x00, Offset);
ym2413_w(p->ym2413[ChipID], 0x01, Data);
break;
case 0x02: // YM2612
ym2612_w(p->ym2612[ChipID], (Port << 1) | 0x00, Offset);
ym2612_w(p->ym2612[ChipID], (Port << 1) | 0x01, Data);
break;
case 0x03: // YM2151
ym2151_w(p->ym2151[ChipID], 0x00, Offset);
ym2151_w(p->ym2151[ChipID], 0x01, Data);
break;
case 0x04: // SegaPCM
break;
case 0x05: // RF5C68
rf5c68_w(p->rf5c68, Offset, Data);
break;
case 0x06: // YM2203
ym2203_w(p->ym2203[ChipID], 0x00, Offset);
ym2203_w(p->ym2203[ChipID], 0x01, Data);
break;
case 0x07: // YM2608
ym2608_w(p->ym2608[ChipID], (Port << 1) | 0x00, Offset);
ym2608_w(p->ym2608[ChipID], (Port << 1) | 0x01, Data);
break;
case 0x08: // YM2610/YM2610B
ym2610_w(p->ym2610[ChipID], (Port << 1) | 0x00, Offset);
ym2610_w(p->ym2610[ChipID], (Port << 1) | 0x01, Data);
break;
case 0x09: // YM3812
ym3812_w(p->ym3812[ChipID], 0x00, Offset);
ym3812_w(p->ym3812[ChipID], 0x01, Data);
break;
case 0x0A: // YM3526
ym3526_w(p->ym3526[ChipID], 0x00, Offset);
ym3526_w(p->ym3526[ChipID], 0x01, Data);
break;
case 0x0B: // Y8950
y8950_w(p->y8950[ChipID], 0x00, Offset);
y8950_w(p->y8950[ChipID], 0x01, Data);
break;
case 0x0C: // YMF262
ymf262_w(p->ymf262[ChipID], (Port << 1) | 0x00, Offset);
ymf262_w(p->ymf262[ChipID], (Port << 1) | 0x01, Data);
break;
case 0x0D: // YMF278B
ymf278b_w(p->ymf278b[ChipID], (Port << 1) | 0x00, Offset);
ymf278b_w(p->ymf278b[ChipID], (Port << 1) | 0x01, Data);
break;
case 0x0E: // YMF271
ymf271_w(p->ymf271[ChipID], (Port << 1) | 0x00, Offset);
ymf271_w(p->ymf271[ChipID], (Port << 1) | 0x01, Data);
break;
case 0x0F: // YMZ280B
ymz280b_w(p->ymz280b[ChipID], 0x00, Offset);
ymz280b_w(p->ymz280b[ChipID], 0x01, Data);
break;
case 0x10: // RF5C164
rf5c164_w(p->rf5c164, Offset, Data);
break;
case 0x11: // PWM
pwm_chn_w(p->pwm, Port, (Offset << 8) | (Data << 0));
break;
case 0x12: // AY8910
ayxx_w(p->ay8910[ChipID], 0x00, Offset);
ayxx_w(p->ay8910[ChipID], 0x01, Data);
break;
case 0x13: // GameBoy
gb_sound_w(p->gbdmg[ChipID], Offset, Data);
break;
case 0x14: // NES APU
nes_w(p->nesapu[ChipID], Offset, Data);
break;
case 0x15: // MultiPCM
multipcm_w(p->multipcm[ChipID], Offset, Data);
break;
case 0x16: // UPD7759
upd7759_write(p->upd7759[ChipID], Offset, Data);
break;
case 0x17: // OKIM6258
okim6258_write(p->okim6258[ChipID], Offset, Data);
break;
case 0x18: // OKIM6295
okim6295_w(p->okim6295[ChipID], Offset, Data);
break;
case 0x19: // K051649 / SCC1
k051649_w(p->k051649[ChipID], (Port << 1) | 0x00, Offset);
k051649_w(p->k051649[ChipID], (Port << 1) | 0x01, Data);
break;
case 0x1A: // K054539
k054539_w(p->k054539[ChipID], (Port << 8) | (Offset << 0), Data);
break;
case 0x1B: // HuC6280
c6280_w(p->huc6280[ChipID], Offset, Data);
break;
case 0x1C: // C140
c140_w(p->c140[ChipID], (Port << 8) | (Offset << 0), Data);
break;
case 0x1D: // K053260
k053260_w(p->k053260[ChipID], Offset, Data);
break;
case 0x1E: // Pokey
pokey_w(p->pokey[ChipID], Offset, Data);
break;
case 0x1F: // QSound
qsound_w(p->qsound[ChipID], 0x00, Port); // Data MSB
qsound_w(p->qsound[ChipID], 0x01, Offset); // Data LSB
qsound_w(p->qsound[ChipID], 0x02, Data); // Register
break;
case 0x20: // YMF292/SCSP
scsp_w(p->scsp[ChipID], (Port << 8) | (Offset << 0), Data);
break;
case 0x21: // WonderSwan
ws_audio_port_write(p->wswan[ChipID], 0x80 | Offset, Data);
break;
case 0x22: // VSU
VSU_Write(p->vsu[ChipID], (Port << 8) | (Offset << 0), Data);
break;
case 0x23: // SAA1099
saa1099_control_w(p->saa1099[ChipID], 0, Offset);
saa1099_data_w(p->saa1099[ChipID], 0, Data);
break;
case 0x24: // ES5503
es5503_w(p->es5503[ChipID], Offset, Data);
break;
case 0x25: // ES5506
if (Port & 0x80)
es550x_w16(p->es550x[ChipID], Port & 0x7F, (Offset << 8) | (Data << 0));
else
es550x_w(p->es550x[ChipID], Port, Data);
break;
case 0x26: // X1-010
seta_sound_w(p->x1_010[ChipID], (Port << 8) | (Offset << 0), Data);
break;
case 0x27: // C352
c352_w(p->c352[ChipID], Port, (Offset << 8) | (Data << 0));
break;
case 0x28: // GA20
irem_ga20_w(p->ga20[ChipID], Offset, Data);
break;
// case 0x##: // OKIM6376
// break;
}
return;
}

View file

@ -0,0 +1 @@
void chip_reg_write(void *, UINT8 ChipType, UINT8 ChipID, UINT8 Port, UINT8 Offset, UINT8 Data);

View file

@ -0,0 +1,202 @@
########################
#
# VGMPlay Makefile
# (for GNU Make 3.81)
#
########################
# TODO: Make this look less horrible.
# TODO: Make it not include pt_ioctl.c when DISABLE_HW_SUPPORT is active.
# Uncomment if you build on Windows using MinGW.
#WINDOWS = 1
# Uncomment if you want to use libao instead of OSS for sound streaming under Linux
USE_LIBAO = 1
CC = gcc
PREFIX = /usr/local
MANPREFIX = $(PREFIX)/share/man
# -- VGMPlay specific Compile Flags --
MAINFLAGS := -DCONSOLE_MODE -DADDITIONAL_FORMATS -DSET_CONSOLE_TITLE
ifdef WINDOWS
# MinGW defines __WINDOWS__, Visual Studio defines WIN32
MAINFLAGS += -DWIN32
else
ifdef USE_LIBAO
MAINFLAGS += -DUSE_LIBAO
endif
endif
EMUFLAGS := -DENABLE_ALL_CORES
#MAINFLAGS := -DVGM_BIG_ENDIAN
#EMUFLAGS := -DVGM_BIG_ENDIAN
#MAINFLAGS := -DDISABLE_HW_SUPPORT
# -- General Compile Flags --
CFLAGS := -O3 -g0 $(CFLAGS)
# libm (math library) and libz (zlib)
LDFLAGS := -lm -lz $(LDFLAGS)
ifdef WINDOWS
# for Windows, add kernel32 and winmm (Multimedia APIs)
LDFLAGS += -lkernel32 -lwinmm
else
# for Linux, add librt (clock stuff) and libpthread (threads)
LDFLAGS += -lrt -lpthread -pthread
MAINFLAGS += -pthread -DSHARE_PREFIX=\"$(PREFIX)\"
ifdef USE_LIBAO
LDFLAGS += -lao
endif
endif
# add Library Path, if defined
ifdef LD_LIBRARY_PATH
LDFLAGS += -L $(LD_LIBRARY_PATH)
endif
SRC = .
OBJ = obj
EMUSRC = $(SRC)/chips
EMUOBJ = $(OBJ)/chips
OBJDIRS = \
$(OBJ) \
$(EMUOBJ)
MAINOBJS = \
$(OBJ)/VGMPlay.o \
$(OBJ)/VGMPlay_AddFmts.o \
$(OBJ)/Stream.o \
$(OBJ)/ChipMapper.o
ifdef WINDOWS
MAINOBJS += $(OBJ)/pt_ioctl.o
endif
EMUOBJS = \
$(EMUOBJ)/262intf.o \
$(EMUOBJ)/2151intf.o \
$(EMUOBJ)/2203intf.o \
$(EMUOBJ)/2413intf.o \
$(EMUOBJ)/2608intf.o \
$(EMUOBJ)/2610intf.o \
$(EMUOBJ)/2612intf.o \
$(EMUOBJ)/3526intf.o \
$(EMUOBJ)/3812intf.o \
$(EMUOBJ)/8950intf.o \
$(EMUOBJ)/adlibemu_opl2.o \
$(EMUOBJ)/adlibemu_opl3.o \
$(EMUOBJ)/ay8910.o \
$(EMUOBJ)/ay_intf.o \
$(EMUOBJ)/c140.o \
$(EMUOBJ)/c352.o \
$(EMUOBJ)/c6280.o \
$(EMUOBJ)/c6280intf.o \
$(EMUOBJ)/dac_control.o \
$(EMUOBJ)/es5503.o \
$(EMUOBJ)/es5506.o \
$(EMUOBJ)/emu2149.o \
$(EMUOBJ)/emu2413.o \
$(EMUOBJ)/fm2612.o \
$(EMUOBJ)/fm.o \
$(EMUOBJ)/fmopl.o \
$(EMUOBJ)/gb.o \
$(EMUOBJ)/iremga20.o \
$(EMUOBJ)/k051649.o \
$(EMUOBJ)/k053260.o \
$(EMUOBJ)/k054539.o \
$(EMUOBJ)/multipcm.o \
$(EMUOBJ)/nes_apu.o \
$(EMUOBJ)/nes_intf.o \
$(EMUOBJ)/np_nes_apu.o \
$(EMUOBJ)/np_nes_dmc.o \
$(EMUOBJ)/np_nes_fds.o \
$(EMUOBJ)/okim6258.o \
$(EMUOBJ)/okim6295.o \
$(EMUOBJ)/Ootake_PSG.o \
$(EMUOBJ)/panning.o \
$(EMUOBJ)/pokey.o \
$(EMUOBJ)/pwm.o \
$(EMUOBJ)/qsound.o \
$(EMUOBJ)/rf5c68.o \
$(EMUOBJ)/saa1099.o \
$(EMUOBJ)/segapcm.o \
$(EMUOBJ)/scd_pcm.o \
$(EMUOBJ)/scsp.o \
$(EMUOBJ)/scspdsp.o \
$(EMUOBJ)/sn76489.o \
$(EMUOBJ)/sn76496.o \
$(EMUOBJ)/sn764intf.o \
$(EMUOBJ)/upd7759.o \
$(EMUOBJ)/vsu.o \
$(EMUOBJ)/ws_audio.o \
$(EMUOBJ)/x1_010.o \
$(EMUOBJ)/ym2151.o \
$(EMUOBJ)/ym2413.o \
$(EMUOBJ)/ym2612.o \
$(EMUOBJ)/ymdeltat.o \
$(EMUOBJ)/ymf262.o \
$(EMUOBJ)/ymf271.o \
$(EMUOBJ)/ymf278b.o \
$(EMUOBJ)/ymz280b.o \
$(EMUOBJ)/ay8910_opl.o \
$(EMUOBJ)/sn76496_opl.o \
$(EMUOBJ)/ym2413hd.o \
$(EMUOBJ)/ym2413_opl.o
VGMPLAY_OBJS = \
$(OBJ)/VGMPlayUI.o
VGM2PCM_OBJS = \
$(OBJ)/vgm2pcm.o
EXTRA_OBJS = $(VGMPLAY_OBJS) $(VGM2PCM_OBJS)
all: vgmplay vgm2pcm
vgmplay: $(EMUOBJS) $(MAINOBJS) $(VGMPLAY_OBJS)
@echo Linking vgmplay ...
@$(CC) $(VGMPLAY_OBJS) $(MAINOBJS) $(EMUOBJS) $(LDFLAGS) -o vgmplay
@echo Done.
vgm2pcm: $(EMUOBJS) $(MAINOBJS) $(VGM2PCM_OBJS)
@echo Linking vgm2pcm ...
@$(CC) $(VGM2PCM_OBJS) $(MAINOBJS) $(EMUOBJS) $(LDFLAGS) -o vgm2pcm
@echo Done.
# compile the chip-emulator c-files
$(EMUOBJ)/%.o: $(EMUSRC)/%.c
@echo Compiling $< ...
@mkdir -p $(@D)
@$(CC) $(CFLAGS) $(EMUFLAGS) -c $< -o $@
# compile the main c-files
$(OBJ)/%.o: $(SRC)/%.c
@echo Compiling $< ...
@mkdir -p $(@D)
@$(CC) $(CFLAGS) $(MAINFLAGS) -c $< -o $@
clean:
@echo Deleting object files ...
@rm -f $(MAINOBJS) $(EMUOBJS) $(EXTRA_OBJS)
@echo Deleting executable files ...
@rm -f vgmplay vgm2pcm
@echo Done.
# Thanks to ZekeSulastin and nextvolume for the install and uninstall routines.
install: vgmplay
install -m 755 vgmplay $(DESTDIR)$(PREFIX)/bin/vgmplay
install -m 644 vgmplay.1 $(DESTDIR)$(MANPREFIX)/man1/vgmplay.1
mkdir -m 755 -p $(DESTDIR)$(PREFIX)/share/vgmplay
install -m 644 VGMPlay.ini $(DESTDIR)$(PREFIX)/share/vgmplay/vgmplay.ini
-install -m 644 yrw801.rom $(DESTDIR)$(PREFIX)/share/vgmplay/yrw801.rom
# Install the "vgm-player" wrapper
play_inst: install
install -m 755 vgm-player $(DESTDIR)$(PREFIX)/bin/vgm-player
uninstall:
rm $(DESTDIR)$(PREFIX)/bin/vgmplay
rm $(DESTDIR)$(PREFIX)/bin/vgm-player
rm $(DESTDIR)$(MANPREFIX)/man1/vgmplay.1
rm -rf $(DESTDIR)$(PREFIX)/share/vgmplay
.PHONY: all clean install uninstall

View file

@ -0,0 +1,37 @@
/******************************************************************************/
/* */
/* PortTalk Driver for Windows NT/2000/XP */
/* Version 2.0, 12th January 2002 */
/* http://www.beyondlogic.org */
/* */
/* Copyright © 2002 Craig Peacock. Craig.Peacock@beyondlogic.org */
/* Any publication or distribution of this code in source form is prohibited */
/* without prior written permission of the copyright holder. This source code */
/* is provided "as is", without any guarantee made as to its suitability or */
/* fitness for any particular use. Permission is herby granted to modify or */
/* enhance this sample code to produce a derivative program which may only be */
/* distributed in compiled object form only. */
/******************************************************************************/
#define PORTTALK_TYPE 40000 /* 32768-65535 are reserved for customers */
// The IOCTL function codes from 0x800 to 0xFFF are for customer use.
#define IOCTL_IOPM_RESTRICT_ALL_ACCESS \
CTL_CODE(PORTTALK_TYPE, 0x900, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_IOPM_ALLOW_EXCUSIVE_ACCESS \
CTL_CODE(PORTTALK_TYPE, 0x901, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_SET_IOPM \
CTL_CODE(PORTTALK_TYPE, 0x902, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_ENABLE_IOPM_ON_PROCESSID \
CTL_CODE(PORTTALK_TYPE, 0x903, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_READ_PORT_UCHAR \
CTL_CODE(PORTTALK_TYPE, 0x904, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_WRITE_PORT_UCHAR \
CTL_CODE(PORTTALK_TYPE, 0x905, METHOD_BUFFERED, FILE_ANY_ACCESS)

View file

@ -0,0 +1,31 @@
VGMPlay Build Instructions
--------------------------
Compile VGMPlay under Windows
-----------------------------
using MS Visual Studio 6.0:
1. Open VGMPlay.dsw.
2. Build the project.
3. Done.
using later versions of MS Visual Studio:
1. Open VGMPlay.dsw.
2. It will ask you to convert the project to the current project format. Click "Yes".
3. Build the project.
4. Done.
using MinGW/MSYS:
1. edit the Makefile and enable the line "WINDOWS = 1" (remove the #)
2. open MSYS and run the "make" command in VGMPlay's folder.
3. Done.
Note: You can compile it without MSYS, but you need to manually create the OBJDIRS paths (or make them use the backslash '\'), because mkdir fails at paths with a forward slash.
Compile VGMPlay under Linux
---------------------------
1. [optional step] If you have libao installed, you can edit the Makefile to make VGMPlay use libao instead of OSS.
2. run "make" in VGMPlay's folder
3. Done.

View file

@ -0,0 +1,147 @@
// Header file for VGM file handling
typedef struct _vgm_file_header
{
UINT32 fccVGM;
UINT32 lngEOFOffset;
UINT32 lngVersion;
UINT32 lngHzPSG;
UINT32 lngHzYM2413;
UINT32 lngGD3Offset;
UINT32 lngTotalSamples;
UINT32 lngLoopOffset;
UINT32 lngLoopSamples;
UINT32 lngRate;
UINT16 shtPSG_Feedback;
UINT8 bytPSG_SRWidth;
UINT8 bytPSG_Flags;
UINT32 lngHzYM2612;
UINT32 lngHzYM2151;
UINT32 lngDataOffset;
UINT32 lngHzSPCM;
UINT32 lngSPCMIntf;
UINT32 lngHzRF5C68;
UINT32 lngHzYM2203;
UINT32 lngHzYM2608;
UINT32 lngHzYM2610;
UINT32 lngHzYM3812;
UINT32 lngHzYM3526;
UINT32 lngHzY8950;
UINT32 lngHzYMF262;
UINT32 lngHzYMF278B;
UINT32 lngHzYMF271;
UINT32 lngHzYMZ280B;
UINT32 lngHzRF5C164;
UINT32 lngHzPWM;
UINT32 lngHzAY8910;
UINT8 bytAYType;
UINT8 bytAYFlag;
UINT8 bytAYFlagYM2203;
UINT8 bytAYFlagYM2608;
UINT8 bytVolumeModifier;
UINT8 bytReserved2;
INT8 bytLoopBase;
UINT8 bytLoopModifier;
UINT32 lngHzGBDMG;
UINT32 lngHzNESAPU;
UINT32 lngHzMultiPCM;
UINT32 lngHzUPD7759;
UINT32 lngHzOKIM6258;
UINT8 bytOKI6258Flags;
UINT8 bytK054539Flags;
UINT8 bytC140Type;
UINT8 bytReservedFlags;
UINT32 lngHzOKIM6295;
UINT32 lngHzK051649;
UINT32 lngHzK054539;
UINT32 lngHzHuC6280;
UINT32 lngHzC140;
UINT32 lngHzK053260;
UINT32 lngHzPokey;
UINT32 lngHzQSound;
UINT32 lngHzSCSP;
// UINT32 lngHzOKIM6376;
//UINT8 bytReserved[0x04];
UINT32 lngExtraOffset;
UINT32 lngHzWSwan;
UINT32 lngHzVSU;
UINT32 lngHzSAA1099;
UINT32 lngHzES5503;
UINT32 lngHzES5506;
UINT8 bytES5503Chns;
UINT8 bytES5506Chns;
UINT8 bytC352ClkDiv;
UINT8 bytESReserved;
UINT32 lngHzX1_010;
UINT32 lngHzC352;
UINT32 lngHzGA20;
} VGM_HEADER;
typedef struct _vgm_header_extra
{
UINT32 DataSize;
UINT32 Chp2ClkOffset;
UINT32 ChpVolOffset;
} VGM_HDR_EXTRA;
typedef struct _vgm_extra_chip_data32
{
UINT8 Type;
UINT32 Data;
} VGMX_CHIP_DATA32;
typedef struct _vgm_extra_chip_data16
{
UINT8 Type;
UINT8 Flags;
UINT16 Data;
} VGMX_CHIP_DATA16;
typedef struct _vgm_extra_chip_extra32
{
UINT8 ChipCnt;
VGMX_CHIP_DATA32* CCData;
} VGMX_CHP_EXTRA32;
typedef struct _vgm_extra_chip_extra16
{
UINT8 ChipCnt;
VGMX_CHIP_DATA16* CCData;
} VGMX_CHP_EXTRA16;
typedef struct _vgm_header_extra_data
{
VGMX_CHP_EXTRA32 Clocks;
VGMX_CHP_EXTRA16 Volumes;
} VGM_EXTRA;
#define VOLUME_MODIF_WRAP 0xC0
typedef struct _vgm_gd3_tag
{
UINT32 fccGD3;
UINT32 lngVersion;
UINT32 lngTagLength;
wchar_t* strTrackNameE;
wchar_t* strTrackNameJ;
wchar_t* strGameNameE;
wchar_t* strGameNameJ;
wchar_t* strSystemNameE;
wchar_t* strSystemNameJ;
wchar_t* strAuthorNameE;
wchar_t* strAuthorNameJ;
wchar_t* strReleaseDate;
wchar_t* strCreator;
wchar_t* strNotes;
} GD3_TAG;
typedef struct _vgm_pcm_bank_data
{
UINT32 DataSize;
UINT8* Data;
UINT32 DataStart;
} VGM_PCM_DATA;
typedef struct _vgm_pcm_bank
{
UINT32 BankCount;
VGM_PCM_DATA* Bank;
UINT32 DataSize;
UINT8* Data;
UINT32 DataPos;
UINT32 BnkPos;
} VGM_PCM_BANK;
#define FCC_VGM 0x206D6756 // 'Vgm '
#define FCC_GD3 0x20336447 // 'Gd3 '

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,29 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNUNG: DIESE ARBEITSBEREICHSDATEI DARF NICHT BEARBEITET ODER GELÖSCHT WERDEN!
###############################################################################
Project: "VGMPlay"=".\VGMPlay.dsp" - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

View file

@ -0,0 +1,295 @@
// Header File for structures and constants used within VGMPlay.c
#include "chips/mamedef.h"
#include "VGMFile.h"
#include "VGMPlay_Intf.h"
#define VGMPLAY_VER_STR "0.40.6"
//#define APLHA
//#define BETA
#define VGM_VER_STR "1.71b"
#define VGM_VER_NUM 0x170
#define CHIP_COUNT 0x29
typedef struct chip_options
{
bool Disabled;
UINT8 EmuCore;
UINT8 ChnCnt;
// Special Flags:
// YM2612: Bit 0 - DAC Highpass Enable, Bit 1 - SSG-EG Enable
// YM-OPN: Bit 0 - Disable AY8910-Part
UINT16 SpecialFlags;
// Channel Mute Mask - 1 Channel is represented by 1 bit
UINT32 ChnMute1;
// Mask 2 - used by YMF287B for OPL4 Wavetable Synth and by YM2608/YM2610 for PCM
UINT32 ChnMute2;
// Mask 3 - used for the AY-part of some OPN-chips
UINT32 ChnMute3;
INT16* Panning;
} CHIP_OPTS;
typedef struct chips_options
{
CHIP_OPTS SN76496;
CHIP_OPTS YM2413;
CHIP_OPTS YM2612;
CHIP_OPTS YM2151;
CHIP_OPTS SegaPCM;
CHIP_OPTS RF5C68;
CHIP_OPTS YM2203;
CHIP_OPTS YM2608;
CHIP_OPTS YM2610;
CHIP_OPTS YM3812;
CHIP_OPTS YM3526;
CHIP_OPTS Y8950;
CHIP_OPTS YMF262;
CHIP_OPTS YMF278B;
CHIP_OPTS YMF271;
CHIP_OPTS YMZ280B;
CHIP_OPTS RF5C164;
CHIP_OPTS PWM;
CHIP_OPTS AY8910;
CHIP_OPTS GameBoy;
CHIP_OPTS NES;
CHIP_OPTS MultiPCM;
CHIP_OPTS UPD7759;
CHIP_OPTS OKIM6258;
CHIP_OPTS OKIM6295;
CHIP_OPTS K051649;
CHIP_OPTS K054539;
CHIP_OPTS HuC6280;
CHIP_OPTS C140;
CHIP_OPTS K053260;
CHIP_OPTS Pokey;
CHIP_OPTS QSound;
CHIP_OPTS SCSP;
CHIP_OPTS WSwan;
CHIP_OPTS VSU;
CHIP_OPTS SAA1099;
CHIP_OPTS ES5503;
CHIP_OPTS ES5506;
CHIP_OPTS X1_010;
CHIP_OPTS C352;
CHIP_OPTS GA20;
// CHIP_OPTS OKIM6376;
} CHIPS_OPTION;
typedef void (*strm_func)(void *, stream_sample_t **outputs, int samples);
typedef struct chip_audio_attributes CAUD_ATTR;
struct chip_audio_attributes
{
UINT32 TargetSmpRate;
UINT32 SmpRate;
UINT32 LastSmpRate;
UINT16 Volume;
UINT8 ChipType;
UINT8 ChipID; // 0 - 1st chip, 1 - 2nd chip, etc.
void* Resampler;
strm_func StreamUpdate;
void* StreamUpdateParam;
CAUD_ATTR* Paired;
};
typedef struct chip_audio_struct
{
CAUD_ATTR SN76496;
CAUD_ATTR YM2413;
CAUD_ATTR YM2612;
CAUD_ATTR YM2151;
CAUD_ATTR SegaPCM;
CAUD_ATTR RF5C68;
CAUD_ATTR YM2203;
CAUD_ATTR YM2608;
CAUD_ATTR YM2610;
CAUD_ATTR YM3812;
CAUD_ATTR YM3526;
CAUD_ATTR Y8950;
CAUD_ATTR YMF262;
CAUD_ATTR YMF278B;
CAUD_ATTR YMF271;
CAUD_ATTR YMZ280B;
CAUD_ATTR RF5C164;
CAUD_ATTR PWM;
CAUD_ATTR AY8910;
CAUD_ATTR GameBoy;
CAUD_ATTR NES;
CAUD_ATTR MultiPCM;
CAUD_ATTR UPD7759;
CAUD_ATTR OKIM6258;
CAUD_ATTR OKIM6295;
CAUD_ATTR K051649;
CAUD_ATTR K054539;
CAUD_ATTR HuC6280;
CAUD_ATTR C140;
CAUD_ATTR K053260;
CAUD_ATTR Pokey;
CAUD_ATTR QSound;
CAUD_ATTR SCSP;
CAUD_ATTR WSwan;
CAUD_ATTR VSU;
CAUD_ATTR SAA1099;
CAUD_ATTR ES5503;
CAUD_ATTR ES5506;
CAUD_ATTR X1_010;
CAUD_ATTR C352;
CAUD_ATTR GA20;
// CAUD_ATTR OKIM6376;
} CHIP_AUDIO;
typedef struct chip_aud_list CA_LIST;
struct chip_aud_list
{
CAUD_ATTR* CAud;
CHIP_OPTS* COpts;
CA_LIST* next;
};
typedef struct daccontrol_data
{
bool Enable;
UINT8 Bank;
} DACCTRL_DATA;
typedef struct pcmbank_table
{
UINT8 ComprType;
UINT8 CmpSubType;
UINT8 BitDec;
UINT8 BitCmp;
UINT16 EntryCount;
void* Entries;
} PCMBANK_TBL;
typedef struct vgm_player
{
// Options Variables
UINT32 SampleRate; // Note: also used by some sound cores to determinate the chip sample rate
UINT32 VGMMaxLoop;
UINT32 VGMPbRate; // in Hz, ignored if this value or VGM's lngRate Header value is 0
#ifdef ADDITIONAL_FORMATS
UINT32 CMFMaxLoop;
#endif
UINT32 FadeTime;
float VolumeLevel;
bool SurroundSound;
bool FadeRAWLog;
//bool FullBufFill; // Fill Buffer until it's full
bool DoubleSSGVol;
UINT8 ResampleMode; // 00 - HQ both, 01 - LQ downsampling, 02 - LQ both
UINT8 CHIP_SAMPLING_MODE;
INT32 CHIP_SAMPLE_RATE;
CHIPS_OPTION ChipOpts[0x02];
stream_sample_t* DUMMYBUF[0x02];
char* AppPaths[8];
UINT8 FileMode;
VGM_HEADER VGMHead;
VGM_HDR_EXTRA VGMHeadX;
VGM_EXTRA VGMH_Extra;
UINT32 VGMDataLen;
UINT8* VGMData;
GD3_TAG VGMTag;
#define PCM_BANK_COUNT 0x40
VGM_PCM_BANK PCMBank[PCM_BANK_COUNT];
PCMBANK_TBL PCMTbl;
UINT8 DacCtrlUsed;
UINT8 DacCtrlUsg[0xFF];
DACCTRL_DATA DacCtrl[0xFF];
CHIP_AUDIO ChipAudio[0x02];
CAUD_ATTR CA_Paired[0x02][0x03];
float MasterVol;
CA_LIST ChipListBuffer[0x200];
CA_LIST* ChipListAll; // all chips needed for playback (in general)
//CA_LIST* ChipListOpt; // ChipListAll minus muted chips
#define SMPL_BUFSIZE 0x100
INT32* StreamBufs[0x02];
UINT32 VGMPos;
INT32 VGMSmplPos;
INT32 VGMSmplPlayed;
INT32 VGMSampleRate;
UINT32 VGMPbRateMul;
UINT32 VGMPbRateDiv;
UINT32 VGMSmplRateMul;
UINT32 VGMSmplRateDiv;
bool VGMEnd;
bool EndPlay;
bool FadePlay;
bool ForceVGMExec;
UINT8 PlayingMode;
UINT32 PlayingTime;
UINT32 FadeStart;
UINT32 VGMMaxLoopM;
UINT32 VGMCurLoop;
float VolumeLevelM;
float FinalVol;
bool ResetPBTimer;
UINT8 IsVGMInit;
UINT16 Last95Drum; // for optvgm debugging
UINT16 Last95Max; // for optvgm debugging
UINT32 Last95Freq; // for optvgm debugging
bool ErrorHappened;
// the chips' states
void * sn764xx[2];
void * ym2413[2];
void * ym2612[2];
void * ym2151[2];
void * segapcm[2];
void * rf5c68;
void * ym2203[2];
void * ym2608[2];
void * ym2610[2];
void * ym3812[2];
void * ym3812_dual_data[2];
void * ym3526[2];
void * y8950[2];
void * ymf262[2];
void * ymf278b[2];
void * ymf271[2];
void * ymz280b[2];
void * rf5c164;
void * pwm;
void * ay8910[2];
void * gbdmg[2];
void * nesapu[2];
void * multipcm[2];
void * upd7759[2];
void * okim6258[2];
void * okim6295[2];
void * k051649[2];
void * k054539[2];
void * huc6280[2];
void * c140[2];
void * k053260[2];
void * pokey[2];
void * qsound[2];
void * scsp[2];
void * wswan[2];
void * vsu[2];
void * saa1099[2];
void * es5503[2];
void * es550x[2];
void * x1_010[2];
void * c352[2];
void * ga20[2];
void * daccontrol[255];
} VGM_PLAYER;

View file

@ -0,0 +1,344 @@
; VGMPlay Configuration File
; --------------------------
;
; Default Values are usually 0 (False for boolean ones)
; Boolean Values are:
; False / 0
; True / 1
[General]
; Default Sample Rate: 44100
SampleRate = 48000
; If you set PlaybackRate to 50, some songs will play slower, like on a PAL console.
; If you set it to 60, some songs may play faster, like PAL games on a NTSC console.
PlaybackRate = 0
; double the volume of the YM2xxx SSG, if it gets overridden by a VGM's header.
; This option will be removed once all VGMs on vgmrips are fixed.
DoubleSSGVol = True
; Display Japanese GD3 Tag if available
; Most western Windows systems won't be able to display Japanese characters in the normal console,
; so use at own risk. (Linux doesn't have this problem.)
PreferJapTag = False
; Default Fade Time: 5000
FadeTime = 8000
; In-Playlist Fade Time: for all looping tracks in a playlist (except the last one)
; Setting this to 0 simulate a Song-Medley without gaps.
; Default Fade Time in Playlist: 2000
FadeTimePL = 0
JinglePause = 1000
; Fade RAW logs from emulators (VGMs without Creator-Tag) so that they don't
; end abruptly at the full volume level but at 33%
;FadeRAWLogs = True
; Default Volume: 1.0 (of course)
Volume = 1.0
; Log Sound to Wave: 0 - no logging, 1 - log only, 2 - play and log
LogSound = 0
; Maximum Loops before fading
; Default: 0x02 (0x01 for CMF)
MaxLoops = 0x02
MaxLoopsCMF = 0x01
; Resampling Mode:
; 0 - always high quality resampler (default)
; 1 - HQ resampler for upsampling, LQ resampler for downsampling (recommend for slow machines)
; 2 - always low quality resampler (very fast)
ResamplingMode = 0
; Chip Sample Mode:
; 0 - Native (default)
; 1 - use highest sampling rate (native or the one below)
; 2 - use always the sampling rate below (CPU friendly)
; 3 - use native sample rate for FM chips and highest sampling rate for all others
ChipSmplMode = 3
; Default Chip Sample Rate: 0 (results in value of Playback SampleRate)
ChipSmplRate = 0
; Force Audio Buffer Number (1 Buffer = 10 ms, Minimum is 4, Maximum is 200)
; higher values result in greater delays while seeking (and pausing with EmulatePause On)
; set this to 50 or 100 if the sound is choppy
; 0 results in 10 for Windows 98/ME/2000/XP/7,
; 50 for Windows 95 and 20 for Windows Vista
AudioBuffers = 0
; "Surround" Sound - inverts the waveform of the right channel to create a pseudo surround effect
; use only with headphones!!
SurroundSound = False
; Emulate during Pause: continue to generate sound while playback is paused
EmulatePause = False
; Shows the last data block played with DAC Stream Command 95. Useful for debugging.
; 0 - don't show
; 1 - show data block ID only
; 2 - show data block ID + frequency
; 3 - show data block ID + frequency in KHz
ShowStreamCmds = 3
; --- FM Hardware Section Start ---
; Hardware FM Port (in hex, usually 220 or 388)
FMPort = 0
; Force FM Mode, even if only the SN76496 is used, also enables Mixed Mode (Hardware FM + Software Emulator)
FMForce = False
; Makes some FM-Voices fading on track-end instead of instant silencing them
FMSoftStop = True
; Overrides Volume setting, if FM hardware is used
; Possible values:
; = 0 - don't override (default)
; > 0 - override Volume setting and VGM Volume Modifier
; < 0 - multiply with volume
FMVolume = 0.0
; --- FM Hardware Section End ---
; Chip Options
; ------------
; - Disabled = False/True
; disable the emulation of the current chip
; - EmulatorType = 0 / 1 / ...
; 0 is recommend/default, 1+ are alternative emulation cores
; - MuteMask = 0
; mute channels by setting the muting bitmask
; - MuteCh? = False/True
; mute channel ?
; - Mutexxx = False/True
; mute channel with the name xxx (e.g. DAC, DT, BD, ...)
[SN76496]
Disabled = False
; EmulatorType: 0 - MAME, 1 - Maxim
EmulatorType = 0x00
; Channels: 4 (0-3)
[YM2413]
Disabled = False
; FMPort = 0:
; EmulatorType: 0 - EMU2413, 1 - MAME
; FMPort != 0:
; EmulatorType: 0 - Valley Bell Custom, 1 - Meka
EmulatorType = 0x00
; Channels: 14 (0-8, BD, SD, TOM, TC, HH)
[YM2612]
Disabled = False
; EmulatorType: 0 - MAME (Genesis Plus GX), 1 - Gens
EmulatorType = 0x00
; MAME: if on, the chip updates its left/right channel alternatively, creating a nice pseudo-stereo effect
; Note: If you emulate at a set sample rate, this option halves it.
PseudoStereo = False
; Gens: DAC Highpass-Filter (sometimes sounds good, but sometimes it generates a terrible noise)
DACHighpass = False
; Gens: SSG-EG Enable (very buggy)
SSG-EG = False
; Channels: 7 (0-5, DAC)
[YM2151]
Disabled = False
; Channels: 8 (0-7)
[SegaPCM]
Disabled = False
; Channels: 16 (0-15)
[RF5C68]
Disabled = False
; Channels: 8 (0-7)
[YM2203]
Disabled = False
; AY/YM2149 EmulatorType: 0 - EMU2149, 1 - MAME
EmulatorType = 0x00
; disable the AY8910-part to speed up loading
DisableAY = False
; Channels: 3 (0-2)
[YM2608]
Disabled = False
EmulatorType = 0x00
DisableAY = False
; Channels: 6 FM (0-5) + 6 ADPCM (0-5) + 1 Delta-T
; Use MuteMask_FM, MuteMask_PCM (Delta-T is Ch6), MuteFMCh, MutePCMCh and MuteDT
[YM2610]
Disabled = False
EmulatorType = 0x00
DisableAY = False
; Channels: 6 FM (0-5) + 6 ADPCM (0-5) + 1 Delta-T
; Use MuteMask_FM, MuteMask_PCM (Delta-T is Ch6), MuteFMCh, MutePCMCh and MuteDT
[YM3812]
Disabled = False
; EmulatorType: 0 - DOSBox (AdLibEmu), 1 - MAME
EmulatorType = 0x00
; Channels: 14 (0-8, BD, SD, TOM, TC, HH)
[YM3526]
Disabled = False
; Channels: 14 (0-8, BD, SD, TOM, TC, HH)
[Y8950]
Disabled = False
; Channels: 15 (0-8, BD, SD, TOM, TC, HH, DT)
[YMF262]
Disabled = False
; EmulatorType: 0 - DOSBox (AdLibEmu), 1 - MAME
EmulatorType = 0x00
; Channels: 23 (0-17, BD, SD, TOM, TC, HH)
[YMF278B]
Disabled = False
; Channels: 23 FM (0-17, BD, SD, TOM, TC, HH) + 24 WaveTable (0-23)
; Use MuteMask_FM, MuteMask_WT, MuteFMCh and MuteWTCh
[YMF271]
Disabled = False
; Channels: 12 (0-11)
[YMZ280B]
Disabled = False
; Channels: 8 (0-7)
[RF5C164]
Disabled = False
; Channels: 8 (0-7)
[PWM]
Disabled = False
; Channels: none (it just has left and right)
[AY8910]
Disabled = False
; EmulatorType: 0 - EMU2149, 1 - MAME
EmulatorType = 0x00
; Channels: 3 (0-2)
[GameBoy]
Disabled = False
; double the volume of the Wave Channel (sounds better, but may be less accurate and seems to sound distorted sometimes, like nezplay++)
BoostWaveChn = True
; don't double volume of the Noise Channel (like MESS and nezplay++, False is like VisualBoy Advance and sounds better for some games)
LowerNoiseChn = True
; disable the accuracy hacks (expect some slightly off-tune notes and a very distorted Wave Channel)
Inaccurate = False
; Channels: 4 (0-3)
[NES APU]
Disabled = False
; EmulatorType: 0 - NSFPlay, 1 - MAME
EmulatorType = 0x00
; Channels: 6 (0-5 = Square 1, Square 2, Triangle, Noise, DPCM, FDS)
; Options (NSFPlay cores only)
; -------
; APU/DMC Options (2 bits, default: 0x03)
; 0x01 - OPT_UNMUTE_ON_RESET (enable all channels by default after reset)
; 0x02 - OPT_NONLINEAR_MIXER
SharedOpts = 0x03
; APU Options (2 bits, default: 0x01)
; 0x01 - OPT_PHASE_REFRESH
; 0x02 - OPT_DUTY_SWAP
APUOpts = 0x01
; DMC Options (6 bits, default: 0x3B)
; 0x01 - OPT_ENABLE_4011
; 0x02 - OPT_ENABLE_PNOISE
; 0x04 - OPT_DPCM_ANTI_CLICK (nullify register 4011 writes, keeps DPCM limits correctly)
; 0x08 - OPT_RANDOMIZE_NOISE
; 0x10 - OPT_TRI_MUTE (stops Triangle wave if set to freq = 0, processes it at a very high rate else)
; 0x20 - OPT_TRI_NULL (VB custom, always makes Triangle return to null-level when stopping)
DMCOpts = 0x3B
; FDS Options (1 bit, default: 0x00)
; 0x01 - OPT_4085_RESET (reset modulation phase on 4085 writes)
FDSOpts = 0x00
[MultiPCM]
Disabled = False
; Channels: 28 (0-27)
[uPD7759]
Disabled = False
; Channels: none (actually 1)
[OKIM6258]
Disabled = False
; enables internal 10-bit processing (original MESS behaviour)
; The comments in the code say something about 10-bit and 12-bit DAC, but that's not what the code does.
Enable10Bit = False
; Remove the DC offset by resetting the ADPCM signal everytime a Play command is issued.
; Note: This causes lots of clicks with polyphonic ADPCM drivers, so the option is False by default.
RemoveDCOfs = True
; Channels: none (actually 1)
[OKIM6295]
Disabled = False
; Channels: 4 (0-3)
[K051649]
; also known as SCC1
Disabled = False
; Channels: 5 (0-4)
[K054539]
Disabled = False
; Channels: 8 (0-7)
[HuC6280]
Disabled = False
; EmulatorType: 0 - Ootake, 1 - MAME (sounds brighter, lacks LFO)
EmulatorType = 0x00
; Channels: 6 (0-5)
[C140]
Disabled = False
; Channels: 24 (0-23)
[K053260]
Disabled = False
; Channels: 4 (0-3)
[Pokey]
Disabled = False
; Channels: 4 (0-3)
[QSound]
Disabled = False
; Channels: 16 (0-15)
[SCSP]
Disabled = False
; Skip all DSP calculations, huge speedup (the DSP doesn't work correctly right now anyway)
BypassDSP = True
; Channels: 32 (0-31)
[WSwan]
Disabled = False
; Channels: 4 (0-3)
[VSU]
Disabled = False
; Channels: 6 (0-5)
[SAA1099]
Disabled = False
; Channels: 6 (0-5)
[ES5503]
Disabled = False
; Channels: 32 (0-31)
[ES5506]
Disabled = False
; Channels: 32 (0-31)
[X1-010]
Disabled = False
; Channels: 16 (0-15)
[C352]
Disabled = False
; Channels: 32 (0-31)
[GA20]
Disabled = False
; Channels: 4 (0-3)

View file

@ -0,0 +1,159 @@
VGM Player - Readme
==========
General
=======
Usage: Drop a file on the executable or open the program and type the filename.
Supported files types are:
- Video Game Music Files (*.vgm, *.vgz)
- Creative Music Files (*.cmf)
- DosBox RAW OPL Log Files (*.dro)
- Playlist files (*.m3u)
Supported chips
---------------
- SN76496** (Sega PSG) and T6W28** (NeoGeo Pocket custom)
- YM2413* (OPLL)
- YM2612 (OPN2)
- YM2151 (OPM)
- SegaPCM
- RF5C68
- YM2203 (OPN)
- YM2608 (OPNA)
- YM2610/B (OPNB)
- YM3812* (OPL2)
- YM3526* (OPL)
- Y8950* (MSX AUDIO)
- YMF262* (OP3)
- YMF278B (OPL4) !
- YMF271 (OPLX)
- YMZ280B
- RF5C164 (Sega MegaCD PCM)
- PWM (from Sega 32x)
- AY8910 (MSX PSG)
- GameBoy DMG
- NES APU (incl. FDS)
- MultiPCM
- UPD7759
- OKI6258 (Sharp X68000 ADPCM)
- OKI6295
- K051649
- K054539
- HuC6280 (PC Engine)
- Namco C140
- K053260
- Pokey (Atari)
- QSound
- SCSP (Saturn Custom Sound Processor, YMF292-F)
- WonderSwan
- Virtual Boy VSU
- SAA1099
- ESS5503
- ESS5505/6
- Seta X1-010
- Namco C352
- Irem GA20
* This chip can be emulated via OPL Hardware (like Soundblaster sound cards).
** OPL hardware emulation is available, but software emulation is prefered. Hardware emulation is used if another chip activates HW emulation or FMForce is True.
! You need a sample ROM, called yrw801.rom, to make playback work. Place it in the directory where VGMPlay.exe lies.
OPL hardware emulation can be enabled by setting the "FMPort"-entry in the ini-file.
If you want to use FM Hardware under Windows NT/2000/XP/... you have to install PortTalk.
PortTalk Website: http://www.beyondlogic.org/porttalk/porttalk.htm
Under Linux the program must have root rights to use Hardware FM.
It's possible to write Wave-Files by editing the "LogSound"-line in the ini-file.
Batch conversions are possible by opening a playlist.
FM Hardware can't be logged to Wave files.
Keys
----
You can use the following keys during playback:
Space - Pause
Cursor Left/Right - Seek 5 seconds backward/forward
Ctrl + Cursor Left/Right - Seek 1 minute backward/forward
ESC/Q - Quit the program
F - Fade out
R - Restart current Track
PageUp/B - Previous Track
PageDown/N - Next Track
Note: All keys also work during silent sound logging.
System Reqiurements
===================
It depends on the files you want to play.
Minimum Reqiurements
--------------------
Software Emulation:
166 MHz should be enough for SN76496 + YM2612.
For chips with 12+ FM channels you need probably need at least 700 MHz.
16 MB RAM (plus a size of the VGM you want to play, so for a 100 MB vgm, you need ~110 MB RAM)
That allows you to play VGMs with up to 2x FM, 2x PSG or FM + PSG + PCM.
It's NOT enough for YMF271 emulation.
The YMF262 is equal to 2x FM. The YMF278B is Wavetable + YMF262 (with the latter one disabled if unused).
Hardware FM Playback:
486 with 33 MHz? - I dunno
On my PII 233 MHz FM Playback takes 3.5% CPU at a maximum.
Bugs
====
PauseEmulation is disabled under Linux unless FM Hardware is used.
Under Linux you have to double-tap ESC to quit the program (or just press Q). I haven't yet found a way around it.
Sometimes MAME's sound cores tend to sound strange. I already fixed some, but it's not my fault.
Ubuntu refuses to run (or maybe compile) VGMPlay correctly. It either crashes upon opening a vgm file or doesn't open the sound device. (and the ini-file, too. VGMs are opened for some reason.)
Using Wine with the Windows-version of VGMPlay should work.
It runs fine on openSUSE. (I compile and test it regularly with 12.3 64-bit. Older version were successfully tested with 11.1 32-bit and 11.4 64-bit)
It also ran fine on the Debian system at university.
Comments
========
If you want to set some options, open the ini-file. It's well commented.
The T6W28 doesn't use MAME's T6W28 core. Instead I modified the SN76496 core to emulate the T6W28 with 2 SN76496 chips.
The SN76496 OPL emulation is okay, but it's impossible to get the noise sound right.
EMU2413 Emulator was added, because sometimes the one of MAME sounds strange.
I added the Gens YM2612 core for the same reason (before I fixed MAME's YM2612 core).
I haven't yet found a player that supports all three version of dro files.
P.S.: AdPlug now seems to support them.
Some may be wondering, how someone can have the idea to implement OPL Hardware support. Here a more or less small story:
I like CMF MIDI files, but I was unable to listen to them while doing other things on my computer in Windows 95. It was impossible to listen to them unter Windows 2000. When I found AdPlug, the CMF support was bad and I started to make my VGM Player play CMF files. Debugging wasn't nice - a Pentium2 233MHz isn't stong enough for a Software OPL Emulator in Debug Mode. The OPL2-Port option in AdPlug was interesting (I have a Soundblaster 16) and showed me the power of PortTalk.
My MIDI-FM Player that got OPL-Hardware-Support earlier than my VGM Player, because playing usual MIDI files requires a lot more debugging than playing simple VGM files. When it was working in my MIDI player, I implemented OPL-Hardware-Support into VGMPlay. Of course the first working chips were OPL/OPL2/OPL3. I remembered that Meka had OPL-Support, too and wrote my OPLL->OPL-Mapper. It sounded quite good, but I was unable to get the PSG and the YM2413 of Space Harrier Theme in sync. So a PSG->OPL-Mapper followed. Later I ported Meka's OPL Mapper, because I liked the bass of some Phantasy Star tunes.
Credits
=======
This program was written by Valley Bell.
- almost all software emulators are from MAME (http://mamedev.org)
- EMU2413 and Gens YM2612 were ported from Maxim's in_vgm
- the YMF278B core was ported from openMSX
- zlib compression by Jean-loup Gailly and Mark Adler is used
- all custom OPL Mappers were written using MAME software emulators and the OPL2/3 programming guides by Jeffrey S. Lee and Vladimir Arnost
- one YM2413 OPL Mapper was ported from MEKA.
- the RF5C164 and PWM cores were ported from Gens/GS
- the MAME YM2612 core was fixed with the help of Blargg's MAME YM2612 fix and Genesis Plus GX' YM2612 core
- AdLibEmu (OPL2 and OPL3 core) was ported from DOSBox
- The default HuC6280 core is from Ootake.
- EMU2149, the alternative NES APU core and the NES FDS core were ported from rainwarrior's NSFPlay.
- the WonderSwan core was ported from in_wsr
- Virtual Boy VSU core was ported from vbjin and originates from mednafen

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,75 @@
// VGMPlay_Intf.h: VGMPlay Interface Header File
//
//#define NO_WCHAR_FILENAMES
#ifndef WIN32
// Linux uses UTF-8 Unicode and has no special wide-character file routines.
#define NO_WCHAR_FILENAMES
#endif
typedef struct waveform_16bit_stereo
{
INT16 Left;
INT16 Right;
} WAVE_16BS;
typedef struct waveform_32bit_stereo
{
INT32 Left;
INT32 Right;
} WAVE_32BS;
typedef struct vgm_file VGM_FILE;
struct vgm_file
{
int (*Read)(VGM_FILE*, void*, UINT32);
int (*Seek)(VGM_FILE*, UINT32);
UINT32 (*GetSize)(VGM_FILE*);
};
#ifdef __cplusplus
extern "C" {
#endif
void * VGMPlay_Init(void);
void VGMPlay_Init2(void* vgmp);
void VGMPlay_Deinit(void* vgmp);
UINT32 GetGZFileLength(const char* FileName);
bool OpenVGMFile(void* vgmp, const char* FileName);
bool OpenVGMFile_Handle(void* vgmp, VGM_FILE*);
void CloseVGMFile(void* vgmp);
void FreeGD3Tag(GD3_TAG* TagData);
UINT32 GetVGMFileInfo(const char* FileName, VGM_HEADER* RetVGMHead, GD3_TAG* RetGD3Tag);
UINT32 GetVGMFileInfo_Handle(VGM_FILE*, VGM_HEADER* RetVGMHead, GD3_TAG* RetGD3Tag);
UINT32 CalcSampleMSec(void* vgmp, UINT64 Value, UINT8 Mode);
UINT32 CalcSampleMSecExt(void* vgmp, UINT64 Value, UINT8 Mode, VGM_HEADER* FileHead);
const char* GetChipName(UINT8 ChipID);
const char* GetAccurateChipName(UINT8 ChipID, UINT8 SubType);
UINT32 GetChipClock(void* vgmp, UINT8 ChipID, UINT8* RetSubType);
#ifndef NO_WCHAR_FILENAMES
UINT32 GetGZFileLengthW(const wchar_t* FileName);
bool OpenVGMFileW(void* vgmp, const wchar_t* FileName);
UINT32 GetVGMFileInfoW(const wchar_t* FileName, VGM_HEADER* RetVGMHead, GD3_TAG* RetGD3Tag);
#endif
INT32 SampleVGM2Playback(void* vgmp, INT32 SampleVal);
INT32 SamplePlayback2VGM(void* vgmp, INT32 SampleVal);
void PlayVGM(void* vgmp);
void StopVGM(void* vgmp);
void RestartVGM(void* vgmp);
void SeekVGM(void* vgmp, bool Relative, INT32 PlayBkSamples);
void RefreshMuting(void* vgmp);
void RefreshPanning(void* vgmp);
void RefreshPlaybackOptions(void* vgmp);
UINT32 FillBuffer(void* vgmp, WAVE_16BS* Buffer, UINT32 BufferSize);
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,130 @@
Update list since 0.4.0u3 (03.12.2012)
- replaced some larger swich statements with function pointers (small speed up)
- fixed Stereo flag in SN76496 OPL mapper
- optimized playback routine (huge speed up, >20% for single-chip VGMs)
- writing to a second chip if only the first one is defined doesn't cause crashes anymore
- shortened the Chip Reset, Chip Mute and Chip Panning routines
- added OKIM6295, OKIM6258 and UPD7759 to DAC Stream Control
- slight improvements on OPL Hardware Playback
- fixed bug where [VGMPlay Linux] was unable to show Unicode characters
- added multiple paths for VGMPlay.ini and OPL4 ROM
- [VGMPlay Linux] is now checking for "vgmplay.ini" as well as "VGMPlay.ini"
- cleaned the code a bit
- [VGMPlay] now frees its memory properly when quitting
17.04.2013 and later:
- improved skipping code for OPL hardware (to hopefully reduce noise after seeking)
- made Makefile print short information instead of full gcc command lines
- added possibility to override volume (+gain) of VGMs when using OPL hardware
- [VGMPlay] made it use stderr for error messages
- added optional debug output for DAC stream control (current data block, frequency)
- fixed a bug with data blocks being re-read when restarting playback (wasted memory)
- [VGMPlay] fixed bug when alternating between OPL hardware playback and emulation without restarting VGMPlay (e.g. via playlist with OPL and non-OPL VGMs)
- fixed crash where the NES ROM could be written to invalid offsets
- added alternative AY8910 core (EMU2149)
- added NES DPCM address overflow behaviour, added alternative DPCM range (based on NSFPlay)
- [VGMPlay] prevented it from writing too quickly to the OPL chip on fast computers
15.06.2013 and later:
- [VGMPlay] console title now changes to "Song (Game) - VGM Player" while playing
- [VGMPlay] made it fall back to Japanese tags if English ones are empty
- [VGMPlay] made Console title use Unicode (yes, that works - not like the in-Console text)
- [in_vgm] made ANSI GetFileInfo function fall back to Japanese tags if English ones are not present
- [in_vgm] fixed Unicode -> ANSI filename conversion bug (caused Unicode Tag function to fail with some non-ANSI filenames)
- [in_vgm] fixed File Info Dialog falling back to tags of the other language (it isn't supposed to do that)
- [VGMPlay] some Codepage fixes for Windows version, hopefully it now behaves correctly in all cases.
The Linux version should now be able to print non-ANSI Unicode characters in tags.
- [VGMPlay Windows] now writes Unicode to the console (via WinAPI), so with the non-raster-fonts Japanese characters should work now. (although I only saw square boxes in WinXP, copying and pasting into Notepad worked at least)
- [in_vgm] Fixed bug where "Chip Rate" == 0 didn't work and would get reset to 44100 when loading the plugin.
- fixed bug where YM2612 Database Block caused DAC Stream Control to malfunction or crash (The MAME devs were right - realloc IS evil.)
- [VGMPlay Linux] added support for libao
09.09.2013 and later:
- added WonderSwan support
- added better SN-PSG name display
- made it work on Big Endian machines (Thanks to nextvolume for sending me a patch that helped to find the critical spots)
- cleaned code that loads VGMs a bit
- shortened the Chip Stop routine
- applied MAME fixes to YM2413/YMF262 (thread safe now), K051649 (added test register, changed sound generation code a bit), K054539 (replaced sound generation code, might improve reverb), YMZ280B (minor stuff), YMF271 (FM code replaced, sounds different now!)
- added NES APU database block type
- added NES APU to 0x68 command (RAM write from database) and fixed its dual chip support
- ported NES APU/DMC emulator from NSFPlay 2.2
- ported NES FDS emulator from NSFPlay 2.3
- fixed MAME NES emulator reset
- fixed MAME NES (and maybe others?) unmuting all channels when restarting a song or seeking back
- added EMU2149 to YM2203, YM2608 and YM2610, fixes wrong AY-PSG tones in some VGMs (bug is still present with MAME's AY core)
- [VGMPlay] modified makefile to make it easier to compile VGMPlay using MSYS/MinGW
- [in_vgm] fixed crash when trying to mute channels after opening Winamp, but before any song was played
- [in_vgm] added options from VGMPlay.ini to in_vgm.ini
- [in_vgm] fixed track length display bug after changing the playback rate
- [VGMPlay Linux] fixed warnings that are printed from ym2612.c
- added VRC7 mode for YM2413 (reducing features and using separate instrument set)
- [in_vgm] made OK button of File Dialog return another error code to Winamp to prevent a playlist bug
Updates since 0.4.0u4 (02.11.2013)
- added code for muting channels to K053260 (looks like I forgot that one) and K054539 (lost when applying MAME fixes)
- made K054539 use a proper clock (with a fallback for older VGMs)
- added a small hack that allows mid-song sample rate changes for the OKIM6258 chip (I'll make a proper implementation for 0.41)
- [VGMPlay] fixed absolute paths in m3u files
- [VGMPlay] fixed path handling, makes paths that contain / and \ work in both Windows and Unix, fixes m3u Windows paths under Unix
- fixed pitch of YM2608 ADPCM Tom Tom and Rim Shot (reported by MaliceX)
- fixed YM2612 Timer A (there are still tiny rounding errors though), this fixed the CSM mode
- fixed probable YM2612 bug (CSM mode was able to prevent KeyOn/Off commands on channels other than FM3)
- fixed noise calculation in MAME's AY8910 (applied latest MAME update)
- fixed a few crashes related to corrupted VGM headers with invalid offsets and insane clock values (though not all)
- [VGMPlay] MuteWTCh# now works in VGMPlay.ini
- fixed clicks in YMF278B core (introduced when porting it from openMSX)
- [VGMPlay] fixed length display when VGMs play slower/faster after using the PlaybackRate option
- fixed bug where VGZs with additional 00s at the end won't play (because VGMPlay will read an unpacked size of 0 bytes)
- changed Endianess of SCSP RAM data to Big Endian (as it should be)
- applied MAME QSound fixes (key on register, chip initialization)
- removed last A from AY-3-8910A and variants
- added an option to force OKIM6258 into 12-bit mode (makes it louder sometimes, but an internal 12-bit calculation seems to be more correct)
- VGMs using the OKIM6258 or OKIM6295 are now half as loud (affects global volume only, not chip-relative volume)
- [VGMPlay] fixed crash that happened on Linux when trying to display a large Notes tag (thanks to vampi-the-frog for the report)
- OKIM6258 lowers its output signal faster if there's no incoming data (reduces clicks)
Updates since 0.4.0u5 (13.04.2014)
- fixed panning in AdLibEmu with 4-op instruments (it used the bits from Channel+0 instead of Channel+3)
- fixed panning in AdLibEmu for rhythm channels
- [VGMPlay] fixed YM2608/YM2610 DeltaT-channel not being muteable via MuteMask_PCM
- [VGMPlay] fixed muting of YM278B's FM drums
- applied MAME YM2612 Timer fix (said to fix SFX in Streets of Rage 2, see MAME Testers 05049)
- fixed C140 sub chip type and C140/System 21 banking (using current MAME code)
- added code to handle "real" C140 clock
- [VGMPlay] fixed "make install" (the share/vgmplay/ folder was created without "execute" rights for users)
- improved OKIM6258 data cache (should reduce clicks a bit)
- YMF278B: fixed OPL3 register writes and OPL3 chip clock
- applied MAME K053260 DPCM decoding fix
- applied MAME OPLx Key Scale Level fix
- added 40h-byte-FIFO to UPD7759 chip when in Slave mode, based on how Sega Pico games work
- fixed T6W28 muting (Noise channel muting was controlled by chip #2, affected in_vgm only)
Thanks to the developers of foo_input_vgm for noticing this bug.
- added NMK112 banking to OKIM6295 emulation
- added callback function for chip sample rate change
-> replaces OKIM6258 hack
-> fixes OPN SSG with MAME AY emulation
-> makes OKIM6295 clock changes work
- added routines for wide-character file names (only used by in_vgm for now)
- fixed RAM write range check for RF5C68 and RF5C164
- made OKIM6258 FIFO queue larger, added RemoveDCOfs option
- [VGMPlay] fixed tag display under Windows 95
- fixed YM2151 internal sample clipping (works like YM2612 now, can reduce distortion)
- fixed SegaPCM volume register bitmask [thanks ctr for finding the bug]
- fix potential crash in MultiPCM chip when playing invalid instruments
- fixed buggy frequency writes in K051649 by backporting some MAME changes
- added VSU, SAA1099 support
- fixed high beep in NSFPlay NES core with triangle at frequency 0 and OPT_TRI_NULL option
- [VGMPlay] fixed YM2612 DAC not being muteable via MuteMask
- added ES5503, ES5506, Seta X1-010, Namco C352, Irem GA20 support
- [VGMPlay] fixed Loop Length (is now adjusted for changed playback rates)
Updates since 0.4.0u6 (30.05.2015)
- fixed SAA1099 muting (muting channel 1 or 4 prevented the envelope generator from running, thus muting 0-2 or 3-5 respectively)
- made SAA1099 output bipolar
- [VGMPlay] fix compiling under Linux (broken since Wide-Charcter file name support)
- fixed ES5503 sample rate (divider was off by one)
- applied fix from VOGONS that makes the SAA1099 core actually use the chip clock
- fixed YMF278B's FM part being emulated at wrong sample rate
- fixed Irem GA20 channel muting
- fixed playing non-NMK banked OKIM6295 VGMs after NMK-banked ones

View file

@ -0,0 +1,403 @@
// SWJ-SQRC01_1C.vgz
UINT8 FF1ws_1C[0x1908] =
{ 0x1F, 0x8B, 0x08, 0x00, 0xD4, 0x7A, 0x2F, 0x52, 0x02, 0x00, 0xD4, 0x98, 0x57, 0xCC, 0x0E, 0x51,
0x10, 0x86, 0xC7, 0xFA, 0x7D, 0x7A, 0x0D, 0x42, 0x5C, 0x10, 0x12, 0x2E, 0x08, 0xA2, 0x25, 0x7A,
0xFB, 0x95, 0x04, 0x21, 0xD1, 0xE2, 0x42, 0x39, 0x21, 0x24, 0x12, 0xD1, 0xAD, 0x16, 0xBD, 0xF7,
0xDE, 0x7B, 0xEF, 0xBD, 0x1B, 0xDC, 0x6D, 0x24, 0x88, 0x1E, 0xA2, 0x04, 0x97, 0x6E, 0x48, 0x5C,
0x48, 0x44, 0x94, 0x67, 0x8F, 0xC3, 0xE2, 0x60, 0xD5, 0xE0, 0x4B, 0x26, 0xF1, 0xAD, 0x9D, 0x77,
0xDE, 0x77, 0x66, 0xCE, 0x9C, 0xF9, 0xFE, 0x2E, 0xFD, 0x06, 0x94, 0xEB, 0xDA, 0x4B, 0x64, 0x70,
0x0E, 0xF9, 0xF0, 0x69, 0xDA, 0x53, 0xE4, 0x71, 0xC9, 0x72, 0x72, 0xB5, 0x80, 0x48, 0xA5, 0x1E,
0x65, 0xE4, 0xF3, 0xCF, 0x1A, 0xF9, 0x87, 0x3E, 0x0F, 0xAB, 0x7E, 0xF2, 0x75, 0x90, 0xE6, 0x11,
0xCD, 0x27, 0x9A, 0x5F, 0x54, 0x44, 0x73, 0x88, 0x06, 0xA2, 0x39, 0x45, 0xB3, 0x44, 0x73, 0x89,
0x66, 0x44, 0x73, 0xF3, 0x46, 0x01, 0xD1, 0x82, 0xA2, 0x79, 0x45, 0x8B, 0x34, 0xD1, 0xE2, 0xA2,
0x45, 0x33, 0x83, 0xB4, 0x50, 0x29, 0x2D, 0x1C, 0x98, 0xD6, 0x41, 0x24, 0x13, 0xDE, 0x44, 0x32,
0x11, 0x9B, 0x84, 0x4D, 0xC6, 0xA6, 0x60, 0x53, 0xB1, 0x69, 0xD8, 0x74, 0x6C, 0x86, 0x44, 0x32,
0x13, 0x9B, 0x85, 0xCD, 0xC6, 0xE6, 0x60, 0x73, 0xB1, 0x79, 0xD8, 0x7C, 0x19, 0x1A, 0xC9, 0x02,
0x5E, 0x5A, 0x88, 0x2D, 0xC2, 0x16, 0x63, 0x4B, 0xB0, 0xA5, 0xD8, 0x32, 0x6C, 0x39, 0xB6, 0x82,
0x17, 0x57, 0x62, 0xAB, 0xB0, 0xD5, 0xD8, 0x1A, 0x6C, 0x2D, 0xB6, 0x0E, 0x5B, 0x2F, 0xC3, 0x22,
0xD9, 0xF0, 0x2A, 0x92, 0x8D, 0xCB, 0x22, 0xD9, 0x54, 0x3D, 0x92, 0xCD, 0x2F, 0x23, 0xD9, 0x32,
0x35, 0x92, 0xAD, 0xCD, 0x22, 0xD9, 0x56, 0x2C, 0x92, 0xED, 0x2D, 0x22, 0xD9, 0xD1, 0x27, 0x92,
0x9D, 0xE5, 0x23, 0xD9, 0x55, 0x3B, 0x92, 0xDD, 0xFB, 0x22, 0xD9, 0xC3, 0xFB, 0x7B, 0x4F, 0x44,
0xB2, 0x6F, 0x78, 0x24, 0xFB, 0x6B, 0x8C, 0x00, 0xA0, 0x39, 0x00, 0xE5, 0x01, 0x78, 0x03, 0xC0,
0x13, 0x00, 0xEA, 0x00, 0xB0, 0x06, 0x80, 0x0C, 0x00, 0x97, 0x01, 0x78, 0x03, 0x00, 0xB6, 0x0B,
0xDB, 0x1D, 0x00, 0xD0, 0x0F, 0x80, 0x0D, 0x00, 0x08, 0x00, 0xC5, 0x06, 0x6B, 0x56, 0x69, 0xCD,
0x95, 0x7B, 0x70, 0x24, 0x07, 0x00, 0x3E, 0x08, 0x91, 0x43, 0x10, 0x39, 0x0C, 0x91, 0x23, 0x10,
0x39, 0x0A, 0x91, 0x63, 0x10, 0x39, 0x0E, 0x91, 0x13, 0x10, 0x39, 0x49, 0x9C, 0x53, 0x10, 0x39,
0x0D, 0x11, 0xE5, 0xFD, 0x33, 0x10, 0x39, 0x0B, 0x91, 0x73, 0x35, 0x86, 0x03, 0xD0, 0x1C, 0x80,
0xF2, 0x00, 0xBC, 0x01, 0xE0, 0x09, 0x00, 0x75, 0x00, 0x58, 0x03, 0x40, 0x06, 0x80, 0xCB, 0x00,
0xBC, 0x01, 0x00, 0x3B, 0x85, 0x9D, 0x86, 0x88, 0xF6, 0x03, 0x60, 0x03, 0x00, 0x02, 0x00, 0x44,
0x32, 0xBD, 0x35, 0x77, 0xD6, 0x20, 0x2D, 0xD2, 0xD6, 0x54, 0x0D, 0x34, 0x6F, 0xCD, 0xA1, 0x9A,
0x0F, 0xCB, 0x5F, 0xD3, 0xDC, 0xC8, 0x68, 0xBE, 0xEC, 0x21, 0x9A, 0x3F, 0xDB, 0xCC, 0xCC, 0xD2,
0xBC, 0xD9, 0xA6, 0x6C, 0x5E, 0xCD, 0xDB, 0xD9, 0xDC, 0xE5, 0x69, 0x27, 0xFE, 0xBF, 0x85, 0xB9,
0x96, 0x51, 0x69, 0xA8, 0x39, 0x72, 0x8F, 0xD4, 0xE0, 0xB9, 0xE6, 0xCC, 0x0A, 0xB5, 0x48, 0x7B,
0x53, 0x23, 0xD0, 0x3C, 0xD9, 0x43, 0x41, 0x31, 0xF3, 0x63, 0x1F, 0xB0, 0xFA, 0x80, 0xD0, 0xD2,
0x34, 0xE2, 0x79, 0x67, 0x73, 0x2B, 0xA3, 0x79, 0xFA, 0x0E, 0x8D, 0x51, 0x96, 0x67, 0x69, 0xFE,
0xF2, 0xA6, 0x21, 0x4F, 0xC3, 0x21, 0x9A, 0xB7, 0xAF, 0x39, 0x50, 0x50, 0xA5, 0xC6, 0x08, 0x0D,
0xCE, 0xDB, 0x67, 0x44, 0x05, 0x61, 0x81, 0x8D, 0x9A, 0x6D, 0x3D, 0x6F, 0xC7, 0x9E, 0x43, 0x62,
0xCF, 0x0E, 0x41, 0xCC, 0x6D, 0x4A, 0x16, 0x9E, 0x43, 0x63, 0xCF, 0xFD, 0x78, 0x36, 0xC4, 0xF3,
0x39, 0x9E, 0x2E, 0xF6, 0x50, 0x18, 0x9A, 0xD9, 0x2E, 0x7E, 0xB6, 0x69, 0xFA, 0x69, 0xEC, 0x21,
0xE8, 0x33, 0x57, 0x33, 0xCE, 0x9F, 0x6F, 0xE5, 0x63, 0xF4, 0x7C, 0x45, 0xCD, 0xCD, 0x0C, 0x1C,
0x46, 0xC2, 0x81, 0x67, 0x12, 0x6A, 0xA6, 0xB2, 0xA9, 0x86, 0x67, 0x11, 0xA2, 0xE6, 0x30, 0x0F,
0x32, 0x71, 0x1E, 0x2E, 0xE1, 0x55, 0x8E, 0xEF, 0x81, 0x39, 0x5E, 0xF0, 0x7D, 0x06, 0x3A, 0x86,
0x1A, 0xB4, 0xD1, 0x9C, 0xB9, 0x4C, 0xBD, 0x4F, 0xA5, 0x8F, 0xF8, 0x92, 0xEC, 0xC5, 0x59, 0x04,
0xB2, 0x84, 0x12, 0xF2, 0xDD, 0x21, 0x3F, 0x04, 0xF2, 0x9F, 0x78, 0xC7, 0x14, 0x1C, 0xF1, 0x44,
0x3A, 0x04, 0x49, 0xD7, 0x7B, 0xBF, 0x81, 0xF8, 0x9D, 0xFA, 0xDC, 0xCF, 0xB4, 0xF8, 0xCC, 0xE7,
0x86, 0x13, 0x4A, 0x8A, 0xE3, 0x58, 0xC8, 0x1B, 0x32, 0x5A, 0x33, 0xCF, 0x34, 0x77, 0xCE, 0x77,
0xEA, 0x86, 0xA2, 0x0E, 0xAA, 0xD6, 0x1D, 0x85, 0x25, 0xF2, 0xBE, 0x57, 0xB8, 0x22, 0x0B, 0x85,
0xD4, 0x1C, 0x19, 0xE8, 0x24, 0x5C, 0x18, 0x87, 0xAB, 0xEF, 0x55, 0xC7, 0x0F, 0x97, 0x48, 0xEB,
0x0B, 0xC5, 0xE5, 0x3E, 0x45, 0x97, 0x14, 0x5F, 0xD6, 0xC1, 0x82, 0x2E, 0x0E, 0x14, 0x8F, 0x98,
0xEA, 0xEF, 0xB3, 0x1F, 0xC6, 0xFC, 0xE6, 0x59, 0x7E, 0x25, 0x3F, 0xF0, 0x5B, 0x6E, 0xF9, 0x95,
0xB3, 0xFC, 0xA8, 0xA6, 0x84, 0x48, 0xBB, 0x93, 0x14, 0xC1, 0x8F, 0x35, 0xD4, 0xF1, 0xFB, 0xA8,
0xE3, 0xC6, 0xC3, 0xEF, 0x05, 0xFC, 0x7E, 0x44, 0xD3, 0x34, 0x7C, 0x4A, 0x6A, 0xCE, 0x0C, 0x6E,
0xDF, 0x1B, 0xEA, 0xA0, 0x0B, 0x75, 0x7F, 0xA4, 0x66, 0x9D, 0xD2, 0x5C, 0xB9, 0x46, 0x68, 0x26,
0x5B, 0x73, 0x07, 0xA6, 0x8A, 0x13, 0x98, 0x1C, 0xB9, 0x19, 0xAE, 0xF6, 0x58, 0x22, 0xD6, 0xB6,
0x6C, 0x27, 0xB3, 0x24, 0x16, 0x4C, 0x4F, 0x80, 0x18, 0x1F, 0x2B, 0x0E, 0xE2, 0xFB, 0xD2, 0xAC,
0x07, 0x7B, 0x0C, 0xA5, 0x49, 0xE7, 0x93, 0xC8, 0x58, 0x89, 0x4F, 0x9F, 0x71, 0x9A, 0x59, 0xC6,
0xA1, 0xC7, 0xCF, 0xB1, 0x28, 0x9F, 0xB0, 0x18, 0x01, 0x03, 0x34, 0xC6, 0x18, 0xED, 0x03, 0xBA,
0x96, 0x21, 0xE0, 0x12, 0xE2, 0x5A, 0xA3, 0x41, 0xE0, 0xF0, 0xEC, 0x48, 0x90, 0xA1, 0x31, 0x9B,
0x2B, 0xB0, 0x99, 0x3B, 0x12, 0x36, 0x23, 0x34, 0xAB, 0x86, 0xE6, 0xCA, 0x98, 0x5A, 0x8E, 0x54,
0x0E, 0x4B, 0x19, 0x62, 0x08, 0x41, 0x82, 0x03, 0xCD, 0x26, 0x94, 0xA5, 0x47, 0x3D, 0xDB, 0x04,
0x24, 0xC1, 0x06, 0x09, 0x47, 0x24, 0x67, 0x32, 0xF6, 0x10, 0xD3, 0x2D, 0x78, 0x37, 0xA4, 0xDE,
0xB5, 0xC4, 0x08, 0x97, 0x2D, 0xD7, 0xB2, 0xE8, 0x72, 0x87, 0xBC, 0x9C, 0x59, 0xFD, 0x59, 0xD3,
0xAE, 0x0C, 0x51, 0xE9, 0x37, 0x85, 0x23, 0x00, 0x19, 0x08, 0xF8, 0xF9, 0xE9, 0x9F, 0x1F, 0xB2,
0xBC, 0xE5, 0x32, 0xEB, 0x55, 0x3A, 0xFB, 0x9B, 0xE7, 0x72, 0x17, 0x3E, 0x5B, 0x4D, 0xA3, 0xEF,
0x6E, 0xAA, 0x93, 0x05, 0xDF, 0xE5, 0xAB, 0x24, 0x6D, 0x51, 0x99, 0x9E, 0x70, 0x87, 0x72, 0xC8,
0xD7, 0x54, 0xFA, 0xC7, 0xF3, 0x3A, 0x4A, 0xB7, 0xA2, 0x74, 0xA1, 0x55, 0x1A, 0xDA, 0xA8, 0x73,
0x9C, 0xAE, 0x6C, 0xFE, 0x45, 0xE4, 0x11, 0x68, 0x25, 0xB9, 0x70, 0x8A, 0xA3, 0xDB, 0x67, 0x35,
0x4D, 0xDB, 0x00, 0xB6, 0x7C, 0xE7, 0x3D, 0x18, 0xA3, 0xD2, 0xF9, 0xCE, 0x75, 0x95, 0x4E, 0x7C,
0xFB, 0xBC, 0xF3, 0x05, 0xCF, 0xF9, 0x52, 0x2E, 0xFC, 0xAC, 0x2A, 0x7A, 0x46, 0xF6, 0xA3, 0xF9,
0x24, 0x08, 0x56, 0x93, 0x1F, 0x3D, 0xD6, 0xE0, 0x7B, 0x93, 0x61, 0xBC, 0xC7, 0x12, 0x1B, 0xF5,
0x2F, 0x38, 0x17, 0xA1, 0x1B, 0x4C, 0x55, 0x9C, 0xCA, 0x1C, 0xF6, 0x5C, 0x24, 0x87, 0x7F, 0x1A,
0xBE, 0x45, 0x5C, 0xE3, 0x64, 0x07, 0xC9, 0x10, 0x68, 0x86, 0x8E, 0x13, 0x74, 0xDD, 0x7D, 0xF4,
0x7B, 0x1A, 0xC2, 0x38, 0x43, 0x53, 0x2C, 0x8B, 0x05, 0x5F, 0x67, 0x31, 0x44, 0xE5, 0x30, 0x1A,
0x2E, 0xD8, 0xAB, 0xA3, 0xEE, 0x8F, 0xE9, 0xB0, 0xAD, 0xDD, 0xD4, 0x69, 0xB9, 0x8F, 0x96, 0x3B,
0x08, 0x39, 0xF2, 0x53, 0x2A, 0x56, 0xA2, 0x82, 0x7E, 0xF5, 0xE3, 0xDB, 0xDB, 0x64, 0xAA, 0xC7,
0xC1, 0x57, 0x71, 0x22, 0x9E, 0x33, 0x56, 0xC5, 0xD7, 0x7A, 0xC1, 0xE5, 0x61, 0xC8, 0x57, 0x55,
0x8C, 0x50, 0xB9, 0x34, 0x92, 0xED, 0xEA, 0x09, 0xDB, 0xD5, 0x7D, 0xB6, 0xAB, 0x8B, 0x6C, 0x57,
0xA7, 0xD9, 0xAE, 0x76, 0xB1, 0x5D, 0xAD, 0x64, 0xBB, 0x9A, 0xC1, 0x76, 0x15, 0xB2, 0x5D, 0xF5,
0x65, 0xBB, 0xEA, 0xCC, 0x76, 0x95, 0xCD, 0x76, 0x55, 0x93, 0xED, 0xAA, 0x3C, 0xDB, 0x55, 0xD1,
0xC1, 0x94, 0x73, 0x94, 0x3D, 0xFC, 0xB9, 0x47, 0xB3, 0x9A, 0x5C, 0x60, 0x35, 0xB9, 0xC7, 0x6A,
0xF2, 0x9A, 0xD5, 0xE4, 0x0D, 0xAB, 0x09, 0x76, 0xF4, 0x29, 0xAB, 0xC9, 0x25, 0x56, 0x13, 0x65,
0x35, 0xA9, 0xC5, 0x6A, 0x52, 0x81, 0xD5, 0x24, 0x07, 0xAB, 0x89, 0x44, 0xA2, 0xD8, 0x99, 0x22,
0xAC, 0x26, 0x35, 0x58, 0x4D, 0x9A, 0xB3, 0x9A, 0x9C, 0x8F, 0x4F, 0x7D, 0x59, 0xA7, 0x64, 0x25,
0x1C, 0xB1, 0xFC, 0x2B, 0x4D, 0x13, 0x18, 0xCF, 0xA0, 0xB2, 0x33, 0x98, 0x42, 0x68, 0x0B, 0x35,
0xDF, 0x0C, 0x9B, 0xCB, 0x90, 0x3C, 0x85, 0x6E, 0x6A, 0xB5, 0x8B, 0x55, 0xF1, 0x4E, 0x5F, 0x37,
0x19, 0xDF, 0xCD, 0xD1, 0x10, 0xFF, 0xCE, 0x64, 0x12, 0xDD, 0xAE, 0x3B, 0xB2, 0xE9, 0x0E, 0x54,
0xBB, 0xC5, 0x81, 0x9E, 0xA1, 0x52, 0x31, 0x16, 0x4F, 0x82, 0x85, 0xE0, 0x95, 0x37, 0x75, 0xF0,
0x97, 0xA1, 0xC4, 0xC7, 0xBF, 0xB3, 0xC9, 0x76, 0xB1, 0x8B, 0x32, 0x3B, 0xDE, 0x45, 0x14, 0xD3,
0xC2, 0x55, 0x93, 0x88, 0xAC, 0xB7, 0x44, 0xFA, 0xB0, 0xFE, 0xC4, 0xD9, 0x77, 0xB3, 0xD5, 0x34,
0x0F, 0x58, 0x7A, 0xC9, 0xEA, 0x24, 0xB2, 0x3A, 0x99, 0xAC, 0x4E, 0x21, 0xAB, 0x53, 0xC9, 0xEA,
0x34, 0xB2, 0x3A, 0x9D, 0xAC, 0xCE, 0x08, 0x59, 0x7A, 0xC9, 0xEA, 0x2C, 0xB2, 0x3A, 0x9B, 0xAC,
0xCE, 0x21, 0xAB, 0x73, 0xC9, 0xEA, 0x3C, 0xB2, 0x2A, 0x0B, 0x35, 0x47, 0x66, 0xC8, 0x3B, 0x56,
0x77, 0x58, 0x37, 0xAC, 0xF0, 0xC0, 0x91, 0x2A, 0x0A, 0x01, 0x48, 0xD9, 0xA0, 0xA1, 0x3D, 0x94,
0x39, 0x48, 0x89, 0xF8, 0x84, 0x28, 0x3D, 0x64, 0xE2, 0x27, 0x72, 0x47, 0x73, 0xE4, 0x72, 0x78,
0x5B, 0xED, 0x75, 0xF6, 0x1E, 0xCF, 0xB4, 0x4E, 0xB0, 0xC0, 0x05, 0xCB, 0xB4, 0x49, 0x70, 0xDC,
0x38, 0x9B, 0xFF, 0x01, 0x67, 0xEB, 0xA7, 0xBC, 0x12, 0x1C, 0x24, 0x0B, 0xC9, 0x94, 0xC1, 0xF1,
0x5E, 0xD8, 0xD8, 0x62, 0x2E, 0x70, 0xFC, 0x52, 0x30, 0x2D, 0x37, 0x20, 0xE8, 0xE7, 0xA0, 0x0F,
0xDC, 0xEC, 0x30, 0x0D, 0x86, 0x38, 0x6E, 0xA9, 0x38, 0x89, 0xC6, 0x3E, 0x09, 0xB7, 0x85, 0x10,
0xFB, 0x3A, 0x48, 0x5B, 0x0B, 0xD2, 0xEA, 0x8B, 0x20, 0x0B, 0xBF, 0xA8, 0x8E, 0x97, 0x3D, 0x90,
0xEF, 0xCF, 0xF6, 0xCF, 0xE1, 0xF8, 0xD9, 0xFE, 0xF1, 0xAA, 0xF9, 0x7C, 0x2E, 0xFC, 0x4A, 0xF5,
0x2F, 0xC0, 0xC7, 0x56, 0xCA, 0xE3, 0x93, 0x52, 0xA9, 0xB4, 0xFC, 0xFC, 0x64, 0xC5, 0xB7, 0xFE,
0x07, 0x15, 0x77, 0x19, 0xFE, 0x7B, 0x15, 0xEF, 0xE3, 0xF1, 0xF9, 0x81, 0xB3, 0xD9, 0x27, 0xA9,
0xF8, 0xC2, 0x9F, 0x3E, 0x98, 0x7E, 0x86, 0x87, 0xFC, 0xB9, 0x9E, 0xF1, 0xCB, 0xED, 0x67, 0xF8,
0x37, 0x57, 0xFC, 0x42, 0x6A, 0xC5, 0x53, 0xCE, 0xD4, 0xEF, 0xAA, 0xF8, 0xD0, 0x24, 0x3F, 0xA3,
0x35, 0xEB, 0xBC, 0xE6, 0xCA, 0xD2, 0x02, 0x32, 0x8A, 0xF5, 0x84, 0x3D, 0x8B, 0x3F, 0xC7, 0xF0,
0xAB, 0xFF, 0xB2, 0xA9, 0xF8, 0xD1, 0xC4, 0x0E, 0x99, 0xD8, 0xBB, 0x58, 0x03, 0x88, 0xC3, 0xC5,
0x66, 0x71, 0xB8, 0xE8, 0xF8, 0xFE, 0x9E, 0x39, 0xCB, 0x20, 0x6B, 0x5F, 0x12, 0xD5, 0x5E, 0x7F,
0x33, 0xDD, 0xCF, 0x16, 0x16, 0x0A, 0x1B, 0xBD, 0xED, 0xE7, 0x27, 0xB1, 0x9E, 0x2D, 0x8D, 0x0B,
0x81, 0x7B, 0x92, 0x56, 0x0F, 0x34, 0x91, 0xC2, 0xBB, 0x0E, 0xD0, 0xEB, 0x99, 0xF1, 0x83, 0x34,
0xF3, 0x48, 0x73, 0xE7, 0x46, 0x02, 0x7B, 0x56, 0x82, 0x5D, 0xCE, 0xEE, 0x59, 0x76, 0x3B, 0x70,
0xC4, 0xBE, 0xD1, 0x02, 0xBC, 0x5F, 0x04, 0xFC, 0xD4, 0x03, 0x3B, 0xE4, 0x8B, 0x9C, 0xC3, 0xCF,
0x39, 0xCF, 0xF7, 0x38, 0x7B, 0xAD, 0xC5, 0xEF, 0xAD, 0xBE, 0x31, 0xE5, 0xAA, 0x1F, 0x43, 0x7B,
0x77, 0x77, 0x0A, 0x74, 0xCA, 0x79, 0x4E, 0x52, 0x9C, 0x74, 0xCA, 0xD7, 0x52, 0x9C, 0xD4, 0xCC,
0xBF, 0x2F, 0xD9, 0x63, 0x97, 0xB3, 0x93, 0x8F, 0x7C, 0xD7, 0x2B, 0x83, 0x6C, 0xA6, 0x3F, 0x6B,
0x94, 0xD3, 0x1F, 0x1A, 0x25, 0xDB, 0x35, 0x0A, 0x99, 0x77, 0x01, 0x53, 0x1B, 0x25, 0xA9, 0xEB,
0xC7, 0xF7, 0x47, 0xA3, 0x8F, 0x8B, 0x89, 0x7B, 0xCA, 0x3C, 0x48, 0x2B, 0x62, 0xA8, 0x59, 0x6D,
0x50, 0xE0, 0xB7, 0x8A, 0x5D, 0x04, 0xA1, 0x6D, 0x5B, 0x65, 0x78, 0x4C, 0x6D, 0xD6, 0x8F, 0xB5,
0xA3, 0x3F, 0x35, 0x52, 0x98, 0xFF, 0x40, 0xFB, 0x5D, 0x78, 0xC7, 0xBC, 0x7C, 0x48, 0xBB, 0x7C,
0x9A, 0xF8, 0x0F, 0x0B, 0xAC, 0xE5, 0x6D, 0x3A, 0x04, 0xEF, 0x35, 0x84, 0xF6, 0xB4, 0x36, 0xFC,
0xB4, 0x7B, 0xEC, 0xF2, 0xDA, 0xD4, 0x46, 0x6C, 0xEF, 0xCA, 0xE3, 0x74, 0x80, 0x21, 0x66, 0x46,
0xEA, 0xC4, 0x21, 0x1E, 0x5A, 0x5A, 0xA4, 0xDC, 0x57, 0xA9, 0x55, 0x18, 0xF9, 0x6E, 0xF2, 0x84,
0x1F, 0xB5, 0x52, 0xE5, 0x3F, 0xD2, 0x4A, 0x5B, 0x3F, 0xBA, 0x9B, 0x9C, 0x88, 0x1F, 0x98, 0x39,
0x29, 0xBD, 0x39, 0x7E, 0xF0, 0x57, 0x66, 0x8E, 0xD7, 0x48, 0x3F, 0xDD, 0xAE, 0x70, 0x4E, 0x9F,
0x93, 0x2D, 0xBC, 0x46, 0xFA, 0xBE, 0x99, 0xF3, 0x27, 0x7B, 0xC8, 0x9F, 0x47, 0xBF, 0x3E, 0x3E,
0xFD, 0x79, 0xF4, 0x96, 0x57, 0xAB, 0xC7, 0x69, 0x23, 0x0C, 0xA2, 0x52, 0xA2, 0xF4, 0x7B, 0x04,
0x8B, 0x2A, 0x0A, 0x22, 0x48, 0xA6, 0x4B, 0x88, 0x44, 0xA4, 0xB5, 0x82, 0x65, 0x8A, 0x48, 0xC8,
0x27, 0x88, 0xB4, 0x6D, 0xD0, 0x6E, 0xC2, 0x1A, 0x28, 0x68, 0x28, 0x42, 0x41, 0x91, 0x32, 0x07,
0xC8, 0x2D, 0x72, 0x03, 0xCE, 0x92, 0x26, 0x27, 0xC8, 0x78, 0x3C, 0x9F, 0x9F, 0x9F, 0x9F, 0xF9,
0x3E, 0x81, 0xA3, 0x34, 0xC8, 0x08, 0xF6, 0x9B, 0xBF, 0x37, 0x6F, 0xDE, 0x37, 0xEB, 0x3F, 0xBF,
0x5E, 0x3C, 0x0F, 0x3E, 0x9A, 0x47, 0xB4, 0x47, 0x11, 0xFD, 0x33, 0x3A, 0xD2, 0x46, 0x40, 0x53,
0x17, 0xC7, 0x6F, 0xAB, 0xF5, 0x0D, 0x08, 0x45, 0x23, 0x7C, 0xB2, 0x46, 0x98, 0x49, 0x07, 0xB8,
0xF7, 0x47, 0xF0, 0xFE, 0x91, 0x53, 0xF7, 0x4E, 0x8B, 0x8F, 0x39, 0xD9, 0xE4, 0xE7, 0xA4, 0x95,
0x35, 0x4A, 0xCC, 0xA8, 0xED, 0xCD, 0x85, 0xAF, 0xF3, 0xE7, 0xDE, 0xCC, 0x0D, 0xF6, 0xBE, 0x17,
0x4C, 0x08, 0x6E, 0xE7, 0x4F, 0xDC, 0xE6, 0xA8, 0xCB, 0x26, 0x47, 0x67, 0x07, 0x7C, 0x41, 0xB5,
0x60, 0x9E, 0xE2, 0xF5, 0x0B, 0xF8, 0x07, 0x8A, 0x97, 0x80, 0x7E, 0xB5, 0x08, 0xE0, 0x6C, 0xB3,
0x27, 0x53, 0xF2, 0x44, 0x88, 0xEC, 0x2A, 0x62, 0x40, 0xB2, 0x5B, 0x8E, 0xFD, 0xA3, 0xC7, 0x6E,
0x9F, 0x99, 0xDA, 0xCE, 0xD3, 0x73, 0x6F, 0x3D, 0xD9, 0x14, 0x7B, 0x67, 0x4F, 0x04, 0xEC, 0xC7,
0xCB, 0x17, 0x59, 0x67, 0x4F, 0x7D, 0x93, 0x75, 0x66, 0xAF, 0x1C, 0xEC, 0x15, 0x8A, 0x63, 0x84,
0xC8, 0xB2, 0x9D, 0xBB, 0x80, 0xEC, 0xBD, 0x8C, 0x95, 0x90, 0x60, 0x3D, 0x96, 0xB4, 0xCD, 0x25,
0xF0, 0xEE, 0xAB, 0x46, 0xF4, 0x97, 0xFF, 0x5E, 0x77, 0x81, 0x9A, 0x58, 0x7D, 0x44, 0xFA, 0x7C,
0xAD, 0x67, 0x96, 0x23, 0x7D, 0x3D, 0x5D, 0x9D, 0x7A, 0x26, 0x4F, 0x3F, 0xA7, 0x31, 0x70, 0x24,
0xF8, 0xDB, 0x79, 0x6C, 0x03, 0x4B, 0xA9, 0xCE, 0x91, 0x49, 0xE7, 0x8F, 0xED, 0xFC, 0xCF, 0x0C,
0x4D, 0x54, 0xF6, 0x95, 0x3F, 0x1E, 0xD8, 0x6C, 0xE7, 0xE4, 0xF4, 0x7E, 0x89, 0xCD, 0xDA, 0x3F,
0x83, 0x9C, 0xA6, 0x09, 0x9F, 0x5E, 0x39, 0x10, 0x93, 0xA7, 0x21, 0x0C, 0x57, 0x44, 0x4E, 0x20,
0x58, 0x33, 0x8A, 0x19, 0xB4, 0xEF, 0x6B, 0xA5, 0x72, 0x07, 0x9A, 0x39, 0xEE, 0xBE, 0xDE, 0x0F,
0x67, 0xBE, 0x32, 0x0C, 0x23, 0x36, 0xFF, 0x67, 0xE6, 0x70, 0x1C, 0x54, 0xE2, 0xEF, 0xE1, 0xCA,
0xE6, 0xC3, 0x3C, 0x20, 0x06, 0x8D, 0x55, 0x1E, 0x0E, 0xF3, 0x5D, 0x7A, 0x07, 0x12, 0xF2, 0x3A,
0xD8, 0xDF, 0xE2, 0x58, 0x8B, 0x28, 0x16, 0xBD, 0xA8, 0x30, 0xCB, 0x3B, 0xF0, 0xC3, 0x1E, 0x41,
0x8C, 0x6B, 0x10, 0x20, 0x6B, 0x53, 0x1D, 0x46, 0x6E, 0xFC, 0x28, 0x8C, 0xC7, 0x90, 0x80, 0x03,
0x97, 0x3A, 0x28, 0xDE, 0xB9, 0x23, 0x93, 0xA5, 0x23, 0xD7, 0x2B, 0x50, 0xE8, 0x17, 0x90, 0x9F,
0x91, 0x3E, 0x80, 0x33, 0x3B, 0x9B, 0xB8, 0x1D, 0x0E, 0x59, 0x4E, 0x28, 0x07, 0xE7, 0xC9, 0x5C,
0x3D, 0x8F, 0xDB, 0xE1, 0xE0, 0x95, 0x24, 0xF3, 0x3D, 0xCB, 0x93, 0x89, 0xA7, 0x02, 0x76, 0xA1,
0x4B, 0x32, 0x76, 0x4F, 0x50, 0x81, 0x36, 0x67, 0x7D, 0x2A, 0xD6, 0x1B, 0x5E, 0x99, 0xC0, 0xE4,
0x40, 0xCA, 0xEC, 0xC1, 0xB5, 0x5C, 0x60, 0x1C, 0x5D, 0xC5, 0xD1, 0x28, 0xF0, 0xE9, 0x1A, 0x11,
0xCF, 0x68, 0x00, 0x10, 0xDE, 0x1D, 0x1D, 0x5C, 0xE0, 0x2E, 0x15, 0xB8, 0xE6, 0xD8, 0xD0, 0x6C,
0xDE, 0xF9, 0xF5, 0x45, 0x74, 0x47, 0x90, 0x30, 0x0A, 0x0C, 0x47, 0x8E, 0xB9, 0xD7, 0x83, 0xC9,
0xD8, 0x8B, 0x81, 0xCE, 0x01, 0x34, 0x32, 0x2A, 0x9B, 0xDA, 0xA5, 0x77, 0x3B, 0x84, 0xF0, 0x0A,
0x08, 0x0F, 0x8E, 0x19, 0x92, 0xFC, 0x77, 0x60, 0xC5, 0x5B, 0x28, 0xED, 0xA4, 0x69, 0x87, 0x3A,
0x82, 0xC7, 0x9A, 0x8E, 0xF5, 0x88, 0xBF, 0xAE, 0x45, 0xF5, 0x82, 0x21, 0xEB, 0x67, 0x72, 0x7F,
0xF3, 0xB3, 0xCA, 0xBA, 0x66, 0xF3, 0x78, 0x3E, 0x88, 0xF3, 0x06, 0xD2, 0x7A, 0xCE, 0xEA, 0x69,
0xEC, 0xA9, 0x22, 0xB3, 0xCF, 0x42, 0x7A, 0xA8, 0x00, 0x94, 0x25, 0x18, 0x56, 0x53, 0x30, 0xD1,
0x14, 0x40, 0xD1, 0x68, 0x0A, 0x10, 0x80, 0x79, 0x6E, 0xD9, 0x15, 0x4C, 0x09, 0x71, 0xD7, 0x30,
0x40, 0xC4, 0xAD, 0x38, 0xBA, 0x0D, 0x36, 0x85, 0x94, 0xCC, 0xB0, 0x69, 0xF9, 0x9A, 0x76, 0x9A,
0xD7, 0x8F, 0x35, 0xF1, 0xBF, 0x22, 0x91, 0x13, 0x34, 0xE2, 0x04, 0x9D, 0xA7, 0x7C, 0x83, 0x6B,
0x0D, 0x01, 0x92, 0xA4, 0x04, 0x15, 0xBE, 0x16, 0xDA, 0xCF, 0xEC, 0x25, 0x0A, 0x20, 0x0E, 0xD1,
0xA8, 0x50, 0xE9, 0x33, 0x50, 0x31, 0x4B, 0x8F, 0x96, 0xF0, 0xCD, 0xBA, 0xF4, 0xAD, 0x99, 0x96,
0x82, 0x8C, 0xE0, 0xBC, 0x42, 0xA5, 0x12, 0xA8, 0x90, 0x2A, 0xE4, 0x7D, 0xC2, 0xF0, 0x99, 0x12,
0xAD, 0x0E, 0xDF, 0xA2, 0x70, 0xE7, 0xC6, 0x57, 0x71, 0xF1, 0x3A, 0xCC, 0x0C, 0x80, 0xCF, 0x85,
0xE7, 0x97, 0x79, 0x71, 0xE1, 0x19, 0x68, 0x59, 0x60, 0x1C, 0x74, 0x49, 0x02, 0x27, 0x2D, 0xB5,
0xD3, 0x01, 0x6A, 0xC2, 0x3C, 0x33, 0xE1, 0xBD, 0x8D, 0x68, 0x3B, 0x74, 0x6F, 0x58, 0x03, 0x5B,
0xA0, 0x84, 0xB8, 0xBA, 0x4D, 0x0C, 0x78, 0xE3, 0x0A, 0x2B, 0xA1, 0xEE, 0x1B, 0xF9, 0x70, 0xCC,
0x0A, 0x6E, 0x8D, 0xF3, 0x46, 0x50, 0x70, 0xAC, 0x12, 0x55, 0xC1, 0xB5, 0x7A, 0xFE, 0x18, 0x31,
0x0A, 0x7B, 0xED, 0x82, 0x61, 0x95, 0xC1, 0x16, 0x99, 0x5D, 0x8A, 0x87, 0xDB, 0xC4, 0x62, 0xC1,
0xF4, 0x0A, 0xCC, 0x2A, 0x24, 0x03, 0x21, 0x49, 0x44, 0x5C, 0xB4, 0x42, 0xF1, 0xFE, 0x77, 0x52,
0x86, 0x10, 0x2C, 0xA8, 0x7E, 0x63, 0x72, 0x57, 0xC6, 0x51, 0x1C, 0x82, 0xBA, 0xDC, 0x03, 0xD5,
0xD0, 0x27, 0xD9, 0x2A, 0xDB, 0x61, 0xC5, 0x0A, 0x43, 0xC1, 0xF5, 0x2B, 0x48, 0xDF, 0x23, 0x8C,
0x95, 0xD1, 0x0E, 0x05, 0x5F, 0x46, 0xFC, 0x34, 0x83, 0xF8, 0xC2, 0x8C, 0x2F, 0x63, 0xDD, 0x33,
0xC2, 0x38, 0xE7, 0x9B, 0x4A, 0xB5, 0x96, 0x85, 0x66, 0x6D, 0xC9, 0x77, 0xC1, 0xA2, 0x91, 0x5B,
0x6C, 0xCB, 0x4B, 0x12, 0x4C, 0x4B, 0xD0, 0xE8, 0x32, 0x6C, 0xCA, 0xE8, 0x9E, 0x24, 0xD1, 0xC9,
0x1D, 0xA9, 0xC2, 0x1D, 0x89, 0xEA, 0x7B, 0xBF, 0x50, 0xA6, 0x3B, 0xA8, 0xAF, 0xA8, 0x53, 0xEF,
0x32, 0xD4, 0x17, 0x03, 0x40, 0xEB, 0x8B, 0x7E, 0xAB, 0x3B, 0xAD, 0xAF, 0x43, 0xB8, 0xF3, 0xC0,
0xC9, 0x97, 0x21, 0xAF, 0xBF, 0xA2, 0xBE, 0xEC, 0xC7, 0xA0, 0xD5, 0xDB, 0xA8, 0xD6, 0x77, 0xB2,
0x29, 0xC9, 0x0F, 0x64, 0x61, 0xAC, 0xFA, 0x1C, 0x2A, 0x8E, 0x97, 0x63, 0xC8, 0x6F, 0x58, 0x6A,
0x10, 0xB1, 0xB3, 0x5D, 0xDF, 0xAA, 0x30, 0x80, 0xBA, 0xF8, 0xBE, 0xF5, 0x45, 0x0D, 0xD9, 0x01,
0x17, 0xEE, 0x93, 0x92, 0x3B, 0x02, 0xF3, 0x5E, 0x68, 0x07, 0x9A, 0xEF, 0xF9, 0xEA, 0xB4, 0xAB,
0x8C, 0x78, 0x43, 0x5C, 0x7C, 0xBD, 0xAA, 0xEF, 0x0E, 0x49, 0xE2, 0x8E, 0x68, 0x5C, 0x17, 0x24,
0x6E, 0x51, 0xDF, 0x6D, 0x21, 0x37, 0xA0, 0x4F, 0x21, 0x37, 0xA8, 0xC6, 0x4A, 0x94, 0xDB, 0x2F,
0x1B, 0xF8, 0x92, 0xF5, 0x13, 0xCA, 0x8F, 0xDE, 0x64, 0xF4, 0xBC, 0x7C, 0xCB, 0x03, 0x98, 0x60,
0x25, 0xC3, 0x18, 0x1E, 0x10, 0x53, 0xF4, 0xC2, 0x14, 0x89, 0x13, 0x79, 0x1A, 0x48, 0x9F, 0x8C,
0x64, 0x12, 0x28, 0x07, 0xA2, 0xFE, 0xF7, 0x22, 0x12, 0x3D, 0xC4, 0x27, 0xCD, 0x82, 0x11, 0xA3,
0x31, 0xBE, 0x71, 0x0B, 0x34, 0x3E, 0x3C, 0x0B, 0x7E, 0x3C, 0x48, 0x8B, 0x10, 0x1F, 0x25, 0x5A,
0xCC, 0x10, 0xFE, 0x5D, 0x1C, 0xFF, 0x7B, 0xB3, 0x94, 0xDC, 0xFD, 0x5F, 0xFB, 0x31, 0x95, 0x98,
0x42, 0x88, 0x25, 0x62, 0x46, 0xA1, 0x8B, 0xA4, 0x5C, 0x31, 0x29, 0xA3, 0xED, 0xFF, 0xF6, 0x72,
0x25, 0xAF, 0x3F, 0x45, 0x51, 0xFC, 0x9A, 0x43, 0x8A, 0x94, 0x4C, 0xE5, 0x87, 0x42, 0x64, 0x9E,
0xE7, 0x79, 0x26, 0x22, 0xAC, 0x2C, 0x9E, 0x29, 0x4A, 0x86, 0x2F, 0xBE, 0xCF, 0xAC, 0x64, 0xA1,
0x64, 0x8A, 0x05, 0x52, 0x94, 0x58, 0xA0, 0xA4, 0x64, 0xCA, 0x7F, 0x80, 0x28, 0x0B, 0x0B, 0x2C,
0x14, 0x76, 0xB2, 0xA6, 0x0C, 0x9F, 0xF7, 0xB9, 0xC3, 0xE7, 0xDD, 0x77, 0xCD, 0x13, 0x7D, 0xF9,
0x0E, 0xF7, 0x9E, 0xF9, 0x9E, 0x73, 0xEE, 0xBD, 0xE7, 0xBC, 0xAD, 0xF7, 0x1A, 0xAF, 0xB9, 0xD7,
0xA4, 0x45, 0x8E, 0x1C, 0x20, 0xE4, 0x98, 0x3A, 0x46, 0x53, 0x52, 0x0D, 0xAA, 0x95, 0x50, 0x93,
0x24, 0xFA, 0x36, 0x0A, 0x77, 0x09, 0x08, 0x33, 0x10, 0x3A, 0xF8, 0xA4, 0xDE, 0x73, 0x14, 0x19,
0x5A, 0x0F, 0xCA, 0x77, 0x90, 0x0C, 0xC7, 0x42, 0x06, 0xDE, 0x8F, 0x9E, 0xE4, 0xD8, 0xD7, 0xCD,
0x0B, 0x5C, 0x23, 0x98, 0xAB, 0xF9, 0xF8, 0x3E, 0xB3, 0x84, 0xA7, 0x63, 0x4B, 0x90, 0x9A, 0x7B,
0xD8, 0x6D, 0x6D, 0x31, 0x15, 0x3C, 0x28, 0x62, 0x1B, 0x8A, 0xD3, 0x7A, 0x69, 0x67, 0x51, 0xF3,
0x98, 0x0E, 0x96, 0x30, 0xB1, 0x48, 0xBA, 0x65, 0x5E, 0x48, 0x7F, 0xE5, 0x4A, 0x99, 0xF3, 0x30,
0xE7, 0xDC, 0x65, 0xCA, 0x6B, 0x4A, 0x57, 0x17, 0x4B, 0x74, 0x2A, 0x05, 0x50, 0xA1, 0xB4, 0x3C,
0x5B, 0xFC, 0x95, 0xFD, 0x4E, 0x97, 0x96, 0xDE, 0x43, 0x0E, 0x45, 0x75, 0x2C, 0x15, 0x8A, 0x59,
0xDD, 0x5A, 0xFA, 0xDA, 0xAE, 0x76, 0xD9, 0x71, 0x90, 0x8A, 0x84, 0xA8, 0xF1, 0x47, 0xD8, 0x5A,
0xBA, 0x6D, 0xEC, 0xF7, 0x75, 0x21, 0x07, 0x83, 0x6B, 0x47, 0x7D, 0x71, 0x39, 0x31, 0x58, 0xE4,
0xDE, 0xAC, 0x40, 0xBF, 0x0F, 0x20, 0xFC, 0x85, 0x16, 0xB3, 0x84, 0xEE, 0x00, 0x34, 0xE1, 0xEA,
0xBE, 0xA1, 0x10, 0x5C, 0xB8, 0x41, 0xE8, 0x61, 0x13, 0x6E, 0x88, 0xAC, 0x13, 0x35, 0xCD, 0x43,
0xAA, 0xCA, 0x65, 0xE6, 0xB4, 0xE8, 0x32, 0x73, 0x46, 0xE3, 0x02, 0xD3, 0x14, 0xF9, 0x7E, 0xD1,
0xC0, 0xCF, 0xE0, 0x29, 0xC6, 0x5F, 0xF3, 0xF8, 0xBB, 0x12, 0x3F, 0x64, 0x80, 0x4A, 0x35, 0xE1,
0x07, 0x5F, 0x56, 0x65, 0xFE, 0x32, 0x32, 0xEC, 0x9A, 0x4B, 0x2B, 0x8D, 0xE9, 0x91, 0x76, 0xCD,
0xDE, 0xC0, 0x73, 0xA9, 0x82, 0x7E, 0x46, 0xC6, 0x0D, 0x31, 0x28, 0x16, 0x44, 0xA2, 0xA0, 0x3D,
0x90, 0x14, 0xAA, 0xA4, 0x8B, 0x23, 0x67, 0x49, 0x49, 0x1C, 0x43, 0x72, 0xEB, 0x02, 0xB6, 0x69,
0x7F, 0xA5, 0xE3, 0xDC, 0x58, 0x27, 0xE9, 0xD2, 0x3F, 0x18, 0x45, 0x12, 0xF0, 0xC6, 0xF5, 0x99,
0xEF, 0x8C, 0xF5, 0x33, 0x4D, 0x31, 0x07, 0x0C, 0x40, 0x03, 0x76, 0x54, 0x0E, 0xC8, 0xB6, 0x5A,
0x58, 0x7E, 0xAB, 0x04, 0xCB, 0x7E, 0xCE, 0x83, 0x1F, 0x23, 0x2C, 0x18, 0xB4, 0x87, 0x02, 0x2C,
0x4D, 0x57, 0xF2, 0x88, 0x71, 0x30, 0x1D, 0xB3, 0x65, 0x32, 0xD7, 0xE2, 0x11, 0xAD, 0xA4, 0x45,
0x90, 0xF7, 0x85, 0x44, 0x66, 0x68, 0x88, 0x38, 0xD4, 0xA4, 0x5D, 0x58, 0xF2, 0xA5, 0xD0, 0x95,
0xA2, 0x1D, 0xD6, 0xA7, 0xFC, 0xBF, 0x08, 0xA7, 0x53, 0x92, 0xB7, 0x17, 0x7B, 0xD9, 0x51, 0x81,
0x8D, 0x5C, 0x34, 0x58, 0xDB, 0xE1, 0x85, 0x2D, 0x87, 0x37, 0xA8, 0x98, 0x53, 0x57, 0x39, 0x65,
0x39, 0xBB, 0x59, 0x93, 0xC6, 0x14, 0x93, 0xEF, 0x28, 0x2C, 0x61, 0x8C, 0x17, 0x51, 0x6A, 0x0D,
0x64, 0xCC, 0x63, 0xDC, 0x07, 0x8C, 0x2B, 0xFD, 0x68, 0x3A, 0xC2, 0xDC, 0x96, 0x9F, 0x83, 0x4A,
0xF9, 0x6E, 0x04, 0x85, 0x20, 0xF4, 0xA1, 0x12, 0xBA, 0xC4, 0xC2, 0x22, 0x50, 0x57, 0xEA, 0x5E,
0x07, 0x0F, 0x95, 0xDD, 0xB8, 0xAC, 0xB8, 0xE2, 0x29, 0xC3, 0x7E, 0xF5, 0xA0, 0x4B, 0x9C, 0x28,
0x3D, 0x79, 0x4B, 0x9B, 0x2E, 0x31, 0xB1, 0x7A, 0xDE, 0xBC, 0xA0, 0xED, 0x09, 0xBD, 0x25, 0xC7,
0x62, 0x04, 0x1B, 0x3D, 0x38, 0xEE, 0x4D, 0xF3, 0xB0, 0x5C, 0xE5, 0x2F, 0x6B, 0x7E, 0xA5, 0x98,
0x2C, 0x6B, 0x0D, 0xCA, 0x39, 0xB6, 0x2D, 0x1D, 0x52, 0x0F, 0xF0, 0x07, 0x59, 0x81, 0xDE, 0xC5,
0x58, 0xF2, 0xD9, 0x84, 0x28, 0xE1, 0x7D, 0xDC, 0x9C, 0x87, 0x51, 0x91, 0xB3, 0x5C, 0x83, 0xDA,
0xE1, 0x70, 0xF4, 0xC4, 0x83, 0xAA, 0x73, 0x4D, 0xED, 0x3A, 0x45, 0x42, 0xE8, 0xB4, 0x03, 0x98,
0xD2, 0x8C, 0x72, 0xB5, 0x79, 0xEE, 0xEA, 0x4B, 0x11, 0x1E, 0xDF, 0xDB, 0xC8, 0x4E, 0x0F, 0x4E,
0xF3, 0xA4, 0x5B, 0x5C, 0xE3, 0xEE, 0x17, 0xC9, 0x93, 0xBC, 0x39, 0x5D, 0xD3, 0x90, 0x7D, 0xD1,
0x79, 0xDA, 0x5F, 0x91, 0xE9, 0xB3, 0xE6, 0x8C, 0x0B, 0x7F, 0x55, 0xA6, 0x74, 0x63, 0xFF, 0x47,
0xA0, 0x32, 0xEF, 0xE9, 0xDF, 0x12, 0xA8, 0xDB, 0x44, 0x9C, 0xAC, 0x08, 0x74, 0x48, 0xDD, 0x3A,
0xB7, 0x9F, 0x95, 0x29, 0x48, 0x22, 0x07, 0x7F, 0x2E, 0x53, 0x45, 0x74, 0xBB, 0x6F, 0x11, 0x1E,
0x45, 0xF4, 0xFA, 0x37, 0x22, 0x3A, 0xC3, 0x93, 0x82, 0x7A, 0x2A, 0x5A, 0x12, 0x26, 0xD1, 0x4E,
0x0E, 0xA2, 0x3D, 0xDF, 0x54, 0xF1, 0x7D, 0xEC, 0x3F, 0x97, 0xAE, 0x22, 0x3A, 0xCF, 0x4D, 0x7E,
0xEC, 0x0C, 0x82, 0xC9, 0x2A, 0xAA, 0x83, 0x22, 0x1A, 0x8A, 0xE3, 0xC0, 0x89, 0x44, 0x51, 0x15,
0x78, 0x10, 0xC6, 0xBE, 0x17, 0x51, 0xE3, 0x88, 0x2E, 0x97, 0x1A, 0x1F, 0xA1, 0xC9, 0xAD, 0x12,
0x7F, 0xEE, 0x55, 0x31, 0xD4, 0xBB, 0xCC, 0x38, 0xCF, 0xD9, 0xA2, 0x00, 0x0B, 0x7E, 0x15, 0x5C,
0x49, 0xD1, 0x8F, 0x73, 0x8C, 0x7D, 0x39, 0xB2, 0xC9, 0xEF, 0xA5, 0x92, 0x8A, 0x52, 0x5A, 0xCC,
0xE9, 0xD2, 0xA1, 0xE1, 0x1D, 0x8A, 0x74, 0x1C, 0x1B, 0xDE, 0x5C, 0x19, 0x1E, 0xB4, 0x23, 0xC3,
0x1B, 0x1E, 0x52, 0x49, 0xC9, 0x7E, 0xE6, 0x8F, 0x52, 0xC9, 0x1C, 0x0B, 0x3A, 0xDA, 0xF5, 0xD2,
0xEA, 0xD2, 0xE5, 0xE0, 0xD2, 0x49, 0xED, 0x72, 0x2F, 0x34, 0x8D, 0x4B, 0x0A, 0xB4, 0xAF, 0x05,
0x89, 0x0B, 0x94, 0x52, 0x6A, 0x5F, 0x4B, 0x51, 0x13, 0xED, 0xFF, 0x4A, 0x26, 0x25, 0xE0, 0xC8,
0xF4, 0xC8, 0x52, 0x6A, 0x7A, 0x3F, 0x50, 0xF4, 0x61, 0x99, 0x9E, 0x8B, 0x2C, 0xDB, 0x93, 0x64,
0xB2, 0x5F, 0x92, 0x4C, 0xD2, 0x9B, 0x8A, 0x0E, 0x60, 0x91, 0xF9, 0x7B, 0xAF, 0x72, 0x52, 0xF8,
0xB1, 0x6C, 0x7F, 0x2E, 0x99, 0x9C, 0x95, 0x26, 0x93, 0xA9, 0xCD, 0xA7, 0x09, 0x25, 0x44, 0xF8,
0x0B, 0x36, 0xFF, 0x93, 0xC9, 0x24, 0xC8, 0xC1, 0xAB, 0x7A, 0x52, 0x3F, 0xE8, 0x5B, 0x89, 0x64,
0xA4, 0x8F, 0x24, 0x8D, 0xC4, 0xAF, 0xED, 0x94, 0xEA, 0x57, 0xD2, 0xBF, 0xC5, 0x61, 0x8C, 0x51,
0x3E, 0x06, 0x42, 0xA3, 0x14, 0x72, 0xDB, 0x9F, 0xB6, 0x35, 0x6F, 0x86, 0x78, 0xC3, 0x41, 0x43,
0x8F, 0x6A, 0x1E, 0x5A, 0x10, 0x58, 0x48, 0xD4, 0xE4, 0x39, 0xCC, 0x60, 0x1B, 0x52, 0xAC, 0x1D,
0xD4, 0x81, 0x1F, 0xFF, 0xDD, 0x7C, 0x94, 0xB3, 0x6B, 0x2E, 0x9D, 0x63, 0x37, 0xE3, 0x1A, 0x61,
0xAA, 0xE4, 0xA5, 0x07, 0xFD, 0xF8, 0xA0, 0xF4, 0x5C, 0x59, 0xA9, 0x90, 0x49, 0x0A, 0x15, 0xF0,
0xB4, 0xD3, 0x7D, 0x4E, 0xCD, 0x62, 0x24, 0x05, 0xBD, 0xA6, 0xB0, 0x27, 0x29, 0xB0, 0x5A, 0xC9,
0xD0, 0xA3, 0x6C, 0x55, 0xE4, 0x45, 0x16, 0xE5, 0xC0, 0x6C, 0xF1, 0xC2, 0x67, 0xD2, 0x15, 0xBA,
0x7D, 0x38, 0xFB, 0x9B, 0x49, 0xAA, 0x08, 0xA0, 0x1C, 0xEA, 0x90, 0xA4, 0x66, 0x45, 0xC9, 0x6A,
0x15, 0xCB, 0xE1, 0x42, 0x16, 0x62, 0xAC, 0xAA, 0xA1, 0x5A, 0x01, 0x77, 0xB6, 0x4B, 0x59, 0xF7,
0x25, 0x29, 0xAB, 0x9B, 0x95, 0x6E, 0xEE, 0xD9, 0x8B, 0xE4, 0xF1, 0xE0, 0x73, 0xE3, 0xC3, 0x4C,
0x60, 0x78, 0x02, 0x16, 0x3B, 0x0A, 0xC0, 0x9F, 0x8F, 0xDF, 0x4F, 0x67, 0x13, 0x9D, 0x04, 0x7A,
0x28, 0x6E, 0x52, 0xB8, 0xD3, 0xB0, 0xA8, 0xAD, 0x2A, 0xD8, 0xD7, 0xC8, 0x8A, 0xAA, 0x7D, 0x5B,
0xE5, 0x28, 0x06, 0xBA, 0xC4, 0xBF, 0x41, 0x3B, 0x4E, 0xA6, 0x55, 0xC0, 0x5B, 0x40, 0xE4, 0xBF,
0xA0, 0xC9, 0x1E, 0x16, 0x99, 0xB7, 0x50, 0xA7, 0x36, 0x17, 0xBC, 0xAE, 0xAF, 0x8E, 0x42, 0xF7,
0xE0, 0xC7, 0xBA, 0x2A, 0xE6, 0x63, 0xEB, 0x88, 0xC1, 0x72, 0xA5, 0x4C, 0x76, 0x93, 0x3A, 0xA1,
0x6C, 0xAA, 0xC8, 0x97, 0xEC, 0x24, 0x6D, 0x5F, 0xBE, 0x8A, 0xA1, 0x17, 0x46, 0x7E, 0xDC, 0x2B,
0x59, 0x0E, 0x20, 0x17, 0x8A, 0xF6, 0xF1, 0xC5, 0xC4, 0xF8, 0x6F, 0xA0, 0x1C, 0xA2, 0x64, 0x27,
0xDD, 0x36, 0xA6, 0x68, 0x5D, 0xD6, 0x29, 0xF3, 0xA8, 0xCB, 0x34, 0x66, 0x6A, 0x74, 0xCE, 0x52,
0x1A, 0xCE, 0x70, 0x39, 0xB5, 0x63, 0xE9, 0x98, 0x87, 0xED, 0x3A, 0x66, 0x31, 0x47, 0xB0, 0x65,
0xFB, 0x55, 0xC3, 0xAF, 0xA7, 0x46, 0x4F, 0x86, 0xF0, 0x6E, 0x28, 0x98, 0x8C, 0x31, 0x26, 0x86,
0x9F, 0x2D, 0x4E, 0x8D, 0xBE, 0x2C, 0x10, 0x50, 0x21, 0xDE, 0x30, 0x82, 0x27, 0x71, 0x76, 0x6A,
0xFE, 0x2D, 0xA5, 0xC5, 0xEC, 0xE5, 0x29, 0x7B, 0x89, 0xE5, 0xC4, 0x4B, 0x3B, 0x39, 0xB9, 0xCD,
0x13, 0xE7, 0xFC, 0x3D, 0xCD, 0xD5, 0x1C, 0x93, 0xD9, 0x84, 0xA0, 0xB6, 0x03, 0xDF, 0xC5, 0xCD,
0x7C, 0x08, 0xFE, 0xF1, 0x4C, 0x36, 0x92, 0x02, 0xFD, 0xB1, 0x31, 0x72, 0x5D, 0xFF, 0xD8, 0x12,
0xB7, 0xA2, 0x5E, 0xF0, 0x3E, 0xEA, 0x05, 0x9F, 0xA3, 0x5C, 0xF0, 0x13, 0xCA, 0x04, 0xDF, 0xA1,
0x4C, 0xF0, 0x21, 0xCA, 0x04, 0xEF, 0xA1, 0x4C, 0x70, 0x18, 0xCA, 0x04, 0x7B, 0xA2, 0x4C, 0xB0,
0x11, 0xCA, 0x03, 0xDB, 0xA2, 0x3C, 0x70, 0x08, 0xCA, 0x03, 0xA7, 0xA2, 0x3C, 0xF0, 0x44, 0xFE,
0xBD, 0x56, 0xCC, 0x4D, 0xDF, 0xEB, 0xC5, 0xDC, 0x74, 0xAF, 0xF1, 0x46, 0x88, 0xF0, 0xD5, 0xBD,
0x66, 0x8D, 0xB7, 0xA3, 0x17, 0x13, 0xE1, 0xE3, 0xFA, 0x67, 0x3E, 0x26, 0x42, 0xBD, 0x98, 0x78,
0xDD, 0xC4, 0xEB, 0x16, 0x5E, 0xB7, 0x0D, 0x7A, 0x31, 0xF1, 0xBA, 0x6B, 0x4A, 0xBD, 0x98, 0xC6,
0x3D, 0x26, 0xC2, 0xE0, 0x7E, 0x63, 0xDE, 0xBD, 0x16, 0xCD, 0x37, 0x15, 0xCD, 0x7C, 0x7D, 0x98,
0x02, 0x79, 0x33, 0x7B, 0xD0, 0xDC, 0x56, 0x7C, 0xC1, 0xC3, 0x29, 0xBF, 0x43, 0x44, 0xC8, 0xAD,
0xD7, 0x41, 0x0E, 0xE7, 0x8A, 0x78, 0xDC, 0xD6, 0xE2, 0x20, 0x12, 0xA5, 0xA2, 0x87, 0xF3, 0xA1,
0xEB, 0x4C, 0xCF, 0xED, 0x66, 0x8D, 0xB1, 0xFD, 0x72, 0x76, 0x1A, 0xD9, 0x19, 0x17, 0x00, 0x20,
0x63, 0x1C, 0xA0, 0xA2, 0x67, 0x1A, 0xB0, 0xAE, 0xB4, 0x01, 0x3E, 0xCE, 0x7E, 0xCE, 0xD9, 0x93,
0x0A, 0x5C, 0x90, 0x35, 0x60, 0xF2, 0x9B, 0xCB, 0x80, 0x02, 0x12, 0x41, 0x03, 0x66, 0xBA, 0x6C,
0x11, 0x59, 0x20, 0xE6, 0x3F, 0xE5, 0xFC, 0x4B, 0x6D, 0x54, 0xAB, 0x76, 0x90, 0x30, 0x4F, 0xEB,
0xE4, 0x95, 0x14, 0x18, 0x52, 0x3E, 0x8D, 0x5E, 0xFF, 0xB2, 0xCA, 0x99, 0xCC, 0x39, 0x58, 0xC3,
0x72, 0x6C, 0xC9, 0x76, 0xE1, 0xB2, 0xF9, 0x97, 0x78, 0xB6, 0x9D, 0xD5, 0x29, 0xCF, 0x2E, 0x75,
0x8A, 0x79, 0x9E, 0xF7, 0x0D, 0x9E, 0x4D, 0x89, 0xE7, 0x47, 0xCC, 0xA5, 0xC9, 0xAD, 0xC3, 0x0B,
0x5A, 0x41, 0x97, 0x78, 0x5E, 0xE2, 0x78, 0x7E, 0x82, 0x91, 0xD3, 0x30, 0x93, 0x19, 0x50, 0x2B,
0xF6, 0xA0, 0x63, 0x93, 0x2C, 0xCE, 0x57, 0xB6, 0xA6, 0x7C, 0x88, 0xFD, 0x2C, 0xB0, 0x5F, 0xCC,
0x46, 0x35, 0x76, 0x57, 0x8A, 0x18, 0x21, 0xBE, 0xFC, 0xBC, 0x1C, 0x8F, 0x4B, 0xC0, 0x6C, 0x2B,
0x57, 0x4A, 0xE8, 0x34, 0xA8, 0xF3, 0xB4, 0xBF, 0xBF, 0xD7, 0xA2, 0x99, 0x36, 0x70, 0x60, 0x41,
0x00, 0xC0, 0x26, 0x26, 0x1F, 0xF9, 0xAE, 0x21, 0x48, 0x0D, 0xDD, 0x98, 0xAE, 0x89, 0xB4, 0x71,
0x54, 0x02, 0x02, 0x16, 0x9B, 0xEA, 0x17, 0x43, 0x09, 0x77, 0x60, 0x83, 0xD2, 0x03, 0xE5, 0x99,
0xE8, 0xA1, 0x9E, 0xDA, 0x1E, 0xF5, 0x20, 0xFE, 0xA1, 0x3F, 0xD9, 0x9E, 0xD0, 0x9D, 0xA6, 0x24,
0x80, 0x94, 0x52, 0x90, 0xED, 0x5C, 0x2D, 0x6C, 0x4F, 0xB3, 0xCB, 0xB2, 0xC9, 0x9E, 0x51, 0x1B,
0xA7, 0x30, 0xF3, 0x4E, 0x36, 0x49, 0xB6, 0x07, 0xCD, 0x4A, 0x8F, 0xD7, 0x28, 0xBB, 0x67, 0x9C,
0xFB, 0x18, 0x9A, 0x31, 0x78, 0xEF, 0xF1, 0xBD, 0x48, 0x04, 0x67, 0x4F, 0xB1, 0x4F, 0x7C, 0x57,
0x70, 0xA4, 0x43, 0x57, 0x34, 0x4C, 0xF6, 0xF1, 0x2E, 0x70, 0x22, 0xEB, 0xBD, 0x06, 0xEB, 0x3D,
0xB1, 0xA3, 0xA0, 0x6E, 0x38, 0xAF, 0x7B, 0x62, 0xA9, 0xF1, 0x1C, 0x9D, 0xFD, 0xE7, 0x0C, 0x4C,
0x80, 0xD4, 0x95, 0x96, 0x6B, 0xD5, 0x60, 0xC4, 0x33, 0xB7, 0x47, 0x3A, 0x64, 0xA3, 0x7C, 0x99,
0x21, 0x05, 0x5B, 0x64, 0xDE, 0xB1, 0x78, 0x67, 0xC1, 0xD1, 0x68, 0xDE, 0x75, 0xC8, 0x26, 0x29,
0x0B, 0x42, 0x20, 0x5F, 0xCE, 0x32, 0x0F, 0x86, 0x03, 0x08, 0xC2, 0x05, 0x46, 0x99, 0x85, 0x30,
0xC2, 0x24, 0x90, 0x0E, 0x68, 0xAD, 0xA0, 0xBB, 0x82, 0x3D, 0xEE, 0xE7, 0x10, 0xCD, 0x3F, 0x32,
0xE0, 0x0D, 0x2D, 0xF4, 0x58, 0x8B, 0x2C, 0x62, 0x47, 0xC0, 0xB7, 0x25, 0x78, 0x89, 0x12, 0xCE,
0x97, 0xCD, 0xEF, 0x35, 0x5D, 0x8C, 0x06, 0x75, 0x88, 0x1E, 0xCC, 0xFA, 0x13, 0x46, 0x09, 0x96,
0x62, 0x01, 0x58, 0x97, 0x12, 0xD1, 0x8A, 0x99, 0xD8, 0x2D, 0x71, 0xE2, 0xC5, 0x8E, 0xAA, 0xF1,
0x78, 0xE7, 0x59, 0xF1, 0xD4, 0x86, 0x4E, 0x08, 0xBF, 0x56, 0xBC, 0xFE, 0x5E, 0x9E, 0xC2, 0xE4,
0xF2, 0x74, 0x42, 0x5E, 0x42, 0x68, 0x64, 0xB3, 0xEE, 0x85, 0x3D, 0xB4, 0x16, 0x6F, 0x47, 0x96,
0xEF, 0xBD, 0xD7, 0xB4, 0x57, 0x41, 0xD6, 0x28, 0x4C, 0x68, 0xE2, 0x40, 0x1D, 0x44, 0x18, 0xF7,
0x77, 0x65, 0xC0, 0x45, 0xAD, 0xBB, 0xE8, 0x03, 0x5B, 0xF2, 0xA5, 0x8F, 0x8D, 0x42, 0x95, 0x5E,
0x8F, 0x9D, 0x20, 0x10, 0xE0, 0xE3, 0x47, 0x2C, 0xA9, 0x20, 0x7D, 0x53, 0x54, 0x91, 0x1E, 0x57,
0xA2, 0xEF, 0xDB, 0x1E, 0x6D, 0x53, 0x77, 0x86, 0x7C, 0xA9, 0xE8, 0x12, 0xEC, 0xFD, 0xE3, 0x6A,
0xE9, 0xE4, 0x16, 0x5E, 0x15, 0xD3, 0x4A, 0x9D, 0xD3, 0x7B, 0xF4, 0xCB, 0xDC, 0xAC, 0xB8, 0xB3,
0x2A, 0x32, 0xDE, 0xC0, 0x03, 0x83, 0xC6, 0x16, 0x56, 0xD6, 0xE0, 0x4C, 0xB2, 0x51, 0x61, 0x06,
0x4C, 0x4A, 0x2F, 0x66, 0x53, 0x43, 0x15, 0x28, 0xDD, 0xB6, 0x7F, 0xB4, 0x06, 0x1F, 0x77, 0x02,
0xC7, 0xD9, 0x94, 0x07, 0xED, 0xBF, 0x5D, 0x1B, 0x74, 0xF0, 0x6B, 0x35, 0x9B, 0xFB, 0xB6, 0xE9,
0xDC, 0x80, 0xB0, 0x9B, 0xF8, 0x3B, 0x7E, 0xB8, 0x02, 0x7F, 0x6A, 0xD0, 0x38, 0xB7, 0x8F, 0xEC,
0x08, 0xE7, 0x05, 0xC4, 0xDB, 0x28, 0x5C, 0xE5, 0xBD, 0x68, 0x1E, 0x84, 0x8A, 0x8B, 0x1A, 0x4F,
0x97, 0x11, 0x5D, 0x30, 0x78, 0x77, 0x8A, 0x69, 0xCE, 0x65, 0x33, 0x7F, 0x5C, 0x3D, 0xA4, 0x6B,
0xE9, 0x9F, 0xAA, 0x1E, 0x3A, 0x51, 0x2B, 0x38, 0xA9, 0xBB, 0x13, 0x1E, 0x09, 0x3C, 0xDD, 0xF7,
0x91, 0x74, 0xAF, 0x04, 0xB2, 0x48, 0x9F, 0xA1, 0x1B, 0xEF, 0x46, 0xBA, 0xA5, 0xB5, 0x87, 0xF6,
0x1C, 0x99, 0x3B, 0xA5, 0x90, 0x54, 0xCC, 0x0A, 0x73, 0xF9, 0x2F, 0x44, 0x13, 0xC6, 0x1F, 0xDE,
0xB7, 0x83, 0x64, 0xFC, 0x72, 0xD1, 0x8E, 0x6A, 0x33, 0xA6, 0xFE, 0x4C, 0xD1, 0x8E, 0xF8, 0x0E,
0xC7, 0x52, 0xD4, 0x9C, 0xCB, 0xC4, 0xE7, 0x8A, 0xC9, 0x32, 0xA1, 0xB4, 0xB7, 0x50, 0x97, 0x82,
0x51, 0x60, 0xD0, 0x55, 0x43, 0x30, 0x89, 0x94, 0xE6, 0xD2, 0xAD, 0x32, 0x98, 0xA4, 0xB0, 0x3C,
0x4D, 0x80, 0xE8, 0x61, 0x9C, 0x00, 0xD3, 0xB4, 0x22, 0xB2, 0x9E, 0x96, 0xF3, 0xFC, 0x52, 0xB9,
0xD6, 0xB8, 0x5F, 0x2C, 0xE7, 0x39, 0xB7, 0xC5, 0x9A, 0xB1, 0x4E, 0x9F, 0xFE, 0xA6, 0x09, 0x90,
0xBB, 0xED, 0x51, 0x53, 0xC7, 0x6F, 0x56, 0x20, 0xF0, 0x8A, 0x7B, 0x4D, 0x3D, 0xDC, 0x18, 0xA9,
0x0A, 0xC1, 0x6E, 0xD2, 0x92, 0x8A, 0xB4, 0x25, 0xE5, 0x92, 0x0B, 0xB1, 0x28, 0x2A, 0xB6, 0x68,
0xB5, 0x46, 0x9B, 0x86, 0x1D, 0x15, 0x1E, 0xC9, 0xC5, 0xE2, 0xEA, 0xB5, 0x60, 0x2D, 0x70, 0xAA,
0x1B, 0x2A, 0x19, 0xEF, 0xAF, 0x96, 0x1D, 0x34, 0x7C, 0xBF, 0xEC, 0x80, 0xCB, 0x57, 0x86, 0x7B,
0x39, 0x31, 0xDC, 0xB6, 0x91, 0xE1, 0x42, 0x5C, 0xDE, 0xE0, 0xA8, 0x20, 0xAA, 0x85, 0x30, 0xA8,
0x12, 0xEF, 0x2A, 0xE9, 0x34, 0x8C, 0x7D, 0x52, 0x93, 0x63, 0x63, 0x7F, 0x6B, 0x6E, 0x19, 0x29,
0xD0, 0x5F, 0xAA, 0xC3, 0x55, 0x61, 0x95, 0x1A, 0x61, 0xD4, 0x86, 0x06, 0x13, 0xA2, 0x8B, 0x91,
0x99, 0xD3, 0x57, 0xD2, 0xC2, 0xA2, 0xE3, 0x7D, 0x86, 0x33, 0xAE, 0x0D, 0xE8, 0xF9, 0xA8, 0x7C,
0xA5, 0xAB, 0xAE, 0x95, 0xAF, 0xDC, 0x14, 0x9C, 0x25, 0x25, 0x69, 0x4A, 0x05, 0xDA, 0x0D, 0x91,
0xB3, 0xFC, 0x9B, 0xC5, 0xAE, 0xA9, 0xB3, 0x4C, 0xAD, 0x28, 0x56, 0x72, 0xBA, 0x52, 0x54, 0xE3,
0xC6, 0x08, 0x20, 0x5F, 0x22, 0x67, 0x39, 0x2F, 0x71, 0x96, 0x52, 0xA5, 0xFC, 0x46, 0xEA, 0x2C,
0xA5, 0x2D, 0xD9, 0xDB, 0xCF, 0x16, 0x11, 0xCB, 0xDE, 0x54, 0xB7, 0x14, 0xF3, 0x9D, 0x06, 0x64,
0x5D, 0x20, 0xC7, 0x4C, 0x92, 0xDC, 0xD4, 0x15, 0xA4, 0xCE, 0x72, 0xD2, 0xD7, 0x9D, 0x65, 0x2A,
0x2C, 0x40, 0x4C, 0xDD, 0x49, 0xBA, 0xD6, 0x7E, 0x5C, 0x5A, 0x27, 0xDE, 0x7F, 0x5C, 0x5E, 0xA7,
0xB3, 0x3D, 0x49, 0xE1, 0x5C, 0xE4, 0x4A, 0xFE, 0xD8, 0x08, 0x6A, 0x89, 0x8C, 0x14, 0x0C, 0x52,
0xF6, 0x7E, 0xBA, 0xB6, 0x93, 0xDE, 0xD2, 0x07, 0x84, 0xD1, 0x5F, 0xBB, 0x5F, 0x4F, 0x02, 0xC2,
0x92, 0x5A, 0xEC, 0x2D, 0xEB, 0x96, 0xC5, 0x88, 0x43, 0xEE, 0x97, 0xBE, 0xC9, 0x61, 0x5C, 0x1D,
0xA1, 0xD3, 0x9C, 0xC8, 0xD0, 0xED, 0xE5, 0xFB, 0x7B, 0xF4, 0x86, 0x62, 0x0B, 0x32, 0x6F, 0xBB,
0xCD, 0x96, 0xB3, 0xC1, 0x8C, 0x51, 0x3F, 0xDD, 0xCF, 0xA1, 0xFE, 0x13, 0xFA, 0x30, 0xF9, 0x97,
0x1A, 0x36, 0xBE, 0xEE, 0x3C, 0x02, 0xF9, 0xB2, 0xF7, 0xAA, 0xED, 0x38, 0xC7, 0xB0, 0x90, 0x89,
0x0F, 0x99, 0xA4, 0x2B, 0xE9, 0x5E, 0x7C, 0x6E, 0xFC, 0x3E, 0x14, 0x76, 0x13, 0xBC, 0xDA, 0x30,
0xBE, 0xF9, 0x64, 0x10, 0x96, 0x0F, 0xCE, 0x2B, 0x2E, 0x64, 0x37, 0xDB, 0x24, 0x5F, 0xE5, 0xE6,
0xA2, 0xDC, 0x27, 0x91, 0x35, 0xBF, 0xF2, 0xD2, 0xC6, 0x1F, 0xD5, 0x86, 0xEF, 0x52, 0x7F, 0xEA,
0x9D, 0x7D, 0xEE, 0x48, 0xC5, 0xF6, 0x27, 0x84, 0xAD, 0x9D, 0xEA, 0x2B, 0x73, 0x05, 0x0E, 0xC7,
0xBC, 0x72, 0xD4, 0x35, 0x21, 0x47, 0xA5, 0xB0, 0x69, 0x5E, 0x43, 0xEB, 0xB4, 0x1A, 0x5F, 0x29,
0xBF, 0x03, 0x12, 0x42, 0xFC, 0x04, 0xEC, 0xFA, 0x57, 0xE1, 0x42, 0x89, 0xF4, 0x2E, 0x31, 0x5C,
0x40, 0xF3, 0x41, 0xA8, 0x9D, 0x2B, 0x39, 0x59, 0x02, 0xE7, 0x6B, 0xCF, 0x5B, 0x69, 0x2E, 0xD8,
0x23, 0xF3, 0x14, 0xF8, 0x60, 0xEE, 0x77, 0x28, 0xE3, 0xFD, 0xF5, 0x87, 0x05, 0x1F, 0x5A, 0xE4,
0x4C, 0xB9, 0x45, 0x2E, 0x5B, 0xC4, 0xCD, 0x10, 0x57, 0x21, 0xC6, 0xA9, 0x2D, 0x6E, 0x71, 0xB1,
0x6B, 0xE6, 0xF7, 0x10, 0x37, 0x4F, 0x6A, 0xA9, 0xA9, 0x09, 0x05, 0x8A, 0x52, 0x0D, 0xB9, 0x71,
0x0F, 0x1C, 0xFC, 0xC9, 0xF6, 0xB8, 0xB4, 0x3B, 0xCC, 0x3D, 0xAC, 0x4E, 0x3D, 0xD2, 0x5B, 0xFD,
0x73, 0x51, 0x20, 0xA7, 0xC1, 0x05, 0x36, 0xC0, 0x08, 0x07, 0x78, 0x9C, 0xD3, 0x2E, 0x75, 0x75,
0x78, 0x6F, 0xA1, 0xDC, 0xA9, 0x43, 0x87, 0x7B, 0xA1, 0x42, 0xE8, 0x0F, 0x73, 0xC3, 0xD1, 0xFF,
0xE4, 0x2A, 0x8C, 0x9A, 0x44, 0x80, 0xB9, 0x9E, 0x79, 0x52, 0x26, 0x68, 0x2F, 0x00, 0xED, 0x05,
0x44, 0xDB, 0x01, 0x01, 0x59, 0xD0, 0x1A, 0x1C, 0xB4, 0x63, 0x36, 0xE0, 0x07, 0x8A, 0x04, 0x49,
0x2D, 0x80, 0xC0, 0x28, 0xBA, 0xC0, 0x53, 0xAF, 0xC2, 0x5E, 0x87, 0x78, 0x60, 0x98, 0xF6, 0x1D,
0x40, 0xFC, 0x57, 0x20, 0x7A, 0xD9, 0xA3, 0xF5, 0x5E, 0x3C, 0xEA, 0xF6, 0x10, 0xB8, 0x5E, 0x27,
0x55, 0xA1, 0x6C, 0x11, 0x73, 0x98, 0x2D, 0xCD, 0x8A, 0xB9, 0x1A, 0x98, 0x83, 0xC0, 0x0B, 0xFE,
0x20, 0xEC, 0x08, 0x5E, 0x43, 0x0A, 0x4F, 0xF9, 0x8C, 0xD8, 0x8B, 0x60, 0x8D, 0x07, 0x6D, 0x39,
0x76, 0xDF, 0x81, 0xB6, 0x5A, 0x44, 0x5B, 0xAE, 0x58, 0x25, 0x05, 0x46, 0x41, 0xB5, 0x1E, 0x02,
0xF1, 0x16, 0xFB, 0x0C, 0xD5, 0x8D, 0x82, 0x03, 0xEC, 0x3F, 0x6F, 0x00, 0x17, 0x5D, 0x29, 0x1A,
0x3C, 0xDB, 0x0D, 0xEC, 0x96, 0xF9, 0xB0, 0x0E, 0xB7, 0x57, 0xEE, 0x6B, 0x99, 0x94, 0x2F, 0x77,
0x37, 0x1B, 0x7A, 0xDE, 0x82, 0xCF, 0x63, 0xD3, 0x76, 0x5A, 0x1C, 0xD9, 0x28, 0xFB, 0x25, 0x1C,
0x6F, 0xD7, 0x79, 0xDA, 0x56, 0x6B, 0xE1, 0xC8, 0xBE, 0x39, 0xFF, 0xA2, 0x0F, 0xDF, 0x9C, 0xDB,
0xA4, 0x6A, 0x47, 0xF8, 0xB5, 0x31, 0xD7, 0x0D, 0x71, 0x61, 0x96, 0x2C, 0x7F, 0xAE, 0xCF, 0xBF,
0x30, 0x5E, 0x17, 0x58, 0x80, 0x58, 0x1E, 0xB5, 0xC5, 0xED, 0xB9, 0xF5, 0xBB, 0xA0, 0x08, 0x8B,
0xE6, 0x2A, 0x73, 0x39, 0x18, 0xED, 0x75, 0xBC, 0xD7, 0xF8, 0x71, 0x03, 0x2A, 0x10, 0x84, 0x2E,
0xE3, 0xD1, 0x15, 0x91, 0xA4, 0x05, 0xE6, 0x84, 0x43, 0x56, 0x28, 0x58, 0xCE, 0xBF, 0xB8, 0x25,
0x88, 0x84, 0x19, 0x4D, 0xC5, 0xF6, 0xB6, 0x78, 0x91, 0x10, 0x17, 0x67, 0x1D, 0xE4, 0x45, 0x47,
0xEE, 0x4E, 0x57, 0x24, 0x92, 0x63, 0x62, 0x2B, 0x0E, 0x9B, 0x07, 0xA3, 0xB3, 0x91, 0x71, 0x24,
0x2E, 0x2A, 0x0B, 0x75, 0x84, 0x2D, 0x70, 0x8C, 0x49, 0xD7, 0xB9, 0x25, 0x6C, 0x67, 0xDC, 0xF3,
0xB4, 0x26, 0xF4, 0x14, 0xAE, 0xB1, 0x89, 0x6A, 0x40, 0x1C, 0x15, 0xC5, 0x12, 0x2F, 0x9F, 0x73,
0x2C, 0x3B, 0xA3, 0xAB, 0x95, 0x40, 0x87, 0x06, 0x81, 0x0E, 0x15, 0x5E, 0xBA, 0xF2, 0x4D, 0x85,
0x44, 0x07, 0x25, 0x86, 0x42, 0xA9, 0xAA, 0x00, 0xA0, 0xCC, 0x75, 0x61, 0x3C, 0xBB, 0xC5, 0x38,
0x09, 0x60, 0x7E, 0x37, 0xDE, 0x33, 0x4C, 0x44, 0x6D, 0xB7, 0x70, 0xB3, 0xA6, 0xB9, 0x32, 0x12,
0x3E, 0x70, 0x98, 0x90, 0xAB, 0xC6, 0xB2, 0x6F, 0x8F, 0x7D, 0xDE, 0x23, 0x42, 0x7A, 0x88, 0x89,
0xB9, 0x0D, 0xFD, 0xC1, 0xEB, 0x0F, 0x55, 0x3B, 0x03, 0x65, 0xD3, 0xA3, 0xD2, 0xFB, 0xDE, 0xAE,
0xD2, 0x75, 0x6D, 0xCA, 0x4D, 0x0D, 0xF8, 0xD7, 0x2B, 0xFF, 0x09, 0xCF, 0x97, 0xD6, 0xB6, 0xF6,
0xCA, 0x5D, 0x85, 0x77, 0x26, 0xEB, 0xDC, 0xA9, 0xD8, 0x1E, 0xB5, 0xEF, 0x84, 0x07, 0x60, 0xE6,
0x08, 0x0E, 0xB9, 0x7D, 0x8E, 0x25, 0xB8, 0x94, 0x7A, 0xD7, 0xB8, 0xBC, 0x38, 0x69, 0xC6, 0x27,
0xC2, 0xA8, 0x5D, 0x99, 0x76, 0xA4, 0x56, 0xE5, 0x69, 0x69, 0x30, 0xAA, 0xAB, 0x59, 0x4F, 0x0E,
0xE3, 0x27, 0x30, 0x88, 0xE5, 0x1F, 0x61, 0xC8, 0x55, 0xB0, 0x8E, 0x1F, 0x5D, 0x3F, 0x7D, 0x39,
0x79, 0x91, 0xD4, 0x92, 0xC4, 0xA5, 0x9D, 0x4B, 0x5C, 0xE6, 0xFC, 0xF6, 0x63, 0x2B, 0x37, 0x25,
0x4F, 0x40, 0xC9, 0xC6, 0xFC, 0xB5, 0xC7, 0x4C, 0xAE, 0x99, 0xB9, 0x6A, 0x68, 0x83, 0x69, 0x64,
0xCC, 0x07, 0x63, 0xCC, 0x3C, 0x93, 0x99, 0x2D, 0x66, 0xAB, 0x69, 0x30, 0x53, 0xF0, 0x6E, 0x2B,
0xFE, 0xAE, 0x37, 0xAB, 0x4D, 0xF1, 0x67, 0x86, 0x59, 0x67, 0x36, 0x98, 0x0C, 0x9F, 0x1B, 0xF0,
0x3E, 0xC3, 0xFB, 0xAD, 0x1C, 0xBB, 0x83, 0xBF, 0x2E, 0x33, 0x1B, 0xF1, 0xCD, 0x2A, 0x8C, 0xAD,
0x99, 0xC5, 0x26, 0xE7, 0xEF, 0x0D, 0x66, 0x2A, 0xBE, 0x5D, 0x8F, 0x57, 0xCD, 0xF8, 0x3F, 0x43,
0xCC, 0x20, 0xFE, 0xED, 0x6F, 0x06, 0xE3, 0x7D, 0x7F, 0xBC, 0x1B, 0x8D, 0x6F, 0x97, 0x16, 0x70,
0x89, 0x69, 0x07, 0x31, 0xAF, 0xE6, 0x27, 0x63, 0x16, 0x63, 0xEE, 0x36, 0xC2, 0x6D, 0x30, 0xB3,
0xCD, 0x34, 0x33, 0x06, 0xFF, 0x0F, 0x06, 0xD4, 0x56, 0x66, 0x26, 0xC6, 0x6C, 0x28, 0xB0, 0x91,
0xCA, 0xD5, 0x1C, 0xB1, 0x82, 0xB3, 0x97, 0x61, 0xD6, 0x22, 0xD3, 0x10, 0xCD, 0x5D, 0x08, 0x68,
0x99, 0xD9, 0xC1, 0xF1, 0x0D, 0x8E, 0x86, 0x11, 0xC4, 0x3E, 0x9C, 0xFF, 0x0E, 0x01, 0xAE, 0x2F,
0x11, 0x23, 0x48, 0xC8, 0x5B, 0x60, 0x00, 0x00};

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show more