diff options
Diffstat (limited to 'trunk/src/mame/drivers/2mindril.c')
-rw-r--r-- | trunk/src/mame/drivers/2mindril.c | 561 |
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) |