summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/machine/midwunit.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/machine/midwunit.c')
-rw-r--r--src/mame/machine/midwunit.c668
1 files changed, 668 insertions, 0 deletions
diff --git a/src/mame/machine/midwunit.c b/src/mame/machine/midwunit.c
new file mode 100644
index 00000000000..8bd63b8aa7d
--- /dev/null
+++ b/src/mame/machine/midwunit.c
@@ -0,0 +1,668 @@
+/*************************************************************************
+
+ Driver for Williams/Midway Wolf-unit games.
+
+**************************************************************************/
+
+#include "driver.h"
+#include "cpu/tms34010/tms34010.h"
+#include "cpu/m6809/m6809.h"
+#include "audio/dcs.h"
+#include "midwunit.h"
+#include "midwayic.h"
+
+
+/* code-related variables */
+ UINT8 * midwunit_decode_memory;
+
+/* CMOS-related variables */
+static UINT8 cmos_write_enable;
+
+/* I/O-related variables */
+static UINT16 iodata[8];
+static UINT8 ioshuffle[16];
+static UINT8 midxunit_analog_port;
+
+/* UART-related variables */
+static UINT8 uart[8];
+static UINT8 security_bits;
+
+/* prototype */
+static READ16_HANDLER( midwunit_sound_state_r );
+static void midxunit_dcs_output_full(int state);
+
+
+
+/*************************************
+ *
+ * State saving
+ *
+ *************************************/
+
+static void register_state_saving(void)
+{
+ state_save_register_global(cmos_write_enable);
+ state_save_register_global_array(iodata);
+ state_save_register_global_array(ioshuffle);
+ state_save_register_global(midxunit_analog_port);
+ state_save_register_global_array(uart);
+ state_save_register_global(security_bits);
+}
+
+
+
+/*************************************
+ *
+ * CMOS reads/writes
+ *
+ *************************************/
+
+WRITE16_HANDLER( midwunit_cmos_enable_w )
+{
+ cmos_write_enable = 1;
+}
+
+
+WRITE16_HANDLER( midwunit_cmos_w )
+{
+ if (cmos_write_enable)
+ {
+ COMBINE_DATA(generic_nvram16+offset);
+ cmos_write_enable = 0;
+ }
+ else
+ {
+ logerror("%08X:Unexpected CMOS W @ %05X\n", activecpu_get_pc(), offset);
+ popmessage("Bad CMOS write");
+ }
+}
+
+
+WRITE16_HANDLER( midxunit_cmos_w )
+{
+ COMBINE_DATA(generic_nvram16+offset);
+}
+
+
+READ16_HANDLER( midwunit_cmos_r )
+{
+ return generic_nvram16[offset];
+}
+
+
+
+/*************************************
+ *
+ * General I/O writes
+ *
+ *************************************/
+
+WRITE16_HANDLER( midwunit_io_w )
+{
+ int oldword, newword;
+
+ offset %= 8;
+ oldword = iodata[offset];
+ newword = oldword;
+ COMBINE_DATA(&newword);
+
+ switch (offset)
+ {
+ case 1:
+ logerror("%08X:Control W @ %05X = %04X\n", activecpu_get_pc(), offset, data);
+
+ /* bit 4 reset sound CPU */
+ dcs_reset_w(newword & 0x10);
+
+ /* bit 5 (active low) reset security chip */
+ midway_serial_pic_reset_w(newword & 0x20);
+ break;
+
+ case 3:
+ /* watchdog reset */
+ /* MK3 resets with this enabled */
+/* watchdog_reset_w(0,0);*/
+ break;
+
+ default:
+ logerror("%08X:Unknown I/O write to %d = %04X\n", activecpu_get_pc(), offset, data);
+ break;
+ }
+ iodata[offset] = newword;
+}
+
+
+WRITE16_HANDLER( midxunit_io_w )
+{
+ int oldword, newword;
+
+ offset = (offset / 2) % 8;
+ oldword = iodata[offset];
+ newword = oldword;
+ COMBINE_DATA(&newword);
+
+ switch (offset)
+ {
+ case 2:
+ /* watchdog reset */
+// watchdog_reset_w(0,0);
+ break;
+
+ default:
+ logerror("%08X:I/O write to %d = %04X\n", activecpu_get_pc(), offset, data);
+// logerror("%08X:Unknown I/O write to %d = %04X\n", activecpu_get_pc(), offset, data);
+ break;
+ }
+ iodata[offset] = newword;
+}
+
+
+WRITE16_HANDLER( midxunit_unknown_w )
+{
+ int offs = offset / 0x40000;
+ if (ACCESSING_LSB && offset % 0x40000 == 0)
+ logerror("%08X:midxunit_unknown_w @ %d = %02X\n", activecpu_get_pc(), offs, data & 0xff);
+}
+
+
+/*************************************
+ *
+ * General I/O reads
+ *
+ *************************************/
+
+READ16_HANDLER( midwunit_io_r )
+{
+ /* apply I/O shuffling */
+ offset = ioshuffle[offset % 16];
+
+ switch (offset)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ return readinputport(offset);
+
+ case 4:
+ return (midway_serial_pic_status_r() << 12) | midwunit_sound_state_r(0,0);
+
+ default:
+ logerror("%08X:Unknown I/O read from %d\n", activecpu_get_pc(), offset);
+ break;
+ }
+ return ~0;
+}
+
+
+READ16_HANDLER( midxunit_io_r )
+{
+ offset = (offset / 2) % 8;
+
+ switch (offset)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ return readinputport(offset);
+
+ default:
+ logerror("%08X:Unknown I/O read from %d\n", activecpu_get_pc(), offset);
+ break;
+ }
+ return ~0;
+}
+
+
+READ16_HANDLER( midxunit_analog_r )
+{
+ return readinputport(midxunit_analog_port);
+}
+
+
+WRITE16_HANDLER( midxunit_analog_select_w )
+{
+ if (offset == 0 && ACCESSING_LSB)
+ midxunit_analog_port = data - 8 + 4;
+}
+
+
+READ16_HANDLER( midxunit_status_r )
+{
+ /* low bit indicates whether the ADC is done reading the current input */
+ return (midway_serial_pic_status_r() << 1) | 1;
+}
+
+
+
+/*************************************
+ *
+ * Revolution X UART
+ *
+ *************************************/
+
+void midxunit_dcs_output_full(int state)
+{
+ /* only signal if not in loopback state */
+ if (uart[1] != 0x66)
+ cpunum_set_input_line(1, 1, state ? ASSERT_LINE : CLEAR_LINE);
+}
+
+
+READ16_HANDLER( midxunit_uart_r )
+{
+ int result = 0;
+
+ /* convert to a byte offset */
+ if (offset & 1)
+ return 0;
+ offset /= 2;
+
+ /* switch off the offset */
+ switch (offset)
+ {
+ case 0: /* register 0 must return 0x13 in order to pass the self test */
+ result = 0x13;
+ break;
+
+ case 1: /* register 1 contains the status */
+
+ /* loopback case: data always ready, and always ok to send */
+ if (uart[1] == 0x66)
+ result |= 5;
+
+ /* non-loopback case: bit 0 means data ready, bit 2 means ok to send */
+ else
+ {
+ int temp = midwunit_sound_state_r(0, 0);
+ result |= (temp & 0x800) >> 9;
+ result |= (~temp & 0x400) >> 10;
+ timer_call_after_resynch(0, 0);
+ }
+ break;
+
+ case 3: /* register 3 contains the data read */
+
+ /* loopback case: feed back last data wrtten */
+ if (uart[1] == 0x66)
+ result = uart[3];
+
+ /* non-loopback case: read from the DCS system */
+ else
+ result = midwunit_sound_r(0, 0);
+ break;
+
+ case 5: /* register 5 seems to be like 3, but with in/out swapped */
+
+ /* loopback case: data always ready, and always ok to send */
+ if (uart[1] == 0x66)
+ result |= 5;
+
+ /* non-loopback case: bit 0 means data ready, bit 2 means ok to send */
+ else
+ {
+ int temp = midwunit_sound_state_r(0, 0);
+ result |= (temp & 0x800) >> 11;
+ result |= (~temp & 0x400) >> 8;
+ timer_call_after_resynch(0, 0);
+ }
+ break;
+
+ default: /* everyone else reads themselves */
+ result = uart[offset];
+ break;
+ }
+
+/* logerror("%08X:UART R @ %X = %02X\n", activecpu_get_pc(), offset, result);*/
+ return result;
+}
+
+
+WRITE16_HANDLER( midxunit_uart_w )
+{
+ /* convert to a byte offset, ignoring MSB writes */
+ if ((offset & 1) || !ACCESSING_LSB)
+ return;
+ offset /= 2;
+ data &= 0xff;
+
+ /* switch off the offset */
+ switch (offset)
+ {
+ case 3: /* register 3 contains the data to be sent */
+
+ /* loopback case: don't feed through */
+ if (uart[1] == 0x66)
+ uart[3] = data;
+
+ /* non-loopback case: send to the DCS system */
+ else
+ midwunit_sound_w(0, data, mem_mask);
+ break;
+
+ case 5: /* register 5 write seems to reset things */
+ dcs_data_r();
+ break;
+
+ default: /* everyone else just stores themselves */
+ uart[offset] = data;
+ break;
+ }
+
+/* logerror("%08X:UART W @ %X = %02X\n", activecpu_get_pc(), offset, data);*/
+}
+
+
+
+/*************************************
+ *
+ * Generic driver init
+ *
+ *************************************/
+
+static void init_wunit_generic(void)
+{
+ UINT8 *base;
+ int i, j;
+
+ /* register for state saving */
+ register_state_saving();
+
+ /* load the graphics ROMs -- quadruples */
+ midyunit_gfx_rom = base = memory_region(REGION_GFX1);
+ for (i = 0; i < memory_region_length(REGION_GFX1) / 0x400000; i++)
+ {
+ memcpy(midwunit_decode_memory, base, 0x400000);
+ for (j = 0; j < 0x100000; j++)
+ {
+ *base++ = midwunit_decode_memory[0x000000 + j];
+ *base++ = midwunit_decode_memory[0x100000 + j];
+ *base++ = midwunit_decode_memory[0x200000 + j];
+ *base++ = midwunit_decode_memory[0x300000 + j];
+ }
+ }
+
+ /* init sound */
+ dcs_init();
+}
+
+
+
+
+/*************************************
+ *
+ * Wolf-unit init (DCS)
+ *
+ * music: ADSP2101
+ *
+ *************************************/
+
+/********************** Mortal Kombat 3 **********************/
+
+static void init_mk3_common(void)
+{
+ /* common init */
+ init_wunit_generic();
+
+ /* serial prefixes 439, 528 */
+ midway_serial_pic_init(528);
+}
+
+DRIVER_INIT( mk3 )
+{
+ init_mk3_common();
+}
+
+DRIVER_INIT( mk3r20 )
+{
+ init_mk3_common();
+}
+
+DRIVER_INIT( mk3r10 )
+{
+ init_mk3_common();
+}
+
+DRIVER_INIT( umk3 )
+{
+ init_mk3_common();
+}
+
+DRIVER_INIT( umk3r11 )
+{
+ init_mk3_common();
+}
+
+
+/********************** 2 On 2 Open Ice Challenge **********************/
+
+DRIVER_INIT( openice )
+{
+ /* common init */
+ init_wunit_generic();
+
+ /* serial prefixes 438, 528 */
+ midway_serial_pic_init(528);
+}
+
+
+/********************** NBA Hangtime & NBA Maximum Hangtime **********************/
+
+DRIVER_INIT( nbahangt )
+{
+ /* common init */
+ init_wunit_generic();
+
+ /* serial prefixes 459, 470, 528 */
+ midway_serial_pic_init(528);
+}
+
+
+/********************** WWF Wrestlemania **********************/
+
+static WRITE16_HANDLER( wwfmania_io_0_w )
+{
+ int i;
+
+ /* start with the originals */
+ for (i = 0; i < 16; i++)
+ ioshuffle[i] = i % 8;
+
+ /* based on the data written, shuffle */
+ switch (data)
+ {
+ case 0:
+ break;
+
+ case 1:
+ ioshuffle[4] = 0;
+ ioshuffle[8] = 1;
+ ioshuffle[1] = 2;
+ ioshuffle[9] = 3;
+ ioshuffle[2] = 4;
+ break;
+
+ case 2:
+ ioshuffle[8] = 0;
+ ioshuffle[2] = 1;
+ ioshuffle[4] = 2;
+ ioshuffle[6] = 3;
+ ioshuffle[1] = 4;
+ break;
+
+ case 3:
+ ioshuffle[1] = 0;
+ ioshuffle[8] = 1;
+ ioshuffle[2] = 2;
+ ioshuffle[10] = 3;
+ ioshuffle[5] = 4;
+ break;
+
+ case 4:
+ ioshuffle[2] = 0;
+ ioshuffle[4] = 1;
+ ioshuffle[1] = 2;
+ ioshuffle[7] = 3;
+ ioshuffle[8] = 4;
+ break;
+ }
+ logerror("Changed I/O swiching to %d\n", data);
+}
+
+DRIVER_INIT( wwfmania )
+{
+ /* common init */
+ init_wunit_generic();
+
+ /* enable I/O shuffling */
+ memory_install_write16_handler(0, ADDRESS_SPACE_PROGRAM, 0x01800000, 0x0180000f, 0, 0, wwfmania_io_0_w);
+
+ /* serial prefixes 430, 528 */
+ midway_serial_pic_init(528);
+}
+
+
+/********************** Rampage World Tour **********************/
+
+DRIVER_INIT( rmpgwt )
+{
+ /* common init */
+ init_wunit_generic();
+
+ /* serial prefixes 465, 528 */
+ midway_serial_pic_init(528);
+}
+
+
+/********************** Revolution X **********************/
+
+DRIVER_INIT( revx )
+{
+ UINT8 *base;
+ int i, j;
+
+ /* register for state saving */
+ register_state_saving();
+
+ /* load the graphics ROMs -- quadruples */
+ midyunit_gfx_rom = base = memory_region(REGION_GFX1);
+ for (i = 0; i < memory_region_length(REGION_GFX1) / 0x200000; i++)
+ {
+ memcpy(midwunit_decode_memory, base, 0x200000);
+ for (j = 0; j < 0x80000; j++)
+ {
+ *base++ = midwunit_decode_memory[0x000000 + j];
+ *base++ = midwunit_decode_memory[0x080000 + j];
+ *base++ = midwunit_decode_memory[0x100000 + j];
+ *base++ = midwunit_decode_memory[0x180000 + j];
+ }
+ }
+
+ /* init sound */
+ dcs_init();
+
+ /* serial prefixes 419, 420 */
+ midway_serial_pic_init(419);
+}
+
+
+
+/*************************************
+ *
+ * Machine init
+ *
+ *************************************/
+
+MACHINE_RESET( midwunit )
+{
+ int i;
+
+ /* reset sound */
+ dcs_reset_w(1);
+ dcs_reset_w(0);
+
+ /* reset I/O shuffling */
+ for (i = 0; i < 16; i++)
+ ioshuffle[i] = i % 8;
+}
+
+
+MACHINE_RESET( midxunit )
+{
+ machine_reset_midwunit(machine);
+ dcs_set_io_callbacks(midxunit_dcs_output_full, NULL);
+}
+
+
+
+/*************************************
+ *
+ * Security chip I/O
+ *
+ *************************************/
+
+READ16_HANDLER( midwunit_security_r )
+{
+ return midway_serial_pic_r();
+}
+
+
+WRITE16_HANDLER( midwunit_security_w )
+{
+ if (offset == 0 && ACCESSING_LSB)
+ midway_serial_pic_w(data);
+}
+
+
+WRITE16_HANDLER( midxunit_security_w )
+{
+ if (ACCESSING_LSB)
+ security_bits = data & 0x0f;
+}
+
+
+WRITE16_HANDLER( midxunit_security_clock_w )
+{
+ if (offset == 0 && ACCESSING_LSB)
+ midway_serial_pic_w(((~data & 2) << 3) | security_bits);
+}
+
+
+
+/*************************************
+ *
+ * Sound write handlers
+ *
+ *************************************/
+
+READ16_HANDLER( midwunit_sound_r )
+{
+ logerror("%08X:Sound read\n", activecpu_get_pc());
+
+ return dcs_data_r() & 0xff;
+}
+
+
+READ16_HANDLER( midwunit_sound_state_r )
+{
+ return dcs_control_r();
+}
+
+
+WRITE16_HANDLER( midwunit_sound_w )
+{
+ /* check for out-of-bounds accesses */
+ if (offset)
+ {
+ logerror("%08X:Unexpected write to sound (hi) = %04X\n", activecpu_get_pc(), data);
+ return;
+ }
+
+ /* call through based on the sound type */
+ if (ACCESSING_LSB)
+ {
+ logerror("%08X:Sound write = %04X\n", activecpu_get_pc(), data);
+ dcs_data_w(data & 0xff);
+ }
+}