Updated and fixed VGM OKIM6258 support from VGMPlay 0.40.4

CQTexperiment
Chris Moeller 2014-02-24 16:38:46 -08:00
parent d3d370b76e
commit 85cc09e07f
5 changed files with 169 additions and 37 deletions

View File

@ -36,6 +36,11 @@ 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 ];

View File

@ -16,6 +16,9 @@ public:
// 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 );

View File

@ -197,9 +197,19 @@ int Vgm_Core::run_pwm( int time )
return pwm.run_until( time );
}
int Vgm_Core::run_okim6258( int time )
int Vgm_Core::run_okim6258( int chip, int time )
{
return okim6258.run_until( time );
chip = !!chip;
if ( okim6258[chip].enabled() )
{
int current_clock = okim6258[chip].get_clock();
if ( okim6258_hz[chip] != current_clock )
{
okim6258_hz[chip] = current_clock;
okim6258[chip].setup( (double)okim6258_hz[chip] / vgm_rate, 0.85, 1.0 );
}
}
return okim6258[chip].run_until( time );
}
int Vgm_Core::run_okim6295( int chip, int time )
@ -703,8 +713,8 @@ void Vgm_Core::chip_reg_write(unsigned Sample, byte ChipType, byte ChipID, byte
break;
case 0x17:
if ( run_okim6258( to_fm_time( Sample ) ) )
okim6258.write( Offset, Data );
if ( run_okim6258( ChipID, to_fm_time( Sample ) ) )
okim6258[ChipID].write( Offset, Data );
break;
case 0x18:
@ -898,7 +908,8 @@ blargg_err_t Vgm_Core::load_mem_( byte const data [], int size )
rf5c68.enable( false );
rf5c164.enable( false );
pwm.enable( false );
okim6258.enable( false );
okim6258[0].enable( false );
okim6258[1].enable( false );
okim6295[0].enable( false );
okim6295[1].enable( false );
k051649.enable( false );
@ -1234,13 +1245,24 @@ blargg_err_t Vgm_Core::init_chips( double* rate, bool reinit )
}
if ( okim6258_rate )
{
bool dual_chip = !!( header().okim6258_rate[3] & 0x40 );
if ( !reinit )
{
okim6258_hz = okim6258.set_rate( okim6258_rate, header().okim6258_flags & 0x03, ( header().okim6258_flags & 0x04 ) >> 2, ( header().okim6258_flags & 0x08 ) >> 3 );
CHECK_ALLOC( okim6258_hz );
okim6258_hz[0] = okim6258[0].set_rate( okim6258_rate, header().okim6258_flags & 0x03, ( header().okim6258_flags & 0x04 ) >> 2, ( header().okim6258_flags & 0x08 ) >> 3 );
CHECK_ALLOC( okim6258_hz[0] );
}
RETURN_ERR( okim6258.setup( (double)okim6258_hz / vgm_rate, 0.85, 1.0 ) );
okim6258.enable();
RETURN_ERR( okim6258[0].setup( (double)okim6258_hz[0] / vgm_rate, 0.85, 1.0 ) );
okim6258[0].enable();
if ( dual_chip )
{
if ( !reinit )
{
okim6258_hz[1] = okim6258[1].set_rate( okim6258_rate, header().okim6258_flags & 0x03, ( header().okim6258_flags & 0x04 ) >> 2, ( header().okim6258_flags & 0x08 ) >> 3 );
CHECK_ALLOC( okim6258_hz[1] );
}
RETURN_ERR( okim6258[1].setup( (double)okim6258_hz[1] / vgm_rate, 0.85, 1.0 ) );
okim6258[1].enable();
}
}
if ( okim6295_rate )
{
@ -1384,8 +1406,11 @@ void Vgm_Core::start_track()
if ( pwm.enabled() )
pwm.reset();
if ( okim6258.enabled() )
okim6258.reset();
if ( okim6258[0].enabled() )
okim6258[0].reset();
if ( okim6258[1].enabled() )
okim6258[1].reset();
if ( okim6295[0].enabled() )
okim6295[0].reset();
@ -1757,7 +1782,7 @@ blip_time_t Vgm_Core::run( vgm_time_t end_time )
break;
case cmd_okim6258_write:
chip_reg_write( vgm_time, 0x17, 0x00, 0x00, pos [0] & 0x7F, pos [1] );
chip_reg_write( vgm_time, 0x17, ChipID, 0x00, pos [0] & 0x7F, pos [1] );
pos += 2;
break;
@ -2157,9 +2182,13 @@ int Vgm_Core::play_frame( blip_time_t blip_time, int sample_count, blip_sample_t
{
pwm.begin_frame( out );
}
if ( okim6258.enabled() )
if ( okim6258[0].enabled() )
{
okim6258.begin_frame( out );
okim6258[0].begin_frame( out );
if ( okim6258[1].enabled() )
{
okim6258[1].begin_frame( out );
}
}
if ( okim6295[0].enabled() )
{
@ -2211,7 +2240,7 @@ int Vgm_Core::play_frame( blip_time_t blip_time, int sample_count, blip_sample_t
run_rf5c68( pairs );
run_rf5c164( pairs );
run_pwm( pairs );
run_okim6258( pairs );
run_okim6258( 0, pairs ); run_okim6258( 1, pairs );
run_okim6295( 0, pairs ); run_okim6295( 1, pairs );
run_k051649( pairs );
run_k053260( pairs );

View File

@ -150,7 +150,7 @@ public:
// 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.enabled() || okim6295[0].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]) ||
@ -205,7 +205,7 @@ public:
Chip_Resampler_Emu<Rf5C68_Emu> rf5c68;
Chip_Resampler_Emu<Rf5C164_Emu> rf5c164;
Chip_Resampler_Emu<Pwm_Emu> pwm;
Chip_Resampler_Emu<Okim6258_Emu> okim6258; int okim6258_hz;
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;
@ -334,7 +334,7 @@ private:
int run_rf5c68( int time );
int run_rf5c164( int time );
int run_pwm( int time );
int run_okim6258( 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 );

View File

@ -42,10 +42,24 @@ struct _okim6258_state
UINT8 output_bits;
// Valley Bell: Added a small queue to prevent race conditions.
UINT8 data_buf[2];
UINT8 data_buf_pos;
// Data Empty Values:
// 00 - data written, but not read yet
// 01 - read data, waiting for next write
// 02 - tried to read, but had no data
UINT8 data_empty;
// Valley Bell: Added pan
UINT8 pan;
INT32 last_smpl;
INT32 signal;
INT32 step;
UINT8 clock_buffer[0x04];
UINT32 initial_clock;
UINT8 initial_div;
};
/* step size index shift table */
@ -144,29 +158,68 @@ void okim6258_update(void *_chip, stream_sample_t **outputs, int samples)
//stream_sample_t *buffer = outputs[0];
stream_sample_t *bufL = outputs[0];
stream_sample_t *bufR = outputs[1];
//memset(outputs[0], 0, samples * sizeof(*outputs[0]));
if (chip->status & STATUS_PLAYING)
{
int nibble_shift = chip->nibble_shift;
while (samples)
{
/* Compute the new amplitude and update the current step */
int nibble = (chip->data_in >> nibble_shift) & 0xf;
//int nibble = (chip->data_in >> nibble_shift) & 0xf;
int nibble;
INT16 sample;
if (! nibble_shift)
{
// 1st nibble - get data
if (! chip->data_empty)
{
chip->data_in = chip->data_buf[chip->data_buf_pos >> 4];
chip->data_buf_pos ^= 0x10;
if ((chip->data_buf_pos >> 4) == (chip->data_buf_pos & 0x0F))
chip->data_empty ++;
}
else
{
chip->data_in = 0x80;
if (chip->data_empty < 0x80)
chip->data_empty ++;
}
}
nibble = (chip->data_in >> nibble_shift) & 0xf;
/* Output to the buffer */
INT16 sample = clock_adpcm(chip, nibble);
//INT16 sample = clock_adpcm(chip, nibble);
if (chip->data_empty < 0x02)
{
sample = clock_adpcm(chip, nibble);
chip->last_smpl = sample;
}
else
{
sample = chip->last_smpl;
// Valley Bell: data_empty behaviour (loosely) ported from XM6
if (chip->data_empty >= 0x12)
{
chip->data_empty -= 0x10;
if (chip->signal < 0)
chip->signal ++;
else if (chip->signal > 0)
chip->signal --;
}
}
nibble_shift ^= 4;
//*buffer++ = sample;
*bufL++ = sample;
*bufR++ = sample;
*bufL++ = (chip->pan & 0x02) ? 0x00 : sample;
*bufR++ = (chip->pan & 0x01) ? 0x00 : sample;
samples--;
}
/* Update the parameters */
chip->nibble_shift = nibble_shift;
}
@ -220,6 +273,8 @@ void * device_start_okim6258(int clock, int divider, int adpcm_type, int output_
compute_tables();
//info->master_clock = device->clock();
info->initial_clock = clock;
info->initial_div = divider;
info->master_clock = clock;
info->adpcm_type = /*intf->*/adpcm_type;
info->clock_buffer[0x00] = (clock & 0x000000FF) >> 0;
@ -263,9 +318,24 @@ void device_reset_okim6258(void *chip)
//stream_update(info->stream);
info->master_clock = info->initial_clock;
info->clock_buffer[0x00] = (info->initial_clock & 0x000000FF) >> 0;
info->clock_buffer[0x01] = (info->initial_clock & 0x0000FF00) >> 8;
info->clock_buffer[0x02] = (info->initial_clock & 0x00FF0000) >> 16;
info->clock_buffer[0x03] = (info->initial_clock & 0xFF000000) >> 24;
info->divider = dividers[info->initial_div];
info->signal = -2;
info->step = 0;
info->status = 0;
// Valley Bell: Added reset of the Data In register.
info->data_in = 0x00;
info->data_buf[0] = info->data_buf[1] = 0x00;
info->data_buf_pos = 0x00;
info->data_empty = 0xFF;
info->pan = 0x00;
}
@ -357,8 +427,17 @@ void okim6258_data_w(void *chip, offs_t offset, UINT8 data)
/* update the stream */
//stream_update(info->stream);
info->data_in = data;
info->nibble_shift = 0;
//info->data_in = data;
//info->nibble_shift = 0;
if (info->data_empty >= 0x02)
{
info->data_buf_pos = 0x00;
info->data_buf[info->data_buf_pos & 0x0F] = 0x80;
}
info->data_buf[info->data_buf_pos & 0x0F] = data;
info->data_buf_pos ^= 0x01;
info->data_empty = 0x00;
}
@ -381,24 +460,27 @@ void okim6258_ctrl_w(void *chip, offs_t offset, UINT8 data)
info->status &= ~(STATUS_PLAYING | STATUS_RECORDING);
return;
}
if (data & COMMAND_PLAY)
{
if (!(info->status & STATUS_PLAYING))
{
info->status |= STATUS_PLAYING;
/* Also reset the ADPCM parameters */
info->signal = -2;
info->step = 0;
info->nibble_shift = 0;
//info->signal = -2;
//info->step = 0;
//info->nibble_shift = 0;
}
//info->signal = -2;
info->step = 0;
info->nibble_shift = 0;
}
else
{
info->status &= ~STATUS_PLAYING;
}
if (data & COMMAND_RECORD)
{
/*logerror("M6258: Record enabled\n");*/
@ -419,6 +501,16 @@ void okim6258_set_clock_byte(void *chip, UINT8 Byte, UINT8 val)
return;
}
static void okim6258_pan_w(void *chip, UINT8 data)
{
okim6258_state *info = (okim6258_state *) chip;
info->pan = data;
return;
}
void okim6258_write(void *chip, UINT8 Port, UINT8 Data)
{
switch(Port)
@ -429,6 +521,9 @@ void okim6258_write(void *chip, UINT8 Port, UINT8 Data)
case 0x01:
okim6258_data_w(chip, 0x00, Data);
break;
case 0x02:
okim6258_pan_w(chip, Data);
break;
case 0x08:
case 0x09:
case 0x0A: