diff options
Diffstat (limited to 'src/mame/machine/midwayic.cpp')
-rw-r--r-- | src/mame/machine/midwayic.cpp | 1246 |
1 files changed, 0 insertions, 1246 deletions
diff --git a/src/mame/machine/midwayic.cpp b/src/mame/machine/midwayic.cpp deleted file mode 100644 index 8045c6cb69c..00000000000 --- a/src/mame/machine/midwayic.cpp +++ /dev/null @@ -1,1246 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Aaron Giles -/*************************************************************************** - - Emulation of various Midway ICs - -***************************************************************************/ - -#include "emu.h" -#include "debugger.h" -#include "midwayic.h" - - -#define LOG_NVRAM (0) - -#define PRINTF_DEBUG (0) -#define LOG_IOASIC (0) -#define LOG_FIFO (0) - - -/************************************* - * - * Constants - * - *************************************/ - -#define FIFO_SIZE 512 - -/************************************* - * - * Serial number input kludge - * - *************************************/ - -static INPUT_PORTS_START( pic_serial_adjust ) - PORT_START("SERIAL_DIGIT") - PORT_DIPNAME( 0x0f, 0x06, "Serial Low Digit") - PORT_DIPSETTING( 0x00, "0") - PORT_DIPSETTING( 0x01, "1") - PORT_DIPSETTING( 0x02, "2") - PORT_DIPSETTING( 0x03, "3") - PORT_DIPSETTING( 0x04, "4") - PORT_DIPSETTING( 0x05, "5") - PORT_DIPSETTING( 0x06, "6") - PORT_DIPSETTING( 0x07, "7") - PORT_DIPSETTING( 0x08, "8") - PORT_DIPSETTING( 0x09, "9") - PORT_BIT( 0xf0, 0x00, IPT_UNUSED ) -INPUT_PORTS_END - -ioport_constructor midway_serial_pic_device::device_input_ports() const -{ - return INPUT_PORTS_NAME(pic_serial_adjust); -} - -/************************************* - * - * Serial number encoding - * - *************************************/ - -void midway_serial_pic_device::generate_serial_data(int upper) -{ - int year = atoi(machine().system().year), month = 12, day = 11; - uint32_t serial_number, temp; - uint8_t serial_digit[9]; - - serial_number = 123450; - serial_number += upper * 1000000; - serial_number += m_io_serial_digit->read() & 0x0f; - - serial_digit[0] = (serial_number / 100000000) % 10; - serial_digit[1] = (serial_number / 10000000) % 10; - serial_digit[2] = (serial_number / 1000000) % 10; - serial_digit[3] = (serial_number / 100000) % 10; - serial_digit[4] = (serial_number / 10000) % 10; - serial_digit[5] = (serial_number / 1000) % 10; - serial_digit[6] = (serial_number / 100) % 10; - serial_digit[7] = (serial_number / 10) % 10; - serial_digit[8] = (serial_number / 1) % 10; - - m_data[12] = machine().rand() & 0xff; - m_data[13] = machine().rand() & 0xff; - - m_data[14] = 0; /* ??? */ - m_data[15] = 0; /* ??? */ - - temp = 0x174 * (year - 1980) + 0x1f * (month - 1) + day; - m_data[10] = (temp >> 8) & 0xff; - m_data[11] = temp & 0xff; - - temp = serial_digit[4] + serial_digit[7] * 10 + serial_digit[1] * 100; - temp = (temp + 5 * m_data[13]) * 0x1bcd + 0x1f3f0; - m_data[7] = temp & 0xff; - m_data[8] = (temp >> 8) & 0xff; - m_data[9] = (temp >> 16) & 0xff; - - temp = serial_digit[6] + serial_digit[8] * 10 + serial_digit[0] * 100 + serial_digit[2] * 10000; - temp = (temp + 2 * m_data[13] + m_data[12]) * 0x107f + 0x71e259; - m_data[3] = temp & 0xff; - m_data[4] = (temp >> 8) & 0xff; - m_data[5] = (temp >> 16) & 0xff; - m_data[6] = (temp >> 24) & 0xff; - - temp = serial_digit[5] * 10 + serial_digit[3] * 100; - temp = (temp + m_data[12]) * 0x245 + 0x3d74; - m_data[0] = temp & 0xff; - m_data[1] = (temp >> 8) & 0xff; - m_data[2] = (temp >> 16) & 0xff; -} - - - -/************************************* - * - * Original serial number PIC - * interface - simulation - * - *************************************/ - -void midway_serial_pic_device::serial_register_state() -{ - save_item(NAME(m_data)); - save_item(NAME(m_buff)); - save_item(NAME(m_idx)); - save_item(NAME(m_status)); - save_item(NAME(m_bits)); -} - -DEFINE_DEVICE_TYPE(MIDWAY_SERIAL_PIC, midway_serial_pic_device, "midway_serial_pic_sim", "Midway Serial PIC Simulation") - - -//------------------------------------------------- -// midway_serial_pic_device - constructor -//------------------------------------------------- - -midway_serial_pic_device::midway_serial_pic_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - midway_serial_pic_device(mconfig, MIDWAY_SERIAL_PIC, tag, owner, clock) -{ -} - -midway_serial_pic_device::midway_serial_pic_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : - device_t(mconfig, type, tag, owner, clock), - m_io_serial_digit(*this, "SERIAL_DIGIT"), - m_upper(0), - m_buff(0), - m_idx(0), - m_status(0), - m_bits(0) -{ - memset(m_data,0,sizeof(m_data)); -} - -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -void midway_serial_pic_device::device_start() -{ - serial_register_state(); -} - -void midway_serial_pic_device::device_reset() -{ - generate_serial_data(m_upper); -} - -WRITE_LINE_MEMBER(midway_serial_pic_device::reset_w) -{ - if (state) - { - m_idx = 0; - m_status = 0; - m_buff = 0; - } -} - - -u8 midway_serial_pic_device::status_r() -{ - return m_status; -} - - -u8 midway_serial_pic_device::read() -{ - if (!machine().side_effects_disabled()) - { - logerror("%s:security R = %04X\n", machine().describe_context(), m_buff); - m_status = 1; - } - return m_buff; -} - - -void midway_serial_pic_device::write(u8 data) -{ - logerror("%s:security W = %04X\n", machine().describe_context(), data); - - /* status seems to reflect the clock bit */ - m_status = (data >> 4) & 1; - - /* on the falling edge, clock the next data byte through */ - if (!m_status) - { - /* the self-test writes 1F, 0F, and expects to read an F in the low 4 bits */ - if (data & 0x0f) - m_buff = data & 0xf; - else - m_buff = m_data[m_idx++ % sizeof(m_data)]; - } -} - - -/************************************* - * - * Original serial number PIC - * interface - emulation - * - * PIC16C57 wiring notes: - * PORTA - 4bit command in (usually 0 = read SN#) - * PORTB - 8bit data out - * PORTC bit 7 - access clock in - * PORTC bit 6 - status out - * PORTC bit 2 - in/out (optional) MK41T56N RTC/NVRAM Data - * PORTC bit 1 - out (optional) MK41T56N RTC/NVRAM Clock - * - *************************************/ - - -DEFINE_DEVICE_TYPE(MIDWAY_SERIAL_PIC_EMU, midway_serial_pic_emu_device, "midway_serial_pic_emu", "Midway Serial PIC Emulation") - - -//------------------------------------------------- -// midway_serial_pic_emu_device - constructor -//------------------------------------------------- - -midway_serial_pic_emu_device::midway_serial_pic_emu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - device_t(mconfig, MIDWAY_SERIAL_PIC_EMU, tag, owner, clock) - , m_pic(*this, "pic") -{ -} - -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -void midway_serial_pic_emu_device::device_start() -{ - save_item(NAME(m_command)); - save_item(NAME(m_data_out)); - save_item(NAME(m_clk)); - save_item(NAME(m_status)); - - m_command = 0; - m_data_out = 0; - m_clk = 0; - m_status = 0; -} - -WRITE_LINE_MEMBER(midway_serial_pic_emu_device::reset_w) -{ - if (!state) // fixme, PIC should be stopped while 0 and start running at 0->1 transition - m_pic->reset(); -} - -u8 midway_serial_pic_emu_device::status_r() -{ - return m_status; -} - -u8 midway_serial_pic_emu_device::read() -{ - return m_data_out; -} - -void midway_serial_pic_emu_device::write(u8 data) -{ - // perhaps this should be split in 2 handlers ? - m_command = data & 0x0f; - m_clk = BIT(data, 4); -} - -u8 midway_serial_pic_emu_device::read_c() -{ - u8 data = 0; - data |= m_clk << 7; - // bit 2 RTC Data - return data; -} - -void midway_serial_pic_emu_device::write_c(u8 data) -{ - m_status = BIT(data, 6); - // bits 1 and 2 is RTC Clock and Data -// printf("%s: write_c %02x\n", machine().describe_context().c_str(), data); -} - -void midway_serial_pic_emu_device::device_add_mconfig(machine_config &config) -{ - PIC16C57(config, m_pic, 4000000); /* ? Mhz */ - m_pic->read_a().set([this]() { return m_command; }); - m_pic->write_b().set([this](u8 data) { m_data_out = data; }); - m_pic->read_c().set(FUNC(midway_serial_pic_emu_device::read_c)); - m_pic->write_c().set(FUNC(midway_serial_pic_emu_device::write_c)); -} - - -/************************************* - * - * Second generation serial number - * PIC interface; this version also - * contained some NVRAM and a real - * time clock - * - *************************************/ - -static inline uint8_t make_bcd(uint8_t data) -{ - return ((data / 10) << 4) | (data % 10); -} - -DEFINE_DEVICE_TYPE(MIDWAY_SERIAL_PIC2, midway_serial_pic2_device, "midway_serial_pic2", "Midway Serial PIC 2") - - -//------------------------------------------------- -// midway_serial_pic2_device - constructor -//------------------------------------------------- - -midway_serial_pic2_device::midway_serial_pic2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - midway_serial_pic2_device(mconfig, MIDWAY_SERIAL_PIC2, tag, owner, clock) -{ -} - -midway_serial_pic2_device::midway_serial_pic2_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : - midway_serial_pic_device(mconfig, type, tag, owner, clock), - device_nvram_interface(mconfig, *this), - m_latch(0), - m_state(0), - m_index(0), - m_total(0), - m_nvram_addr(0), - m_time_index(0), - m_time_just_written(0), - m_yearoffs(0), - m_time_write_timer(nullptr) -{ - memset(m_buffer,0,sizeof(m_buffer)); - memset(m_time_buf,0,sizeof(m_time_buf)); - memset(m_nvram,0,sizeof(m_nvram)); - memset(m_default_nvram,0,sizeof(m_default_nvram)); -} - - -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -void midway_serial_pic2_device::device_start() -{ - midway_serial_pic_device::device_start(); - //void midway_serial_pic2_init(running_machine &machine, int upper, int yearoffs) - pic_register_state(); - - //m_yearoffs = yearoffs; - m_time_just_written = 0; - m_time_write_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(midway_serial_pic2_device::reset_timer),this)); - memset(m_default_nvram, 0xff, sizeof(m_default_nvram)); -} - - -TIMER_CALLBACK_MEMBER( midway_serial_pic2_device::reset_timer ) -{ - m_time_just_written = 0; -} - - -void midway_serial_pic2_device::pic_register_state() -{ - save_item(NAME(m_latch)); - save_item(NAME(m_latch_expire_time)); - save_item(NAME(m_state)); - save_item(NAME(m_index)); - save_item(NAME(m_total)); - save_item(NAME(m_nvram_addr)); - save_item(NAME(m_buffer)); - save_item(NAME(m_nvram)); - save_item(NAME(m_default_nvram)); - save_item(NAME(m_time_buf)); - save_item(NAME(m_time_index)); - save_item(NAME(m_time_just_written)); - save_item(NAME(m_yearoffs)); -} - - - -void midway_serial_pic2_device::set_default_nvram(const uint8_t *nvram) -{ - memcpy(m_default_nvram, nvram, sizeof(m_default_nvram)); -} - - -u8 midway_serial_pic2_device::status_r() -{ - uint8_t result = 0; - - if (!machine().side_effects_disabled()) - { - /* if we're still holding the data ready bit high, do it */ - if (m_latch & 0xf00) - { - if (machine().time() > m_latch_expire_time) - m_latch &= 0xff; - else - m_latch -= 0x100; - result = 1; - } - - logerror("%s:PIC status %d\n", machine().describe_context(), result); - } - return result; -} - - -u8 midway_serial_pic2_device::read() -{ - uint8_t result = 0; - - /* PIC data register */ - if (!machine().side_effects_disabled()) - logerror("%s:PIC data read (index=%d total=%d latch=%03X) =", machine().describe_context(), m_index, m_total, m_latch); - - /* return the current result */ - if (m_latch & 0xf00) - result = m_latch & 0xff; - - /* otherwise, return 0xff if we have data ready */ - else if (m_index < m_total) - result = 0xff; - - if (!machine().side_effects_disabled()) - logerror("%02X\n", result); - return result; -} - - -void midway_serial_pic2_device::write(u8 data) -{ - static FILE *nvramlog; - if (LOG_NVRAM && !nvramlog) - nvramlog = fopen("nvram.log", "w"); - - /* PIC command register */ - if (m_state == 0) - logerror("%s:PIC command %02X\n", machine().describe_context(), data); - else - logerror("%s:PIC data %02X\n", machine().describe_context(), data); - - /* store in the latch, along with a bit to indicate we have data */ - m_latch = (data & 0x00f) | 0x480; - m_latch_expire_time = machine().time() + attotime::from_msec(1); - if (data & 0x10) - { - int cmd = m_state ? (m_state & 0x0f) : (m_latch & 0x0f); - switch (cmd) - { - /* written to latch the next byte of data */ - case 0: - if (m_index < m_total) - m_latch = 0x400 | m_buffer[m_index++]; - break; - - /* fetch the serial number */ - case 1: - /* note: Biofreaks assumes that it can latch the next byte this way */ - if (m_index < m_total) - m_latch = 0x400 | m_buffer[m_index++]; - else - { - memcpy(m_buffer, m_data, 16); - m_total = 16; - m_index = 0; - machine().debug_break(); - } - break; - - /* read the clock */ - case 3: - { - /* stuff it into the data bytes */ - m_index = 0; - m_total = 0; - - /* if we haven't written a new time recently, use the real live time */ - if (!m_time_just_written) - { - system_time systime; - machine().base_datetime(systime); - - m_buffer[m_total++] = make_bcd(systime.local_time.second); - m_buffer[m_total++] = make_bcd(systime.local_time.minute); - m_buffer[m_total++] = make_bcd(systime.local_time.hour); - m_buffer[m_total++] = make_bcd(systime.local_time.weekday + 1); - m_buffer[m_total++] = make_bcd(systime.local_time.mday); - m_buffer[m_total++] = make_bcd(systime.local_time.month + 1); - m_buffer[m_total++] = make_bcd(systime.local_time.year - 1900 - m_yearoffs); - } - - /* otherwise, just parrot back what was written to pass self tests */ - else - { - m_buffer[m_total++] = m_time_buf[0]; - m_buffer[m_total++] = m_time_buf[1]; - m_buffer[m_total++] = m_time_buf[2]; - m_buffer[m_total++] = m_time_buf[3]; - m_buffer[m_total++] = m_time_buf[4]; - m_buffer[m_total++] = m_time_buf[5]; - m_buffer[m_total++] = m_time_buf[6]; - } - break; - } - - /* write the clock */ - case 4: - - /* if coming from state 0, go to state 1 (this is just the command byte) */ - if (m_state == 0) - { - m_state = 0x14; - m_time_index = 0; - } - - /* if in states 1-2 put data in the buffer until it's full */ - else if (m_state == 0x14) - { - m_time_buf[m_time_index] = m_latch & 0x0f; - m_state = 0x24; - } - else if (m_state == 0x24) - { - m_time_buf[m_time_index++] |= m_latch << 4; - - /* if less than 7 bytes accumulated, go back to state 1 */ - if (m_time_index < 7) - m_state = 0x14; - - /* otherwise, flag the time as having just been written for 1/2 second */ - else - { - m_time_write_timer->adjust(attotime::from_msec(500)); - m_time_just_written = 1; - m_state = 0; - } - } - break; - - /* write to NVRAM */ - case 5: - - /* if coming from state 0, go to state 1 (this is just the command byte) */ - if (m_state == 0) - m_state = 0x15; - - /* coming from state 1, go to state 2 and latch the low 4 address bits */ - else if (m_state == 0x15) - { - m_nvram_addr = m_latch & 0x0f; - m_state = 0x25; - } - - /* coming from state 2, go to state 3 and latch the high 4 address bits */ - else if (m_state == 0x25) - { - m_state = 0x35; - m_nvram_addr |= m_latch << 4; - } - - /* coming from state 3, go to state 4 and write the low 4 bits */ - else if (m_state == 0x35) - { - m_state = 0x45; - m_nvram[m_nvram_addr] = m_latch & 0x0f; - } - - /* coming from state 4, reset the states and write the upper 4 bits */ - else if (m_state == 0x45) - { - m_state = 0; - m_nvram[m_nvram_addr] |= m_latch << 4; - if (nvramlog) - fprintf(nvramlog, "Write byte %02X = %02X\n", m_nvram_addr, m_nvram[m_nvram_addr]); - } - break; - - /* read from NVRAM */ - case 6: - - /* if coming from state 0, go to state 1 (this is just the command byte) */ - if (m_state == 0) - m_state = 0x16; - - /* coming from state 1, go to state 2 and latch the low 4 address bits */ - else if (m_state == 0x16) - { - m_nvram_addr = m_latch & 0x0f; - m_state = 0x26; - } - - /* coming from state 2, reset the states and make the data available */ - else if (m_state == 0x26) - { - m_state = 0; - m_nvram_addr |= m_latch << 4; - - m_total = 0; - m_index = 0; - m_buffer[m_total++] = m_nvram[m_nvram_addr]; - if (nvramlog) - fprintf(nvramlog, "Read byte %02X = %02X\n", m_nvram_addr, m_nvram[m_nvram_addr]); - } - break; - - /* reflect inverted? (Cruisin' Exotica) */ - case 8: - m_latch = 0x400 | (~cmd & 0xff); - break; - } - } -} - -void midway_serial_pic2_device::nvram_default() -{ - memcpy(m_nvram, m_default_nvram, sizeof(m_nvram)); -} - -void midway_serial_pic2_device::nvram_read(emu_file &file) -{ - file.read(m_nvram, sizeof(m_nvram)); -} - -void midway_serial_pic2_device::nvram_write(emu_file &file) -{ - file.write(m_nvram, sizeof(m_nvram)); -} - - -/************************************* - * - * The I/O ASIC was first introduced - * in War Gods, then later used on - * the Seattle hardware - * - *************************************/ - -enum -{ - IOASIC_PORT0, /* 0: input port 0 */ - IOASIC_PORT1, /* 1: input port 1 */ - IOASIC_PORT2, /* 2: input port 2 */ - IOASIC_PORT3, /* 3: input port 3 */ - IOASIC_UARTCONTROL, /* 4: controls some UART behavior */ - IOASIC_UARTOUT, /* 5: UART output */ - IOASIC_UARTIN, /* 6: UART input */ - IOASIC_COIN, /* 7: triggered on coin insertion */ - IOASIC_SOUNDCTL, /* 8: sound communications control */ - IOASIC_SOUNDOUT, /* 9: sound output port */ - IOASIC_SOUNDSTAT, /* a: sound status port */ - IOASIC_SOUNDIN, /* b: sound input port */ - IOASIC_PICOUT, /* c: PIC output port */ - IOASIC_PICIN, /* d: PIC input port */ - IOASIC_INTSTAT, /* e: interrupt status */ - IOASIC_INTCTL /* f: interrupt control */ -}; - -void midway_ioasic_device::ioasic_register_state() -{ - save_item(NAME(m_reg)); - save_item(NAME(m_shuffle_active)); - save_item(NAME(m_irq_state)); - save_item(NAME(m_sound_irq_state)); - save_item(NAME(m_auto_ack)); - save_item(NAME(m_force_fifo_full)); - save_item(NAME(m_fifo)); - save_item(NAME(m_fifo_in)); - save_item(NAME(m_fifo_out)); - save_item(NAME(m_fifo_bytes)); - save_item(NAME(m_fifo_force_buffer_empty_pc)); -} - -DEFINE_DEVICE_TYPE(MIDWAY_IOASIC, midway_ioasic_device, "midway_ioasic", "Midway IOASIC") - - -//------------------------------------------------- -// midway_serial_pic2_device - constructor -//------------------------------------------------- - -midway_ioasic_device::midway_ioasic_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - midway_serial_pic2_device(mconfig, MIDWAY_IOASIC, tag, owner, clock), - m_io_dips(*this, ":DIPS"), - m_io_system(*this, ":SYSTEM"), - m_io_in1(*this, ":IN1"), - m_io_in2(*this, ":IN2"), - m_serial_tx_cb(*this), - m_aux_output_cb(*this), - m_has_dcs(0), - m_has_cage(0), - m_dcs_cpu(nullptr), - m_shuffle_type(0), - m_shuffle_default(0), - m_shuffle_active(0), - m_shuffle_map(nullptr), - m_irq_callback(*this), - m_irq_state(0), - m_sound_irq_state(0), - m_auto_ack(0), - m_force_fifo_full(0), - m_fifo_in(0), - m_fifo_out(0), - m_fifo_bytes(0), - m_fifo_force_buffer_empty_pc(0), - m_cage(*this, ":cage"), - m_dcs(*this, ":dcs") -{ - memset(m_fifo,0,sizeof(m_fifo)); - memset(m_reg,0,sizeof(m_reg)); -} - - -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -void midway_ioasic_device::device_start() -//void midway_ioasic_init(running_machine &machine, int shuffle, int upper, int yearoffs, void (*irq_callback)(running_machine &, int)) -{ - static const uint8_t shuffle_maps[][16] = - { - { 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf }, /* WarGods, WG3DH, SFRush, MK4 */ - { 0x4,0x5,0x6,0x7,0xb,0xa,0x9,0x8,0x3,0x2,0x1,0x0,0xf,0xe,0xd,0xc }, /* Blitz, Blitz99 */ - { 0x7,0x3,0x2,0x0,0x1,0xc,0xd,0xe,0xf,0x4,0x5,0x6,0x8,0x9,0xa,0xb }, /* Carnevil */ - { 0x8,0x9,0xa,0xb,0x0,0x1,0x2,0x3,0xf,0xe,0xc,0xd,0x4,0x5,0x6,0x7 }, /* Calspeed, Gauntlet Legends */ - { 0xf,0xe,0xd,0xc,0x4,0x5,0x6,0x7,0x9,0x8,0xa,0xb,0x2,0x3,0x1,0x0 }, /* Mace */ - { 0xc,0xd,0xe,0xf,0x0,0x1,0x2,0x3,0x7,0x8,0x9,0xb,0xa,0x5,0x6,0x4 }, /* Gauntlet Dark Legacy */ - { 0x7,0x4,0x5,0x6,0x2,0x0,0x1,0x3,0x8,0x9,0xa,0xb,0xd,0xc,0xe,0xf }, /* Vapor TRX */ - { 0x7,0x4,0x5,0x6,0x2,0x0,0x1,0x3,0x8,0x9,0xa,0xb,0xd,0xc,0xe,0xf }, /* San Francisco Rush: The Rock */ - { 0x1,0x2,0x3,0x0,0x4,0x5,0x6,0x7,0xa,0xb,0x8,0x9,0xc,0xd,0xe,0xf }, /* Hyperdrive */ - }; - - ioasic_register_state(); - - /* do we have a DCS2 sound chip connected? */ - m_has_dcs = (m_dcs != nullptr); - m_has_cage = (m_cage != nullptr); - - if (m_has_dcs) - { - m_dcs_cpu = m_dcs->get_cpu(); - } - - m_shuffle_map = &shuffle_maps[m_shuffle_type][0]; - // resolve callbacks - m_irq_callback.resolve_safe(); - m_serial_tx_cb.resolve_safe(); - m_aux_output_cb.resolve(); - - /* initialize the PIC */ - midway_serial_pic2_device::device_start(); - - /* reset the chip */ - ioasic_reset(); - - m_reg[IOASIC_SOUNDCTL] = 0x0001; - - - /* configure the fifo */ - if (m_has_dcs) - { - m_dcs->set_fifo_callbacks( - read16smo_delegate(*this, FUNC(midway_ioasic_device::fifo_r)), - read16mo_delegate(*this, FUNC(midway_ioasic_device::fifo_status_r)), - write_line_delegate(*this, FUNC(midway_ioasic_device::fifo_reset_w))); - m_dcs->set_io_callbacks( - write_line_delegate(*this, FUNC(midway_ioasic_device::ioasic_output_full)), - write_line_delegate(*this, FUNC(midway_ioasic_device::ioasic_input_empty))); - } - - fifo_reset_w(1); -} - -void midway_ioasic_device::set_shuffle_state(int state) -{ - m_shuffle_active = state; -} - - -void midway_ioasic_device::ioasic_reset() -{ - m_shuffle_active = m_shuffle_default; - m_sound_irq_state = 0x0080; - m_reg[IOASIC_INTCTL] = 0; - if (m_has_dcs) - fifo_reset_w(1); - update_ioasic_irq(); - midway_serial_pic_device::reset_w(1); -} - - -void midway_ioasic_device::update_ioasic_irq() -{ - uint16_t fifo_state = fifo_status_r(machine().dummy_space()); - uint16_t irqbits = 0x2000; - uint8_t new_state; - - irqbits |= m_sound_irq_state & 0xff; - irqbits |= m_reg[IOASIC_UARTIN] & 0x3f00; - if (fifo_state & 8) - irqbits |= 0x0008; - if (irqbits) - irqbits |= 0x0001; - - m_reg[IOASIC_INTSTAT] = irqbits; - - new_state = ((m_reg[IOASIC_INTCTL] & 0x0001) != 0) && ((m_reg[IOASIC_INTSTAT] & m_reg[IOASIC_INTCTL] & 0x3ffe) != 0); - if (new_state != m_irq_state) - { - m_irq_state = new_state; - if (!m_irq_callback.isnull()) - m_irq_callback(m_irq_state ? ASSERT_LINE : CLEAR_LINE); - if (m_irq_state && (m_reg[IOASIC_UARTIN] & 0x1000)) - logerror("IOASIC: Asserting IRQ INTCTRL=%04x INTSTAT=%04X\n", m_reg[IOASIC_INTCTL], m_reg[IOASIC_INTSTAT]); - } -} - - -void midway_ioasic_device::cage_irq_handler(uint8_t data) -{ - logerror("CAGE irq handler: %d\n", data); - m_sound_irq_state = 0; - if (data & atari_cage_device::CAGE_IRQ_REASON_DATA_READY) - m_sound_irq_state |= 0x0040; - if (data & atari_cage_device::CAGE_IRQ_REASON_BUFFER_EMPTY) - m_sound_irq_state |= 0x0080; - update_ioasic_irq(); -} - - -WRITE_LINE_MEMBER(midway_ioasic_device::ioasic_input_empty) -{ -// logerror("ioasic_input_empty(%d)\n", state); - if (state) - m_sound_irq_state |= 0x0080; - else - m_sound_irq_state &= ~0x0080; - update_ioasic_irq(); -} - - -WRITE_LINE_MEMBER(midway_ioasic_device::ioasic_output_full) -{ -// logerror("ioasic_output_full(%d)\n", state); - if (state) - m_sound_irq_state |= 0x0040; - else - m_sound_irq_state &= ~0x0040; - update_ioasic_irq(); -} - - - -/************************************* - * - * ASIC sound FIFO; used by CarnEvil - * - *************************************/ - -uint16_t midway_ioasic_device::fifo_r() -{ - uint16_t result = 0; - - /* we can only read data if there's some to read! */ - if (m_fifo_bytes != 0) - { - /* fetch the data from the buffer and update the IOASIC state */ - result = m_fifo[m_fifo_out++ % FIFO_SIZE]; - m_fifo_bytes--; - update_ioasic_irq(); - - if (LOG_FIFO && (m_fifo_bytes < 4 || m_fifo_bytes >= FIFO_SIZE - 4)) - logerror("fifo_r(%04X): FIFO bytes = %d!\n", result, m_fifo_bytes); - - /* if we just cleared the buffer, this may generate an IRQ on the master CPU */ - /* because of the way the streaming code works, we need to make sure that the */ - /* next status read indicates an empty buffer, even if we've timesliced and the */ - /* main CPU is handling the I/O ASIC interrupt */ - if (m_fifo_bytes == 0 && m_has_dcs) - { - m_fifo_force_buffer_empty_pc = m_dcs_cpu->pc(); - if (LOG_FIFO) - logerror("fifo_r(%04X): FIFO empty, PC = %04X\n", result, m_fifo_force_buffer_empty_pc); - } - } - else - { - if (LOG_FIFO) - logerror("fifo_r(): nothing to read!\n"); - } - return result; -} - - -uint16_t midway_ioasic_device::fifo_status_r(address_space &space) -{ - uint16_t result = 0; - - if (m_fifo_bytes == 0 && !m_force_fifo_full) - result |= 0x08; - if (m_fifo_bytes >= FIFO_SIZE/2) - result |= 0x10; - if (m_fifo_bytes >= FIFO_SIZE || m_force_fifo_full) - result |= 0x20; - - /* kludge alert: if we're reading this from the DCS CPU itself, and we recently cleared */ - /* the FIFO, and we're within 16 instructions of the read that cleared the FIFO, make */ - /* sure the FIFO clear bit is set */ - if (m_fifo_force_buffer_empty_pc && &space.device() == m_dcs_cpu) - { - offs_t currpc = m_dcs_cpu->pc(); - if (currpc >= m_fifo_force_buffer_empty_pc && currpc < m_fifo_force_buffer_empty_pc + 0x10) - { - m_fifo_force_buffer_empty_pc = 0; - result |= 0x08; - if (LOG_FIFO) - logerror("ioasic_fifo_status_r(%04X): force empty, PC = %04X\n", result, currpc); - } - } - - return result; -} - - -WRITE_LINE_MEMBER(midway_ioasic_device::fifo_reset_w) -{ - /* on the high state, reset the FIFO data */ - if (state) - { - m_fifo_in = 0; - m_fifo_out = 0; - m_fifo_bytes = 0; - m_force_fifo_full = 0; - update_ioasic_irq(); - } - if (LOG_FIFO) - logerror("%s:fifo_reset(%d)\n", machine().describe_context(), state); -} - - -void midway_ioasic_device::fifo_w(uint16_t data) -{ - /* if we have room, add it to the FIFO buffer */ - if (m_fifo_bytes < FIFO_SIZE) - { - m_fifo[m_fifo_in++ % FIFO_SIZE] = data; - m_fifo_bytes++; - update_ioasic_irq(); - if (LOG_FIFO && (m_fifo_bytes < 4 || m_fifo_bytes >= FIFO_SIZE - 4)) - logerror("fifo_w(%04X): FIFO bytes = %d!\n", data, m_fifo_bytes); - } - else - { - if (LOG_FIFO) - logerror("fifo_w(%04X): out of space!\n", data); - } - m_dcs->fifo_notify(m_fifo_bytes, FIFO_SIZE); -} - - -void midway_ioasic_device::fifo_full_w(uint16_t data) -{ - if (LOG_FIFO) - logerror("fifo_full_w(%04X)\n", data); - m_force_fifo_full = 1; - update_ioasic_irq(); - m_dcs->fifo_notify(m_fifo_bytes, FIFO_SIZE); -} - - - -/************************************* - * - * I/O ASIC master read/write - * - *************************************/ - -uint32_t midway_ioasic_device::packed_r(address_space &space, offs_t offset, uint32_t mem_mask) -{ - uint32_t result = 0; - if (ACCESSING_BITS_0_15) - result |= read(space, offset*2) & 0xffff; - if (ACCESSING_BITS_16_31) - result |= (read(space, offset*2+1) & 0xffff) << 16; - return result; -} - - -uint32_t midway_ioasic_device::read(address_space &space, offs_t offset) -{ - uint32_t result; - - offset = m_shuffle_active ? m_shuffle_map[offset & 15] : offset; - result = m_reg[offset]; - - switch (offset) - { - case IOASIC_PORT0: - // bit 0 is PIC ready flag before shuffling happens - // bits 15:13 == 001 - if (!m_shuffle_active) - { - /* blitz99 wants bit bits 13-15 to be 1 */ - result = 0x2001; - } - else { - result = m_io_dips->read(); - } - break; - - case IOASIC_PORT1: - result = m_io_system->read(); - break; - - case IOASIC_PORT2: - result = m_io_in1->read(); - break; - - case IOASIC_PORT3: - result = m_io_in2->read(); - break; - - case IOASIC_UARTIN: - m_reg[offset] &= ~0x1000; - if (result & 0x1000) - logerror("%s: ioasic_r(%d) = %08X\n", machine().describe_context(), offset, result); - // Add lf - if ((result & 0xff)==0x0d) - m_reg[offset] = 0x300a; - update_ioasic_irq(); - break; - - case IOASIC_SOUNDSTAT: - /* status from sound CPU */ - result = 0; - if (m_has_dcs) - { - result |= ((m_dcs->control_r() >> 4) ^ 0x40) & 0x00c0; - result |= fifo_status_r(space) & 0x0038; - result |= m_dcs->data2_r() & 0xff00; - } - else if (m_has_cage) - { - result |= (m_cage->control_r() << 6) ^ 0x80; - } - else - result |= 0x48; - break; - - case IOASIC_SOUNDIN: - result = 0; - if (m_has_dcs) - { - result = m_dcs->data_r(); - if (m_auto_ack) - m_dcs->ack_w(); - } - else if (m_has_cage) - result = m_cage->main_r(); - else - { - static uint16_t val = 0; - result = val = ~val; - } - break; - - case IOASIC_PICIN: - result = midway_serial_pic2_device::read() | (midway_serial_pic2_device::status_r() << 8); - break; - - default: - break; - } - - if (LOG_IOASIC && offset != IOASIC_SOUNDSTAT && offset != IOASIC_SOUNDIN) - logerror("%s:ioasic_r(%d) = %08X\n", machine().describe_context(), offset, result); - - return result; -} - - -void midway_ioasic_device::packed_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - if (ACCESSING_BITS_0_15) - write(offset*2, data & 0xffff, 0x0000ffff); - if (ACCESSING_BITS_16_31) - write(offset*2+1, data >> 16, 0x0000ffff); -} - -void midway_ioasic_device::serial_rx_w(u8 data) -{ - // Break Detect 0x0100 - // Frame Error 0x0200 - // Overrun 0x0400 - // Rx FIFO FULL 0x0800 - // Rx Ready 0x1000 - // Tx EMPTY 0x2000 - // CTS IN 0x4000 - // CTS OUT 0x8000 - if (m_reg[IOASIC_UARTCONTROL] & 0x200) { - m_reg[IOASIC_UARTIN] = data | 0x3000; - update_ioasic_irq(); - } - -} - -void midway_ioasic_device::write(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - uint32_t oldreg, newreg; - - offset = m_shuffle_active ? m_shuffle_map[offset & 15] : offset; - oldreg = m_reg[offset]; - // Block register updates until ioasic is unlocked - // mwskins and thegrid use this as test to see if the ioasic is unlocked - if (m_shuffle_active) - COMBINE_DATA(&m_reg[offset]); - newreg = m_reg[offset]; - - if (LOG_IOASIC && offset != IOASIC_SOUNDOUT) - logerror("%s ioasic_w(%d) = %08X\n", machine().describe_context(), offset, data); - - switch (offset) - { - case IOASIC_PORT0: - /* the last write here seems to turn on shuffling */ - if (data == 0xe2) - { - m_shuffle_active = 1; - logerror("*** I/O ASIC unlocked!\n"); - m_reg[IOASIC_INTCTL] = 0; - m_reg[IOASIC_UARTCONTROL] = 0; /* bug in 10th Degree assumes this */ - } - break; - - case IOASIC_PORT2: - case IOASIC_PORT3: - /* ignore writes here if we're not shuffling yet */ - if (!m_shuffle_active) - break; - break; - - case IOASIC_UARTCONTROL: - logerror("%s: IOASIC uart control = %04X INTCTRL=%04x\n", machine().describe_context(), data, m_reg[IOASIC_INTCTL]); - break; - - case IOASIC_UARTOUT: - if (m_reg[IOASIC_UARTCONTROL] & 0x800) - { - /* we're in loopback mode -- copy to the input */ - m_reg[IOASIC_UARTIN] = (newreg & 0x00ff) | 0x3000; - update_ioasic_irq(); - } - else { - m_serial_tx_cb(data); - m_reg[IOASIC_UARTIN] |= 0x2000; - update_ioasic_irq(); - if (PRINTF_DEBUG) { - osd_printf_info("%c", data & 0xff); - logerror("%c", data & 0xff); - } - } - //logerror("IOASIC uart tx data = %04X\n", data); - break; - - case IOASIC_SOUNDCTL: - if (LOG_IOASIC) - logerror("%s: write IOASIC_SOUNDCTL=%04x\n", machine().describe_context(), data); - /* sound reset? */ - if (m_has_dcs) - { - m_dcs->reset_w(newreg & 1); - } - else if (m_has_cage) - { - if ((oldreg ^ newreg) & 1) - { - m_cage->control_w(0); - if (!(~newreg & 1)) - m_cage->control_w(3); - } - } - - /* FIFO reset? */ - fifo_reset_w(~newreg & 4); - break; - - case IOASIC_SOUNDOUT: - if (m_has_dcs) - m_dcs->data_w(newreg); - else if (m_has_cage) - m_cage->main_w(newreg); - break; - - case IOASIC_SOUNDIN: - m_dcs->ack_w(); - /* acknowledge data read */ - break; - - case IOASIC_PICOUT: - if (m_shuffle_type == MIDWAY_IOASIC_VAPORTRX) - midway_serial_pic2_device::write(newreg ^ 0x0a); - else if (m_shuffle_type == MIDWAY_IOASIC_SFRUSHRK) - midway_serial_pic2_device::write(newreg ^ 0x05); - else - midway_serial_pic2_device::write(newreg); - break; - - case IOASIC_PICIN: - /* This is P15 on vegas boards */ - if (!m_aux_output_cb.isnull()) - m_aux_output_cb(data); - break; - - case IOASIC_INTCTL: - /* interrupt enables */ - /* bit 0 = global interrupt enable */ - /* bit 3 = FIFO empty */ - /* bit 6 = sound input buffer full */ - /* bit 7 = sound output buffer empty */ - /* bit 14 = LED */ - /* bit 15 = TI320Cx Mode Enable */ - if (LOG_IOASIC && ((oldreg ^ newreg) & 0x3ff6)) - logerror("IOASIC interrupt control = %04X\n", data); - update_ioasic_irq(); - break; - - default: - break; - } -} |