diff options
Diffstat (limited to 'src/mame/drivers/turrett.cpp')
-rw-r--r-- | src/mame/drivers/turrett.cpp | 414 |
1 files changed, 414 insertions, 0 deletions
diff --git a/src/mame/drivers/turrett.cpp b/src/mame/drivers/turrett.cpp new file mode 100644 index 00000000000..ba7c5cac401 --- /dev/null +++ b/src/mame/drivers/turrett.cpp @@ -0,0 +1,414 @@ +// license:BSD-3-Clause +// copyright-holders:Philip Bennett +/*************************************************************************** + + Turret Tower by Dell Electronics + + driver by Phil Bennett + +****************************************************************************/ + +#include "emu.h" +#include "cpu/mips/r3000.h" +#include "machine/ataintf.h" +#include "includes/turrett.h" + + + +/************************************* + * + * Definitions + * + *************************************/ + +#define R3041_CLOCK XTAL_25MHz + + + +/************************************* + * + * Machine initialization + * + *************************************/ + +void turrett_state::machine_start() +{ + // Allocate memory for the two 256kx16 banks of video RAM + m_video_ram[0] = (UINT16*)auto_alloc_array(machine(), UINT16, VRAM_BANK_WORDS); + m_video_ram[1] = (UINT16*)auto_alloc_array(machine(), UINT16, VRAM_BANK_WORDS); + + // Register our state for saving + save_pointer(NAME(m_video_ram[0]), VRAM_BANK_WORDS); + save_pointer(NAME(m_video_ram[1]), VRAM_BANK_WORDS); + save_item(NAME(m_inputs_active)); + save_item(NAME(m_last_pixel)); + save_item(NAME(m_video_ctrl)); + save_item(NAME(m_video_fade)); + save_item(NAME(m_x_pos)); + save_item(NAME(m_x_start)); + save_item(NAME(m_x_mod)); + save_item(NAME(m_dx)); + save_item(NAME(m_y_pos)); + save_item(NAME(m_scale_cnt_y)); + save_item(NAME(m_scale_cnt_x)); + save_item(NAME(m_skip_x)); + save_item(NAME(m_skip_y)); + save_item(NAME(m_scale)); + save_item(NAME(m_hotspot_x)); + save_item(NAME(m_hotspot_y)); + save_item(NAME(m_dma_idle)); + save_item(NAME(m_dma_addr)); + save_item(NAME(m_ipt_val)); + save_item(NAME(m_frame)); + save_item(NAME(m_adc)); + + m_dma_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(turrett_state::dma_complete), this)); +} + + +void turrett_state::machine_reset() +{ + m_dma_idle = true; + m_frame = 0; + m_adc = 0; + m_inputs_active = 0; +} + + + +/************************************* + * + * Memory maps + * + *************************************/ + +static ADDRESS_MAP_START( cpu_map, AS_PROGRAM, 32, turrett_state ) + AM_RANGE(0x00000000, 0x0007ffff) AM_RAM + AM_RANGE(0x02000010, 0x02000013) AM_RAM + AM_RANGE(0x02000040, 0x02000043) AM_RAM + AM_RANGE(0x02000050, 0x02000053) AM_RAM + AM_RANGE(0x02000060, 0x02000063) AM_RAM + AM_RANGE(0x02000070, 0x02000073) AM_RAM // TODO: What are these? + AM_RANGE(0x04000000, 0x0400000f) AM_WRITE(dma_w) + AM_RANGE(0x04000100, 0x04000103) AM_READWRITE(int_r, int_w) + AM_RANGE(0x04000200, 0x040003ff) AM_DEVREADWRITE("ttsound", turrett_device, read, write) + AM_RANGE(0x08000000, 0x0800000f) AM_READWRITE(video_r, video_w) + AM_RANGE(0x08000200, 0x080003ff) AM_DEVREADWRITE16("ata", ata_interface_device, read_cs0, write_cs0, 0xffffffff) + AM_RANGE(0x1fc00000, 0x1fdfffff) AM_ROM AM_REGION("maincpu", 0) +ADDRESS_MAP_END + + +static ADDRESS_MAP_START( turrett_sound_map, AS_0, 16, turrett_state ) + AM_RANGE(0x0000000, 0x7ffffff) AM_RAM AM_SHARE("bank_a") + AM_RANGE(0x8000000, 0xfffffff) AM_RAM AM_SHARE("bank_b") +ADDRESS_MAP_END + + + +/************************************* + * + * Port definitions + * + *************************************/ + +static INPUT_PORTS_START( turrett ) + PORT_START("PORT 0X") + PORT_BIT( 0x3f, 0x00, IPT_AD_STICK_Y ) PORT_MINMAX(0x20,0x1f) PORT_SENSITIVITY(60) PORT_KEYDELTA(2) + + PORT_START("PORT 4X") + PORT_BIT( 0x3f, 0x00, IPT_AD_STICK_X ) PORT_MINMAX(0x20,0x1f) PORT_SENSITIVITY(60) PORT_KEYDELTA(2) + + PORT_START("PORT CX") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CHANGED_MEMBER(DEVICE_SELF, turrett_state, ipt_change, (void *)0x00000100) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_SERVICE1 ) PORT_CHANGED_MEMBER(DEVICE_SELF, turrett_state, ipt_change, (void *)0x00000200) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BILL1 ) PORT_CHANGED_MEMBER(DEVICE_SELF, turrett_state, ipt_change, (void *)0x00000400) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_SERVICE ) PORT_CHANGED_MEMBER(DEVICE_SELF, turrett_state, ipt_change, (void *)0x00000800) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_CHANGED_MEMBER(DEVICE_SELF, turrett_state, ipt_change, (void *)0x00001000) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_COIN2 ) PORT_CHANGED_MEMBER(DEVICE_SELF, turrett_state, ipt_change, (void *)0x00002000) + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_START ) PORT_CHANGED_MEMBER(DEVICE_SELF, turrett_state, ipt_change, (void *)0x00004000) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CHANGED_MEMBER(DEVICE_SELF, turrett_state, ipt_change, (void *)0x00008000) + + PORT_START("PORT DX") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CHANGED_MEMBER(DEVICE_SELF, turrett_state, ipt_change, (void *)0x00010000) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_CHANGED_MEMBER(DEVICE_SELF, turrett_state, ipt_change, (void *)0x00020000) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_CHANGED_MEMBER(DEVICE_SELF, turrett_state, ipt_change, (void *)0x00040000) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CHANGED_MEMBER(DEVICE_SELF, turrett_state, ipt_change, (void *)0x00080000) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CHANGED_MEMBER(DEVICE_SELF, turrett_state, ipt_change, (void *)0x00100000) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CHANGED_MEMBER(DEVICE_SELF, turrett_state, ipt_change, (void *)0x00200000) + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CHANGED_MEMBER(DEVICE_SELF, turrett_state, ipt_change, (void *)0x00400000) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CHANGED_MEMBER(DEVICE_SELF, turrett_state, ipt_change, (void *)0x00800000) + + PORT_START("PORT EX") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("Floor mat") + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_NAME("Door Lock") PORT_TOGGLE + + PORT_START("PORT FX") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_NAME("Seat Belt") PORT_TOGGLE + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON6 ) PORT_NAME("Home") + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_BUTTON7 ) PORT_NAME("Emergency Stop") PORT_TOGGLE +INPUT_PORTS_END + + + +/************************************* + * + * I/O handling + * + *************************************/ + +READ_LINE_MEMBER( turrett_state::sbrc2_r ) +{ + return m_screen->vblank(); +} + + +READ_LINE_MEMBER( turrett_state::sbrc3_r ) +{ + return m_dma_idle; +} + + +READ32_MEMBER( turrett_state::int_r ) +{ + return update_inputs() << 24; +} + + +WRITE32_MEMBER( turrett_state::int_w ) +{ + // TODO + logerror("Output write: %08x\n", data); +} + + +UINT32 turrett_state::update_inputs(void) +{ + UINT32 val = 0; + + // TODO: Prioritise? + if (m_inputs_active) + { + if (m_inputs_active & 0x00000001) + { + val = 0x00 | (ioport("PORT 0X")->read() & 0x3f); + m_inputs_active &= ~1; + } + else if (m_inputs_active & 0x00000002) + { + val = 0x40 | (ioport("PORT 4X")->read() & 0x3f); + m_inputs_active &= ~2; + } + else if (m_inputs_active & 0x0000ff00) + { + UINT32 data = ioport("PORT CX")->read(); + UINT32 bits = m_inputs_active >> 8; + + val = 0xc0; + + for (int i = 0; i < 8; ++i) + { + if (bits & (1 << i)) + { + val |= i << 1; + val |= (data >> i) & 1; + m_inputs_active &= ~(1 << (i + 8)); + break; + } + } + } + else if (m_inputs_active & 0x00ff0000) + { + UINT32 data = ioport("PORT DX")->read(); + UINT32 bits = m_inputs_active >> 16; + + val = 0xd0; + + for (int i = 0; i < 8; ++i) + { + if (bits & (1 << i)) + { + val |= i << 1; + val |= (data >> i) & 1; + m_inputs_active &= ~(1 << (i + 16)); + break; + } + } + } + else if (m_inputs_active & 0x01000000) + { + val = 0xe0 | ioport("PORT EX")->read(); + m_inputs_active &= ~0x01000000; + } + else if (m_inputs_active & 0x02000000) + { + val = 0xf0 | ioport("PORT FX")->read(); + m_inputs_active &= ~0x02000000; + } + } + + // Update IRQ state + m_maincpu->set_input_line(R3000_IRQ1, m_inputs_active ? ASSERT_LINE : CLEAR_LINE); + return val; +} + + +INPUT_CHANGED_MEMBER( turrett_state::ipt_change ) +{ + int p = (FPTR)param; + + if (newval != oldval) + { + // TODO: Tidy this up + if (p & (0x02000000 | 0x00000200 | 0x00000400 | 0x00001000 | 0x00002000)) + { + if (newval == 0) + { + m_inputs_active |= p; + m_maincpu->set_input_line(R3000_IRQ1, ASSERT_LINE); + } + } + else + { + m_inputs_active |= p; + m_maincpu->set_input_line(R3000_IRQ1, ASSERT_LINE); + } + } +} + + + +/************************************* + * + * Interrupts + * + *************************************/ + +INTERRUPT_GEN_MEMBER( turrett_state::vblank ) +{ + if (m_frame) + m_inputs_active |= 0x01000000; + else + m_inputs_active |= 0x02000000; + + m_frame ^= 1; + m_maincpu->set_input_line(R3000_IRQ1, ASSERT_LINE); +} + + +INTERRUPT_GEN_MEMBER( turrett_state::adc ) +{ + if (m_adc) + m_inputs_active |= 0x00000001; + else + m_inputs_active |= 0x00000002; + + m_adc ^= 1; + m_maincpu->set_input_line(R3000_IRQ1, ASSERT_LINE); +} + +/************************************* + * + * Hard drive + * + *************************************/ + +/// HACK: The game expects a different LBA mapping to the standard HDD. +/// The reason for this is unknown. + +#include "machine/idehd.h" + +extern const device_type TURRETT_HARDDISK; + +class turrett_hdd : public ide_hdd_device +{ +public: + turrett_hdd(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : ide_hdd_device(mconfig, TURRETT_HARDDISK, "HDD Turrett Tower", tag, owner, clock, "turrett_hdd", __FILE__) + { + } + + virtual UINT32 lba_address() + { + if (m_device_head & IDE_DEVICE_HEAD_L) + return (((m_device_head & IDE_DEVICE_HEAD_HS) << 24) | (m_cylinder_high << 16) | (m_cylinder_low << 8) | m_sector_number) - 63; + + return ata_mass_storage_device::lba_address(); + } +}; + +const device_type TURRETT_HARDDISK = &device_creator<turrett_hdd>; + +SLOT_INTERFACE_START(turrett_devices) + SLOT_INTERFACE("hdd", TURRETT_HARDDISK) +SLOT_INTERFACE_END + +/************************************* + * + * Machine driver + * + *************************************/ + +static MACHINE_CONFIG_START( turrett, turrett_state ) + + /* basic machine hardware */ + MCFG_CPU_ADD("maincpu", R3041, R3041_CLOCK) + MCFG_R3000_ENDIANNESS(ENDIANNESS_BIG) + MCFG_R3000_BRCOND2_INPUT(READLINE(turrett_state, sbrc2_r)) + MCFG_R3000_BRCOND3_INPUT(READLINE(turrett_state, sbrc3_r)) + MCFG_CPU_PROGRAM_MAP(cpu_map) + MCFG_CPU_VBLANK_INT_DRIVER("screen", turrett_state, vblank) + MCFG_CPU_PERIODIC_INT_DRIVER(turrett_state, adc, 60) + + MCFG_ATA_INTERFACE_ADD("ata", turrett_devices, "hdd", NULL, true) + + /* video hardware */ + MCFG_SCREEN_ADD("screen", RASTER) + // TODO: Likely not correct. Refresh rate empirically determined + // to ensure in-sync streaming sound + MCFG_SCREEN_RAW_PARAMS(4000000, 512, 0, 336, 259, 0, 244) + MCFG_SCREEN_UPDATE_DRIVER(turrett_state, screen_update) + MCFG_SCREEN_PALETTE("palette") + + MCFG_PALETTE_ADD_RRRRRGGGGGBBBBB("palette") + + /* sound hardware */ + MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") + + MCFG_DEVICE_ADD("ttsound", TURRETT, R3041_CLOCK) // ? + MCFG_DEVICE_ADDRESS_MAP(AS_0, turrett_sound_map) + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 1.0) + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 1.0) +MACHINE_CONFIG_END + + + + /************************************* + * + * ROM definition + * + *************************************/ + +ROM_START( turrett ) + ROM_REGION( 0x200000, "maincpu", 0 ) + ROM_LOAD32_BYTE( "turret.u13", 0x000000, 0x080000, CRC(85287007) SHA1(990b954905c66340d3e88918b2f8cc7f1b9c7cf4) ) + ROM_LOAD32_BYTE( "turret.u12", 0x000001, 0x080000, CRC(a2a498fc) SHA1(47f2c9c9f2496b49fd923acb400166e963095e1d) ) + ROM_LOAD32_BYTE( "turret.u8", 0x000002, 0x080000, CRC(ddff4898) SHA1(a8f859a0dcab8ec83fbfe255d58b3e644933b923) ) + ROM_LOAD32_BYTE( "turret.u7", 0x000003, 0x080000, CRC(fa8b5a5a) SHA1(658e9eeadc9c70185973470565d562c76f4fcdd7) ) + + DISK_REGION( "ata:0:hdd:image" ) + /// According to http://personal.inet.fi/cool/lwgt/myoldvdr/V40ProductManual.pdf + /// The drive should have CYLS:38869, HEADS:16, SECS:63, Total Units:39,179,952 + /// We are missing 13482 sectors and we have to adjust the LBA by 63 sectors for + /// the game to work. + DISK_IMAGE( "turrett", 0, BAD_DUMP SHA1(b0c98c5876870dd8b3e37a38fe35846c9e011df4) ) +ROM_END + + + +/************************************* + * + * Game driver + * + *************************************/ + +GAME( 2001, turrett, 0, turrett, turrett, driver_device, 0, ROT0, "Dell Electronics (Namco license)", "Turret Tower", 0 ) |