/********************************************************************************************** * okim6258_status_r -- read the status port of an OKIM6258-compatible chip ***********************************************************************************************/ //READ8_DEVICE_HANDLER( okim6258_status_r ) /*UINT8 okim6258_status_r(UINT8 ChipID, offs_t offset) * { * //okim6258_state *info = get_safe_token(device); * okim6258_state *info = &OKIM6258Data[ChipID]; * * //stream_update(info->stream); * * return (info->status & STATUS_PLAYING) ? 0x00 : 0x80; * }*/ /********************************************************************************************** * * okim6258_data_w -- write to the control port of an OKIM6258-compatible chip * ***********************************************************************************************/ //WRITE8_DEVICE_HANDLER( okim6258_data_w ) private static void okim6258_data_w(byte ChipID, /*offs_t offset, */ byte data) { //okim6258_state *info = get_safe_token(device); okim6258_state info = OKIM6258Data[ChipID]; /* update the stream */ //stream_update(info->stream); //info->data_in = data; //info->nibble_shift = 0; if (info.data_empty >= 0x02) { info.data_buf_pos = 0x00; } info.data_in_last = data; info.data_buf[info.data_buf_pos & 0x0F] = data; info.data_buf_pos += 0x01; info.data_buf_pos &= 0xf7; if ((info.data_buf_pos >> 4) == (info.data_buf_pos & 0x0F)) { //logerror("Warning: FIFO full!\n"); info.data_buf_pos = (byte)((info.data_buf_pos & 0xF0) | ((info.data_buf_pos - 1) & 0x07)); } info.data_empty = 0x00; }
//static DEVICE_RESET( okim6258 ) private void device_reset_okim6258(byte ChipID) { //okim6258_state *info = get_safe_token(device); okim6258_state info = OKIM6258Data[ChipID]; //stream_update(info->stream); info.master_clock = info.initial_clock; info.clock_buffer[0x00] = (byte)((info.initial_clock & 0x000000FF) >> 0); info.clock_buffer[0x01] = (byte)((info.initial_clock & 0x0000FF00) >> 8); info.clock_buffer[0x02] = (byte)((info.initial_clock & 0x00FF0000) >> 16); info.clock_buffer[0x03] = (byte)((info.initial_clock & 0xFF000000) >> 24); info.divider = (uint)dividers[info.initial_div]; if (info.SmpRateFunc != null) { info.SmpRateFunc(info.SmpRateData, get_vclk(info)); //Console.WriteLine("passed"); } 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; }
/********************************************************************************************** * * okim6258_get_vclk -- get the VCLK/sampling frequency * ***********************************************************************************************/ //int okim6258_get_vclk(running_device *device) private int okim6258_get_vclk(byte ChipID) { //okim6258_state *info = get_safe_token(device); okim6258_state info = OKIM6258Data[ChipID]; return(get_vclk(info)); //(int)(info.master_clock / info.divider); }
private static short clock_adpcm(okim6258_state chip, byte nibble) { int max = (int)chip.output_mask - 1; int min = -(int)chip.output_mask; int sample = diff_lookup[chip.step * 16 + (nibble & 15)]; chip.signal = ((sample << 8) + (chip.signal * 245)) >> 8; /* clamp to the maximum */ if (chip.signal > max) { chip.signal = max; } else if (chip.signal < min) { chip.signal = min; } /* adjust the step size and clamp */ chip.step += index_shift[nibble & 7]; if (chip.step > 48) { chip.step = 48; } else if (chip.step < 0) { chip.step = 0; } /* return the signal scaled up to 32767 */ return((short)(chip.signal << 4)); }
private static void okim6258_pan_w(byte ChipID, byte data) { okim6258_state info = OKIM6258Data[ChipID]; info.pan = data; return; }
private static void okim6258_set_clock_byte(byte ChipID, byte Byte, byte val) { okim6258_state info = OKIM6258Data[ChipID]; info.clock_buffer[Byte] = val; return; }
/********************************************************************************************** * * state save support for MAME * ***********************************************************************************************/ /*static void okim6258_state_save_register(okim6258_state *info, running_device *device) * { * state_save_register_device_item(device, 0, info->status); * state_save_register_device_item(device, 0, info->master_clock); * state_save_register_device_item(device, 0, info->divider); * state_save_register_device_item(device, 0, info->data_in); * state_save_register_device_item(device, 0, info->nibble_shift); * state_save_register_device_item(device, 0, info->signal); * state_save_register_device_item(device, 0, info->step); * }*/ private static int get_vclk(okim6258_state info) { int clk_rnd; clk_rnd = (int)info.master_clock; clk_rnd += (int)(info.divider / 2); // for better rounding - should help some of the streams return((int)(clk_rnd / info.divider)); }
public void okim6258_set_srchg_cb(byte ChipID, dlgSRATE_CALLBACK CallbackFunc, MDSound.Chip chip) { okim6258_state info = OKIM6258Data[ChipID]; // set Sample Rate Change Callback routine info.SmpRateFunc = CallbackFunc; info.SmpRateData = chip; return; }
/********************************************************************************************** * * okim6258_set_divider -- set the master clock divider * ***********************************************************************************************/ //void okim6258_set_divider(running_device *device, int val) private void okim6258_set_divider(byte ChipID, int val) { //okim6258_state *info = get_safe_token(device); okim6258_state info = OKIM6258Data[ChipID]; int divider = dividers[val]; info.divider = (uint)dividers[val]; //stream_set_sample_rate(info->stream, info->master_clock / divider); if (info.SmpRateFunc != null) { info.SmpRateFunc(info.SmpRateData, get_vclk(info)); } }
/********************************************************************************************** * * okim6258_ctrl_w -- write to the control port of an OKIM6258-compatible chip * ***********************************************************************************************/ //WRITE8_DEVICE_HANDLER( okim6258_ctrl_w ) private static void okim6258_ctrl_w(byte ChipID, /*offs_t offset, */ byte data) { //okim6258_state *info = get_safe_token(device); okim6258_state info = OKIM6258Data[ChipID]; //stream_update(info->stream); if ((data & COMMAND_STOP) != 0) { //Console.WriteLine("COMMAND:STOP"); //info.status &= (byte)(~((byte)STATUS_PLAYING | (byte)STATUS_RECORDING))); info.status &= (byte)(0x2 + 0x4); return; } if ((data & COMMAND_PLAY) != 0) { //Console.WriteLine("COMMAND:PLAY"); if ((info.status & STATUS_PLAYING) == 0) { info.status |= STATUS_PLAYING; /* Also reset the ADPCM parameters */ info.signal = -2; info.step = 0; info.nibble_shift = 0; info.data_buf[0x00] = data; info.data_buf_pos = 0x01; // write pos 01, read pos 00 info.data_empty = 0x00; } info.step = 0; info.nibble_shift = 0; } else { //info.status &= ~STATUS_PLAYING; info.status &= 0xd; } if ((data & COMMAND_RECORD) != 0) { //logerror("M6258: Record enabled\n"); info.status |= STATUS_RECORDING; } else { //info.status &= ~STATUS_RECORDING; info.status &= 0xb; } }
/********************************************************************************************** * * okim6258_set_clock -- set the master clock * ***********************************************************************************************/ //void okim6258_set_clock(running_device *device, int val) private void okim6258_set_clock(byte ChipID, int val) { //okim6258_state *info = get_safe_token(device); okim6258_state info = OKIM6258Data[ChipID]; if (val != 0) { info.master_clock = (uint)val; } else { info.master_clock = (uint)((info.clock_buffer[0x00] << 0) | (info.clock_buffer[0x01] << 8) | (info.clock_buffer[0x02] << 16) | (info.clock_buffer[0x03] << 24)); } //stream_set_sample_rate(info->stream, info->master_clock / info->divider); if (info.SmpRateFunc != null) { info.SmpRateFunc(info.SmpRateData, get_vclk(info)); } }
/********************************************************************************************** * okim6258_update -- update the sound chip so that it is in sync with CPU execution ***********************************************************************************************/ //static STREAM_UPDATE( okim6258_update ) override public void Update(byte ChipID, int[][] outputs, int samples) { //okim6258_state *chip = (okim6258_state *)param; okim6258_state chip = OKIM6258Data[ChipID]; //stream_sample_t *buffer = outputs[0]; int[] bufL = outputs[0]; int[] bufR = outputs[1]; int ind = 0; //memset(outputs[0], 0, samples * sizeof(*outputs[0])); if ((chip.status & STATUS_PLAYING) != 0) { int nibble_shift = chip.nibble_shift; while (samples != 0) { //System.Console.Write("status={0} chip.nibble_shift={1} ", chip.status, chip.nibble_shift); /* Compute the new amplitude and update the current step */ //int nibble = (chip->data_in >> nibble_shift) & 0xf; int nibble; short sample; //System.Console.Write("chip.data_empty={0} ", chip.data_empty); if (nibble_shift == 0) { // 1st nibble - get data if (chip.data_empty == 0) { chip.data_in = chip.data_buf[chip.data_buf_pos >> 4]; chip.data_buf_pos += 0x10; chip.data_buf_pos &= 0x7f; if ((chip.data_buf_pos >> 4) == (chip.data_buf_pos & 0x0F)) { chip.data_empty++; } } else { 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); if (chip.data_empty < 0x02) { sample = clock_adpcm(chip, (byte)nibble); chip.last_smpl = sample; } else { // Valley Bell: data_empty behaviour (loosely) ported from XM6 if (chip.data_empty >= 0x02 + 0x01) { chip.data_empty -= 0x01; //if (chip.signal < 0) // chip.signal++; //else if (chip.signal > 0) // chip.signal--; chip.signal = chip.signal * 15 / 16; chip.last_smpl = chip.signal << 4; } sample = (short)chip.last_smpl; } nibble_shift ^= 4; //*buffer++ = sample; //System.Console.WriteLine("chip.pan={0} sample={1} ", chip.pan, sample); bufL[ind] = ((chip.pan & 0x02) != 0) ? 0x00 : sample; bufR[ind] = ((chip.pan & 0x01) != 0) ? 0x00 : sample; //Console.WriteLine("001 bufL[{0}]={1} bufR[{2}]={3}", ind, bufL[ind], ind, bufR[ind]); samples--; ind++; } /* Update the parameters */ chip.nibble_shift = (byte)nibble_shift; } else { /* Fill with 0 */ while ((samples--) != 0) { // System.Console.Write("passed "); //*buffer++ = 0; bufL[ind] = 0; bufR[ind] = 0; ind++; } } visVolume[ChipID][0][0] = outputs[0][0]; visVolume[ChipID][0][1] = outputs[1][0]; }