diff options
Diffstat (limited to 'src/mame/machine/midwunit.c')
-rw-r--r-- | src/mame/machine/midwunit.c | 668 |
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); + } +} |