summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/machine/midyunit.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/machine/midyunit.c')
-rw-r--r--src/mame/machine/midyunit.c578
1 files changed, 578 insertions, 0 deletions
diff --git a/src/mame/machine/midyunit.c b/src/mame/machine/midyunit.c
new file mode 100644
index 00000000000..868fa40b56e
--- /dev/null
+++ b/src/mame/machine/midyunit.c
@@ -0,0 +1,578 @@
+/*************************************************************************
+
+ Williams/Midway Y/Z-unit system
+
+**************************************************************************/
+
+#include "driver.h"
+#include "cpu/tms34010/tms34010.h"
+#include "cpu/m6809/m6809.h"
+#include "machine/6821pia.h"
+#include "audio/williams.h"
+#include "midyunit.h"
+
+
+/* constant definitions */
+#define SOUND_NARC 1
+#define SOUND_CVSD_SMALL 2
+#define SOUND_CVSD 3
+#define SOUND_ADPCM 4
+#define SOUND_YAWDIM 5
+
+
+/* protection data types */
+struct protection_data
+{
+ UINT16 reset_sequence[3];
+ UINT16 data_sequence[100];
+};
+static const struct protection_data *prot_data;
+static UINT16 prot_result;
+static UINT16 prot_sequence[3];
+static UINT8 prot_index;
+
+
+/* input-related variables */
+static UINT8 term2_analog_select;
+
+/* CMOS-related variables */
+ UINT16 *midyunit_cmos_ram;
+ UINT32 midyunit_cmos_page;
+static UINT8 cmos_w_enable;
+
+/* sound-related variables */
+static UINT8 chip_type;
+
+/* hack-related variables */
+static UINT16 *t2_hack_mem;
+
+
+
+/*************************************
+ *
+ * CMOS reads/writes
+ *
+ *************************************/
+
+WRITE16_HANDLER( midyunit_cmos_w )
+{
+ logerror("%08x:CMOS Write @ %05X\n", activecpu_get_pc(), offset);
+ COMBINE_DATA(&midyunit_cmos_ram[offset + midyunit_cmos_page]);
+}
+
+
+READ16_HANDLER( midyunit_cmos_r )
+{
+ return midyunit_cmos_ram[offset + midyunit_cmos_page];
+}
+
+
+
+/*************************************
+ *
+ * CMOS enable and protection
+ *
+ *************************************/
+
+WRITE16_HANDLER( midyunit_cmos_enable_w )
+{
+ cmos_w_enable = (~data >> 9) & 1;
+
+ logerror("%08x:Protection write = %04X\n", activecpu_get_pc(), data);
+
+ /* only go down this path if we have a data structure */
+ if (prot_data)
+ {
+ /* mask off the data */
+ data &= 0x0f00;
+
+ /* update the FIFO */
+ prot_sequence[0] = prot_sequence[1];
+ prot_sequence[1] = prot_sequence[2];
+ prot_sequence[2] = data;
+
+ /* special case: sequence entry 1234 means Strike Force, which is different */
+ if (prot_data->reset_sequence[0] == 0x1234)
+ {
+ if (data == 0x500)
+ {
+ prot_result = program_read_word(TOBYTE(0x10a4390)) << 4;
+ logerror(" desired result = %04X\n", prot_result);
+ }
+ }
+
+ /* all other games use the same pattern */
+ else
+ {
+ /* look for a reset */
+ if (prot_sequence[0] == prot_data->reset_sequence[0] &&
+ prot_sequence[1] == prot_data->reset_sequence[1] &&
+ prot_sequence[2] == prot_data->reset_sequence[2])
+ {
+ logerror("Protection reset\n");
+ prot_index = 0;
+ }
+
+ /* look for a clock */
+ if ((prot_sequence[1] & 0x0800) != 0 && (prot_sequence[2] & 0x0800) == 0)
+ {
+ prot_result = prot_data->data_sequence[prot_index++];
+ logerror("Protection clock (new data = %04X)\n", prot_result);
+ }
+ }
+ }
+}
+
+
+READ16_HANDLER( midyunit_protection_r )
+{
+ /* return the most recently clocked value */
+ logerror("%08X:Protection read = %04X\n", activecpu_get_pc(), prot_result);
+ return prot_result;
+}
+
+
+
+/*************************************
+ *
+ * Generic input ports
+ *
+ *************************************/
+
+READ16_HANDLER( midyunit_input_r )
+{
+ return readinputport(offset);
+}
+
+
+
+/*************************************
+ *
+ * Special Terminator 2 input ports
+ *
+ *************************************/
+
+static READ16_HANDLER( term2_input_r )
+{
+ if (offset != 2)
+ return readinputport(offset);
+
+ switch (term2_analog_select)
+ {
+ default:
+ case 0: return readinputport(2); break;
+ case 1: return readinputport(6); break;
+ case 2: return readinputport(7); break;
+ case 3: return readinputport(8); break;
+ }
+}
+
+static WRITE16_HANDLER( term2_sound_w )
+{
+ if (offset == 0)
+ term2_analog_select = (data >> 0x0c) & 0x03;
+
+ williams_adpcm_data_w(data);
+}
+
+
+
+/*************************************
+ *
+ * Special Terminator 2 hack
+ *
+ *************************************/
+
+static WRITE16_HANDLER( term2_hack_w )
+{
+ if (offset == 0 && activecpu_get_pc() == 0xffce5230)
+ {
+ t2_hack_mem[offset] = 0;
+ return;
+ }
+ COMBINE_DATA(&t2_hack_mem[offset]);
+}
+
+static WRITE16_HANDLER( term2la2_hack_w )
+{
+ if (offset == 0 && activecpu_get_pc() == 0xffce4b80)
+ {
+ t2_hack_mem[offset] = 0;
+ return;
+ }
+ COMBINE_DATA(&t2_hack_mem[offset]);
+}
+
+static WRITE16_HANDLER( term2la1_hack_w )
+{
+ if (offset == 0 && activecpu_get_pc() == 0xffce33f0)
+ {
+ t2_hack_mem[offset] = 0;
+ return;
+ }
+ COMBINE_DATA(&t2_hack_mem[offset]);
+}
+
+
+
+/*************************************
+ *
+ * Generic driver init
+ *
+ *************************************/
+
+static UINT8 *cvsd_protection_base;
+static WRITE8_HANDLER( cvsd_protection_w )
+{
+ /* because the entire CVSD ROM is banked, we have to make sure that writes */
+ /* go to the proper location (i.e., bank 0); currently bank 0 always lives */
+ /* in the 0x10000-0x17fff space, so we just need to add 0x8000 to get the */
+ /* proper offset */
+ cvsd_protection_base[offset] = data;
+}
+
+
+static void init_generic(int bpp, int sound, int prot_start, int prot_end)
+{
+ offs_t gfx_chunk = midyunit_gfx_rom_size / 4;
+ UINT8 d1, d2, d3, d4, d5, d6;
+ UINT8 *base;
+ int i;
+
+ /* load graphics ROMs */
+ base = memory_region(REGION_GFX1);
+ switch (bpp)
+ {
+ case 4:
+ for (i = 0; i < midyunit_gfx_rom_size; i += 2)
+ {
+ d1 = ((base[0 * gfx_chunk + (i + 0) / 4]) >> (2 * ((i + 0) % 4))) & 3;
+ d2 = ((base[1 * gfx_chunk + (i + 0) / 4]) >> (2 * ((i + 0) % 4))) & 3;
+ d3 = ((base[0 * gfx_chunk + (i + 1) / 4]) >> (2 * ((i + 1) % 4))) & 3;
+ d4 = ((base[1 * gfx_chunk + (i + 1) / 4]) >> (2 * ((i + 1) % 4))) & 3;
+
+ midyunit_gfx_rom[i + 0] = d1 | (d2 << 2);
+ midyunit_gfx_rom[i + 1] = d3 | (d4 << 2);
+ }
+ break;
+
+ case 6:
+ for (i = 0; i < midyunit_gfx_rom_size; i += 2)
+ {
+ d1 = ((base[0 * gfx_chunk + (i + 0) / 4]) >> (2 * ((i + 0) % 4))) & 3;
+ d2 = ((base[1 * gfx_chunk + (i + 0) / 4]) >> (2 * ((i + 0) % 4))) & 3;
+ d3 = ((base[2 * gfx_chunk + (i + 0) / 4]) >> (2 * ((i + 0) % 4))) & 3;
+ d4 = ((base[0 * gfx_chunk + (i + 1) / 4]) >> (2 * ((i + 1) % 4))) & 3;
+ d5 = ((base[1 * gfx_chunk + (i + 1) / 4]) >> (2 * ((i + 1) % 4))) & 3;
+ d6 = ((base[2 * gfx_chunk + (i + 1) / 4]) >> (2 * ((i + 1) % 4))) & 3;
+
+ midyunit_gfx_rom[i + 0] = d1 | (d2 << 2) | (d3 << 4);
+ midyunit_gfx_rom[i + 1] = d4 | (d5 << 2) | (d6 << 4);
+ }
+ break;
+
+ case 8:
+ for (i = 0; i < midyunit_gfx_rom_size; i += 4)
+ {
+ midyunit_gfx_rom[i + 0] = base[0 * gfx_chunk + i / 4];
+ midyunit_gfx_rom[i + 1] = base[1 * gfx_chunk + i / 4];
+ midyunit_gfx_rom[i + 2] = base[2 * gfx_chunk + i / 4];
+ midyunit_gfx_rom[i + 3] = base[3 * gfx_chunk + i / 4];
+ }
+ break;
+ }
+
+ /* load sound ROMs and set up sound handlers */
+ chip_type = sound;
+ switch (sound)
+ {
+ case SOUND_CVSD_SMALL:
+ williams_cvsd_init(0);
+ memory_install_write8_handler(1, ADDRESS_SPACE_PROGRAM, prot_start, prot_end, 0, 0, cvsd_protection_w);
+ cvsd_protection_base = memory_region(REGION_CPU2) + 0x10000 + (prot_start - 0x8000);
+ break;
+
+ case SOUND_CVSD:
+ williams_cvsd_init(0);
+ memory_install_write8_handler(1, ADDRESS_SPACE_PROGRAM, prot_start, prot_end, 0, 0, MWA8_RAM);
+ break;
+
+ case SOUND_ADPCM:
+ williams_adpcm_init();
+ memory_install_write8_handler(1, ADDRESS_SPACE_PROGRAM, prot_start, prot_end, 0, 0, MWA8_RAM);
+ break;
+
+ case SOUND_NARC:
+ williams_narc_init();
+ memory_install_write8_handler(1, ADDRESS_SPACE_PROGRAM, prot_start, prot_end, 0, 0, MWA8_RAM);
+ break;
+
+ case SOUND_YAWDIM:
+ break;
+ }
+}
+
+
+
+/*************************************
+ *
+ * Z-unit init
+ *
+ * music: 6809 driving YM2151, DAC
+ * effects: 6809 driving CVSD, DAC
+ *
+ *************************************/
+
+DRIVER_INIT( narc )
+{
+ /* common init */
+ init_generic(8, SOUND_NARC, 0xcdff, 0xce29);
+}
+
+
+/*************************************
+ *
+ * Y-unit init (CVSD)
+ *
+ * music: 6809 driving YM2151, DAC, and CVSD
+ *
+ *************************************/
+
+
+/********************** Trog **************************/
+
+DRIVER_INIT( trog )
+{
+ /* protection */
+ static const struct protection_data trog_protection_data =
+ {
+ { 0x0f00, 0x0f00, 0x0f00 },
+ { 0x3000, 0x1000, 0x2000, 0x0000,
+ 0x2000, 0x3000,
+ 0x3000, 0x1000,
+ 0x0000, 0x0000, 0x2000, 0x3000, 0x1000, 0x1000, 0x2000 }
+ };
+ prot_data = &trog_protection_data;
+
+ /* common init */
+ init_generic(4, SOUND_CVSD_SMALL, 0x9eaf, 0x9ed9);
+}
+
+
+/********************** Smash TV **********************/
+
+DRIVER_INIT( smashtv )
+{
+ /* common init */
+ init_generic(6, SOUND_CVSD_SMALL, 0x9cf6, 0x9d21);
+}
+
+
+/********************** High Impact Football **********************/
+
+DRIVER_INIT( hiimpact )
+{
+ /* protection */
+ static const struct protection_data hiimpact_protection_data =
+ {
+ { 0x0b00, 0x0b00, 0x0b00 },
+ { 0x2000, 0x4000, 0x4000, 0x0000, 0x6000, 0x6000, 0x2000, 0x4000,
+ 0x2000, 0x4000, 0x2000, 0x0000, 0x4000, 0x6000, 0x2000 }
+ };
+ prot_data = &hiimpact_protection_data;
+
+ /* common init */
+ init_generic(6, SOUND_CVSD, 0x9b79, 0x9ba3);
+}
+
+
+/********************** Super High Impact Football **********************/
+
+DRIVER_INIT( shimpact )
+{
+ /* protection */
+ static const struct protection_data shimpact_protection_data =
+ {
+ { 0x0f00, 0x0e00, 0x0d00 },
+ { 0x0000, 0x4000, 0x2000, 0x5000, 0x2000, 0x1000, 0x4000, 0x6000,
+ 0x3000, 0x0000, 0x2000, 0x5000, 0x5000, 0x5000, 0x2000 }
+ };
+ prot_data = &shimpact_protection_data;
+
+ /* common init */
+ init_generic(6, SOUND_CVSD, 0x9c06, 0x9c15);
+}
+
+
+/********************** Strike Force **********************/
+
+DRIVER_INIT( strkforc )
+{
+ /* protection */
+ static const struct protection_data strkforc_protection_data =
+ {
+ { 0x1234 }
+ };
+ prot_data = &strkforc_protection_data;
+
+ /* common init */
+ init_generic(4, SOUND_CVSD_SMALL, 0x9f7d, 0x9fa7);
+}
+
+
+
+/*************************************
+ *
+ * Y-unit init (ADPCM)
+ *
+ * music: 6809 driving YM2151, DAC, and OKIM6295
+ *
+ *************************************/
+
+
+/********************** Mortal Kombat **********************/
+
+DRIVER_INIT( mkyunit )
+{
+ /* protection */
+ static const struct protection_data mk_protection_data =
+ {
+ { 0x0d00, 0x0c00, 0x0900 },
+ { 0x4600, 0xf600, 0xa600, 0x0600, 0x2600, 0x9600, 0xc600, 0xe600,
+ 0x8600, 0x7600, 0x8600, 0x8600, 0x9600, 0xd600, 0x6600, 0xb600,
+ 0xd600, 0xe600, 0xf600, 0x7600, 0xb600, 0xa600, 0x3600 }
+ };
+ prot_data = &mk_protection_data;
+
+ /* common init */
+ init_generic(6, SOUND_ADPCM, 0xfb9c, 0xfbc6);
+}
+
+DRIVER_INIT( mkyawdim )
+{
+ /* common init */
+ init_generic(6, SOUND_YAWDIM, 0, 0);
+}
+
+
+/********************** Terminator 2 **********************/
+
+static void term2_init_common(write16_handler hack_w)
+{
+ /* protection */
+ static const struct protection_data term2_protection_data =
+ {
+ { 0x0f00, 0x0f00, 0x0f00 },
+ { 0x4000, 0xf000, 0xa000 }
+ };
+ prot_data = &term2_protection_data;
+
+ /* common init */
+ init_generic(6, SOUND_ADPCM, 0xfa8d, 0xfa9c);
+
+ /* special inputs */
+ memory_install_read16_handler(0, ADDRESS_SPACE_PROGRAM, 0x01c00000, 0x01c0005f, 0, 0, term2_input_r);
+ memory_install_write16_handler(0, ADDRESS_SPACE_PROGRAM, 0x01e00000, 0x01e0001f, 0, 0, term2_sound_w);
+
+ /* HACK: this prevents the freeze on the movies */
+ /* until we figure whats causing it, this is better than nothing */
+ t2_hack_mem = memory_install_write16_handler(0, ADDRESS_SPACE_PROGRAM, 0x010aa0e0, 0x010aa0ff, 0, 0, hack_w);
+}
+
+DRIVER_INIT( term2 ) { term2_init_common(term2_hack_w); }
+DRIVER_INIT( term2la2 ) { term2_init_common(term2la2_hack_w); }
+DRIVER_INIT( term2la1 ) { term2_init_common(term2la1_hack_w); }
+
+
+
+/********************** Total Carnage **********************/
+
+DRIVER_INIT( totcarn )
+{
+ /* protection */
+ static const struct protection_data totcarn_protection_data =
+ {
+ { 0x0f00, 0x0f00, 0x0f00 },
+ { 0x4a00, 0x6a00, 0xda00, 0x6a00, 0x9a00, 0x4a00, 0x2a00, 0x9a00, 0x1a00,
+ 0x8a00, 0xaa00 }
+ };
+ prot_data = &totcarn_protection_data;
+
+ /* common init */
+ init_generic(6, SOUND_ADPCM, 0xfc04, 0xfc2e);
+}
+
+
+
+/*************************************
+ *
+ * Machine init
+ *
+ *************************************/
+
+MACHINE_RESET( midyunit )
+{
+ /* reset sound */
+ switch (chip_type)
+ {
+ case SOUND_NARC:
+ williams_narc_reset_w(1);
+ williams_narc_reset_w(0);
+ break;
+
+ case SOUND_CVSD:
+ case SOUND_CVSD_SMALL:
+ williams_cvsd_reset_w(1);
+ williams_cvsd_reset_w(0);
+ break;
+
+ case SOUND_ADPCM:
+ williams_adpcm_reset_w(1);
+ williams_adpcm_reset_w(0);
+ break;
+
+ case SOUND_YAWDIM:
+ break;
+ }
+}
+
+
+
+/*************************************
+ *
+ * Sound write handlers
+ *
+ *************************************/
+
+WRITE16_HANDLER( midyunit_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 && ACCESSING_MSB)
+ switch (chip_type)
+ {
+ case SOUND_NARC:
+ williams_narc_data_w(data);
+ break;
+
+ case SOUND_CVSD_SMALL:
+ case SOUND_CVSD:
+ williams_cvsd_data_w((data & 0xff) | ((data & 0x200) >> 1));
+ break;
+
+ case SOUND_ADPCM:
+ williams_adpcm_data_w(data);
+ break;
+
+ case SOUND_YAWDIM:
+ soundlatch_w(0, data);
+ cpunum_set_input_line(1, INPUT_LINE_NMI, PULSE_LINE);
+ break;
+ }
+}