summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/mame/drivers/2mindril.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/mame/drivers/2mindril.c')
-rw-r--r--trunk/src/mame/drivers/2mindril.c561
1 files changed, 561 insertions, 0 deletions
diff --git a/trunk/src/mame/drivers/2mindril.c b/trunk/src/mame/drivers/2mindril.c
new file mode 100644
index 00000000000..a27083502a9
--- /dev/null
+++ b/trunk/src/mame/drivers/2mindril.c
@@ -0,0 +1,561 @@
+/*
+ Two Minute Drill - Taito 1993
+ -----------------------------
+ Half Video, Half Mechanical?
+(video hw + motion/acceleration sensor ?)
+
+ preliminary driver by
+ David Haywood
+ Tomasz Slanina
+ Angelo Salese
+
+TODO:
+ - understand the ball hit sensor
+ - simulate the sensors (there are still some shutter errors/defender errors that pops up)
+ - Hook-up timers for shutter/defender sensors (check service mode)
+ - Dip-Switches
+
+ Brief hardware overview:
+ ------------------------
+
+ Main processor - 68000 16Mhz
+
+ Sound - Yamaha YM2610B
+
+ Taito custom ICs - TC0400YSC (m68k -> ym2610 communication)
+ - TC0260DAR (palette chip)
+ - TC0630FDP (Taito F3 video chip)
+ - TC0510NIO (known input chip)
+
+DAC -26.6860Mhz
+ -32.0000Mhz
+
+*/
+
+#include "emu.h"
+#include "cpu/m68000/m68000.h"
+#include "sound/2610intf.h"
+#include "includes/taito_f3.h"
+
+
+class _2mindril_state : public taito_f3_state
+{
+public:
+ _2mindril_state(const machine_config &mconfig, device_type type, const char *tag)
+ : taito_f3_state(mconfig, type, tag),
+ m_iodata(*this, "iodata") { }
+
+ /* memory pointers */
+ required_shared_ptr<UINT16> m_iodata;
+
+ /* input-related */
+ UINT16 m_defender_sensor;
+ UINT16 m_shutter_sensor;
+ UINT16 irq_reg;
+
+ /* devices */
+ device_t *m_maincpu;
+ DECLARE_READ16_MEMBER(drill_io_r);
+ DECLARE_WRITE16_MEMBER(drill_io_w);
+ DECLARE_WRITE16_MEMBER(sensors_w);
+ DECLARE_READ16_MEMBER(drill_irq_r);
+ DECLARE_WRITE16_MEMBER(drill_irq_w);
+};
+
+
+READ16_MEMBER(_2mindril_state::drill_io_r)
+{
+
+
+// if (offset * 2 == 0x4)
+ /*popmessage("PC=%08x %04x %04x %04x %04x %04x %04x %04x %04x", cpu_get_pc(&space.device()), m_iodata[0/2], m_iodata[2/2], m_iodata[4/2], m_iodata[6/2],
+ m_iodata[8/2], m_iodata[0xa/2], m_iodata[0xc/2], m_iodata[0xe/2]);*/
+
+ switch(offset)
+ {
+ case 0x0/2: return ioport("DSW")->read();
+ case 0x2/2:
+ {
+ int arm_pwr = ioport("IN0")->read();//throw
+ //popmessage("PC=%08x %02x",cpu_get_pc(&space.device()),arm_pwr);
+
+ if(arm_pwr > 0xe0) return ~0x1800;
+ if(arm_pwr > 0xc0) return ~0x1400;
+ if(arm_pwr > 0x80) return ~0x1200;
+ if(arm_pwr > 0x40) return ~0x1000;
+ else return ~0x0000;
+ }
+ case 0x4/2: return (m_defender_sensor) | (m_shutter_sensor);
+ case 0xe/2: return ioport("IN2")->read();//coins
+// default: printf("PC=%08x [%04x] -> %04x R\n", cpu_get_pc(&space.device()), offset * 2, m_iodata[offset]);
+ }
+
+ return 0xffff;
+}
+
+WRITE16_MEMBER(_2mindril_state::drill_io_w)
+{
+
+ COMBINE_DATA(&m_iodata[offset]);
+
+ switch(offset)
+ {
+ case 0x8/2:
+ coin_counter_w(machine(), 0, m_iodata[offset] & 0x0400);
+ coin_counter_w(machine(), 1, m_iodata[offset] & 0x0800);
+ coin_lockout_w(machine(), 0, ~m_iodata[offset] & 0x0100);
+ coin_lockout_w(machine(), 1, ~m_iodata[offset] & 0x0200);
+ break;
+ }
+
+// if(data != 0 && offset != 8)
+// printf("PC=%08x [%04x] <- %04x W\n", cpu_get_pc(&space.device()), offset * 2, data);
+}
+
+/*
+ PORT_DIPNAME( 0x0100, 0x0000, DEF_STR( Unknown ) )//up sensor <- shutter
+ PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x0100, DEF_STR( On ) )
+ PORT_DIPNAME( 0x0200, 0x0000, DEF_STR( Unknown ) )//down sensor
+ PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x0200, DEF_STR( On ) )
+ PORT_DIPNAME( 0x0400, 0x0000, DEF_STR( Unknown ) )//left sensor <-defender
+ PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x0400, DEF_STR( On ) )
+ PORT_DIPNAME( 0x0800, 0x0000, DEF_STR( Unknown ) )//right sensor
+ PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x0800, DEF_STR( On ) )
+*/
+#ifdef UNUSED_FUNCTION
+static TIMER_CALLBACK( shutter_req )
+{
+ _2mindril_state *state = machine.driver_data<_2mindril_state>();
+ state->m_shutter_sensor = param;
+}
+
+static TIMER_CALLBACK( defender_req )
+{
+ _2mindril_state *state = machine.driver_data<_2mindril_state>();
+ state->m_defender_sensor = param;
+}
+#endif
+
+WRITE16_MEMBER(_2mindril_state::sensors_w)
+{
+
+
+ /*---- xxxx ---- ---- select "lamps" (guess)*/
+ /*---- ---- ---- -x-- lamp*/
+ if (data & 1)
+ {
+ //machine().scheduler().timer_set(attotime::from_seconds(2), FUNC(shutter_req ), 0x100);
+ m_shutter_sensor = 0x100;
+ }
+ else if (data & 2)
+ {
+ //machine().scheduler().timer_set( attotime::from_seconds(2), FUNC(shutter_req ), 0x200);
+ m_shutter_sensor = 0x200;
+ }
+
+ if (data & 0x1000 || data & 0x4000)
+ {
+ //machine().scheduler().timer_set( attotime::from_seconds(2), FUNC(defender_req ), 0x800);
+ m_defender_sensor = 0x800;
+ }
+ else if (data & 0x2000 || data & 0x8000)
+ {
+ //machine().scheduler().timer_set( attotime::from_seconds(2), FUNC(defender_req ), 0x400);
+ m_defender_sensor = 0x400;
+ }
+}
+
+READ16_MEMBER(_2mindril_state::drill_irq_r)
+{
+
+ return irq_reg;
+}
+
+WRITE16_MEMBER(_2mindril_state::drill_irq_w)
+{
+
+ /*
+ (note: could rather be irq mask)
+ ---- ---- ---x ---- irq lv 5 ack, 0->1 latch
+ ---- ---- ---- x--- irq lv 4 ack, 0->1 latch
+ ---- ---- -??- -??? connected to the other levels?
+ */
+ if(((irq_reg & 8) == 0) && data & 8)
+ cputag_set_input_line(machine(), "maincpu", 4, CLEAR_LINE);
+
+ if(((irq_reg & 0x10) == 0) && data & 0x10)
+ cputag_set_input_line(machine(), "maincpu", 5, CLEAR_LINE);
+
+ if(data & 0xffe7)
+ printf("%04x\n",data);
+
+ COMBINE_DATA(&irq_reg);
+}
+
+static ADDRESS_MAP_START( drill_map, AS_PROGRAM, 16, _2mindril_state )
+ AM_RANGE(0x000000, 0x07ffff) AM_ROM
+ AM_RANGE(0x200000, 0x20ffff) AM_RAM
+ AM_RANGE(0x300000, 0x3000ff) AM_RAM
+ AM_RANGE(0x400000, 0x40ffff) AM_READWRITE(f3_spriteram_r,f3_spriteram_w)
+ AM_RANGE(0x410000, 0x41bfff) AM_READWRITE(f3_pf_data_r,f3_pf_data_w)
+ AM_RANGE(0x41c000, 0x41dfff) AM_READWRITE(f3_videoram_r,f3_videoram_w)
+ AM_RANGE(0x41e000, 0x41ffff) AM_READWRITE(f3_vram_r,f3_vram_w)
+ AM_RANGE(0x420000, 0x42ffff) AM_READWRITE(f3_lineram_r,f3_lineram_w)
+ AM_RANGE(0x430000, 0x43ffff) AM_READWRITE(f3_pivot_r,f3_pivot_w)
+ AM_RANGE(0x460000, 0x46000f) AM_WRITE(f3_control_0_w)
+ AM_RANGE(0x460010, 0x46001f) AM_WRITE(f3_control_1_w)
+ AM_RANGE(0x500000, 0x501fff) AM_RAM_WRITE(paletteram_RRRRGGGGBBBBRGBx_word_w) AM_SHARE("paletteram")
+ AM_RANGE(0x502022, 0x502023) AM_WRITENOP //countinously switches between 0 and 2
+ AM_RANGE(0x600000, 0x600007) AM_DEVREADWRITE8_LEGACY("ymsnd", ym2610_r, ym2610_w, 0x00ff)
+ AM_RANGE(0x60000c, 0x60000d) AM_READWRITE(drill_irq_r,drill_irq_w)
+ AM_RANGE(0x60000e, 0x60000f) AM_RAM // unknown purpose, zeroed at start-up and nothing else
+ AM_RANGE(0x700000, 0x70000f) AM_READWRITE(drill_io_r,drill_io_w) AM_SHARE("iodata") // i/o
+ AM_RANGE(0x800000, 0x800001) AM_WRITE(sensors_w)
+ADDRESS_MAP_END
+
+static INPUT_PORTS_START( drill )
+ PORT_START("DSW")//Dip-Switches
+ PORT_DIPNAME( 0x0001, 0x0001, "DSW" )
+ PORT_DIPSETTING( 0x0001, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
+ PORT_DIPNAME( 0x0002, 0x0002, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x0002, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
+ PORT_DIPNAME( 0x0004, 0x0004, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x0004, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
+ PORT_DIPNAME( 0x0008, 0x0008, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x0008, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
+ PORT_DIPNAME( 0x0010, 0x0010, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x0010, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
+ PORT_DIPNAME( 0x0020, 0x0020, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x0020, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
+ PORT_DIPNAME( 0x0040, 0x0040, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x0040, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
+ PORT_DIPNAME( 0x0080, 0x0080, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x0080, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
+ PORT_DIPNAME( 0x0100, 0x0100, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x0100, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
+ PORT_DIPNAME( 0x0200, 0x0200, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x0200, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
+ PORT_DIPNAME( 0x0400, 0x0400, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x0400, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
+ PORT_DIPNAME( 0x0800, 0x0800, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x0800, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
+ PORT_DIPNAME( 0x1000, 0x1000, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x1000, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
+ PORT_DIPNAME( 0x2000, 0x2000, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x2000, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
+ PORT_DIPNAME( 0x4000, 0x4000, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x4000, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
+ PORT_DIPNAME( 0x8000, 0x8000, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x8000, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
+
+ PORT_START("IN0")//sensors
+ PORT_BIT( 0xff, 0x00, IPT_DIAL ) PORT_SENSITIVITY(25) PORT_KEYDELTA(20)
+
+ PORT_START("IN1")
+ PORT_DIPNAME( 0x0001, 0x0000, "IN1" )
+ PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x0001, DEF_STR( On ) )
+ PORT_DIPNAME( 0x0002, 0x0000, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x0002, DEF_STR( On ) )
+ PORT_DIPNAME( 0x0004, 0x0000, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x0004, DEF_STR( On ) )
+ PORT_DIPNAME( 0x0008, 0x0008, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x0008, DEF_STR( On ) )
+ PORT_DIPNAME( 0x0010, 0x0000, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x0010, DEF_STR( On ) )
+ PORT_DIPNAME( 0x0020, 0x0000, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x0020, DEF_STR( On ) )
+ PORT_DIPNAME( 0x0040, 0x0000, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x0040, DEF_STR( On ) )
+ PORT_DIPNAME( 0x0080, 0x0000, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x0080, DEF_STR( On ) )
+ PORT_DIPNAME( 0x0100, 0x0000, DEF_STR( Unknown ) )//up sensor
+ PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x0100, DEF_STR( On ) )
+ PORT_DIPNAME( 0x0200, 0x0000, DEF_STR( Unknown ) )//down sensor
+ PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x0200, DEF_STR( On ) )
+ PORT_DIPNAME( 0x0400, 0x0000, DEF_STR( Unknown ) )//left sensor
+ PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x0400, DEF_STR( On ) )
+ PORT_DIPNAME( 0x0800, 0x0000, DEF_STR( Unknown ) )//right sensor
+ PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x0800, DEF_STR( On ) )
+ PORT_DIPNAME( 0x1000, 0x0000, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x1000, DEF_STR( On ) )
+ PORT_DIPNAME( 0x2000, 0x0000, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x2000, DEF_STR( On ) )
+ PORT_DIPNAME( 0x4000, 0x0000, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x4000, DEF_STR( On ) )
+ PORT_DIPNAME( 0x8000, 0x0000, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x8000, DEF_STR( On ) )
+
+ PORT_START("IN2")//coins
+ PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_SERVICE )
+ PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_SERVICE1 )
+ PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_COIN1 )
+ PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("Select SW-1")
+ PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("Select SW-2")
+ PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("Select SW-3")
+ PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("Select SW-4")
+INPUT_PORTS_END
+
+static const gfx_layout charlayout =
+{
+ 8,8,
+ 256,
+ 4,
+ { 0,1,2,3 },
+ { 20, 16, 28, 24, 4, 0, 12, 8 },
+ { 0*32, 1*32, 2*32, 3*32, 4*32, 5*32, 6*32, 7*32 },
+ 32*8
+};
+
+static const gfx_layout pivotlayout =
+{
+ 8,8,
+ 2048,
+ 4,
+ { 0,1,2,3 },
+ { 20, 16, 28, 24, 4, 0, 12, 8 },
+ { 0*32, 1*32, 2*32, 3*32, 4*32, 5*32, 6*32, 7*32 },
+ 32*8
+};
+
+static const gfx_layout spriteram_layout =
+{
+ 16,16,
+ RGN_FRAC(1,2),
+ 6, /* Palettes have 4 bpp indexes despite up to 6 bpp data */
+ { RGN_FRAC(1,2)+0, RGN_FRAC(1,2)+1, 0, 1, 2, 3 },
+ {
+ 4, 0, 12, 8,
+ 16+4, 16+0, 16+12, 16+8,
+ 32+4, 32+0, 32+12, 32+8,
+ 48+4, 48+0, 48+12, 48+8 },
+ { 0*64, 1*64, 2*64, 3*64, 4*64, 5*64, 6*64, 7*64,
+ 8*64, 9*64, 10*64, 11*64, 12*64, 13*64, 14*64, 15*64 },
+ 128*8 /* every sprite takes 128 consecutive bytes */
+};
+
+static const gfx_layout tile_layout =
+{
+ 16,16,
+ RGN_FRAC(1,2),
+ 6, /* Palettes have 4 bpp indexes despite up to 6 bpp data */
+ { RGN_FRAC(1,2)+2, RGN_FRAC(1,2)+3, 0, 1, 2, 3 },
+ {
+ 4, 0, 16+4, 16+0,
+ 8+4, 8+0, 24+4, 24+0,
+ 32+4, 32+0, 48+4, 48+0,
+ 40+4, 40+0, 56+4, 56+0,
+ },
+ { 0*64, 1*64, 2*64, 3*64, 4*64, 5*64, 6*64, 7*64,
+ 8*64, 9*64, 10*64, 11*64, 12*64, 13*64, 14*64, 15*64 },
+ 128*8 /* every sprite takes 128 consecutive bytes */
+};
+
+static GFXDECODE_START( 2mindril )
+ GFXDECODE_ENTRY( NULL, 0x000000, charlayout, 0x0000, 0x0400>>4 ) /* Dynamically modified */
+ GFXDECODE_ENTRY( "gfx2", 0x000000, tile_layout, 0x0000, 0x2000>>4 ) /* Tiles area */
+ GFXDECODE_ENTRY( "gfx1", 0x000000, spriteram_layout, 0x1000, 0x1000>>4 ) /* Sprites area */
+ GFXDECODE_ENTRY( NULL, 0x000000, pivotlayout, 0x0000, 0x400>>4 ) /* Dynamically modified */
+GFXDECODE_END
+
+
+static INTERRUPT_GEN( drill_vblank_irq )
+{
+ device_set_input_line(device, 4, ASSERT_LINE);
+}
+
+#if 0
+static INTERRUPT_GEN( drill_device_irq )
+{
+ device_set_input_line(device, 5, ASSERT_LINE);
+}
+#endif
+
+/* WRONG,it does something with 60000c & 700002,likely to be called when the player throws the ball.*/
+static void irqhandler(device_t *device, int irq)
+{
+// _2mindril_state *state = machine.driver_data<_2mindril_state>();
+// device_set_input_line(state->m_maincpu, 5, irq ? ASSERT_LINE : CLEAR_LINE);
+}
+
+static const ym2610_interface ym2610_config =
+{
+ irqhandler
+};
+
+
+static MACHINE_START( drill )
+{
+ _2mindril_state *state = machine.driver_data<_2mindril_state>();
+
+ state->m_maincpu = machine.device("maincpu");
+
+ state->save_item(NAME(state->m_defender_sensor));
+ state->save_item(NAME(state->m_shutter_sensor));
+}
+
+static MACHINE_RESET( drill )
+{
+ _2mindril_state *state = machine.driver_data<_2mindril_state>();
+
+ state->m_defender_sensor = 0;
+ state->m_shutter_sensor = 0;
+ state->irq_reg = 0;
+}
+
+static MACHINE_CONFIG_START( drill, _2mindril_state )
+
+ MCFG_CPU_ADD("maincpu", M68000, 16000000 )
+ MCFG_CPU_PROGRAM_MAP(drill_map)
+ MCFG_CPU_VBLANK_INT("screen", drill_vblank_irq)
+ //MCFG_CPU_PERIODIC_INT(drill_device_irq,60)
+ MCFG_GFXDECODE(2mindril)
+
+ MCFG_MACHINE_START(drill)
+ MCFG_MACHINE_RESET(drill)
+
+ MCFG_SCREEN_ADD("screen", RASTER)
+ MCFG_SCREEN_REFRESH_RATE(60)
+ MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* inaccurate, same as Taito F3? (needs screen raw params anyway) */
+ MCFG_SCREEN_SIZE(40*8+48*2, 32*8)
+ MCFG_SCREEN_VISIBLE_AREA(46, 40*8-1 + 46, 24, 24+224-1)
+ MCFG_SCREEN_UPDATE_STATIC(f3)
+ MCFG_SCREEN_VBLANK_STATIC(f3)
+
+ MCFG_PALETTE_LENGTH(0x2000)
+
+ MCFG_VIDEO_START(f3)
+
+ MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
+
+ MCFG_SOUND_ADD("ymsnd", YM2610B, 16000000/2)
+ MCFG_SOUND_CONFIG(ym2610_config)
+ MCFG_SOUND_ROUTE(0, "lspeaker", 0.25)
+ MCFG_SOUND_ROUTE(0, "rspeaker", 0.25)
+ MCFG_SOUND_ROUTE(1, "lspeaker", 1.0)
+ MCFG_SOUND_ROUTE(2, "rspeaker", 1.0)
+MACHINE_CONFIG_END
+
+
+ROM_START( 2mindril )
+ ROM_REGION( 0x80000, "maincpu", 0 ) /* 68000 Code */
+ ROM_LOAD16_BYTE( "d58-38.ic11", 0x00000, 0x40000, CRC(c58e8e4f) SHA1(648db679c3bfb5de1cd6c1b1217773a2fe56f11b) )
+ ROM_LOAD16_BYTE( "d58-37.ic9", 0x00001, 0x40000, CRC(19e5cc3c) SHA1(04ac0eef893c579fe90d91d7fd55c5741a2b7460) )
+
+ ROM_REGION( 0x200000, "ymsnd", 0 ) /* Samples */
+ ROM_LOAD( "d58-11.ic31", 0x000000, 0x200000, CRC(dc26d58d) SHA1(cffb18667da18f5367b02af85a2f7674dd61ae97) )
+
+ ROM_REGION( 0x800000, "gfx1", ROMREGION_ERASE00 )
+
+ ROM_REGION( 0x800000, "gfx2", 0 )
+ ROM_LOAD16_BYTE( "d58-09.ic28", 0x000001, 0x200000, CRC(d8f6a86a) SHA1(d6b2ec309e21064574ee63e025ae4716b1982a98) )
+ ROM_LOAD16_BYTE( "d58-08.ic27", 0x000000, 0x200000, CRC(9f5a3f52) SHA1(7b696bd823819965b974c853cebc1660750db61e) )
+ ROM_LOAD( "d58-10.ic29", 0x400000, 0x200000, CRC(74c87e08) SHA1(f39b3a64f8338ccf5ca6eb76cee92a10fe0aad8f) )
+ ROM_RELOAD( 0x600000, 0x200000 )
+ROM_END
+
+static void tile_decode(running_machine &machine)
+{
+ UINT8 lsb,msb;
+ UINT32 offset,i;
+ UINT8 *gfx = machine.root_device().memregion("gfx2")->base();
+ int size=machine.root_device().memregion("gfx2")->bytes();
+ int data;
+
+ /* Setup ROM formats:
+
+ Some games will only use 4 or 5 bpp sprites, and some only use 4 bpp tiles,
+ I don't believe this is software or prom controlled but simply the unused data lines
+ are tied low on the game board if unused. This is backed up by the fact the palette
+ indices are always related to 4 bpp data, even in 6 bpp games.
+
+ Most (all?) games with 5bpp tiles have the sixth bit set. Also, in Arabian Magic
+ sprites 1200-120f contain 6bpp data which is probably bogus.
+ VIDEO_START( f3 ) clears the fifth and sixth bit of the decoded graphics according
+ to the bit depth specified in f3_config_table.
+
+ */
+
+ offset = size/2;
+ for (i = size/2+size/4; i<size; i+=2)
+ {
+ /* Expand 2bits into 4bits format */
+ lsb = gfx[i+1];
+ msb = gfx[i];
+
+ gfx[offset+0]=((msb&0x02)<<3) | ((msb&0x01)>>0) | ((lsb&0x02)<<4) | ((lsb&0x01)<<1);
+ gfx[offset+2]=((msb&0x08)<<1) | ((msb&0x04)>>2) | ((lsb&0x08)<<2) | ((lsb&0x04)>>1);
+ gfx[offset+1]=((msb&0x20)>>1) | ((msb&0x10)>>4) | ((lsb&0x20)<<0) | ((lsb&0x10)>>3);
+ gfx[offset+3]=((msb&0x80)>>3) | ((msb&0x40)>>6) | ((lsb&0x80)>>2) | ((lsb&0x40)>>5);
+
+ offset+=4;
+ }
+
+ gfx = machine.root_device().memregion("gfx1")->base();
+ size=machine.root_device().memregion("gfx1")->bytes();
+
+ offset = size/2;
+ for (i = size/2+size/4; i<size; i++)
+ {
+ int d1,d2,d3,d4;
+
+ /* Expand 2bits into 4bits format */
+ data = gfx[i];
+ d1 = (data>>0) & 3;
+ d2 = (data>>2) & 3;
+ d3 = (data>>4) & 3;
+ d4 = (data>>6) & 3;
+
+ gfx[offset] = (d1<<2) | (d2<<6);
+ offset++;
+
+ gfx[offset] = (d3<<2) | (d4<<6);
+ offset++;
+ }
+}
+
+static DRIVER_INIT( drill )
+{
+ taito_f3_state *state = machine.driver_data<taito_f3_state>();
+ state->m_f3_game=TMDRILL;
+ tile_decode(machine);
+}
+
+GAME( 1993, 2mindril, 0, drill, drill, drill, ROT0, "Taito", "Two Minute Drill", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_SUPPORTS_SAVE | GAME_MECHANICAL)