summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/machine/mexico86.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/machine/mexico86.c')
-rw-r--r--src/mame/machine/mexico86.c334
1 files changed, 334 insertions, 0 deletions
diff --git a/src/mame/machine/mexico86.c b/src/mame/machine/mexico86.c
new file mode 100644
index 00000000000..bb5dd1fbfff
--- /dev/null
+++ b/src/mame/machine/mexico86.c
@@ -0,0 +1,334 @@
+#include "driver.h"
+
+
+UINT8 *mexico86_protection_ram;
+
+
+static int kikikai_mcu_running, kikikai_mcu_initialised;
+
+
+/*
+$f008 - write
+bit 7 = ? (unused?)
+bit 6 = ? (unused?)
+bit 5 = ? (unused?)
+bit 4 = ? (usually set in game)
+bit 3 = ? (usually set in game)
+bit 2 = sound cpu reset line
+bit 1 = microcontroller reset line
+bit 0 = ? (unused?)
+*/
+WRITE8_HANDLER( mexico86_f008_w )
+{
+ cpunum_set_input_line(1, INPUT_LINE_RESET, (data & 4) ? CLEAR_LINE : ASSERT_LINE);
+ if (Machine->drv->cpu[2].type != CPU_DUMMY)
+ {
+ // mexico 86, knight boy
+ cpunum_set_input_line(2, INPUT_LINE_RESET, (data & 2) ? CLEAR_LINE : ASSERT_LINE);
+ }
+ else
+ {
+ // simulation for KiKi KaiKai
+ kikikai_mcu_running = data & 2;
+ if (!kikikai_mcu_running)
+ kikikai_mcu_initialised = 0;
+ }
+}
+
+
+/***************************************************************************
+
+ KiKi KaiKai MCU simulation
+
+ This is derived from examination of the bootleg 68705 MCU code, with an
+ addition to fix collision detection which is missing from the bootleg.
+
+***************************************************************************/
+
+static void mcu_simulate(void)
+{
+ if (!kikikai_mcu_initialised)
+ {
+ if (mexico86_protection_ram[0x01] == 0x00)
+ {
+logerror("initialising MCU\n");
+ mexico86_protection_ram[0x04] = 0xfc; // coin inputs
+ mexico86_protection_ram[0x02] = 0xff; // player 1
+ mexico86_protection_ram[0x03] = 0xff; // player 2
+ mexico86_protection_ram[0x1b] = 0xff; // active player
+ mexico86_protection_ram[0x06] = 0xff; // must be FF otherwise PS4 ERROR
+ mexico86_protection_ram[0x07] = 0x03; // must be 03 otherwise PS4 ERROR
+ mexico86_protection_ram[0x00] = 0x00;
+ kikikai_mcu_initialised = 1;
+ }
+ }
+
+ if (kikikai_mcu_initialised)
+ {
+ int i;
+ static int coin_last;
+ int coin_curr;
+
+
+ coin_curr = ~readinputport(0) & 1;
+ if (coin_curr && !coin_last && mexico86_protection_ram[0x01] < 9)
+ {
+ mexico86_protection_ram[0x01]++; // increase credits counter
+ mexico86_protection_ram[0x0a] = 0x01; // set flag (coin inserted sound is not played otherwise)
+ }
+ coin_last = coin_curr;
+
+ mexico86_protection_ram[0x04] = 0x3c; // coin inputs
+
+ mexico86_protection_ram[0x02] = BITSWAP8(readinputport(1), 7,6,5,4,2,3,1,0); // player 1
+ mexico86_protection_ram[0x03] = BITSWAP8(readinputport(2), 7,6,5,4,2,3,1,0); // player 2
+
+ if (mexico86_protection_ram[0x19] == 0xaa) // player 2 active
+ mexico86_protection_ram[0x1b] = mexico86_protection_ram[0x03];
+ else
+ mexico86_protection_ram[0x1b] = mexico86_protection_ram[0x02];
+
+
+ for (i = 0; i < 0x10; i += 2)
+ mexico86_protection_ram[i + 0xb1] = mexico86_protection_ram[i + 0xb0];
+
+ for (i = 0; i < 0x0a; i++)
+ mexico86_protection_ram[i + 0xc0] = mexico86_protection_ram[i + 0x90] + 1;
+
+ if (mexico86_protection_ram[0xd1] == 0xff)
+ {
+ if (mexico86_protection_ram[0xd0] > 0 && mexico86_protection_ram[0xd0] < 4)
+ {
+ mexico86_protection_ram[0xd2] = 0x81;
+ mexico86_protection_ram[0xd0] = 0xff;
+ }
+ }
+
+
+ if (mexico86_protection_ram[0xe0] > 0 && mexico86_protection_ram[0xe0] < 4)
+ {
+ static UINT8 answers[3][16] =
+ {
+ { 0x00,0x40,0x48,0x50,0x58,0x60,0x68,0x70,0x78,0x80,0x88,0x00,0x00,0x00,0x00,0x00 },
+ { 0x00,0x04,0x08,0x0C,0x10,0x14,0x18,0x1C,0x20,0x31,0x2B,0x35,0x00,0x00,0x00,0x00 },
+ { 0x00,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,0x03,0x0A,0x0B,0x14,0x00,0x00,0x00,0x00 },
+ };
+ int table = mexico86_protection_ram[0xe0] - 1;
+
+ for (i = 1; i < 0x10; i++)
+ mexico86_protection_ram[0xe0 + i] = answers[table][i];
+ mexico86_protection_ram[0xe0] = 0xff;
+ }
+
+ if (mexico86_protection_ram[0xf0] > 0 && mexico86_protection_ram[0xf0] < 4)
+ {
+ mexico86_protection_ram[0xf1] = 0xb3;
+ mexico86_protection_ram[0xf0] = 0xff;
+ }
+
+
+ // The following is missing from Knight Boy
+ // this should be equivalent to the obfuscated kiki_clogic() below
+ {
+ static int db[16]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x10,0x18,0x00,0x00,0x00,0x00};
+ int sy = mexico86_protection_ram[0xa0] + ((0x18)>>1);
+ int sx = mexico86_protection_ram[0xa1] + ((0x18)>>1);
+
+ for (i = 0; i < 0x38; i += 8)
+ {
+ int hw = db[mexico86_protection_ram[0x20 + i] & 0xf];
+
+ if (hw)
+ {
+ if (abs(sx - (mexico86_protection_ram[0x20 + i+6] * 256 + mexico86_protection_ram[0x20 + i+7])) < hw &&
+ abs(sy - (mexico86_protection_ram[0x20 + i+4] * 256 + mexico86_protection_ram[0x20 + i+5])) < hw)
+ mexico86_protection_ram[0xa2] = 1; // we have a collision
+ }
+ }
+ }
+ }
+}
+
+
+INTERRUPT_GEN( kikikai_interrupt )
+{
+ if (kikikai_mcu_running)
+ mcu_simulate();
+
+ cpunum_set_input_line_vector(0,0,mexico86_protection_ram[0]);
+ cpunum_set_input_line(0,0,HOLD_LINE);
+}
+
+
+
+#if 0
+//AT
+/***************************************************************************
+
+ Collision logic used by Kiki Kaikai (theoretical)
+
+***************************************************************************/
+#define KIKI_CL_OUT 0xa2
+#define KIKI_CL_TRIGGER 0xa3
+#define DCWIDTH 0
+#define DCHEIGHT 0
+
+static void kiki_clogic(int address, int latch)
+{
+ static UINT8 db[16]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x10,0x18,0x00,0x00,0x00,0x00};
+ static UINT8 queue[64];
+ static int qfront = 0, state = 0;
+ int sy, sx, hw, i, qptr, diff1, diff2;
+
+ if (address != KIKI_CL_TRIGGER) // queue latched data
+ {
+ queue[qfront++] = latch;
+ qfront &= 0x3f;
+ }
+ else if (state ^= 1) // scan queue
+ {
+ sy = queue[(qfront-0x3a)&0x3f] + ((0x18-DCHEIGHT)>>1);
+ sx = queue[(qfront-0x39)&0x3f] + ((0x18-DCWIDTH)>>1);
+
+ for (i=0x38; i; i-=8)
+ {
+ qptr = qfront - i;
+ if (!(hw = db[queue[qptr&0x3f]&0xf])) continue;
+
+ diff1 = sx - (short)(queue[(qptr+6)&0x3f]<<8|queue[(qptr+7)&0x3f]) + DCWIDTH;
+ diff2 = diff1 - (hw + DCWIDTH);
+ if ((diff1^diff2)<0)
+ {
+ diff1 = sy - (short)(queue[(qptr+4)&0x3f]<<8|queue[(qptr+5)&0x3f]) + DCHEIGHT;
+ diff2 = diff1 - (hw + DCHEIGHT);
+ if ((diff1^diff2)<0)
+ mexico86_protection_ram[KIKI_CL_OUT] = 1; // we have a collision
+ }
+ }
+ }
+}
+//ZT
+#endif
+
+
+/***************************************************************************
+
+ Mexico 86 68705 protection interface
+
+ The following is ENTIRELY GUESSWORK!!!
+
+***************************************************************************/
+
+INTERRUPT_GEN( mexico86_m68705_interrupt )
+{
+ /* I don't know how to handle the interrupt line so I just toggle it every time. */
+ if (cpu_getiloops() & 1)
+ cpunum_set_input_line(2,0,CLEAR_LINE);
+ else
+ cpunum_set_input_line(2,0,ASSERT_LINE);
+}
+
+
+
+static UINT8 portA_in,portA_out,ddrA;
+
+READ8_HANDLER( mexico86_68705_portA_r )
+{
+//logerror("%04x: 68705 port A read %02x\n",activecpu_get_pc(),portA_in);
+ return (portA_out & ddrA) | (portA_in & ~ddrA);
+}
+
+WRITE8_HANDLER( mexico86_68705_portA_w )
+{
+//logerror("%04x: 68705 port A write %02x\n",activecpu_get_pc(),data);
+ portA_out = data;
+}
+
+WRITE8_HANDLER( mexico86_68705_ddrA_w )
+{
+ ddrA = data;
+}
+
+
+
+/*
+ * Port B connections:
+ *
+ * all bits are logical 1 when read (+5V pullup)
+ *
+ * 0 W enables latch which holds data from main Z80 memory
+ * 1 W loads the latch which holds the low 8 bits of the address of
+ * the main Z80 memory location to access
+ * 2 W 0 = read input ports, 1 = access Z80 memory
+ * 3 W clocks main Z80 memory access
+ * 4 W selects Z80 memory access direction (0 = write 1 = read)
+ * 5 W clocks a flip-flop which causes IRQ on the main Z80
+ * 6 W not used?
+ * 7 W not used?
+ */
+
+static UINT8 portB_in,portB_out,ddrB;
+
+READ8_HANDLER( mexico86_68705_portB_r )
+{
+ return (portB_out & ddrB) | (portB_in & ~ddrB);
+}
+
+static int address,latch;
+
+WRITE8_HANDLER( mexico86_68705_portB_w )
+{
+//logerror("%04x: 68705 port B write %02x\n",activecpu_get_pc(),data);
+
+ if ((ddrB & 0x01) && (~data & 0x01) && (portB_out & 0x01))
+ {
+ portA_in = latch;
+ }
+ if ((ddrB & 0x02) && (data & 0x02) && (~portB_out & 0x02)) /* positive edge trigger */
+ {
+ address = portA_out;
+//if (address >= 0x80) logerror("%04x: 68705 address %02x\n",activecpu_get_pc(),portA_out);
+ }
+ if ((ddrB & 0x08) && (~data & 0x08) && (portB_out & 0x08))
+ {
+ if (data & 0x10) /* read */
+ {
+ if (data & 0x04)
+ {
+//logerror("%04x: 68705 read %02x from address %04x\n",activecpu_get_pc(),shared[0x800+address],address);
+ latch = mexico86_protection_ram[address];
+ }
+ else
+ {
+//logerror("%04x: 68705 read input port %04x\n",activecpu_get_pc(),address);
+ latch = readinputport((address & 1) + 1);
+ }
+ }
+ else /* write */
+ {
+//logerror("%04x: 68705 write %02x to address %04x\n",activecpu_get_pc(),portA_out,address);
+ mexico86_protection_ram[address] = portA_out;
+ }
+ }
+ if ((ddrB & 0x20) && (data & 0x20) && (~portB_out & 0x20))
+ {
+ cpunum_set_input_line_vector(0,0,mexico86_protection_ram[0]);
+ //cpunum_set_input_line(0,0,PULSE_LINE);
+ cpunum_set_input_line(0, 0, HOLD_LINE); //AT: HOLD_LINE works better in Z80 interrupt mode 1.
+ }
+ if ((ddrB & 0x40) && (~data & 0x40) && (portB_out & 0x40))
+ {
+logerror("%04x: 68705 unknown port B bit %02x\n",activecpu_get_pc(),data);
+ }
+ if ((ddrB & 0x80) && (~data & 0x80) && (portB_out & 0x80))
+ {
+logerror("%04x: 68705 unknown port B bit %02x\n",activecpu_get_pc(),data);
+ }
+
+ portB_out = data;
+}
+
+WRITE8_HANDLER( mexico86_68705_ddrB_w )
+{
+ ddrB = data;
+}