From b566662a053b1985ac48db0600be98ae24ddd44d Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Mon, 17 Sep 2018 20:03:25 +1000 Subject: Add Sun mouse port and hook it up to sun3, sun3x, sun4, and sun4c. Also add notes to Sun keyboard emulation. There's a hack to make the 1200 Baud mouse actually run at 9600 Baud. This is necessary because the SCC is incorrectly expecting 9600 Baud rather than 1200 Baud. I don't have time to fix the SCC, so I'd appreciate it if someone else would. There's no way it should be expecting 9600 Baud on the mouse port. Solaris 2.3 and later support 1200 Baud and 4800 Baud, and earlier versions support 1200 Baud only. No version of Solaris works with a 9600 Baud mouse. The workaround allows the mouse to be used in SunView on sun4_60 - I haven't tested any other drivers. --- scripts/src/bus.lua | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'scripts/src') diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index 6e5cbd9c70e..662b2627c7e 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -3031,6 +3031,20 @@ if (BUSES["SUNKBD"]~=null) then } end +--------------------------------------------------- +-- +--@src/devices/bus/sunmouse/sunmouse.h,BUSES["SUNMOUSE"] = true +--------------------------------------------------- + +if (BUSES["SUNMOUSE"]~=null) then + files { + MAME_DIR .. "src/devices/bus/sunmouse/hlemouse.cpp", + MAME_DIR .. "src/devices/bus/sunmouse/hlemouse.h", + MAME_DIR .. "src/devices/bus/sunmouse/sunmouse.cpp", + MAME_DIR .. "src/devices/bus/sunmouse/sunmouse.h", + } +end + --------------------------------------------------- -- --@src/devices/bus/sbus/sbus.h,BUSES["SBUS"] = true -- cgit v1.2.3 From bcad4e9c09a322a09bf18628e2f7c6cd3e4c1c01 Mon Sep 17 00:00:00 2001 From: Nigel Barnes Date: Mon, 17 Sep 2018 19:18:38 +0100 Subject: bbcb: Added floppy disc controller options:- - AMS 3" Microdrive Disc System - Microware DDFS FDC (not working) --- scripts/src/bus.lua | 8 +- src/devices/bus/bbc/fdc/ams.cpp | 146 ++++++++++++++++++++++++++++ src/devices/bus/bbc/fdc/ams.h | 61 ++++++++++++ src/devices/bus/bbc/fdc/fdc.cpp | 8 +- src/devices/bus/bbc/fdc/microware.cpp | 176 ++++++++++++++++++++++++++++++++++ src/devices/bus/bbc/fdc/microware.h | 68 +++++++++++++ src/lib/formats/acorn_dsk.cpp | 4 + 7 files changed, 465 insertions(+), 6 deletions(-) create mode 100644 src/devices/bus/bbc/fdc/ams.cpp create mode 100644 src/devices/bus/bbc/fdc/ams.h create mode 100644 src/devices/bus/bbc/fdc/microware.cpp create mode 100644 src/devices/bus/bbc/fdc/microware.h (limited to 'scripts/src') diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index 662b2627c7e..7a1ff75d43a 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -107,12 +107,12 @@ if (BUSES["ACORN"]~=null) then files { MAME_DIR .. "src/devices/bus/acorn/bus.cpp", MAME_DIR .. "src/devices/bus/acorn/bus.h", - MAME_DIR .. "src/devices/bus/acorn/atom/sid.cpp", - MAME_DIR .. "src/devices/bus/acorn/atom/sid.h", MAME_DIR .. "src/devices/bus/acorn/atom/discpack.cpp", MAME_DIR .. "src/devices/bus/acorn/atom/discpack.h", MAME_DIR .. "src/devices/bus/acorn/atom/econet.cpp", MAME_DIR .. "src/devices/bus/acorn/atom/econet.h", + MAME_DIR .. "src/devices/bus/acorn/atom/sid.cpp", + MAME_DIR .. "src/devices/bus/acorn/atom/sid.h", MAME_DIR .. "src/devices/bus/acorn/cms/4080term.cpp", MAME_DIR .. "src/devices/bus/acorn/cms/4080term.h", MAME_DIR .. "src/devices/bus/acorn/cms/fdc.cpp", @@ -273,10 +273,14 @@ if (BUSES["BBC_FDC"]~=null) then MAME_DIR .. "src/devices/bus/bbc/fdc/fdc.h", MAME_DIR .. "src/devices/bus/bbc/fdc/acorn.cpp", MAME_DIR .. "src/devices/bus/bbc/fdc/acorn.h", + MAME_DIR .. "src/devices/bus/bbc/fdc/ams.cpp", + MAME_DIR .. "src/devices/bus/bbc/fdc/ams.h", MAME_DIR .. "src/devices/bus/bbc/fdc/cumana.cpp", MAME_DIR .. "src/devices/bus/bbc/fdc/cumana.h", MAME_DIR .. "src/devices/bus/bbc/fdc/cv1797.cpp", MAME_DIR .. "src/devices/bus/bbc/fdc/cv1797.h", + MAME_DIR .. "src/devices/bus/bbc/fdc/microware.cpp", + MAME_DIR .. "src/devices/bus/bbc/fdc/microware.h", MAME_DIR .. "src/devices/bus/bbc/fdc/opus.cpp", MAME_DIR .. "src/devices/bus/bbc/fdc/opus.h", MAME_DIR .. "src/devices/bus/bbc/fdc/watford.cpp", diff --git a/src/devices/bus/bbc/fdc/ams.cpp b/src/devices/bus/bbc/fdc/ams.cpp new file mode 100644 index 00000000000..2afc7c969a2 --- /dev/null +++ b/src/devices/bus/bbc/fdc/ams.cpp @@ -0,0 +1,146 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/********************************************************************** + + AMS 3" Microdrive Disc System + +**********************************************************************/ + + +#include "emu.h" +#include "ams.h" + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +DEFINE_DEVICE_TYPE(BBC_AMS3, bbc_ams3_device, "bbc_ams3", "AMS 3" Microdrive Disc System") + + +//------------------------------------------------- +// MACHINE_DRIVER( ams3 ) +//------------------------------------------------- + +FLOPPY_FORMATS_MEMBER( bbc_ams3_device::floppy_formats ) + FLOPPY_ACORN_SSD_FORMAT +FLOPPY_FORMATS_END + +ROM_START( ams3 ) + ROM_REGION(0x8000, "dfs_rom", 0) + ROM_LOAD("dfs098.rom", 0x0000, 0x2000, CRC(90852e7d) SHA1(6df3552d5426f3a4625b9a0c7829bdba03f05e84)) + ROM_RELOAD( 0x2000, 0x2000) + ROM_LOAD("amsdisc.rom", 0x4000, 0x1000, CRC(93876595) SHA1(a9d9123667e65334b28b8588b09642478653e356)) + ROM_RELOAD( 0x5000, 0x1000) + ROM_RELOAD( 0x6000, 0x1000) + ROM_RELOAD( 0x7000, 0x1000) +ROM_END + + +//------------------------------------------------- +// device_add_mconfig - add device configuration +//------------------------------------------------- + +void bbc_ams3_device::device_add_mconfig(machine_config &config) +{ + I8271(config, m_fdc, 16_MHz_XTAL / 8); + m_fdc->intrq_wr_callback().set(FUNC(bbc_ams3_device::fdc_intrq_w)); + m_fdc->hdl_wr_callback().set(FUNC(bbc_ams3_device::motor_w)); + m_fdc->opt_wr_callback().set(FUNC(bbc_ams3_device::side_w)); + // Hitachi HFD 305S + FLOPPY_CONNECTOR(config, m_floppy0, "3dsdd", FLOPPY_3_DSDD, true, bbc_ams3_device::floppy_formats).enable_sound(true); + FLOPPY_CONNECTOR(config, m_floppy1, "3dsdd", FLOPPY_3_DSDD, false, bbc_ams3_device::floppy_formats).enable_sound(true); +} + + +const tiny_rom_entry *bbc_ams3_device::device_rom_region() const +{ + return ROM_NAME( ams3 ); +} + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// bbc_ams3_device - constructor +//------------------------------------------------- + +bbc_ams3_device::bbc_ams3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, BBC_AMS3, tag, owner, clock) + , device_bbc_fdc_interface(mconfig, *this) + , m_dfs_rom(*this, "dfs_rom") + , m_fdc(*this, "i8271") + , m_floppy0(*this, "i8271:0") + , m_floppy1(*this, "i8271:1") +{ +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void bbc_ams3_device::device_start() +{ +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void bbc_ams3_device::device_reset() +{ + machine().root_device().membank("bank4")->configure_entry(12, memregion("dfs_rom")->base() + 0x0000); + machine().root_device().membank("bank4")->configure_entry(13, memregion("dfs_rom")->base() + 0x4000); +} + + +//************************************************************************** +// IMPLEMENTATION +//************************************************************************** + +READ8_MEMBER(bbc_ams3_device::read) +{ + uint8_t data; + + if (offset & 0x04) + { + data = m_fdc->data_r(space , 0); + } + else + { + data = m_fdc->read(space, offset & 0x03); + } + return data; +} + +WRITE8_MEMBER(bbc_ams3_device::write) +{ + if (offset & 0x04) + { + m_fdc->data_w(space, 0, data); + } + else + { + m_fdc->write(space, offset & 0x03, data); + } +} + +WRITE_LINE_MEMBER(bbc_ams3_device::motor_w) +{ + if (m_floppy0->get_device()) m_floppy0->get_device()->mon_w(!state); + if (m_floppy1->get_device()) m_floppy1->get_device()->mon_w(!state); + m_fdc->ready_w(!state); +} + +WRITE_LINE_MEMBER(bbc_ams3_device::side_w) +{ + if (m_floppy0->get_device()) m_floppy0->get_device()->ss_w(state); + if (m_floppy1->get_device()) m_floppy1->get_device()->ss_w(state); +} + +WRITE_LINE_MEMBER(bbc_ams3_device::fdc_intrq_w) +{ + m_slot->intrq_w(state); +} diff --git a/src/devices/bus/bbc/fdc/ams.h b/src/devices/bus/bbc/fdc/ams.h new file mode 100644 index 00000000000..acdb077b3f6 --- /dev/null +++ b/src/devices/bus/bbc/fdc/ams.h @@ -0,0 +1,61 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/********************************************************************** + + AMS 3" Microdrive Disc System + +**********************************************************************/ + + +#ifndef MAME_BUS_BBC_FDC_AMS_H +#define MAME_BUS_BBC_FDC_AMS_H + +#pragma once + +#include "fdc.h" +#include "machine/i8271.h" +#include "formats/acorn_dsk.h" + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +class bbc_ams3_device : + public device_t, + public device_bbc_fdc_interface +{ +public: + // construction/destruction + bbc_ams3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + DECLARE_FLOPPY_FORMATS(floppy_formats); + +protected: + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + + // optional information overrides + virtual void device_add_mconfig(machine_config &config) override; + virtual const tiny_rom_entry *device_rom_region() const override; + + virtual DECLARE_READ8_MEMBER(read) override; + virtual DECLARE_WRITE8_MEMBER(write) override; + +private: + DECLARE_WRITE_LINE_MEMBER(fdc_intrq_w); + DECLARE_WRITE_LINE_MEMBER(motor_w); + DECLARE_WRITE_LINE_MEMBER(side_w); + + required_memory_region m_dfs_rom; + required_device m_fdc; + required_device m_floppy0; + optional_device m_floppy1; +}; + + +// device type definition +DECLARE_DEVICE_TYPE(BBC_AMS3, bbc_ams3_device) + + +#endif // MAME_BUS_BBC_FDC_AMS_H diff --git a/src/devices/bus/bbc/fdc/fdc.cpp b/src/devices/bus/bbc/fdc/fdc.cpp index d3588ea9f6f..1db62be6357 100644 --- a/src/devices/bus/bbc/fdc/fdc.cpp +++ b/src/devices/bus/bbc/fdc/fdc.cpp @@ -114,10 +114,10 @@ WRITE8_MEMBER(bbc_fdc_slot_device::write) // slot devices #include "acorn.h" -//#include "ams.h" +#include "ams.h" #include "cumana.h" #include "cv1797.h" -//#include "microware.h" +#include "microware.h" #include "opus.h" //#include "solidisk.h" #include "watford.h" @@ -128,11 +128,11 @@ void bbc_fdc_devices(device_slot_interface &device) { device.option_add("acorn8271", BBC_ACORN8271); device.option_add("acorn1770", BBC_ACORN1770); - //device.option_add("ams3", BBC_AMS3); + device.option_add("ams3", BBC_AMS3); device.option_add("cumana1", BBC_CUMANA1); device.option_add("cumana2", BBC_CUMANA2); device.option_add("cv1797", BBC_CV1797); - //device.option_add("microware", BBC_MICROWARE); + device.option_add("microware", BBC_MICROWARE); device.option_add("opus8272", BBC_OPUS8272); device.option_add("opus2791", BBC_OPUS2791); device.option_add("opus2793", BBC_OPUS2793); diff --git a/src/devices/bus/bbc/fdc/microware.cpp b/src/devices/bus/bbc/fdc/microware.cpp new file mode 100644 index 00000000000..2dc527ea822 --- /dev/null +++ b/src/devices/bus/bbc/fdc/microware.cpp @@ -0,0 +1,176 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/********************************************************************** + + United Disk Memories DDFS FDC + + Microware DDFS FDC + +**********************************************************************/ + + +#include "emu.h" +#include "microware.h" + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +DEFINE_DEVICE_TYPE(BBC_MICROWARE, bbc_microware_device, "bbc_microware", "Microware DDFS FDC") + + +//------------------------------------------------- +// MACHINE_DRIVER( microware ) +//------------------------------------------------- + +FLOPPY_FORMATS_MEMBER( bbc_microware_device::floppy_formats ) + FLOPPY_ACORN_SSD_FORMAT, + FLOPPY_ACORN_DSD_FORMAT, + FLOPPY_FSD_FORMAT +FLOPPY_FORMATS_END + +static void bbc_floppies_525(device_slot_interface &device) +{ + device.option_add("525sssd", FLOPPY_525_SSSD); + device.option_add("525sd", FLOPPY_525_SD); + device.option_add("525ssdd", FLOPPY_525_SSDD); + device.option_add("525dd", FLOPPY_525_DD); + device.option_add("525qd", FLOPPY_525_QD); +} + +ROM_START( microware ) + ROM_REGION(0x4000, "dfs_rom", 0) + ROM_DEFAULT_BIOS("udm200") + ROM_SYSTEM_BIOS(0, "ddfs090", "Microware DDFS 0.90") + ROMX_LOAD("microware_ddfs090.rom", 0x0000, 0x4000, CRC(700d50e5) SHA1(6834e46cb15354003d553e6c2bdb4ed76b47a465), ROM_BIOS(0)) + ROM_SYSTEM_BIOS(1, "udm200", "UDM DDFS 2.00") + ROMX_LOAD("udm_ddfs200.rom", 0x0000, 0x4000, CRC(1b4708a2) SHA1(0f37bcc73a758657cfe58c19f0cc92be9107e767), ROM_BIOS(1)) +ROM_END + + +//------------------------------------------------- +// device_add_mconfig - add device configuration +//------------------------------------------------- + +void bbc_microware_device::device_add_mconfig(machine_config &config) +{ + WD2793(config, m_fdc, 16_MHz_XTAL / 16); // Replay advert suggests Type R8272 UDM DFS + m_fdc->intrq_wr_callback().set(FUNC(bbc_microware_device::fdc_intrq_w)); + m_fdc->drq_wr_callback().set(FUNC(bbc_microware_device::fdc_drq_w)); + m_fdc->hld_wr_callback().set(FUNC(bbc_microware_device::motor_w)); + + FLOPPY_CONNECTOR(config, m_floppy0, bbc_floppies_525, "525qd", floppy_formats).enable_sound(true); + FLOPPY_CONNECTOR(config, m_floppy1, bbc_floppies_525, "525qd", floppy_formats).enable_sound(true); +} + +const tiny_rom_entry *bbc_microware_device::device_rom_region() const +{ + return ROM_NAME( microware ); +} + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// bbc_microware_device - constructor +//------------------------------------------------- + +bbc_microware_device::bbc_microware_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, BBC_MICROWARE, tag, owner, clock) + , device_bbc_fdc_interface(mconfig, *this) + , m_dfs_rom(*this, "dfs_rom") + , m_fdc(*this, "wd2793") + , m_floppy0(*this, "wd2793:0") + , m_floppy1(*this, "wd2793:1") + , m_drive_control(0) +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void bbc_microware_device::device_start() +{ + save_item(NAME(m_drive_control)); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void bbc_microware_device::device_reset() +{ + machine().root_device().membank("bank4")->configure_entry(12, memregion("dfs_rom")->base()); +} + + +//************************************************************************** +// IMPLEMENTATION +//************************************************************************** + +READ8_MEMBER(bbc_microware_device::read) +{ + uint8_t data; + + if (offset & 0x04) + { + data = m_fdc->read(offset & 0x03); + } + else + { + data = m_drive_control; + } + return data; +} + +WRITE8_MEMBER(bbc_microware_device::write) +{ + if (offset & 0x04) + { + m_fdc->write(offset & 0x03, data); + } + else + { + floppy_image_device *floppy = nullptr; + + m_drive_control = data; + logerror("fdc: Drive control %02x \n", data); + // bit 0: drive select + switch (BIT(data, 0)) + { + case 0: floppy = m_floppy0->get_device(); break; + case 1: floppy = m_floppy1->get_device(); break; + } + m_fdc->set_floppy(floppy); + + // bit 1: side select + if (floppy) + floppy->ss_w(BIT(data, 1)); + + // bit 2: density + m_fdc->dden_w(BIT(data, 2)); + + // bit 3: always set ??? + + // bit 4: ??? interrupt + } +} + +WRITE_LINE_MEMBER(bbc_microware_device::fdc_intrq_w) +{ + m_slot->intrq_w(state); +} + +WRITE_LINE_MEMBER(bbc_microware_device::fdc_drq_w) +{ + m_slot->drq_w(state); +} + +WRITE_LINE_MEMBER(bbc_microware_device::motor_w) +{ + if (m_floppy0->get_device()) m_floppy0->get_device()->mon_w(!state); + if (m_floppy1->get_device()) m_floppy1->get_device()->mon_w(!state); +} diff --git a/src/devices/bus/bbc/fdc/microware.h b/src/devices/bus/bbc/fdc/microware.h new file mode 100644 index 00000000000..9d42eb2b668 --- /dev/null +++ b/src/devices/bus/bbc/fdc/microware.h @@ -0,0 +1,68 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/********************************************************************** + + United Disk Memories DDFS FDC + + Microware DDFS FDC + +**********************************************************************/ + + +#ifndef MAME_BUS_BBC_FDC_MICROWARE_H +#define MAME_BUS_BBC_FDC_MICROWARE_H + +#pragma once + +#include "fdc.h" +#include "machine/wd_fdc.h" +#include "formats/acorn_dsk.h" +#include "formats/fsd_dsk.h" + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +class bbc_microware_device : + public device_t, + public device_bbc_fdc_interface +{ +public: + static constexpr feature_type imperfect_features() { return feature::DISK; } + + // construction/destruction + bbc_microware_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + + // optional information overrides + virtual void device_add_mconfig(machine_config &config) override; + virtual const tiny_rom_entry *device_rom_region() const override; + + virtual DECLARE_READ8_MEMBER(read) override; + virtual DECLARE_WRITE8_MEMBER(write) override; + +private: + DECLARE_FLOPPY_FORMATS(floppy_formats); + + DECLARE_WRITE_LINE_MEMBER(fdc_intrq_w); + DECLARE_WRITE_LINE_MEMBER(fdc_drq_w); + DECLARE_WRITE_LINE_MEMBER(motor_w); + + required_memory_region m_dfs_rom; + required_device m_fdc; + required_device m_floppy0; + optional_device m_floppy1; + + int m_drive_control; +}; + + +// device type definition +DECLARE_DEVICE_TYPE(BBC_MICROWARE, bbc_microware_device); + + +#endif /* MAME_BUS_BBC_FDC_MICROWARE_H */ diff --git a/src/lib/formats/acorn_dsk.cpp b/src/lib/formats/acorn_dsk.cpp index 59261f9b4d5..d8992b9ad5a 100644 --- a/src/lib/formats/acorn_dsk.cpp +++ b/src/lib/formats/acorn_dsk.cpp @@ -127,6 +127,10 @@ const acorn_ssd_format::format acorn_ssd_format::formats[] = floppy_image::FF_35, floppy_image::DSDD, floppy_image::FM, 4000, 10, 80, 2, 256,{}, 0,{}, 40, 10, 10 }, + { // 100k 40 track single sided single density + floppy_image::FF_3, floppy_image::SSSD, floppy_image::FM, + 4000, 10, 40, 1, 256,{}, 0,{}, 40, 10, 10 + }, {} }; -- cgit v1.2.3 From 282ebf014d19ce688b9e1884ab5e8c34e9eb803c Mon Sep 17 00:00:00 2001 From: Nigel Barnes Date: Mon, 17 Sep 2018 19:42:45 +0100 Subject: bbc: Added Acorn Bitstik and Bitstik 2 analogue controllers. --- scripts/src/bus.lua | 2 + src/devices/bus/bbc/analogue/analogue.cpp | 6 +- src/devices/bus/bbc/analogue/bitstik.cpp | 143 ++++++++++++++++++++++++++++++ src/devices/bus/bbc/analogue/bitstik.h | 75 ++++++++++++++++ 4 files changed, 223 insertions(+), 3 deletions(-) create mode 100644 src/devices/bus/bbc/analogue/bitstik.cpp create mode 100644 src/devices/bus/bbc/analogue/bitstik.h (limited to 'scripts/src') diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index 7a1ff75d43a..c006658333b 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -298,6 +298,8 @@ if (BUSES["BBC_ANALOGUE"]~=null) then files { MAME_DIR .. "src/devices/bus/bbc/analogue/analogue.cpp", MAME_DIR .. "src/devices/bus/bbc/analogue/analogue.h", + MAME_DIR .. "src/devices/bus/bbc/analogue/bitstik.cpp", + MAME_DIR .. "src/devices/bus/bbc/analogue/bitstik.h", MAME_DIR .. "src/devices/bus/bbc/analogue/joystick.cpp", MAME_DIR .. "src/devices/bus/bbc/analogue/joystick.h", MAME_DIR .. "src/devices/bus/bbc/analogue/cfa3000a.cpp", diff --git a/src/devices/bus/bbc/analogue/analogue.cpp b/src/devices/bus/bbc/analogue/analogue.cpp index 44a3156f11c..facc1a827bc 100644 --- a/src/devices/bus/bbc/analogue/analogue.cpp +++ b/src/devices/bus/bbc/analogue/analogue.cpp @@ -104,7 +104,7 @@ void bbc_analogue_slot_device::device_reset() // slot devices #include "joystick.h" -//#include "bitstik.h" +#include "bitstik.h" //#include "lightpen.h" //#include "micromike.h" //#include "quinkey.h" @@ -114,8 +114,8 @@ void bbc_analogue_slot_device::device_reset() void bbc_analogue_devices(device_slot_interface &device) { device.option_add("acornjoy", BBC_ACORNJOY); /* Acorn ANH01 Joysticks */ - //device.option_add("bitstik1", BBC_BITSTIK1); /* Acorn ANF04 Bitstik */ - //device.option_add("bitstik2", BBC_BITSTIK2); /* Robocom Bitstik 2 */ + device.option_add("bitstik1", BBC_BITSTIK1); /* Acorn ANF04 Bitstik */ + device.option_add("bitstik2", BBC_BITSTIK2); /* Robocom Bitstik 2 */ //device.option_add("lightpen", BBC_LIGHTPEN); /* RH Electronics Lightpen */ //device.option_add("micromike", BBC_MICROMIKE); /* Micro Mike */ device.option_add("voltmace3b", BBC_VOLTMACE3B); /* Voltmace Delta 3b "Twin" Joysticks */ diff --git a/src/devices/bus/bbc/analogue/bitstik.cpp b/src/devices/bus/bbc/analogue/bitstik.cpp new file mode 100644 index 00000000000..42d8fff9504 --- /dev/null +++ b/src/devices/bus/bbc/analogue/bitstik.cpp @@ -0,0 +1,143 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/********************************************************************** + + Acorn ANF04 Bitstik + + http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Acorn_BitStik.html + + Robocom Bitstik 2 + +**********************************************************************/ + +#include "emu.h" +#include "bitstik.h" + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +DEFINE_DEVICE_TYPE(BBC_BITSTIK1, bbc_bitstik1_device, "bbc_bitstik1", "Acorn Bitstik") +DEFINE_DEVICE_TYPE(BBC_BITSTIK2, bbc_bitstik2_device, "bbc_bitstik2", "Robo Bitstik 2") + +//------------------------------------------------- +// ROM( bitstik ) +//------------------------------------------------- + +ROM_START(bitstik1) + ROM_REGION(0x4000, "rom", 0) + ROM_LOAD("bitstik1.rom", 0x0000, 0x2000, CRC(a3c539f8) SHA1(c6f2cf2f6d1e48819a8381c6a1c97ca8fa5ab117)) + ROM_RELOAD(0x2000, 0x2000) +ROM_END + +ROM_START(bitstik2) + ROM_REGION(0x4000, "rom", 0) + ROM_LOAD("bitstik2.rom", 0x0000, 0x2000, CRC(a2b5a743) SHA1(4d0040af6bdc6a587e42d4aa36d528b768cf9549)) + ROM_RELOAD(0x2000, 0x2000) +ROM_END + +//------------------------------------------------- +// INPUT_PORTS( bitstik ) +//------------------------------------------------- + +static INPUT_PORTS_START(bitstik) + PORT_START("CHANNEL0") + PORT_BIT(0xff, 0x00, IPT_AD_STICK_X) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(200) PORT_NAME("AD Stick X") PORT_REVERSE + + PORT_START("CHANNEL1") + PORT_BIT(0xff, 0x00, IPT_AD_STICK_Y) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(200) PORT_NAME("AD Stick Y") PORT_REVERSE + + PORT_START("CHANNEL2") + PORT_BIT(0xff, 0x00, IPT_AD_STICK_Z) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(200) PORT_NAME("AD Stick Z") PORT_REVERSE + + PORT_START("CHANNEL3") + PORT_BIT(0xff, IP_ACTIVE_HIGH, IPT_BUTTON3) PORT_NAME("Right Button - Release") + + PORT_START("BUTTONS") + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Top Button - Execute") + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_NAME("Left Button - Confirm") +INPUT_PORTS_END + +//------------------------------------------------- +// input_ports - device-specific input ports +//------------------------------------------------- + +ioport_constructor bbc_bitstik_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(bitstik); +} + +//------------------------------------------------- +// rom_region - device-specific ROM region +//------------------------------------------------- + +const tiny_rom_entry *bbc_bitstik1_device::device_rom_region() const +{ + return ROM_NAME(bitstik1); +} + +const tiny_rom_entry *bbc_bitstik2_device::device_rom_region() const +{ + return ROM_NAME(bitstik2); +} + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// bbc_bitstik_device - constructor +//------------------------------------------------- + +bbc_bitstik_device::bbc_bitstik_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, type, tag, owner, clock), + device_bbc_analogue_interface(mconfig, *this), + m_channel(*this, "CHANNEL%u", 0), + m_buttons(*this, "BUTTONS"), + m_rom(*this, "rom") +{ +} + +bbc_bitstik1_device::bbc_bitstik1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + bbc_bitstik_device(mconfig, BBC_BITSTIK1, tag, owner, clock) +{ +} + +bbc_bitstik2_device::bbc_bitstik2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + bbc_bitstik_device(mconfig, BBC_BITSTIK2, tag, owner, clock) +{ +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void bbc_bitstik_device::device_start() +{ +} + + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void bbc_bitstik_device::device_reset() +{ + machine().root_device().membank("bank4")->configure_entry(13, memregion("rom")->base()); +} + + +//************************************************************************** +// IMPLEMENTATION +//************************************************************************** + +uint8_t bbc_bitstik_device::ch_r(int channel) +{ + return m_channel[channel]->read(); +} + +uint8_t bbc_bitstik_device::pb_r() +{ + return m_buttons->read() & 0x30; +} diff --git a/src/devices/bus/bbc/analogue/bitstik.h b/src/devices/bus/bbc/analogue/bitstik.h new file mode 100644 index 00000000000..3319bfe0c2e --- /dev/null +++ b/src/devices/bus/bbc/analogue/bitstik.h @@ -0,0 +1,75 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/********************************************************************** + + Acorn ANF04 Bitstik + + http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Acorn_BitStik.html + + Robocom Bitstik 2 + +**********************************************************************/ + + +#ifndef MAME_BUS_BBC_ANALOGUE_BITSTIK_H +#define MAME_BUS_BBC_ANALOGUE_BITSTIK_H + +#pragma once + + +#include "analogue.h" + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> bbc_bitstik_device + +class bbc_bitstik_device : + public device_t, + public device_bbc_analogue_interface +{ +protected: + // construction/destruction + bbc_bitstik_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + + // optional information overrides + virtual ioport_constructor device_input_ports() const override; + + virtual uint8_t ch_r(int channel) override; + virtual uint8_t pb_r() override; + +private: + required_ioport_array<4> m_channel; + required_ioport m_buttons; + required_memory_region m_rom; +}; + +class bbc_bitstik1_device : public bbc_bitstik_device +{ +public: + bbc_bitstik1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + virtual const tiny_rom_entry *device_rom_region() const override; +}; + +class bbc_bitstik2_device : public bbc_bitstik_device +{ +public: + bbc_bitstik2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + virtual const tiny_rom_entry *device_rom_region() const override; +}; + +// device type definition +DECLARE_DEVICE_TYPE(BBC_BITSTIK1, bbc_bitstik1_device) +DECLARE_DEVICE_TYPE(BBC_BITSTIK2, bbc_bitstik2_device) + + +#endif // MAME_BUS_BBC_ANALOGUE_BITSTIK_H -- cgit v1.2.3 From b5758f5273e030845f94678ae8a4302c5d3343c2 Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Wed, 19 Sep 2018 20:00:56 +1000 Subject: Re-write serial mouse support: * Separate Microsoft 2-button mouse and Logitech 3-button Microsoft-compatible mouse * Add Microsoft wheel mouse * Make Mouse Systems mouse behave more realistically * Add Mouse Systems "rotatable" mouse * Simplify code and eliminate timers (nw) X/Y translation and buttons works for all devices. The wheel on the wheel mouse seems to be transmitting the right data, and CuteMouse detects the wheel as being present, but no software seems to support it properly. Software supporting the Mouse Systems "rotatable" mouse is very rare - typically people just set the DIP switches on their M-1 for "non-rotatable" mode. A standard mouse driver will see the "rotatable" mouse moving two mickeys for each count, and move eratically on rotation. The "rotable" mouse is poorly tested due to lack of software. (nw) MAME doesn't have a proper input type for a mouse wheel, and it doesn't seem to be possible to map the host mouse wheel to an axis when configuring inputs. The default mapping ends up assigining the wheel or rotation to one of the translation axes, which is very unhelpful. --- scripts/src/bus.lua | 4 +- src/devices/bus/isa/com.cpp | 18 +- src/devices/bus/rs232/hlemouse.cpp | 691 ++++++++++++++++++++++++++++++++++ src/devices/bus/rs232/hlemouse.h | 221 +++++++++++ src/devices/bus/rs232/ser_mouse.cpp | 267 ------------- src/devices/bus/rs232/ser_mouse.h | 84 ----- src/devices/bus/sunmouse/hlemouse.cpp | 4 +- src/emu/diserial.h | 24 +- src/mame/drivers/ibmpcjr.cpp | 9 +- src/mame/drivers/pcat_dyn.cpp | 4 +- src/mame/drivers/pcipc.cpp | 15 +- src/mame/drivers/pcw16.cpp | 4 +- src/mame/drivers/rainbow.cpp | 9 +- 13 files changed, 967 insertions(+), 387 deletions(-) create mode 100644 src/devices/bus/rs232/hlemouse.cpp create mode 100644 src/devices/bus/rs232/hlemouse.h delete mode 100644 src/devices/bus/rs232/ser_mouse.cpp delete mode 100644 src/devices/bus/rs232/ser_mouse.h (limited to 'scripts/src') diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index c006658333b..0abd88b3765 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -2028,8 +2028,8 @@ if (BUSES["RS232"]~=null) then MAME_DIR .. "src/devices/bus/rs232/rs232.h", MAME_DIR .. "src/devices/bus/rs232/pty.cpp", MAME_DIR .. "src/devices/bus/rs232/pty.h", - MAME_DIR .. "src/devices/bus/rs232/ser_mouse.cpp", - MAME_DIR .. "src/devices/bus/rs232/ser_mouse.h", + MAME_DIR .. "src/devices/bus/rs232/hlemouse.cpp", + MAME_DIR .. "src/devices/bus/rs232/hlemouse.h", MAME_DIR .. "src/devices/bus/rs232/sun_kbd.cpp", MAME_DIR .. "src/devices/bus/rs232/sun_kbd.h", MAME_DIR .. "src/devices/bus/rs232/terminal.cpp", diff --git a/src/devices/bus/isa/com.cpp b/src/devices/bus/isa/com.cpp index 57393a52500..bd2b500d611 100644 --- a/src/devices/bus/isa/com.cpp +++ b/src/devices/bus/isa/com.cpp @@ -8,18 +8,24 @@ #include "emu.h" #include "com.h" + +#include "bus/rs232/hlemouse.h" +#include "bus/rs232/null_modem.h" #include "bus/rs232/rs232.h" -#include "bus/rs232/ser_mouse.h" +#include "bus/rs232/sun_kbd.h" #include "bus/rs232/terminal.h" -#include "bus/rs232/null_modem.h" #include "machine/ins8250.h" static void isa_com(device_slot_interface &device) { - device.option_add("microsoft_mouse", MSFT_SERIAL_MOUSE); - device.option_add("msystems_mouse", MSYSTEM_SERIAL_MOUSE); + device.option_add("microsoft_mouse", MSFT_HLE_SERIAL_MOUSE); + device.option_add("logitech_mouse", LOGITECH_HLE_SERIAL_MOUSE); + device.option_add("wheel_mouse", WHEEL_HLE_SERIAL_MOUSE); + device.option_add("msystems_mouse", MSYSTEMS_HLE_SERIAL_MOUSE); + device.option_add("rotatable_mouse", ROTATABLE_HLE_SERIAL_MOUSE); device.option_add("terminal", SERIAL_TERMINAL); device.option_add("null_modem", NULL_MODEM); + device.option_add("sun_kbd", SUN_KBD_ADAPTOR); } @@ -55,7 +61,7 @@ MACHINE_CONFIG_START(isa8_com_device::device_add_mconfig) uart3.out_rts_callback().set("serport3", FUNC(rs232_port_device::write_rts)); uart3.out_int_callback().set(FUNC(isa8_com_device::pc_com_interrupt_2));*/ - MCFG_DEVICE_ADD( "serport0", RS232_PORT, isa_com, "microsoft_mouse" ) + MCFG_DEVICE_ADD( "serport0", RS232_PORT, isa_com, "logitech_mouse" ) MCFG_RS232_RXD_HANDLER(WRITELINE(uart0, ins8250_uart_device, rx_w)) MCFG_RS232_DCD_HANDLER(WRITELINE(uart0, ins8250_uart_device, dcd_w)) MCFG_RS232_DSR_HANDLER(WRITELINE(uart0, ins8250_uart_device, dsr_w)) @@ -156,7 +162,7 @@ MACHINE_CONFIG_START(isa8_com_at_device::device_add_mconfig) uart3.out_dtr_callback().set("serport3", FUNC(rs232_port_device::write_dtr)); uart3.out_rts_callback().set("serport3", FUNC(rs232_port_device::write_rts)); uart3.out_int_callback().set(FUNC(isa8_com_device::pc_com_interrupt_2));*/ - MCFG_DEVICE_ADD( "serport0", RS232_PORT, isa_com, "microsoft_mouse" ) + MCFG_DEVICE_ADD( "serport0", RS232_PORT, isa_com, "logitech_mouse" ) MCFG_RS232_RXD_HANDLER(WRITELINE(uart0, ins8250_uart_device, rx_w)) MCFG_RS232_DCD_HANDLER(WRITELINE(uart0, ins8250_uart_device, dcd_w)) MCFG_RS232_DSR_HANDLER(WRITELINE(uart0, ins8250_uart_device, dsr_w)) diff --git a/src/devices/bus/rs232/hlemouse.cpp b/src/devices/bus/rs232/hlemouse.cpp new file mode 100644 index 00000000000..caf9ebcdb57 --- /dev/null +++ b/src/devices/bus/rs232/hlemouse.cpp @@ -0,0 +1,691 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/************************************************************************** + + PC Serial Mouse Simulation + + Microsoft mouse is the classic two-button PC mouse. Data is 7N1 at + 1,200 Baud. Mouse can be reset by de-asserting RTS. On start, the + mouse identifies itself with the string "M". Bit 6 is only set for + the first byte of a report - it's clear for all subsequent bytes of + a report, and also for all identification bytes. + + Reports consist of three bytes: the first byte contains the button + state and the two high bits of the Y and X delta; the second byte + contains the low six bits of the X delta; the third byte contains + the low six bits of the Y delta. Button bits are set when pressed, + and positive delta is rightwards/downwards. + + 1lryyxx 0xxxxxx 0yyyyyy + + Logitech extended the Microsoft protocol to support a third button. + The mouse identifies itself with the string "M3". If the third + button changes state, and additional byte is sent indicating the + new state of the third button. + + 1lryyxx 0xxxxxx 0yyyyyy 0m00000 + + The serial wheel mouse protocol extends the Microsoft mouse protocol + in a different way. The mouse identifies itself with the string + "MZ@\0\0\0". If the third button or wheel state changes, a fourth + an additional byte is sent containing the third button state and a + four-bit wheel delta value. The wheel value is positive for + downward movement. Note that the third button is value is in a + different position to the logitech protocol. + + 1lryyxx 0xxxxxx 0yyyyyy 00mwwww + + The Mouse Systems non-rotatable protocol provides two-axis movement + and three buttons. Data is 8N1 at 1,200 Baud (the M-1 mouse could + also be configured for 300 Baud by turning DIP switch 1 off). The + mouse does not send an identification string. The first byte of a + report can be identified by a fixed pattern in the five most + significant bits. + + Reports are five bytes long. The first byte contains the the button + state; the second and fourth bytes contain X delta; the third and + fifth bytes contain Y delta. The two delta values for each axis + should be summed. Delta values range from -120 to 127 to prevent + being mistaken for the lead byte of a report. Button bits are clear + when set, and positive delta is rightwards/upwards. Delta values + are generated immediately before transmission - reports are not + atomic. + + 10000lmr xxxxxxxx yyyyyyyy xxxxxxxx yyyyyyyy + + The Mouse systems rotatable protcol allows the host to infer + rotation around the third axis at the cost of halving the maximum + sustained movement speed. The M-1 mouse has two sensors spaced 100 + counts apart horizontally. If DIP switch 2 is on, the X and Y delta + for each sensor is reported separately. The right sensor delta is + reported before the left sensor delta. If the mouse is rotated, the + delta values for the two sensors will differ. + +**************************************************************************/ + +#include "emu.h" +#include "hlemouse.h" + +#include +#include + + +//************************************************** +// Device type globals +//************************************************** + +DEFINE_DEVICE_TYPE_NS(MSFT_HLE_SERIAL_MOUSE, bus::rs232, hle_msft_mouse_device, "rs232_mouse_hle_msft", "Microsoft 2-Button Serial Mouse (HLE)") +DEFINE_DEVICE_TYPE_NS(LOGITECH_HLE_SERIAL_MOUSE, bus::rs232, hle_logitech_mouse_device, "rs232_mouse_hle_logitech", "Logitech 3-Button Serial Mouse (HLE)") +DEFINE_DEVICE_TYPE_NS(WHEEL_HLE_SERIAL_MOUSE, bus::rs232, hle_wheel_mouse_device, "rs232_mouse_hle_wheel", "Microsoft Serial Mouse with Wheel (HLE)") +DEFINE_DEVICE_TYPE_NS(MSYSTEMS_HLE_SERIAL_MOUSE, bus::rs232, hle_msystems_mouse_device, "rs232_mouse_hle_msystems", "Mouse Systems Non-rotatable Mouse (HLE)") +DEFINE_DEVICE_TYPE_NS(ROTATABLE_HLE_SERIAL_MOUSE, bus::rs232, hle_rotatable_mouse_device, "rs232_mouse_hle_rotatable", "Mouse Systems Rotatable Mouse (HLE)") + +namespace bus { namespace rs232 { + +namespace { + +INPUT_PORTS_START(msft) + PORT_START("BTN") + PORT_BIT( 0xfffc, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_CODE(MOUSECODE_BUTTON1) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_msmouse_device_base, input_changed, nullptr) + PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_CODE(MOUSECODE_BUTTON3) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_msmouse_device_base, input_changed, nullptr) + + PORT_START("X") + PORT_BIT( 0xf000, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x0fff, 0x00, IPT_MOUSE_X ) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_msmouse_device_base, input_changed, nullptr) + + PORT_START("Y") + PORT_BIT( 0xf000, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x0fff, 0x00, IPT_MOUSE_Y ) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_msmouse_device_base, input_changed, nullptr) +INPUT_PORTS_END + + +INPUT_PORTS_START(logitech) + PORT_INCLUDE(msft) + + PORT_MODIFY("BTN") + PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_CODE(MOUSECODE_BUTTON2) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_msmouse_device_base, input_changed, nullptr) + PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_CODE(MOUSECODE_BUTTON3) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_msmouse_device_base, input_changed, nullptr) +INPUT_PORTS_END + + +INPUT_PORTS_START(wheel) + PORT_INCLUDE(logitech) + + PORT_START("WHEEL") + PORT_BIT( 0xf000, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x0fff, 0x00, IPT_DIAL_V ) PORT_SENSITIVITY(10) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_msmouse_device_base, input_changed, nullptr) +INPUT_PORTS_END + + +INPUT_PORTS_START(msystems) + PORT_START("BTN") + PORT_BIT( 0xfff8, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_CODE(MOUSECODE_BUTTON1) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_msystems_device_base, input_changed, nullptr) + PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_CODE(MOUSECODE_BUTTON2) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_msystems_device_base, input_changed, nullptr) + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_CODE(MOUSECODE_BUTTON3) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_msystems_device_base, input_changed, nullptr) + + PORT_START("X") + PORT_BIT( 0xf000, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x0fff, 0x00, IPT_MOUSE_X ) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_msystems_device_base, input_changed, nullptr) + + PORT_START("Y") + PORT_BIT( 0xf000, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x0fff, 0x00, IPT_MOUSE_Y ) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_msystems_device_base, input_changed, nullptr) +INPUT_PORTS_END + + +INPUT_PORTS_START(rotatable) + PORT_INCLUDE(msystems) + + PORT_START("ROT") + PORT_BIT( 0xf000, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x0fff, 0x00, IPT_DIAL ) PORT_SENSITIVITY(10) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_msystems_device_base, input_changed, nullptr) +INPUT_PORTS_END + + +template +std::make_signed_t read_axis(ioport_port &port, T &val) +{ + static_assert((1U < Bits) && ((sizeof(T) * 8) > Bits), "invalid field bits"); + + T const updated(T(std::make_unsigned_t(port.read())) & make_bitmask(Bits)); + std::make_signed_t delta(std::make_signed_t(updated) - std::make_signed_t(val)); + if (std::make_signed_t(std::make_unsigned_t(1) << (Bits - 1)) <= delta) + delta -= std::make_signed_t(std::make_unsigned_t(1) << Bits); + else if (-std::make_signed_t(std::make_unsigned_t(1) << (Bits - 1)) >= delta) + delta += std::make_signed_t(std::make_unsigned_t(1) << Bits); + val = updated; + return delta; +} + + +template +uint8_t report_axis(T &delta, T low, T high) +{ + T const result(std::min(std::max(delta, low), high)); + delta -= result; + return uint8_t(int8_t(result)); +} + +} // anonymous namespace + + +//************************************************** +// Microsoft mouse base +//************************************************** + +INPUT_CHANGED_MEMBER(hle_msmouse_device_base::input_changed) +{ + if (fifo_empty() && is_transmit_register_empty()) + check_inputs(); +} + +hle_msmouse_device_base::hle_msmouse_device_base( + machine_config const &mconfig, + device_type type, + char const *tag, + device_t *owner, + uint32_t clock) + : buffered_rs232_device<8>(mconfig, type, tag, owner, clock) + , m_buttons(*this, "BTN") + , m_x_axis(*this, "X") + , m_y_axis(*this, "Y") + , m_x_delta(0) + , m_y_delta(0) + , m_x_val(0U) + , m_y_val(0U) + , m_btn_val(0x00U) + , m_btn_sent(0x00U) + , m_dtr(0U) + , m_rts(0U) + , m_enable(0U) +{ +} + +void hle_msmouse_device_base::device_resolve_objects() +{ + buffered_rs232_device<8>::device_resolve_objects(); + + m_dtr = 0U; + m_rts = 0U; +} + +void hle_msmouse_device_base::device_start() +{ + buffered_rs232_device<8>::device_start(); + + save_item(NAME(m_x_delta)); + save_item(NAME(m_y_delta)); + save_item(NAME(m_x_val)); + save_item(NAME(m_y_val)); + save_item(NAME(m_btn_val)); + save_item(NAME(m_btn_sent)); + save_item(NAME(m_dtr)); + save_item(NAME(m_rts)); + save_item(NAME(m_enable)); + + set_data_frame(1, 7, PARITY_NONE, STOP_BITS_2); + set_rate(1'200); + receive_register_reset(); + transmit_register_reset(); + + m_x_delta = m_y_delta = 0; + m_x_val = m_y_val = 0U; + m_btn_val = m_btn_sent = 0x00U; + m_enable = 0U; + + machine().scheduler().synchronize(timer_expired_delegate(FUNC(hle_msmouse_device_base::start_mouse), this)); +} + +WRITE_LINE_MEMBER(hle_msmouse_device_base::input_dtr) +{ + m_dtr = state ? 1U : 0U; + check_enable(); +} + +WRITE_LINE_MEMBER(hle_msmouse_device_base::input_rts) +{ + m_dtr = state ? 1U : 0U; + check_enable(); +} + +void hle_msmouse_device_base::tra_complete() +{ + buffered_rs232_device<8>::tra_complete(); + if (fifo_empty() && is_transmit_register_empty()) + check_inputs(); +} + +void hle_msmouse_device_base::received_byte(u8 byte) +{ +} + + +TIMER_CALLBACK_MEMBER(hle_msmouse_device_base::start_mouse) +{ + check_enable(); +} + +void hle_msmouse_device_base::check_enable() +{ + bool const enable(!m_dtr && !m_rts); + if (bool(m_enable) != enable) + { + m_enable = enable ? 1U : 0U; + clear_fifo(); + receive_register_reset(); + transmit_register_reset(); + if (enable) + { + read_inputs(); + m_x_delta = m_y_delta = 0; + m_btn_sent = m_btn_val; + reset_and_identify(); + } + } +} + +void hle_msmouse_device_base::check_inputs() +{ + if (m_enable && read_inputs()) + { + uint8_t const x(report_axis(m_x_delta, -128, 127)); + uint8_t const y(report_axis(m_y_delta, -128, 127)); + transmit_byte(0x40U | ((m_btn_val << 4) & 0x30U) | ((y >> 4) & 0x0cU) | ((x >> 6) & 0x03U)); + transmit_byte(x & 0x3fU); + transmit_byte(y & 0x3fU); + transmit_extensions(m_btn_val, m_btn_sent); + m_btn_sent = m_btn_val; + } +} + +bool hle_msmouse_device_base::read_inputs() +{ + m_x_delta += read_axis<12>(*m_x_axis, m_x_val); + m_y_delta += read_axis<12>(*m_y_axis, m_y_val); + m_btn_val = m_buttons->read(); + return m_x_delta || m_y_delta || (m_btn_val != m_btn_sent); +} + + +//************************************************** +// Microsoft 2-button mouse +//************************************************** + +hle_msft_mouse_device::hle_msft_mouse_device( + machine_config const &mconfig, + char const *tag, + device_t *owner, + uint32_t clock) + : hle_msmouse_device_base(mconfig, MSFT_HLE_SERIAL_MOUSE, tag, owner, clock) +{ +} + +ioport_constructor hle_msft_mouse_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(msft); +} + +void hle_msft_mouse_device::reset_and_identify() +{ + // assume ASCII host system + transmit_byte('M'); +} + +void hle_msft_mouse_device::transmit_extensions(uint8_t btn_val, uint8_t btn_sent) +{ +} + + +//************************************************** +// Logitech 3-button mouse +//************************************************** + +hle_logitech_mouse_device::hle_logitech_mouse_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock) + : hle_msmouse_device_base(mconfig, LOGITECH_HLE_SERIAL_MOUSE, tag, owner, clock) +{ +} + +ioport_constructor hle_logitech_mouse_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(logitech); +} + +void hle_logitech_mouse_device::reset_and_identify() +{ + // assume ASCII host system + transmit_byte('M'); + transmit_byte('3'); +} + +void hle_logitech_mouse_device::transmit_extensions(uint8_t btn_val, uint8_t btn_sent) +{ + if (BIT(btn_val | btn_sent, 2)) + transmit_byte(BIT(btn_val, 2) << 5); +} + + + +//************************************************** +// Microsoft wheel mouse +//************************************************** + +hle_wheel_mouse_device::hle_wheel_mouse_device( + machine_config const &mconfig, + char const *tag, + device_t *owner, + uint32_t clock) + : hle_msmouse_device_base(mconfig, WHEEL_HLE_SERIAL_MOUSE, tag, owner, clock) + , m_wheel(*this, "WHEEL") + , m_wheel_delta(0) + , m_wheel_val(0U) +{ +} + +ioport_constructor hle_wheel_mouse_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(wheel); +} + +void hle_wheel_mouse_device::device_start() +{ + hle_msmouse_device_base::device_start(); + + save_item(NAME(m_wheel_delta)); + save_item(NAME(m_wheel_val)); + + m_wheel_delta = 0; + m_wheel_val = 0U; +} + +bool hle_wheel_mouse_device::read_inputs() +{ + m_wheel_delta += read_axis<12>(*m_wheel, m_wheel_val); + return hle_msmouse_device_base::read_inputs() || m_wheel_delta; +} + +void hle_wheel_mouse_device::reset_and_identify() +{ + m_wheel_delta = 0; + + // assume ASCII host system + transmit_byte('M'); + transmit_byte('Z'); + transmit_byte('@'); + transmit_byte('\0'); + transmit_byte('\0'); + transmit_byte('\0'); +} + +void hle_wheel_mouse_device::transmit_extensions(uint8_t btn_val, uint8_t btn_sent) +{ + if (BIT(btn_val | btn_sent, 2) || m_wheel_delta) + transmit_byte((BIT(btn_val, 2) << 4) | (report_axis(m_wheel_delta, -8, 7) & 0x0fU)); +} + + +//************************************************** +// Mouse Systems mouse base +//************************************************** + +INPUT_CHANGED_MEMBER(hle_msystems_device_base::input_changed) +{ + if (is_transmit_register_empty()) + { + assert(0U == m_phase); + tra_complete(); + } +} + +hle_msystems_device_base::hle_msystems_device_base( + machine_config const &mconfig, + device_type type, + char const *tag, + device_t *owner, + uint32_t clock) + : device_t(mconfig, type, tag, owner, clock) + , device_rs232_port_interface(mconfig, *this) + , device_serial_interface(mconfig, *this) + , m_phase(0U) +{ +} + +void hle_msystems_device_base::device_start() +{ + save_item(NAME(m_phase)); + + set_data_frame(1, 8, PARITY_NONE, STOP_BITS_1); + set_rate(1'200); + receive_register_reset(); + transmit_register_reset(); + + m_phase = 0U; + + machine().scheduler().synchronize(timer_expired_delegate(FUNC(hle_msystems_device_base::start_mouse), this)); +} + +void hle_msystems_device_base::tra_callback() +{ + output_rxd(transmit_register_get_data_bit()); +} + +void hle_msystems_device_base::tra_complete() +{ + if (4U <= m_phase) + m_phase = 0U; + else + ++m_phase; + + bool const dirty(read_inputs()); + switch (m_phase) + { + case 0U: + if (dirty) + transmit_register_setup((report_buttons() & 0x07U) | 0x80U); + break; + case 1U: + transmit_register_setup(report_x1_delta()); + break; + case 2U: + transmit_register_setup(report_y1_delta()); + break; + case 3U: + transmit_register_setup(report_x2_delta()); + break; + case 4U: + transmit_register_setup(report_y2_delta()); + break; + }; +} + +TIMER_CALLBACK_MEMBER(hle_msystems_device_base::start_mouse) +{ + if (is_transmit_register_empty()) + { + assert(0U == m_phase); + tra_complete(); + } +} + + +//************************************************** +// Mouse Systems non-rotatable mouse +//************************************************** + +hle_msystems_mouse_device::hle_msystems_mouse_device( + machine_config const &mconfig, + char const *tag, + device_t *owner, + uint32_t clock) + : hle_msystems_device_base(mconfig, MSYSTEMS_HLE_SERIAL_MOUSE, tag, owner, clock) + , m_buttons(*this, "BTN") + , m_x_axis(*this, "X") + , m_y_axis(*this, "Y") + , m_x_delta(0) + , m_y_delta(0) + , m_x_val(0U) + , m_y_val(0U) + , m_btn_val(0x00U) + , m_btn_sent(0x00U) +{ +} + +ioport_constructor hle_msystems_mouse_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(msystems); +} + +void hle_msystems_mouse_device::device_start() +{ + hle_msystems_device_base::device_start(); + + save_item(NAME(m_x_delta)); + save_item(NAME(m_y_delta)); + save_item(NAME(m_x_val)); + save_item(NAME(m_y_val)); + save_item(NAME(m_btn_val)); + save_item(NAME(m_btn_sent)); + + m_x_delta = m_y_delta = 0; + m_x_val = m_y_val = 0U; + m_btn_val = m_btn_sent = 0x00U; +} + +bool hle_msystems_mouse_device::read_inputs() +{ + m_x_delta += read_axis<12>(*m_x_axis, m_x_val); + m_y_delta -= read_axis<12>(*m_y_axis, m_y_val); + m_btn_val = m_buttons->read(); + return m_x_delta || m_y_delta || (m_btn_val != m_btn_sent); +} + +uint8_t hle_msystems_mouse_device::report_buttons() +{ + m_btn_sent = m_btn_val; + return m_btn_sent; +} + +uint8_t hle_msystems_mouse_device::report_x1_delta() +{ + return report_axis(m_x_delta, -120, 127); +} + +uint8_t hle_msystems_mouse_device::report_y1_delta() +{ + return report_axis(m_y_delta, -120, 127); +} + +uint8_t hle_msystems_mouse_device::report_x2_delta() +{ + return report_axis(m_x_delta, -120, 127); +} + +uint8_t hle_msystems_mouse_device::report_y2_delta() +{ + return report_axis(m_y_delta, -120, 127); +} + + +//************************************************** +// Mouse Systems rotatable mouse +//************************************************** + +hle_rotatable_mouse_device::hle_rotatable_mouse_device( + machine_config const &mconfig, + char const *tag, + device_t *owner, + uint32_t clock) + : hle_msystems_device_base(mconfig, ROTATABLE_HLE_SERIAL_MOUSE, tag, owner, clock) + , m_buttons(*this, "BTN") + , m_x_axis(*this, "X") + , m_y_axis(*this, "Y") + , m_rotation(*this, "ROT") + , m_x_delta{ 0, 0 } + , m_y_delta{ 0, 0 } + , m_x_val(0U) + , m_y_val(0U) + , m_rot_val(0U) + , m_btn_val(0x00U) + , m_btn_sent(0x00U) +{ +} + +ioport_constructor hle_rotatable_mouse_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(rotatable); +} + +void hle_rotatable_mouse_device::device_start() +{ + hle_msystems_device_base::device_start(); + + save_item(NAME(m_x_delta)); + save_item(NAME(m_y_delta)); + save_item(NAME(m_x_val)); + save_item(NAME(m_y_val)); + save_item(NAME(m_rot_val)); + save_item(NAME(m_btn_val)); + save_item(NAME(m_btn_sent)); + + m_x_delta[0] = m_x_delta[1] = m_y_delta[0] = m_y_delta[1] = 0; + m_x_val = m_y_val = m_rot_val = 0U; + m_btn_val = m_btn_sent = 0x00U; +} + +bool hle_rotatable_mouse_device::read_inputs() +{ + // translation is straighforward + int16_t const x_delta(read_axis<12>(*m_x_axis, m_x_val)); + int16_t const y_delta(read_axis<12>(*m_y_axis, m_y_val)); + m_x_delta[0] += x_delta; + m_x_delta[1] += x_delta; + m_y_delta[0] -= y_delta; + m_y_delta[1] -= y_delta; + + // there are two sensors 100 counts apart, one inch below the centre of the mouse + // for simplicity, assume the mouse is rotated around the point midway the sensors + int16_t const rot_delta(read_axis<12>(*m_rotation, m_rot_val)); + if (rot_delta) + { + double const rot_angle(-0.15 * rot_delta); + long const x_diff(std::lround((1 - std::cos(rot_angle)) * 100)); + long const y_diff(std::lround(std::sin(rot_angle) * 100)); + m_x_delta[0] -= x_diff / 2; + m_x_delta[1] += x_diff - (x_diff / 2); + m_y_delta[0] += y_diff / 2; + m_y_delta[1] -= y_diff - (y_diff / 2); + } + + // this is straightforward, too + m_btn_val = m_buttons->read(); + return m_x_delta[0] || m_x_delta[1] || m_y_delta[0] || m_y_delta[1] || (m_btn_val != m_btn_sent); +} + +uint8_t hle_rotatable_mouse_device::report_buttons() +{ + m_btn_sent = m_btn_val; + return m_btn_sent; +} + +uint8_t hle_rotatable_mouse_device::report_x1_delta() +{ + return report_axis(m_x_delta[0], -120, 127); +} + +uint8_t hle_rotatable_mouse_device::report_y1_delta() +{ + return report_axis(m_y_delta[0], -120, 127); +} + +uint8_t hle_rotatable_mouse_device::report_x2_delta() +{ + return report_axis(m_x_delta[1], -120, 127); +} + +uint8_t hle_rotatable_mouse_device::report_y2_delta() +{ + return report_axis(m_y_delta[1], -120, 127); +} + +} } // namespace bus::rs232 diff --git a/src/devices/bus/rs232/hlemouse.h b/src/devices/bus/rs232/hlemouse.h new file mode 100644 index 00000000000..be3142ad118 --- /dev/null +++ b/src/devices/bus/rs232/hlemouse.h @@ -0,0 +1,221 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/************************************************************************** + + PC Serial Mouse Simulation + +**************************************************************************/ +#ifndef MAME_BUS_RS232_HLEMOUSE_H +#define MAME_BUS_RS232_HLEMOUSE_H + +#pragma once + +#include "rs232.h" +#include "diserial.h" + +#include + + +namespace bus { namespace rs232 { + +//************************************************** +// Microsoft mouse base +//************************************************** + +class hle_msmouse_device_base : public buffered_rs232_device<8> +{ +public: + DECLARE_INPUT_CHANGED_MEMBER(input_changed); + +protected: + hle_msmouse_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, uint32_t clock); + + virtual void device_resolve_objects() override; + virtual void device_start() override; + + virtual DECLARE_WRITE_LINE_MEMBER(input_dtr) override; + virtual DECLARE_WRITE_LINE_MEMBER(input_rts) override; + + virtual void tra_complete() override; + + virtual void received_byte(u8 byte) override; + + virtual bool read_inputs(); + +private: + TIMER_CALLBACK_MEMBER(start_mouse); + void check_enable(); + void check_inputs(); + + virtual void reset_and_identify() = 0; + virtual void transmit_extensions(uint8_t btn_val, uint8_t btn_sent) = 0; + + required_ioport m_buttons, m_x_axis, m_y_axis; + int16_t m_x_delta, m_y_delta; + uint16_t m_x_val, m_y_val; + uint8_t m_btn_val, m_btn_sent; + uint8_t m_dtr, m_rts, m_enable; +}; + + +//************************************************** +// Microsoft 2-button mouse +//************************************************** + +class hle_msft_mouse_device : public hle_msmouse_device_base +{ +public: + hle_msft_mouse_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock); + +protected: + virtual ioport_constructor device_input_ports() const override; + +private: + virtual void reset_and_identify() override; + virtual void transmit_extensions(uint8_t btn_val, uint8_t btn_sent) override; +}; + + +//************************************************** +// Logitech 3-button mouse +//************************************************** + +class hle_logitech_mouse_device : public hle_msmouse_device_base +{ +public: + hle_logitech_mouse_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock); + +protected: + virtual ioport_constructor device_input_ports() const override; + +private: + virtual void reset_and_identify() override; + virtual void transmit_extensions(uint8_t btn_val, uint8_t btn_sent) override; +}; + + +//************************************************** +// Microsoft wheel mouse +//************************************************** + +class hle_wheel_mouse_device : public hle_msmouse_device_base +{ +public: + hle_wheel_mouse_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock); + +protected: + virtual ioport_constructor device_input_ports() const override; + virtual void device_start() override; + + virtual bool read_inputs() override; + +private: + virtual void reset_and_identify() override; + virtual void transmit_extensions(uint8_t btn_val, uint8_t btn_sent) override; + + required_ioport m_wheel; + int16_t m_wheel_delta; + uint16_t m_wheel_val; +}; + + +//************************************************** +// Mouse Systems mouse base +//************************************************** + +class hle_msystems_device_base : public device_t, public device_rs232_port_interface, public device_serial_interface +{ +public: + DECLARE_INPUT_CHANGED_MEMBER(input_changed); + +protected: + hle_msystems_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, uint32_t clock); + + virtual void device_start() override; + + virtual void tra_callback() override; + virtual void tra_complete() override; + +private: + TIMER_CALLBACK_MEMBER(start_mouse); + + virtual bool read_inputs() = 0; + virtual uint8_t report_buttons() = 0; + virtual uint8_t report_x1_delta() = 0; + virtual uint8_t report_y1_delta() = 0; + virtual uint8_t report_x2_delta() = 0; + virtual uint8_t report_y2_delta() = 0; + + uint8_t m_phase; +}; + + +//************************************************** +// Mouse Systems non-rotatable mouse +//************************************************** + +class hle_msystems_mouse_device : public hle_msystems_device_base +{ +public: + hle_msystems_mouse_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock); + +protected: + virtual ioport_constructor device_input_ports() const override; + virtual void device_start() override; + +private: + virtual bool read_inputs() override; + virtual uint8_t report_buttons() override; + virtual uint8_t report_x1_delta() override; + virtual uint8_t report_y1_delta() override; + virtual uint8_t report_x2_delta() override; + virtual uint8_t report_y2_delta() override; + + required_ioport m_buttons, m_x_axis, m_y_axis; + int16_t m_x_delta, m_y_delta; + uint16_t m_x_val, m_y_val; + uint8_t m_btn_val, m_btn_sent; +}; + + +//************************************************** +// Mouse Systems rotatable mouse +//************************************************** + +class hle_rotatable_mouse_device : public hle_msystems_device_base +{ +public: + hle_rotatable_mouse_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock); + +protected: + virtual ioport_constructor device_input_ports() const override; + virtual void device_start() override; + +private: + virtual bool read_inputs() override; + virtual uint8_t report_buttons() override; + virtual uint8_t report_x1_delta() override; + virtual uint8_t report_y1_delta() override; + virtual uint8_t report_x2_delta() override; + virtual uint8_t report_y2_delta() override; + + required_ioport m_buttons, m_x_axis, m_y_axis, m_rotation; + int16_t m_x_delta[2], m_y_delta[2]; + uint16_t m_x_val, m_y_val, m_rot_val; + uint8_t m_btn_val, m_btn_sent; +}; + +} } // namespace bus::rs232 + + +//************************************************** +// Device type globals +//************************************************** + +DECLARE_DEVICE_TYPE_NS(MSFT_HLE_SERIAL_MOUSE, bus::rs232, hle_msft_mouse_device) +DECLARE_DEVICE_TYPE_NS(LOGITECH_HLE_SERIAL_MOUSE, bus::rs232, hle_logitech_mouse_device) +DECLARE_DEVICE_TYPE_NS(WHEEL_HLE_SERIAL_MOUSE, bus::rs232, hle_wheel_mouse_device) +DECLARE_DEVICE_TYPE_NS(MSYSTEMS_HLE_SERIAL_MOUSE, bus::rs232, hle_msystems_mouse_device) +DECLARE_DEVICE_TYPE_NS(ROTATABLE_HLE_SERIAL_MOUSE, bus::rs232, hle_rotatable_mouse_device) + +#endif // MAME_BUS_RS232_SER_MOUSE_H diff --git a/src/devices/bus/rs232/ser_mouse.cpp b/src/devices/bus/rs232/ser_mouse.cpp deleted file mode 100644 index 2c80fc43ef5..00000000000 --- a/src/devices/bus/rs232/ser_mouse.cpp +++ /dev/null @@ -1,267 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:smf -/*************************************************************************** - - machine/ser_mouse.c - - Code for emulating PC-style serial mouses - -***************************************************************************/ - -#include "emu.h" -#include "ser_mouse.h" - - -serial_mouse_device::serial_mouse_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, type, tag, owner, clock), - device_rs232_port_interface(mconfig, *this), - device_serial_interface(mconfig, *this), - m_dtr(1), - m_rts(1), - m_head(0), - m_tail(0), - m_mb(0), - m_timer(nullptr), - m_enabled(false), - m_x(*this, "ser_mouse_x"), - m_y(*this, "ser_mouse_y"), - m_btn(*this, "ser_mouse_btn") -{ -} - -DEFINE_DEVICE_TYPE(MSFT_SERIAL_MOUSE, microsoft_mouse_device, "microsoft_mouse", "Microsoft Serial Mouse") - -microsoft_mouse_device::microsoft_mouse_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : serial_mouse_device(mconfig, MSFT_SERIAL_MOUSE, tag, owner, clock) -{ -} - -DEFINE_DEVICE_TYPE(MSYSTEM_SERIAL_MOUSE, mouse_systems_mouse_device, "mouse_systems_mouse", "Mouse Systems Serial Mouse") - -mouse_systems_mouse_device::mouse_systems_mouse_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : serial_mouse_device(mconfig, MSYSTEM_SERIAL_MOUSE, tag, owner, clock) -{ -} - -void serial_mouse_device::device_start() -{ - m_timer = timer_alloc(); - m_enabled = false; - set_frame(); - set_tra_rate(1200); - reset_mouse(); - - save_item(NAME(m_dtr)); - save_item(NAME(m_rts)); - save_item(NAME(m_queue)); - save_item(NAME(m_head)); - save_item(NAME(m_tail)); - save_item(NAME(m_mb)); - save_item(NAME(m_enabled)); -} - -void serial_mouse_device::reset_mouse() -{ - m_head = m_tail = 0; - output_rxd(1); - output_dcd(0); - output_dsr(0); - output_ri(0); - output_cts(0); -} - -void serial_mouse_device::tra_complete() -{ - if(m_tail != m_head) - transmit_register_setup(unqueue_data()); -} - -void serial_mouse_device::tra_callback() -{ - output_rxd(transmit_register_get_data_bit()); -} - -/************************************************************************** - * Check for mouse moves and buttons. Build delta x/y packets - **************************************************************************/ -void serial_mouse_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) -{ - if (!id) - { - static int ox = 0, oy = 0; - int nx,ny; - int dx, dy, nb; - int mbc; - - /* Do not get deltas or send packets if queue is not empty (Prevents drifting) */ - if (m_head==m_tail) - { - nx = m_x->read(); - - dx = nx - ox; - if (dx<=-0x800) dx = nx + 0x1000 - ox; /* Prevent jumping */ - if (dx>=0x800) dx = nx - 0x1000 - ox; - ox = nx; - - ny = m_y->read(); - - dy = ny - oy; - if (dy<=-0x800) dy = ny + 0x1000 - oy; - if (dy>=0x800) dy = ny - 0x1000 - oy; - oy = ny; - - nb = m_btn->read(); - mbc = nb^m_mb; - m_mb = nb; - - /* check if there is any delta or mouse buttons changed */ - if ( (dx!=0) || (dy!=0) || (mbc!=0) ) - mouse_trans(dx, dy, nb, mbc); - } - - if(m_tail != m_head && is_transmit_register_empty()) - transmit_register_setup(unqueue_data()); - } -} - -void microsoft_mouse_device::mouse_trans(int dx, int dy, int nb, int mbc) -{ - /* split deltas into packets of -128..+127 max */ - do - { - uint8_t m0, m1, m2; - int ddx = (dx < -128) ? -128 : (dx > 127) ? 127 : dx; - int ddy = (dy < -128) ? -128 : (dy > 127) ? 127 : dy; - m0 = 0x40 | ((nb << 4) & 0x30) | ((ddx >> 6) & 0x03) | ((ddy >> 4) & 0x0c); - m1 = ddx & 0x3f; - m2 = ddy & 0x3f; - - /* KT - changed to use a function */ - queue_data(m0 | 0x40); - queue_data(m1 & 0x03f); - queue_data(m2 & 0x03f); - if ((mbc & 0x04) != 0) /* If button 3 changed send extra byte */ - queue_data( (nb & 0x04) << 3); - - dx -= ddx; - dy -= ddy; - } while( dx || dy ); -} - -/* mouse systems mouse - from "PC Mouse information" by Tomi Engdahl */ - -/* - The data is sent in 5 byte packets in following format: - D7 D6 D5 D4 D3 D2 D1 D0 - - 1. 1 0 0 0 0 LB CB RB - 2. X7 X6 X5 X4 X3 X2 X1 X0 - 3. Y7 Y6 Y5 Y4 Y3 Y4 Y1 Y0 - 4. X7' X6' X5' X4' X3' X2' X1' X0' - 5. Y7' Y6' Y5' Y4' Y3' Y4' Y1' Y0' - - LB is left button state (0=pressed, 1=released) - CB is center button state (0=pressed, 1=released) - RB is right button state (0=pressed, 1=released) - X7-X0 movement in X direction since last packet in signed byte - format (-128..+127), positive direction right - Y7-Y0 movement in Y direction since last packet in signed byte - format (-128..+127), positive direction up - X7'-X0' movement in X direction since sending of X7-X0 packet in signed byte - format (-128..+127), positive direction right - Y7'-Y0' movement in Y direction since sending of Y7-Y0 in signed byte - format (-128..+127), positive direction up - - The last two bytes in the packet (bytes 4 and 5) contains information - about movement data changes which have occurred after data bytes 2 and 3 have been sent. */ - -void mouse_systems_mouse_device::mouse_trans(int dx, int dy, int nb, int mbc) -{ - dy =-dy; - - do - { - int ddx = (dx < -128) ? -128 : (dx > 127) ? 127 : dx; - int ddy = (dy < -128) ? -128 : (dy > 127) ? 127 : dy; - - /* KT - changed to use a function */ - queue_data(0x080 | ((((nb & 0x04) >> 1) + ((nb & 0x02) << 1) + (nb & 0x01)) ^ 0x07)); - queue_data(ddx); - queue_data(ddy); - /* for now... */ - queue_data(0); - queue_data(0); - dx -= ddx; - dy -= ddy; - } while( dx || dy ); -} - -/************************************************************************** - * Check for mouse control line changes and (de-)install timer - **************************************************************************/ - -void serial_mouse_device::set_mouse_enable(bool state) -{ - if(state && !m_enabled) - { - m_timer->adjust(attotime::zero, 0, attotime::from_hz(240)); - } - else if(!state && m_enabled) - { - m_timer->adjust(attotime::never); - m_head = m_tail = 0; - } - m_enabled = state; - -} - - -WRITE_LINE_MEMBER(serial_mouse_device::input_dtr) -{ - m_dtr = state; - check_state(); -} - -WRITE_LINE_MEMBER(serial_mouse_device::input_rts) -{ - m_rts = state; - check_state(); -} - -WRITE_LINE_MEMBER(microsoft_mouse_device::input_rts) -{ - if (!m_dtr && m_rts && !state) - { - reset_mouse(); - /* Identify as Microsoft 3 Button Mouse */ - queue_data('M'); - queue_data('3'); - } - - serial_mouse_device::input_rts(state); -} - - - -/************************************************************************** - * Mouse INPUT_PORT declarations - **************************************************************************/ - -static INPUT_PORTS_START( ser_mouse ) - PORT_START( "ser_mouse_btn" ) - PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Mouse Left Button") PORT_CODE(MOUSECODE_BUTTON1) - PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_NAME("Mouse Middle Button") PORT_CODE(MOUSECODE_BUTTON3) - PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON3) PORT_NAME("Mouse Right Button") PORT_CODE(MOUSECODE_BUTTON2) - - PORT_START( "ser_mouse_x" ) /* Mouse - X AXIS */ - PORT_BIT( 0xfff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_PLAYER(1) - - PORT_START( "ser_mouse_y" ) /* Mouse - Y AXIS */ - PORT_BIT( 0xfff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_PLAYER(1) -INPUT_PORTS_END - -ioport_constructor serial_mouse_device::device_input_ports() const -{ - return INPUT_PORTS_NAME(ser_mouse); -} diff --git a/src/devices/bus/rs232/ser_mouse.h b/src/devices/bus/rs232/ser_mouse.h deleted file mode 100644 index ff4e7a81995..00000000000 --- a/src/devices/bus/rs232/ser_mouse.h +++ /dev/null @@ -1,84 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:smf -/***************************************************************************** - * - * machine/ser_mouse.h - * - ****************************************************************************/ - -#ifndef MAME_BUS_RS232_SER_MOUSE_H -#define MAME_BUS_RS232_SER_MOUSE_H - -#include "rs232.h" -#include "diserial.h" - -class serial_mouse_device : - public device_t, - public device_rs232_port_interface, - public device_serial_interface -{ -public: - virtual ioport_constructor device_input_ports() const override; - -protected: - serial_mouse_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - - virtual void device_start() override; - virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; - - virtual void mouse_trans(int dx, int dy, int nb, int mbc) = 0; - virtual void set_frame() = 0; - void set_mouse_enable(bool state); - void queue_data(uint8_t data) {m_queue[m_head] = data; ++m_head %= 256;} - uint8_t unqueue_data() {uint8_t ret = m_queue[m_tail]; ++m_tail %= 256; return ret;} - virtual void tra_complete() override; - virtual void tra_callback() override; - void reset_mouse(); - - virtual WRITE_LINE_MEMBER(input_dtr) override; - virtual WRITE_LINE_MEMBER(input_rts) override; - - int m_dtr; - int m_rts; - -private: - void check_state() { set_mouse_enable(!m_dtr && !m_rts); } - - uint8_t m_queue[256]; - uint8_t m_head, m_tail, m_mb; - - emu_timer *m_timer; - bool m_enabled; - - required_ioport m_x; - required_ioport m_y; - required_ioport m_btn; -}; - -class microsoft_mouse_device : public serial_mouse_device -{ -public: - microsoft_mouse_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - -protected: - virtual WRITE_LINE_MEMBER(input_rts) override; - - virtual void set_frame() override { set_data_frame(1, 7, PARITY_NONE, STOP_BITS_2); } - virtual void mouse_trans(int dx, int dy, int nb, int mbc) override; -}; - -DECLARE_DEVICE_TYPE(MSFT_SERIAL_MOUSE, microsoft_mouse_device) - -class mouse_systems_mouse_device : public serial_mouse_device -{ -public: - mouse_systems_mouse_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - -protected: - virtual void set_frame() override { set_data_frame(1, 8, PARITY_NONE, STOP_BITS_2); } - virtual void mouse_trans(int dx, int dy, int nb, int mbc) override; -}; - -DECLARE_DEVICE_TYPE(MSYSTEM_SERIAL_MOUSE, mouse_systems_mouse_device) - -#endif // MAME_BUS_RS232_SER_MOUSE_H diff --git a/src/devices/bus/sunmouse/hlemouse.cpp b/src/devices/bus/sunmouse/hlemouse.cpp index 0737f5e4702..9f3422188dc 100644 --- a/src/devices/bus/sunmouse/hlemouse.cpp +++ b/src/devices/bus/sunmouse/hlemouse.cpp @@ -264,11 +264,11 @@ void hle_device_base::check_inputs() // deal with wraparound if (0x0800 <= x_delta) x_delta -= 0x1000; - else if (-0x8000 >= x_delta) + else if (-0x0800 >= x_delta) x_delta += 0x1000; if (0x0800 <= y_delta) y_delta -= 0x1000; - else if (-0x8000 >= y_delta) + else if (-0x0800 >= y_delta) x_delta += 0x1000; // update state diff --git a/src/emu/diserial.h b/src/emu/diserial.h index af55c7d4bc5..e1e2a447dff 100644 --- a/src/emu/diserial.h +++ b/src/emu/diserial.h @@ -188,6 +188,16 @@ class device_buffered_serial_interface : public device_serial_interface protected: using device_serial_interface::device_serial_interface; + void interface_post_start() override + { + device_serial_interface::interface_post_start(); + + device().save_item(NAME(m_fifo)); + device().save_item(NAME(m_head)); + device().save_item(NAME(m_tail)); + device().save_item(NAME(m_empty)); + } + virtual void tra_complete() override { assert(!m_empty || (m_head == m_tail)); @@ -236,20 +246,14 @@ protected: } } - bool fifo_full() const + bool fifo_empty() const { - return !m_empty && (m_head == m_tail); + return m_empty; } -protected: - void interface_post_start() override + bool fifo_full() const { - device_serial_interface::interface_post_start(); - - device().save_item(NAME(m_fifo)); - device().save_item(NAME(m_head)); - device().save_item(NAME(m_tail)); - device().save_item(NAME(m_empty)); + return !m_empty && (m_head == m_tail); } private: diff --git a/src/mame/drivers/ibmpcjr.cpp b/src/mame/drivers/ibmpcjr.cpp index 07774a1eef6..1e6ef97f708 100644 --- a/src/mame/drivers/ibmpcjr.cpp +++ b/src/mame/drivers/ibmpcjr.cpp @@ -20,8 +20,8 @@ #include "bus/generic/slot.h" #include "bus/isa/fdc.h" #include "bus/pc_joy/pc_joy.h" +#include "bus/rs232/hlemouse.h" #include "bus/rs232/rs232.h" -#include "bus/rs232/ser_mouse.h" #include "screen.h" #include "softlist.h" @@ -512,8 +512,11 @@ static void pcjr_floppies(device_slot_interface &device) static void pcjr_com(device_slot_interface &device) { - device.option_add("microsoft_mouse", MSFT_SERIAL_MOUSE); - device.option_add("mousesys_mouse", MSYSTEM_SERIAL_MOUSE); + device.option_add("microsoft_mouse", MSFT_HLE_SERIAL_MOUSE); + device.option_add("logitech_mouse", LOGITECH_HLE_SERIAL_MOUSE); + device.option_add("wheel_mouse", WHEEL_HLE_SERIAL_MOUSE); + device.option_add("msystems_mouse", MSYSTEMS_HLE_SERIAL_MOUSE); + device.option_add("rotatable_mouse", ROTATABLE_HLE_SERIAL_MOUSE); } static const gfx_layout pc_8_charlayout = diff --git a/src/mame/drivers/pcat_dyn.cpp b/src/mame/drivers/pcat_dyn.cpp index 6aa0d303c17..72ff59519f0 100644 --- a/src/mame/drivers/pcat_dyn.cpp +++ b/src/mame/drivers/pcat_dyn.cpp @@ -33,8 +33,8 @@ If the output isn't satisfactory, it prints "I/O BOARD FAILURE". #include "bus/isa/isa.h" #include "bus/isa/sblaster.h" #include "bus/isa/trident.h" +#include "bus/rs232/hlemouse.h" #include "bus/rs232/rs232.h" -#include "bus/rs232/ser_mouse.h" #include "screen.h" @@ -145,7 +145,7 @@ INPUT_PORTS_END static void pcat_dyn_com(device_slot_interface &device) { - device.option_add("msmouse", MSYSTEM_SERIAL_MOUSE); + device.option_add("msmouse", MSYSTEMS_HLE_SERIAL_MOUSE); } static void pcat_dyn_isa8_cards(device_slot_interface &device) diff --git a/src/mame/drivers/pcipc.cpp b/src/mame/drivers/pcipc.cpp index 8068ba762df..08669a9b8dd 100644 --- a/src/mame/drivers/pcipc.cpp +++ b/src/mame/drivers/pcipc.cpp @@ -26,10 +26,11 @@ #include "machine/i82371sb.h" #include "video/mga2064w.h" #include "bus/isa/isa_cards.h" +#include "bus/rs232/hlemouse.h" +#include "bus/rs232/null_modem.h" #include "bus/rs232/rs232.h" -#include "bus/rs232/ser_mouse.h" +#include "bus/rs232/sun_kbd.h" #include "bus/rs232/terminal.h" -#include "bus/rs232/null_modem.h" #include "machine/fdc37c93x.h" class pcipc_state : public driver_device @@ -481,10 +482,14 @@ static void isa_internal_devices(device_slot_interface &device) static void isa_com(device_slot_interface &device) { - device.option_add("microsoft_mouse", MSFT_SERIAL_MOUSE); - device.option_add("msystems_mouse", MSYSTEM_SERIAL_MOUSE); + device.option_add("microsoft_mouse", MSFT_HLE_SERIAL_MOUSE); + device.option_add("logitech_mouse", LOGITECH_HLE_SERIAL_MOUSE); + device.option_add("wheel_mouse", WHEEL_HLE_SERIAL_MOUSE); + device.option_add("msystems_mouse", MSYSTEMS_HLE_SERIAL_MOUSE); + device.option_add("rotatable_mouse", ROTATABLE_HLE_SERIAL_MOUSE); device.option_add("terminal", SERIAL_TERMINAL); device.option_add("null_modem", NULL_MODEM); + device.option_add("sun_kbd", SUN_KBD_ADAPTOR); } void pcipc_state::superio_config(device_t *device) @@ -539,7 +544,7 @@ MACHINE_CONFIG_START(pcipc_state::pcipc) MCFG_DEVICE_ADD("isa3", ISA16_SLOT, 0, "pci:07.0:isabus", pc_isa16_cards, nullptr, false) MCFG_DEVICE_ADD("isa4", ISA16_SLOT, 0, "pci:07.0:isabus", pc_isa16_cards, nullptr, false) MCFG_DEVICE_ADD("isa5", ISA16_SLOT, 0, "pci:07.0:isabus", pc_isa16_cards, nullptr, false) - MCFG_DEVICE_ADD("serport0", RS232_PORT, isa_com, "microsoft_mouse") + MCFG_DEVICE_ADD("serport0", RS232_PORT, isa_com, "logitech_mouse") MCFG_RS232_RXD_HANDLER(WRITELINE("board4:fdc37c93x", fdc37c93x_device, rxd1_w)) MCFG_RS232_DCD_HANDLER(WRITELINE("board4:fdc37c93x", fdc37c93x_device, ndcd1_w)) MCFG_RS232_DSR_HANDLER(WRITELINE("board4:fdc37c93x", fdc37c93x_device, ndsr1_w)) diff --git a/src/mame/drivers/pcw16.cpp b/src/mame/drivers/pcw16.cpp index 822c9dfb5e6..9c6e8b6accf 100644 --- a/src/mame/drivers/pcw16.cpp +++ b/src/mame/drivers/pcw16.cpp @@ -91,8 +91,8 @@ TODO: #include "emu.h" #include "includes/pcw16.h" +#include "bus/rs232/hlemouse.h" #include "bus/rs232/rs232.h" -#include "bus/rs232/ser_mouse.h" #include "screen.h" #include "softlist.h" #include "speaker.h" @@ -1007,7 +1007,7 @@ INPUT_PORTS_END static void pcw16_com(device_slot_interface &device) { - device.option_add("msystems_mouse", MSYSTEM_SERIAL_MOUSE); + device.option_add("msystems_mouse", MSYSTEMS_HLE_SERIAL_MOUSE); } MACHINE_CONFIG_START(pcw16_state::pcw16) diff --git a/src/mame/drivers/rainbow.cpp b/src/mame/drivers/rainbow.cpp index df625970c02..37bcfef0172 100644 --- a/src/mame/drivers/rainbow.cpp +++ b/src/mame/drivers/rainbow.cpp @@ -356,8 +356,8 @@ W17 pulls J1 serial port pin 1 to GND when set (chassis to logical GND). #include "bus/rs232/rs232.h" #include "imagedev/bitbngr.h" #include "machine/com8116.h" +#include "bus/rs232/hlemouse.h" #include "bus/rs232/terminal.h" -#include "bus/rs232/ser_mouse.h" #include "machine/i8251.h" #include "machine/dec_lk201.h" @@ -3326,9 +3326,10 @@ MACHINE_CONFIG_START(rainbow_state::rainbow) MCFG_RS232_DCD_HANDLER(WRITELINE(m_mpsc, upd7201_new_device, ctsb_w)) // actually DTR MCFG_DEVICE_MODIFY("comm") - MCFG_SLOT_OPTION_ADD("microsoft_mouse", MSFT_SERIAL_MOUSE) - MCFG_SLOT_OPTION_ADD("mouse_systems_mouse", MSYSTEM_SERIAL_MOUSE) - MCFG_SLOT_DEFAULT_OPTION("microsoft_mouse") + MCFG_SLOT_OPTION_ADD("microsoft_mouse", MSFT_HLE_SERIAL_MOUSE) + MCFG_SLOT_OPTION_ADD("logitech_mouse", LOGITECH_HLE_SERIAL_MOUSE) + MCFG_SLOT_OPTION_ADD("msystems_mouse", MSYSTEMS_HLE_SERIAL_MOUSE) + MCFG_SLOT_DEFAULT_OPTION("logitech_mouse") MCFG_DEVICE_MODIFY("printer") MCFG_SLOT_DEFAULT_OPTION("printer") -- cgit v1.2.3 From 895ffe0763a713fe644c53afe573e9839ee822a1 Mon Sep 17 00:00:00 2001 From: Patrick Mackinlay Date: Thu, 20 Sep 2018 18:08:59 +0700 Subject: jazz: new skeleton driver (nw) A skeleton for the Microsoft Jazz architecture, which was implemented in the MIPS Magnum 4000, Olivetti M700-10 and was the base/origin of several other MIPS ARC systems. * added skeleton Inmos G300/G332/G364 device * added skeleton NatSemi DP83932C SONIC device * added skeleton MCT-ADR device --- scripts/src/machine.lua | 12 +++ scripts/src/video.lua | 12 +++ scripts/target/mame/mess.lua | 11 ++ src/devices/machine/dp83932c.cpp | 140 ++++++++++++++++++++++++++ src/devices/machine/dp83932c.h | 59 +++++++++++ src/devices/video/ims_cvc.cpp | 139 +++++++++++++++++++++++++ src/devices/video/ims_cvc.h | 142 ++++++++++++++++++++++++++ src/mame/drivers/jazz.cpp | 206 ++++++++++++++++++++++++++++++++++++++ src/mame/includes/jazz.h | 97 ++++++++++++++++++ src/mame/machine/jazz_mct_adr.cpp | 51 ++++++++++ src/mame/machine/jazz_mct_adr.h | 25 +++++ src/mame/mame.lst | 4 + 12 files changed, 898 insertions(+) create mode 100644 src/devices/machine/dp83932c.cpp create mode 100644 src/devices/machine/dp83932c.h create mode 100644 src/devices/video/ims_cvc.cpp create mode 100644 src/devices/video/ims_cvc.h create mode 100644 src/mame/drivers/jazz.cpp create mode 100644 src/mame/includes/jazz.h create mode 100644 src/mame/machine/jazz_mct_adr.cpp create mode 100644 src/mame/machine/jazz_mct_adr.h (limited to 'scripts/src') diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua index 7c1cc8e66ca..cd141b26cb3 100644 --- a/scripts/src/machine.lua +++ b/scripts/src/machine.lua @@ -3178,6 +3178,18 @@ if (MACHINES["DP8390"]~=null) then } end +--------------------------------------------------- +-- +--@src/devices/machine/dp83932c.h,MACHINES["DP83932C"] = true +--------------------------------------------------- + +if (MACHINES["DP83932C"]~=null) then + files { + MAME_DIR .. "src/devices/machine/dp83932c.cpp", + MAME_DIR .. "src/devices/machine/dp83932c.h", + } +end + --------------------------------------------------- -- --@src/devices/machine/pc_lpt.h,MACHINES["PC_LPT"] = true diff --git a/scripts/src/video.lua b/scripts/src/video.lua index c014a026fad..a5b47457dd3 100644 --- a/scripts/src/video.lua +++ b/scripts/src/video.lua @@ -495,6 +495,18 @@ if (VIDEOS["I8275"]~=null) then } end +-------------------------------------------------- +-- +--@src/devices/video/ims_cvc.h,VIDEOS["IMS_CVC"] = true +-------------------------------------------------- + +if (VIDEOS["IMS_CVC"]~=null) then + files { + MAME_DIR .. "src/devices/video/ims_cvc.cpp", + MAME_DIR .. "src/devices/video/ims_cvc.h", + } +end + -------------------------------------------------- -- --@src/devices/video/m50458.h,VIDEOS["M50458"] = true diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index b8a01662661..3ad7dd9413a 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -324,6 +324,7 @@ VIDEOS["HUC6272"] = true VIDEOS["I8244"] = true VIDEOS["I82730"] = true VIDEOS["I8275"] = true +VIDEOS["IMS_CVC"] = true --VIDEOS["M50458"] = true --VIDEOS["MB90082"] = true --VIDEOS["MB_VCU"] = true @@ -420,6 +421,7 @@ MACHINES["CS4031"] = true MACHINES["CS8221"] = true MACHINES["CXD1095"] = true MACHINES["DP8390"] = true +MACHINES["DP83932C"] = true --MACHINES["DS1204"] = true MACHINES["DS1302"] = true MACHINES["DS1315"] = true @@ -1064,6 +1066,7 @@ function linkProjects_mame_mess(_target, _subtarget) "interton", "intv", "isc", + "jazz", "kaypro", "koei", "kontron", @@ -2340,6 +2343,14 @@ files { MAME_DIR .. "src/mame/drivers/compucolor.cpp", } +createMESSProjects(_target, _subtarget, "jazz") +files { + MAME_DIR .. "src/mame/drivers/jazz.cpp", + MAME_DIR .. "src/mame/includes/jazz.h", + MAME_DIR .. "src/mame/machine/jazz_mct_adr.cpp", + MAME_DIR .. "src/mame/machine/jazz_mct_adr.h", +} + createMESSProjects(_target, _subtarget, "kaypro") files { MAME_DIR .. "src/mame/drivers/kaypro.cpp", diff --git a/src/devices/machine/dp83932c.cpp b/src/devices/machine/dp83932c.cpp new file mode 100644 index 00000000000..c8c7fcfcd9e --- /dev/null +++ b/src/devices/machine/dp83932c.cpp @@ -0,0 +1,140 @@ +// license:BSD-3-Clause +// copyright-holders:Patrick Mackinlay + +/* + * An implementation of the National Semiconductor DP83932C SONIC™ (Systems- + * Oriented Network Interface Controller) device. + * + * References: + * + * http://bitsavers.org/components/national/_dataBooks/1995_National_Ethernet_Databook.pdf + * + * TODO + * - everything (skeleton only) + */ + +#include "emu.h" +#include "dp83932c.h" +#include "hashing.h" + +#define VERBOSE 0 +#include "logmacro.h" + +DEFINE_DEVICE_TYPE(DP83932C_BE, dp83932c_be_device, "dp83932c_be", "National Semiconductor DP83932C SONIC (big)") +DEFINE_DEVICE_TYPE(DP83932C_LE, dp83932c_le_device, "dp83932c_le", "National Semiconductor DP83932C SONIC (little)") + +dp83932c_device::dp83932c_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, endianness_t endian) + : device_t(mconfig, type, tag, owner, clock) + , device_memory_interface(mconfig, *this) + , device_network_interface(mconfig, *this, 10.0f) + , m_space_config("shared", endian, 32, 32) + , m_out_int(*this) +{ +} + +dp83932c_be_device::dp83932c_be_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : dp83932c_device(mconfig, DP83932C_BE, tag, owner, clock, ENDIANNESS_BIG) +{ +} + +dp83932c_le_device::dp83932c_le_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : dp83932c_device(mconfig, DP83932C_LE, tag, owner, clock, ENDIANNESS_LITTLE) +{ +} + +void dp83932c_device::map(address_map &map) +{ +/* + // command and status registers + map(0x00, 0x03).rw(FUNC(dp83932c_device::cr_r), FUNC(dp83932c_device::cr_w)); + map(0x04, 0x07).rw(FUNC(dp83932c_device::dcr_r), FUNC(dp83932c_device::dcr_w)); + map(0x08, 0x0b).rw(FUNC(dp83932c_device::rcr_r), FUNC(dp83932c_device::rcr_w)); + map(0x0c, 0x0f).rw(FUNC(dp83932c_device::tcr_r), FUNC(dp83932c_device::tcr_w)); + map(0x10, 0x13).rw(FUNC(dp83932c_device::imr_r), FUNC(dp83932c_device::imr_w)); + map(0x14, 0x17).rw(FUNC(dp83932c_device::isr_r), FUNC(dp83932c_device::isr_w)); + + // transmit registers + map(0x18, 0x1b).rw(FUNC(dp83932c_device::utda_r), FUNC(dp83932c_device::utda_w)); + map(0x1c, 0x1f).rw(FUNC(dp83932c_device::ctda_r), FUNC(dp83932c_device::ctda_w)); + + // tps + // tfc + // tsa0 + // tsa1 + // tfs + + // receive registers + map(0x34, 0x37).rw(FUNC(dp83932c_device::urda_r), FUNC(dp83932c_device::urda_w)); + map(0x38, 0x3b).rw(FUNC(dp83932c_device::crda_r), FUNC(dp83932c_device::crda_w)); + + // crba0 + // crba1 + // rbwc0 + // rbwc1 + // eobc + // urra + // rsa + // rea + // rrp + // rwp + // trba0 + // trba1 + // tbwc0 + // tbwc1 + // addr0 + // addr1 + // llfa + // ttda + // cep + // cap2 + // cap1 + // cap0 + // ce + // cdp + // cdc + // sr + // wt0 + // wt1 + // rsc + // crct + // faet + // mpt + // mdt + + // 30-3e internal use registers +*/ +} + +void dp83932c_device::device_start() +{ + m_space = &space(0); + m_out_int.resolve(); +} + +void dp83932c_device::device_reset() +{ +} + +void dp83932c_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ +} + +device_memory_interface::space_config_vector dp83932c_device::memory_space_config() const +{ + return space_config_vector { + std::make_pair(0, &m_space_config) + }; +} + +void dp83932c_device::send_complete_cb(int result) +{ +} + +int dp83932c_device::recv_start_cb(u8 *buf, int length) +{ + return 0; +} + +void dp83932c_device::recv_complete_cb(int result) +{ +} diff --git a/src/devices/machine/dp83932c.h b/src/devices/machine/dp83932c.h new file mode 100644 index 00000000000..27f5ae60d85 --- /dev/null +++ b/src/devices/machine/dp83932c.h @@ -0,0 +1,59 @@ +// license:BSD-3-Clause +// copyright-holders:Patrick Mackinlay + +#ifndef MAME_MACHINE_DP83932C_H +#define MAME_MACHINE_DP83932C_H + +#pragma once + +class dp83932c_device : + public device_t, + public device_memory_interface, + public device_network_interface +{ +public: + // callback configuration + auto out_int_cb() { return m_out_int.bind(); } + + void map(address_map &map); + +protected: + dp83932c_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, endianness_t endian); + + // device_t overrides + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; + + // device_memory_interface overrides + virtual space_config_vector memory_space_config() const override; + + // device_network_interface overrides + virtual void send_complete_cb(int result) override; + virtual int recv_start_cb(u8 *buf, int length) override; + virtual void recv_complete_cb(int result) override; + +private: + // device_memory_interface members + const address_space_config m_space_config; + address_space *m_space; + + devcb_write_line m_out_int; +}; + +class dp83932c_be_device : public dp83932c_device +{ +public: + dp83932c_be_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); +}; + +class dp83932c_le_device : public dp83932c_device +{ +public: + dp83932c_le_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); +}; + +DECLARE_DEVICE_TYPE(DP83932C_BE, dp83932c_be_device) +DECLARE_DEVICE_TYPE(DP83932C_LE, dp83932c_le_device) + +#endif // MAME_MACHINE_DP83932C_H diff --git a/src/devices/video/ims_cvc.cpp b/src/devices/video/ims_cvc.cpp new file mode 100644 index 00000000000..ca6efc1b7d1 --- /dev/null +++ b/src/devices/video/ims_cvc.cpp @@ -0,0 +1,139 @@ +// license:BSD-3-Clause +// copyright-holders:Patrick Mackinlay + +/* + * An implementation of the INMOS G300, G332 and G364 CVC (Colour Video + * Controller) devices. + * + * References: + * + * http://bitsavers.org/components/inmos/graphics/72-TRN-204-01_Graphics_Databook_Second_Edition_1990.pdf + * + * TODO + * - everything (skeleton only) + */ + +#include "emu.h" +#include "ims_cvc.h" + +#include "screen.h" + +#define VERBOSE 0 +#include "logmacro.h" + +DEFINE_DEVICE_TYPE(G300, g300_device, "g300", "INMOS G300 Colour Video Controller") +DEFINE_DEVICE_TYPE(G332, g332_device, "g332", "INMOS G332 Colour Video Controller") +DEFINE_DEVICE_TYPE(G364, g364_device, "g364", "INMOS G364 Colour Video Controller") + +ims_cvc_device::ims_cvc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, type, tag, owner, clock) + , device_memory_interface(mconfig, *this) + , device_palette_interface(mconfig, *this) + , m_space_config("shared", ENDIANNESS_LITTLE, 32, 24) +{ +} + +g300_device::g300_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : ims_cvc_device(mconfig, G300, tag, owner, clock) +{ +} + +g332_device::g332_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : ims_cvc_device(mconfig, type, tag, owner, clock) +{ +} + +g332_device::g332_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : ims_cvc_device(mconfig, G332, tag, owner, clock) +{ +} + +g364_device::g364_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : g332_device(mconfig, G364, tag, owner, clock) +{ +} + +device_memory_interface::space_config_vector ims_cvc_device::memory_space_config() const +{ + return space_config_vector{ + std::make_pair(0, &m_space_config) + }; +} + +void g300_device::map(address_map &map) +{ + // datasheet gives unshifted addresses + const int shift = 2; + + // colour palette + map(0x000 << shift, (0x0ff << shift) | 0x3).rw(FUNC(g300_device::colour_palette_r), FUNC(g300_device::colour_palette_w)); + + // data path registers + map(0x121, (0x121 << shift) | 0x3).rw(FUNC(g300_device::halfsync_r), FUNC(g300_device::halfsync_w)); + map(0x122, (0x122 << shift) | 0x3).rw(FUNC(g300_device::backporch_r), FUNC(g300_device::backporch_w)); + map(0x123, (0x123 << shift) | 0x3).rw(FUNC(g300_device::display_r), FUNC(g300_device::display_w)); + map(0x124, (0x124 << shift) | 0x3).rw(FUNC(g300_device::shortdisplay_r), FUNC(g300_device::shortdisplay_w)); + map(0x125, (0x125 << shift) | 0x3).rw(FUNC(g300_device::broadpulse_r), FUNC(g300_device::broadpulse_w)); + map(0x126, (0x126 << shift) | 0x3).rw(FUNC(g300_device::vsync_r), FUNC(g300_device::vsync_w)); + map(0x127, (0x127 << shift) | 0x3).rw(FUNC(g300_device::vblank_r), FUNC(g300_device::vblank_w)); + map(0x128, (0x128 << shift) | 0x3).rw(FUNC(g300_device::vdisplay_r), FUNC(g300_device::vdisplay_w)); + map(0x129, (0x129 << shift) | 0x3).rw(FUNC(g300_device::linetime_r), FUNC(g300_device::linetime_w)); + map(0x12a, (0x12a << shift) | 0x3).rw(FUNC(g300_device::tos_r), FUNC(g300_device::tos_w)); + map(0x12b, (0x12b << shift) | 0x3).rw(FUNC(g300_device::meminit_r), FUNC(g300_device::meminit_w)); + map(0x12c, (0x12c << shift) | 0x3).rw(FUNC(g300_device::transferdelay_r), FUNC(g300_device::transferdelay_w)); + + map(0x140 << shift, (0x140 << shift) | 0x3).rw(FUNC(g300_device::mask_r), FUNC(g300_device::mask_w)); + map(0x160 << shift, (0x160 << shift) | 0x3).rw(FUNC(g300_device::control_r), FUNC(g300_device::control_w)); + map(0x180 << shift, (0x180 << shift) | 0x3).rw(FUNC(g300_device::tos_r), FUNC(g300_device::tos_w)); + map(0x1a0 << shift, (0x1a0 << shift) | 0x3).w(FUNC(g300_device::boot_w)); +} + +void g332_device::map(address_map &map) +{ + // datasheet gives unshifted addresses + const int shift = 2; // TODO: 64 bit mode + + map(0x000 << shift, (0x000 << shift) | 0x3).w(FUNC(g332_device::boot_w)); + + // data path registers + map(0x021, (0x021 << shift) | 0x3).rw(FUNC(g332_device::halfsync_r), FUNC(g332_device::halfsync_w)); + map(0x022, (0x022 << shift) | 0x3).rw(FUNC(g332_device::backporch_r), FUNC(g332_device::backporch_w)); + map(0x023, (0x023 << shift) | 0x3).rw(FUNC(g332_device::display_r), FUNC(g332_device::display_w)); + map(0x024, (0x024 << shift) | 0x3).rw(FUNC(g332_device::shortdisplay_r), FUNC(g332_device::shortdisplay_w)); + map(0x025, (0x025 << shift) | 0x3).rw(FUNC(g332_device::broadpulse_r), FUNC(g332_device::broadpulse_w)); + map(0x026, (0x026 << shift) | 0x3).rw(FUNC(g332_device::vsync_r), FUNC(g332_device::vsync_w)); + map(0x027, (0x027 << shift) | 0x3).rw(FUNC(g332_device::vpreequalise_r), FUNC(g332_device::vpreequalise_w)); + map(0x028, (0x028 << shift) | 0x3).rw(FUNC(g332_device::vpostequalise_r), FUNC(g332_device::vpostequalise_w)); + map(0x029, (0x029 << shift) | 0x3).rw(FUNC(g332_device::vblank_r), FUNC(g332_device::vblank_w)); + map(0x02a, (0x02a << shift) | 0x3).rw(FUNC(g332_device::vdisplay_r), FUNC(g332_device::vdisplay_w)); + map(0x02b, (0x02b << shift) | 0x3).rw(FUNC(g332_device::linetime_r), FUNC(g332_device::linetime_w)); + map(0x02c, (0x02c << shift) | 0x3).rw(FUNC(g332_device::linestart_r), FUNC(g332_device::linestart_w)); + map(0x02d, (0x02d << shift) | 0x3).rw(FUNC(g332_device::meminit_r), FUNC(g332_device::meminit_w)); + map(0x02e, (0x02e << shift) | 0x3).rw(FUNC(g332_device::transferdelay_r), FUNC(g332_device::transferdelay_w)); + + map(0x040 << shift, (0x040 << shift) | 0x3).rw(FUNC(g332_device::mask_r), FUNC(g332_device::mask_w)); + map(0x060 << shift, (0x060 << shift) | 0x3).rw(FUNC(g332_device::control_a_r), FUNC(g332_device::control_a_w)); + map(0x070 << shift, (0x070 << shift) | 0x3).rw(FUNC(g332_device::control_b_r), FUNC(g332_device::control_b_w)); + map(0x080 << shift, (0x080 << shift) | 0x3).rw(FUNC(g332_device::tos_r), FUNC(g332_device::tos_w)); + + // cursor palette (0a1-0a3) + // checksum registers (0c0-0c2) + + // colour palette + map(0x100 << shift, (0x1ff << shift) | 0x3).rw(FUNC(g332_device::colour_palette_r), FUNC(g332_device::colour_palette_w)); + + // cursor store (200-3ff) + // cursor position (0c7) +} + +void ims_cvc_device::device_start() +{ +} + +void ims_cvc_device::device_reset() +{ +} + +void ims_cvc_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ +} diff --git a/src/devices/video/ims_cvc.h b/src/devices/video/ims_cvc.h new file mode 100644 index 00000000000..25c0163642d --- /dev/null +++ b/src/devices/video/ims_cvc.h @@ -0,0 +1,142 @@ +// license:BSD-3-Clause +// copyright-holders:Patrick Mackinlay +#ifndef MAME_VIDEO_IMS_CVC_H +#define MAME_VIDEO_IMS_CVC_H + +#pragma once + +class ims_cvc_device : + public device_t, + public device_memory_interface, + public device_palette_interface +{ +public: + virtual void map(address_map &map) = 0; + + void screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); + +protected: + ims_cvc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + // device_t overrides + virtual void device_start() override; + virtual void device_reset() override; + + // device_memory_interface overrides + virtual space_config_vector memory_space_config() const override; + + // device_palette_interface overrides + virtual u32 palette_entries() const override { return 256; } // FIXME + + u32 colour_palette_r(const offs_t offset) { return 0; } + void colour_palette_w(const offs_t offset, const u32 data) {} + u32 halfsync_r() { return m_halfsync; } + void halfsync_w(const u32 data) { m_halfsync = data; } + u32 backporch_r() { return m_backporch; } + void backporch_w(const u32 data) { m_backporch = data; } + u32 display_r() { return m_display; } + void display_w(const u32 data) { m_display = data; } + u32 shortdisplay_r() { return m_shortdisplay; } + void shortdisplay_w(const u32 data) { m_shortdisplay = data; } + u32 broadpulse_r() { return m_broadpulse; } + void broadpulse_w(const u32 data) { m_broadpulse = data; } + u32 vsync_r() { return m_vsync; } + void vsync_w(const u32 data) { m_vsync = data; } + u32 vblank_r() { return m_vblank; } + void vblank_w(const u32 data) { m_vblank = data; } + u32 vdisplay_r() { return m_vdisplay; } + void vdisplay_w(const u32 data) { m_vdisplay = data; } + u32 linetime_r() { return m_linetime; } + void linetime_w(const u32 data) { m_linetime = data; } + //u32 tos_r() { return m_tos; } + //void tos_w(const u32 data) { m_tos = data; } + u32 meminit_r() { return m_meminit; } + void meminit_w(const u32 data) { m_meminit = data; } + u32 transferdelay_r() { return m_transferdelay; } + void transferdelay_w(const u32 data) { m_transferdelay = data; } + + u32 mask_r() { return m_mask; } + void mask_w(const u32 data) { m_mask = data; } + u32 tos_r() { return m_tos; } + void tos_w(const u32 data) { m_tos = data; } + + void boot_w(const u32 data) { m_boot = data; } + +private: + // device_memory_interface members + const address_space_config m_space_config; + address_space *m_space; + + // device state + u32 m_halfsync; + u32 m_backporch; + u32 m_display; + u32 m_shortdisplay; + u32 m_broadpulse; + u32 m_vsync; + u32 m_vblank; + u32 m_vdisplay; + u32 m_linetime; + u32 m_meminit; + u32 m_transferdelay; + + u32 m_mask; + u32 m_tos; + u32 m_boot; +}; + +class g300_device : public ims_cvc_device +{ +public: + g300_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + virtual void map(address_map &map) override; + +protected: + u32 control_r() { return m_control; } + void control_w(const u32 data) { m_control = data; } + +private: + u32 m_control; +}; + +class g332_device : public ims_cvc_device +{ +public: + g332_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + virtual void map(address_map &map) override; + +protected: + g332_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + u32 vpreequalise_r() { return m_vpreequalise; } + void vpreequalise_w(const u32 data) { m_vpreequalise = data; } + u32 vpostequalise_r() { return m_vpostequalise; } + void vpostequalise_w(const u32 data) { m_vpostequalise = data; } + u32 linestart_r() { return m_linestart; } + void linestart_w(const u32 data) { m_linestart = data; } + u32 control_a_r() { return m_control_a; } + void control_a_w(const u32 data) { m_control_a = data; } + u32 control_b_r() { return m_control_b; } + void control_b_w(const u32 data) { m_control_b = data; } + +private: + u32 m_vpreequalise; + u32 m_vpostequalise; + u32 m_linestart; + u32 m_control_a; + u32 m_control_b; +}; + +class g364_device : public g332_device +{ +public: + g364_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); +}; + +DECLARE_DEVICE_TYPE(G300, g300_device) +DECLARE_DEVICE_TYPE(G332, g332_device) +DECLARE_DEVICE_TYPE(G364, g364_device) + +#endif // MAME_VIDEO_IMS_CVC_H diff --git a/src/mame/drivers/jazz.cpp b/src/mame/drivers/jazz.cpp new file mode 100644 index 00000000000..14b9d0876dc --- /dev/null +++ b/src/mame/drivers/jazz.cpp @@ -0,0 +1,206 @@ +// license:BSD-3-Clause +// copyright-holders:Patrick Mackinlay + +/* + * An emulation of systems based on the Jazz computer architecture, originally + * developed by Microsoft. Specific systems which implemented this architecture + * include the MIPS Magnum/Millenium 4000 and Olivetti M700-10. + * + * References: + * + * https://www.linux-mips.org/wiki/Jazz + * http://gunkies.org/wiki/MIPS_Magnum + * http://www.sensi.org/~alec/mips/mips-history.html + * + * TODO + * - everything (skeleton only) + * + * Unconfirmed parts lists from ARCSystem reference design (which appears to + * be very similar or identical to the Jazz system) taken from: + * https://www.linux-mips.org/archives/riscy/1993-12/msg00013.html + * + * Ref Part Function + * + * System board: + * + * Dallas DS1287 RTC and NVRAM + * Dallas DS1225Y 8k non-volatile SRAM + * WD16C552 Dual serial and parallel port controller + * Intel N82077A Floppy drive controller + * National DP83932BFV Ethernet controller + * Intel 82358 EISA Bus Controller + * Intel 82357 EISA Integrated System Peripheral (ISP) + * Intel 82352 x 2 EISA Bus Buffer (EBB) + * Emulex FAS216 SCSI controller + * 27C01 128k EPROM + * 28F020 256k flash memory + * NEC μPD31432 ARC address path ASIC + * NEC μPD31431 x 2 ARC data path ASIC + * NEC μPD30400 R4000PC/50 CPU + * + * Audio board: + * + * Crystal CS4215 Audio codec + * Altera FPGA x 4 Audio DMA + * + * Video board: + * + * 27C010 128k EPROM + * IMS G364-11S Video controller + * NEC μPD42274V-80 x 16 256kx4 VRAM (2MiB) + */ + +#include "emu.h" + +#include "includes/jazz.h" + +#include "debugger.h" + +#define VERBOSE 0 +#include "logmacro.h" + +void jazz_state::machine_start() +{ +} + +void jazz_state::machine_reset() +{ +} + +void jazz_state::init_common() +{ + // map the configured ram + m_maincpu->space(AS_PROGRAM).install_ram(0, m_ram->mask(), m_ram->pointer()); +} + +void jazz_state::jazz_common_map(address_map &map) +{ + map(0x1fc00000, 0x1fc3ffff).r(m_flash, FUNC(amd_28f020_device::read)); + + // FIXME: lots of guesswork and assumptions here for now + map(0x80000000, 0x80000fff).m(m_mct_adr, FUNC(jazz_mct_adr_device::map)); + map(0x80001000, 0x80001fff).m(m_network, FUNC(dp83932c_device::map)); + //map(0x80002000, 0x80002fff).m(m_scsi, FUNC(ncr5390_device::map)).umask32(0x000000ff); + map(0x80003000, 0x80003fff).m(m_fdc, FUNC(n82077aa_device::map)); + //map(0x80004000, 0x80004fff).rw(m_rtc, FUNC(mc146818_device::read), FUNC(mc146818_device::write)); + //map(0x80005000, 0x80005fff).m() // keyboard/mouse + //map(0x80006000, 0x80006fff).m() // serial1 + //map(0x80007000, 0x80007fff).m() // serial2 + //map(0x80008000, 0x80008fff).m() // parallel + map(0x80009000, 0x80009fff).ram().share("nvram"); // unprotected? + map(0x8000a000, 0x8000afff).ram().share("nvram"); // protected? + map(0x8000b000, 0x8000bfff).ram().share("nvram"); // read-only? also sonic IO access? + //map(0x8000c000, 0x8000cfff) // sound + map(0x8000d000, 0x8000dfff).noprw(); // dummy dma device? + + map(0x8000f000, 0x8000f001).rw(FUNC(jazz_state::led_r), FUNC(jazz_state::led_w)); + + //map(0x800e0000, 0x800e0000).rw(FUNC(jazz_state::dram_config_r), FUNC(jazz_state::dram_config_w)); + + map(0xe0800000, 0xe0bfffff).ram().share("vram"); // framebuffer? + + map(0xfff00000, 0xfff3ffff).r(m_flash, FUNC(amd_28f020_device::read)); // mirror? +} + +static void jazz_scsi_devices(device_slot_interface &device) +{ + device.option_add("harddisk", NSCSI_HARDDISK); + device.option_add("cdrom", NSCSI_CDROM); +} + +void jazz_state::jazz(machine_config &config) +{ + m_maincpu->set_addrmap(AS_PROGRAM, &jazz_state::jazz_common_map); + + RAM(config, m_ram, 0); + m_ram->set_default_size("8M"); + m_ram->set_extra_options("16M,32M,64M,128M,256M"); + m_ram->set_default_value(0); + + // FIXME: may require big and little endian variants + JAZZ_MCT_ADR(config, m_mct_adr, 0); + + // scsi bus and devices + NSCSI_BUS(config, m_scsibus, 0); + + nscsi_connector &harddisk(NSCSI_CONNECTOR(config, "scsi:0", 0)); + jazz_scsi_devices(harddisk); + harddisk.set_default_option("harddisk"); + + nscsi_connector &cdrom(NSCSI_CONNECTOR(config, "scsi:6", 0)); + jazz_scsi_devices(cdrom); + cdrom.set_default_option("cdrom"); + + jazz_scsi_devices(NSCSI_CONNECTOR(config, "scsi:1", 0)); + jazz_scsi_devices(NSCSI_CONNECTOR(config, "scsi:2", 0)); + jazz_scsi_devices(NSCSI_CONNECTOR(config, "scsi:3", 0)); + jazz_scsi_devices(NSCSI_CONNECTOR(config, "scsi:4", 0)); + jazz_scsi_devices(NSCSI_CONNECTOR(config, "scsi:5", 0)); + + // scsi host adapter + nscsi_connector &adapter(NSCSI_CONNECTOR(config, "scsi:7", 0)); + adapter.option_add_internal("host", NCR53C90A); + adapter.set_default_option("host"); + adapter.set_fixed(true); + + N82077AA(config, m_fdc, 24_MHz_XTAL); + + MC146818(config, m_rtc, 32.768_kHz_XTAL); + + NVRAM(config, m_nvram, nvram_device::DEFAULT_ALL_0); + + AMD_28F020(config, m_flash); + + // pc keyboard controller? + pc_kbdc_device &kbdc(PC_KBDC(config, "pc_kbdc", 0)); + kbdc.out_clock_cb().set(m_kbdc, FUNC(at_keyboard_controller_device::keyboard_clock_w)); + kbdc.out_data_cb().set(m_kbdc, FUNC(at_keyboard_controller_device::keyboard_data_w)); + + // keyboard port + pc_kbdc_slot_device &kbd(PC_KBDC_SLOT(config, "kbd", 0)); + pc_at_keyboards(kbd); + kbd.set_default_option(STR_KBD_IBM_PC_AT_84); + kbd.set_pc_kbdc_slot(&kbdc); + + // at keyboard controller + AT_KEYBOARD_CONTROLLER(config, m_kbdc, 12_MHz_XTAL); + m_kbdc->system_reset_cb().set_inputline(m_maincpu, INPUT_LINE_RESET); + m_kbdc->keyboard_clock_cb().set(kbdc, FUNC(pc_kbdc_device::clock_write_from_mb)); + m_kbdc->keyboard_data_cb().set(kbdc, FUNC(pc_kbdc_device::data_write_from_mb)); + + G364(config, m_ramdac, 0); +} + +void jazz_state::mmr4000be(machine_config &config) +{ + R4000BE(config, m_maincpu, 50_MHz_XTAL); + + jazz(config); + + DP83932C_BE(config, m_network, 20_MHz_XTAL); +} + +void jazz_state::mmr4000le(machine_config &config) +{ + R4000LE(config, m_maincpu, 50_MHz_XTAL); + + jazz(config); + + DP83932C_LE(config, m_network, 20_MHz_XTAL); +} + +ROM_START(mmr4000be) + ROM_REGION32_BE(0x40000, "flash", 0) + ROM_SYSTEM_BIOS(0, "riscos", "R4000 RISC/os PROM") + ROMX_LOAD("riscos.bin", 0x00000, 0x40000, CRC(cea6bc8f) SHA1(3e47b4ad5d1a0c7aac649e6aef3df1bf86fc938b), ROM_BIOS(0)) +ROM_END + +ROM_START(mmr4000le) + ROM_REGION32_LE(0x40000, "flash", 0) + ROM_SYSTEM_BIOS(0, "ntprom", "R4000 Windows NT PROM") + ROMX_LOAD("ntprom.bin", 0x00000, 0x40000, CRC(d91018d7) SHA1(316de17820192c89b8ee6d9936ab8364a739ca53), ROM_BIOS(0)) +ROM_END + +/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */ +COMP( 1992, mmr4000be, 0, 0, mmr4000be, 0, jazz_state, init_common, "MIPS", "Magnum R4000 (big)", MACHINE_IS_SKELETON) +COMP( 1992, mmr4000le, 0, 0, mmr4000le, 0, jazz_state, init_common, "MIPS", "Magnum R4000 (little)", MACHINE_IS_SKELETON) diff --git a/src/mame/includes/jazz.h b/src/mame/includes/jazz.h new file mode 100644 index 00000000000..d666b81a45a --- /dev/null +++ b/src/mame/includes/jazz.h @@ -0,0 +1,97 @@ +// license:BSD-3-Clause +// copyright-holders:Patrick Mackinlay + +#ifndef MAME_INCLUDES_JAZZ_H +#define MAME_INCLUDES_JAZZ_H + +#pragma once + +#include "cpu/mips/mips3.h" + +// memory +#include "machine/ram.h" +#include "machine/nvram.h" +#include "machine/28fxxx.h" + +// various hardware +#include "machine/jazz_mct_adr.h" +#include "machine/dp83932c.h" +#include "machine/mc146818.h" +#include "machine/ncr5390.h" +#include "machine/upd765.h" +#include "machine/at_keybc.h" + +// video +#include "screen.h" +#include "video/ims_cvc.h" + +// busses and connectors +#include "machine/nscsi_bus.h" +#include "machine/nscsi_cd.h" +#include "machine/nscsi_hd.h" +#include "bus/rs232/rs232.h" +#include "bus/pc_kbd/pc_kbdc.h" +#include "bus/pc_kbd/keyboards.h" + +class jazz_state : public driver_device +{ +public: + jazz_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag) + , m_maincpu(*this, "cpu") + , m_ram(*this, "ram") + , m_mct_adr(*this, "mct_adr") + , m_scsibus(*this, "scsi") + , m_scsi(*this, "scsi:7:host") + , m_fdc(*this, "fdc") + , m_rtc(*this, "rtc") + , m_nvram(*this, "nvram") + , m_flash(*this, "flash") + , m_kbdc(*this, "kbdc") + , m_network(*this, "net") + , m_ramdac(*this, "g364") + { + } + +protected: + // driver_device overrides + virtual void machine_start() override; + virtual void machine_reset() override; + + // address maps + void jazz_common_map(address_map &map); + + // machine config + void jazz(machine_config &config); +public: + void mmr4000be(machine_config &config); + void mmr4000le(machine_config &config); + + void init_common(); + +protected: + // devices + required_device m_maincpu; + required_device m_ram; + required_device m_mct_adr; + required_device m_scsibus; + required_device m_scsi; + required_device m_fdc; + required_device m_rtc; + required_device m_nvram; + required_device m_flash; + required_device m_kbdc; + required_device m_network; + //required_device m_screen; + required_device m_ramdac; + + // helpers + u8 led_r() { return m_led; } + void led_w(const u8 data) { logerror("led 0x%02x\n", data); m_led = data; } + +private: + // machine state + u8 m_led; +}; + +#endif // MAME_INCLUDES_JAZZ_H diff --git a/src/mame/machine/jazz_mct_adr.cpp b/src/mame/machine/jazz_mct_adr.cpp new file mode 100644 index 00000000000..e14075f3f3f --- /dev/null +++ b/src/mame/machine/jazz_mct_adr.cpp @@ -0,0 +1,51 @@ +// license:BSD-3-Clause +// copyright-holders:Patrick Mackinlay + +/* + * An implementation of the MCT-ADR device found in Microsoft Jazz/MIPS + * ARCSystem 100 architecture systems. This device was originally designed + * by Microsoft, and then implemented and used in various forms by MIPS, + * Olivetti, LSI Logic, NEC, Acer and others. + * + * Specific implementations/derivatives include: + * + * LSI Logic R4030/R4230 + * NEC μPD31432 + * ALI M6101-A1 + * + * References: + * + * https://datasheet.datasheetarchive.com/originals/scans/Scans-054/DSAIH000102184.pdf + * https://github.com/torvalds/linux/tree/master/arch/mips/jazz/ + * http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/arch/arc/jazz/ + * + * TODO + * - everything (skeleton only) + */ + +#include "emu.h" +#include "jazz_mct_adr.h" + +#define VERBOSE 0 +#include "logmacro.h" + +DEFINE_DEVICE_TYPE(JAZZ_MCT_ADR, jazz_mct_adr_device, "jazz_mct_adr", "Jazz MCT-ADR") + +jazz_mct_adr_device::jazz_mct_adr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, JAZZ_MCT_ADR, tag, owner, clock) +{ +} + +void jazz_mct_adr_device::map(address_map &map) +{ + map(0x000, 0x003).lr32("config", [](){ return 0x00000000; }); + map(0x008, 0x00b).lr32("revision", [](){ return 0xf0000000; }); +} + +void jazz_mct_adr_device::device_start() +{ +} + +void jazz_mct_adr_device::device_reset() +{ +} diff --git a/src/mame/machine/jazz_mct_adr.h b/src/mame/machine/jazz_mct_adr.h new file mode 100644 index 00000000000..dd2b651d25c --- /dev/null +++ b/src/mame/machine/jazz_mct_adr.h @@ -0,0 +1,25 @@ +// license:BSD-3-Clause +// copyright-holders:Patrick Mackinlay + +#ifndef MAME_MACHINE_JAZZ_MCT_ADR_H +#define MAME_MACHINE_JAZZ_MCT_ADR_H + +#pragma once + +class jazz_mct_adr_device : public device_t +{ +public: + jazz_mct_adr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + virtual void map(address_map &map); + +protected: + // device_t overrides + virtual void device_start() override; + virtual void device_reset() override; +}; + +// device type definition +DECLARE_DEVICE_TYPE(JAZZ_MCT_ADR, jazz_mct_adr_device) + +#endif // MAME_MACHINE_JAZZ_MCT_ADR_H diff --git a/src/mame/mame.lst b/src/mame/mame.lst index 13291fa64db..384bd1bef8e 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -15922,6 +15922,10 @@ jankenmn // (c) 1985 Sunwise @source:jantotsu.cpp jantotsu // (c) 1983 Sanritsu +@source:jazz.cpp +mmr4000be // MIPS Magnum R4000 (big) +mmr4000le // MIPS Magnum R4000 (little) + @source:jchan.cpp jchan // (c) 1995 Kaneko jchan2 // (c) 1995 Kaneko -- cgit v1.2.3 From 27ee4f39156863330dd2c369b47699ad774306aa Mon Sep 17 00:00:00 2001 From: mooglyguy Date: Sat, 22 Sep 2018 19:40:43 +0200 Subject: -sun4: Added a sun4c MMU device. Currently wraps the functionality of S4-buffer, S4-cache, and S4-MMU, will eventually be split. [Ryan Holtz] -sun4: Significant optimization, from 150% -> 330% unthrottled on an i7-5930K. [Ryan Holtz] --- scripts/src/cpu.lua | 1 + scripts/src/machine.lua | 12 + scripts/target/mame/arcade.lua | 1 + scripts/target/mame/mess.lua | 1 + src/devices/bus/nubus/quadralink.cpp | 32 +- src/devices/bus/sbus/bwtwo.cpp | 40 +- src/devices/bus/sbus/bwtwo.h | 7 +- src/devices/cpu/sparc/mb86901.cpp | 448 +++++++++++----------- src/devices/cpu/sparc/sparc.h | 50 ++- src/devices/cpu/sparc/sparc_intf.h | 30 ++ src/devices/cpu/sparc/sparcdefs.h | 2 +- src/devices/machine/ncr5390.cpp | 67 ++++ src/devices/machine/ncr5390.h | 9 + src/devices/machine/sun4c_mmu.cpp | 497 ++++++++++++++++++++++++ src/devices/machine/sun4c_mmu.h | 149 ++++++++ src/devices/machine/z80scc.cpp | 8 +- src/devices/machine/z80scc.h | 18 +- src/mame/drivers/apple2gs.cpp | 16 +- src/mame/drivers/sun4.cpp | 712 ++++++++--------------------------- src/mame/machine/iteagle_fpga.cpp | 18 +- 20 files changed, 1243 insertions(+), 875 deletions(-) create mode 100644 src/devices/cpu/sparc/sparc_intf.h create mode 100644 src/devices/machine/sun4c_mmu.cpp create mode 100644 src/devices/machine/sun4c_mmu.h (limited to 'scripts/src') diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua index 6a8519a644b..846e1bad71c 100644 --- a/scripts/src/cpu.lua +++ b/scripts/src/cpu.lua @@ -2713,6 +2713,7 @@ if (CPUS["MB86901"]~=null) then MAME_DIR .. "src/devices/cpu/sparc/mb86901.cpp", MAME_DIR .. "src/devices/cpu/sparc/sparcv8ops.ipp", MAME_DIR .. "src/devices/cpu/sparc/sparcdefs.h", + MAME_DIR .. "src/devices/cpu/sparc/sparc_intf.h", MAME_DIR .. "src/devices/cpu/sparc/sparc.h", } end diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua index cd141b26cb3..b161f1ddbcf 100644 --- a/scripts/src/machine.lua +++ b/scripts/src/machine.lua @@ -3747,3 +3747,15 @@ if (MACHINES["IOPTIMER"]~=null) then MAME_DIR .. "src/devices/machine/ioptimer.h", } end + +--------------------------------------------------- +-- +--@src/devices/machine/sun4c_mmu.h,MACHINES["SUN4C_MMU"] = true +--------------------------------------------------- + +if (MACHINES["SUN4C_MMU"]~=null) then + files { + MAME_DIR .. "src/devices/machine/sun4c_mmu.cpp", + MAME_DIR .. "src/devices/machine/sun4c_mmu.h", + } +end diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua index f27b41c32a2..705c4c92aa9 100644 --- a/scripts/target/mame/arcade.lua +++ b/scripts/target/mame/arcade.lua @@ -574,6 +574,7 @@ MACHINES["SMC91C9X"] = true MACHINES["SEGA_SCU"] = true MACHINES["SMPC"] = true MACHINES["STVCD"] = true +--MACHINES["SUN4C_MMU"] = true MACHINES["TC0091LVC"] = true MACHINES["TE7750"] = true MACHINES["TICKET"] = true diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index 29e19eee5ea..95e8e3fabfc 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -576,6 +576,7 @@ MACHINES["SMIOC"] = true MACHINES["SEGA_SCU"] = true MACHINES["SMPC"] = true MACHINES["STVCD"] = true +MACHINES["SUN4C_MMU"] = true MACHINES["TC0091LVC"] = true --MACHINES["TE7750"] = true MACHINES["TIMEKPR"] = true diff --git a/src/devices/bus/nubus/quadralink.cpp b/src/devices/bus/nubus/quadralink.cpp index f38a0f3b57b..a2d138874e6 100644 --- a/src/devices/bus/nubus/quadralink.cpp +++ b/src/devices/bus/nubus/quadralink.cpp @@ -126,35 +126,35 @@ WRITE32_MEMBER( nubus_quadralink_device::dev_w ) switch (offset) { case 0x0000: // SCC 2 A control - m_scc2->ca_w(space, 0, data & 0xff); + m_scc2->ca_w(0, data & 0xff); break; case 0x0002: // SCC 2 A data - m_scc2->da_w(space, 0, data & 0xff); + m_scc2->da_w(0, data & 0xff); break; case 0x0004: // SCC 2 B control - m_scc2->cb_w(space, 0, data & 0xff); + m_scc2->cb_w(0, data & 0xff); break; case 0x0006: // SCC 2 B data - m_scc2->db_w(space, 0, data & 0xff); + m_scc2->db_w(0, data & 0xff); break; case 0x10000: // SCC 1 A control - m_scc1->ca_w(space, 0, data & 0xff); + m_scc1->ca_w(0, data & 0xff); break; case 0x10002: // SCC 1 A data - m_scc1->da_w(space, 0, data & 0xff); + m_scc1->da_w(0, data & 0xff); break; case 0x10004: // SCC 1 B control - m_scc1->cb_w(space, 0, data & 0xff); + m_scc1->cb_w(0, data & 0xff); break; case 0x10006: // SCC 1 B data - m_scc1->db_w(space, 0, data & 0xff); + m_scc1->db_w(0, data & 0xff); break; } } @@ -165,28 +165,28 @@ READ32_MEMBER( nubus_quadralink_device::dev_r ) switch (offset) { case 0x0000: - return m_scc2->ca_r(space, 0); + return m_scc2->ca_r(0); case 0x0002: - return m_scc2->da_r(space, 0); + return m_scc2->da_r(0); case 0x0004: - return m_scc2->cb_r(space, 0); + return m_scc2->cb_r(0); case 0x0006: - return m_scc2->db_r(space, 0); + return m_scc2->db_r(0); case 0x10000: - return m_scc1->ca_r(space, 0); + return m_scc1->ca_r(0); case 0x10002: - return m_scc1->da_r(space, 0); + return m_scc1->da_r(0); case 0x10004: - return m_scc1->cb_r(space, 0); + return m_scc1->cb_r(0); case 0x10006: - return m_scc1->db_r(space, 0); + return m_scc1->db_r(0); } return 0xffffffff; } diff --git a/src/devices/bus/sbus/bwtwo.cpp b/src/devices/bus/sbus/bwtwo.cpp index ab9fd194a88..553e040ec1a 100644 --- a/src/devices/bus/sbus/bwtwo.cpp +++ b/src/devices/bus/sbus/bwtwo.cpp @@ -54,7 +54,15 @@ sbus_bwtwo_device::sbus_bwtwo_device(const machine_config &mconfig, const char * void sbus_bwtwo_device::device_start() { - m_vram = std::make_unique(0x100000/4); + m_vram = std::make_unique(0x100000); + + for (int i = 0; i < 0x100; i++) + { + for (int bit = 7; bit >= 0; bit--) + { + m_mono_lut[i][7 - bit] = BIT(i, bit) ? 0 : ~0; + } + } } void sbus_bwtwo_device::install_device() @@ -64,25 +72,15 @@ void sbus_bwtwo_device::install_device() uint32_t sbus_bwtwo_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { - static const uint32_t palette[2] = { 0xffffff, 0 }; - uint8_t *vram = (uint8_t *)&m_vram[0]; - for (int y = 0; y < 900; y++) { uint32_t *scanline = &bitmap.pix32(y); - uint8_t *line = vram + y * (1152/8); + uint8_t *line = &m_vram[y * 1152/8]; for (int x = 0; x < 1152/8; x++) { - const uint8_t pixels = line[BYTE4_XOR_BE(x)]; - - *scanline++ = palette[BIT(pixels, 7)]; - *scanline++ = palette[BIT(pixels, 6)]; - *scanline++ = palette[BIT(pixels, 5)]; - *scanline++ = palette[BIT(pixels, 4)]; - *scanline++ = palette[BIT(pixels, 3)]; - *scanline++ = palette[BIT(pixels, 2)]; - *scanline++ = palette[BIT(pixels, 1)]; - *scanline++ = palette[BIT(pixels, 0)]; + memcpy(scanline, m_mono_lut[*line], sizeof(uint32_t) * 8); + line++; + scanline += 8; } } @@ -100,17 +98,17 @@ WRITE8_MEMBER(sbus_bwtwo_device::regs_w) logerror("%s: regs_w (unimplemented): %08x = %02x\n", machine().describe_context(), 0x400000 + offset, data); } -READ32_MEMBER(sbus_bwtwo_device::vram_r) +READ32_MEMBER(sbus_bwtwo_device::rom_r) { - return m_vram[offset]; + return ((uint32_t*)m_rom->base())[offset]; } -READ32_MEMBER(sbus_bwtwo_device::rom_r) +READ8_MEMBER(sbus_bwtwo_device::vram_r) { - return ((uint32_t*)m_rom->base())[offset]; + return m_vram[offset]; } -WRITE32_MEMBER(sbus_bwtwo_device::vram_w) +WRITE8_MEMBER(sbus_bwtwo_device::vram_w) { - COMBINE_DATA(&m_vram[offset]); + m_vram[offset] = data; } diff --git a/src/devices/bus/sbus/bwtwo.h b/src/devices/bus/sbus/bwtwo.h index 0d4a96f2f39..fb3408db7d4 100644 --- a/src/devices/bus/sbus/bwtwo.h +++ b/src/devices/bus/sbus/bwtwo.h @@ -32,8 +32,8 @@ protected: DECLARE_READ8_MEMBER(regs_r); DECLARE_WRITE8_MEMBER(regs_w); DECLARE_READ32_MEMBER(rom_r); - DECLARE_READ32_MEMBER(vram_r); - DECLARE_WRITE32_MEMBER(vram_w); + DECLARE_READ8_MEMBER(vram_r); + DECLARE_WRITE8_MEMBER(vram_w); private: uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); @@ -41,8 +41,9 @@ private: void mem_map(address_map &map) override; required_memory_region m_rom; - std::unique_ptr m_vram; + std::unique_ptr m_vram; required_device m_screen; + uint32_t m_mono_lut[256][8]; }; diff --git a/src/devices/cpu/sparc/mb86901.cpp b/src/devices/cpu/sparc/mb86901.cpp index 76ef7ac56e4..751e39610e3 100644 --- a/src/devices/cpu/sparc/mb86901.cpp +++ b/src/devices/cpu/sparc/mb86901.cpp @@ -8,6 +8,13 @@ // the integer instructions in a SPARC v7 // compatible instruction set. // +// Notes: +// - The CPU core implementation has been simplified +// somewhat compared to the spec. In particular, bus +// holding on read/write accesses is disabled, as there +// is currently no use made of it, and it is unlikely to +// ever be. +// // To-Do: // - Ops: FBFcc, LDF, STF // - Test: SPARCv8 ops are untested @@ -41,16 +48,9 @@ const int mb86901_device::NWINDOWS = 7; mb86901_device::mb86901_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : cpu_device(mconfig, MB86901, tag, owner, clock) + , m_mmu(*this, finder_base::DUMMY_TAG) { m_default_config = address_space_config("program", ENDIANNESS_BIG, 32, 32); - - char buf[32]; - for (uint32_t i = 0; i < AS_COUNT; i++) - { - snprintf(buf, ARRAY_LENGTH(buf), "asi%d", i); - m_asi_names[i] = buf; - m_asi_config[i] = address_space_config(m_asi_names[i].c_str(), ENDIANNESS_BIG, 32, 32); - } } @@ -153,6 +153,29 @@ void mb86901_device::device_start() memset(m_privileged_asr, 1, 32 * sizeof(bool)); m_privileged_asr[0] = false; + memset(m_alu_setcc, 0, 64 * sizeof(bool)); + m_alu_setcc[OP3_ADDCC] = true; + m_alu_setcc[OP3_ANDCC] = true; + m_alu_setcc[OP3_ORCC] = true; + m_alu_setcc[OP3_XORCC] = true; + m_alu_setcc[OP3_SUBCC] = true; + m_alu_setcc[OP3_ANDNCC] = true; + m_alu_setcc[OP3_ORNCC] = true; + m_alu_setcc[OP3_XNORCC] = true; + m_alu_setcc[OP3_ADDXCC] = true; + m_alu_setcc[OP3_SUBXCC] = true; + m_alu_setcc[OP3_TADDCC] = true; + m_alu_setcc[OP3_TSUBCC] = true; + m_alu_setcc[OP3_TADDCCTV] = true; + m_alu_setcc[OP3_TSUBCCTV] = true; + m_alu_setcc[OP3_MULSCC] = true; +#if SPARCV8 + m_alu_setcc[OP3_UMULCC] = true; + m_alu_setcc[OP3_SMULCC] = true; + m_alu_setcc[OP3_UDIVCC] = true; + m_alu_setcc[OP3_SDIVCC] = true; +#endif + memset(m_alu_op3_assigned, 0, 64 * sizeof(bool)); m_alu_op3_assigned[OP3_ADD] = true; m_alu_op3_assigned[OP3_AND] = true; @@ -210,11 +233,6 @@ void mb86901_device::device_start() m_alu_op3_assigned[OP3_UDIVCC] = true; m_alu_op3_assigned[OP3_SDIVCC] = true; #endif - for (uint32_t i = 0; i < AS_COUNT; i++) - { - m_space[i] = &space(AS_START + i); - m_access_cache[i] = m_space[i]->cache<2, 0, ENDIANNESS_BIG>(); - } memset(m_ldst_op3_assigned, 0, 64 * sizeof(bool)); m_ldst_op3_assigned[OP3_LD] = true; @@ -379,6 +397,10 @@ void mb86901_device::device_stop() { } +void mb86901_device::device_resolve_objects() +{ + m_mmu->set_host(this); +} void mb86901_device::device_reset() { @@ -405,6 +427,8 @@ void mb86901_device::device_reset() m_bp_irl = 0; m_irq_state = 0; + m_stashed_icount = -1; + MAE = false; HOLD_BUS = false; m_annul = false; @@ -420,7 +444,8 @@ void mb86901_device::device_reset() PSR = PSR_S_MASK | PSR_PS_MASK; m_s = true; - m_fetch_space = 9; + m_insn_space = 9; + m_data_space = 11; for (int i = 0; i < 8; i++) { @@ -448,10 +473,6 @@ device_memory_interface::space_config_vector mb86901_device::memory_space_config { space_config_vector config_vector; config_vector.push_back(std::make_pair(AS_PROGRAM, &m_default_config)); - for (uint32_t i = 0; i < 32; i++) - { - config_vector.push_back(std::make_pair(AS_START + i, &m_asi_config[i])); - } return config_vector; } @@ -463,21 +484,10 @@ device_memory_interface::space_config_vector mb86901_device::memory_space_config // a 32-bit word in a big-endian system. //------------------------------------------------- -uint32_t mb86901_device::read_sized_word(uint8_t asi, uint32_t address, int size) +uint32_t mb86901_device::read_sized_word(const uint8_t asi, const uint32_t address, const uint32_t mem_mask) { assert(asi < 0x20); // We do not currently support ASIs outside the range used by actual Sun machines. - if (size == 1) - { - return m_access_cache[asi]->read_byte(address) << ((3 - (address & 3)) * 8); - } - else if (size == 2) - { - return m_access_cache[asi]->read_word(address) << ((2 - (address & 2)) * 8); - } - else - { - return m_access_cache[asi]->read_dword(address); - } + return m_mmu->read_asi(asi, address >> 2, mem_mask); } @@ -490,21 +500,10 @@ uint32_t mb86901_device::read_sized_word(uint8_t asi, uint32_t address, int size // size handlers //------------------------------------------------- -void mb86901_device::write_sized_word(uint8_t asi, uint32_t address, uint32_t data, int size) +void mb86901_device::write_sized_word(const uint8_t asi, const uint32_t address, const uint32_t data, const uint32_t mem_mask) { assert(asi < 0x20); // We do not currently support ASIs outside the range used by actual Sun machines. - if (size == 1) - { - m_access_cache[asi]->write_byte(address, data >> ((3 - (address & 3)) * 8)); - } - else if (size == 2) - { - m_access_cache[asi]->write_word(address, data >> ((2 - (address & 2)) * 8)); - } - else - { - m_access_cache[asi]->write_dword(address, data); - } + m_mmu->write_asi(asi, address >> 2, data, mem_mask); } @@ -911,10 +910,11 @@ void mb86901_device::execute_logical(uint32_t op) ); */ - uint32_t operand2 = USEIMM ? SIMM13 : RS2REG; + const uint32_t operand2 = USEIMM ? SIMM13 : RS2REG; + const uint32_t op3 = OP3; uint32_t result = 0; - switch (OP3) + switch (op3) { case OP3_AND: case OP3_ANDCC: @@ -945,11 +945,13 @@ void mb86901_device::execute_logical(uint32_t op) if (RD != 0) RDREG = result; - if (ANDCC || ANDNCC || ORCC || ORNCC || XORCC || XNORCC) + if (m_alu_setcc[op3]) { CLEAR_ICC; - PSR |= (BIT31(result)) ? PSR_N_MASK : 0; - PSR |= (result == 0) ? PSR_Z_MASK : 0; + if (result & 0x80000000) + PSR |= PSR_N_MASK; + else if (result == 0) + PSR |= PSR_Z_MASK; } PC = nPC; @@ -1205,7 +1207,16 @@ void mb86901_device::execute_wrsr(uint32_t op) m_et = PSR & PSR_ET_MASK; m_pil = (PSR & PSR_PIL_MASK) >> PSR_PIL_SHIFT; m_s = PSR & PSR_S_MASK; - m_fetch_space = m_s ? 9 : 8; + if (m_s) + { + m_insn_space = 9; + m_data_space = 11; + } + else + { + m_insn_space = 8; + m_data_space = 10; + } PC = nPC; nPC = nPC + 4; @@ -1304,6 +1315,8 @@ void mb86901_device::execute_rett(uint32_t op) m_tt = 3; m_execute_mode = 0; m_error_mode = 1; + m_stashed_icount = m_icount; + m_icount = 0; return; } else if ((WIM & (1 << new_cwp)) != 0) @@ -1313,6 +1326,8 @@ void mb86901_device::execute_rett(uint32_t op) m_tt = 6; m_execute_mode = 0; m_error_mode = 1; + m_stashed_icount = m_icount; + m_icount = 0; return; } else if (address & 3) @@ -1322,6 +1337,8 @@ void mb86901_device::execute_rett(uint32_t op) m_tt = 7; m_execute_mode = 0; m_error_mode = 1; + m_stashed_icount = m_icount; + m_icount = 0; return; } @@ -1337,13 +1354,15 @@ void mb86901_device::execute_rett(uint32_t op) { PSR |= PSR_S_MASK; m_s = true; - m_fetch_space = 9; + m_insn_space = 9; + m_data_space = 11; } else { PSR &= ~PSR_S_MASK; m_s = false; - m_fetch_space = 8; + m_insn_space = 8; + m_data_space = 10; } update_gpr_pointers(); @@ -1405,7 +1424,6 @@ void mb86901_device::execute_saverestore(uint32_t op) result = rs1 + operand2; PSR &= ~PSR_CWP_MASK; PSR |= new_cwp; - //BREAK_PSR; } else if (RESTORE) { @@ -1420,7 +1438,6 @@ void mb86901_device::execute_saverestore(uint32_t op) result = rs1 + operand2; PSR &= ~PSR_CWP_MASK; PSR |= new_cwp; - //BREAK_PSR; } update_gpr_pointers(); @@ -1475,7 +1492,7 @@ void mb86901_device::execute_jmpl(uint32_t op) // mostly ALU ops //------------------------------------------------- -void mb86901_device::execute_group2(uint32_t op) +inline void mb86901_device::execute_group2(uint32_t op) { switch (OP3) { @@ -1550,6 +1567,7 @@ void mb86901_device::execute_group2(uint32_t op) m_trap = 1; m_fp_disabled = 1; } + complete_fp_execution(op); return; case OP3_JMPL: @@ -1592,14 +1610,14 @@ void mb86901_device::execute_group2(uint32_t op) case OP3_CPOP1: case OP3_CPOP2: - printf("fpop @ %08x: %08x\n", PC, op); + logerror("fpop @ %08x: %08x\n", PC, op); m_trap = 1; m_cp_disabled = 1; return; #endif default: - printf("illegal instruction at %08x: %08x\n", PC, op); + logerror("illegal instruction at %08x: %08x\n", PC, op); m_trap = 1; m_illegal_instruction = 1; break; @@ -1768,7 +1786,7 @@ void mb86901_device::execute_store(uint32_t op) if (STD || ST || STH || STB || STF || STDF || STFSR || STDFQ || STCSR || STC || STDC || STDCQ) { address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); + addr_space = m_data_space; } else if (STDA || STA || STHA || STBA) { @@ -1925,7 +1943,9 @@ void mb86901_device::execute_store(uint32_t op) } } - write_sized_word(addr_space, address, data0, (ST || STA || STD || STDA || STF || STDF || STDFQ || STFSR || STC || STDC || STDCQ || STCSR) ? 4 : ((STH || STHA) ? 2 : 1)); + static const uint32_t mask16[4] = { 0xffff0000, 0x00000000, 0x0000ffff, 0x00000000 }; + static const uint32_t mask8[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff }; + m_mmu->write_asi(addr_space, address >> 2, data0, (ST || STA || STD || STDA || STF || STDF || STDFQ || STFSR || STC || STDC || STDCQ || STCSR) ? 0xffffffff : ((STH || STHA) ? mask16[address & 2] : mask8[address & 3])); if (MAE) { m_trap = 1; @@ -1957,7 +1977,7 @@ void mb86901_device::execute_store(uint32_t op) data1 = 0; } - write_sized_word(addr_space, address + 4, data1, 4); + m_mmu->write_asi(addr_space, (address + 4) >> 2, data1, 0xffffffff); if (MAE) { m_trap = 1; @@ -2076,14 +2096,14 @@ void mb86901_device::execute_load(uint32_t op) ); */ - uint32_t address = 0; - uint8_t addr_space = 0; + static const uint32_t mask16[4] = { 0xffff0000, 0x00000000, 0x0000ffff, 0x00000000 }; + static const uint32_t mask8[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff }; + switch (OP3) { case OP3_LDD: { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); + const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); if (address & 7) { @@ -2091,7 +2111,7 @@ void mb86901_device::execute_load(uint32_t op) m_mem_address_not_aligned = 1; } - const uint32_t data = read_sized_word(addr_space, address, 4); + const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); if (MAE) { @@ -2103,7 +2123,7 @@ void mb86901_device::execute_load(uint32_t op) if (RD != 0) RDREG = data; - const uint32_t word1 = read_sized_word(addr_space, address + 4, 4); + const uint32_t word1 = m_mmu->read_asi(m_data_space, (address + 4) >> 2, 0xffffffff); if (MAE) { m_trap = 1; @@ -2116,8 +2136,7 @@ void mb86901_device::execute_load(uint32_t op) } case OP3_LD: { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); + const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); if (address & 3) { @@ -2126,7 +2145,7 @@ void mb86901_device::execute_load(uint32_t op) return; } - const uint32_t data = read_sized_word(addr_space, address, 4); + const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); if (m_mae) { @@ -2141,8 +2160,7 @@ void mb86901_device::execute_load(uint32_t op) } case OP3_LDSH: { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); + const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); if (address & 1) { @@ -2151,7 +2169,7 @@ void mb86901_device::execute_load(uint32_t op) return; } - const uint32_t data = read_sized_word(addr_space, address, 2); + const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, mask16[address & 2]); if (m_mae) { @@ -2169,8 +2187,7 @@ void mb86901_device::execute_load(uint32_t op) } case OP3_LDUH: { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); + const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); if (address & 1) { @@ -2179,7 +2196,7 @@ void mb86901_device::execute_load(uint32_t op) return; } - const uint32_t data = read_sized_word(addr_space, address, 2); + const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, mask16[address & 2]); if (m_mae) { @@ -2197,10 +2214,9 @@ void mb86901_device::execute_load(uint32_t op) } case OP3_LDSB: { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); + const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - const uint32_t data = read_sized_word(addr_space, address, 1); + const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, mask8[address & 3]); if (m_mae) { @@ -2220,10 +2236,9 @@ void mb86901_device::execute_load(uint32_t op) } case OP3_LDUB: { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); + const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - const uint32_t data = read_sized_word(addr_space, address, 1); + const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, mask8[address & 3]); if (m_mae) { @@ -2243,8 +2258,7 @@ void mb86901_device::execute_load(uint32_t op) } case OP3_LDDFPR: { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); + const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); if (!(PSR & PSR_EF_MASK) || m_bp_fpu_present == 0) { @@ -2276,7 +2290,7 @@ void mb86901_device::execute_load(uint32_t op) return; } - const uint32_t data = read_sized_word(addr_space, address, 4); + const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); if (m_mae) { @@ -2287,7 +2301,7 @@ void mb86901_device::execute_load(uint32_t op) FREG(RD & 0x1e) = data; - const uint32_t word1 = read_sized_word(addr_space, address + 4, 4); + const uint32_t word1 = m_mmu->read_asi(m_data_space, (address + 4) >> 2, 0xffffffff); if (MAE) { m_trap = 1; @@ -2300,8 +2314,7 @@ void mb86901_device::execute_load(uint32_t op) } case OP3_LDFPR: { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); + const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); if (!(PSR & PSR_EF_MASK) || m_bp_fpu_present == 0) { @@ -2325,7 +2338,7 @@ void mb86901_device::execute_load(uint32_t op) return; } - const uint32_t data = read_sized_word(addr_space, address, 4); + const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); if (m_mae) { @@ -2339,8 +2352,7 @@ void mb86901_device::execute_load(uint32_t op) } case OP3_LDFSR: { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); + const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); if (!(PSR & PSR_EF_MASK) || m_bp_fpu_present == 0) { @@ -2364,7 +2376,7 @@ void mb86901_device::execute_load(uint32_t op) return; } - const uint32_t data = read_sized_word(addr_space, address, 4); + const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); if (m_mae) { @@ -2378,8 +2390,7 @@ void mb86901_device::execute_load(uint32_t op) } case OP3_LDDCPR: { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); + const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); if (!(PSR & PSR_EC_MASK) || !m_bp_cp_present) { @@ -2403,7 +2414,7 @@ void mb86901_device::execute_load(uint32_t op) return; } - read_sized_word(addr_space, address, 4); + m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); if (MAE) { m_trap = 1; @@ -2413,7 +2424,7 @@ void mb86901_device::execute_load(uint32_t op) // implementation-dependent actions - read_sized_word(addr_space, address + 4, 4); + m_mmu->read_asi(m_data_space, (address + 4) >> 2, 0xffffffff); if (MAE) { m_trap = 1; @@ -2426,8 +2437,7 @@ void mb86901_device::execute_load(uint32_t op) } case OP3_LDCPR: { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); + const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); if (!(PSR & PSR_EC_MASK) || !m_bp_cp_present) { @@ -2451,7 +2461,7 @@ void mb86901_device::execute_load(uint32_t op) return; } - read_sized_word(addr_space, address, 4); + m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); if (MAE) { @@ -2465,8 +2475,7 @@ void mb86901_device::execute_load(uint32_t op) } case OP3_LDCSR: { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); + const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); if (!(PSR & PSR_EC_MASK) || !m_bp_cp_present) { @@ -2490,7 +2499,7 @@ void mb86901_device::execute_load(uint32_t op) return; } - read_sized_word(addr_space, address, 4); + m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); if (MAE) { @@ -2516,11 +2525,9 @@ void mb86901_device::execute_load(uint32_t op) m_illegal_instruction = 1; return; } - else - { - address = RS1REG + RS2REG; - addr_space = ASI; - } + + const uint32_t address = RS1REG + RS2REG; + const uint32_t addr_space = ASI; if (address & 7) { @@ -2529,7 +2536,7 @@ void mb86901_device::execute_load(uint32_t op) return; } - const uint32_t data = read_sized_word(addr_space, address, 4); + const uint32_t data = m_mmu->read_asi(addr_space, address >> 2, 0xffffffff); if (m_mae) { @@ -2541,7 +2548,7 @@ void mb86901_device::execute_load(uint32_t op) if (RD != 0) RDREG = data; - uint32_t word1 = read_sized_word(addr_space, address + 4, 4); + uint32_t word1 = m_mmu->read_asi(addr_space, (address + 4) >> 2, 0xffffffff); if (MAE) { m_trap = 1; @@ -2566,11 +2573,8 @@ void mb86901_device::execute_load(uint32_t op) m_illegal_instruction = 1; return; } - else - { - address = RS1REG + RS2REG; - addr_space = ASI; - } + + const uint32_t address = RS1REG + RS2REG; if (address & 3) { @@ -2579,7 +2583,7 @@ void mb86901_device::execute_load(uint32_t op) return; } - const uint32_t data = read_sized_word(addr_space, address, 4); + const uint32_t data = m_mmu->read_asi(ASI, address >> 2, 0xffffffff); if (m_mae) { @@ -2606,11 +2610,8 @@ void mb86901_device::execute_load(uint32_t op) m_illegal_instruction = 1; return; } - else - { - address = RS1REG + RS2REG; - addr_space = ASI; - } + + const uint32_t address = RS1REG + RS2REG; if (address & 1) { @@ -2619,7 +2620,7 @@ void mb86901_device::execute_load(uint32_t op) return; } - const uint32_t data = read_sized_word(addr_space, address, 2); + const uint32_t data = m_mmu->read_asi(ASI, address >> 2, mask16[address & 2]); if (m_mae) { @@ -2649,12 +2650,8 @@ void mb86901_device::execute_load(uint32_t op) m_illegal_instruction = 1; return; } - else - { - address = RS1REG + RS2REG; - addr_space = ASI; - } + const uint32_t address = RS1REG + RS2REG; if (address & 1) { m_trap = 1; @@ -2662,7 +2659,7 @@ void mb86901_device::execute_load(uint32_t op) return; } - const uint32_t data = read_sized_word(addr_space, address, 2); + const uint32_t data = m_mmu->read_asi(ASI, address >> 2, mask16[address & 2]); if (m_mae) { @@ -2692,13 +2689,9 @@ void mb86901_device::execute_load(uint32_t op) m_illegal_instruction = 1; return; } - else - { - address = RS1REG + RS2REG; - addr_space = ASI; - } - const uint32_t data = read_sized_word(addr_space, address, 1); + const uint32_t address = RS1REG + RS2REG; + const uint32_t data = m_mmu->read_asi(ASI, address >> 2, mask8[address & 3]); if (m_mae) { @@ -2730,13 +2723,9 @@ void mb86901_device::execute_load(uint32_t op) m_illegal_instruction = 1; return; } - else - { - address = RS1REG + RS2REG; - addr_space = ASI; - } - const uint32_t data = read_sized_word(addr_space, address, 1); + const uint32_t address = RS1REG + RS2REG; + const uint32_t data = m_mmu->read_asi(ASI, address >> 2, mask8[address & 3]); if (m_mae) { @@ -2868,7 +2857,8 @@ void mb86901_device::execute_ldstub(uint32_t op) m_pb_block_ldst_byte = 1; - data = read_sized_word(addr_space, address, 1); + static const uint32_t mask8[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff }; + data = m_mmu->read_asi(addr_space, address >> 2, mask8[address & 3]); if (MAE) { @@ -2877,24 +2867,7 @@ void mb86901_device::execute_ldstub(uint32_t op) return; } - //uint8_t byte_mask; - if ((address & 3) == 0) - { - //byte_mask = 8; - } - else if ((address & 3) == 1) - { - //byte_mask = 4; - } - else if ((address & 3) == 2) - { - //byte_mask = 2; - } - else if ((address & 3) == 3) - { - //byte_mask = 1; - } - write_sized_word(addr_space, address, 0xffffffff, 1); + m_mmu->write_asi(addr_space, address >> 2, 0xffffffff, mask8[address & 3]); m_pb_block_ldst_byte = 0; @@ -2935,7 +2908,7 @@ void mb86901_device::execute_ldstub(uint32_t op) // (load/store) //------------------------------------------------- -void mb86901_device::execute_group3(uint32_t op) +inline void mb86901_device::execute_group3(uint32_t op) { static const int ldst_cycles[64] = { 1, 1, 1, 2, 2, 2, 2, 3, @@ -3003,13 +2976,13 @@ void mb86901_device::execute_group3(uint32_t op) #endif default: - printf("illegal instruction at %08x: %08x\n", PC, op); + logerror("illegal instruction at %08x: %08x\n", PC, op); m_trap = 1; m_illegal_instruction = 1; break; } - if (MAE || HOLD_BUS) + if (MAE /*|| HOLD_BUS*/) m_icount--; else m_icount -= ldst_cycles[OP3]; @@ -3186,6 +3159,8 @@ void mb86901_device::select_trap() { m_execute_mode = 0; m_error_mode = 1; + m_stashed_icount = m_icount; + m_icount = 0; } else if (m_data_store_error) m_tt = 0x2b; @@ -3355,7 +3330,8 @@ void mb86901_device::execute_trap() PSR |= PSR_S_MASK; m_s = true; - m_fetch_space = 9; + m_insn_space = 9; + m_data_space = 11; int cwp = PSR & PSR_CWP_MASK; int new_cwp = ((cwp + NWINDOWS) - 1) % NWINDOWS; @@ -3425,13 +3401,14 @@ if (trap = 0) then ( inline void mb86901_device::dispatch_instruction(uint32_t op) { - switch (OP_NS) + const uint8_t op_type = OP; + switch (op_type) { - case OP_TYPE0_NS: // Bicc, SETHI, FBfcc + case OP_TYPE0: // Bicc, SETHI, FBfcc switch (OP2) { case OP2_UNIMP: // unimp - printf("unimp @ %x\n", PC); + logerror("unimp @ %x\n", PC); break; case OP2_BICC: // branch on integer condition codes execute_bicc(op); @@ -3446,7 +3423,7 @@ inline void mb86901_device::dispatch_instruction(uint32_t op) case OP2_FBFCC: // branch on floating-point condition codes if (!(PSR & PSR_EF_MASK) || !m_bp_fpu_present) { - //printf("fbfcc at %08x: %08x\n", PC, op); + logerror("fbfcc at %08x: %08x\n", PC, op); m_trap = 1; m_fp_disabled = 1; return; @@ -3456,7 +3433,7 @@ inline void mb86901_device::dispatch_instruction(uint32_t op) case OP2_CBCCC: // branch on coprocessor condition codes, SPARCv8 if (!(PSR & PSR_EC_MASK) || !m_bp_cp_present) { - printf("cbccc @ %08x: %08x\n", PC, op); + logerror("cbccc @ %08x: %08x\n", PC, op); m_trap = 1; m_cp_disabled = 1; return; @@ -3464,14 +3441,14 @@ inline void mb86901_device::dispatch_instruction(uint32_t op) return; #endif default: - printf("illegal instruction at %08x: %08x\n", PC, op); + logerror("illegal instruction at %08x: %08x\n", PC, op); m_trap = 1; m_illegal_instruction = 1; return; } break; - case OP_CALL_NS: // call + case OP_CALL: { uint32_t pc = PC; uint32_t callpc = PC + DISP30; @@ -3482,11 +3459,11 @@ inline void mb86901_device::dispatch_instruction(uint32_t op) break; } - case OP_ALU_NS: + case OP_ALU: execute_group2(op); break; - case OP_LDST_NS: + case OP_LDST: execute_group3(op); break; } @@ -3506,7 +3483,7 @@ void mb86901_device::complete_fp_execution(uint32_t /*op*/) // mode (versus error or reset modes) //------------------------------------------------- -void mb86901_device::execute_step() +inline void mb86901_device::execute_step() { /* The SPARC Instruction Manual: Version 8, page 156, "Appendix C - ISP Descriptions - C.5. Processor States and Instruction Dispatch" (SPARCv8.pdf, pg. 153) @@ -3565,7 +3542,8 @@ void mb86901_device::execute_step() m_execute_mode = 0; m_error_mode = 0; m_reset_mode = 1; - //printf("Entering reset mode\n"); + m_stashed_icount = m_icount; + m_icount = 0; return; } else if (m_et && (m_bp_irl == 15 || m_bp_irl > m_pil)) @@ -3577,51 +3555,35 @@ void mb86901_device::execute_step() if (m_trap) { execute_trap(); - //BREAK_PSR; - debugger_instruction_hook(PC); } - if (m_execute_mode) - { - // write-state-register delay not yet implemented + // write-state-register delay not yet implemented - const uint32_t op = read_sized_word(m_fetch_space, PC, 4); + const uint32_t op = m_mmu->read_asi(m_insn_space, PC >> 2, 0xffffffff); #if LOG_FCODES - //if (m_log_fcodes) - { - log_fcodes(); - } + //if (m_log_fcodes) + { + log_fcodes(); + } #endif - if (MAE && !m_annul) + if (MAE && !m_annul) + { + m_trap = 1; + m_instruction_access_exception = 1; + } + else + { + if (!m_annul) { - m_trap = 1; - m_instruction_access_exception = 1; + dispatch_instruction(op); } else { - if (!m_annul) - { - dispatch_instruction(op); - - if (FPOP1 || FPOP2) - { - complete_fp_execution(op); - } - - //if (m_trap == 0 && !(OP == OP_CALL || (OP == OP_TYPE0 && (OP2 == OP2_BICC || OP2 == OP2_FBFCC || OP2 == OP2_CBCCC)) || (OP == OP_ALU && (JMPL || TICC || RETT)))) - //{ - //PC = nPC; - //nPC = nPC + 4; - //} - } - else - { - m_annul = 0; - PC = nPC; - nPC = nPC + 4; - } + m_annul = 0; + PC = nPC; + nPC = nPC + 4; } } } @@ -3651,7 +3613,8 @@ void mb86901_device::reset_step() m_execute_mode = 1; m_trap = 1; m_reset_trap = 1; - //printf("m_bp_reset_in is false, resetting\n"); + m_stashed_icount = m_icount; + m_icount = 0; } } @@ -3678,44 +3641,39 @@ void mb86901_device::error_step() m_error_mode = 0; m_reset_mode = 1; m_pb_error = 0; + m_stashed_icount = m_icount; + m_icount = 0; } } - -//------------------------------------------------- -// execute_run - execute a timeslice's worth of -// opcodes -//------------------------------------------------- - -void mb86901_device::execute_run() +template +void mb86901_device::run_loop() { - bool debug = machine().debug_flags & DEBUG_FLAG_ENABLED; - - while (m_icount > 0) + do { - if (HOLD_BUS) + /*if (HOLD_BUS) { m_icount--; continue; - } + }*/ - //BREAK_PSR; - debugger_instruction_hook(PC); + if (CHECK_DEBUG) + debugger_instruction_hook(PC); - if (m_reset_mode) + if (MODE == MODE_RESET) { reset_step(); } - else if (m_error_mode) + else if (MODE == MODE_ERROR) { error_step(); } - else if (m_execute_mode) + else if (MODE == MODE_EXECUTE) { execute_step(); } - if (debug) + if (CHECK_DEBUG) { for (int i = 0; i < 8; i++) { @@ -3725,7 +3683,45 @@ void mb86901_device::execute_run() } } --m_icount; - } + } while (m_icount >= 0); +} + +//------------------------------------------------- +// execute_run - execute a timeslice's worth of +// opcodes +//------------------------------------------------- + +void mb86901_device::execute_run() +{ + bool debug = machine().debug_flags & DEBUG_FLAG_ENABLED; + + do + { + if (debug) + { + if (m_reset_mode) + run_loop(); + else if (m_error_mode) + run_loop(); + else + run_loop(); + } + else + { + if (m_reset_mode) + run_loop(); + else if (m_error_mode) + run_loop(); + else + run_loop(); + } + + if (m_stashed_icount >= 0) + { + m_icount = m_stashed_icount; + m_stashed_icount = -1; + } + } while (m_icount >= 0); } diff --git a/src/devices/cpu/sparc/sparc.h b/src/devices/cpu/sparc/sparc.h index 41264b6ed2b..1bbcccc44fe 100644 --- a/src/devices/cpu/sparc/sparc.h +++ b/src/devices/cpu/sparc/sparc.h @@ -10,6 +10,7 @@ #pragma once #include "sparcdasm.h" +#include "sparc_intf.h" #define SPARCV8 (1) #define LOG_FCODES (0) @@ -22,28 +23,18 @@ #define MCFG_SPARC_ADD_ASI_DESC(desc) \ downcast(*device).add_asi_desc([](sparc_disassembler *dasm) { dasm->add_asi_desc(desc); }); -class mb86901_device : public cpu_device, protected sparc_disassembler::config +class mb86901_device : public cpu_device, public sparc_mmu_host_interface, protected sparc_disassembler::config { public: mb86901_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - enum - { - AS_COUNT = 32, - - AS_START = 128, - AS_END = AS_START + (AS_COUNT - 1) - }; - - template void set_asi_addrmap(int asi, T &&obj) - { - set_addrmap(asi + AS_START, std::forward(obj)); - } + template void set_mmu(T &&tag) { m_mmu.set_tag(std::forward(tag)); } // device-level overrides virtual void device_start() override; virtual void device_reset() override; virtual void device_stop() override; + virtual void device_resolve_objects() override; // device_execute_interface overrides virtual uint32_t execute_min_cycles() const override; @@ -63,7 +54,7 @@ public: uint8_t get_asi() { return 0; } uint32_t pc() { return m_pc; } - void set_mae() { m_mae = 1; } + void set_mae() override { m_mae = 1; } void add_asi_desc(std::function f) { m_asi_desc_adder = f; } @@ -92,7 +83,7 @@ protected: void execute_mul(uint32_t op); void execute_div(uint32_t op); #endif - void execute_group2(uint32_t op); + inline void execute_group2(uint32_t op); void execute_load(uint32_t op); void execute_store(uint32_t op); @@ -100,7 +91,7 @@ protected: #if SPARCV8 void execute_swap(uint32_t op); #endif - void execute_group3(uint32_t op); + inline void execute_group3(uint32_t op); bool evaluate_condition(uint32_t op); void execute_bicc(uint32_t op); @@ -111,26 +102,33 @@ protected: void complete_instruction_execution(uint32_t op); inline void dispatch_instruction(uint32_t op); void complete_fp_execution(uint32_t /*op*/); - void execute_step(); + inline void execute_step(); void reset_step(); void error_step(); + enum running_mode + { + MODE_RESET, + MODE_ERROR, + MODE_EXECUTE + }; + + template void run_loop(); #if LOG_FCODES void indent(); void disassemble_ss1_fcode(uint32_t r5, uint32_t opcode, uint32_t handler_base, uint32_t entry_point, uint32_t stack); void log_fcodes(); #endif + required_device m_mmu; + // address spaces - std::string m_asi_names[AS_COUNT]; - address_space_config m_asi_config[AS_COUNT]; - memory_access_cache<2, 0, ENDIANNESS_BIG> *m_access_cache[AS_COUNT]; address_space_config m_default_config; // memory access - uint32_t read_sized_word(uint8_t asi, uint32_t address, int size); - void write_sized_word(uint8_t asi, uint32_t address, uint32_t data, int size); + uint32_t read_sized_word(const uint8_t asi, const uint32_t address, const uint32_t mem_mask); + void write_sized_word(const uint8_t asi, const uint32_t address, const uint32_t data, const uint32_t mem_mask); // helpers for the disassembler virtual uint64_t get_reg_r(unsigned index) const override; @@ -209,6 +207,7 @@ protected: bool m_alu_op3_assigned[64]; bool m_ldst_op3_assigned[64]; + bool m_alu_setcc[64]; // register windowing helpers uint32_t* m_regs[32]; @@ -220,14 +219,13 @@ protected: bool m_annul; bool m_hold_bus; int m_icount; - int m_fetch_space; + int m_stashed_icount; + int m_insn_space; + int m_data_space; // debugger helpers uint32_t m_dbgregs[24]; - // address spaces - address_space *m_space[32]; - #if LOG_FCODES uint32_t m_ss1_next_pc; uint32_t m_ss1_next_opcode; diff --git a/src/devices/cpu/sparc/sparc_intf.h b/src/devices/cpu/sparc/sparc_intf.h new file mode 100644 index 00000000000..a203abd92ea --- /dev/null +++ b/src/devices/cpu/sparc/sparc_intf.h @@ -0,0 +1,30 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +/*************************************************************************** + + sparc_intf.h - Sun SPARC MMU interfaces + +***************************************************************************/ + +#ifndef MAME_CPU_SPARC_SPARC_INTF_H +#define MAME_CPU_SPARC_SPARC_INTF_H + +#pragma once + +class sparc_mmu_host_interface +{ +public: + virtual ~sparc_mmu_host_interface() { } + virtual void set_mae() = 0; +}; + +class sparc_mmu_interface +{ +public: + virtual ~sparc_mmu_interface() { } + virtual void set_host(sparc_mmu_host_interface *host) = 0; + virtual uint32_t read_asi(uint8_t asi, uint32_t offset, uint32_t mem_mask) = 0; + virtual void write_asi(uint8_t asi, uint32_t offset, uint32_t data, uint32_t mem_mask) = 0; +}; + +#endif // MAME_CPU_SPARC_SPARC_INTF_H \ No newline at end of file diff --git a/src/devices/cpu/sparc/sparcdefs.h b/src/devices/cpu/sparc/sparcdefs.h index 0ae566ad5a7..050f1aa1f74 100644 --- a/src/devices/cpu/sparc/sparcdefs.h +++ b/src/devices/cpu/sparc/sparcdefs.h @@ -105,7 +105,7 @@ #define SHCNT32 (op & 31) #define SHCNT64 (op & 63) #define IAMODE (op & 0x7) -#define USEIMM ((op >> 13) & 1) +#define USEIMM (op & (1 << 13)) #define USEEXT ((op >> 12) & 1) diff --git a/src/devices/machine/ncr5390.cpp b/src/devices/machine/ncr5390.cpp index 8d9f4b9641b..135bcdb9705 100644 --- a/src/devices/machine/ncr5390.cpp +++ b/src/devices/machine/ncr5390.cpp @@ -33,6 +33,42 @@ void ncr5390_device::map(address_map &map) map(0x9, 0x9).w(FUNC(ncr5390_device::clock_w)); } +READ8_MEMBER(ncr5390_device::read) +{ + switch (offset) + { + case 0: return tcounter_lo_r(space, 0); + case 1: return tcounter_hi_r(space, 0); + case 2: return fifo_r(space, 0); + case 3: return command_r(space, 0); + case 4: return status_r(space, 0); + case 5: return istatus_r(space, 0); + case 6: return seq_step_r(space, 0); + case 7: return fifo_flags_r(space, 0); + case 8: return conf_r(space, 0); + default: return 0; + } +} + +WRITE8_MEMBER(ncr5390_device::write) +{ + switch (offset) + { + case 0: tcount_lo_w(space, 0, data); break; + case 1: tcount_hi_w(space, 0, data); break; + case 2: fifo_w(space, 0, data); break; + case 3: command_w(space, 0, data); break; + case 4: bus_id_w(space, 0, data); break; + case 5: timeout_w(space, 0, data); break; + case 6: sync_period_w(space, 0, data); break; + case 7: sync_offset_w(space, 0, data); break; + case 8: conf_w(space, 0, data); break; + case 9: clock_w(space, 0, data); break; + case 10: test_w(space, 0, data); break; + default: break; + } +} + void ncr53c90a_device::map(address_map &map) { ncr5390_device::map(map); @@ -40,6 +76,20 @@ void ncr53c90a_device::map(address_map &map) map(0xb, 0xb).rw(FUNC(ncr53c90a_device::conf2_r), FUNC(ncr53c90a_device::conf2_w)); } +READ8_MEMBER(ncr53c90a_device::read) +{ + if (offset == 11) + return conf2_r(space, 0); + return ncr5390_device::read(space, offset); +} + +WRITE8_MEMBER(ncr53c90a_device::write) +{ + if (offset == 11) + return conf2_w(space, 0, data); + ncr5390_device::write(space, offset, data); +} + void ncr53c94_device::map(address_map &map) { ncr53c90a_device::map(map); @@ -48,6 +98,23 @@ void ncr53c94_device::map(address_map &map) map(0xf, 0xf).w(FUNC(ncr53c94_device::fifo_align_w)); } +READ8_MEMBER(ncr53c94_device::read) +{ + if (offset == 12) + return conf3_r(space, 0); + return ncr53c90a_device::read(space, offset); +} + +WRITE8_MEMBER(ncr53c94_device::write) +{ + if (offset == 11) + conf3_w(space, 0, data); + else if (offset == 15) + fifo_align_w(space, 0, data); + else + ncr53c90a_device::write(space, offset, data); +} + ncr5390_device::ncr5390_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : nscsi_device(mconfig, type, tag, owner, clock) , tm(nullptr), config(0), status(0), istatus(0), clock_conv(0), sync_offset(0), sync_period(0), bus_id(0) diff --git a/src/devices/machine/ncr5390.h b/src/devices/machine/ncr5390.h index 9a2bed1bc28..d39b352ddb7 100644 --- a/src/devices/machine/ncr5390.h +++ b/src/devices/machine/ncr5390.h @@ -48,6 +48,9 @@ public: DECLARE_WRITE8_MEMBER(test_w); DECLARE_WRITE8_MEMBER(clock_w); + virtual DECLARE_READ8_MEMBER(read); + virtual DECLARE_WRITE8_MEMBER(write); + virtual void scsi_ctrl_changed() override; uint8_t dma_r(); @@ -264,6 +267,9 @@ public: DECLARE_READ8_MEMBER(conf2_r) { return config2; }; DECLARE_WRITE8_MEMBER(conf2_w) { config2 = data; }; + DECLARE_READ8_MEMBER(read) override; + DECLARE_WRITE8_MEMBER(write) override; + protected: ncr53c90a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); @@ -292,6 +298,9 @@ public: DECLARE_WRITE8_MEMBER(conf3_w) { config3 = data; }; DECLARE_WRITE8_MEMBER(fifo_align_w) { fifo_align = data; }; + DECLARE_READ8_MEMBER(read) override; + DECLARE_WRITE8_MEMBER(write) override; + protected: virtual void device_start() override; void reset_soft(); diff --git a/src/devices/machine/sun4c_mmu.cpp b/src/devices/machine/sun4c_mmu.cpp new file mode 100644 index 00000000000..68290f1fac9 --- /dev/null +++ b/src/devices/machine/sun4c_mmu.cpp @@ -0,0 +1,497 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +/*************************************************************************** + + sun4c_mmu.cpp - Sun 4c MMU emulation + +***************************************************************************/ + +#include "emu.h" +#include "sun4c_mmu.h" +#include "cpu/sparc/sparc.h" + +DEFINE_DEVICE_TYPE(SUN4C_MMU, sun4c_mmu_device, "sun4c_mmu", "Sun 4C MMU") + +sun4c_mmu_device::sun4c_mmu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, SUN4C_MMU, tag, owner, clock) + , m_cpu(*this, finder_base::DUMMY_TAG) + , m_ram(*this, finder_base::DUMMY_TAG) + , m_rom(*this, finder_base::DUMMY_TAG) + , m_scc(*this, finder_base::DUMMY_TAG) + , m_host(nullptr) + , m_type1_r(*this) + , m_type1_w(*this) + , m_rom_ptr(nullptr) + , m_ram_ptr(nullptr) + , m_ram_size(0) + , m_ram_size_words(0) + , m_context(0) + , m_context_masked(0) + , m_system_enable(0) + , m_fetch_bootrom(true) + , m_curr_segmap(nullptr) + , m_curr_segmap_masked(nullptr) +{ +} + +void sun4c_mmu_device::device_start() +{ + m_type1_r.resolve_safe(0xffffffff); + m_type1_w.resolve_safe(); + + // allocate timer for system reset + m_reset_timer = timer_alloc(TIMER_RESET); + m_reset_timer->adjust(attotime::never); +} + +void sun4c_mmu_device::device_reset() +{ + m_rom_ptr = (uint32_t *)m_rom->base(); + m_ram_ptr = (uint32_t *)m_ram->pointer(); + m_ram_size = m_ram->size(); + m_ram_size_words = m_ram_size >> 2; + + m_context = 0; + m_context_masked = 0; + m_curr_segmap = m_segmap[0]; + m_curr_segmap_masked = m_segmap_masked[0]; + m_system_enable = 0; + m_fetch_bootrom = true; + + memset(m_buserr, 0, sizeof(uint32_t) * 4); + memset(m_segmap, 0, sizeof(uint8_t) * 16 * 4096); + memset(m_pagemap, 0, sizeof(page_entry_t) * 16384); + memset(m_cachetags, 0, sizeof(uint32_t) * 16384); + memset(m_cachedata, 0, sizeof(uint32_t) * 16384); +} + +void sun4c_mmu_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + if (id == TIMER_RESET) + { + m_reset_timer->adjust(attotime::never); + m_cpu->set_input_line(SPARC_RESET, CLEAR_LINE); + //printf("Clearing reset line\n"); + } +} + +uint32_t sun4c_mmu_device::read_asi(uint8_t asi, uint32_t offset, uint32_t mem_mask) +{ + //logerror("read_asi %d: %08x & %08x\n", asi, offset << 2, mem_mask); + switch (asi) + { + case 2: + return system_r(offset, mem_mask); + case 3: + return segment_map_r(offset, mem_mask); + case 4: + return page_map_r(offset, mem_mask); + case 8: + return insn_data_r(offset, mem_mask); + case 9: + return insn_data_r(offset, mem_mask); + case 10: + return insn_data_r(offset, mem_mask); + case 11: + return insn_data_r(offset, mem_mask); + case 12: + case 13: + case 14: + cache_flush_r(); + return 0; + default: + return ~0; + } +} + +void sun4c_mmu_device::write_asi(uint8_t asi, uint32_t offset, uint32_t data, uint32_t mem_mask) +{ + //logerror("write_asi %d: %08x = %08x & %08x\n", asi, offset << 2, data, mem_mask); + switch (asi) + { + case 2: + system_w(offset, data, mem_mask); + return; + case 3: + segment_map_w(offset, data, mem_mask); + return; + case 4: + page_map_w(offset, data, mem_mask); + return; + case 8: + insn_data_w(offset, data, mem_mask); + return; + case 9: + insn_data_w(offset, data, mem_mask); + return; + case 10: + insn_data_w(offset, data, mem_mask); + return; + case 11: + insn_data_w(offset, data, mem_mask); + return; + case 12: + case 13: + case 14: + cache_flush_w(); + return; + default: + return; + } +} + +uint32_t sun4c_mmu_device::cache_flush_r() +{ + // Do nothing for now + return 0; +} + +void sun4c_mmu_device::cache_flush_w() +{ + // Do nothing for now +} + +uint32_t sun4c_mmu_device::system_r(const uint32_t offset, const uint32_t mem_mask) +{ + //logerror("%s: system_r: %08x & %08x\n", machine().describe_context(), offset << 2, mem_mask); + switch (offset >> 26) + { + case 3: // context reg + if (mem_mask == 0x00ff0000) return m_context<<16; + return m_context<<24; + + case 4: // system enable reg + return m_system_enable<<24; + + case 6: // bus error register + { + //printf("sun4c_mmu: read buserror %08x, PC=%x (mask %08x)\n", 0x60000000 | (offset << 2), m_cpu->pc(), mem_mask); + const uint32_t retval = m_buserr[offset & 0xf]; + m_buserr[offset & 0xf] = 0; // clear on reading + return retval; + } + + case 8: // (d-)cache tags + //logerror("sun4_mmu: read dcache tags @ %x, PC = %x\n", offset, m_cpu->pc()); + return m_cachetags[(offset >> 3) & 0x3fff]; + + case 9: // (d-)cache data + //logerror("sun4c_mmu: read dcache data @ %x, PC = %x\n", offset, m_cpu->pc()); + return m_cachedata[offset & 0x3fff]; + + case 0xf: // UART bypass + //printf("sun4c_mmu: read UART bypass @ %x mask %08x\n", offset<<2, mem_mask); + switch (offset & 3) + { + case 0: if (mem_mask == 0xff000000) return m_scc->cb_r(0)<<24; else return m_scc->db_r(0)<<8; break; + case 1: if (mem_mask == 0xff000000) return m_scc->ca_r(0)<<24; else return m_scc->da_r(0)<<8; break; + } + return 0xffffffff; + + case 0: // IDPROM - SPARCstation-1 does not have an ID prom and a timeout should occur. + default: + logerror("%s: sun4c_mmu: ASI 2 space unhandled read @ %x\n", machine().describe_context(), offset<<2); + return 0; + } +} + +void sun4c_mmu_device::system_w(const uint32_t offset, const uint32_t data, const uint32_t mem_mask) +{ + //logerror("%s: system_w: %08x = %08x & %08x\n", machine().describe_context(), offset << 2, data, mem_mask); + switch (offset >> 26) + { + case 3: // context reg + //printf("%08x to context, mask %08x, offset %x\n", data, mem_mask, offset); + m_context = data >> 24; + m_context_masked = m_context & m_ctx_mask; + m_curr_segmap = m_segmap[m_context_masked]; + m_curr_segmap_masked = m_segmap_masked[m_context_masked]; + return; + + case 4: // system enable reg + { + m_system_enable = data >> 24; + m_fetch_bootrom = !(m_system_enable & ENA_NOTBOOT); + + if (m_system_enable & ENA_RESET) + { + m_reset_timer->adjust(attotime::from_usec(1)); + m_cpu->set_input_line(SPARC_RESET, ASSERT_LINE); + //logerror("%s: Asserting reset line\n", machine().describe_context()); + } + //printf("%08x to system enable, mask %08x\n", data, mem_mask); + if (m_system_enable & ENA_RESET) + { + m_system_enable = 0; + m_cpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); + m_cpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE); + } + return; + } + + case 6: // bus error + //logerror("%08x to bus error @ %x, mask %08x\n", data, offset, mem_mask); + m_buserr[offset & 0xf] = data; + return; + + case 8: // cache tags + //logerror("sun4: %08x to cache tags @ %x, PC = %x\n", data, offset, m_cpu->pc()); + m_cachetags[(offset>>3)&0x3fff] = data & 0x03f8fffc; + return; + + case 9: // cache data + //logerror("sun4c: %08x to cache data @ %x, PC = %x\n", data, offset, m_cpu->pc()); + m_cachedata[offset&0x3fff] = data; + return; + + case 0xf: // UART bypass + //printf("%08x to UART bypass @ %x, mask %08x\n", data, offset<<2, mem_mask); + switch (offset & 3) + { + case 0: if (mem_mask == 0xff000000) m_scc->cb_w(0, data>>24); else m_scc->db_w(0, data>>8); break; + case 1: if (mem_mask == 0xff000000) m_scc->ca_w(0, data>>24); else { m_scc->da_w(0, data>>8); printf("%c", data>>8); } break; + } + return; + + case 0: // IDPROM + default: + logerror("sun4c: ASI 2 space unhandled write %x @ %x (mask %08x, PC=%x, shift %x)\n", data, offset<<2, mem_mask, m_cpu->pc(), offset>>26); + return; + } +} + +uint32_t sun4c_mmu_device::segment_map_r(const uint32_t offset, const uint32_t mem_mask) +{ + //logerror("%s: segment_map_r: %08x & %08x\n", machine().describe_context(), offset << 2, mem_mask); + if (mem_mask == 0xffff0000) + return m_curr_segmap[(offset>>16) & 0xfff]<<16; + else if (mem_mask == 0xff000000) + return m_curr_segmap[(offset>>16) & 0xfff]<<24; + else + logerror("sun4: read segment map w/ unknown mask %08x\n", mem_mask); + return 0; +} + +void sun4c_mmu_device::segment_map_w(const uint32_t offset, const uint32_t data, const uint32_t mem_mask) +{ + //logerror("segment_map_w: %08x = %08x & %08x\n", machine().describe_context(), offset << 2, data, mem_mask); + + uint8_t segdata = 0; + if (mem_mask == 0xffff0000) segdata = (data >> 16) & 0xff; + else if (mem_mask == 0xff000000) segdata = (data >> 24) & 0xff; + else logerror("sun4c: writing segment map with unknown mask %08x, PC=%x\n", mem_mask, m_cpu->pc()); + + const uint32_t seg = (offset>>16) & 0xfff; + m_curr_segmap[seg] = segdata; + m_curr_segmap_masked[seg] = (segdata & m_pmeg_mask) << 6; +} + +uint32_t sun4c_mmu_device::page_map_r(const uint32_t offset, const uint32_t mem_mask) +{ + //logerror("%s: page_map_r: %08x & %08x\n", machine().describe_context(), offset << 2, mem_mask); + const uint32_t page = m_curr_segmap_masked[(offset >> 16) & 0xfff] | ((offset >> 10) & 0x3f); + return m_pagemap[page].to_uint(); +} + +void sun4c_mmu_device::page_map_w(const uint32_t offset, const uint32_t data, const uint32_t mem_mask) +{ + //logerror("%s: page_map_w: %08x = %08x & %08x\n", machine().describe_context(), offset << 2, data, mem_mask); + const uint32_t page = m_curr_segmap_masked[(offset >> 16) & 0xfff] | ((offset >> 10) & 0x3f); + m_pagemap[page].merge_uint(data, mem_mask); + m_page_valid[page] = m_pagemap[page].valid; +} + +void sun4c_mmu_device::type0_timeout_r(const uint32_t offset) +{ + m_buserr[0] = 0x20; // read timeout + m_buserr[1] = 0x04000000 + (offset << 2); + m_host->set_mae(); +} + +void sun4c_mmu_device::type0_timeout_w(const uint32_t offset) +{ + m_buserr[0] = 0x8020; // write timeout + m_buserr[1] = 0x04000000 + (offset << 2); + m_host->set_mae(); +} + +uint32_t sun4c_mmu_device::page_entry_t::to_uint() +{ + return valid | writable | supervisor | uncached | (type << 26) | accessed | modified | (page >> 10); +} + +void sun4c_mmu_device::page_entry_t::merge_uint(uint32_t data, uint32_t mem_mask) +{ + const uint32_t new_value = (to_uint() & ~mem_mask) | (data & mem_mask); + valid = new_value & PM_VALID; + writable = new_value & PM_WRITEMASK; + supervisor = new_value & PM_SYSMASK; + uncached = new_value & PM_CACHE; + type = (new_value & PM_TYPEMASK) >> 26; + accessed = new_value & PM_ACCESSED; + modified = new_value & PM_MODIFIED; + page = (new_value & 0xffff) << 10; +} + +template uint32_t sun4c_mmu_device::insn_data_r(const uint32_t, const uint32_t); +template uint32_t sun4c_mmu_device::insn_data_r(const uint32_t, const uint32_t); +template uint32_t sun4c_mmu_device::insn_data_r(const uint32_t, const uint32_t); +template uint32_t sun4c_mmu_device::insn_data_r(const uint32_t, const uint32_t); + +template +uint32_t sun4c_mmu_device::insn_data_r(const uint32_t offset, const uint32_t mem_mask) +{ + // supervisor program fetches in boot state are special + if (m_fetch_bootrom && MODE == SUPER_INSN) + { + return m_rom_ptr[offset & 0x1ffff]; + } + + // it's translation time + const uint32_t pmeg = m_curr_segmap_masked[(offset >> 16) & 0xfff]; + const uint32_t entry_index = pmeg | ((offset >> 10) & 0x3f); + + if (m_page_valid[entry_index]) + { + page_entry_t &entry = m_pagemap[entry_index]; + entry.accessed = PM_ACCESSED; + + const uint32_t tmp = entry.page | (offset & 0x3ff); + + //printf("sun4c: read translated vaddr %08x to phys %08x type %d, PTE %08x, PC=%x\n", offset<<2, tmp<<2, entry.type, entry.to_uint(), m_cpu->pc()); + + switch (entry.type) + { + case 0: // type 0 space + //return m_type0space->read32(space, tmp, mem_mask); + if (tmp < 0x1000000 >> 2) + { + return m_ram_ptr[tmp]; + } + else if (tmp >= 0x4000000 >> 2 && tmp < 0x10000000 >> 2) + { + type0_timeout_r(tmp); + } + return ~0; + + case 1: // type 1 space + return m_type1_r(tmp, mem_mask); + + default: + //logerror("sun4c_mmu: access to memory type not defined in sun4c\n"); + m_host->set_mae(); + m_buserr[0] = 0x20; + m_buserr[1] = offset << 2; + return 0; + } + } + else + { + if (!machine().side_effects_disabled()) + { + //logerror("sun4c: INVALID PTE entry %d %08x accessed! vaddr=%x PC=%x\n", entry_index, m_pagemap[entry_index].to_uint(), offset <<2, m_cpu->pc()); + m_host->set_mae(); + m_buserr[0] |= 0x80; // invalid PTE + m_buserr[0] &= ~0x8000; // read + m_buserr[1] = offset << 2; + if (mem_mask != ~0 && mem_mask != 0xffff0000 && mem_mask != 0xff000000) + { + if (mem_mask == 0x0000ffff || mem_mask == 0x0000ff00) + { + m_buserr[1] |= 2; + } + else if (mem_mask == 0x00ff0000) + { + m_buserr[1] |= 1; + } + else if (mem_mask == 0x000000ff) + { + m_buserr[1] |= 3; + } + } + } + return 0; + } +} + +template void sun4c_mmu_device::insn_data_w(const uint32_t, const uint32_t, const uint32_t); +template void sun4c_mmu_device::insn_data_w(const uint32_t, const uint32_t, const uint32_t); +template void sun4c_mmu_device::insn_data_w(const uint32_t, const uint32_t, const uint32_t); +template void sun4c_mmu_device::insn_data_w(const uint32_t, const uint32_t, const uint32_t); + +template +void sun4c_mmu_device::insn_data_w(const uint32_t offset, const uint32_t data, const uint32_t mem_mask) +{ + // it's translation time + const uint32_t pmeg = m_curr_segmap_masked[(offset >> 16) & 0xfff]; + const uint32_t entry_index = pmeg | ((offset >> 10) & 0x3f); + + if (m_page_valid[entry_index]) + { + page_entry_t &entry = m_pagemap[entry_index]; + if ((!entry.writable) || (entry.supervisor && MODE != SUPER_DATA && MODE != SUPER_INSN)) + { + //logerror("sun4c: write protect MMU error (PC=%x)\n", m_cpu->pc()); + m_buserr[0] |= 0x8040; // write, protection error + m_buserr[1] = offset << 2; + m_host->set_mae(); + return; + } + + entry.accessed = PM_ACCESSED; + entry.modified = PM_MODIFIED; + + const uint32_t tmp = entry.page | (offset & 0x3ff); + + //printf("sun4: write translated vaddr %08x to phys %08x type %d, PTE %08x, ASI %d, PC=%x\n", offset<<2, tmp<<2, entry.type, entry.to_uint(), asi, m_cpu->pc()); + + switch (entry.type) + { + case 0: // type 0 + if (tmp < 0x1000000 >> 2) + { + COMBINE_DATA((m_ram_ptr + tmp)); + } + else if (tmp >= 0x4000000 >> 2 && tmp < 0x10000000 >> 2) + { + type0_timeout_w(tmp); + } + return; + + case 1: // type 1 + //printf("write device space @ %x = %08x\n", tmp << 2, data); + m_type1_w(tmp, data, mem_mask); + return; + + default: + //logerror("sun4c_mmu: access to memory type not defined\n"); + m_host->set_mae(); + m_buserr[0] = 0x8020; + m_buserr[1] = offset << 2; + return; + } + } + else + { + //logerror("sun4c: INVALID PTE entry %d %08x accessed! data=%08x vaddr=%x PC=%x\n", entry_index, m_pagemap[entry_index].to_uint(), data, offset <<2, m_cpu->pc()); + m_host->set_mae(); + m_buserr[0] |= 0x8080; // write cycle, invalid PTE + m_buserr[1] = offset << 2; + if (mem_mask != ~0 && mem_mask != 0xffff0000 && mem_mask != 0xff000000) + { + if (mem_mask == 0x0000ffff || mem_mask == 0x0000ff00) + { + m_buserr[1] |= 2; + } + else if (mem_mask == 0x00ff0000) + { + m_buserr[1] |= 1; + } + else if (mem_mask == 0x000000ff) + { + m_buserr[1] |= 3; + } + } + } +} + diff --git a/src/devices/machine/sun4c_mmu.h b/src/devices/machine/sun4c_mmu.h new file mode 100644 index 00000000000..0beafb73c29 --- /dev/null +++ b/src/devices/machine/sun4c_mmu.h @@ -0,0 +1,149 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +/*************************************************************************** + + sun4c_mmu.h - Sun 4c MMU emulation + +***************************************************************************/ + +#ifndef MAME_MACHINE_SUN4C_MMU_H +#define MAME_MACHINE_SUN4C_MMU_H + +#pragma once + +#include "cpu/sparc/sparc_intf.h" +#include "machine/ram.h" +#include "machine/z80scc.h" + +class sun4c_mmu_device : public device_t, public sparc_mmu_interface +{ +public: + sun4c_mmu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, uint8_t ctx_mask, uint8_t pmeg_mask) + : sun4c_mmu_device(mconfig, tag, owner, clock) + { + m_ctx_mask = ctx_mask; + m_pmeg_mask = pmeg_mask; + } + + sun4c_mmu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + template void set_cpu(T &&cpu_tag) { m_cpu.set_tag(std::forward(cpu_tag)); } + template void set_ram(T &&ram_tag) { m_ram.set_tag(std::forward(ram_tag)); } + template void set_rom(T &&rom_tag) { m_rom.set_tag(std::forward(rom_tag)); } + template void set_scc(T &&scc_tag) { m_scc.set_tag(std::forward(scc_tag)); } + + enum insn_data_mode + { + USER_INSN, + SUPER_INSN, + USER_DATA, + SUPER_DATA + }; + + template uint32_t insn_data_r(const uint32_t offset, const uint32_t mem_mask); + template void insn_data_w(const uint32_t offset, const uint32_t data, const uint32_t mem_mask); + + auto type1_r() { return m_type1_r.bind(); } + auto type1_w() { return m_type1_w.bind(); } + + // sparc_mmu_device overrides + uint32_t read_asi(uint8_t asi, uint32_t offset, uint32_t mem_mask) override; + void write_asi(uint8_t asi, uint32_t offset, uint32_t data, uint32_t mem_mask) override; + void set_host(sparc_mmu_host_interface *host) override { logerror("Setting host\n"); m_host = host; } + +protected: + static const device_timer_id TIMER_RESET = 0; + + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; + + uint32_t cache_flush_r(); + void cache_flush_w(); + uint32_t system_r(const uint32_t offset, const uint32_t mem_mask); + void system_w(const uint32_t offset, const uint32_t data, const uint32_t mem_mask); + uint32_t segment_map_r(const uint32_t offset, const uint32_t mem_mask); + void segment_map_w(const uint32_t offset, const uint32_t data, const uint32_t mem_mask); + uint32_t page_map_r(const uint32_t offset, const uint32_t mem_mask); + void page_map_w(const uint32_t offset, const uint32_t data, const uint32_t mem_mask); + void type0_timeout_r(const uint32_t offset); + void type0_timeout_w(const uint32_t offset); + + enum + { + // system enable constants + ENA_NOTBOOT = 0x80, + ENA_SDVMA = 0x20, + ENA_CACHE = 0x10, + ENA_RESET = 0x04, + ENA_DIAG = 0x01, + + // page table entry constants + PM_VALID = 0x80000000, // page is valid + PM_WRITEMASK = 0x40000000, // writable? + PM_SYSMASK = 0x20000000, // system use only? + PM_CACHE = 0x10000000, // cachable? + PM_TYPEMASK = 0x0c000000, // type mask + PM_ACCESSED = 0x02000000, // accessed flag + PM_MODIFIED = 0x01000000 // modified flag + }; + + struct page_entry_t + { + uint32_t valid; + uint32_t writable; + uint32_t supervisor; + uint32_t uncached; + uint32_t accessed; + uint32_t modified; + uint32_t page; + uint8_t type; + uint8_t pad[3]; + + uint32_t to_uint(); + void merge_uint(uint32_t data, uint32_t mem_mask); + }; + + required_device m_cpu; + required_device m_ram; + required_memory_region m_rom; + required_device m_scc; + + sparc_mmu_host_interface *m_host; + + // Bus access callbacks + devcb_read32 m_type1_r; + devcb_write32 m_type1_w; + + // Actual SRAM + uint8_t m_segmap[16][4096]; + page_entry_t m_pagemap[16384]; + uint32_t m_cachetags[16384]; + uint32_t m_cachedata[16384]; + + uint32_t *m_rom_ptr; + uint32_t *m_ram_ptr; + uint32_t m_ram_size; + uint32_t m_ram_size_words; + uint32_t m_context; + uint32_t m_context_masked; + uint8_t m_system_enable; + bool m_fetch_bootrom; + uint32_t m_buserr[4]; + + // Pre-computed data for optimization purposes + uint32_t m_segmap_masked[16][4096]; + uint8_t *m_curr_segmap; + uint32_t *m_curr_segmap_masked; + bool m_page_valid[16384]; + + // Internal MAME device state + uint8_t m_ctx_mask; // SS2 is sun4c but has 16 contexts; most have 8 + uint8_t m_pmeg_mask; // SS2 is sun4c but has 16384 PTEs; most have 8192 + emu_timer *m_reset_timer; +}; + + +DECLARE_DEVICE_TYPE(SUN4C_MMU, sun4c_mmu_device) + +#endif // MAME_MACHINE_SUN4C_MMU_H \ No newline at end of file diff --git a/src/devices/machine/z80scc.cpp b/src/devices/machine/z80scc.cpp index dd967d6af27..711d58b8b49 100644 --- a/src/devices/machine/z80scc.cpp +++ b/src/devices/machine/z80scc.cpp @@ -2590,10 +2590,10 @@ void z80scc_channel::m_tx_fifo_rp_step() } } -READ8_MEMBER (z80scc_device::da_r) { return m_chanA->data_read(); } -WRITE8_MEMBER (z80scc_device::da_w) { m_chanA->data_write(data); } -READ8_MEMBER (z80scc_device::db_r) { return m_chanB->data_read(); } -WRITE8_MEMBER (z80scc_device::db_w) { m_chanB->data_write(data); } +uint8_t z80scc_device::da_r(offs_t offset) { return m_chanA->data_read(); } +void z80scc_device::da_w(offs_t offset, uint8_t data) { m_chanA->data_write(data); } +uint8_t z80scc_device::db_r(offs_t offset) { return m_chanB->data_read(); } +void z80scc_device::db_w(offs_t offset, uint8_t data) { m_chanB->data_write(data); } //------------------------------------------------- // data_write - write data register diff --git a/src/devices/machine/z80scc.h b/src/devices/machine/z80scc.h index 259536290da..e2cad9e660b 100644 --- a/src/devices/machine/z80scc.h +++ b/src/devices/machine/z80scc.h @@ -363,15 +363,15 @@ public: DECLARE_WRITE8_MEMBER( ba_cd_inv_w ); /* Definitions moved to z80scc.c for enhancements */ - DECLARE_READ8_MEMBER( da_r ); // { return m_chanA->data_read(); } - DECLARE_WRITE8_MEMBER( da_w ); // { m_chanA->data_write(data); } - DECLARE_READ8_MEMBER( db_r ); // { return m_chanB->data_read(); } - DECLARE_WRITE8_MEMBER( db_w ); // { m_chanB->data_write(data); } - - DECLARE_READ8_MEMBER( ca_r ) { return m_chanA->control_read(); } - DECLARE_WRITE8_MEMBER( ca_w ) { m_chanA->control_write(data); } - DECLARE_READ8_MEMBER( cb_r ) { return m_chanB->control_read(); } - DECLARE_WRITE8_MEMBER( cb_w ) { m_chanB->control_write(data); } + uint8_t da_r(offs_t offset); + void da_w(offs_t offset, uint8_t data); + uint8_t db_r(offs_t offset); + void db_w(offs_t offset, uint8_t data); + + uint8_t ca_r(offs_t offset) { return m_chanA->control_read(); } + void ca_w(offs_t offset, uint8_t data) { m_chanA->control_write(data); } + uint8_t cb_r(offs_t offset) { return m_chanB->control_read(); } + void cb_w(offs_t offset, uint8_t data) { m_chanB->control_write(data); } DECLARE_READ8_MEMBER( zbus_r ); DECLARE_WRITE8_MEMBER( zbus_w ); diff --git a/src/mame/drivers/apple2gs.cpp b/src/mame/drivers/apple2gs.cpp index 237e5b74ebc..237965808c5 100644 --- a/src/mame/drivers/apple2gs.cpp +++ b/src/mame/drivers/apple2gs.cpp @@ -2227,16 +2227,16 @@ READ8_MEMBER(apple2gs_state::c000_r) return m_speed; case 0x38: // SCCBREG - return m_scc->cb_r(space, 0); + return m_scc->cb_r(0); case 0x39: // SCCAREG - return m_scc->ca_r(space, 0); + return m_scc->ca_r(0); case 0x3a: // SCCBDATA - return m_scc->db_r(space, 0); + return m_scc->db_r(0); case 0x3b: // SCCADATA - return m_scc->da_r(space, 0); + return m_scc->da_r(0); case 0x3c: // SOUNDCTL return m_sndglu_ctrl; @@ -2549,19 +2549,19 @@ WRITE8_MEMBER(apple2gs_state::c000_w) break; case 0x38: // SCCBREG - m_scc->cb_w(space, 0, data); + m_scc->cb_w(0, data); break; case 0x39: // SCCAREG - m_scc->ca_w(space, 0, data); + m_scc->ca_w(0, data); break; case 0x3a: // SCCBDATA - m_scc->db_w(space, 0, data); + m_scc->db_w(0, data); break; case 0x3b: // SCCADATA - m_scc->da_w(space, 0, data); + m_scc->da_w(0, data); break; case 0x3c: // SOUNDCTL diff --git a/src/mame/drivers/sun4.cpp b/src/mame/drivers/sun4.cpp index 8127d3258e3..8855cfa70a6 100644 --- a/src/mame/drivers/sun4.cpp +++ b/src/mame/drivers/sun4.cpp @@ -425,6 +425,7 @@ #include "machine/nscsi_hd.h" #include "machine/nvram.h" #include "machine/ram.h" +#include "machine/sun4c_mmu.h" #include "machine/timekpr.h" #include "machine/upd765.h" #include "machine/z80scc.h" @@ -449,23 +450,6 @@ #define FDC_TAG "fdc" #define LANCE_TAG "lance" -#define ENA_NOTBOOT (0x80) -#define ENA_SDVMA (0x20) -#define ENA_CACHE (0x10) -#define ENA_RESET (0x04) -#define ENA_DIAG (0x01) - -// page table entry constants -#define PM_VALID (0x80000000) // page is valid -#define PM_WRITEMASK (0x40000000) // writable? -#define PM_SYSMASK (0x20000000) // system use only? -#define PM_CACHE (0x10000000) // cachable? -#define PM_TYPEMASK (0x0c000000) // type mask -#define PM_ACCESSED (0x02000000) // accessed flag -#define PM_MODIFIED (0x01000000) // modified flag - -#define PAGE_SIZE (0x00000400) - // DMA controller constants #define DMA_DEV_ID (0x80000000) #define DMA_L (0x00008000) // use ILACC @@ -547,6 +531,7 @@ public: sun4_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag) , m_maincpu(*this, "maincpu") + , m_mmu(*this, "mmu") , m_timekpr(*this, TIMEKEEPER_TAG) , m_scc1(*this, SCC1_TAG) , m_scc2(*this, SCC2_TAG) @@ -561,13 +546,13 @@ public: , m_ram(*this, RAM_TAG) , m_rom(*this, "user1") , m_rom_ptr(nullptr) - , m_system_enable(0) { } void sun4c(machine_config &config); void sun4_40(machine_config &config); void sun4_60(machine_config &config); + void sun4_75(machine_config &config); void sun4(machine_config &config); void init_sun4(); @@ -591,6 +576,25 @@ private: SUPER_DATA }; + enum + { + // system enable constants + ENA_NOTBOOT = 0x80, + ENA_SDVMA = 0x20, + ENA_CACHE = 0x10, + ENA_RESET = 0x04, + ENA_DIAG = 0x01, + + // page table entry constants + PM_VALID = 0x80000000, // page is valid + PM_WRITEMASK = 0x40000000, // writable? + PM_SYSMASK = 0x20000000, // system use only? + PM_CACHE = 0x10000000, // cachable? + PM_TYPEMASK = 0x0c000000, // type mask + PM_ACCESSED = 0x02000000, // accessed flag + PM_MODIFIED = 0x01000000 // modified flag + }; + DECLARE_READ32_MEMBER( sun4_cache_flush_r ); DECLARE_WRITE32_MEMBER( sun4_cache_flush_w ); DECLARE_READ32_MEMBER( sun4_system_r ); @@ -602,16 +606,8 @@ private: template DECLARE_READ32_MEMBER( sun4_insn_data_r ); DECLARE_WRITE32_MEMBER( sun4_insn_data_w ); - DECLARE_READ32_MEMBER( sun4c_cache_flush_r ); - DECLARE_WRITE32_MEMBER( sun4c_cache_flush_w ); - DECLARE_READ32_MEMBER( sun4c_system_r ); - DECLARE_WRITE32_MEMBER( sun4c_system_w ); - DECLARE_READ32_MEMBER( sun4c_segment_map_r ); - DECLARE_WRITE32_MEMBER( sun4c_segment_map_w ); - DECLARE_READ32_MEMBER( sun4c_page_map_r ); - DECLARE_WRITE32_MEMBER( sun4c_page_map_w ); - template DECLARE_READ32_MEMBER( sun4c_insn_data_r ); - template DECLARE_WRITE32_MEMBER( sun4c_insn_data_w ); + DECLARE_READ32_MEMBER( sun4c_debugger_r ); + DECLARE_WRITE32_MEMBER( sun4c_debugger_w ); DECLARE_READ32_MEMBER( sun4_mmu_r ); DECLARE_WRITE32_MEMBER( sun4_mmu_w ); @@ -656,14 +652,7 @@ private: void sun4_data_map(address_map &map); void sun4_supervisor_data_map(address_map &map); - void sun4c_system_map(address_map &map); - void sun4c_segment_map(address_map &map); - void sun4c_page_map(address_map &map); - void sun4c_insn_map(address_map &map); - void sun4c_supervisor_insn_map(address_map &map); - void sun4c_data_map(address_map &map); - void sun4c_supervisor_data_map(address_map &map); - void sun4c_cache_flush_map(address_map &map); + void sun4c_debugger_map(address_map &map); void type0space_map(address_map &map); void type1space_map(address_map &map); @@ -677,6 +666,7 @@ private: }; required_device m_maincpu; + required_device m_mmu; required_device m_timekpr; @@ -696,21 +686,6 @@ private: required_device m_ram; required_memory_region m_rom; - uint32_t *m_rom_ptr; - uint32_t m_context; - uint32_t m_context_masked; - uint8_t m_system_enable; - bool m_fetch_bootrom; - uint8_t m_auxio; - uint32_t m_buserr[4]; - uint32_t m_counter[4]; - uint32_t m_dma[4]; - bool m_dma_irq; - bool m_dma_tc_read; - uint32_t m_dma_pack_register; - int m_scsi_irq; - int m_fdc_irq; - struct page_entry_t { uint32_t valid; @@ -723,16 +698,14 @@ private: uint8_t type; uint8_t pad[3]; - template uint32_t to_uint() { - return valid | writable | supervisor | uncached | (type << 26) | accessed | modified | (ARCH_4C ? (page >> 10) : (page >> 11)); + return valid | writable | supervisor | uncached | (type << 26) | accessed | modified | (page >> 11); } - template void merge_uint(uint32_t data, uint32_t mem_mask) { - const uint32_t new_value = (to_uint() & ~mem_mask) | (data & mem_mask); + const uint32_t new_value = (to_uint() & ~mem_mask) | (data & mem_mask); valid = new_value & PM_VALID; writable = new_value & PM_WRITEMASK; supervisor = new_value & PM_SYSMASK; @@ -740,23 +713,39 @@ private: type = (new_value & PM_TYPEMASK) >> 26; accessed = new_value & PM_ACCESSED; modified = new_value & PM_MODIFIED; - page = ARCH_4C ? ((new_value & 0xffff) << 10) : ((new_value & 0x7ffff) << 11); + page = (new_value & 0x7ffff) << 11; } }; - uint32_t *m_ram_ptr; uint8_t m_segmap[16][4096]; - uint8_t *m_curr_segmap; - uint32_t m_segmap_masked[16][4096]; - uint32_t *m_curr_segmap_masked; page_entry_t m_pagemap[16384]; - bool m_page_valid[16384]; - uint32_t m_cachetags[0x4000]; - uint32_t m_cachedata[0x4000]; + uint32_t m_cachetags[16384]; + uint32_t m_cachedata[16384]; + + uint32_t *m_rom_ptr; + uint32_t *m_ram_ptr; uint32_t m_ram_size; uint32_t m_ram_size_words; - uint8_t m_ctx_mask; // SS2 is sun4c but has 16 contexts; most have 8 - uint8_t m_pmeg_mask; // SS2 is sun4c but has 16384 PTEs; most have 8192 + uint32_t m_context; + uint32_t m_context_masked; + uint8_t m_system_enable; + bool m_fetch_bootrom; + uint32_t m_buserr[4]; + + uint32_t m_segmap_masked[16][4096]; + uint8_t *m_curr_segmap; + uint32_t *m_curr_segmap_masked; + bool m_page_valid[16384]; + + uint8_t m_auxio; + uint32_t m_counter[4]; + uint32_t m_dma[4]; + bool m_dma_irq; + bool m_dma_tc_read; + uint32_t m_dma_pack_register; + int m_scsi_irq; + int m_fdc_irq; + uint8_t m_irq_reg; // IRQ control uint8_t m_scc1_int, m_scc2_int; uint8_t m_diag; @@ -776,353 +765,6 @@ private: void fcodes_command(int ref, const std::vector ¶ms); }; -READ32_MEMBER( sun4_state::sun4c_cache_flush_r ) -{ - // Do nothing for now - return 0; -} - -WRITE32_MEMBER( sun4_state::sun4c_cache_flush_w ) -{ - // Do nothing for now -} - -READ32_MEMBER( sun4_state::sun4c_system_r ) -{ - //logerror("%s: system_space_r: %08x & %08x\n", machine().describe_context(), offset << 2, mem_mask); - switch (offset >> 26) - { - case 3: // context reg - if (mem_mask == 0x00ff0000) return m_context<<16; - return m_context<<24; - - case 4: // system enable reg - return m_system_enable<<24; - - case 6: // bus error register - { - //printf("sun4c: read buserror %08x, PC=%x (mask %08x)\n", 0x60000000 | (offset << 2), m_maincpu->pc(), mem_mask); - const uint32_t retval = m_buserr[offset & 0xf]; - m_buserr[offset & 0xf] = 0; // clear on reading - return retval; - } - - case 8: // (d-)cache tags - //logerror("sun4: read dcache tags @ %x, PC = %x\n", offset, m_maincpu->pc()); - return m_cachetags[(offset>>3)&0x3fff]; - - case 9: // (d-)cache data - //logerror("sun4c: read dcache data @ %x, PC = %x\n", offset, m_maincpu->pc()); - return m_cachedata[offset&0x3fff]; - - case 0xf: // UART bypass - //printf("read UART bypass @ %x mask %08x\n", offset<<2, mem_mask); - switch (offset & 3) - { - case 0: if (mem_mask == 0xff000000) return m_scc2->cb_r(space, offset)<<24; else return m_scc2->db_r(space, offset)<<8; break; - case 1: if (mem_mask == 0xff000000) return m_scc2->ca_r(space, offset)<<24; else return m_scc2->da_r(space, offset)<<8; break; - } - return 0xffffffff; - - case 0: // IDPROM - TODO: SPARCstation-1 does not have an ID prom and a timeout should occur. - default: - logerror("sun4c: ASI 2 space unhandled read @ %x (PC=%x)\n", offset<<2, m_maincpu->pc()); - return 0; - } -} - -WRITE32_MEMBER( sun4_state::sun4c_system_w ) -{ - //logerror("%s: system_w: %08x = %08x & %08x\n", machine().describe_context(), offset << 2, data, mem_mask); - switch (offset >> 26) - { - case 3: // context reg - //printf("%08x to context, mask %08x, offset %x\n", data, mem_mask, offset); - m_context = data>>24; - m_context_masked = m_context & m_ctx_mask; - m_curr_segmap = m_segmap[m_context_masked]; - m_curr_segmap_masked = m_segmap_masked[m_context_masked]; - return; - - case 4: // system enable reg - { - const uint8_t old_enable = m_system_enable; - m_system_enable = data>>24; - m_fetch_bootrom = !(m_system_enable & ENA_NOTBOOT); - - if (m_system_enable & ENA_RESET) - { - m_reset_timer->adjust(attotime::from_usec(1)); - m_maincpu->set_input_line(SPARC_RESET, ASSERT_LINE); - logerror("%s: Asserting reset line\n", machine().describe_context()); - } - //printf("%08x to system enable, mask %08x\n", data, mem_mask); - if (m_system_enable & ENA_RESET) - { - m_system_enable = 0; - m_maincpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); - m_maincpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE); - } - - if ((old_enable ^ m_system_enable) & ENA_NOTBOOT) - { - //printf("%c", (m_system_enable & ENA_NOTBOOT) ? 'A' : 'B'); - /*if (m_system_enable & ENA_NOTBOOT) - { - m_maincpu->space(mb86901_device::AS_START + 9).install_readwrite_handler(0x00000000, 0xffffffff, 0, 0, 0 - , read32_delegate(FUNC(sun4_state::sun4c_insn_data_r), this) - , write32_delegate(FUNC(sun4_state::sun4c_insn_data_w), this)); - m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x00000000, 0xffffffff, 0, 0, 0 - , read32_delegate(FUNC(sun4_state::sun4c_insn_data_r), this) - , write32_delegate(FUNC(sun4_state::sun4c_insn_data_w), this)); - } - else - { - m_maincpu->space(mb86901_device::AS_START + 9).install_rom(0x00000000, 0x7ffff, 0xfff80000, m_rom_ptr); - m_maincpu->space(AS_PROGRAM).install_rom(0x00000000, 0x7ffff, 0xfff80000, m_rom_ptr); - }*/ - } - return; - } - - case 6: // bus error - logerror("%08x to bus error @ %x, mask %08x\n", data, offset, mem_mask); - m_buserr[offset & 0xf] = data; - return; - - case 8: // cache tags - //logerror("sun4: %08x to cache tags @ %x, PC = %x\n", data, offset, m_maincpu->pc()); - m_cachetags[(offset>>3)&0x3fff] = data & 0x03f8fffc; - return; - - case 9: // cache data - //logerror("sun4c: %08x to cache data @ %x, PC = %x\n", data, offset, m_maincpu->pc()); - m_cachedata[offset&0x3fff] = data; - return; - - case 0xf: // UART bypass - //printf("%08x to UART bypass @ %x, mask %08x\n", data, offset<<2, mem_mask); - switch (offset & 3) - { - case 0: if (mem_mask == 0xff000000) m_scc2->cb_w(space, offset, data>>24); else m_scc2->db_w(space, offset, data>>8); break; - case 1: if (mem_mask == 0xff000000) m_scc2->ca_w(space, offset, data>>24); else { m_scc2->da_w(space, offset, data>>8); printf("%c", data>>8); } break; - } - return; - - case 0: // IDPROM - default: - logerror("sun4c: ASI 2 space unhandled write %x @ %x (mask %08x, PC=%x, shift %x)\n", data, offset<<2, mem_mask, m_maincpu->pc(), offset>>26); - return; - } -} - -READ32_MEMBER( sun4_state::sun4c_segment_map_r ) -{ - //logerror("%s: segment_map_r: %08x & %08x\n", machine().describe_context(), offset << 2, mem_mask); - //printf("sun4: read segment map @ %x (ctx %d entry %d, mem_mask %08x, PC=%x)\n", offset << 2, m_context_masked, (offset>>16) & 0xfff, mem_mask, m_maincpu->pc()); - if (mem_mask == 0xffff0000) - return m_curr_segmap[(offset>>16) & 0xfff]<<16; - else if (mem_mask == 0xff000000) - return m_curr_segmap[(offset>>16) & 0xfff]<<24; - else - logerror("sun4: read segment map w/ unknown mask %08x\n", mem_mask); - return 0; -} - -WRITE32_MEMBER( sun4_state::sun4c_segment_map_w ) -{ - logerror("segment_map_w: %08x = %08x & %08x\n", machine().describe_context(), offset << 2, data, mem_mask); - uint8_t segdata = 0; - //printf("segment write, mask %08x, PC=%x\n", mem_mask, m_maincpu->pc()); - if (mem_mask == 0xffff0000) segdata = (data >> 16) & 0xff; - else if (mem_mask == 0xff000000) segdata = (data >> 24) & 0xff; - else logerror("sun4c: writing segment map with unknown mask %08x, PC=%x\n", mem_mask, m_maincpu->pc()); - - //printf("sun4c: %08x to segment map @ %x (ctx %d entry %d, mem_mask %08x, PC=%x)\n", segdata, offset << 2, m_context_masked, (offset>>16) & 0xfff, mem_mask, m_maincpu->pc()); - const uint32_t seg = (offset>>16) & 0xfff; - m_curr_segmap[seg] = segdata; - m_curr_segmap_masked[seg] = (segdata & m_pmeg_mask) << 6; -} - -READ32_MEMBER( sun4_state::sun4c_page_map_r ) -{ - //logerror("%s: page_map_r: %08x & %08x\n", machine().describe_context(), offset << 2, mem_mask); - const uint32_t page = m_curr_segmap_masked[(offset >> 16) & 0xfff] | ((offset >> 10) & 0x3f); - //printf("sun4: read page map @ %x (entry %d, seg %d, PMEG %d, mem_mask %08x, PC=%x)\n", offset << 2, page, (offset >> 16) & 0xfff, m_curr_segmap_masked[(offset >> 16) & 0xfff] >> 6, mem_mask, m_maincpu->pc()); - return m_pagemap[page].to_uint(); -} - -WRITE32_MEMBER( sun4_state::sun4c_page_map_w ) -{ - //logerror("%s: page_map_w: %08x = %08x & %08x\n", machine().describe_context(), offset << 2, data, mem_mask); - const uint32_t page = m_curr_segmap_masked[(offset >> 16) & 0xfff] | ((offset >> 10) & 0x3f); - //printf("sun4c: %08x to page map @ %x (entry %d, mem_mask %08x, PC=%x)\n", data, offset << 2, page, mem_mask, m_maincpu->pc()); - m_pagemap[page].merge_uint(data, mem_mask); - m_page_valid[page] = m_pagemap[page].valid; -} - -template -READ32_MEMBER( sun4_state::sun4c_insn_data_r ) -{ - // supervisor program fetches in boot state are special - if (m_fetch_bootrom && MODE == SUPER_INSN) - { - return m_rom_ptr[offset & 0x1ffff]; - } - - // it's translation time - const uint32_t pmeg = m_curr_segmap_masked[(offset >> 16) & 0xfff]; - const uint32_t entry_index = pmeg | ((offset >> 10) & 0x3f); - - if (m_page_valid[entry_index]) - { - page_entry_t &entry = m_pagemap[entry_index]; - entry.accessed = PM_ACCESSED; - - const uint32_t tmp = entry.page | (offset & 0x3ff); - - //printf("sun4: read translated vaddr %08x to phys %08x type %d, PTE %08x, PC=%x\n", offset<<2, tmp<<2, entry.type, entry.to_uint(), m_maincpu->pc()); - - switch (entry.type) - { - case 0: // type 0 space - //return m_type0space->read32(space, tmp, mem_mask); - if (tmp < 0x1000000>>2) - { - return m_ram_ptr[tmp]; - } - else if (tmp >= 0x4000000>>2 && tmp < 0x10000000>>2) - { - timeout_r(space, tmp, mem_mask); - } - return ~0; - - case 1: // type 1 space - // magic EPROM bypass - if ((tmp >= (0x6000000>>2)) && (tmp <= (0x6ffffff>>2))) - { - return m_rom_ptr[offset & 0x1ffff]; - } - //printf("Read type 1 @ VA %08x, phys %08x\n", offset<<2, tmp<<2); - return m_type1space->read32(space, tmp, mem_mask); - - default: - logerror("sun4c: access to memory type not defined in sun4c\n"); - m_maincpu->set_mae(); - m_buserr[0] = 0x20; - m_buserr[1] = offset << 2; - return 0; - } - } - else - { - if (!machine().side_effects_disabled()) - { - logerror("sun4c: INVALID PTE entry %d %08x accessed! vaddr=%x PC=%x\n", entry_index, m_pagemap[entry_index].to_uint(), offset <<2, m_maincpu->pc()); - m_maincpu->set_mae(); - m_buserr[0] |= 0x80; // invalid PTE - m_buserr[0] &= ~0x8000; // read - m_buserr[1] = offset<<2; - if (mem_mask != ~0 && mem_mask != 0xffff0000 && mem_mask != 0xff000000) - { - if (mem_mask == 0x0000ffff || mem_mask == 0x0000ff00) - { - m_buserr[1] |= 2; - } - else if (mem_mask == 0x00ff0000) - { - m_buserr[1] |= 1; - } - else if (mem_mask == 0x000000ff) - { - m_buserr[1] |= 3; - } - } - } - return 0; - } -} - -template -WRITE32_MEMBER( sun4_state::sun4c_insn_data_w ) -{ - // it's translation time - const uint32_t pmeg = m_curr_segmap_masked[(offset >> 16) & 0xfff]; - const uint32_t entry_index = pmeg | ((offset >> 10) & 0x3f); - - if (m_page_valid[entry_index]) - { - page_entry_t &entry = m_pagemap[entry_index]; - if ((!entry.writable) || (entry.supervisor && MODE != SUPER_DATA && MODE != SUPER_INSN)) - { - logerror("sun4c: write protect MMU error (PC=%x)\n", m_maincpu->pc()); - m_buserr[0] |= 0x8040; // write, protection error - m_buserr[1] = offset<<2; - m_maincpu->set_mae(); - return; - } - - entry.accessed = PM_ACCESSED; - entry.modified = PM_MODIFIED; - - const uint32_t tmp = entry.page | (offset & 0x3ff); - - //printf("sun4: write translated vaddr %08x to phys %08x type %d, PTE %08x, ASI %d, PC=%x\n", offset<<2, tmp<<2, entry.type, entry.to_uint(), asi, m_maincpu->pc()); - - switch (entry.type) - { - case 0: // type 0 - //m_type0space->write32(space, tmp, data, mem_mask); - if (tmp < 0x1000000>>2) - { - COMBINE_DATA((m_ram_ptr + tmp)); - } - else if (tmp >= 0x4000000>>2 && tmp < 0x10000000>>2) - { - timeout_w(space, tmp, data, mem_mask); - } - return; - - case 1: // type 1 - //printf("write device space @ %x\n", tmp<<1); - m_type1space->write32(space, tmp, data, mem_mask); - return; - - default: - logerror("sun4c: access to memory type not defined\n"); - m_maincpu->set_mae(); - m_buserr[0] = 0x8020; - m_buserr[1] = offset << 2; - return; - } - } - else - { - logerror("sun4c: INVALID PTE entry %d %08x accessed! data=%08x vaddr=%x PC=%x\n", entry_index, m_pagemap[entry_index].to_uint(), data, offset <<2, m_maincpu->pc()); - m_maincpu->set_mae(); - m_buserr[0] |= 0x8080; // write cycle, invalid PTE - m_buserr[1] = offset<<2; - if (mem_mask != ~0 && mem_mask != 0xffff0000 && mem_mask != 0xff000000) - { - if (mem_mask == 0x0000ffff || mem_mask == 0x0000ff00) - { - m_buserr[1] |= 2; - } - else if (mem_mask == 0x00ff0000) - { - m_buserr[1] |= 1; - } - else if (mem_mask == 0x000000ff) - { - m_buserr[1] |= 3; - } - } - } -} - - -// ----------------------------------------------------------------- - READ32_MEMBER( sun4_state::sun4_system_r ) { switch (offset >> 26) @@ -1150,8 +792,8 @@ READ32_MEMBER( sun4_state::sun4_system_r ) //printf("read UART bypass @ %x mask %08x (PC=%x)\n", offset<<2, mem_mask, m_maincpu->pc()); switch (offset & 3) { - case 0: if (mem_mask == 0xff000000) return m_scc2->cb_r(space, offset)<<24; else return m_scc2->db_r(space, offset)<<8; break; - case 1: if (mem_mask == 0xff000000) return m_scc2->ca_r(space, offset)<<24; else return m_scc2->da_r(space, offset)<<8; break; + case 0: if (mem_mask == 0xff000000) return m_scc2->cb_r(offset)<<24; else return m_scc2->db_r(offset)<<8; break; + case 1: if (mem_mask == 0xff000000) return m_scc2->ca_r(offset)<<24; else return m_scc2->da_r(offset)<<8; break; } return 0xffffffff; @@ -1221,8 +863,8 @@ WRITE32_MEMBER( sun4_state::sun4_system_w ) //printf("%08x to UART bypass @ %x, mask %08x\n", data, offset<<2, mem_mask); switch (offset & 3) { - case 0: if (mem_mask == 0xff000000) m_scc2->cb_w(space, offset, data>>24); else m_scc2->db_w(space, offset, data>>8); break; - case 1: if (mem_mask == 0xff000000) m_scc2->ca_w(space, offset, data>>24); else { m_scc2->da_w(space, offset, data>>8); printf("%c", data>>8); } break; + case 0: if (mem_mask == 0xff000000) m_scc2->cb_w(offset, data>>24); else m_scc2->db_w(offset, data>>8); break; + case 1: if (mem_mask == 0xff000000) m_scc2->ca_w(offset, data>>24); else { m_scc2->da_w(offset, data>>8); printf("%c", data>>8); } break; } return; @@ -1262,17 +904,27 @@ READ32_MEMBER( sun4_state::sun4_page_map_r ) { uint32_t page = m_curr_segmap_masked[(offset >> 16) & 0xfff] | ((offset >> 11) & 0x1f); //printf("sun4: read page map @ %x (entry %d, seg %d, PMEG %d, mem_mask %08x, PC=%x)\n", offset << 2, page, (offset >> 16) & 0xfff, m_segmap[m_context][(offset >> 16) & 0xfff] & m_pmeg_mask, mem_mask, m_maincpu->pc()); - return m_pagemap[page].to_uint(); + return m_pagemap[page].to_uint(); } WRITE32_MEMBER( sun4_state::sun4_page_map_w ) { const uint32_t page = m_curr_segmap_masked[(offset >> 16) & 0xfff] | ((offset >> 11) & 0x1f); //printf("sun4: %08x to page map @ %x (entry %d, mem_mask %08x, PC=%x)\n", data, offset << 2, page, mem_mask, m_maincpu->pc()); - m_pagemap[page].merge_uint(data, mem_mask); + m_pagemap[page].merge_uint(data, mem_mask); m_page_valid[page] = m_pagemap[page].valid; } +READ32_MEMBER( sun4_state::sun4c_debugger_r ) +{ + return m_mmu->insn_data_r(offset, mem_mask); +} + +WRITE32_MEMBER( sun4_state::sun4c_debugger_w ) +{ + m_mmu->insn_data_w(offset, data, mem_mask); +} + template READ32_MEMBER( sun4_state::sun4_insn_data_r ) { @@ -1293,7 +945,7 @@ READ32_MEMBER( sun4_state::sun4_insn_data_r ) const uint32_t tmp = entry.page | (offset & 0x7ff); - //printf("sun4: read translated vaddr %08x to phys %08x type %d, PTE %08x, PC=%x\n", offset<<2, tmp<<2, entry.type, entry.to_uint(), m_maincpu->pc()); + //printf("sun4: read translated vaddr %08x to phys %08x type %d, PTE %08x, PC=%x\n", offset<<2, tmp<<2, entry.type, entry.to_uint(), m_maincpu->pc()); switch (entry.type) { @@ -1318,7 +970,7 @@ READ32_MEMBER( sun4_state::sun4_insn_data_r ) { if (!machine().side_effects_disabled()) { - logerror("sun4: INVALID PTE entry %d %08x accessed! vaddr=%x PC=%x\n", entry_index, m_pagemap[entry_index].to_uint(), offset <<2, m_maincpu->pc()); + logerror("sun4: INVALID PTE entry %d %08x accessed! vaddr=%x PC=%x\n", entry_index, m_pagemap[entry_index].to_uint(), offset <<2, m_maincpu->pc()); m_maincpu->set_mae(); m_buserr[0] |= 0x80; // invalid PTE m_buserr[0] &= ~0x8000; // read @@ -1356,7 +1008,7 @@ WRITE32_MEMBER( sun4_state::sun4_insn_data_w ) uint32_t tmp = entry.page | (offset & 0x7ff); - //printf("sun4: write translated vaddr %08x to phys %08x type %d, PTE %08x, PC=%x\n", offset<<2, tmp<<2, entry.type, entry.to_uint(), m_maincpu->pc()); + //printf("sun4: write translated vaddr %08x to phys %08x type %d, PTE %08x, PC=%x\n", offset<<2, tmp<<2, entry.type, entry.to_uint(), m_maincpu->pc()); switch (entry.type) { @@ -1376,7 +1028,7 @@ WRITE32_MEMBER( sun4_state::sun4_insn_data_w ) } else { - logerror("sun4: INVALID PTE entry %d %08x accessed! data=%08x vaddr=%x PC=%x\n", entry_index, m_pagemap[entry_index].to_uint(), data, offset <<2, m_maincpu->pc()); + logerror("sun4: INVALID PTE entry %d %08x accessed! data=%08x vaddr=%x PC=%x\n", entry_index, m_pagemap[entry_index].to_uint(), data, offset <<2, m_maincpu->pc()); //m_maincpu->trap(SPARC_DATA_ACCESS_EXCEPTION); //m_buserr[0] = 0x8; // invalid PTE //m_buserr[1] = offset<<2; @@ -1404,14 +1056,7 @@ void sun4_state::l2p_command(int ref, const std::vector ¶ms) pmeg = m_curr_segmap_masked[(offset >> 16) & 0xfff]; entry_index = pmeg | ((offset >> 11) & 0x1f); tmp = m_pagemap[entry_index].page | (offset & 0x7ff); - entry_value = m_pagemap[entry_index].to_uint(); - } - else if (m_arch == ARCH_SUN4C) - { - pmeg = m_curr_segmap_masked[(offset >> 16) & 0xfff]; - entry_index = pmeg | ((offset >> 10) & 0x3f); - tmp = m_pagemap[entry_index].page | (offset & 0x3ff); - entry_value = m_pagemap[entry_index].to_uint(); + entry_value = m_pagemap[entry_index].to_uint(); } if (m_page_valid[entry_index]) @@ -1480,44 +1125,9 @@ void sun4_state::sun4_data_map(address_map &map) map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4_insn_data_r), FUNC(sun4_state::sun4_insn_data_w)); } -void sun4_state::sun4c_system_map(address_map &map) -{ - map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4c_system_r), FUNC(sun4_state::sun4c_system_w)); -} - -void sun4_state::sun4c_segment_map(address_map &map) -{ - map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4c_segment_map_r), FUNC(sun4_state::sun4c_segment_map_w)); -} - -void sun4_state::sun4c_page_map(address_map &map) -{ - map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4c_page_map_r), FUNC(sun4_state::sun4c_page_map_w)); -} - -void sun4_state::sun4c_supervisor_insn_map(address_map &map) -{ - map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4c_insn_data_r), FUNC(sun4_state::sun4c_insn_data_w)); -} - -void sun4_state::sun4c_supervisor_data_map(address_map &map) -{ - map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4c_insn_data_r), FUNC(sun4_state::sun4c_insn_data_w)); -} - -void sun4_state::sun4c_insn_map(address_map &map) +void sun4_state::sun4c_debugger_map(address_map &map) { - map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4c_insn_data_r), FUNC(sun4_state::sun4c_insn_data_w)); -} - -void sun4_state::sun4c_data_map(address_map &map) -{ - map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4c_insn_data_r), FUNC(sun4_state::sun4c_insn_data_w)); -} - -void sun4_state::sun4c_cache_flush_map(address_map &map) -{ - map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4c_cache_flush_r), FUNC(sun4_state::sun4c_cache_flush_w)); + map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4c_debugger_r), FUNC(sun4_state::sun4c_debugger_w)); } void sun4_state::type0space_map(address_map &map) @@ -1561,12 +1171,6 @@ INPUT_PORTS_END void sun4_state::machine_reset() { - m_context = 0; - m_context_masked = 0; - m_curr_segmap = m_segmap[0]; - m_curr_segmap_masked = m_segmap_masked[0]; - m_system_enable = 0; - m_fetch_bootrom = true; m_auxio = 0xc0; m_irq_reg = 0; m_scc1_int = m_scc2_int = 0; @@ -1587,12 +1191,6 @@ void sun4_state::machine_start() m_ram_size = m_ram->size(); m_ram_size_words = m_ram_size >> 2; - //m_maincpu->space(mb86901_device::AS_START + 9).install_rom(0x00000, 0x7ffff, 0xfff80000, m_rom_ptr); - //m_maincpu->space(AS_PROGRAM).install_rom(0x00000, 0x7ffff, 0xfff80000, m_rom_ptr); - //memory_space().install_ram(start << 8, (start << 8) | 0x00ffU, m_memory); - - m_type1_cache = m_type1space->space(0).cache<2, 0, ENDIANNESS_BIG>(); // Not currently used - unsure how to make it work - if (machine().debug_flags & DEBUG_FLAG_ENABLED) { using namespace std::placeholders; @@ -1613,21 +1211,6 @@ void sun4_state::machine_start() m_reset_timer->adjust(attotime::never); } -READ32_MEMBER( sun4_state::timeout_r ) -{ - m_buserr[0] = 0x20; // read timeout - m_buserr[1] = 0x04000000 + (offset << 2); - m_maincpu->set_mae(); - return ~0; -} - -WRITE32_MEMBER( sun4_state::timeout_w ) -{ - m_buserr[0] = 0x8020; // write timeout - m_buserr[1] = 0x04000000 + (offset << 2); - m_maincpu->set_mae(); -} - READ32_MEMBER( sun4_state::ram_r ) { return m_ram_ptr[offset]; @@ -1695,6 +1278,21 @@ WRITE32_MEMBER( sun4_state::ram_w ) COMBINE_DATA(&m_ram_ptr[offset]); } +READ32_MEMBER( sun4_state::timeout_r ) +{ + m_buserr[0] = 0x20; // read timeout + m_buserr[1] = 0x04000000 + (offset << 2); + m_maincpu->set_mae(); + return 0; +} + +WRITE32_MEMBER( sun4_state::timeout_w ) +{ + m_buserr[0] = 0x8020; // write timeout + m_buserr[1] = 0x04000000 + (offset << 2); + m_maincpu->set_mae(); +} + READ8_MEMBER( sun4_state::fdc_r ) { if (machine().side_effects_disabled()) @@ -1952,8 +1550,6 @@ void sun4_state::dma_transfer_write() { //logerror("DMAing from device to RAM\n"); - address_space &space = m_maincpu->space(mb86901_device::AS_START+9); - uint8_t pack_cnt = (m_dma[DMA_CTRL] & DMA_PACK_CNT) >> DMA_PACK_CNT_SHIFT; while (m_dma[DMA_CTRL] & DMA_REQ_PEND) { @@ -1970,13 +1566,9 @@ void sun4_state::dma_transfer_write() { //logerror("Writing pack register %08x to %08x\n", m_dma_pack_register, m_dma[DMA_ADDR]); if (m_arch == ARCH_SUN4C) - { - sun4c_insn_data_w(space, m_dma[DMA_ADDR] >> 2, m_dma_pack_register, ~0); - } - else - { - sun4c_insn_data_w(space, m_dma[DMA_ADDR] >> 2, m_dma_pack_register, ~0); - } + m_mmu->insn_data_w(m_dma[DMA_ADDR] >> 2, m_dma_pack_register, ~0); + //else - TODO + //sun4_insn_data_w(space, m_dma[DMA_ADDR] >> 2, m_dma_pack_register, ~0); pack_cnt = 0; m_dma_pack_register = 0; @@ -1992,8 +1584,6 @@ void sun4_state::dma_transfer_read() { //logerror("DMAing from RAM to device\n"); - address_space &space = m_maincpu->space(mb86901_device::AS_START+9); - bool word_cached = false; uint32_t current_word = 0; while (m_dma[DMA_CTRL] & DMA_REQ_PEND) @@ -2001,13 +1591,9 @@ void sun4_state::dma_transfer_read() if (!word_cached) { if (m_arch == ARCH_SUN4C) - { - current_word = sun4c_insn_data_r(space, m_dma[DMA_ADDR] >> 2, ~0); - } - else - { - current_word = sun4c_insn_data_r(space, m_dma[DMA_ADDR] >> 2, ~0); - } + current_word = m_mmu->insn_data_r(m_dma[DMA_ADDR] >> 2, ~0); + //else - TODO + //current_word = sun4_insn_data_r(space, m_dma[DMA_ADDR] >> 2, ~0); word_cached = true; //logerror("Current word: %08x\n", current_word); } @@ -2029,13 +1615,9 @@ void sun4_state::dma_transfer_read() void sun4_state::dma_transfer() { if (m_dma[DMA_CTRL] & DMA_WRITE) - { dma_transfer_write(); - } else - { dma_transfer_read(); - } if (m_dma[DMA_BYTE_COUNT] == 0 && (m_dma[DMA_CTRL] & DMA_EN_CNT)) { @@ -2088,7 +1670,10 @@ WRITE32_MEMBER( sun4_state::dma_w ) const uint32_t bit_index = (3 - i) * 8; //const uint32_t value = m_dma_pack_register & (0xff << bit_index); //logerror("dma_w: draining %02x to RAM address %08x & %08x\n", value >> bit_index, m_dma[DMA_ADDR], 0xff << (24 - bit_index)); - sun4c_insn_data_w(space, m_dma[DMA_ADDR] >> 2, m_dma_pack_register, 0xff << bit_index); + if (m_arch == ARCH_SUN4C) + m_mmu->insn_data_w(m_dma[DMA_ADDR] >> 2, m_dma_pack_register, 0xff << bit_index); + else + sun4_insn_data_w(space, m_dma[DMA_ADDR] >> 2, m_dma_pack_register, 0xff << bit_index); m_dma[DMA_ADDR]++; } m_dma_pack_register = 0; @@ -2159,7 +1744,7 @@ READ32_MEMBER( sun4_state::lance_dma_r ) if (m_arch == ARCH_SUN4) return sun4_insn_data_r(space, offset, mem_mask); else - return sun4c_insn_data_r(space, offset, mem_mask); + return m_mmu->insn_data_r(offset, mem_mask); } WRITE32_MEMBER( sun4_state::lance_dma_w ) @@ -2167,7 +1752,7 @@ WRITE32_MEMBER( sun4_state::lance_dma_w ) if (m_arch == ARCH_SUN4) sun4_insn_data_w(space, offset, data, mem_mask); else - sun4c_insn_data_w(space, offset, data, mem_mask); + m_mmu->insn_data_w(offset, data, mem_mask); } WRITE32_MEMBER( sun4_state::buserr_w ) @@ -2214,15 +1799,19 @@ void sun4_state::ncr53c90a(device_t *device) MACHINE_CONFIG_START(sun4_state::sun4) /* basic machine hardware */ - MCFG_DEVICE_ADD(m_maincpu, MB86901, 16670000) + MCFG_DEVICE_ADD(m_maincpu, MB86901, 16'670'000) MCFG_SPARC_ADD_ASI_DESC(sun4_asi_desc) - m_maincpu->set_asi_addrmap(2, &sun4_state::sun4_system_map); - m_maincpu->set_asi_addrmap(3, &sun4_state::sun4_segment_map); - m_maincpu->set_asi_addrmap(4, &sun4_state::sun4_page_map); - m_maincpu->set_asi_addrmap(8, &sun4_state::sun4_insn_map); - m_maincpu->set_asi_addrmap(9, &sun4_state::sun4_supervisor_insn_map); - m_maincpu->set_asi_addrmap(10, &sun4_state::sun4_data_map); - m_maincpu->set_asi_addrmap(11, &sun4_state::sun4_supervisor_data_map); + m_maincpu->set_addrmap(0, &sun4_state::sun4c_debugger_map); + + // TODO: MMU for sun4 hardware + SUN4C_MMU(config, m_mmu, 25'000'000, 7, 0x7f); + m_mmu->type1_r().set(m_type1space, FUNC(address_map_bank_device::read32)); + m_mmu->type1_w().set(m_type1space, FUNC(address_map_bank_device::write32)); + m_mmu->set_cpu(m_maincpu); + m_mmu->set_ram(m_ram); + m_mmu->set_rom("user1"); + m_mmu->set_scc(m_scc2); + m_maincpu->set_mmu(m_mmu); RAM(config, RAM_TAG).set_default_size("16M").set_default_value(0x00); @@ -2284,19 +1873,18 @@ MACHINE_CONFIG_END MACHINE_CONFIG_START(sun4_state::sun4c) /* basic machine hardware */ - MCFG_DEVICE_ADD(m_maincpu, MB86901, 16670000) + MCFG_DEVICE_ADD(m_maincpu, MB86901, 16'670'000) MCFG_SPARC_ADD_ASI_DESC(sun4c_asi_desc) - m_maincpu->set_addrmap(0, &sun4_state::sun4c_supervisor_insn_map); - m_maincpu->set_asi_addrmap(2, &sun4_state::sun4c_system_map); - m_maincpu->set_asi_addrmap(3, &sun4_state::sun4c_segment_map); - m_maincpu->set_asi_addrmap(4, &sun4_state::sun4c_page_map); - m_maincpu->set_asi_addrmap(8, &sun4_state::sun4c_insn_map); - m_maincpu->set_asi_addrmap(9, &sun4_state::sun4c_supervisor_insn_map); - m_maincpu->set_asi_addrmap(10, &sun4_state::sun4c_data_map); - m_maincpu->set_asi_addrmap(11, &sun4_state::sun4c_supervisor_data_map); - m_maincpu->set_asi_addrmap(12, &sun4_state::sun4c_cache_flush_map); - m_maincpu->set_asi_addrmap(13, &sun4_state::sun4c_cache_flush_map); - m_maincpu->set_asi_addrmap(14, &sun4_state::sun4c_cache_flush_map); + m_maincpu->set_addrmap(0, &sun4_state::sun4c_debugger_map); + + SUN4C_MMU(config, m_mmu, 16'670'000, 7, 0x7f); + m_mmu->type1_r().set(m_type1space, FUNC(address_map_bank_device::read32)); + m_mmu->type1_w().set(m_type1space, FUNC(address_map_bank_device::write32)); + m_mmu->set_cpu(m_maincpu); + m_mmu->set_ram(m_ram); + m_mmu->set_rom("user1"); + m_mmu->set_scc(m_scc2); + m_maincpu->set_mmu(m_mmu); RAM(config, RAM_TAG).set_default_size("16M").set_default_value(0x00); @@ -2355,22 +1943,30 @@ MACHINE_CONFIG_START(sun4_state::sun4c) MCFG_SLOT_OPTION_MACHINE_CONFIG("ncr53c90a", [this] (device_t *device) { ncr53c90a(device); }) MACHINE_CONFIG_END -MACHINE_CONFIG_START(sun4_state::sun4_40) +void sun4_state::sun4_40(machine_config &config) +{ sun4c(config); + m_mmu->set_clock(25'000'000); + m_maincpu->set_clock(25'000'000); + m_maincpu->set_mmu(m_mmu); + m_type1space->set_map(&sun4_state::type1space_sbus_map).set_options(ENDIANNESS_BIG, 32, 32, 0x80000000); // SBus - SBUS(config, m_sbus, 16670000, "maincpu", "type1"); - SBUS_SLOT(config, "slot1", 16'670'000, m_sbus, sbus_cards, nullptr); - SBUS_SLOT(config, "slot2", 16'670'000, m_sbus, sbus_cards, nullptr); - SBUS_SLOT(config, "slot3", 16'670'000, m_sbus, sbus_cards, "bwtwo"); -MACHINE_CONFIG_END + SBUS(config, m_sbus, 25'000'000, "maincpu", "type1"); + SBUS_SLOT(config, "slot1", 25'000'000, m_sbus, sbus_cards, nullptr); + SBUS_SLOT(config, "slot2", 25'000'000, m_sbus, sbus_cards, nullptr); + SBUS_SLOT(config, "slot3", 25'000'000, m_sbus, sbus_cards, "bwtwo"); +} -MACHINE_CONFIG_START(sun4_state::sun4_60) +void sun4_state::sun4_60(machine_config &config) +{ sun4c(config); + m_mmu->set_clock(20'000'000); m_maincpu->set_clock(20'000'000); + m_maincpu->set_mmu(m_mmu); m_type1space->set_map(&sun4_state::type1space_sbus_map).set_options(ENDIANNESS_BIG, 32, 32, 0x80000000); @@ -2379,8 +1975,24 @@ MACHINE_CONFIG_START(sun4_state::sun4_60) SBUS_SLOT(config, "slot1", 20'000'000, m_sbus, sbus_cards, nullptr); SBUS_SLOT(config, "slot2", 20'000'000, m_sbus, sbus_cards, nullptr); SBUS_SLOT(config, "slot3", 20'000'000, m_sbus, sbus_cards, nullptr); -MACHINE_CONFIG_END +} +void sun4_state::sun4_75(machine_config &config) +{ + sun4c(config); + + m_mmu->set_clock(40'000'000); + m_maincpu->set_clock(40'000'000); + m_maincpu->set_mmu(m_mmu); + + m_type1space->set_map(&sun4_state::type1space_sbus_map).set_options(ENDIANNESS_BIG, 32, 32, 0x80000000); + + // SBus + SBUS(config, m_sbus, 20'000'000, "maincpu", "type1"); + SBUS_SLOT(config, "slot1", 20'000'000, m_sbus, sbus_cards, nullptr); + SBUS_SLOT(config, "slot2", 20'000'000, m_sbus, sbus_cards, nullptr); + SBUS_SLOT(config, "slot3", 20'000'000, m_sbus, sbus_cards, nullptr); +} /* Boot PROM @@ -2628,15 +2240,11 @@ void sun4_state::init_sun4() void sun4_state::init_sun4c() { - m_ctx_mask = 0x7; - m_pmeg_mask = 0x7f; m_arch = ARCH_SUN4C; } void sun4_state::init_ss2() { - m_ctx_mask = 0xf; - m_pmeg_mask = 0xff; m_arch = ARCH_SUN4C; } @@ -2654,7 +2262,7 @@ COMP( 1991, sun4_50, sun4_300, 0, sun4c, sun4, sun4_state, init_ss2, COMP( 199?, sun4_20, sun4_300, 0, sun4c, sun4, sun4_state, init_sun4c, "Sun Microsystems", "SPARCstation SLC (Sun 4/20)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) COMP( 1989, sun4_60, sun4_300, 0, sun4_60, sun4, sun4_state, init_sun4c, "Sun Microsystems", "SPARCstation 1 (Sun 4/60)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) COMP( 1990, sun4_65, sun4_300, 0, sun4c, sun4, sun4_state, init_sun4c, "Sun Microsystems", "SPARCstation 1+ (Sun 4/65)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) -COMP( 1990, sun4_75, sun4_300, 0, sun4c, sun4, sun4_state, init_ss2, "Sun Microsystems", "SPARCstation 2 (Sun 4/75)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) +COMP( 1990, sun4_75, sun4_300, 0, sun4_75, sun4, sun4_state, init_ss2, "Sun Microsystems", "SPARCstation 2 (Sun 4/75)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) // sun4m (using the SPARC "reference MMU", probably will go to a separate driver) COMP( 1992, sun_s10, sun4_300, 0, sun4c, sun4, sun4_state, init_sun4c, "Sun Microsystems", "SPARCstation 10 (Sun S10)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) diff --git a/src/mame/machine/iteagle_fpga.cpp b/src/mame/machine/iteagle_fpga.cpp index 7da81e6900b..7ba6967747f 100644 --- a/src/mame/machine/iteagle_fpga.cpp +++ b/src/mame/machine/iteagle_fpga.cpp @@ -293,19 +293,19 @@ READ32_MEMBER( iteagle_fpga_device::fpga_r ) m_cpu->eat_cycles(40); } if (ACCESSING_BITS_0_7) { - result |= m_scc1->cb_r(space, offset) << 0; + result |= m_scc1->cb_r(offset) << 0; if (LOG_SERIAL) m_serial0_1.read_control(1); } if (ACCESSING_BITS_8_15) { - result |= m_scc1->ca_r(space, offset) << 8; + result |= m_scc1->ca_r(offset) << 8; if (LOG_SERIAL) m_serial0_1.read_control(0); } if (ACCESSING_BITS_16_23) { - result |= m_scc1->db_r(space, offset) <<16; + result |= m_scc1->db_r(offset) <<16; if (LOG_SERIAL) m_serial0_1.read_data(1); } if (ACCESSING_BITS_24_31) { - result |= m_scc1->da_r(space, offset) << 24; + result |= m_scc1->da_r(offset) << 24; if (LOG_SERIAL) m_serial0_1.read_data(0); } if (0 && LOG_FPGA && m_prev_reg != offset) @@ -390,20 +390,20 @@ WRITE32_MEMBER( iteagle_fpga_device::fpga_w ) break; case 0x0c/4: if (ACCESSING_BITS_0_7) { - m_scc1->cb_w(space, offset, (data >> 0) & 0xff); + m_scc1->cb_w(offset, (data >> 0) & 0xff); if (LOG_SERIAL) m_serial0_1.write_control((data >> 0) & 0xff, 1); } if (ACCESSING_BITS_8_15) { - m_scc1->ca_w(space, offset, (data >> 8) & 0xff); + m_scc1->ca_w(offset, (data >> 8) & 0xff); if (LOG_SERIAL) m_serial0_1.write_control((data >> 8) & 0xff, 0); } if (ACCESSING_BITS_16_23) { // Convert 0xd to 0xa uint8_t byte = data >> 16; if (byte==0xd) - m_scc1->db_w(space, offset, 0xa); + m_scc1->db_w(offset, 0xa); else - m_scc1->db_w(space, offset, byte); + m_scc1->db_w(offset, byte); if (LOG_SERIAL) { m_serial0_1.write_data((data >> 16) & 0xff, 1); if (m_serial0_1.get_tx_str(1).back() == 0xd) { @@ -414,7 +414,7 @@ WRITE32_MEMBER( iteagle_fpga_device::fpga_w ) } } if (ACCESSING_BITS_24_31) { - m_scc1->da_w(space, offset, (data >> 24) & 0xff); + m_scc1->da_w(offset, (data >> 24) & 0xff); if (LOG_SERIAL) m_serial0_1.write_data((data >> 24) & 0xff, 0); } if (1 && LOG_FPGA) -- cgit v1.2.3 From fad9283ecc0290e07bedc992537db6c8d982ab83 Mon Sep 17 00:00:00 2001 From: AJR Date: Tue, 25 Sep 2018 00:51:14 -0400 Subject: Preliminary emulation of National DP8350 CRT controller family --- scripts/src/video.lua | 12 ++ scripts/target/mame/arcade.lua | 1 + scripts/target/mame/mess.lua | 1 + src/devices/video/dp8350.cpp | 289 +++++++++++++++++++++++++++++++++++++++++ src/devices/video/dp8350.h | 132 +++++++++++++++++++ src/mame/drivers/hazl1420.cpp | 13 +- src/mame/drivers/hp2620.cpp | 15 ++- 7 files changed, 453 insertions(+), 10 deletions(-) create mode 100644 src/devices/video/dp8350.cpp create mode 100644 src/devices/video/dp8350.h (limited to 'scripts/src') diff --git a/scripts/src/video.lua b/scripts/src/video.lua index a5b47457dd3..fa529660ab1 100644 --- a/scripts/src/video.lua +++ b/scripts/src/video.lua @@ -149,6 +149,18 @@ if (VIDEOS["DM9368"]~=null) then } end +-------------------------------------------------- +-- +--@src/devices/video/dp8350.h,VIDEOS["DP8350"] = true +-------------------------------------------------- + +if (VIDEOS["DP8350"]~=null) then + files { + MAME_DIR .. "src/devices/video/dp8350.cpp", + MAME_DIR .. "src/devices/video/dp8350.h", + } +end + -------------------------------------------------- -- --@src/devices/video/ef9340_1.h,VIDEOS["EF9340_1"] = true diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua index 2ff01e51362..5e8d6b36b20 100644 --- a/scripts/target/mame/arcade.lua +++ b/scripts/target/mame/arcade.lua @@ -288,6 +288,7 @@ VIDEOS["CESBLIT"] = true VIDEOS["CRTC_EGA"] = true --VIDEOS["DL1416"] = true VIDEOS["DM9368"] = true +VIDEOS["DP8350"] = true --VIDEOS["EF9340_1"] = true --VIDEOS["EF9345"] = true --VIDEOS["EF9364"] = true diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index 95e8e3fabfc..5500370302f 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -297,6 +297,7 @@ VIDEOS["CRT9212"] = true VIDEOS["CRTC_EGA"] = true VIDEOS["DL1416"] = true VIDEOS["DM9368"] = true +VIDEOS["DP8350"] = true VIDEOS["EF9340_1"] = true VIDEOS["EF9345"] = true VIDEOS["EF9364"] = true diff --git a/src/devices/video/dp8350.cpp b/src/devices/video/dp8350.cpp new file mode 100644 index 00000000000..7fbb1dd5978 --- /dev/null +++ b/src/devices/video/dp8350.cpp @@ -0,0 +1,289 @@ +// license:BSD-3-Clause +// copyright-holders:AJR +/********************************************************************** + + National Semiconductor DP8350 Series CRT Controllers + + These dedicated CRTC devices are “programmable” by specifying a + long list of mask parameters. The number of parameters adjustable + through software is relatively small, there being no dedicated + microprocessor data bus. + + National released the DP8350 and a few other standard versions. + DP8367 appears to have originally been a custom mask variant + ordered by Hewlett-Packard, though it is listed as option “I” in + later datasheets; its parameters have been derived from the + information presented in Manual Part No. 13220-91087. + + Variant Dot rate Monitor type + ------- -------- ------------ + DP8350 10.92 MHz Ball Brothers TV-12, TV-120, etc. + DP8352 7.02 MHz RS-170 compatible + DP8353 17.6256 MHz Motorola M3003 + DP8367 25.7715 MHz HP 13220 + +**********************************************************************/ + +#include "emu.h" +#include "video/dp8350.h" +#include "screen.h" + + +//************************************************************************** +// GLOBAL VARIABLES +//************************************************************************** + +// device type definitions +DEFINE_DEVICE_TYPE(DP8350, dp8350_device, "dp8350", "DP8350 CRTC") +DEFINE_DEVICE_TYPE(DP8367, dp8367_device, "dp8367", "DP8367 CRTC") + + +//************************************************************************** +// DEVICE IMPLEMENTATION +//************************************************************************** + +//------------------------------------------------- +// dp835x_device - constructor +//------------------------------------------------- + +dp835x_device::dp835x_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, + int char_width, int char_height, int chars_per_row, int rows_per_frame, + int vsync_delay_f1, int vsync_width_f1, int vblank_interval_f1, + int vsync_delay_f0, int vsync_width_f0, int vblank_interval_f0, + int chars_per_line, int hsync_delay, int hsync_width, int vblank_stop, + bool cursor_on_all_lines, int lbc_0_width, int hsync_serration, + bool hsync_active, bool vsync_active, bool vblank_active) + : device_t(mconfig, type, tag, owner, clock) + , device_video_interface(mconfig, *this) + , m_char_width(char_width) + , m_char_height(char_height) + , m_chars_per_row(chars_per_row) + , m_rows_per_frame(rows_per_frame) + , m_vsync_delay{vsync_delay_f0, vsync_delay_f1} + , m_vsync_width{vsync_width_f0, vsync_width_f1} + , m_vblank_interval{vblank_interval_f0, vblank_interval_f1} + , m_chars_per_line(chars_per_line) + , m_hsync_delay(hsync_delay) + , m_hsync_width(hsync_width) + , m_vblank_stop(vblank_stop) + , m_cursor_on_all_lines(cursor_on_all_lines) + , m_lbc_0_width(lbc_0_width) + , m_hsync_serration(hsync_serration) + , m_hsync_active(hsync_active) + , m_vsync_active(vsync_active) + , m_vblank_active(vblank_active) + , m_vblank_callback(*this) + , m_60hz_refresh(true) +{ + // many parameters are not used yet + (void)m_vsync_delay; + (void)m_vsync_width; + (void)m_hsync_delay; + (void)m_hsync_width; + (void)m_vblank_stop; + (void)m_cursor_on_all_lines; + (void)m_lbc_0_width; + (void)m_hsync_serration; + (void)m_hsync_active; + (void)m_vsync_active; +} + + +//------------------------------------------------- +// dp8350_device - constructor +//------------------------------------------------- + +dp8350_device::dp8350_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : dp835x_device(mconfig, DP8350, tag, owner, clock, + 7, 10, 80, 24, + 4, 10, 20, + 30, 10, 72, + 100, 0, 4, 1, // HSYNC width given in datasheet as an impossible 43 character times + true, 4, 0, + true, false, true) +{ +} + + +//------------------------------------------------- +// dp8367_device - constructor +//------------------------------------------------- + +dp8367_device::dp8367_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : dp835x_device(mconfig, DP8367, tag, owner, clock, + 9, 15, 80, 26, + 0, 19, 25, + 38, 64, 108, + 115, -16, 7, 1, // value of vblank_stop assumed + true, 5, 0, // values assumed + true, true, true) +{ +} + + +//------------------------------------------------- +// device_config_complete - finalise device +// configuration +//------------------------------------------------- + +void dp835x_device::device_config_complete() +{ + if (has_screen() && screen().refresh_attoseconds() == 0) + { + int dots_per_line = m_char_width * m_chars_per_line; + int dots_per_row = m_char_width * m_chars_per_row; + int lines_per_frame = m_char_height * m_rows_per_frame + m_vblank_interval[m_60hz_refresh ? 1 : 0]; + + if (m_half_shift) + screen().set_raw(clock() * 2, dots_per_line * 2, 0, dots_per_row * 2, lines_per_frame, 0, m_char_height * m_rows_per_frame); + else + screen().set_raw(clock(), dots_per_line, 0, dots_per_row, lines_per_frame, 0, m_char_height * m_rows_per_frame); + } +} + + +//------------------------------------------------- +// device_resolve_objects - resolve objects that +// may be needed for other devices to set +// initial conditions at start time +//------------------------------------------------- + +void dp835x_device::device_resolve_objects() +{ + //m_hsync_callback.resolve_safe(); + //m_vsync_callback.resolve_safe(); + m_vblank_callback.resolve_safe(); +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void dp835x_device::device_start() +{ + screen().register_vblank_callback(vblank_state_delegate(&dp835x_device::screen_vblank, this)); + + save_item(NAME(m_60hz_refresh)); +} + + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void dp835x_device::device_reset() +{ +} + + +//------------------------------------------------- +// device_clock_changed - called when the +// device clock is altered in any way +//------------------------------------------------- + +void dp835x_device::device_clock_changed() +{ + reconfigure_screen(); +} + + +//------------------------------------------------- +// reconfigure_screen - update screen parameters +//------------------------------------------------- + +void dp835x_device::reconfigure_screen() +{ + int dots_per_line = m_char_width * m_chars_per_line; + int dots_per_row = m_char_width * m_chars_per_row; + int lines_per_frame = m_char_height * m_rows_per_frame + m_vblank_interval[m_60hz_refresh ? 1 : 0]; + attoseconds_t refresh = clocks_to_attotime(lines_per_frame * dots_per_line).as_attoseconds(); + + if (m_half_shift) + { + rectangle visarea(0, 2 * dots_per_row - 1, 0, m_char_height * m_rows_per_frame - 1); + screen().configure(2 * dots_per_line, lines_per_frame, visarea, refresh); + } + else + { + rectangle visarea(0, dots_per_row - 1, 0, m_char_height * m_rows_per_frame - 1); + screen().configure(dots_per_line, lines_per_frame, visarea, refresh); + } + + logerror("Frame rate refresh: %.2f Hz (f%d); horizontal rate scan: %.4f kHz; character rate: %.4f MHz; dot rate: %.5f MHz\n", + ATTOSECONDS_TO_HZ(refresh), + m_60hz_refresh ? 1 : 0, + clock() / (dots_per_line * 1000.0), + clock() / (m_char_width * 1000000.0), + clock() / 1000000.0); +} + + +//------------------------------------------------- +// refresh_control - set or configure one of two +// field refresh rates (f1 = 60 Hz, f0 = 50 Hz) +//------------------------------------------------- + +WRITE_LINE_MEMBER(dp835x_device::refresh_control) +{ + if (m_60hz_refresh != bool(state)) + { + m_60hz_refresh = state; + if (started()) + reconfigure_screen(); + } +} + + +//------------------------------------------------- +// register_load - write to one of three CRTC +// address registers +//------------------------------------------------- + +void dp835x_device::register_load(u8 rs, u16 addr) +{ + addr &= 0xfff; + + switch (rs & 3) + { + case 0: + default: + // No Select + break; + + case 1: + // Top-of-Page + logerror("Top-of-Page Register = %03X\n", addr); + break; + + case 2: + // Row Start + logerror("Row Start Register = %03X\n", addr); + break; + + case 3: + // Cursor + logerror("Cursor Register = %03X\n", addr); + break; + } +} + + +//------------------------------------------------- +// vblank_r - report vertical blanking state +//------------------------------------------------- + +READ_LINE_MEMBER(dp835x_device::vblank_r) +{ + return bool(screen().vblank()) == m_vblank_active; +} + + +//------------------------------------------------- +// screen_vblank - vertical blanking handler +//------------------------------------------------- + +void dp835x_device::screen_vblank(screen_device &screen, bool state) +{ + m_vblank_callback(state == m_vblank_active); +} diff --git a/src/devices/video/dp8350.h b/src/devices/video/dp8350.h new file mode 100644 index 00000000000..c14adf05a1b --- /dev/null +++ b/src/devices/video/dp8350.h @@ -0,0 +1,132 @@ +// license:BSD-3-Clause +// copyright-holders:AJR +/********************************************************************** + + National Semiconductor DP8350 Series CRT Controllers + +*********************************************************************** + _____ _____ + RSB 1 |* \__/ | 40 Vcc + VBLANK 2 | | 39 RSA + 50/60 HZ 3 | | 38 RL + VSYNC 4 | | 37 RAE + FULL/HALF 5 | | 36 A0 + LC3 6 | | 35 A1 + LC2 7 | | 34 A2 + LC1 8 | | 33 A3 + LC0 9 | | 32 A4 + CLC 10 | | 31 A5 + CGP 11 | DP835X | 30 A6 + LBRE 12 | | 29 A7 + LRC 13 | | 28 A8 + HSYNC 14 | | 27 A9 + RESET 15 | | 26 A10 + LBC 16 | | 25 A11 + ECLC 17 | | 24 LCGA + LVSR 18 | | 23 DRC + CUR 19 | | 22 X2 + GND 20 |______________| 21 X1 + +**********************************************************************/ + +#ifndef MAME_VIDEO_DP8350_H +#define MAME_VIDEO_DP8350_H + +#pragma once + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> dp835x_device + +class dp835x_device : public device_t, public device_video_interface +{ +public: + // device configuration + auto vblank_callback() { return m_vblank_callback.bind(); } + void set_half_shift(bool half_shift) { m_half_shift = half_shift; } + + // write handlers + DECLARE_WRITE_LINE_MEMBER(refresh_control); + void register_load(u8 rs, u16 addr); + + // read handlers + DECLARE_READ_LINE_MEMBER(vblank_r); + +protected: + // base type constructor + dp835x_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, + int char_width, int char_height, int chars_per_row, int rows_per_frame, + int vsync_delay_f1, int vsync_width_f1, int vblank_interval_f1, + int vsync_delay_f0, int vsync_width_f0, int vblank_interval_f0, + int chars_per_line, int hsync_delay, int hsync_width, int vblank_stop, + bool cursor_on_all_lines, int lbc_0_width, int hsync_serration, + bool hsync_active, bool vsync_active, bool vblank_active); + + // device-specific overrides + virtual void device_config_complete() override; + virtual void device_resolve_objects() override; + virtual void device_start() override; + virtual void device_clock_changed() override; + virtual void device_reset() override; + +private: + // internal helpers + void reconfigure_screen(); + void screen_vblank(screen_device &screen, bool state); + + // mask parameters + const int m_char_width; // character field cell size (width in dots) + const int m_char_height; // character field cell size (height in scan lines) + const int m_chars_per_row; // video characters per row + const int m_rows_per_frame; // video characters per frame + const int m_vsync_delay[2]; // delay from VBLANK start to VSYNC in scan lines + const int m_vsync_width[2]; // vertical sync width in scan lines + const int m_vblank_interval[2]; // scan lines of vertical blanking + const int m_chars_per_line; // character times per scan line + const int m_hsync_delay; // delay from HBLANK start to HSYNC in character times + const int m_hsync_width; // horizontal sync width in character times + const int m_vblank_stop; // VBLANK stop before video start in scan lines + const bool m_cursor_on_all_lines; // true if cursor active on all scan lines of row + const int m_lbc_0_width; // width of LBC 0 output within character time + const int m_hsync_serration; // width of HSYNC pulse serrations within VSYNC (0 if unused) + const bool m_hsync_active; // active level of horizontal sync pulse + const bool m_vsync_active; // active level of vertical sync pulse + const bool m_vblank_active; // active level of vertical blanking pulse + + // misc. configuration + bool m_half_shift; // adjust screen parameters to allow half-dot shifting + + // device callbacks + //devcb_write_line m_hsync_callback; // horizontal sync output (polarity may vary by type) + //devcb_write_line m_vsync_callback; // vertical sync output (polarity may vary by type) + devcb_write_line m_vblank_callback; // vertical blanking output (polarity may vary by type) + + // internal registers and control parameters + bool m_60hz_refresh; // refresh rate selector (true = f1, false = f0) +}; + +// ======================> dp8350_device + +class dp8350_device : public dp835x_device +{ +public: + // device constructor + dp8350_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); +}; + +// ======================> dp8367_device + +class dp8367_device : public dp835x_device +{ +public: + // device constructor + dp8367_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); +}; + +// device type declarations +DECLARE_DEVICE_TYPE(DP8350, dp8350_device) +DECLARE_DEVICE_TYPE(DP8367, dp8367_device) + +#endif // MAME_VIDEO_DP8350_H diff --git a/src/mame/drivers/hazl1420.cpp b/src/mame/drivers/hazl1420.cpp index 28149828d96..f349d9910ec 100644 --- a/src/mame/drivers/hazl1420.cpp +++ b/src/mame/drivers/hazl1420.cpp @@ -12,7 +12,7 @@ #include "machine/bankdev.h" #include "machine/i8243.h" #include "machine/ins8250.h" -//#include "video/dp8350.h" +#include "video/dp8350.h" #include "screen.h" class hazl1420_state : public driver_device @@ -23,7 +23,7 @@ public: , m_maincpu(*this, "maincpu") , m_bankdev(*this, "bankdev") , m_ioexp(*this, "ioexp%u", 0U) - , m_screen(*this, "screen") + , m_crtc(*this, "crtc") { } @@ -46,7 +46,7 @@ private: required_device m_maincpu; required_device m_bankdev; required_device_array m_ioexp; - required_device m_screen; + required_device m_crtc; }; void hazl1420_state::p1_w(u8 data) @@ -57,7 +57,7 @@ void hazl1420_state::p1_w(u8 data) u8 hazl1420_state::p2_r() { - u8 result = m_screen->vblank() ? 0xf0 : 0xe0; + u8 result = 0xe0 | (m_crtc->vblank_r() << 4); result |= m_ioexp[0]->p2_r() & m_ioexp[1]->p2_r(); return result; } @@ -187,12 +187,11 @@ void hazl1420_state::hazl1420(machine_config &config) INS8250(config, "ace", 2'764'800); - //DP8350(config, "crtc", 10.92_MHz_XTAL); + DP8350(config, m_crtc, 10.92_MHz_XTAL).set_screen("screen"); + m_crtc->vblank_callback().set_inputline(m_maincpu, MCS48_INPUT_IRQ); screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); - screen.set_raw(10.92_MHz_XTAL, 700, 0, 560, 260, 0, 240); screen.set_screen_update(FUNC(hazl1420_state::screen_update)); - screen.screen_vblank().set_inputline(m_maincpu, MCS48_INPUT_IRQ); } ROM_START(hazl1420) diff --git a/src/mame/drivers/hp2620.cpp b/src/mame/drivers/hp2620.cpp index 0bf3e11c1c1..f091e0bf0b7 100644 --- a/src/mame/drivers/hp2620.cpp +++ b/src/mame/drivers/hp2620.cpp @@ -10,7 +10,7 @@ Skeleton driver for HP-2620 series display terminals. #include "cpu/z80/z80.h" #include "machine/mos6551.h" #include "machine/nvram.h" -//#include "video/dp8350.h" +#include "video/dp8350.h" #include "screen.h" class hp2620_state : public driver_device @@ -19,6 +19,7 @@ public: hp2620_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag) , m_maincpu(*this, "maincpu") + , m_crtc(*this, "crtc") , m_p_chargen(*this, "chargen") , m_nvram(*this, "nvram") { } @@ -32,6 +33,7 @@ private: DECLARE_WRITE8_MEMBER(keydisp_w); DECLARE_READ8_MEMBER(sysstat_r); DECLARE_WRITE8_MEMBER(modem_w); + void crtc_w(offs_t offset, u8 data); u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); @@ -39,6 +41,7 @@ private: void mem_map(address_map &map); required_device m_maincpu; + required_device m_crtc; required_region_ptr m_p_chargen; required_shared_ptr m_nvram; }; @@ -77,9 +80,15 @@ WRITE8_MEMBER(hp2620_state::modem_w) { } +void hp2620_state::crtc_w(offs_t offset, u8 data) +{ + m_crtc->register_load(data & 3, offset & 0xfff); +} + void hp2620_state::mem_map(address_map &map) { map(0x0000, 0xbfff).rom().region("maincpu", 0); + map(0x8000, 0xbfff).w(FUNC(hp2620_state::crtc_w)); map(0xc000, 0xffff).ram(); } @@ -107,10 +116,10 @@ void hp2620_state::hp2622(machine_config &config) NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0); // 5101 (A7 tied to GND) + battery (+ wait states) screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); - screen.set_raw(25.7715_MHz_XTAL, 1035, 0, 720, 415, 0, 390); // 498 total lines in 50 Hz mode screen.set_screen_update(FUNC(hp2620_state::screen_update)); - //DP8367(config, "crtc", 25.7715_MHz_XTAL).set_screen("screen"); + DP8367(config, m_crtc, 25.7715_MHz_XTAL).set_screen("screen"); + m_crtc->set_half_shift(true); mos6551_device &acia(MOS6551(config, "acia", 0)); // SY6551 acia.set_xtal(25.7715_MHz_XTAL / 14); // 1.84 MHz -- cgit v1.2.3 From 42b42714ed4d5444d50c9b0f0edadceac14abc65 Mon Sep 17 00:00:00 2001 From: Nigel Barnes Date: Tue, 25 Sep 2018 17:09:19 +0100 Subject: bbc_tube_6502/65c102: Added ReCo6502 Tube 1.21 ROM. - Rewritten using bankdev and combined 6502/65c102 variants (nw) --- scripts/src/bus.lua | 2 - src/devices/bus/bbc/tube/tube.cpp | 1 - src/devices/bus/bbc/tube/tube_6502.cpp | 125 +++++++++++++++--------- src/devices/bus/bbc/tube/tube_6502.h | 33 +++++-- src/devices/bus/bbc/tube/tube_65c102.cpp | 157 ------------------------------- src/devices/bus/bbc/tube/tube_65c102.h | 66 ------------- 6 files changed, 108 insertions(+), 276 deletions(-) delete mode 100644 src/devices/bus/bbc/tube/tube_65c102.cpp delete mode 100644 src/devices/bus/bbc/tube/tube_65c102.h (limited to 'scripts/src') diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index 0abd88b3765..e86393a9e8f 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -353,8 +353,6 @@ if (BUSES["BBC_TUBE"]~=null) then MAME_DIR .. "src/devices/bus/bbc/tube/tube.h", MAME_DIR .. "src/devices/bus/bbc/tube/tube_6502.cpp", MAME_DIR .. "src/devices/bus/bbc/tube/tube_6502.h", - MAME_DIR .. "src/devices/bus/bbc/tube/tube_65c102.cpp", - MAME_DIR .. "src/devices/bus/bbc/tube/tube_65c102.h", MAME_DIR .. "src/devices/bus/bbc/tube/tube_80186.cpp", MAME_DIR .. "src/devices/bus/bbc/tube/tube_80186.h", MAME_DIR .. "src/devices/bus/bbc/tube/tube_80286.cpp", diff --git a/src/devices/bus/bbc/tube/tube.cpp b/src/devices/bus/bbc/tube/tube.cpp index c69b57cd45f..521497361ee 100644 --- a/src/devices/bus/bbc/tube/tube.cpp +++ b/src/devices/bus/bbc/tube/tube.cpp @@ -113,7 +113,6 @@ WRITE8_MEMBER(bbc_tube_slot_device::host_w) // slot devices #include "tube_6502.h" -#include "tube_65c102.h" #include "tube_80186.h" #include "tube_80286.h" //#include "tube_a500.h" diff --git a/src/devices/bus/bbc/tube/tube_6502.cpp b/src/devices/bus/bbc/tube/tube_6502.cpp index 3aa3c6a1175..8120ab16812 100644 --- a/src/devices/bus/bbc/tube/tube_6502.cpp +++ b/src/devices/bus/bbc/tube/tube_6502.cpp @@ -6,6 +6,10 @@ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Acorn_ANC01_65022ndproc.html + Acorn ADC06 65C102 Co-processor + + http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Acorn_ADC06_65C102CoPro.html + **********************************************************************/ @@ -18,7 +22,8 @@ // DEVICE DEFINITIONS //************************************************************************** -DEFINE_DEVICE_TYPE(BBC_TUBE_6502, bbc_tube_6502_device, "bbc_tube_6502", "Acorn 6502 2nd Processor") +DEFINE_DEVICE_TYPE(BBC_TUBE_6502, bbc_tube_6502_device, "bbc_tube_6502", "Acorn 6502 2nd Processor") +DEFINE_DEVICE_TYPE(BBC_TUBE_65C102, bbc_tube_65c102_device, "bbc_tube_65c102", "Acorn 65C102 Co-Processor") //------------------------------------------------- @@ -27,7 +32,17 @@ DEFINE_DEVICE_TYPE(BBC_TUBE_6502, bbc_tube_6502_device, "bbc_tube_6502", "Acorn void bbc_tube_6502_device::tube_6502_mem(address_map &map) { - map(0x0000, 0xffff).rw(FUNC(bbc_tube_6502_device::read), FUNC(bbc_tube_6502_device::write)); + map(0x0000, 0xffff).m(m_bankdev, FUNC(address_map_bank_device::amap8)); + map(0xfef0, 0xfeff).rw(FUNC(bbc_tube_6502_device::tube_r), FUNC(bbc_tube_6502_device::tube_w)); +} + +void bbc_tube_6502_device::tube_6502_bank(address_map &map) +{ + // ROM enabled + map(0x00000, 0x0ffff).ram().share("ram"); + map(0x0f000, 0x0ffff).rom().region("rom", 0); + // ROM disabled + map(0x10000, 0x1ffff).ram().share("ram"); } //------------------------------------------------- @@ -36,21 +51,33 @@ void bbc_tube_6502_device::tube_6502_mem(address_map &map) ROM_START( tube_6502 ) ROM_REGION(0x1000, "rom", 0) - ROM_LOAD("6502tube.rom", 0x0000, 0x1000, CRC(98b5fe42) SHA1(338269d03cf6bfa28e09d1651c273ea53394323b)) + ROM_DEFAULT_BIOS("110") + ROM_SYSTEM_BIOS(0, "110", "Tube 1.10") + ROMX_LOAD("6502tube.rom", 0x0000, 0x1000, CRC(98b5fe42) SHA1(338269d03cf6bfa28e09d1651c273ea53394323b), ROM_BIOS(0)) + ROM_SYSTEM_BIOS(1, "121", "Tube 1.21 (ReCo6502)") + ROMX_LOAD("reco6502tube.rom", 0x0000, 0x1000, CRC(75b2a466) SHA1(9ecef24de58a48c3fbe01b12888c3f6a5d24f57f), ROM_BIOS(1)) +ROM_END + +ROM_START( tube_65c102 ) + ROM_REGION(0x1000, "rom", 0) + ROM_DEFAULT_BIOS("110") + ROM_SYSTEM_BIOS(0, "110", "Tube 1.10") + ROMX_LOAD("65c102_boot_110.rom", 0x0000, 0x1000, CRC(ad5b70cc) SHA1(0ac9a1c70e55a79e2c81e102afae1d016af229fa), ROM_BIOS(0)) // 2201,243-02 + ROM_SYSTEM_BIOS(1, "121", "Tube 1.21 (ReCo6502)") + ROMX_LOAD("reco6502tube.rom", 0x0000, 0x1000, CRC(75b2a466) SHA1(9ecef24de58a48c3fbe01b12888c3f6a5d24f57f), ROM_BIOS(1)) ROM_END //------------------------------------------------- // device_add_mconfig - add device configuration //------------------------------------------------- -void bbc_tube_6502_device::device_add_mconfig(machine_config &config) +void bbc_tube_6502_device::add_common_devices(machine_config &config) { - M65C02(config, m_m6502, 12_MHz_XTAL / 4); - m_m6502->set_addrmap(AS_PROGRAM, &bbc_tube_6502_device::tube_6502_mem); + ADDRESS_MAP_BANK(config, m_bankdev).set_map(&bbc_tube_6502_device::tube_6502_bank).set_options(ENDIANNESS_LITTLE, 8, 17, 0x10000); TUBE(config, m_ula); - m_ula->pnmi_handler().set_inputline(m_m6502, M65C02_NMI_LINE); - m_ula->pirq_handler().set_inputline(m_m6502, M65C02_IRQ_LINE); + m_ula->pnmi_handler().set_inputline(m_maincpu, M65C02_NMI_LINE); + m_ula->pirq_handler().set_inputline(m_maincpu, M65C02_IRQ_LINE); /* internal ram */ RAM(config, m_ram).set_default_size("64K").set_default_value(0); @@ -60,6 +87,22 @@ void bbc_tube_6502_device::device_add_mconfig(machine_config &config) SOFTWARE_LIST(config, "flop_ls_65c102").set_original("bbc_flop_65c102"); } +void bbc_tube_6502_device::device_add_mconfig(machine_config &config) +{ + M65C02(config, m_maincpu, 12_MHz_XTAL / 4); + m_maincpu->set_addrmap(AS_PROGRAM, &bbc_tube_6502_device::tube_6502_mem); + + add_common_devices(config); +} + +void bbc_tube_65c102_device::device_add_mconfig(machine_config &config) +{ + M65C02(config, m_maincpu, 16_MHz_XTAL / 4); + m_maincpu->set_addrmap(AS_PROGRAM, &bbc_tube_65c102_device::tube_6502_mem); + + add_common_devices(config); +} + //------------------------------------------------- // rom_region - device-specific ROM region //------------------------------------------------- @@ -69,6 +112,11 @@ const tiny_rom_entry *bbc_tube_6502_device::device_rom_region() const return ROM_NAME( tube_6502 ); } +const tiny_rom_entry *bbc_tube_65c102_device::device_rom_region() const +{ + return ROM_NAME( tube_65c102 ); +} + //************************************************************************** // LIVE DEVICE //************************************************************************** @@ -77,14 +125,24 @@ const tiny_rom_entry *bbc_tube_6502_device::device_rom_region() const // bbc_tube_6502_device - constructor //------------------------------------------------- +bbc_tube_6502_device::bbc_tube_6502_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, type, tag, owner, clock) + , device_bbc_tube_interface(mconfig, *this) + , m_maincpu(*this, "maincpu") + , m_bankdev(*this, "bankdev") + , m_ula(*this, "ula") + , m_ram(*this, "ram") + , m_rom(*this, "rom") +{ +} + bbc_tube_6502_device::bbc_tube_6502_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, BBC_TUBE_6502, tag, owner, clock), - device_bbc_tube_interface(mconfig, *this), - m_m6502(*this, "m6502"), - m_ula(*this, "ula"), - m_ram(*this, "ram"), - m_rom(*this, "rom"), - m_rom_enabled(true) + : bbc_tube_6502_device(mconfig, BBC_TUBE_6502, tag, owner, clock) +{ +} + +bbc_tube_65c102_device::bbc_tube_65c102_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : bbc_tube_6502_device(mconfig, BBC_TUBE_65C102, tag, owner, clock) { } @@ -94,7 +152,6 @@ bbc_tube_6502_device::bbc_tube_6502_device(const machine_config &mconfig, const void bbc_tube_6502_device::device_start() { - m_slot = dynamic_cast(owner()); } //------------------------------------------------- @@ -103,9 +160,7 @@ void bbc_tube_6502_device::device_start() void bbc_tube_6502_device::device_reset() { - m_ula->reset(); - - m_rom_enabled = true; + m_bankdev->set_bank(0); } @@ -124,34 +179,16 @@ WRITE8_MEMBER(bbc_tube_6502_device::host_w) } -READ8_MEMBER(bbc_tube_6502_device::read) +READ8_MEMBER(bbc_tube_6502_device::tube_r) { - uint8_t data; + // Disable ROM on first access + if (!machine().side_effects_disabled()) + m_bankdev->set_bank(1); - if (offset >= 0xfef0 && offset <= 0xfeff) - { - if (!machine().side_effects_disabled()) m_rom_enabled = false; - data = m_ula->parasite_r(space, offset); - } - else if (m_rom_enabled && (offset >= 0xf000)) - { - data = m_rom->base()[offset & 0xfff]; - } - else - { - data = m_ram->pointer()[offset]; - } - return data; + return m_ula->parasite_r(space, offset); } -WRITE8_MEMBER(bbc_tube_6502_device::write) +WRITE8_MEMBER(bbc_tube_6502_device::tube_w) { - if (offset >= 0xfef0 && offset <= 0xfeff) - { - m_ula->parasite_w(space, offset, data); - } - else - { - m_ram->pointer()[offset] = data; - } + m_ula->parasite_w(space, offset, data); } diff --git a/src/devices/bus/bbc/tube/tube_6502.h b/src/devices/bus/bbc/tube/tube_6502.h index 67d14bd539f..244eb9f2105 100644 --- a/src/devices/bus/bbc/tube/tube_6502.h +++ b/src/devices/bus/bbc/tube/tube_6502.h @@ -6,6 +6,10 @@ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Acorn_ANC01_65022ndproc.html + Acorn ADC06 65C102 Co-processor + + http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Acorn_ADC06_65C102CoPro.html + **********************************************************************/ @@ -14,6 +18,7 @@ #include "tube.h" #include "cpu/m6502/m65c02.h" +#include "machine/bankdev.h" #include "machine/ram.h" #include "machine/tube.h" @@ -32,6 +37,8 @@ public: bbc_tube_6502_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); protected: + bbc_tube_6502_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + // device-level overrides virtual void device_start() override; virtual void device_reset() override; @@ -40,26 +47,40 @@ protected: virtual void device_add_mconfig(machine_config &config) override; virtual const tiny_rom_entry *device_rom_region() const override; + void tube_6502_bank(address_map &map); + void tube_6502_mem(address_map &map); + + void add_common_devices(machine_config &config); + virtual DECLARE_READ8_MEMBER( host_r ) override; virtual DECLARE_WRITE8_MEMBER( host_w ) override; -private: - required_device m_m6502; + virtual DECLARE_READ8_MEMBER( tube_r ); + virtual DECLARE_WRITE8_MEMBER( tube_w ); + + required_device m_maincpu; + required_device m_bankdev; required_device m_ula; required_device m_ram; required_memory_region m_rom; +}; - bool m_rom_enabled; - DECLARE_READ8_MEMBER( read ); - DECLARE_WRITE8_MEMBER( write ); +class bbc_tube_65c102_device : public bbc_tube_6502_device +{ +public: + bbc_tube_65c102_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - void tube_6502_mem(address_map &map); +protected: + // optional information overrides + virtual void device_add_mconfig(machine_config &config) override; + virtual const tiny_rom_entry *device_rom_region() const override; }; // device type definition DECLARE_DEVICE_TYPE(BBC_TUBE_6502, bbc_tube_6502_device) +DECLARE_DEVICE_TYPE(BBC_TUBE_65C102, bbc_tube_65c102_device) #endif /* MAME_BUS_BBC_TUBE_6502_H */ diff --git a/src/devices/bus/bbc/tube/tube_65c102.cpp b/src/devices/bus/bbc/tube/tube_65c102.cpp deleted file mode 100644 index 1ef92732526..00000000000 --- a/src/devices/bus/bbc/tube/tube_65c102.cpp +++ /dev/null @@ -1,157 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Nigel Barnes -/********************************************************************** - - Acorn ADC06 65C102 Co-processor - - http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Acorn_ADC06_65C102CoPro.html - -**********************************************************************/ - - -#include "emu.h" -#include "tube_65c102.h" -#include "softlist_dev.h" - - -//************************************************************************** -// DEVICE DEFINITIONS -//************************************************************************** - -DEFINE_DEVICE_TYPE(BBC_TUBE_65C102, bbc_tube_65c102_device, "bbc_tube_65c102", "Acorn 65C102 Co-Processor") - - -//------------------------------------------------- -// ADDRESS_MAP( tube_6502_mem ) -//------------------------------------------------- - -void bbc_tube_65c102_device::tube_6502_mem(address_map &map) -{ - map(0x0000, 0xffff).rw(FUNC(bbc_tube_65c102_device::read), FUNC(bbc_tube_65c102_device::write)); -} - -//------------------------------------------------- -// ROM( tube_65c102 ) -//------------------------------------------------- - -ROM_START( tube_65c102 ) - ROM_REGION(0x1000, "rom", 0) - ROM_LOAD("65c102_boot_110.rom", 0x0000, 0x1000, CRC(ad5b70cc) SHA1(0ac9a1c70e55a79e2c81e102afae1d016af229fa)) // 2201,243-02 -ROM_END - -//------------------------------------------------- -// device_add_mconfig - add device configuration -//------------------------------------------------- - -void bbc_tube_65c102_device::device_add_mconfig(machine_config &config) -{ - M65C02(config, m_maincpu, 16_MHz_XTAL / 4); - m_maincpu->set_addrmap(AS_PROGRAM, &bbc_tube_65c102_device::tube_6502_mem); - - TUBE(config, m_ula); - m_ula->pnmi_handler().set_inputline(m_maincpu, M65C02_NMI_LINE); - m_ula->pirq_handler().set_inputline(m_maincpu, M65C02_IRQ_LINE); - - /* internal ram */ - RAM(config, m_ram).set_default_size("64K").set_default_value(0); - - /* software lists */ - SOFTWARE_LIST(config, "flop_ls_6502").set_original("bbc_flop_6502"); - SOFTWARE_LIST(config, "flop_ls_65c102").set_original("bbc_flop_65c102"); -} - -//------------------------------------------------- -// rom_region - device-specific ROM region -//------------------------------------------------- - -const tiny_rom_entry *bbc_tube_65c102_device::device_rom_region() const -{ - return ROM_NAME( tube_65c102 ); -} - -//************************************************************************** -// LIVE DEVICE -//************************************************************************** - -//------------------------------------------------- -// bbc_tube_65c102_device - constructor -//------------------------------------------------- - -bbc_tube_65c102_device::bbc_tube_65c102_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, BBC_TUBE_65C102, tag, owner, clock), - device_bbc_tube_interface(mconfig, *this), - m_maincpu(*this, "maincpu"), - m_ula(*this, "ula"), - m_ram(*this, "ram"), - m_rom(*this, "rom"), - m_rom_enabled(true) -{ -} - -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -void bbc_tube_65c102_device::device_start() -{ - m_slot = dynamic_cast(owner()); -} - -//------------------------------------------------- -// device_reset - device-specific reset -//------------------------------------------------- - -void bbc_tube_65c102_device::device_reset() -{ - m_ula->reset(); - - m_rom_enabled = true; -} - - -//************************************************************************** -// IMPLEMENTATION -//************************************************************************** - -READ8_MEMBER(bbc_tube_65c102_device::host_r) -{ - return m_ula->host_r(space, offset); -} - -WRITE8_MEMBER(bbc_tube_65c102_device::host_w) -{ - m_ula->host_w(space, offset, data); -} - - -READ8_MEMBER(bbc_tube_65c102_device::read) -{ - uint8_t data; - - if ((offset >= 0xfef0) && (offset <= 0xfeff)) - { - if (!machine().side_effects_disabled()) m_rom_enabled = false; - data = m_ula->parasite_r(space, offset); - } - else if (m_rom_enabled && (offset >= 0xf000)) - { - data = m_rom->base()[offset & 0xfff]; - } - else - { - data = m_ram->pointer()[offset]; - } - return data; -} - -WRITE8_MEMBER(bbc_tube_65c102_device::write) -{ - if ((offset >= 0xfef0) && (offset <= 0xfeff)) - { - m_ula->parasite_w(space, offset, data); - } - else - { - m_ram->pointer()[offset] = data; - } -} diff --git a/src/devices/bus/bbc/tube/tube_65c102.h b/src/devices/bus/bbc/tube/tube_65c102.h deleted file mode 100644 index 1ba891739d1..00000000000 --- a/src/devices/bus/bbc/tube/tube_65c102.h +++ /dev/null @@ -1,66 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Nigel Barnes -/********************************************************************** - - Acorn ADC06 65C102 Co-processor - - http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Acorn_ADC06_65C102CoPro.html - -**********************************************************************/ - - -#ifndef MAME_BUS_BBC_TUBE_65C102_H -#define MAME_BUS_BBC_TUBE_65C102_H - -#include "tube.h" -#include "cpu/m6502/m65c02.h" -#include "machine/ram.h" -#include "machine/tube.h" - -//************************************************************************** -// TYPE DEFINITIONS -//************************************************************************** - -// ======================> bbc_tube_65c102_device - -class bbc_tube_65c102_device : - public device_t, - public device_bbc_tube_interface -{ -public: - // construction/destruction - bbc_tube_65c102_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - -protected: - // device-level overrides - virtual void device_start() override; - virtual void device_reset() override; - - // optional information overrides - virtual void device_add_mconfig(machine_config &config) override; - virtual const tiny_rom_entry *device_rom_region() const override; - - virtual DECLARE_READ8_MEMBER( host_r ) override; - virtual DECLARE_WRITE8_MEMBER( host_w ) override; - -private: - required_device m_maincpu; - required_device m_ula; - required_device m_ram; - required_memory_region m_rom; - - bool m_rom_enabled; - - DECLARE_READ8_MEMBER( read ); - DECLARE_WRITE8_MEMBER( write ); - - void tube_6502_mem(address_map &map); -}; - - - -// device type definition -DECLARE_DEVICE_TYPE(BBC_TUBE_65C102, bbc_tube_65c102_device) - - -#endif /* MAME_BUS_BBC_TUBE_65C102_H */ -- cgit v1.2.3 From b159118e220399c4fba32b9bd9a4f11ccd913f68 Mon Sep 17 00:00:00 2001 From: mooglyguy Date: Sat, 6 Oct 2018 20:44:52 +0200 Subject: vii: Device-ified the SPG2xx SoC. [Ryan Holtz] --- scripts/src/machine.lua | 12 + scripts/target/mame/arcade.lua | 1 + scripts/target/mame/mess.lua | 1 + src/devices/cpu/unsp/unsp.cpp | 64 +- src/devices/cpu/unsp/unsp.h | 15 +- src/devices/cpu/unsp/unspdasm.cpp | 14 +- src/devices/cpu/unsp/unspdasm.h | 11 +- src/devices/machine/spg2xx.cpp | 948 +++++++++++++++++++++++++++++ src/devices/machine/spg2xx.h | 151 +++++ src/mame/drivers/vii.cpp | 1216 ++++--------------------------------- 10 files changed, 1289 insertions(+), 1144 deletions(-) create mode 100644 src/devices/machine/spg2xx.cpp create mode 100644 src/devices/machine/spg2xx.h (limited to 'scripts/src') diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua index b161f1ddbcf..32f12d96b0b 100644 --- a/scripts/src/machine.lua +++ b/scripts/src/machine.lua @@ -2601,6 +2601,18 @@ if (MACHINES["SEGA_SCU"]~=null) then } end +--------------------------------------------------- +-- +--@src/devices/machine/spg2xx.h,MACHINES["SPG2XX"] = true +--------------------------------------------------- + +if (MACHINES["SPG2XX"]~=null) then + files { + MAME_DIR .. "src/devices/machine/spg2xx.cpp", + MAME_DIR .. "src/devices/machine/spg2xx.h", + } +end + --------------------------------------------------- -- --@src/devices/machine/stvcd.h,MACHINES["STVCD"] = true diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua index 5e8d6b36b20..80dcca56354 100644 --- a/scripts/target/mame/arcade.lua +++ b/scripts/target/mame/arcade.lua @@ -574,6 +574,7 @@ MACHINES["SERFLASH"] = true MACHINES["SMC91C9X"] = true MACHINES["SEGA_SCU"] = true MACHINES["SMPC"] = true +--MACHINES["SPG2XX"] = true MACHINES["STVCD"] = true --MACHINES["SUN4C_MMU"] = true MACHINES["TC0091LVC"] = true diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index dea849b592a..ccc964417d6 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -576,6 +576,7 @@ MACHINES["SMC91C9X"] = true MACHINES["SMIOC"] = true MACHINES["SEGA_SCU"] = true MACHINES["SMPC"] = true +MACHINES["SPG2XX"] = true MACHINES["STVCD"] = true MACHINES["SUN4C_MMU"] = true MACHINES["TC0091LVC"] = true diff --git a/src/devices/cpu/unsp/unsp.cpp b/src/devices/cpu/unsp/unsp.cpp index 45bd343cd8c..966fc70fbc4 100644 --- a/src/devices/cpu/unsp/unsp.cpp +++ b/src/devices/cpu/unsp/unsp.cpp @@ -102,24 +102,47 @@ void unsp_device::device_start() m_program = &space(AS_PROGRAM); - state_add( UNSP_SP, "SP", UNSP_REG(SP)).formatstr("%04X"); - state_add( UNSP_R1, "R1", UNSP_REG(R1)).formatstr("%04X"); - state_add( UNSP_R2, "R2", UNSP_REG(R2)).formatstr("%04X"); - state_add( UNSP_R3, "R3", UNSP_REG(R3)).formatstr("%04X"); - state_add( UNSP_R4, "R4", UNSP_REG(R4)).formatstr("%04X"); - state_add( UNSP_BP, "BP", UNSP_REG(BP)).formatstr("%04X"); - state_add( UNSP_SR, "SR", UNSP_REG(SR)).formatstr("%04X"); - state_add( UNSP_PC, "PC", m_debugger_temp).callimport().callexport().formatstr("%06X"); - state_add( UNSP_IRQ_EN, "IRQE", m_enable_irq).formatstr("%1u"); - state_add( UNSP_FIQ_EN, "FIQE", m_enable_fiq).formatstr("%1u"); - state_add( UNSP_IRQ, "IRQ", m_irq).formatstr("%1u"); - state_add( UNSP_FIQ, "FIQ", m_fiq).formatstr("%1u"); - state_add( UNSP_SB, "SB", m_sb).formatstr("%1u"); + state_add(STATE_GENFLAGS, "GENFLAGS", UNSP_REG(SR)).callimport().callexport().formatstr("%4s").noshow(); + state_add(UNSP_SP, "SP", UNSP_REG(SP)).formatstr("%04X"); + state_add(UNSP_R1, "R1", UNSP_REG(R1)).formatstr("%04X"); + state_add(UNSP_R2, "R2", UNSP_REG(R2)).formatstr("%04X"); + state_add(UNSP_R3, "R3", UNSP_REG(R3)).formatstr("%04X"); + state_add(UNSP_R4, "R4", UNSP_REG(R4)).formatstr("%04X"); + state_add(UNSP_BP, "BP", UNSP_REG(BP)).formatstr("%04X"); + state_add(UNSP_SR, "SR", UNSP_REG(SR)).formatstr("%04X"); + state_add(UNSP_PC, "PC", m_debugger_temp).callimport().callexport().formatstr("%06X"); + state_add(UNSP_IRQ_EN, "IRQE", m_enable_irq).formatstr("%1u"); + state_add(UNSP_FIQ_EN, "FIQE", m_enable_fiq).formatstr("%1u"); + state_add(UNSP_IRQ, "IRQ", m_irq).formatstr("%1u"); + state_add(UNSP_FIQ, "FIQ", m_fiq).formatstr("%1u"); + state_add(UNSP_SB, "SB", m_sb).formatstr("%1u"); state_add(STATE_GENPC, "GENPC", m_debugger_temp).callexport().noshow(); state_add(STATE_GENPCBASE, "CURPC", m_debugger_temp).callexport().noshow(); set_icountptr(m_icount); + + save_item(NAME(m_r)); + save_item(NAME(m_enable_irq)); + save_item(NAME(m_enable_fiq)); + save_item(NAME(m_irq)); + save_item(NAME(m_fiq)); + save_item(NAME(m_curirq)); + save_item(NAME(m_sirq)); + save_item(NAME(m_sb)); + save_item(NAME(m_saved_sb)); +} + +void unsp_device::state_string_export(const device_state_entry &entry, std::string &str) const +{ + switch (entry.index()) + { + case STATE_GENFLAGS: + { + const uint16_t sr = UNSP_REG(SR); + str = string_format("%c%c%c%c", (sr & UNSP_N) ? 'N' : ' ', (sr & UNSP_Z) ? 'Z' : ' ', (sr & UNSP_S) ? 'S' : ' ', (sr & UNSP_C) ? 'C' : ' '); + } + } } void unsp_device::state_export(const device_state_entry &entry) @@ -197,8 +220,11 @@ uint16_t unsp_device::pop(uint16_t *reg) void unsp_device::trigger_fiq() { - if (!m_enable_fiq || m_fiq) + if (!m_enable_fiq || m_fiq || m_irq) + { + logerror("FIQs are disabled or we're already in an FIQ/IRQ, bailing\n"); return; + } m_fiq = true; @@ -213,8 +239,11 @@ void unsp_device::trigger_fiq() void unsp_device::trigger_irq(int line) { - if (!m_enable_irq || m_irq) + if (!m_enable_irq || m_irq || m_fiq) + { + logerror("IRQs are disabled or we're already in an FIQ/IRQ, bailing\n"); return; + } m_irq = true; @@ -229,6 +258,9 @@ void unsp_device::trigger_irq(int line) void unsp_device::check_irqs() { + if (!m_sirq) + return; + int highest_irq = -1; for (int i = 0; i <= 8; i++) { @@ -423,6 +455,7 @@ void unsp_device::execute_run() m_saved_sb[1] = m_sb; m_sb = m_saved_sb[0]; } + m_curirq = 0; check_irqs(); continue; @@ -485,7 +518,6 @@ void unsp_device::execute_run() { m_icount -= 5; UNSP_REG(PC) = read16(UNSP_LPC); - UNSP_REG(PC)++; UNSP_REG(SR) &= 0xffc0; UNSP_REG(SR) |= OPIMM; } diff --git a/src/devices/cpu/unsp/unsp.h b/src/devices/cpu/unsp/unsp.h index 83b52edd9aa..b7bada4045a 100644 --- a/src/devices/cpu/unsp/unsp.h +++ b/src/devices/cpu/unsp/unsp.h @@ -1,12 +1,12 @@ // license:BSD-3-Clause // copyright-holders:Ryan Holtz -/**************************\ -* -* SunPlus u'nSP emulator -* -* by Ryan Holtz -* -\**************************/ +/***************************************************************************** + + SunPlus micro'nSP core + + based primarily on Unununium, by segher + +*****************************************************************************/ #ifndef MAME_CPU_UNSP_UNSP_H #define MAME_CPU_UNSP_UNSP_H @@ -75,6 +75,7 @@ protected: // device_state_interface overrides virtual void state_import(const device_state_entry &entry) override; virtual void state_export(const device_state_entry &entry) override; + virtual void state_string_export(const device_state_entry &entry, std::string &str) const override; // device_disasm_interface overrides virtual std::unique_ptr create_disassembler() override; diff --git a/src/devices/cpu/unsp/unspdasm.cpp b/src/devices/cpu/unsp/unspdasm.cpp index 6e615670256..861670fb889 100644 --- a/src/devices/cpu/unsp/unspdasm.cpp +++ b/src/devices/cpu/unsp/unspdasm.cpp @@ -1,18 +1,14 @@ // license:BSD-3-Clause // copyright-holders:Ryan Holtz -/**************************\ -* -* SunPlus u'nSP disassembler -* -* by Ryan Holtz -* -\**************************/ +/***************************************************************************** + + SunPlus micro'nSP disassembler + +*****************************************************************************/ #include "emu.h" #include "unspdasm.h" -/*****************************************************************************/ - char const *const unsp_disassembler::reg[] = { "sp", "r1", "r2", "r3", "r4", "bp", "sr", "pc" diff --git a/src/devices/cpu/unsp/unspdasm.h b/src/devices/cpu/unsp/unspdasm.h index 303cc369a8f..3a88e525be7 100644 --- a/src/devices/cpu/unsp/unspdasm.h +++ b/src/devices/cpu/unsp/unspdasm.h @@ -1,13 +1,10 @@ // license:BSD-3-Clause // copyright-holders:Ryan Holtz -/**************************\ -* -* SunPlus u'nSP disassembler -* -* by Ryan Holtz -* -\**************************/ +/***************************************************************************** + SunPlus micro'nSP disassembler + +*****************************************************************************/ #ifndef MAME_CPU_UNSP_UNSPDASM_H #define MAME_CPU_UNSP_UNSPDASM_H diff --git a/src/devices/machine/spg2xx.cpp b/src/devices/machine/spg2xx.cpp new file mode 100644 index 00000000000..d703ffcf98d --- /dev/null +++ b/src/devices/machine/spg2xx.cpp @@ -0,0 +1,948 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +/***************************************************************************** + + SunPlus SPG2xx-series SoC peripheral emulation + + TODO: + - Serial UART + - I2C + - SPI + +**********************************************************************/ + +#include "spg2xx.h" + +DEFINE_DEVICE_TYPE(SPG2XX, spg2xx_device, "spg2xx", "SPG200-series System-on-a-Chip") + +#define VERBOSE_LEVEL (4) + +#define ENABLE_VERBOSE_LOG (1) + +inline void spg2xx_device::verboselog(int n_level, const char *s_fmt, ...) +{ +#if ENABLE_VERBOSE_LOG + if (VERBOSE_LEVEL >= n_level) + { + va_list v; + char buf[32768]; + va_start(v, s_fmt); + vsprintf(buf, s_fmt, v); + logerror("%s: %s", machine().describe_context(), buf); + va_end(v); + } +#endif +} + +#define SPG_DEBUG_VIDEO (0) + +#define IO_IRQ_ENABLE m_io_regs[0x21] +#define IO_IRQ_STATUS m_io_regs[0x22] +#define VIDEO_IRQ_ENABLE m_video_regs[0x62] +#define VIDEO_IRQ_STATUS m_video_regs[0x63] + +spg2xx_device::spg2xx_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, SPG2XX, tag, owner, clock) + , m_porta_out(*this) + , m_portb_out(*this) + , m_portc_out(*this) + , m_porta_in(*this) + , m_portb_in(*this) + , m_portc_in(*this) + , m_eeprom_w(*this) + , m_eeprom_r(*this) + , m_uart_tx(*this) + , m_uart_rx(*this) + , m_cpu(*this, finder_base::DUMMY_TAG) + , m_screen(*this, finder_base::DUMMY_TAG) + , m_scrollram(*this, "scrollram") + , m_paletteram(*this, "paletteram") + , m_spriteram(*this, "spriteram") +{ +} + +void spg2xx_device::map(address_map &map) +{ + map(0x000000, 0x0027ff).ram(); + map(0x002800, 0x0028ff).rw(FUNC(spg2xx_device::video_r), FUNC(spg2xx_device::video_w)); + map(0x002900, 0x002aff).ram().share("scrollram"); + map(0x002b00, 0x002bff).ram().share("paletteram"); + map(0x002c00, 0x002fff).ram().share("spriteram"); + map(0x003000, 0x0037ff).rw(FUNC(spg2xx_device::audio_r), FUNC(spg2xx_device::audio_w)); + map(0x003d00, 0x003eff).rw(FUNC(spg2xx_device::io_r), FUNC(spg2xx_device::io_w)); +} + +void spg2xx_device::device_start() +{ + m_porta_out.resolve_safe(); + m_portb_out.resolve_safe(); + m_portc_out.resolve_safe(); + m_porta_in.resolve_safe(0); + m_portb_in.resolve_safe(0); + m_portc_in.resolve_safe(0); + m_eeprom_w.resolve_safe(); + m_eeprom_r.resolve_safe(0); + m_uart_tx.resolve_safe(); + m_uart_rx.resolve_safe(0); + + m_tmb1 = timer_alloc(TIMER_TMB1); + m_tmb2 = timer_alloc(TIMER_TMB2); + m_tmb1->adjust(attotime::never); + m_tmb2->adjust(attotime::never); + + m_screenpos_timer = timer_alloc(TIMER_SCREENPOS); + m_screenpos_timer->adjust(attotime::never); +} + +void spg2xx_device::device_reset() +{ + memset(m_video_regs, 0, 0x100 * sizeof(m_video_regs[0])); + memset(m_io_regs, 0, 0x200 * sizeof(m_io_regs[0])); + + m_video_regs[0x36] = 0xffff; + m_video_regs[0x37] = 0xffff; + + m_hide_page0 = false; + m_hide_page1 = false; + m_hide_sprites = false; + m_debug_sprites = false; + m_debug_blit = false; + m_sprite_index_to_debug = 0; +} + + +/************************* +* Video Hardware * +*************************/ + +inline uint8_t spg2xx_device::expand_rgb5_to_rgb8(uint8_t val) +{ + uint8_t temp = val & 0x1f; + return (temp << 3) | (temp >> 2); +} + +// Perform a lerp between a and b +inline uint8_t spg2xx_device::mix_channel(uint8_t a, uint8_t b) +{ + uint8_t alpha = (m_video_regs[0x2a] & 3) << 6; + return ((255 - alpha) * a + alpha * b) / 255; +} + +void spg2xx_device::mix_pixel(uint32_t offset, uint16_t rgb) +{ + m_screenbuf[offset].r = mix_channel(m_screenbuf[offset].r, expand_rgb5_to_rgb8(rgb >> 10)); + m_screenbuf[offset].g = mix_channel(m_screenbuf[offset].g, expand_rgb5_to_rgb8(rgb >> 5)); + m_screenbuf[offset].b = mix_channel(m_screenbuf[offset].b, expand_rgb5_to_rgb8(rgb)); +} + +void spg2xx_device::set_pixel(uint32_t offset, uint16_t rgb) +{ + m_screenbuf[offset].r = expand_rgb5_to_rgb8(rgb >> 10); + m_screenbuf[offset].g = expand_rgb5_to_rgb8(rgb >> 5); + m_screenbuf[offset].b = expand_rgb5_to_rgb8(rgb); +} + +void spg2xx_device::blit(bitmap_rgb32 &bitmap, const rectangle &cliprect, uint32_t xoff, uint32_t yoff, uint32_t attr, uint32_t ctrl, uint32_t bitmap_addr, uint16_t tile) +{ + address_space &space = m_cpu->space(AS_PROGRAM); + + uint32_t h = 8 << ((attr & PAGE_TILE_HEIGHT_MASK) >> PAGE_TILE_HEIGHT_SHIFT); + uint32_t w = 8 << ((attr & PAGE_TILE_WIDTH_MASK) >> PAGE_TILE_WIDTH_SHIFT); + + uint32_t yflipmask = attr & TILE_Y_FLIP ? h - 1 : 0; + uint32_t xflipmask = attr & TILE_X_FLIP ? w - 1 : 0; + + uint32_t nc = ((attr & 0x0003) + 1) << 1; + + uint32_t palette_offset = (attr & 0x0f00) >> 4; + if (m_debug_blit && SPG_DEBUG_VIDEO) + { + printf("xy:%08x,%08x attr:%08x ctrl:%08x bitmap_addr:%08x tile:%04x\n", xoff, yoff, attr, ctrl, bitmap_addr, tile); + printf("hw:%d,%d f:%d,%d fm:%d,%d ncols:%d pobs:%02x ", w, h, (attr & TILE_X_FLIP) ? 1 : 0, (attr & TILE_Y_FLIP) ? 1 : 0, xflipmask, yflipmask, nc, palette_offset); + } + palette_offset >>= nc; + palette_offset <<= nc; + if (m_debug_blit && SPG_DEBUG_VIDEO) + { + printf("poas:%02x\n", palette_offset); + } + + uint32_t m = bitmap_addr + nc * w*h / 16 * tile; + uint32_t bits = 0; + uint32_t nbits = 0; + + for (uint32_t y = 0; y < h; y++) + { + int yy = (yoff + (y ^ yflipmask)) & 0x1ff; + if (yy >= 0x01c0) + yy -= 0x0200; + + if (m_debug_blit && SPG_DEBUG_VIDEO) + printf("%3d:\n", yy); + + for (uint32_t x = 0; x < w; x++) + { + int xx = xoff + (x ^ xflipmask); + + bits <<= nc; + if (m_debug_blit && SPG_DEBUG_VIDEO) + printf(" %08x:%d ", bits, nbits); + if (nbits < nc) + { + uint16_t b = space.read_word(m++ & 0x3fffff); + b = (b << 8) | (b >> 8); + bits |= b << (nc - nbits); + nbits += 16; + if (m_debug_blit && SPG_DEBUG_VIDEO) + printf("(%04x:%08x:%d) ", b, bits, nbits); + } + nbits -= nc; + + uint32_t pal = palette_offset + (bits >> 16); + if (m_debug_blit && SPG_DEBUG_VIDEO) + printf("%02x:%02x:%04x ", bits >> 16, pal, bits & 0xffff); + bits &= 0xffff; + + if ((ctrl & 0x0010) && yy < 240) + xx -= (int16_t)m_scrollram[yy + 15]; + + xx &= 0x01ff; + if (xx >= 0x01c0) + xx -= 0x0200; + + if (xx >= 0 && xx < 320 && yy >= 0 && yy < 240) + { + uint16_t rgb = m_paletteram[pal]; + if (m_debug_blit && SPG_DEBUG_VIDEO) + printf("rgb:%04x ", rgb); + if (!(rgb & 0x8000)) + { + if (attr & 0x4000 || ctrl & 0x0100) + { + if (m_debug_blit && SPG_DEBUG_VIDEO) + printf("M\n"); + mix_pixel(xx + 320 * yy, rgb); + } + else + { + if (m_debug_blit && SPG_DEBUG_VIDEO) + printf("S\n"); + set_pixel(xx + 320 * yy, rgb); + } + } + else if (m_debug_blit && SPG_DEBUG_VIDEO) + { + printf("X\n"); + } + } + } + } +} + +void spg2xx_device::blit_page(bitmap_rgb32 &bitmap, const rectangle &cliprect, int depth, uint32_t bitmap_addr, uint16_t *regs) +{ + uint32_t xscroll = regs[0]; + uint32_t yscroll = regs[1]; + uint32_t attr = regs[2]; + uint32_t ctrl = regs[3]; + uint32_t tilemap = regs[4]; + uint32_t palette_map = regs[5]; + address_space &space = m_cpu->space(AS_PROGRAM); + + if (!(ctrl & PAGE_ENABLE_MASK)) + { + return; + } + + if (((attr & PAGE_DEPTH_FLAG_MASK) >> PAGE_DEPTH_FLAG_SHIFT) != depth) + { + return; + } + + uint32_t h = 8 << ((attr & PAGE_TILE_HEIGHT_MASK) >> PAGE_TILE_HEIGHT_SHIFT); + uint32_t w = 8 << ((attr & PAGE_TILE_WIDTH_MASK) >> PAGE_TILE_WIDTH_SHIFT); + + uint32_t hn = 256 / h; + uint32_t wn = 512 / w; + + for (uint32_t y0 = 0; y0 < hn; y0++) + { + for (uint32_t x0 = 0; x0 < wn; x0++) + { + uint16_t tile = (ctrl & PAGE_BLANK_MASK) ? 0 : space.read_word(tilemap + x0 + wn * y0); + uint16_t palette = 0; + uint32_t xx, yy; + + if (!tile) + { + continue; + } + + palette = space.read_word(palette_map + (x0 + wn * y0) / 2); + if (x0 & 1) + { + palette >>= 8; + } + + uint32_t tileattr = attr; + uint32_t tilectrl = ctrl; + if ((ctrl & 2) == 0) + { // -(1) bld(1) flip(2) pal(4) + tileattr &= ~0x000c; + tileattr |= (palette >> 2) & 0x000c; // flip + + tileattr &= ~0x0f00; + tileattr |= (palette << 8) & 0x0f00; // palette + + tilectrl &= ~0x0100; + tilectrl |= (palette << 2) & 0x0100; // blend + } + + yy = ((h*y0 - yscroll + 0x10) & 0xff) - 0x10; + xx = (w*x0 - xscroll) & 0x1ff; + + blit(bitmap, cliprect, xx, yy, tileattr, tilectrl, bitmap_addr, tile); + } + } +} + +void spg2xx_device::blit_sprite(bitmap_rgb32 &bitmap, const rectangle &cliprect, int depth, uint32_t base_addr) +{ + address_space &space = m_cpu->space(AS_PROGRAM); + uint32_t bitmap_addr = 0x40 * m_video_regs[0x22]; + + uint16_t tile = space.read_word(base_addr + 0); + int16_t x = space.read_word(base_addr + 1); + int16_t y = space.read_word(base_addr + 2); + uint16_t attr = space.read_word(base_addr + 3); + + if (!tile) + { + return; + } + + if (((attr & PAGE_DEPTH_FLAG_MASK) >> PAGE_DEPTH_FLAG_SHIFT) != depth) + { + return; + } + + if (!(m_video_regs[0x42] & SPRITE_COORD_TL_MASK)) + { + x = 160 + x; + y = 120 - y; + + uint32_t h = 8 << ((attr & PAGE_TILE_HEIGHT_MASK) >> PAGE_TILE_HEIGHT_SHIFT); + uint32_t w = 8 << ((attr & PAGE_TILE_WIDTH_MASK) >> PAGE_TILE_WIDTH_SHIFT); + + x -= (w / 2); + y -= (h / 2) - 8; + } + + x &= 0x01ff; + y &= 0x01ff; + +#if SPG_DEBUG_VIDEO + if (m_debug_sprites && machine().input().code_pressed(KEYCODE_MINUS)) + m_debug_blit = true; + blit(bitmap, cliprect, x, y, attr, 0, bitmap_addr, tile); + m_debug_blit = false; +#else + blit(bitmap, cliprect, x, y, attr, 0, bitmap_addr, tile); +#endif +} + +void spg2xx_device::blit_sprites(bitmap_rgb32 &bitmap, const rectangle &cliprect, int depth) +{ + if (!(m_video_regs[0x42] & SPRITE_ENABLE_MASK)) + { + return; + } + +#if SPG_DEBUG_VIDEO + if (!m_debug_sprites) + { +#endif + for (uint32_t n = 0; n < 256; n++) + { + blit_sprite(bitmap, cliprect, depth, 0x2c00 + 4 * n); + } +#if SPG_DEBUG_VIDEO + } + else + { + blit_sprite(bitmap, cliprect, depth, 0x2c00 + 4 * m_sprite_index_to_debug); + } +#endif +} + +uint32_t spg2xx_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + memset(&m_screenbuf[320 * cliprect.min_y], 0, 3 * 320 * ((cliprect.max_y - cliprect.min_y) + 1)); + + for (int i = 0; i < 4; i++) + { + if (!m_hide_page0) + blit_page(bitmap, cliprect, i, 0x40 * m_video_regs[0x20], m_video_regs + 0x10); + if (!m_hide_page1) + blit_page(bitmap, cliprect, i, 0x40 * m_video_regs[0x21], m_video_regs + 0x16); + if (!m_hide_sprites) + blit_sprites(bitmap, cliprect, i); + } + + bitmap.fill(0, cliprect); + for (int y = cliprect.min_y; y <= cliprect.max_y; y++) + { + for (int x = cliprect.min_x; x <= cliprect.max_x; x++) + { + bitmap.pix32(y, x) = (m_screenbuf[x + 320 * y].r << 16) | (m_screenbuf[x + 320 * y].g << 8) | m_screenbuf[x + 320 * y].b; + } + } + + return 0; +} + +void spg2xx_device::do_video_dma(uint32_t len) +{ + address_space &mem = m_cpu->space(AS_PROGRAM); + + uint32_t src = m_video_regs[0x70] & 0x3fff; + uint32_t dst = (m_video_regs[0x71] & 0x3ff) + 0x2c00; + + for (uint32_t j = 0; j < len; j++) + { + mem.write_word(dst + j, mem.read_word(src + j)); + } + + m_video_regs[0x72] = 0; + VIDEO_IRQ_STATUS |= 4; +} + +READ16_MEMBER(spg2xx_device::video_r) +{ + switch (offset) + { + case 0x38: // Current Line + verboselog(3, "video_r: Current Line: %04x\n", m_screen->vpos()); + return m_screen->vpos(); + + case 0x62: // Video IRQ Enable + verboselog(0, "video_r: Video IRQ Enable: %04x\n", VIDEO_IRQ_ENABLE); + return VIDEO_IRQ_ENABLE; + + case 0x63: // Video IRQ Status + verboselog(0, "video_r: Video IRQ Status: %04x\n", VIDEO_IRQ_STATUS); + return VIDEO_IRQ_STATUS; + + default: + verboselog(0, "video_r: Unknown register %04x = %04x\n", 0x2800 + offset, m_video_regs[offset]); + break; + } + return m_video_regs[offset]; +} + +WRITE16_MEMBER(spg2xx_device::video_w) +{ + switch (offset) + { + case 0x10: // Page 1 X scroll + verboselog(4, "video_w: Page 1 X Scroll: %04x = %04x\n", 0x2800 | offset, data & 0x01ff); + m_video_regs[offset] = data & 0x01ff; + break; + + case 0x16: // Page 2 X scroll + verboselog(4, "video_w: Page 2 X Scroll: %04x = %04x\n", 0x2800 | offset, data & 0x01ff); + m_video_regs[offset] = data & 0x01ff; + break; + + case 0x11: // Page 1 Y scroll + verboselog(4, "video_w: Page 1 Y Scroll: %04x = %04x\n", 0x2800 | offset, data & 0x00ff); + m_video_regs[offset] = data & 0x00ff; + break; + + case 0x17: // Page 2 Y scroll + verboselog(4, "video_w: Page 2 Y Scroll: %04x = %04x\n", 0x2800 | offset, data & 0x00ff); + m_video_regs[offset] = data & 0x00ff; + break; + + case 0x36: // IRQ pos V + case 0x37: // IRQ pos H + m_video_regs[offset] = data & 0x01ff; + verboselog(0, "video_w: Video IRQ Position: %04x,%04x (%04x)\n", m_video_regs[0x37], m_video_regs[0x36], 0x2800 | offset); + if (m_video_regs[0x37] < 160 && m_video_regs[0x36] < 240) + m_screenpos_timer->adjust(m_screen->time_until_pos(m_video_regs[0x36], m_video_regs[0x37] << 1)); + else + m_screenpos_timer->adjust(attotime::never); + break; + + case 0x62: // Video IRQ Enable + { + verboselog(0, "video_w: Video IRQ Enable = %04x (%04x)\n", data, mem_mask); + const uint16_t old = VIDEO_IRQ_ENABLE & VIDEO_IRQ_STATUS; + COMBINE_DATA(&VIDEO_IRQ_ENABLE); + const uint16_t changed = old ^ (VIDEO_IRQ_ENABLE & VIDEO_IRQ_STATUS); + if (changed) + check_video_irq(); + break; + } + + case 0x63: // Video IRQ Acknowledge + { + verboselog(0, "video_w: Video IRQ Acknowledge = %04x (%04x)\n", data, mem_mask); + const uint16_t old = VIDEO_IRQ_ENABLE & VIDEO_IRQ_STATUS; + VIDEO_IRQ_STATUS &= ~data; + verboselog(4, "Setting video IRQ status to %04x\n", VIDEO_IRQ_STATUS); + const uint16_t changed = old ^ (VIDEO_IRQ_ENABLE & VIDEO_IRQ_STATUS); + if (changed) + check_video_irq(); + break; + } + + case 0x70: // Video DMA Source + verboselog(0, "video_w: Video DMA Source = %04x (%04x)\n", data, mem_mask); + COMBINE_DATA(&m_video_regs[offset]); + break; + + case 0x71: // Video DMA Dest + verboselog(0, "video_w: Video DMA Dest = %04x (%04x)\n", data, mem_mask); + COMBINE_DATA(&m_video_regs[offset]); + break; + + case 0x72: // Video DMA Length + verboselog(0, "video_w: Video DMA Length = %04x (%04x)\n", data, mem_mask); + do_video_dma(data & 0x3ff); + break; + + default: + verboselog(0, "video_w: Unknown register %04x = %04x (%04x)\n", 0x2800 + offset, data, mem_mask); + COMBINE_DATA(&m_video_regs[offset]); + break; + } +} + +WRITE_LINE_MEMBER(spg2xx_device::vblank) +{ + if (!state) + return; + +#if SPG_DEBUG_VIDEO + if (machine().input().code_pressed_once(KEYCODE_5)) + m_hide_page0 = !m_hide_page0; + if (machine().input().code_pressed_once(KEYCODE_6)) + m_hide_page1 = !m_hide_page1; + if (machine().input().code_pressed_once(KEYCODE_7)) + m_hide_sprites = !m_hide_sprites; + if (machine().input().code_pressed_once(KEYCODE_8)) + m_debug_sprites = !m_debug_sprites; + if (machine().input().code_pressed_once(KEYCODE_9)) + m_sprite_index_to_debug--; + if (machine().input().code_pressed_once(KEYCODE_0)) + m_sprite_index_to_debug++; +#endif + + const uint16_t old = VIDEO_IRQ_ENABLE & VIDEO_IRQ_STATUS; + VIDEO_IRQ_STATUS |= 1; + verboselog(4, "Setting video IRQ status to %04x\n", VIDEO_IRQ_STATUS); + const uint16_t changed = old ^ (VIDEO_IRQ_ENABLE & VIDEO_IRQ_STATUS); + if (changed) + check_video_irq(); + + // For now, manually trigger controller IRQs + if (IO_IRQ_ENABLE & 0x2100) + { + IO_IRQ_STATUS |= 0x0100; + m_cpu->set_input_line(UNSP_IRQ3_LINE, ASSERT_LINE); + } +} + +void spg2xx_device::check_video_irq() +{ + m_cpu->set_input_line(UNSP_IRQ0_LINE, (VIDEO_IRQ_STATUS & VIDEO_IRQ_ENABLE) ? ASSERT_LINE : CLEAR_LINE); +} + + +/************************* +* Machine Hardware * +*************************/ + +READ16_MEMBER(spg2xx_device::audio_r) +{ + switch (offset) + { + default: + verboselog(4, "audio_r: Unknown register %04x\n", 0x3000 + offset); + break; + } + return 0; +} + +WRITE16_MEMBER(spg2xx_device::audio_w) +{ + switch (offset) + { + default: + verboselog(5, "audio_w: Unknown register %04x = %04x (%04x)\n", 0x3000 + offset, data, mem_mask); + break; + } +} + +READ16_MEMBER(spg2xx_device::io_r) +{ + static const char *const gpioregs[] = { "GPIO Data Port", "GPIO Buffer Port", "GPIO Direction Port", "GPIO Attribute Port", "GPIO IRQ/Latch Port" }; + static const char gpioports[] = { 'A', 'B', 'C' }; + + uint16_t val = m_io_regs[offset]; + + switch (offset) + { + case 0x01: case 0x06: case 0x0b: // GPIO Data Port A/B/C + do_gpio(offset); + verboselog(3, "io_r: %s %c = %04x (%04x)\n", gpioregs[(offset - 1) % 5], gpioports[(offset - 1) / 5], m_io_regs[offset], mem_mask); + val = m_io_regs[offset]; + break; + + case 0x02: case 0x03: case 0x04: case 0x05: + case 0x07: case 0x08: case 0x09: case 0x0a: + case 0x0c: case 0x0d: case 0x0e: case 0x0f: // Other GPIO regs + verboselog(3, "io_r: %s %c = %04x (%04x)\n", gpioregs[(offset - 1) % 5], gpioports[(offset - 1) / 5], m_io_regs[offset], mem_mask); + break; + + case 0x1c: // Video line counter + val = m_screen->vpos(); + verboselog(3, "io_r: Video Line = %04x (%04x)\n", val, mem_mask); + break; + + case 0x21: // IRQ Control + verboselog(3, "io_r: Controller IRQ Control = %04x (%04x)\n", val, mem_mask); + break; + + case 0x22: // IRQ Status + verboselog(3, "io_r: Controller IRQ Status = %04x (%04x)\n", val, mem_mask); + break; + + case 0x2b: + return 0x0000; + + case 0x2c: case 0x2d: // PRNG 0/1 + val = machine().rand() & 0x0000ffff; + verboselog(3, "io_r: PRNG %d = %04x (%04x)\n", offset - 0x2c, val, mem_mask); + break; + + case 0x2f: // Data Segment + val = m_cpu->state_int(UNSP_SR) >> 10; + verboselog(3, "io_r: Data Segment = %04x (%04x)\n", val, mem_mask); + break; + + case 0x31: // UART Status + verboselog(3, "io_r: UART Status = %04x (%04x)\n", 3, mem_mask); + val = 3; // HACK + break; + + case 0x36: // UART RX Data + val = m_uart_rx(); + verboselog(3, "io_r: UART RX Data = %04x (%04x)\n", val, mem_mask); + break; + + case 0x59: // I2C Status + verboselog(3, "io_r: I2C Status = %04x (%04x)\n", val, mem_mask); + break; + + case 0x5e: // I2C Data In + verboselog(3, "io_r: I2C Data In = %04x (%04x)\n", val, mem_mask); + break; + + default: + verboselog(3, "io_r: Unknown register %04x\n", 0x3d00 + offset); + break; + } + + return val; +} + +WRITE16_MEMBER(spg2xx_device::io_w) +{ + static const char *const gpioregs[] = { "GPIO Data Port", "GPIO Buffer Port", "GPIO Direction Port", "GPIO Attribute Port", "GPIO IRQ/Latch Port" }; + static const char gpioports[3] = { 'A', 'B', 'C' }; + + uint16_t temp = 0; + + switch (offset) + { + case 0x00: // GPIO special function select + verboselog(3, "io_w: GPIO Function Select = %04x (%04x)\n", data, mem_mask); + COMBINE_DATA(&m_io_regs[offset]); + break; + + case 0x01: case 0x06: case 0x0b: // GPIO data, port A/B/C + offset++; + // Intentional fallthrough - we redirect data register writes to the buffer register. + + case 0x02: case 0x03: case 0x04: case 0x05: // Port A + case 0x07: case 0x08: case 0x09: case 0x0a: // Port B + case 0x0c: case 0x0d: case 0x0e: case 0x0f: // Port C + verboselog(3, "io_w: %s %c = %04x (%04x)\n", gpioregs[(offset - 1) % 5], gpioports[(offset - 1) / 5], data, mem_mask); + COMBINE_DATA(&m_io_regs[offset]); + do_gpio(offset); + break; + + case 0x10: // timebase control + if ((m_io_regs[offset] & 0x0003) != (data & 0x0003)) + { + uint16_t hz = 8 << (data & 0x0003); + verboselog(3, "*** TMB1 FREQ set to %dHz\n", hz); + m_tmb1->adjust(attotime::from_hz(hz), 0, attotime::from_hz(hz)); + } + if ((m_io_regs[offset] & 0x000c) != (data & 0x000c)) + { + uint16_t hz = 128 << ((data & 0x000c) >> 2); + verboselog(3, "*** TMB2 FREQ set to %dHz\n", hz); + m_tmb2->adjust(attotime::from_hz(hz), 0, attotime::from_hz(hz)); + } + COMBINE_DATA(&m_io_regs[offset]); + break; + + case 0x21: // IRQ Enable + { + verboselog(3, "io_w: IRQ Control = %04x (%04x)\n", data, mem_mask); + const uint16_t old = IO_IRQ_ENABLE & IO_IRQ_STATUS; + COMBINE_DATA(&IO_IRQ_ENABLE); + const uint16_t changed = old ^ (IO_IRQ_ENABLE & IO_IRQ_STATUS); + if (changed) + check_irqs(changed); + break; + } + + case 0x22: // IRQ Acknowledge + { + verboselog(3, "io_w: IRQ Acknowledge = %04x (%04x)\n", data, mem_mask); + const uint16_t old = IO_IRQ_STATUS; + IO_IRQ_STATUS &= ~data; + const uint16_t changed = old ^ (IO_IRQ_ENABLE & IO_IRQ_STATUS); + if (changed) + check_irqs(changed); + break; + } + + case 0x2f: // Data Segment + temp = m_cpu->state_int(UNSP_SR); + m_cpu->set_state_int(UNSP_SR, (temp & 0x03ff) | ((data & 0x3f) << 10)); + verboselog(3, "io_w: Data Segment = %04x (%04x)\n", data, mem_mask); + break; + + case 0x31: // Unknown UART + verboselog(3, "io_w: Unknown UART = %04x (%04x)\n", data, mem_mask); + COMBINE_DATA(&m_io_regs[offset]); + break; + + case 0x32: // UART Reset + verboselog(3, "io_w: UART Reset\n"); + break; + + case 0x33: // UART Baud Rate + verboselog(3, "io_w: UART Baud Rate = %u\n", 27000000 / 16 / (0x10000 - (m_io_regs[0x34] << 8) - data)); + COMBINE_DATA(&m_io_regs[offset]); + break; + + case 0x35: // UART TX Data + verboselog(3, "io_w: UART Baud Rate = %u\n", 27000000 / 16 / (0x10000 - (data << 8) - m_io_regs[0x33])); + COMBINE_DATA(&m_io_regs[offset]); + break; + + case 0x58: // I2C Command + verboselog(3, "io_w: I2C Command = %04x (%04x)\n", data, mem_mask); + COMBINE_DATA(&m_io_regs[offset]); + do_i2c(); + break; + + case 0x59: // I2C Status / Acknowledge + verboselog(3, "io_w: I2C Acknowledge = %04x (%04x)\n", data, mem_mask); + m_io_regs[offset] &= ~data; + break; + + case 0x5a: // I2C Access Mode + verboselog(3, "io_w: I2C Access Mode = %04x (%04x)\n", data, mem_mask); + COMBINE_DATA(&m_io_regs[offset]); + break; + + case 0x5b: // I2C Device Address + verboselog(3, "io_w: I2C Device Address = %04x (%04x)\n", data, mem_mask); + COMBINE_DATA(&m_io_regs[offset]); + break; + + case 0x5c: // I2C Sub-Address + verboselog(3, "io_w: I2C Sub-Address = %04x (%04x)\n", data, mem_mask); + COMBINE_DATA(&m_io_regs[offset]); + break; + + case 0x5d: // I2C Data Out + verboselog(3, "io_w: I2C Data Out = %04x (%04x)\n", data, mem_mask); + COMBINE_DATA(&m_io_regs[offset]); + break; + + case 0x5e: // I2C Data In + verboselog(3, "io_w: I2C Data In = %04x (%04x)\n", data, mem_mask); + COMBINE_DATA(&m_io_regs[offset]); + break; + + case 0x5f: // I2C Controller Mode + verboselog(3, "io_w: I2C Controller Mode = %04x (%04x)\n", data, mem_mask); + COMBINE_DATA(&m_io_regs[offset]); + break; + + case 0x100: // DMA Source (L) + verboselog(3, "io_w: DMA Source (L) 3e00 = %04x (%04x)\n", data, mem_mask); + COMBINE_DATA(&m_io_regs[offset]); + break; + + case 0x101: // DMA Source (H) + verboselog(3, "io_w: DMA Source (H) 3e01 = %04x (%04x)\n", data, mem_mask); + COMBINE_DATA(&m_io_regs[offset]); + break; + + case 0x103: // DMA Destination + verboselog(3, "io_w: DMA Dest 3e03 = %04x (%04x)\n", data, mem_mask); + COMBINE_DATA(&m_io_regs[offset]); + break; + + case 0x102: // DMA Length + verboselog(3, "io_w: DMA Length 3e02 = %04x (%04x)\n", data, mem_mask); + do_cpu_dma(data); + break; + + default: + verboselog(3, "io_w: Unknown register %04x = %04x (%04x)\n", 0x3d00 + offset, data, mem_mask); + COMBINE_DATA(&m_io_regs[offset]); + break; + } +} + +void spg2xx_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + switch (id) + { + case TIMER_TMB1: + { + const uint16_t old = (IO_IRQ_ENABLE & IO_IRQ_STATUS); + IO_IRQ_STATUS |= 1; + const uint16_t changed = old ^ (IO_IRQ_ENABLE & IO_IRQ_STATUS); + if (changed) + check_irqs(changed); + break; + } + case TIMER_TMB2: + { + const uint16_t old = m_io_regs[0x22] & m_io_regs[0x21]; + IO_IRQ_STATUS |= 2; + const uint16_t changed = old ^ (IO_IRQ_ENABLE & IO_IRQ_STATUS); + if (changed) + check_irqs(changed); + break; + } + case TIMER_SCREENPOS: + { + const uint16_t old = VIDEO_IRQ_ENABLE & VIDEO_IRQ_STATUS; + VIDEO_IRQ_STATUS |= 2; + const uint16_t changed = old ^ (VIDEO_IRQ_ENABLE & VIDEO_IRQ_STATUS); + if (changed) + { + check_video_irq(); + } + m_screen->update_partial(m_screen->vpos()); + break; + } + } +} + +void spg2xx_device::check_irqs(const uint16_t changed) +{ + // { + // verboselog(0, "audio 1 IRQ\n"); + // m_cpu->set_input_line(UNSP_IRQ1_LINE, ASSERT_LINE); + // } + if (changed & 0x0c00) // Timer A, Timer B IRQ + { + m_cpu->set_input_line(UNSP_IRQ2_LINE, (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x0c00) ? ASSERT_LINE : CLEAR_LINE); + } + + if (changed & 0x2100) // UART, ADC IRQ + m_cpu->set_input_line(UNSP_IRQ3_LINE, (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x2100) ? ASSERT_LINE : CLEAR_LINE); + + // { + // verboselog(0, "audio 4 IRQ\n"); + // m_cpu->set_input_line(UNSP_IRQ4_LINE, ASSERT_LINE); + // } + + if (changed & 0x1200) // External IRQ + { + m_cpu->set_input_line(UNSP_IRQ5_LINE, (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x1200) ? ASSERT_LINE : CLEAR_LINE); + } + + if (changed & 0x0070) // 1024Hz, 2048Hz, 4096Hz IRQ + { + m_cpu->set_input_line(UNSP_IRQ6_LINE, (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x0070) ? ASSERT_LINE : CLEAR_LINE); + } + + if (changed & 0x008b) // TMB1, TMB2, 4Hz, key change IRQ + { + m_cpu->set_input_line(UNSP_IRQ7_LINE, (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x008b) ? ASSERT_LINE : CLEAR_LINE); + } +} + +void spg2xx_device::do_gpio(uint32_t offset) +{ + uint32_t index = (offset - 1) / 5; + uint16_t buffer = m_io_regs[5 * index + 2]; + uint16_t dir = m_io_regs[5 * index + 3]; + uint16_t attr = m_io_regs[5 * index + 4]; + uint16_t special = m_io_regs[5 * index + 5]; + + uint16_t push = dir; + uint16_t pull = (~dir) & (~attr); + uint16_t what = (buffer & (push | pull)); + what ^= (dir & ~attr); + what &= ~special; + + switch (index) + { + case 0: + m_porta_out(what); + what = (what & ~pull) | (m_porta_in() & pull); + break; + case 1: + m_portb_out(what); + what = (what & ~pull) | (m_portb_in() & pull); + break; + case 2: + m_portc_out(what); + what = (what & ~pull) | (m_portc_in() & pull); + break; + } + + m_io_regs[5 * index + 1] = what; +} + +void spg2xx_device::do_i2c() +{ + const uint16_t addr = ((m_io_regs[0x5b] & 0x06) << 7) | (uint8_t)m_io_regs[0x5c]; + + if (m_io_regs[0x58] & 0x40) // Serial EEPROM read + m_io_regs[0x5e] = m_eeprom_r(addr); + else + m_eeprom_w(addr, m_io_regs[0x5d]); + + m_io_regs[0x59] |= 1; +} + +void spg2xx_device::do_cpu_dma(uint32_t len) +{ + address_space &mem = m_cpu->space(AS_PROGRAM); + + uint32_t src = ((m_io_regs[0x101] & 0x3f) << 16) | m_io_regs[0x100]; + uint32_t dst = m_io_regs[0x103] & 0x3fff; + + for (uint32_t j = 0; j < len; j++) + { + mem.write_word(dst + j, mem.read_word(src + j)); + } + + m_io_regs[0x102] = 0; +} diff --git a/src/devices/machine/spg2xx.h b/src/devices/machine/spg2xx.h new file mode 100644 index 00000000000..e5cc86d6ca3 --- /dev/null +++ b/src/devices/machine/spg2xx.h @@ -0,0 +1,151 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +/***************************************************************************** + + SunPlus SPG2xx-series SoC peripheral emulation + + TODO: + - Serial UART + - I2C + - SPI + +**********************************************************************/ + +#ifndef DEVICES_MACHINE_SPG2XX_H +#define DEVICES_MACHINE_SPG2XX_H + +#pragma once + +#include "emu.h" +#include "cpu/unsp/unsp.h" +#include "screen.h" + +class spg2xx_device : public device_t +{ +public: + template + spg2xx_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&cpu_tag, U &&screen_tag) + : spg2xx_device(mconfig, tag, owner, clock) + { + m_cpu.set_tag(std::forward(cpu_tag)); + m_screen.set_tag(std::forward(screen_tag)); + } + + spg2xx_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + void map(address_map &map); + + auto porta_out() { return m_porta_out.bind(); } + auto portb_out() { return m_portb_out.bind(); } + auto portc_out() { return m_portc_out.bind(); } + auto porta_in() { return m_porta_in.bind(); } + auto portb_in() { return m_portb_in.bind(); } + auto portc_in() { return m_portc_in.bind(); } + + auto eeprom_w() { return m_eeprom_w.bind(); } + auto eeprom_r() { return m_eeprom_r.bind(); } + + auto uart_tx() { return m_uart_tx.bind(); } + auto uart_rx() { return m_uart_rx.bind(); } + + uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); + DECLARE_WRITE_LINE_MEMBER(vblank); + +protected: + enum + { + PAGE_ENABLE_MASK = 0x0008, + PAGE_BLANK_MASK = 0x0004, + + SPRITE_ENABLE_MASK = 0x0001, + SPRITE_COORD_TL_MASK = 0x0002, + + PAGE_DEPTH_FLAG_MASK = 0x3000, + PAGE_DEPTH_FLAG_SHIFT = 12, + PAGE_TILE_HEIGHT_MASK = 0x00c0, + PAGE_TILE_HEIGHT_SHIFT = 6, + PAGE_TILE_WIDTH_MASK = 0x0030, + PAGE_TILE_WIDTH_SHIFT = 4, + TILE_X_FLIP = 0x0004, + TILE_Y_FLIP = 0x0008 + }; + + DECLARE_READ16_MEMBER(video_r); + DECLARE_WRITE16_MEMBER(video_w); + DECLARE_READ16_MEMBER(audio_r); + DECLARE_WRITE16_MEMBER(audio_w); + DECLARE_READ16_MEMBER(io_r); + DECLARE_WRITE16_MEMBER(io_w); + + void check_irqs(const uint16_t changed); + inline void check_video_irq(); + + void spg2xx_map(address_map &map); + + static const device_timer_id TIMER_TMB1 = 0; + static const device_timer_id TIMER_TMB2 = 1; + static const device_timer_id TIMER_SCREENPOS = 2; + + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; + + void do_gpio(uint32_t offset); + void do_i2c(); + void do_video_dma(uint32_t len); + void do_cpu_dma(uint32_t len); + + void blit(bitmap_rgb32 &bitmap, const rectangle &cliprect, uint32_t xoff, uint32_t yoff, uint32_t attr, uint32_t ctrl, uint32_t bitmap_addr, uint16_t tile); + void blit_page(bitmap_rgb32 &bitmap, const rectangle &cliprect, int depth, uint32_t bitmap_addr, uint16_t *regs); + void blit_sprite(bitmap_rgb32 &bitmap, const rectangle &cliprect, int depth, uint32_t base_addr); + void blit_sprites(bitmap_rgb32 &bitmap, const rectangle &cliprect, int depth); + inline uint8_t expand_rgb5_to_rgb8(uint8_t val); + inline uint8_t mix_channel(uint8_t a, uint8_t b); + void mix_pixel(uint32_t offset, uint16_t rgb); + void set_pixel(uint32_t offset, uint16_t rgb); + + inline void verboselog(int n_level, const char *s_fmt, ...) ATTR_PRINTF(3, 4); + + struct + { + uint8_t r, g, b; + } + m_screenbuf[320 * 240]; + + bool m_hide_page0; + bool m_hide_page1; + bool m_hide_sprites; + bool m_debug_sprites; + bool m_debug_blit; + uint8_t m_sprite_index_to_debug; + + uint16_t m_video_regs[0x100]; + uint16_t m_io_regs[0x200]; + + devcb_write16 m_porta_out; + devcb_write16 m_portb_out; + devcb_write16 m_portc_out; + devcb_read16 m_porta_in; + devcb_read16 m_portb_in; + devcb_read16 m_portc_in; + + devcb_write8 m_eeprom_w; + devcb_read8 m_eeprom_r; + + devcb_write8 m_uart_tx; + devcb_read8 m_uart_rx; + + emu_timer *m_tmb1; + emu_timer *m_tmb2; + emu_timer *m_screenpos_timer; + + required_device m_cpu; + required_device m_screen; + required_shared_ptr m_scrollram; + required_shared_ptr m_paletteram; + required_shared_ptr m_spriteram; +}; + +DECLARE_DEVICE_TYPE(SPG2XX, spg2xx_device) + +#endif // DEVICES_MACHINE_SPG2XX_H diff --git a/src/mame/drivers/vii.cpp b/src/mame/drivers/vii.cpp index 7d40b96dc34..65f9d34f06f 100644 --- a/src/mame/drivers/vii.cpp +++ b/src/mame/drivers/vii.cpp @@ -63,6 +63,7 @@ Detailed list of bugs: #include "emu.h" #include "cpu/unsp/unsp.h" +#include "machine/spg2xx.h" #include "machine/i2cmem.h" #include "bus/generic/slot.h" @@ -72,33 +73,16 @@ Detailed list of bugs: #include "screen.h" #include "softlist.h" -#define VII_DEBUG_VIDEO (0) - -#define PAGE_ENABLE_MASK 0x0008 -#define PAGE_BLANK_MASK 0x0004 - -#define PAGE_DEPTH_FLAG_MASK 0x3000 -#define PAGE_DEPTH_FLAG_SHIFT 12 -#define PAGE_TILE_HEIGHT_MASK 0x00c0 -#define PAGE_TILE_HEIGHT_SHIFT 6 -#define PAGE_TILE_WIDTH_MASK 0x0030 -#define PAGE_TILE_WIDTH_SHIFT 4 -#define TILE_X_FLIP 0x0004 -#define TILE_Y_FLIP 0x0008 - class spg2xx_game_state : public driver_device, public device_nvram_interface { public: spg2xx_game_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag) , device_nvram_interface(mconfig, *this) + , m_spg(*this, "spg") , m_bank(*this, "cart") , m_maincpu(*this, "maincpu") , m_screen(*this, "screen") - , m_p_ram(*this, "p_ram") - , m_p_rowscroll(*this, "p_rowscroll") - , m_p_palette(*this, "p_palette") - , m_p_spriteram(*this, "p_spriteram") , m_io_p1(*this, "P1") , m_io_p2(*this, "P2") , m_io_p3(*this, "P3") @@ -109,24 +93,30 @@ public: void spg2xx_base(machine_config &config); void spg2xx_basep(machine_config &config); - void batman(machine_config &config); + void jakks(machine_config &config); + void wireless60(machine_config &config); + void rad_skat(machine_config &config); - void init_walle(); - void init_batman(); - void init_wirels60(); - void init_rad_skat(); void init_rad_crik(); protected: void switch_bank(uint32_t bank); - uint32_t m_centered_coordinates; // this must be a vreg? - void test_centered(uint8_t *ROM); virtual void machine_start() override; - typedef delegate unsp_io_rw_delegate; - unsp_io_rw_delegate m_unsp_io_rw; + DECLARE_READ8_MEMBER(uart_rx); + + DECLARE_WRITE8_MEMBER(eeprom_w); + DECLARE_READ8_MEMBER(eeprom_r); + + DECLARE_READ16_MEMBER(jakks_porta_r); + DECLARE_WRITE16_MEMBER(wireless60_porta_w); + DECLARE_WRITE16_MEMBER(wireless60_portb_w); + DECLARE_READ16_MEMBER(wireless60_porta_r); + + DECLARE_WRITE_LINE_MEMBER(poll_controls); + required_device m_spg; required_memory_bank m_bank; // device_nvram_interface overrides @@ -135,84 +125,22 @@ protected: virtual void nvram_write(emu_file &file) override; private: - DECLARE_READ16_MEMBER(video_r); - DECLARE_WRITE16_MEMBER(video_w); - DECLARE_READ16_MEMBER(audio_r); - DECLARE_WRITE16_MEMBER(audio_w); - DECLARE_READ16_MEMBER(io_r); - DECLARE_WRITE16_MEMBER(io_w); - DECLARE_READ16_MEMBER(rom_r); - - DECLARE_WRITE_LINE_MEMBER(vii_vblank); - void check_irqs(const uint16_t changed); - inline void check_video_irq(); - - uint32_t screen_update_vii(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); - - void vii_mem(address_map &map); - - static const device_timer_id TIMER_TMB1 = 0; - static const device_timer_id TIMER_TMB2 = 1; - static const device_timer_id TIMER_SCREENPOS = 2; - virtual void machine_reset() override; - virtual void video_start() override; - virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; - uint16_t do_spg240_rad_skat_io(uint16_t what, int index); - uint16_t do_spg243_batman_io(uint16_t what, int index); - uint16_t do_spg243_wireless60_io(uint16_t what, int index); + void mem_map(address_map &map); uint32_t m_current_bank; - uint16_t m_video_regs[0x100]; - - struct - { - uint8_t r, g, b; - } - m_screenram[320 * 240]; - - bool m_hide_page0; - bool m_hide_page1; - bool m_hide_sprites; - bool m_debug_sprites; - bool m_debug_blit; - uint8_t m_sprite_index_to_debug; - - uint16_t m_io_regs[0x200]; std::unique_ptr m_serial_eeprom; uint16_t m_uart_rx_count; uint8_t m_controller_input[8]; uint8_t m_w60_controller_input; + uint16_t m_w60_porta_data; - emu_timer *m_tmb1; - emu_timer *m_tmb2; - emu_timer *m_screenpos_timer; - - void do_dma(uint32_t len); - void do_gpio(uint32_t offset); - void do_i2c(); - void spg_do_dma(uint32_t len); - - void blit(bitmap_rgb32 &bitmap, const rectangle &cliprect, uint32_t xoff, uint32_t yoff, uint32_t attr, uint32_t ctrl, uint32_t bitmap_addr, uint16_t tile); - void blit_page(bitmap_rgb32 &bitmap, const rectangle &cliprect, int depth, uint32_t bitmap_addr, uint16_t *regs); - void blit_sprite(bitmap_rgb32 &bitmap, const rectangle &cliprect, int depth, uint32_t base_addr); - void blit_sprites(bitmap_rgb32 &bitmap, const rectangle &cliprect, int depth); inline void verboselog(int n_level, const char *s_fmt, ...) ATTR_PRINTF(3, 4); - inline uint8_t expand_rgb5_to_rgb8(uint8_t val); - inline uint8_t mix_channel(uint8_t a, uint8_t b); - void mix_pixel(uint32_t offset, uint16_t rgb); - void set_pixel(uint32_t offset, uint16_t rgb); - - // devices required_device m_maincpu; required_device m_screen; - required_shared_ptr m_p_ram; - required_shared_ptr m_p_rowscroll; - required_shared_ptr m_p_palette; - required_shared_ptr m_p_spriteram; required_ioport m_io_p1; optional_ioport m_io_p2; optional_ioport m_io_p3; @@ -237,11 +165,9 @@ public: void vsmile(machine_config &config); void init_vii(); - void init_vsmile(); private: - uint16_t do_spg243_vsmile_io(uint16_t what, int index); - uint16_t do_spg243_vii_io(uint16_t what, int index); + DECLARE_WRITE16_MEMBER(vii_portb_w); DECLARE_DEVICE_IMAGE_LOAD_MEMBER(vii_cart); DECLARE_DEVICE_IMAGE_LOAD_MEMBER(vsmile_cart); @@ -252,11 +178,6 @@ private: memory_region *m_cart_rom; }; -#define VII_IRQ_ENABLE m_io_regs[0x21] -#define VII_IRQ_STATUS m_io_regs[0x22] -#define VII_VIDEO_IRQ_ENABLE m_video_regs[0x62] -#define VII_VIDEO_IRQ_STATUS m_video_regs[0x63] - #define VERBOSE_LEVEL (4) #define ENABLE_VERBOSE_LOG (1) @@ -277,557 +198,87 @@ inline void spg2xx_game_state::verboselog(int n_level, const char *s_fmt, ...) } /************************* -* Video Hardware * +* Machine Hardware * *************************/ -void spg2xx_game_state::video_start() -{ -} - -inline uint8_t spg2xx_game_state::expand_rgb5_to_rgb8(uint8_t val) -{ - uint8_t temp = val & 0x1f; - return (temp << 3) | (temp >> 2); -} - -// Perform a lerp between a and b -inline uint8_t spg2xx_game_state::mix_channel(uint8_t a, uint8_t b) -{ - uint8_t alpha = (m_video_regs[0x2a] & 3) << 6; - return ((255 - alpha) * a + alpha * b) / 255; -} - -void spg2xx_game_state::mix_pixel(uint32_t offset, uint16_t rgb) -{ - m_screenram[offset].r = mix_channel(m_screenram[offset].r, expand_rgb5_to_rgb8(rgb >> 10)); - m_screenram[offset].g = mix_channel(m_screenram[offset].g, expand_rgb5_to_rgb8(rgb >> 5)); - m_screenram[offset].b = mix_channel(m_screenram[offset].b, expand_rgb5_to_rgb8(rgb)); -} - -void spg2xx_game_state::set_pixel(uint32_t offset, uint16_t rgb) -{ - m_screenram[offset].r = expand_rgb5_to_rgb8(rgb >> 10); - m_screenram[offset].g = expand_rgb5_to_rgb8(rgb >> 5); - m_screenram[offset].b = expand_rgb5_to_rgb8(rgb); -} - -void spg2xx_game_state::blit(bitmap_rgb32 &bitmap, const rectangle &cliprect, uint32_t xoff, uint32_t yoff, uint32_t attr, uint32_t ctrl, uint32_t bitmap_addr, uint16_t tile) -{ - address_space &space = m_maincpu->space(AS_PROGRAM); - - uint32_t h = 8 << ((attr & PAGE_TILE_HEIGHT_MASK) >> PAGE_TILE_HEIGHT_SHIFT); - uint32_t w = 8 << ((attr & PAGE_TILE_WIDTH_MASK) >> PAGE_TILE_WIDTH_SHIFT); - - uint32_t yflipmask = attr & TILE_Y_FLIP ? h - 1 : 0; - uint32_t xflipmask = attr & TILE_X_FLIP ? w - 1 : 0; - - uint32_t nc = ((attr & 0x0003) + 1) << 1; - - uint32_t palette_offset = (attr & 0x0f00) >> 4; - if (m_debug_blit && VII_DEBUG_VIDEO) - { - printf("xy:%08x,%08x attr:%08x ctrl:%08x bitmap_addr:%08x tile:%04x\n", xoff, yoff, attr, ctrl, bitmap_addr, tile); - printf("hw:%d,%d f:%d,%d fm:%d,%d ncols:%d pobs:%02x ", w, h, (attr & TILE_X_FLIP) ? 1 : 0, (attr & TILE_Y_FLIP) ? 1 : 0, xflipmask, yflipmask, nc, palette_offset); - } - palette_offset >>= nc; - palette_offset <<= nc; - if (m_debug_blit && VII_DEBUG_VIDEO) - { - printf("poas:%02x\n", palette_offset); - } - - uint32_t m = bitmap_addr + nc * w*h / 16 * tile; - uint32_t bits = 0; - uint32_t nbits = 0; - - for (uint32_t y = 0; y < h; y++) - { - int yy = (yoff + (y ^ yflipmask)) & 0x1ff; - if (yy >= 0x01c0) - yy -= 0x0200; - - if (m_debug_blit && VII_DEBUG_VIDEO) - printf("%3d:\n", yy); - - for (uint32_t x = 0; x < w; x++) - { - int xx = xoff + (x ^ xflipmask); - - bits <<= nc; - if (m_debug_blit && VII_DEBUG_VIDEO) - printf(" %08x:%d ", bits, nbits); - if (nbits < nc) - { - uint16_t b = space.read_word(m++ & 0x3fffff); - b = (b << 8) | (b >> 8); - bits |= b << (nc - nbits); - nbits += 16; - if (m_debug_blit && VII_DEBUG_VIDEO) - printf("(%04x:%08x:%d) ", b, bits, nbits); - } - nbits -= nc; - - uint32_t pal = palette_offset + (bits >> 16); - if (m_debug_blit && VII_DEBUG_VIDEO) - printf("%02x:%02x:%04x ", bits >> 16, pal, bits & 0xffff); - bits &= 0xffff; - - if ((ctrl & 0x0010) && yy < 240) - xx -= (int16_t)m_p_rowscroll[yy + 15]; - - xx &= 0x01ff; - if (xx >= 0x01c0) - xx -= 0x0200; - - if (xx >= 0 && xx < 320 && yy >= 0 && yy < 240) - { - uint16_t rgb = m_p_palette[pal]; - if (m_debug_blit && VII_DEBUG_VIDEO) - printf("rgb:%04x ", rgb); - if (!(rgb & 0x8000)) - { - if (attr & 0x4000 || ctrl & 0x0100) - { - if (m_debug_blit && VII_DEBUG_VIDEO) - printf("M\n"); - mix_pixel(xx + 320 * yy, rgb); - } - else - { - if (m_debug_blit && VII_DEBUG_VIDEO) - printf("S\n"); - set_pixel(xx + 320 * yy, rgb); - } - } - else if (m_debug_blit && VII_DEBUG_VIDEO) - { - printf("X\n"); - } - } - } - } -} - -void spg2xx_game_state::blit_page(bitmap_rgb32 &bitmap, const rectangle &cliprect, int depth, uint32_t bitmap_addr, uint16_t *regs) -{ - uint32_t xscroll = regs[0]; - uint32_t yscroll = regs[1]; - uint32_t attr = regs[2]; - uint32_t ctrl = regs[3]; - uint32_t tilemap = regs[4]; - uint32_t palette_map = regs[5]; - address_space &space = m_maincpu->space(AS_PROGRAM); - - if (!(ctrl & PAGE_ENABLE_MASK)) - { - return; - } - - if (((attr & PAGE_DEPTH_FLAG_MASK) >> PAGE_DEPTH_FLAG_SHIFT) != depth) - { - return; - } - - uint32_t h = 8 << ((attr & PAGE_TILE_HEIGHT_MASK) >> PAGE_TILE_HEIGHT_SHIFT); - uint32_t w = 8 << ((attr & PAGE_TILE_WIDTH_MASK) >> PAGE_TILE_WIDTH_SHIFT); - - uint32_t hn = 256 / h; - uint32_t wn = 512 / w; - - for (uint32_t y0 = 0; y0 < hn; y0++) - { - for (uint32_t x0 = 0; x0 < wn; x0++) - { - uint16_t tile = (ctrl & PAGE_BLANK_MASK) ? 0 : space.read_word(tilemap + x0 + wn * y0); - uint16_t palette = 0; - uint32_t xx, yy; - - if (!tile) - { - continue; - } - - palette = space.read_word(palette_map + (x0 + wn * y0) / 2); - if (x0 & 1) - { - palette >>= 8; - } - - uint32_t tileattr = attr; - uint32_t tilectrl = ctrl; - if ((ctrl & 2) == 0) - { // -(1) bld(1) flip(2) pal(4) - tileattr &= ~0x000c; - tileattr |= (palette >> 2) & 0x000c; // flip - - tileattr &= ~0x0f00; - tileattr |= (palette << 8) & 0x0f00; // palette - - tilectrl &= ~0x0100; - tilectrl |= (palette << 2) & 0x0100; // blend - } - - yy = ((h*y0 - yscroll + 0x10) & 0xff) - 0x10; - xx = (w*x0 - xscroll) & 0x1ff; - - blit(bitmap, cliprect, xx, yy, tileattr, tilectrl, bitmap_addr, tile); - } - } -} - -void spg2xx_game_state::blit_sprite(bitmap_rgb32 &bitmap, const rectangle &cliprect, int depth, uint32_t base_addr) -{ - address_space &space = m_maincpu->space(AS_PROGRAM); - uint32_t bitmap_addr = 0x40 * m_video_regs[0x22]; - - uint16_t tile = space.read_word(base_addr + 0); - int16_t x = space.read_word(base_addr + 1); - int16_t y = space.read_word(base_addr + 2); - uint16_t attr = space.read_word(base_addr + 3); - - if (!tile) - { - return; - } - - if (((attr & PAGE_DEPTH_FLAG_MASK) >> PAGE_DEPTH_FLAG_SHIFT) != depth) - { - return; - } - - if (m_centered_coordinates) - { - x = 160 + x; - y = 120 - y; - - uint32_t h = 8 << ((attr & PAGE_TILE_HEIGHT_MASK) >> PAGE_TILE_HEIGHT_SHIFT); - uint32_t w = 8 << ((attr & PAGE_TILE_WIDTH_MASK) >> PAGE_TILE_WIDTH_SHIFT); - - x -= (w / 2); - y -= (h / 2) - 8; - } - - x &= 0x01ff; - y &= 0x01ff; - -#if VII_DEBUG_VIDEO - if (m_debug_sprites && machine().input().code_pressed(KEYCODE_MINUS)) - m_debug_blit = true; - blit(bitmap, cliprect, x, y, attr, 0, bitmap_addr, tile); - m_debug_blit = false; -#else - blit(bitmap, cliprect, x, y, attr, 0, bitmap_addr, tile); -#endif -} - -void spg2xx_game_state::blit_sprites(bitmap_rgb32 &bitmap, const rectangle &cliprect, int depth) +void spg2xx_game_state::switch_bank(uint32_t bank) { - if (!(m_video_regs[0x42] & 1)) - { - return; - } - -#if VII_DEBUG_VIDEO - if (!m_debug_sprites) - { -#endif - for (uint32_t n = 0; n < 256; n++) - { - blit_sprite(bitmap, cliprect, depth, 0x2c00 + 4 * n); - } -#if VII_DEBUG_VIDEO - } - else + if (bank != m_current_bank) { - blit_sprite(bitmap, cliprect, depth, 0x2c00 + 4 * m_sprite_index_to_debug); + m_current_bank = bank; + m_bank->set_entry(bank); } -#endif } -uint32_t spg2xx_game_state::screen_update_vii(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +WRITE8_MEMBER(spg2xx_game_state::eeprom_w) { - memset(&m_screenram[320 * cliprect.min_y], 0, 3 * 320 * ((cliprect.max_y - cliprect.min_y) + 1)); - - for (int i = 0; i < 4; i++) - { - if (!m_hide_page0) - blit_page(bitmap, cliprect, i, 0x40 * m_video_regs[0x20], m_video_regs + 0x10); - if (!m_hide_page1) - blit_page(bitmap, cliprect, i, 0x40 * m_video_regs[0x21], m_video_regs + 0x16); - if (!m_hide_sprites) - blit_sprites(bitmap, cliprect, i); - } - - bitmap.fill(0, cliprect); - for (int y = cliprect.min_y; y <= cliprect.max_y; y++) - { - for (int x = cliprect.min_x; x <= cliprect.max_x; x++) - { - bitmap.pix32(y, x) = (m_screenram[x + 320 * y].r << 16) | (m_screenram[x + 320 * y].g << 8) | m_screenram[x + 320 * y].b; - } - } - - return 0; + m_serial_eeprom[offset & 0x3ff] = data; } -/************************* -* Machine Hardware * -*************************/ - -void spg2xx_game_state::do_dma(uint32_t len) +READ8_MEMBER(spg2xx_game_state::eeprom_r) { - address_space &mem = m_maincpu->space(AS_PROGRAM); - uint32_t src = m_video_regs[0x70]; - uint32_t dst = m_video_regs[0x71] + 0x2c00; - - //printf("Video DMAing from %08x to %08x\n", src, dst); - for (uint32_t j = 0; j < len; j++) - { - const uint16_t word = mem.read_word(src + j); - //printf("%04x ", word); - mem.write_word(dst + j, word); - } - //printf("\n"); - - m_video_regs[0x72] = 0; - //const uint16_t old = VII_VIDEO_IRQ_ENABLE & VII_VIDEO_IRQ_STATUS; - VII_VIDEO_IRQ_STATUS |= 4; - //const uint16_t changed = old ^ (VII_VIDEO_IRQ_ENABLE & VII_VIDEO_IRQ_STATUS); - //if (changed) - //check_video_irq(); + return m_serial_eeprom[offset & 0x3ff]; } -READ16_MEMBER(spg2xx_game_state::video_r) +READ8_MEMBER(spg2xx_game_state::uart_rx) { - switch (offset) - { - case 0x38: // Current Line - verboselog(3, "video_r: Current Line: %04x\n", m_screen->vpos()); - return m_screen->vpos(); - - case 0x62: // Video IRQ Enable - verboselog(0, "video_r: Video IRQ Enable: %04x\n", VII_VIDEO_IRQ_ENABLE); - return VII_VIDEO_IRQ_ENABLE; - - case 0x63: // Video IRQ Status - verboselog(0, "video_r: Video IRQ Status: %04x\n", VII_VIDEO_IRQ_STATUS); - return VII_VIDEO_IRQ_STATUS; - - default: - verboselog(0, "video_r: Unknown register %04x = %04x\n", 0x2800 + offset, m_video_regs[offset]); - break; - } - return m_video_regs[offset]; + uint8_t val = m_controller_input[m_uart_rx_count]; + m_uart_rx_count = (m_uart_rx_count + 1) % 8; + return val; } -WRITE16_MEMBER(spg2xx_game_state::video_w) +WRITE16_MEMBER(spg2xx_game_state::wireless60_porta_w) { - switch (offset) + m_w60_porta_data = data & 0xf00; + switch (m_w60_porta_data & 0x300) { - case 0x10: case 0x16: // page 1,2 X scroll - data &= 0x01ff; - COMBINE_DATA(&m_video_regs[offset]); - break; - - case 0x11: case 0x17: // page 1,2 Y scroll - data &= 0x00ff; - COMBINE_DATA(&m_video_regs[offset]); - break; - case 0x36: // IRQ pos V - case 0x37: // IRQ pos H - data &= 0x01ff; - COMBINE_DATA(&m_video_regs[offset]); - verboselog(0, "video_w: Video IRQ Position: %04x,%04x (%04x)\n", m_video_regs[0x37], m_video_regs[0x36], 0x2800 | offset); - if (m_video_regs[0x37] < 160 && m_video_regs[0x36] < 240) - m_screenpos_timer->adjust(m_screen->time_until_pos(m_video_regs[0x36], m_video_regs[0x37] << 1)); - else - m_screenpos_timer->adjust(attotime::never); + case 0x300: + m_w60_controller_input = -1; break; - case 0x62: // Video IRQ Enable - { - verboselog(0, "video_w: Video IRQ Enable = %04x (%04x)\n", data, mem_mask); - const uint16_t old = VII_VIDEO_IRQ_ENABLE & VII_VIDEO_IRQ_STATUS; - COMBINE_DATA(&VII_VIDEO_IRQ_ENABLE); - const uint16_t changed = old ^ (VII_VIDEO_IRQ_ENABLE & VII_VIDEO_IRQ_STATUS); - if (changed) - check_video_irq(); - break; - } - - case 0x63: // Video IRQ Acknowledge - { - verboselog(0, "video_w: Video IRQ Acknowledge = %04x (%04x)\n", data, mem_mask); - const uint16_t old = VII_VIDEO_IRQ_ENABLE & VII_VIDEO_IRQ_STATUS; - VII_VIDEO_IRQ_STATUS &= ~data; - const uint16_t changed = old ^ (VII_VIDEO_IRQ_ENABLE & VII_VIDEO_IRQ_STATUS); - if (changed) - check_video_irq(); - break; - } - - case 0x70: // Video DMA Source - verboselog(0, "video_w: Video DMA Source = %04x (%04x)\n", data, mem_mask); - COMBINE_DATA(&m_video_regs[offset]); - break; - - case 0x71: // Video DMA Dest - verboselog(0, "video_w: Video DMA Dest = %04x (%04x)\n", data, mem_mask); - COMBINE_DATA(&m_video_regs[offset]); - break; - - case 0x72: // Video DMA Length - verboselog(0, "video_w: Video DMA Length = %04x (%04x)\n", data, mem_mask); - do_dma(data); + case 0x200: + m_w60_controller_input++; break; default: - verboselog(0, "video_w: Unknown register %04x = %04x (%04x)\n", 0x2800 + offset, data, mem_mask); - COMBINE_DATA(&m_video_regs[offset]); + uint16_t temp1 = m_io_p1->read(); + uint16_t temp2 = m_io_p2->read(); + uint16_t temp3 = 1 << m_w60_controller_input; + if (temp1 & temp3) m_w60_porta_data ^= 0x400; + if (temp2 & temp3) m_w60_porta_data ^= 0x800; break; } } -READ16_MEMBER(spg2xx_game_state::audio_r) +READ16_MEMBER(spg2xx_game_state::wireless60_porta_r) { - switch (offset) - { - default: - verboselog(4, "audio_r: Unknown register %04x\n", 0x3000 + offset); - break; - } - return 0; + return m_w60_porta_data; } -WRITE16_MEMBER(spg2xx_game_state::audio_w) +WRITE16_MEMBER(spg2xx_game_state::wireless60_portb_w) { - switch (offset) - { - default: - verboselog(4, "audio_w: Unknown register %04x = %04x (%04x)\n", 0x3000 + offset, data, mem_mask); - break; - } + switch_bank(data & 7); } -void spg2xx_game_state::switch_bank(uint32_t bank) +WRITE16_MEMBER(spg2xx_cart_state::vii_portb_w) { - if (bank != m_current_bank) - { - m_current_bank = bank; - m_bank->set_entry(bank); - } -} - -uint16_t spg2xx_cart_state::do_spg243_vii_io(uint16_t what, int index) -{ - if (index == 1) - { - uint32_t bank = ((what & 0x80) >> 7) | ((what & 0x20) >> 4); - switch_bank(bank); - } - return what; + if (data == 0x7c) machine().debug_break(); + switch_bank(((data & 0x80) >> 7) | ((data & 0x20) >> 4)); } -uint16_t spg2xx_cart_state::do_spg243_vsmile_io(uint16_t what, int index) +READ16_MEMBER(spg2xx_game_state::jakks_porta_r) { - // TODO: find out how vsmile accesses these GPIO regs! - return what; -} - -uint16_t spg2xx_game_state::do_spg243_batman_io(uint16_t what, int index) -{ - if (index == 0) - { - uint16_t temp = m_io_p1->read(); - what |= (temp & 0x0001) ? 0x8000 : 0; - what |= (temp & 0x0002) ? 0x4000 : 0; - what |= (temp & 0x0004) ? 0x2000 : 0; - what |= (temp & 0x0008) ? 0x1000 : 0; - what |= (temp & 0x0010) ? 0x0800 : 0; - what |= (temp & 0x0020) ? 0x0400 : 0; - what |= (temp & 0x0040) ? 0x0200 : 0; - what |= (temp & 0x0080) ? 0x0100 : 0; - } - - if (index == 2) - { - // TODO: what is here? - } - - return what; -} - -uint16_t spg2xx_game_state::do_spg240_rad_skat_io(uint16_t what, int index) -{ - // have not checked for outputs yet. - - if (index == 0) - { - what = m_io_p1->read(); - } - else if (index == 1) - { - what = m_io_p2->read(); - } - else if (index == 2) - { - what = m_io_p3->read(); - } - return what; -} - -uint16_t spg2xx_game_state::do_spg243_wireless60_io(uint16_t what, int index) -{ - if (index == 0) - { - switch (what & 0x300) - { - case 0x300: - m_w60_controller_input = -1; - break; - - case 0x200: - m_w60_controller_input++; - break; - - default: - uint16_t temp1 = m_io_p1->read(); - uint16_t temp2 = m_io_p2->read(); - uint16_t temp3 = 1 << m_w60_controller_input; - if (temp1 & temp3) what ^= 0x400; - if (temp2 & temp3) what ^= 0x800; - break; - } - } - - if (index == 1) - { - uint32_t bank = (what & 7); - switch_bank(bank); - } - - return what; -} - - -void spg2xx_game_state::do_gpio(uint32_t offset) -{ - uint32_t index = (offset - 1) / 5; - uint16_t buffer = m_io_regs[5 * index + 2]; - uint16_t dir = m_io_regs[5 * index + 3]; - uint16_t attr = m_io_regs[5 * index + 4]; - uint16_t special = m_io_regs[5 * index + 5]; - - uint16_t push = dir; - uint16_t pull = (~dir) & (~attr); - uint16_t what = (buffer & (push | pull)); - what ^= (dir & ~attr); - what &= ~special; - - if (!m_unsp_io_rw.isnull()) - what = m_unsp_io_rw(what, index); - - m_io_regs[5 * index + 1] = what; + const uint16_t temp = m_io_p1->read(); + uint16_t value = 0; + value |= (temp & 0x0001) ? 0x8000 : 0; + value |= (temp & 0x0002) ? 0x4000 : 0; + value |= (temp & 0x0004) ? 0x2000 : 0; + value |= (temp & 0x0008) ? 0x1000 : 0; + value |= (temp & 0x0010) ? 0x0800 : 0; + value |= (temp & 0x0020) ? 0x0400 : 0; + value |= (temp & 0x0040) ? 0x0200 : 0; + value |= (temp & 0x0080) ? 0x0100 : 0; + return value; } void spg2xx_game_state::nvram_default() @@ -845,291 +296,10 @@ void spg2xx_game_state::nvram_write(emu_file &file) file.write(&m_serial_eeprom[0], 0x400); } -void spg2xx_game_state::do_i2c() -{ - const uint16_t addr = ((m_io_regs[0x5b] & 0x06) << 7) | (uint8_t)m_io_regs[0x5c]; - - if (m_io_regs[0x58] & 0x40) // Serial EEPROM read - m_io_regs[0x5e] = m_serial_eeprom[addr]; - else - m_serial_eeprom[addr] = m_io_regs[0x5d]; - - m_io_regs[0x59] |= 1; -} - -void spg2xx_game_state::spg_do_dma(uint32_t len) -{ - address_space &mem = m_maincpu->space(AS_PROGRAM); - - uint32_t src = ((m_io_regs[0x101] & 0x3f) << 16) | m_io_regs[0x100]; - uint32_t dst = m_io_regs[0x103] & 0x3fff; - - //printf("CPU DMAing from %08x to %08x\n", src, dst); - for (uint32_t j = 0; j < len; j++) - { - const uint16_t word = mem.read_word(src + j); - //printf("%04x ", word); - mem.write_word(dst + j, word); - } - //printf("\n"); - - m_io_regs[0x102] = 0; -} - -READ16_MEMBER(spg2xx_game_state::io_r) -{ - static const char *const gpioregs[] = { "GPIO Data Port", "GPIO Buffer Port", "GPIO Direction Port", "GPIO Attribute Port", "GPIO IRQ/Latch Port" }; - static const char gpioports[] = { 'A', 'B', 'C' }; - - uint16_t val = m_io_regs[offset]; - - switch (offset) - { - case 0x01: case 0x06: case 0x0b: // GPIO Data Port A/B/C - do_gpio(offset); - verboselog(3, "io_r: %s %c = %04x (%04x)\n", gpioregs[(offset - 1) % 5], gpioports[(offset - 1) / 5], m_io_regs[offset], mem_mask); - val = m_io_regs[offset]; - break; - - case 0x02: case 0x03: case 0x04: case 0x05: - case 0x07: case 0x08: case 0x09: case 0x0a: - case 0x0c: case 0x0d: case 0x0e: case 0x0f: // Other GPIO regs - verboselog(3, "io_r: %s %c = %04x (%04x)\n", gpioregs[(offset - 1) % 5], gpioports[(offset - 1) / 5], m_io_regs[offset], mem_mask); - break; - - case 0x1c: // Video line counter - val = m_screen->vpos(); - verboselog(3, "io_r: Video Line = %04x (%04x)\n", val, mem_mask); - break; - - case 0x21: // IRQ Control - verboselog(3, "io_r: Controller IRQ Control = %04x (%04x)\n", val, mem_mask); - break; - - case 0x22: // IRQ Status - verboselog(3, "io_r: Controller IRQ Status = %04x (%04x)\n", val, mem_mask); - break; - - case 0x2b: - return 0x0000; - - case 0x2c: case 0x2d: // Timers? - val = machine().rand() & 0x0000ffff; - verboselog(3, "io_r: Unknown Timer %d Register = %04x (%04x)\n", offset - 0x2c, val, mem_mask); - break; - - case 0x2f: // Data Segment - val = m_maincpu->state_int(UNSP_SR) >> 10; - verboselog(3, "io_r: Data Segment = %04x (%04x)\n", val, mem_mask); - break; - - case 0x31: // Unknown, UART Status? - verboselog(3, "io_r: Unknown (UART Status?) = %04x (%04x)\n", 3, mem_mask); - val = 3; - break; - - case 0x36: // UART RX Data - val = m_controller_input[m_uart_rx_count]; - m_uart_rx_count = (m_uart_rx_count + 1) % 8; - verboselog(3, "io_r: UART RX Data = %04x (%04x)\n", val, mem_mask); - break; - - case 0x59: // I2C Status - verboselog(3, "io_r: I2C Status = %04x (%04x)\n", val, mem_mask); - break; - - case 0x5e: // I2C Data In - verboselog(3, "io_r: I2C Data In = %04x (%04x)\n", val, mem_mask); - break; - - default: - verboselog(3, "io_r: Unknown register %04x\n", 0x3d00 + offset); - break; - } - - return val; -} - -WRITE16_MEMBER(spg2xx_game_state::io_w) -{ - static const char *const gpioregs[] = { "GPIO Data Port", "GPIO Buffer Port", "GPIO Direction Port", "GPIO Attribute Port", "GPIO IRQ/Latch Port" }; - static const char gpioports[3] = { 'A', 'B', 'C' }; - - uint16_t temp = 0; - - switch (offset) - { - case 0x00: // GPIO special function select - verboselog(3, "io_w: GPIO Function Select = %04x (%04x)\n", data, mem_mask); - COMBINE_DATA(&m_io_regs[offset]); - break; - - case 0x01: case 0x06: case 0x0b: // GPIO data, port A/B/C - offset++; - // Intentional fallthrough - - case 0x02: case 0x03: case 0x04: case 0x05: // Port A - case 0x07: case 0x08: case 0x09: case 0x0a: // Port B - case 0x0c: case 0x0d: case 0x0e: case 0x0f: // Port C - verboselog(3, "io_w: %s %c = %04x (%04x)\n", gpioregs[(offset - 1) % 5], gpioports[(offset - 1) / 5], data, mem_mask); - COMBINE_DATA(&m_io_regs[offset]); - do_gpio(offset); - break; - - case 0x10: // timebase control - if ((m_io_regs[offset] & 0x0003) != (data & 0x0003)) - { - uint16_t hz = 8 << (data & 0x0003); - verboselog(3, "*** TMB1 FREQ set to %dHz\n", hz); - m_tmb1->adjust(attotime::zero, 0, attotime::from_hz(hz)); - } - if ((m_io_regs[offset] & 0x000c) != (data & 0x000c)) - { - uint16_t hz = 128 << ((data & 0x000c) >> 2); - verboselog(3, "*** TMB2 FREQ set to %dHz\n", hz); - m_tmb2->adjust(attotime::zero, 0, attotime::from_hz(hz)); - } - COMBINE_DATA(&m_io_regs[offset]); - break; - - case 0x21: // IRQ Enable - { - verboselog(3, "io_w: IRQ Control = %04x (%04x)\n", data, mem_mask); - const uint16_t old = VII_IRQ_ENABLE & VII_IRQ_STATUS; - COMBINE_DATA(&VII_IRQ_ENABLE); - const uint16_t changed = old ^ (VII_IRQ_ENABLE & VII_IRQ_STATUS); - if (changed) - check_irqs(changed); - break; - } - - case 0x22: // IRQ Acknowledge - { - verboselog(3, "io_w: IRQ Acknowledge = %04x (%04x)\n", data, mem_mask); - const uint16_t old = VII_IRQ_STATUS; - VII_IRQ_STATUS &= ~data; - const uint16_t changed = old ^ (VII_IRQ_ENABLE & VII_IRQ_STATUS); - if (changed) - check_irqs(changed); - break; - } - - case 0x2f: // Data Segment - temp = m_maincpu->state_int(UNSP_SR); - m_maincpu->set_state_int(UNSP_SR, (temp & 0x03ff) | ((data & 0x3f) << 10)); - verboselog(3, "io_w: Data Segment = %04x (%04x)\n", data, mem_mask); - break; - - case 0x31: // Unknown UART - verboselog(3, "io_w: Unknown UART = %04x (%04x)\n", data, mem_mask); - COMBINE_DATA(&m_io_regs[offset]); - break; - - case 0x32: // UART Reset - verboselog(3, "io_w: UART Reset\n"); - break; - - case 0x33: // UART Baud Rate - verboselog(3, "io_w: UART Baud Rate = %u\n", 27000000 / 16 / (0x10000 - (m_io_regs[0x34] << 8) - data)); - COMBINE_DATA(&m_io_regs[offset]); - break; - - case 0x35: // UART TX Data - verboselog(3, "io_w: UART Baud Rate = %u\n", 27000000 / 16 / (0x10000 - (data << 8) - m_io_regs[0x33])); - COMBINE_DATA(&m_io_regs[offset]); - break; - - case 0x58: // I2C Command - verboselog(3, "io_w: I2C Command = %04x (%04x)\n", data, mem_mask); - COMBINE_DATA(&m_io_regs[offset]); - do_i2c(); - break; - - case 0x59: // I2C Status / Acknowledge - verboselog(3, "io_w: I2C Acknowledge = %04x (%04x)\n", data, mem_mask); - m_io_regs[offset] &= ~data; - break; - - case 0x5a: // I2C Access Mode - verboselog(3, "io_w: I2C Access Mode = %04x (%04x)\n", data, mem_mask); - COMBINE_DATA(&m_io_regs[offset]); - break; - - case 0x5b: // I2C Device Address - verboselog(3, "io_w: I2C Device Address = %04x (%04x)\n", data, mem_mask); - COMBINE_DATA(&m_io_regs[offset]); - break; - - case 0x5c: // I2C Sub-Address - verboselog(3, "io_w: I2C Sub-Address = %04x (%04x)\n", data, mem_mask); - COMBINE_DATA(&m_io_regs[offset]); - break; - - case 0x5d: // I2C Data Out - verboselog(3, "io_w: I2C Data Out = %04x (%04x)\n", data, mem_mask); - COMBINE_DATA(&m_io_regs[offset]); - break; - - case 0x5e: // I2C Data In - verboselog(3, "io_w: I2C Data In = %04x (%04x)\n", data, mem_mask); - COMBINE_DATA(&m_io_regs[offset]); - break; - - case 0x5f: // I2C Controller Mode - verboselog(3, "io_w: I2C Controller Mode = %04x (%04x)\n", data, mem_mask); - COMBINE_DATA(&m_io_regs[offset]); - break; - - case 0x100: // DMA Source (L) - case 0x101: // DMA Source (H) - case 0x103: // DMA Destination - COMBINE_DATA(&m_io_regs[offset]); - break; - - case 0x102: // DMA Length - spg_do_dma(data); - break; - - default: - verboselog(3, "io_w: Unknown register %04x = %04x (%04x)\n", 0x3d00 + offset, data, mem_mask); - COMBINE_DATA(&m_io_regs[offset]); - break; - } -} - -/* -WRITE16_MEMBER( spg2xx_game_state::rowscroll_w ) -{ - switch(offset) - { - default: - verboselog(0, "rowscroll_w: %04x = %04x (%04x)\n", 0x2900 + offset, data, mem_mask); - break; - } -} - -WRITE16_MEMBER( spg2xx_game_state::spriteram_w ) -{ - switch(offset) - { - default: - verboselog(0, "spriteram_w: %04x = %04x (%04x)\n", 0x2c00 + offset, data, mem_mask); - break; - } -} -*/ - -void spg2xx_game_state::vii_mem(address_map &map) +void spg2xx_game_state::mem_map(address_map &map) { map(0x000000, 0x3fffff).bankr("cart"); - - map(0x000000, 0x0027ff).ram().share("p_ram"); - map(0x002800, 0x0028ff).rw(FUNC(spg2xx_game_state::video_r), FUNC(spg2xx_game_state::video_w)); - map(0x002900, 0x002aff).ram().share("p_rowscroll"); - map(0x002b00, 0x002bff).ram().share("p_palette"); - map(0x002c00, 0x002fff).ram().share("p_spriteram"); - map(0x003000, 0x0037ff).rw(FUNC(spg2xx_game_state::audio_r), FUNC(spg2xx_game_state::audio_w)); - map(0x003d00, 0x003eff).rw(FUNC(spg2xx_game_state::io_r), FUNC(spg2xx_game_state::io_w)); + map(0x000000, 0x003fff).m(m_spg, FUNC(spg2xx_device::map)); } static INPUT_PORTS_START( vii ) @@ -1359,58 +529,6 @@ static INPUT_PORTS_START( rad_crik ) PORT_BIT( 0xffff, IP_ACTIVE_LOW, IPT_UNKNOWN ) INPUT_PORTS_END -void spg2xx_game_state::test_centered(uint8_t *ROM) -{ - if (ROM[0x3cd808] == 0x99 && - ROM[0x3cd809] == 0x99 && - ROM[0x3cd80a] == 0x83 && - ROM[0x3cd80b] == 0x5e && - ROM[0x3cd80c] == 0x52 && - ROM[0x3cd80d] == 0x6b && - ROM[0x3cd80e] == 0x78 && - ROM[0x3cd80f] == 0x7f) - { - m_centered_coordinates = 0; - } -} - -void spg2xx_game_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) -{ - switch (id) - { - case TIMER_TMB1: - { - const uint16_t old = (VII_IRQ_ENABLE & VII_IRQ_STATUS); - VII_IRQ_STATUS |= 1; - const uint16_t changed = old ^ (VII_IRQ_ENABLE & VII_IRQ_STATUS); - if (changed) - check_irqs(changed); - break; - } - case TIMER_TMB2: - { - const uint16_t old = m_io_regs[0x22] & m_io_regs[0x21]; - VII_IRQ_STATUS |= 2; - const uint16_t changed = old ^ (VII_IRQ_ENABLE & VII_IRQ_STATUS); - if (changed) - check_irqs(changed); - break; - } - case TIMER_SCREENPOS: - { - const uint16_t old = VII_VIDEO_IRQ_ENABLE & VII_VIDEO_IRQ_STATUS; - VII_VIDEO_IRQ_STATUS |= 2; - const uint16_t changed = old ^ (VII_VIDEO_IRQ_ENABLE & VII_VIDEO_IRQ_STATUS); - if (changed) - { - check_video_irq(); - } - m_screen->update_partial(m_screen->vpos()); - break; - } - } -} - void spg2xx_cart_state::machine_start() { spg2xx_game_state::machine_start(); @@ -1427,14 +545,6 @@ void spg2xx_cart_state::machine_start() void spg2xx_game_state::machine_start() { - m_tmb1 = timer_alloc(TIMER_TMB1); - m_tmb2 = timer_alloc(TIMER_TMB2); - m_tmb1->adjust(attotime::never); - m_tmb2->adjust(attotime::never); - - m_screenpos_timer = timer_alloc(TIMER_SCREENPOS); - m_screenpos_timer->adjust(attotime::never); - m_bank->configure_entries(0, ceilf((float)memregion("maincpu")->bytes() / 0x800000), memregion("maincpu")->base(), 0x800000); m_bank->set_entry(0); @@ -1443,8 +553,6 @@ void spg2xx_game_state::machine_start() void spg2xx_game_state::machine_reset() { - memset(m_video_regs, 0, 0x100 * sizeof(m_video_regs[0])); - memset(m_io_regs, 0, 0x200 * sizeof(m_io_regs[0])); m_current_bank = 0; m_controller_input[0] = 0; @@ -1452,38 +560,14 @@ void spg2xx_game_state::machine_reset() m_controller_input[6] = 0xff; m_controller_input[7] = 0; m_w60_controller_input = -1; - - m_video_regs[0x36] = 0xffff; - m_video_regs[0x37] = 0xffff; - - m_hide_page0 = false; - m_hide_page1 = false; - m_hide_sprites = false; - m_debug_sprites = false; - m_debug_blit = false; - m_sprite_index_to_debug = 0; + m_w60_porta_data = 0; } -WRITE_LINE_MEMBER(spg2xx_game_state::vii_vblank) +WRITE_LINE_MEMBER(spg2xx_game_state::poll_controls) { if (!state) return; -#if VII_DEBUG_VIDEO - if (machine().input().code_pressed_once(KEYCODE_5)) - m_hide_page0 = !m_hide_page0; - if (machine().input().code_pressed_once(KEYCODE_6)) - m_hide_page1 = !m_hide_page1; - if (machine().input().code_pressed_once(KEYCODE_7)) - m_hide_sprites = !m_hide_sprites; - if (machine().input().code_pressed_once(KEYCODE_8)) - m_debug_sprites = !m_debug_sprites; - if (machine().input().code_pressed_once(KEYCODE_9)) - m_sprite_index_to_debug--; - if (machine().input().code_pressed_once(KEYCODE_0)) - m_sprite_index_to_debug++; -#endif - int32_t x = m_io_motionx ? ((int32_t)m_io_motionx->read() - 0x200) : 0; int32_t y = m_io_motiony ? ((int32_t)m_io_motiony->read() - 0x200) : 0; int32_t z = m_io_motionz ? ((int32_t)m_io_motionz->read() - 0x200) : 0; @@ -1501,59 +585,6 @@ WRITE_LINE_MEMBER(spg2xx_game_state::vii_vblank) m_controller_input[7] = 0; m_uart_rx_count = 0; - - const uint16_t old = VII_VIDEO_IRQ_ENABLE & VII_VIDEO_IRQ_STATUS; - VII_VIDEO_IRQ_STATUS |= 1; - const uint16_t changed = old ^ (VII_VIDEO_IRQ_ENABLE & VII_VIDEO_IRQ_STATUS); - if (changed) - check_video_irq(); - - // For now, manually trigger controller IRQs - if (VII_IRQ_ENABLE & 0x2100) - { - VII_IRQ_STATUS |= 0x0100; - m_maincpu->set_input_line(UNSP_IRQ3_LINE, ASSERT_LINE); - } -} - -void spg2xx_game_state::check_video_irq() -{ - m_maincpu->set_input_line(UNSP_IRQ0_LINE, (VII_VIDEO_IRQ_STATUS & VII_VIDEO_IRQ_ENABLE) ? ASSERT_LINE : CLEAR_LINE); -} - -void spg2xx_game_state::check_irqs(const uint16_t changed) -{ - // { - // verboselog(0, "audio 1 IRQ\n"); - // m_maincpu->set_input_line(UNSP_IRQ1_LINE, ASSERT_LINE); - // } - if (changed & 0x0c00) // Timer A, Timer B IRQ - { - m_maincpu->set_input_line(UNSP_IRQ2_LINE, (VII_IRQ_ENABLE & VII_IRQ_STATUS & 0x0c00) ? ASSERT_LINE : CLEAR_LINE); - } - - if (changed & 0x2100) // UART, ADC IRQ - m_maincpu->set_input_line(UNSP_IRQ3_LINE, (VII_IRQ_ENABLE & VII_IRQ_STATUS & 0x2100) ? ASSERT_LINE : CLEAR_LINE); - - // { - // verboselog(0, "audio 4 IRQ\n"); - // m_maincpu->set_input_line(UNSP_IRQ4_LINE, ASSERT_LINE); - // } - - if (changed & 0x1200) // External IRQ - { - m_maincpu->set_input_line(UNSP_IRQ5_LINE, (VII_IRQ_ENABLE & VII_IRQ_STATUS & 0x1200) ? ASSERT_LINE : CLEAR_LINE); - } - - if (changed & 0x0070) // 1024Hz, 2048Hz, 4096Hz IRQ - { - m_maincpu->set_input_line(UNSP_IRQ6_LINE, (VII_IRQ_ENABLE & VII_IRQ_STATUS & 0x0070) ? ASSERT_LINE : CLEAR_LINE); - } - - if (changed & 0x008b) // TMB1, TMB2, 4Hz, key change IRQ - { - m_maincpu->set_input_line(UNSP_IRQ7_LINE, (VII_IRQ_ENABLE & VII_IRQ_STATUS & 0x008b) ? ASSERT_LINE : CLEAR_LINE); - } } DEVICE_IMAGE_LOAD_MEMBER(spg2xx_cart_state, vii_cart) @@ -1569,8 +600,6 @@ DEVICE_IMAGE_LOAD_MEMBER(spg2xx_cart_state, vii_cart) m_cart->rom_alloc(size, GENERIC_ROM16_WIDTH, ENDIANNESS_LITTLE); m_cart->common_load_rom(m_cart->get_rom_base(), size, "rom"); - test_centered(m_cart->get_rom_base()); - return image_init_result::PASS; } @@ -1587,17 +616,18 @@ DEVICE_IMAGE_LOAD_MEMBER(spg2xx_cart_state, vsmile_cart) void spg2xx_game_state::spg2xx_base(machine_config &config) { UNSP(config, m_maincpu, XTAL(27'000'000)); - m_maincpu->set_addrmap(AS_PROGRAM, &spg2xx_game_state::vii_mem); + m_maincpu->set_addrmap(AS_PROGRAM, &spg2xx_game_state::mem_map); SCREEN(config, m_screen, SCREEN_TYPE_RASTER); m_screen->set_refresh_hz(60); - m_screen->set_size(320, 240); + m_screen->set_size(320, 262); m_screen->set_visarea(0, 320-1, 0, 240-1); - m_screen->set_screen_update(FUNC(spg2xx_game_state::screen_update_vii)); - //m_screen->set_video_attributes(VIDEO_UPDATE_SCANLINE); - m_screen->screen_vblank().set(FUNC(spg2xx_game_state::vii_vblank)); + m_screen->set_screen_update("spg", FUNC(spg2xx_device::screen_update)); + m_screen->screen_vblank().set(m_spg, FUNC(spg2xx_device::vblank)); + m_screen->screen_vblank().append(FUNC(spg2xx_game_state::poll_controls)); - PALETTE(config, "palette", 32768); + SPG2XX(config, m_spg, XTAL(27'000'000), m_maincpu, m_screen); + m_spg->uart_rx().set(FUNC(spg2xx_game_state::uart_rx)); } void spg2xx_game_state::spg2xx_basep(machine_config &config) @@ -1608,11 +638,12 @@ void spg2xx_game_state::spg2xx_basep(machine_config &config) m_screen->set_size(320, 312); } - void spg2xx_cart_state::vii(machine_config &config) { spg2xx_base(config); + m_spg->portb_out().set(FUNC(spg2xx_cart_state::vii_portb_w)); + GENERIC_CARTSLOT(config, m_cart, generic_plain_slot, "vii_cart"); m_cart->set_width(GENERIC_ROM16_WIDTH); m_cart->set_device_load(device_image_load_delegate(&spg2xx_cart_state::device_image_load_vii_cart, this)); @@ -1631,35 +662,30 @@ void spg2xx_cart_state::vsmile(machine_config &config) SOFTWARE_LIST(config, "cart_list").set_original("vsmile_cart"); } -void spg2xx_game_state::batman(machine_config &config) +void spg2xx_game_state::wireless60(machine_config &config) { spg2xx_base(config); - I2CMEM(config, "i2cmem", 0).set_data_size(0x200); -} - - -void spg2xx_cart_state::init_vii() -{ - m_unsp_io_rw = unsp_io_rw_delegate(&spg2xx_cart_state::do_spg243_vii_io, this); - m_centered_coordinates = 1; -} -void spg2xx_cart_state::init_vsmile() -{ - m_unsp_io_rw = unsp_io_rw_delegate(&spg2xx_cart_state::do_spg243_vsmile_io, this); - m_centered_coordinates = 1; + m_spg->porta_out().set(FUNC(spg2xx_game_state::wireless60_porta_w)); + m_spg->portb_out().set(FUNC(spg2xx_game_state::wireless60_portb_w)); + m_spg->porta_in().set(FUNC(spg2xx_game_state::wireless60_porta_r)); } -void spg2xx_game_state::init_batman() +void spg2xx_game_state::jakks(machine_config &config) { - m_unsp_io_rw = unsp_io_rw_delegate(&spg2xx_game_state::do_spg243_batman_io, this); - m_centered_coordinates = 1; + spg2xx_base(config); + m_spg->porta_in().set(FUNC(spg2xx_cart_state::jakks_porta_r)); + I2CMEM(config, "i2cmem", 0).set_data_size(0x200); } -void spg2xx_game_state::init_rad_skat() +void spg2xx_game_state::rad_skat(machine_config &config) { - m_unsp_io_rw = unsp_io_rw_delegate(&spg2xx_game_state::do_spg240_rad_skat_io, this); - m_centered_coordinates = 1; + spg2xx_base(config); + m_spg->porta_in().set_ioport("P1"); + m_spg->portb_in().set_ioport("P2"); + m_spg->portc_in().set_ioport("P3"); + m_spg->eeprom_w().set(FUNC(spg2xx_game_state::eeprom_w)); + m_spg->eeprom_r().set(FUNC(spg2xx_game_state::eeprom_r)); } READ16_MEMBER(spg2xx_game_state::rad_crik_hack_r) @@ -1673,25 +699,8 @@ READ16_MEMBER(spg2xx_game_state::rad_crik_hack_r) void spg2xx_game_state::init_rad_crik() { - m_maincpu->space(AS_PROGRAM).install_writeonly(0x5800, 0x5bff, m_p_spriteram); // is this due to a CPU or DMA bug? 5800 == 2c00 << 1 - // not 100% sure what this is waiting on, could be eeprom as it seems to end up here frequently during the eeprom test, patch running code, not ROM, so that checksum can still pass m_maincpu->space(AS_PROGRAM).install_read_handler(0xf851, 0xf851, read16_delegate(FUNC(spg2xx_game_state::rad_crik_hack_r),this)); - - m_unsp_io_rw = unsp_io_rw_delegate(&spg2xx_game_state::do_spg240_rad_skat_io, this); - m_centered_coordinates = 1; -} - -void spg2xx_game_state::init_walle() -{ - m_unsp_io_rw = unsp_io_rw_delegate(&spg2xx_game_state::do_spg243_batman_io, this); - m_centered_coordinates = 0; -} - -void spg2xx_game_state::init_wirels60() -{ - m_unsp_io_rw = unsp_io_rw_delegate(&spg2xx_game_state::do_spg243_wireless60_io, this); - m_centered_coordinates = 1; } ROM_START( vii ) @@ -1881,35 +890,32 @@ ROM_START( wrlshunt ) ROM_LOAD16_WORD_SWAP( "wireless.bin", 0x0000, 0x8000000, CRC(a6ecc20e) SHA1(3645f23ba2bb218e92d4560a8ae29dddbaabf796) ) ROM_END -// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS +// year, name, parent, compat, machine, input, class, init, company, fullname, flags // VTech systems -CONS( 2005, vsmile, 0, 0, vsmile, vsmile, spg2xx_cart_state, init_vsmile, "VTech", "V.Smile (US)", MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING ) -CONS( 2005, vsmileg, vsmile, 0, vsmile, vsmile, spg2xx_cart_state, init_vsmile, "VTech", "V.Smile (Germany)", MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING ) -CONS( 2005, vsmilef, vsmile, 0, vsmile, vsmile, spg2xx_cart_state, init_vsmile, "VTech", "V.Smile (France)", MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING ) -CONS( 2005, vsmileb, 0, 0, vsmile, vsmile, spg2xx_cart_state, init_vsmile, "VTech", "V.Smile Baby (US)", MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING ) +CONS( 2005, vsmile, 0, 0, vsmile, vsmile, spg2xx_cart_state, empty_init, "VTech", "V.Smile (US)", MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING ) +CONS( 2005, vsmileg, vsmile, 0, vsmile, vsmile, spg2xx_cart_state, empty_init, "VTech", "V.Smile (Germany)", MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING ) +CONS( 2005, vsmilef, vsmile, 0, vsmile, vsmile, spg2xx_cart_state, empty_init, "VTech", "V.Smile (France)", MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING ) +CONS( 2005, vsmileb, 0, 0, vsmile, vsmile, spg2xx_cart_state, empty_init, "VTech", "V.Smile Baby (US)", MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING ) // Jungle's Soft TV games -CONS( 2007, vii, 0, 0, vii, vii, spg2xx_cart_state, init_vii, "Jungle's Soft / KenSingTon / Siatronics", "Vii", MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING ) // some games run, others crash - -CONS( 2010, zone60, 0, 0, spg2xx_base, wirels60, spg2xx_game_state, init_wirels60, "Jungle's Soft / Ultimate Products (HK) Ltd", "Zone 60", MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS ) -CONS( 2010, wirels60, 0, 0, spg2xx_base, wirels60, spg2xx_game_state, init_wirels60, "Jungle's Soft / Kids Station Toys Inc", "Wireless 60", MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS ) +CONS( 2007, vii, 0, 0, vii, vii, spg2xx_cart_state, empty_init, "Jungle's Soft / KenSingTon / Siatronics", "Vii", MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS ) // motion controls are awkward, but playable for the most part +CONS( 2010, zone60, 0, 0, wireless60, wirels60, spg2xx_game_state, empty_init, "Jungle's Soft / Ultimate Products (HK) Ltd", "Zone 60", MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS ) +CONS( 2010, wirels60, 0, 0, wireless60, wirels60, spg2xx_game_state, empty_init, "Jungle's Soft / Kids Station Toys Inc", "Wireless 60", MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS ) // JAKKS Pacific Inc TV games -CONS( 2004, batmantv, 0, 0, batman, batman, spg2xx_game_state, init_batman, "JAKKS Pacific Inc / HotGen Ltd", "The Batman", MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS ) -CONS( 2008, walle, 0, 0, batman, walle, spg2xx_game_state, init_walle, "JAKKS Pacific Inc", "Wall-E", MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS ) +CONS( 2004, batmantv, 0, 0, jakks, batman, spg2xx_game_state, empty_init, "JAKKS Pacific Inc / HotGen Ltd", "The Batman", MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS ) +CONS( 2008, walle, 0, 0, jakks, walle, spg2xx_game_state, empty_init, "JAKKS Pacific Inc", "Wall-E", MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS ) // Radica TV games -CONS( 2006, rad_skat, 0, 0, spg2xx_base, rad_skat, spg2xx_game_state, init_rad_skat, "Radica", "Play TV Skateboarder (NTSC)", MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS ) -CONS( 2006, rad_skatp, rad_skat,0, spg2xx_basep,rad_skatp,spg2xx_game_state, init_rad_skat, "Radica", "Connectv Skateboarder (PAL)", MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS ) - -CONS( 2006, rad_crik, 0, 0, spg2xx_basep,rad_crik, spg2xx_game_state, init_rad_crik, "Radica", "Connectv Cricket (PAL)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) // Version 3.00 20/03/06 is listed in INTERNAL TEST - -CONS( 2007, rad_sktv, 0, 0, spg2xx_base, rad_sktv, spg2xx_game_state, init_rad_skat, "Radica", "Skannerz TV", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) - +CONS( 2006, rad_skat, 0, 0, rad_skat, rad_skat, spg2xx_game_state, empty_init, "Radica", "Play TV Skateboarder (NTSC)", MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS ) +CONS( 2006, rad_skatp, rad_skat, 0, rad_skat, rad_skatp, spg2xx_game_state, empty_init, "Radica", "Connectv Skateboarder (PAL)", MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS ) +CONS( 2006, rad_crik, 0, 0, rad_skat, rad_crik, spg2xx_game_state, empty_init, "Radica", "Connectv Cricket (PAL)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) // Version 3.00 20/03/06 is listed in INTERNAL TEST +CONS( 2007, rad_sktv, 0, 0, rad_skat, rad_sktv, spg2xx_game_state, empty_init, "Radica", "Skannerz TV", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) // might not fit here. First 0x8000 bytes are blank (not too uncommon for these) then rest of rom looks like it's probably encrypted at least -CONS( 2009, zone40, 0, 0, spg2xx_base, wirels60, spg2xx_game_state, init_wirels60, "Jungle Soft / Ultimate Products (HK) Ltd", "Zone 40", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) -// might not fit here, NAND dump, has internal bootstrap at least, see above. -CONS( 2010, wlsair60, 0, 0, spg2xx_base, wirels60, spg2xx_game_state, init_wirels60, "Jungle Soft / Kids Station Toys Inc", "Wireless Air 60", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) -CONS( 2011, wrlshunt, 0, 0, spg2xx_base, wirels60, spg2xx_game_state, init_wirels60, "Hamy / Kids Station Toys Inc", "Wireless: Hunting Video Game System", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) +CONS( 2009, zone40, 0, 0, spg2xx_base, wirels60, spg2xx_game_state, empty_init, "Jungle Soft / Ultimate Products (HK) Ltd", "Zone 40", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) + +// NAND dumps w/ internal bootstrap. Almost certainly do not fit in this driver, as the SPG2xx can only address up to 4Mwords. +CONS( 2010, wlsair60, 0, 0, spg2xx_base, wirels60, spg2xx_game_state, empty_init, "Jungle Soft / Kids Station Toys Inc", "Wireless Air 60", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) +CONS( 2011, wrlshunt, 0, 0, spg2xx_base, wirels60, spg2xx_game_state, empty_init, "Hamy / Kids Station Toys Inc", "Wireless: Hunting Video Game System", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) -- cgit v1.2.3 From 395d6a93b1e0b3eb9c9d125a95c3f7d0f634b5f9 Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Sun, 7 Oct 2018 15:37:23 +0200 Subject: mb87030: add new SCSI controller (nw) --- scripts/src/machine.lua | 12 + src/devices/machine/mb87030.cpp | 797 ++++++++++++++++++++++++++++++++++++++++ src/devices/machine/mb87030.h | 220 +++++++++++ 3 files changed, 1029 insertions(+) create mode 100644 src/devices/machine/mb87030.cpp create mode 100644 src/devices/machine/mb87030.h (limited to 'scripts/src') diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua index 32f12d96b0b..1c0ecc07b59 100644 --- a/scripts/src/machine.lua +++ b/scripts/src/machine.lua @@ -1645,6 +1645,18 @@ if (MACHINES["MB8421"]~=null) then } end +--------------------------------------------------- +-- +--@src/devices/machine/mb87030.h,MACHINES["MB87030"] = true +--------------------------------------------------- + +if (MACHINES["MB87030"]~=null) then + files { + MAME_DIR .. "src/devices/machine/mb87030.cpp", + MAME_DIR .. "src/devices/machine/mb87030.h", + } +end + --------------------------------------------------- -- --@src/devices/machine/mb87078.h,MACHINES["MB87078"] = true diff --git a/src/devices/machine/mb87030.cpp b/src/devices/machine/mb87030.cpp new file mode 100644 index 00000000000..39e306866a6 --- /dev/null +++ b/src/devices/machine/mb87030.cpp @@ -0,0 +1,797 @@ +// license:BSD-3-Clause +// copyright-holders:Sven Schnelle + +#include "emu.h" +#define VERBOSE 0 +#include "logmacro.h" +#include "mb87030.h" + +DEFINE_DEVICE_TYPE(MB87030, mb87030_device, "MB87030", "Fujitsu MB87030 SCSI controller") + +mb87030_device::mb87030_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + mb87030_device(mconfig, MB87030, tag, owner, clock) +{ + +} + +mb87030_device::mb87030_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : + nscsi_device(mconfig, type, tag, owner, clock), + m_irq_handler(*this), + m_dreq_handler(*this) +{ + +} + +void mb87030_device::map(address_map &map) +{ + map(0x00, 0x00).rw(FUNC(mb87030_device::bdid_r), FUNC(mb87030_device::bdid_w)); + map(0x01, 0x01).rw(FUNC(mb87030_device::sctl_r), FUNC(mb87030_device::sctl_w)); + map(0x02, 0x02).rw(FUNC(mb87030_device::scmd_r), FUNC(mb87030_device::scmd_w)); + map(0x03, 0x03).rw(FUNC(mb87030_device::tmod_r), FUNC(mb87030_device::tmod_w)); + map(0x04, 0x04).rw(FUNC(mb87030_device::ints_r), FUNC(mb87030_device::ints_w)); + map(0x05, 0x05).rw(FUNC(mb87030_device::psns_r), FUNC(mb87030_device::sdgc_w)); + map(0x06, 0x06).r(FUNC(mb87030_device::ssts_r)); + map(0x07, 0x07).r(FUNC(mb87030_device::serr_r)); + map(0x08, 0x08).rw(FUNC(mb87030_device::pctl_r), FUNC(mb87030_device::pctl_w)); + map(0x09, 0x09).r(FUNC(mb87030_device::mbc_r)); + map(0x0a, 0x0a).rw(FUNC(mb87030_device::dreg_r), FUNC(mb87030_device::dreg_w)); + map(0x0b, 0x0b).rw(FUNC(mb87030_device::temp_r), FUNC(mb87030_device::temp_w)); + map(0x0c, 0x0c).rw(FUNC(mb87030_device::tch_r), FUNC(mb87030_device::tch_w)); + map(0x0d, 0x0d).rw(FUNC(mb87030_device::tcm_r), FUNC(mb87030_device::tcm_w)); + map(0x0e, 0x0e).rw(FUNC(mb87030_device::tcl_r), FUNC(mb87030_device::tcl_w)); + map(0x0f, 0x0f).rw(FUNC(mb87030_device::exbf_r), FUNC(mb87030_device::exbf_w)); +} + +void mb87030_device::device_reset() +{ + m_bdid = 0; + m_sctl = SCTL_RESET_AND_DISABLE; + m_scmd = 0; + m_tmod = 0; + m_ints = 0; + m_sdgc = 0; + m_ssts = 0; + m_serr = 0; + m_pctl = 0; + m_mbc = 0; + m_dreg = 0; + m_temp = 0; + m_tch = 0; + m_tcm = 0; + m_tc = 0; + m_exbf = 0; + m_fifo.clear(); + scsi_bus->ctrl_wait(scsi_refid, S_SEL|S_BSY|S_RST, S_ALL); + update_state(State::Idle, 0); + scsi_set_ctrl(0, S_ALL); + scsi_bus->data_w(scsi_refid, 0); + update_ssts(); + update_ints(); +} + +auto mb87030_device::get_state_name(State state) const +{ + switch(state) { + case State::Idle: + return "Idle"; + case State::ArbitrationWaitBusFree: + return "ArbitrationWaitBusFree"; + case State::ArbitrationAssertBSY: + return "ArbitrationAssertBSY"; + case State::ArbitrationWait: + return "ArbitrationWait"; + case State::ArbitrationAssertSEL: + return "ArbitrationAssertSEL"; + case State::ArbitrationDeAssertBSY: + return "ArbitrationDeAssertBSY"; + case State::SelectionWaitBusFree: + return "SelectionWaitBusFree"; + case State::SelectionWaitBSY: + return "SelectionWaitBSY"; + case State::SelectionAssertSEL: + return "SelectionAssertSEL"; + case State::Selection: + return "Selection"; + case State::TransferWaitReq: + return "TransferWaitReq"; + case State::TransferSendAck: + return "TransferSendAck"; + case State::TransferSendData: + return "TransferSendData"; + case State::TransferSendDataDMAReq: + return "TransferSendDataDMAReq"; + case State::TransferSendDataDMAResp: + return "TransferSendDataDMAResp"; + case State::TransferRecvData: + return "TransferRecvData"; + case State::TransferRecvDataDMAReq: + return "TransferRecvDataDMAReq"; + case State::TransferRecvDataDMAResp: + return "TransferRecvDataDMAResp"; + + case State::TransferWaitDeassertREQ: + return "TransferWaitDeassertREQ"; + case State::TransferDeassertACK: + return "TransferDeassertACK"; + } + return "Unknown state"; +} + +void mb87030_device::update_state(mb87030_device::State new_state, int delay, int timeout) +{ + LOG("new state: %s -> %s (delay %d, timeout %d)\n", get_state_name(m_state), + get_state_name(new_state), delay, timeout); + m_state = new_state; + if (delay) + m_delay_timer->adjust(clocks_to_attotime(delay)); + else + m_delay_timer->reset(); + if (timeout) + m_timer->adjust(clocks_to_attotime(timeout)); + else + m_timer->reset(); +} + +void mb87030_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + switch(id) { + case TimerId::Delay: + m_delay_timer->reset(); + step(false); + break; + case TimerId::Timeout: + m_timer->reset(); + step(true); + break; + } +} + +void mb87030_device::scsi_command_complete() +{ + m_ints |= INTS_COMMAND_COMPLETE; + m_ssts &= ~(SSTS_SPC_BUSY|SSTS_XFER_IN_PROGRESS); + update_ints(); + update_state(State::Idle); +} + +void mb87030_device::scsi_disconnect_timeout() +{ + scsi_set_ctrl(0, S_ALL); + scsi_bus->data_w(scsi_refid, 0); + m_ints = INTS_SPC_TIMEOUT; + update_ints(); + update_state(State::Idle); +} + +void mb87030_device::scsi_disconnect() +{ + LOG("%s: m_tc %d\n", __FUNCTION__, m_tc); + m_ssts &= ~(SSTS_INIT_CONNECTED|SSTS_TARG_CONNECTED|SSTS_SPC_BUSY|SSTS_XFER_IN_PROGRESS); + m_ints = INTS_DISCONNECTED; + if (m_pctl & PCTL_BUS_FREE_IE) { + LOG("disconnect IE\n"); + m_ints |= INTS_DISCONNECTED; + } + update_ints(); + update_state(State::Idle); +} + +void mb87030_device::scsi_set_ctrl(uint32_t value, uint32_t mask) +{ + if (m_sctl & SCTL_DIAG_MODE) { + m_scsi_ctrl &= ~mask; + m_scsi_ctrl |= value; + logerror("update m_scsi_ctrl: %02X%s%s%s%s%s%s\n", m_scsi_ctrl, + (m_scsi_ctrl & S_REQ) ? " REQ" : "", + (m_scsi_ctrl & S_ACK) ? " ACK" : "", + (m_scsi_ctrl & S_BSY) ? " BSY" : "", + (m_scsi_ctrl & S_MSG) ? " MSG" : "", + (m_scsi_ctrl & S_CTL) ? " CTL" : "", + (m_scsi_ctrl & S_INP) ? " INP" : ""); + } else { + scsi_bus->ctrl_w(scsi_refid, value, mask); + } +} + +uint32_t mb87030_device::scsi_get_ctrl(void) +{ + if (m_sctl & SCTL_DIAG_MODE) { + uint32_t ret = 0; + if ((m_sdgc & SDGC_DIAG_IO) || (m_scsi_ctrl & S_INP)) + ret |= S_INP; + if ((m_sdgc & SDGC_DIAG_CD) || (m_scsi_ctrl & S_CTL)) + ret |= S_CTL; + if ((m_sdgc & SDGC_DIAG_MSG) || (m_scsi_ctrl & S_MSG)) + ret |= S_MSG; + if ((m_sdgc & SDGC_DIAG_BSY) || (m_scsi_ctrl & S_BSY)) + ret |= S_BSY; + if ((m_sdgc & SDGC_DIAG_ACK) || (m_scsi_ctrl & S_ACK)) + ret |= S_ACK; + if ((m_sdgc & SDGC_DIAG_REQ) || (m_scsi_ctrl & S_REQ)) + ret |= S_REQ; + if (m_scsi_ctrl & S_SEL) + ret |= S_SEL; + if (m_scsi_ctrl & S_ATN) + ret |= S_ATN; + + return ret; + } else { + return scsi_bus->ctrl_r(); + } +} + +void mb87030_device::step(bool timeout) +{ + uint32_t ctrl = scsi_get_ctrl(); + uint32_t data = scsi_bus->data_r(); + + LOG("%s: %d %s,%s data %02X ctrl %02X TC %d\n", __FUNCTION__, + scsi_refid, get_state_name(m_state), + timeout ? " timeout" : "", data, + ctrl, m_tc); + + if (m_sctl & SCTL_RESET_AND_DISABLE && m_state != State::Idle) { + scsi_set_ctrl(0, S_ALL); + update_state(State::Idle); + return; + } + + + if ((m_ssts & SSTS_INIT_CONNECTED) && !(ctrl & S_BSY)) { + LOG("SCSI disconnect\n"); + scsi_disconnect(); + scsi_set_ctrl(0, S_ALL); + } + + + switch(m_state) { + case State::Idle: + + if (ctrl == 0 && (m_pctl & PCTL_BUS_FREE_IE)) { + m_ints |= INTS_DISCONNECTED; + update_ints(); + } + break; + case State::ArbitrationWaitBusFree: + if (!(ctrl & (S_BSY|S_SEL))) + update_state(State::ArbitrationAssertBSY, 1); + + break; + case State::ArbitrationAssertBSY: + scsi_set_ctrl(S_BSY, S_BSY); + scsi_bus->data_w(scsi_refid, (1 << m_bdid)); + update_state(State::ArbitrationWait, 1); + break; + + case State::ArbitrationWait: + + for (int id = (2 << m_bdid); id <= 0x80; id <<= 1) { + LOG("check %d\n", id); + if (data & id) { + LOG("arbitration lost, winner %d\n", id); + scsi_disconnect_timeout(); + break; + } + } + LOG("Arbitration won\n"); + update_state(State::ArbitrationAssertSEL, 1); + break; + + case State::ArbitrationAssertSEL: + scsi_set_ctrl(S_SEL, S_SEL); + update_state(State::ArbitrationDeAssertBSY, 1); + break; + + case State::ArbitrationDeAssertBSY: + scsi_set_ctrl(0, S_BSY); + update_state(State::SelectionAssertSEL, 1); + break; + + case State::SelectionWaitBusFree: + if (!(ctrl & (S_BSY|S_SEL))) + update_state(State::SelectionAssertSEL, 10); + break; + + case State::SelectionAssertSEL: + scsi_bus->data_w(scsi_refid, m_temp); + scsi_set_ctrl(0, S_SEL); //XXX: needed? + scsi_set_ctrl(S_SEL | (m_send_atn_during_selection ? S_ATN : 0), S_ATN|S_SEL|S_BSY); + scsi_bus->ctrl_wait(scsi_refid, S_BSY, S_BSY); + update_state(State::SelectionWaitBSY, 0, m_tc / 8); + break; + + case State::SelectionWaitBSY: + if (timeout) { + LOG("select timeout\n"); + scsi_disconnect_timeout(); + break; + } + m_timer->reset(); + if ((ctrl & (S_REQ|S_BSY|S_MSG|S_CTL|S_INP)) == S_BSY) + update_state(State::Selection, 1); + + break; + + case State::Selection: + LOG("selection success\n"); + scsi_set_ctrl(0, S_SEL); + m_ssts |= SSTS_INIT_CONNECTED|SSTS_XFER_IN_PROGRESS; + m_ssts &= ~(SSTS_TARG_CONNECTED|SSTS_SPC_BUSY); + update_ssts(); + scsi_command_complete(); + break; + + case State::TransferWaitReq: + + + if (!m_tc && (m_fifo.empty() || m_dma_transfer)) { + LOG("TransferWaitReq: tc == 0\n"); + scsi_bus->data_w(scsi_refid, 0); + scsi_command_complete(); + break; + } + + if (m_tc < 0) + break; + + if (m_scsi_phase != (ctrl & S_PHASE_MASK)) { + LOG("SCSI phase change during transfer\n"); + m_ints |= INTS_SERVICE_REQUIRED; + m_ssts &= ~SSTS_SPC_BUSY; + update_ints(); + break; + } + + if (!(ctrl & S_REQ)) { + scsi_bus->ctrl_wait(scsi_refid, S_REQ, S_REQ); + break; + } + + if (!m_dma_transfer) { + update_state((ctrl & S_INP) ? State::TransferRecvData : State::TransferSendData, 1); + } else { + update_state((ctrl & S_INP) ? State::TransferRecvDataDMAReq : State::TransferSendDataDMAReq, 1); + } + break; + + case State::TransferRecvData: + if (!m_tc || m_fifo.full()) + break; + + LOG("pushing read data: %02X\n", data); + m_fifo.enqueue(data); + m_tc--; + + update_state(State::TransferSendAck, 10); + break; + + case State::TransferRecvDataDMAReq: + m_hdb = data; + m_hdb_loaded = true; + update_state(State::TransferRecvDataDMAResp, 10); + m_tc--; + m_dreq_handler(true); + break; + + case State::TransferRecvDataDMAResp: + if (m_hdb_loaded) + break; + update_state(State::TransferSendAck, 10); + m_dreq_handler(false); + break; + + case State::TransferSendData: + + if (m_tc < 0 || m_fifo.empty()) { + LOG("fifo empty or m_tc(%d) zero\n", m_tc); + break; + } + + scsi_bus->data_w(scsi_refid, m_fifo.dequeue()); + m_tc--; + update_state(State::TransferSendAck, 10); + break; + + case State::TransferSendDataDMAReq: + m_hdb_loaded = false; + update_state(State::TransferSendDataDMAResp, 10); + m_dreq_handler(true); + break; + + case State::TransferSendDataDMAResp: + if (!m_hdb_loaded) + break; + m_hdb_loaded = false; + m_dreq_handler(false); + scsi_bus->data_w(scsi_refid, m_hdb); + m_tc--; + update_state(State::TransferSendAck, 10); + break; + + case State::TransferSendAck: + + scsi_set_ctrl(S_ACK, S_ACK); + scsi_bus->ctrl_wait(scsi_refid, 0, S_REQ); + + update_state(State::TransferWaitDeassertREQ, 10); + break; + + case State::TransferWaitDeassertREQ: + if (!(ctrl & S_REQ)) + update_state(State::TransferDeassertACK, 10); + break; + + case State::TransferDeassertACK: + scsi_set_ctrl(0, S_ACK); + scsi_bus->ctrl_wait(scsi_refid, S_REQ, S_REQ); + update_state(State::TransferWaitReq, 10); + break; + + } +} + +void mb87030_device::device_start() +{ + m_timer = timer_alloc(TimerId::Timeout); + m_delay_timer = timer_alloc(TimerId::Delay); + m_irq_handler.resolve_safe(); + m_dreq_handler.resolve_safe(); + + save_item(NAME(m_bdid)); + save_item(NAME(m_sctl)); + save_item(NAME(m_scmd)); + save_item(NAME(m_tmod)); + save_item(NAME(m_ints)); + save_item(NAME(m_sdgc)); + save_item(NAME(m_ssts)); + save_item(NAME(m_serr)); + save_item(NAME(m_pctl)); + save_item(NAME(m_mbc)); + save_item(NAME(m_dreg)); + save_item(NAME(m_temp)); + save_item(NAME(m_tch)); + save_item(NAME(m_tcm)); + save_item(NAME(m_tc)); + save_item(NAME(m_exbf)); + save_item(NAME(m_hdb)); + save_item(NAME(m_hdb_loaded)); + save_item(NAME(m_send_atn_during_selection)); +// save_item(NAME(m_fifo)); + save_item(NAME(m_scsi_phase)); + save_item(NAME(m_scsi_ctrl)); + save_item(NAME(m_dma_transfer)); +// save_item(NAME(m_state)); +} + +void mb87030_device::scsi_ctrl_changed() +{ + if (m_delay_timer->remaining() == attotime::never) + step(false); +} + +WRITE_LINE_MEMBER(mb87030_device::reset_w) +{ + LOG("%s: %s\n", __FUNCTION__, state); + if (state) + device_reset(); +} + +void mb87030_device::update_ssts() +{ + if (!m_tc) + m_ssts |= SSTS_TC_ZERO; + else + m_ssts &= ~SSTS_TC_ZERO; + + if (m_fifo.empty()) + m_ssts |= SSTS_DREQ_EMPTY; + else + m_ssts &= ~SSTS_DREQ_EMPTY; + + if (m_fifo.full()) + m_ssts |= SSTS_DREQ_FULL; + else + m_ssts &= ~SSTS_DREQ_FULL; +} + +void mb87030_device::update_ints() +{ + LOG("%s: %s\n", __FUNCTION__, (m_ints && (m_sctl & 1)) ? "true" : "false"); + m_irq_handler(m_ints && (m_sctl & 1));// || (m_ints & INTS_DISCONNECTED)); +} + +READ8_MEMBER(mb87030_device::bdid_r) +{ + LOG("%s %02X\n", __FUNCTION__, (1 << m_bdid)); + return (1 << m_bdid); +} + +WRITE8_MEMBER(mb87030_device::bdid_w) +{ + LOG("%s: %02X\n", __FUNCTION__, data); + m_bdid = data & 0x7; +} + +READ8_MEMBER(mb87030_device::sctl_r) +{ + LOG("%s: %02X\n", __FUNCTION__, m_sctl); + return m_sctl; +} + +WRITE8_MEMBER(mb87030_device::sctl_w) +{ + LOG("%s: %02X\n", __FUNCTION__, data); + m_sctl = data; + update_ints(); +} + +READ8_MEMBER(mb87030_device::scmd_r) +{ + LOG("%s: %02X\n", __FUNCTION__, m_scmd); + return m_scmd; +} + +WRITE8_MEMBER(mb87030_device::scmd_w) +{ + LOG("%s: %02X\n", __FUNCTION__, data); + m_scmd = data; + + switch(m_scmd & SCMD_CMD_MASK) { + case SCMD_CMD_BUS_RELEASE: + LOG("%s: Bus release\n", __FUNCTION__); + break; + case SCMD_CMD_SELECT: + LOG("%s: Select\n", __FUNCTION__); + if (m_sctl & SCTL_ARBITRATION_ENABLE) + update_state(State::ArbitrationWaitBusFree, 10); + else + update_state(State::SelectionWaitBusFree, 10); + step(false); + break; + case SCMD_CMD_RESET_ATN: + LOG("%s: Reset ATN\n", __FUNCTION__); +// if (m_state == State::Idle) + m_send_atn_during_selection = false; +// else + scsi_set_ctrl(0, S_ATN); + break; + case SCMD_CMD_SET_ATN: + LOG("%s: Set ATN\n", __FUNCTION__); + if (m_state == State::Idle) + m_send_atn_during_selection = true; + else + scsi_set_ctrl(S_ATN, S_ATN); + break; + case SCMD_CMD_TRANSFER: + if (!(m_ssts & (SSTS_INIT_CONNECTED|SSTS_TARG_CONNECTED))) + break; + + m_dma_transfer = !(data & 0x04); + LOG("%s Transfer\n", m_dma_transfer ? "DMA" : "Program"); + m_ssts |= SSTS_SPC_BUSY|SSTS_XFER_IN_PROGRESS; + update_state(State::TransferWaitReq, 5); + break; + case SCMD_CMD_TRANSFER_PAUSE: + LOG("%s: Transfer Pause\n", __FUNCTION__); + break; + case SCMD_CMD_RESET_ACK_REQ: + LOG("%s: Reset ACK/REQ\n", __FUNCTION__); + if (m_ssts & SSTS_INIT_CONNECTED) + scsi_set_ctrl(0, S_ACK); + if (m_ssts & SSTS_TARG_CONNECTED) + scsi_set_ctrl(0, S_REQ); + break; + case SCMD_CMD_SET_ACK_REQ: + LOG("%s: Set ACK/REQ\n", __FUNCTION__); + if (m_ssts & SSTS_INIT_CONNECTED) { + if (m_pctl & 1) { + m_temp = scsi_bus->data_r(); + } else { + scsi_bus->data_w(scsi_refid, m_temp); + } + LOG("set ACK\n"); + scsi_set_ctrl(S_ACK, S_ACK); + } else { + logerror("not connected\n"); + } + if (m_ssts & SSTS_TARG_CONNECTED) + scsi_set_ctrl(S_REQ, S_REQ); + break; + } +} + +READ8_MEMBER(mb87030_device::tmod_r) +{ + LOG("%s: %02X\n", __FUNCTION__, m_tmod); + return m_tmod; +} + +WRITE8_MEMBER(mb87030_device::tmod_w) +{ + LOG("%s: %02X\n", __FUNCTION__, data); + m_tmod = data; +} + +READ8_MEMBER(mb87030_device::ints_r) +{ + LOG("%s: %02X\n", __FUNCTION__, m_ints); + return m_ints; +} + +WRITE8_MEMBER(mb87030_device::ints_w) +{ + LOG("%s: %02X\n", __FUNCTION__, data); + m_ints &= ~(data); + update_ints(); +} + +READ8_MEMBER(mb87030_device::psns_r) +{ + uint32_t ctrl = scsi_get_ctrl(); + uint8_t ret = (!!(ctrl & S_REQ) << 7) | + (!!(ctrl & S_ACK) << 6) | + (!!(ctrl & S_ATN) << 5) | + (!!(ctrl & S_SEL) << 4) | + (!!(ctrl & S_BSY) << 3) | + (!!(ctrl & S_MSG) << 2) | + (!!(ctrl & S_CTL) << 1) | + (!!(ctrl & S_INP)); + LOG("%s: %02X\n", __FUNCTION__, ret); + return ret; +} + +WRITE8_MEMBER(mb87030_device::sdgc_w) +{ + LOG("%s: %02X\n", __FUNCTION__, data); + m_sdgc = data; + scsi_ctrl_changed(); +} + +READ8_MEMBER(mb87030_device::ssts_r) +{ + LOG("%s: %02X\n", __FUNCTION__, m_ssts); + update_ssts(); + return m_ssts; +} + +READ8_MEMBER(mb87030_device::serr_r) +{ + LOG("%s: %02X\n", __FUNCTION__, m_serr); + return m_serr; +} + +READ8_MEMBER(mb87030_device::pctl_r) +{ + LOG("%s: %02X\n", __FUNCTION__, m_pctl); + return m_pctl; +} + +WRITE8_MEMBER(mb87030_device::pctl_w) +{ + LOG("%s: %02X\n", __FUNCTION__, data); + m_pctl = data; + m_scsi_phase = m_pctl & 7; + if (m_pctl & PCTL_BUS_FREE_IE) + step(false); + +} + +READ8_MEMBER(mb87030_device::mbc_r) +{ + LOG("%s: %02X\n", __FUNCTION__, m_mbc); + return m_mbc; +} + +READ8_MEMBER(mb87030_device::dreg_r) +{ + + step(false); + if (!m_fifo.empty()) + m_dreg = m_fifo.dequeue(); + LOG("%s: %02X\n", __FUNCTION__, m_dreg); + return m_dreg; +} + +WRITE8_MEMBER(mb87030_device::dreg_w) +{ + LOG("%s: %02X\n", __FUNCTION__, data); + m_dreg = data; + if (!m_fifo.full()) + m_fifo.enqueue(data); + step(false); +} + +READ8_MEMBER(mb87030_device::temp_r) +{ + m_temp = scsi_bus->data_r(); + LOG("%s: %02X\n", __FUNCTION__, m_temp); + return m_temp; + +} + +WRITE8_MEMBER(mb87030_device::temp_w) +{ + LOG("%s: %02X\n", __FUNCTION__, data); + m_temp = data; + step(false); +} + +READ8_MEMBER(mb87030_device::tch_r) +{ + uint8_t ret = (m_tc >> 16) & 0xff; + LOG("%s: %02X\n", __FUNCTION__, ret); + return ret; +} + +READ8_MEMBER(mb87030_device::tcm_r) +{ + uint8_t ret = (m_tc >> 8) & 0xff; + LOG("%s: %02X\n", __FUNCTION__, ret); + return ret; +} + +READ8_MEMBER(mb87030_device::tcl_r) +{ + uint8_t ret = m_tc & 0xff; + LOG("%s: %02X\n", __FUNCTION__, ret); + return ret; +} + + +WRITE8_MEMBER(mb87030_device::tch_w) +{ + LOG("%s: %02X\n", __FUNCTION__, data); + m_tc &= 0x00ffff; + m_tc |= data << 16; + update_ssts(); +} + +WRITE8_MEMBER(mb87030_device::tcm_w) +{ + LOG("%s: %02X\n", __FUNCTION__, data); + m_tc &= 0xff00ff; + m_tc |= data << 8; + update_ssts(); +} + +WRITE8_MEMBER(mb87030_device::tcl_w) +{ + LOG("%s: %02X\n", __FUNCTION__, data); + m_tc &= 0xffff00; + m_tc |= data; + update_ssts(); +} + +READ8_MEMBER(mb87030_device::exbf_r) +{ + LOG("%s: %02X\n", __FUNCTION__, m_exbf); + return m_exbf; +} + +WRITE8_MEMBER(mb87030_device::exbf_w) +{ + LOG("%s: %02X\n", __FUNCTION__, data); + m_exbf = data; +} + +void mb87030_device::dma_w(uint8_t data) +{ + if (machine().side_effects_disabled()) + return; + LOG("dma_w: %02X\n", data); + m_hdb = data; + m_hdb_loaded = true; + step(false); +} + +uint8_t mb87030_device::dma_r(void) +{ + uint8_t val = m_hdb; + + if (machine().side_effects_disabled()) + return 0; + LOG("dma_r: %02X\n", val); + m_hdb_loaded = false; + step(false); + return val; +} diff --git a/src/devices/machine/mb87030.h b/src/devices/machine/mb87030.h new file mode 100644 index 00000000000..3b5945434a1 --- /dev/null +++ b/src/devices/machine/mb87030.h @@ -0,0 +1,220 @@ +// license:BSD-3-Clause +// copyright-holders:Sven Schnelle +#ifndef MAME_MACHINE_MB87030_H +#define MAME_MACHINE_MB87030_H + +#pragma once + +#include "machine/nscsi_bus.h" +#include + +class mb87030_device : public nscsi_device +{ +public: + mb87030_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + virtual void map(address_map &map); + + auto out_irq_callback() { return m_irq_handler.bind(); } + auto out_dreq_callback() { return m_dreq_handler.bind(); } + + DECLARE_READ8_MEMBER(bdid_r); + DECLARE_READ8_MEMBER(sctl_r); + DECLARE_READ8_MEMBER(scmd_r); + DECLARE_READ8_MEMBER(tmod_r); + DECLARE_READ8_MEMBER(ints_r); + DECLARE_READ8_MEMBER(psns_r); + DECLARE_READ8_MEMBER(ssts_r); + DECLARE_READ8_MEMBER(serr_r); + DECLARE_READ8_MEMBER(pctl_r); + DECLARE_READ8_MEMBER(mbc_r); + DECLARE_READ8_MEMBER(dreg_r); + DECLARE_READ8_MEMBER(temp_r); + DECLARE_READ8_MEMBER(tch_r); + DECLARE_READ8_MEMBER(tcm_r); + DECLARE_READ8_MEMBER(tcl_r); + DECLARE_READ8_MEMBER(exbf_r); + + DECLARE_WRITE8_MEMBER(bdid_w); + DECLARE_WRITE8_MEMBER(sctl_w); + DECLARE_WRITE8_MEMBER(scmd_w); + DECLARE_WRITE8_MEMBER(tmod_w); + DECLARE_WRITE8_MEMBER(ints_w); + DECLARE_WRITE8_MEMBER(sdgc_w); + DECLARE_WRITE8_MEMBER(pctl_w); + DECLARE_WRITE8_MEMBER(dreg_w); + DECLARE_WRITE8_MEMBER(temp_w); + DECLARE_WRITE8_MEMBER(tch_w); + DECLARE_WRITE8_MEMBER(tcm_w); + DECLARE_WRITE8_MEMBER(tcl_w); + DECLARE_WRITE8_MEMBER(exbf_w); + + DECLARE_WRITE_LINE_MEMBER(reset_w); + virtual void scsi_ctrl_changed() override; + + uint8_t dma_r(); + void dma_w(uint8_t val); + + void ctrl_write(uint32_t value, uint32_t mask) { scsi_bus->ctrl_w(scsi_refid, value, mask); scsi_ctrl_changed(); } + uint32_t data_read() { return scsi_bus->data_r(); }; +protected: + mb87030_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + virtual void device_start() override; + virtual void device_reset() override; +private: + + constexpr static uint8_t SCTL_INT_ENABLE = 0x01; + constexpr static uint8_t SCTL_RESELECT_ENABLE = 0x02; + constexpr static uint8_t SCTL_SELECT_ENABLE = 0x04; + constexpr static uint8_t SCTL_PARITY_ENABLE = 0x08; + constexpr static uint8_t SCTL_ARBITRATION_ENABLE = 0x10; + constexpr static uint8_t SCTL_DIAG_MODE = 0x20; + constexpr static uint8_t SCTL_CONTROL_RESET = 0x40; + constexpr static uint8_t SCTL_RESET_AND_DISABLE = 0x80; + + constexpr static uint8_t SCMD_TERM_MODE = 0x01; + constexpr static uint8_t SCMD_PRG_XFER = 0x02; + constexpr static uint8_t SCMD_INTERCEPT_XFER = 0x04; + constexpr static uint8_t SCMD_RST_OUT = 0x08; + constexpr static uint8_t SCMD_CMD_BUS_RELEASE = 0x00; + constexpr static uint8_t SCMD_CMD_SELECT = 0x20; + constexpr static uint8_t SCMD_CMD_RESET_ATN = 0x40; + constexpr static uint8_t SCMD_CMD_SET_ATN = 0x60; + constexpr static uint8_t SCMD_CMD_TRANSFER = 0x80; + constexpr static uint8_t SCMD_CMD_TRANSFER_PAUSE = 0xa0; + constexpr static uint8_t SCMD_CMD_RESET_ACK_REQ = 0xc0; + constexpr static uint8_t SCMD_CMD_SET_ACK_REQ = 0xe0; + constexpr static uint8_t SCMD_CMD_MASK = 0xe0; + + constexpr static uint8_t TMOD_MIN_TRANSFER_PERIOD_SHIFT = 0x02; + constexpr static uint8_t TMOD_MIN_TRANSFER_PERIOD_MASK = 0x0c; + constexpr static uint8_t TMOD_MAX_TRANSFER_OFFSET_SHIFT = 0x04; + constexpr static uint8_t TMOD_MIN_TRANSFER_OFFSET_MASK = 0x70; + constexpr static uint8_t TMOD_SYNC_XFER = 0x80; + + constexpr static uint8_t PCTL_PHASE_SHIFT = 0x00; + constexpr static uint8_t PCTL_PHASE_MASK = 0x07; + constexpr static uint8_t PCTL_BUS_FREE_IE = 0x80; + + constexpr static uint8_t PSNS_IO = 0x01; + constexpr static uint8_t PSNS_CD = 0x02; + constexpr static uint8_t PSNS_MSG = 0x04; + constexpr static uint8_t PSNS_BSY = 0x08; + constexpr static uint8_t PSNS_SEL = 0x10; + constexpr static uint8_t PSNS_ATN = 0x20; + constexpr static uint8_t PSNS_ACK = 0x40; + constexpr static uint8_t PSNS_REQ = 0x80; + + constexpr static uint8_t INTS_RESET_CONDITION = 0x01; + constexpr static uint8_t INTS_SPC_HARD_ERR = 0x02; + constexpr static uint8_t INTS_SPC_TIMEOUT = 0x04; + constexpr static uint8_t INTS_SERVICE_REQUIRED = 0x08; + constexpr static uint8_t INTS_COMMAND_COMPLETE = 0x10; + constexpr static uint8_t INTS_DISCONNECTED = 0x20; + constexpr static uint8_t INTS_RESELECTED = 0x40; + constexpr static uint8_t INTS_SELECTED = 0x80; + + constexpr static uint8_t SSTS_DREQ_EMPTY = 0x01; + constexpr static uint8_t SSTS_DREQ_FULL = 0x02; + constexpr static uint8_t SSTS_TC_ZERO = 0x04; + constexpr static uint8_t SSTS_SCSI_RST = 0x08; + constexpr static uint8_t SSTS_XFER_IN_PROGRESS = 0x10; + constexpr static uint8_t SSTS_SPC_BUSY = 0x20; + constexpr static uint8_t SSTS_TARG_CONNECTED = 0x40; + constexpr static uint8_t SSTS_INIT_CONNECTED = 0x80; + + constexpr static uint8_t SERR_OFFSET_ERROR = 0x01; + constexpr static uint8_t SERR_SHORT_PERIOD = 0x02; + constexpr static uint8_t SERR_PHASE_ERROR = 0x04; + constexpr static uint8_t SERR_TC_P_ERROR = 0x08; + constexpr static uint8_t SERR_DATA_ERROR_SPC = 0x40; + constexpr static uint8_t SERR_DATA_ERROR_SCSI = 0x80; + + constexpr static uint8_t SDGC_DIAG_IO = 0x01; + constexpr static uint8_t SDGC_DIAG_CD = 0x02; + constexpr static uint8_t SDGC_DIAG_MSG = 0x04; + constexpr static uint8_t SDGC_DIAG_BSY = 0x08; + constexpr static uint8_t SDGC_DIAG_ACK = 0x40; + constexpr static uint8_t SDGC_DIAG_REQ = 0x80; + + emu_timer *m_timer; + emu_timer *m_delay_timer; + + enum TimerId { + Delay, + Timeout, + }; + enum class State: uint8_t { + Idle, + ArbitrationWaitBusFree, + ArbitrationAssertBSY, + ArbitrationWait, + ArbitrationAssertSEL, + ArbitrationDeAssertBSY, + SelectionWaitBusFree, + SelectionAssertSEL, + SelectionWaitBSY, + Selection, + TransferWaitReq, + TransferSendData, + TransferSendDataDMAReq, + TransferSendDataDMAResp, + TransferRecvData, + TransferRecvDataDMAReq, + TransferRecvDataDMAResp, + TransferSendAck, + TransferWaitDeassertREQ, + TransferDeassertACK + //TransferCommand, + } m_state; + + void update_ssts(void); + void update_ints(void); + + void scsi_disconnect_timeout(void); + void scsi_command_complete(void); + void scsi_disconnect(void); + void update_state(mb87030_device::State new_state, int delay = 0, int timeout = 0); + auto get_state_name(State state) const; + void scsi_set_ctrl(uint32_t val, uint32_t mask); + uint32_t scsi_get_ctrl(); + void step(bool timeout); + + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; + devcb_write_line m_irq_handler; + devcb_write_line m_dreq_handler; + + // registers + uint8_t m_bdid; + uint8_t m_sctl; + uint8_t m_scmd; + uint8_t m_tmod; + uint8_t m_ints; + uint8_t m_sdgc; + uint8_t m_ssts; + uint8_t m_serr; + uint8_t m_pctl; + uint8_t m_mbc; + uint8_t m_dreg; + uint8_t m_temp; + uint8_t m_tch; + uint8_t m_tcm; + uint32_t m_tc; + uint8_t m_exbf; + + uint8_t m_hdb; + bool m_hdb_loaded; + bool m_send_atn_during_selection; + util::fifo m_fifo; + + uint8_t m_scsi_phase; + uint32_t m_scsi_ctrl; + + bool m_dma_transfer; +}; + + +DECLARE_DEVICE_TYPE(MB87030, mb87030_device) + +#endif // MAME_MACHINE_MB87030_H -- cgit v1.2.3 From d929f8b41b256ddefb3cd997b1cbe3ebd6e9f820 Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Mon, 8 Oct 2018 22:49:46 +0200 Subject: hp9k_3xx: move Sound, GPIB, Keyboard and RTC to human interface module On HP9000/300, these modules where always a logical unit connected to the DIO bus. On some systems this was even a seperate DIO module. Lets represent this in software. It also cleans up hp9k_3xx.cpp. --- scripts/src/bus.lua | 2 + src/devices/bus/hp_dio/hp_dio.h | 2 + src/devices/bus/hp_dio/human_interface.cpp | 304 +++++++++++++++++++++++++++++ src/devices/bus/hp_dio/human_interface.h | 94 +++++++++ src/mame/drivers/hp9k_3xx.cpp | 237 ++++------------------ 5 files changed, 439 insertions(+), 200 deletions(-) create mode 100644 src/devices/bus/hp_dio/human_interface.cpp create mode 100644 src/devices/bus/hp_dio/human_interface.h (limited to 'scripts/src') diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index e86393a9e8f..86fade73bff 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -893,6 +893,8 @@ if (BUSES["HPDIO"]~=null) then MAME_DIR .. "src/devices/bus/hp_dio/hp98603b.h", MAME_DIR .. "src/devices/bus/hp_dio/hp98644.cpp", MAME_DIR .. "src/devices/bus/hp_dio/hp98644.h", + MAME_DIR .. "src/devices/bus/hp_dio/human_interface.cpp", + MAME_DIR .. "src/devices/bus/hp_dio/human_interface.h", } end diff --git a/src/devices/bus/hp_dio/hp_dio.h b/src/devices/bus/hp_dio/hp_dio.h index 938e267b7f6..d44a9e3bf66 100644 --- a/src/devices/bus/hp_dio/hp_dio.h +++ b/src/devices/bus/hp_dio/hp_dio.h @@ -89,6 +89,7 @@ public: void unmap_bank(offs_t start, offs_t end); void unmap_rom(offs_t start, offs_t end); + address_space *program_space() { return m_prgspace; } // IRQs 1, 2, and 7 are reserved for non-bus usage. @@ -186,6 +187,7 @@ protected: virtual void interface_pre_start() override; int get_index() { return m_index; }; + address_space *program_space() { return m_dio_dev->program_space(); } DECLARE_WRITE_LINE_MEMBER(irq1_out) { m_dio_dev->set_irq(m_index, 0, state); } DECLARE_WRITE_LINE_MEMBER(irq2_out) { m_dio_dev->set_irq(m_index, 1, state); } diff --git a/src/devices/bus/hp_dio/human_interface.cpp b/src/devices/bus/hp_dio/human_interface.cpp new file mode 100644 index 00000000000..4358d71ffd9 --- /dev/null +++ b/src/devices/bus/hp_dio/human_interface.cpp @@ -0,0 +1,304 @@ +// license:BSD-3-Clause +// copyright-holders:Sven Schnelle +/*************************************************************************** + + HP Human interface board + +***************************************************************************/ + +#include "emu.h" +#include "human_interface.h" +#include "cpu/mcs48/mcs48.h" +#include "machine/tms9914.h" +#include "machine/msm58321.h" +#include "sound/sn76496.h" +#include "bus/hp_hil/hp_hil.h" +#include "bus/hp_hil/hil_devices.h" +#include "bus/ieee488/ieee488.h" +#include "speaker.h" +//#define VERBOSE 1 +#include "logmacro.h" + +DEFINE_DEVICE_TYPE_NS(HPDIO_HUMAN_INTERFACE, bus::hp_dio, human_interface_device, "human_interface", "HP human interface card") + +namespace bus { + namespace hp_dio { + +MACHINE_CONFIG_START(human_interface_device::device_add_mconfig) + + i8042_device &iocpu(I8042(config, "iocpu", XTAL(5'000'000))); + iocpu.set_addrmap(AS_PROGRAM, &human_interface_device::iocpu_map); + iocpu.p1_out_cb().set(FUNC(human_interface_device::iocpu_port1_w)); + iocpu.p2_out_cb().set(FUNC(human_interface_device::iocpu_port2_w)); + iocpu.p1_in_cb().set(FUNC(human_interface_device::iocpu_port1_r)); + iocpu.t0_in_cb().set(FUNC(human_interface_device::iocpu_test0_r)); + iocpu.p2_in_cb().set_constant(0xdf); + iocpu.t1_in_cb().set_constant(1); + + MCFG_DEVICE_ADD(m_mlc, HP_HIL_MLC, XTAL(8'000'000)) + MCFG_HP_HIL_SLOT_ADD("mlc", "hil1", hp_hil_devices, "hp_46021a") + SPEAKER(config, "mono").front_center(); + MCFG_DEVICE_ADD("sn76494", SN76494, 333333) + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.75) + + MCFG_DEVICE_ADD("rtc", MSM58321, 32.768_kHz_XTAL) + MCFG_MSM58321_DEFAULT_24H(false) + MCFG_MSM58321_D0_HANDLER(WRITELINE(*this, human_interface_device, rtc_d0_w)) + MCFG_MSM58321_D1_HANDLER(WRITELINE(*this, human_interface_device, rtc_d1_w)) + MCFG_MSM58321_D2_HANDLER(WRITELINE(*this, human_interface_device, rtc_d2_w)) + MCFG_MSM58321_D3_HANDLER(WRITELINE(*this, human_interface_device, rtc_d3_w)) + + MCFG_DEVICE_ADD(m_tms9914, TMS9914, XTAL(5000000)) + MCFG_TMS9914_INT_WRITE_CB(WRITELINE(*this, human_interface_device, gpib_irq)); + MCFG_TMS9914_ACCRQ_WRITE_CB(WRITELINE(*this, human_interface_device, gpib_dreq)); + MCFG_TMS9914_DIO_READWRITE_CB(READ8(IEEE488_TAG, ieee488_device, dio_r), WRITE8(IEEE488_TAG, ieee488_device, host_dio_w)) + MCFG_TMS9914_EOI_WRITE_CB(WRITELINE(IEEE488_TAG, ieee488_device, host_eoi_w)) + MCFG_TMS9914_DAV_WRITE_CB(WRITELINE(IEEE488_TAG, ieee488_device, host_dav_w)) + MCFG_TMS9914_NRFD_WRITE_CB(WRITELINE(IEEE488_TAG, ieee488_device, host_nrfd_w)) + MCFG_TMS9914_NDAC_WRITE_CB(WRITELINE(IEEE488_TAG, ieee488_device, host_ndac_w)) + MCFG_TMS9914_IFC_WRITE_CB(WRITELINE(IEEE488_TAG, ieee488_device, host_ifc_w)) + MCFG_TMS9914_SRQ_WRITE_CB(WRITELINE(IEEE488_TAG, ieee488_device, host_srq_w)) + MCFG_TMS9914_ATN_WRITE_CB(WRITELINE(IEEE488_TAG, ieee488_device, host_atn_w)) + MCFG_TMS9914_REN_WRITE_CB(WRITELINE(IEEE488_TAG, ieee488_device, host_ren_w)) + + MCFG_IEEE488_SLOT_ADD("ieee0", 0, hp_ieee488_devices, "hp9122c") + MCFG_IEEE488_SLOT_ADD("ieee_rem", 0, remote488_devices, nullptr) + MCFG_IEEE488_BUS_ADD() + + MCFG_IEEE488_EOI_CALLBACK(WRITELINE(m_tms9914, tms9914_device, eoi_w)) + MCFG_IEEE488_DAV_CALLBACK(WRITELINE(m_tms9914, tms9914_device, dav_w)) + MCFG_IEEE488_NRFD_CALLBACK(WRITELINE(m_tms9914, tms9914_device, nrfd_w)) + MCFG_IEEE488_NDAC_CALLBACK(WRITELINE(m_tms9914, tms9914_device, ndac_w)) + MCFG_IEEE488_IFC_CALLBACK(WRITELINE(m_tms9914, tms9914_device, ifc_w)) + MCFG_IEEE488_SRQ_CALLBACK(WRITELINE(m_tms9914, tms9914_device, srq_w)) + MCFG_IEEE488_ATN_CALLBACK(WRITELINE(m_tms9914, tms9914_device, atn_w)) + MCFG_IEEE488_REN_CALLBACK(WRITELINE(m_tms9914, tms9914_device, ren_w)) +MACHINE_CONFIG_END + +ROM_START(human_interface) + ROM_REGION(0x800 , "iocpu" , 0) + ROM_LOAD( "1820-4784.bin", 0x000000, 0x000800, CRC(e929044a) SHA1(90849a10bdb8c6e38e73ce027c9c0ad8b3956b1b)) +ROM_END + +const tiny_rom_entry *human_interface_device::device_rom_region() const +{ + return ROM_NAME(human_interface); +} + +void human_interface_device::iocpu_map(address_map& map) +{ + map(0x0000, 0x07ff).rom().region("iocpu", 0); +} +void human_interface_device::map(address_map& map) +{ + map(0x00420000, 0x00420003).mirror(0x0000fffc).rw(m_iocpu, FUNC(upi41_cpu_device::upi41_master_r), FUNC(upi41_cpu_device::upi41_master_w)).umask32(0x00ff00ff); + map(0x00470000, 0x0047001f).mirror(0x0000ffe0).rw(FUNC(human_interface_device::gpib_r), FUNC(human_interface_device::gpib_w)).umask16(0x00ff); + +} + +human_interface_device::human_interface_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + human_interface_device(mconfig, HPDIO_HUMAN_INTERFACE, tag, owner, clock) +{ +} + +human_interface_device::human_interface_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, type, tag, owner, clock), + device_dio16_card_interface(mconfig, *this), + m_iocpu(*this, "iocpu"), + m_mlc(*this, "mlc"), + m_sound(*this, "sn76494"), + m_tms9914(*this, "tms9914"), + m_rtc(*this, "rtc") +{ +} + +void human_interface_device::device_start() +{ + program_space()->install_readwrite_handler(0x420000, 0x420003, 0x0003, 0xfffc, 0, + read8_delegate(FUNC(upi41_cpu_device::upi41_master_r), &(*m_iocpu)), + write8_delegate(FUNC(upi41_cpu_device::upi41_master_w), &(*m_iocpu)), 0x00ff00ff); + + program_space()->install_readwrite_handler(0x470000, 0x47001f, 0x1f, 0xffe0, 0, + read8_delegate(FUNC(human_interface_device::gpib_r), this), + write8_delegate(FUNC(human_interface_device::gpib_w), this), 0x00ff00ff); + + save_item(NAME(m_hil_read)); + save_item(NAME(m_kbd_nmi)); + save_item(NAME(gpib_irq_line)); + save_item(NAME(m_old_latch_enable)); + save_item(NAME(m_hil_data)); + save_item(NAME(m_latch_data)); + save_item(NAME(m_rtc_data)); +} + +void human_interface_device::device_reset() +{ + m_rtc->cs1_w(ASSERT_LINE); + m_rtc->cs2_w(CLEAR_LINE); + m_rtc->write_w(CLEAR_LINE); + m_rtc->read_w(CLEAR_LINE); + m_rtc->cs2_w(CLEAR_LINE); + m_iocpu->reset(); +} + +WRITE_LINE_MEMBER(human_interface_device::reset_in) +{ + if (state) + device_reset(); +} +WRITE_LINE_MEMBER(human_interface_device::gpib_irq) +{ + gpib_irq_line = state; + irq3_out(state ? ASSERT_LINE : CLEAR_LINE); +} + +WRITE_LINE_MEMBER(human_interface_device::gpib_dreq) +{ + dmar0_out(state); +} + +WRITE8_MEMBER(human_interface_device::gpib_w) +{ + if (offset & 0x08) { + m_tms9914->reg8_w(space, offset & 0x07, data); + return; + } + LOG("gpib_w: %s %02X = %02X\n", machine().describe_context().c_str(), offset, data); +} + +READ8_MEMBER(human_interface_device::gpib_r) +{ + uint8_t data = 0xff; + + if (offset & 0x8) { + data = m_tms9914->reg8_r(space, offset & 0x07); + return data; + } + + switch(offset) { + case 0: /* ID */ + data = 0x80; + break; + case 1: + /* Int control */ + data = 0x80 | (gpib_irq_line ? 0x40 : 0); + break; + case 2: + /* Address */ + data = (m_tms9914->cont_r() ? 0x0 : 0x40) | 0x81; + if (m_kbd_nmi) + data |= 0x04; + break; + } + LOG("gpib_r: %s %02X = %02X\n", machine().describe_context().c_str(), offset, data); + return data; +} + + +WRITE8_MEMBER(human_interface_device::iocpu_port1_w) +{ + m_hil_data = data; + m_rtc->d0_w(data & 0x01 ? ASSERT_LINE : CLEAR_LINE); + m_rtc->d1_w(data & 0x02 ? ASSERT_LINE : CLEAR_LINE); + m_rtc->d2_w(data & 0x04 ? ASSERT_LINE : CLEAR_LINE); + m_rtc->d3_w(data & 0x08 ? ASSERT_LINE : CLEAR_LINE); +} + +WRITE8_MEMBER(human_interface_device::iocpu_port2_w) +{ + bool latch_enable = data & LATCH_EN; + + if ((data & (HIL_CS|HIL_WE)) == 0) + m_mlc->write(space, (m_latch_data & 0xc0) >> 6, m_hil_data, 0xff); + + if ((data & SN76494_EN) == 0) + m_sound->write(m_hil_data); + + m_hil_read = ((data & (HIL_CS|HIL_OE)) == 0); + + m_rtc->address_write_w(data & 0x02 ? ASSERT_LINE : CLEAR_LINE); + m_rtc->write_w(data & 0x04 ? ASSERT_LINE : CLEAR_LINE); + + if (!m_old_latch_enable && latch_enable) { + m_latch_data = m_hil_data; + m_rtc->read_w(m_latch_data & 0x20 ? ASSERT_LINE : CLEAR_LINE); + m_rtc->cs2_w(m_latch_data & 0x10 ? ASSERT_LINE : CLEAR_LINE); + } + irq1_out((data & 0x10) ? ASSERT_LINE : CLEAR_LINE); + + if (!(data & KBD_RESET)) { + irq7_out(ASSERT_LINE); + m_kbd_nmi = true; + } else { + irq7_out(CLEAR_LINE); + m_kbd_nmi = false; + } + m_old_latch_enable = latch_enable; +} + +READ8_MEMBER(human_interface_device::iocpu_port1_r) +{ + if (m_hil_read) + return m_mlc->read(space, (m_latch_data & 0xc0) >> 6, 0xff); + if (m_latch_data & 0x20) + return m_rtc_data; + return 0xff; +} + +READ8_MEMBER(human_interface_device::iocpu_test0_r) +{ + return !m_mlc->get_int(); +} + +WRITE_LINE_MEMBER(human_interface_device::rtc_d0_w) +{ + if (state) + m_rtc_data |= 1; + else + m_rtc_data &= ~1; + +} + +WRITE_LINE_MEMBER(human_interface_device::rtc_d1_w) +{ + if (state) + m_rtc_data |= 2; + else + m_rtc_data &= ~2; +} + +WRITE_LINE_MEMBER(human_interface_device::rtc_d2_w) +{ + if (state) + m_rtc_data |= 4; + else + m_rtc_data &= ~4; + +} + +WRITE_LINE_MEMBER(human_interface_device::rtc_d3_w) +{ + if (state) + m_rtc_data |= 8; + else + m_rtc_data &= ~8; + +} + +void human_interface_device::dmack_w_in(int channel, uint8_t data) +{ + if (channel) + return; +// FIXME +// m_tms9914->reg8_w(memory_space(), 7, data); +} + +uint8_t human_interface_device::dmack_r_in(int channel) +{ + if (channel) + return 0xff; + return m_tms9914->reg8_r(machine().dummy_space(), 7); +} + +} // namespace bus::hp_dio +} // namespace bus diff --git a/src/devices/bus/hp_dio/human_interface.h b/src/devices/bus/hp_dio/human_interface.h new file mode 100644 index 00000000000..b2d412b6306 --- /dev/null +++ b/src/devices/bus/hp_dio/human_interface.h @@ -0,0 +1,94 @@ +// license:BSD-3-Clause +// copyright-holders:Sven Schnelle + +#ifndef MAME_BUS_HPDIO_HUMAN_INTERFACE_H +#define MAME_BUS_HPDIO_HUMAN_INTERFACE_H + +#pragma once + +#include "hp_dio.h" +#include "cpu/mcs48/mcs48.h" +#include "machine/tms9914.h" +#include "machine/msm58321.h" +#include "sound/sn76496.h" +#include "bus/hp_hil/hp_hil.h" +#include "bus/hp_hil/hil_devices.h" + +namespace bus { + namespace hp_dio { +class human_interface_device : + public device_t, + public device_dio16_card_interface +{ +public: + human_interface_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + human_interface_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + virtual void device_start() override; + virtual void device_reset() override; + + virtual void device_add_mconfig(machine_config &config) override; + virtual const tiny_rom_entry *device_rom_region() const override; + +private: + + /* 8042 interface */ + DECLARE_WRITE8_MEMBER(iocpu_port1_w); + DECLARE_WRITE8_MEMBER(iocpu_port2_w); + DECLARE_READ8_MEMBER(iocpu_port1_r); + DECLARE_READ8_MEMBER(iocpu_test0_r); + + /* GPIB */ + DECLARE_READ8_MEMBER(gpib_r); + DECLARE_WRITE8_MEMBER(gpib_w); + + DECLARE_WRITE_LINE_MEMBER(gpib_irq); + DECLARE_WRITE_LINE_MEMBER(gpib_dreq); + + /* RTC */ + DECLARE_WRITE_LINE_MEMBER(rtc_d0_w); + DECLARE_WRITE_LINE_MEMBER(rtc_d1_w); + DECLARE_WRITE_LINE_MEMBER(rtc_d2_w); + DECLARE_WRITE_LINE_MEMBER(rtc_d3_w); + + DECLARE_WRITE_LINE_MEMBER(reset_in) override; + + void dmack_w_in(int channel, uint8_t data) override; + uint8_t dmack_r_in(int channel) override; + + required_device m_iocpu; + required_device m_mlc; + required_device m_sound; + required_device m_tms9914; + required_device m_rtc; + + void map(address_map &map); + void iocpu_map(address_map &map); + + static constexpr uint8_t HIL_CS = 0x01; + static constexpr uint8_t HIL_WE = 0x02; + static constexpr uint8_t HIL_OE = 0x04; + static constexpr uint8_t LATCH_EN = 0x08; + static constexpr uint8_t KBD_RESET = 0x40; + static constexpr uint8_t SN76494_EN = 0x80; + + bool m_hil_read; + bool m_kbd_nmi; + + bool gpib_irq_line; + bool m_old_latch_enable; + + uint8_t m_hil_data; + uint8_t m_latch_data; + uint8_t m_rtc_data; + + +}; +} +} +// device type definition +DECLARE_DEVICE_TYPE_NS(HPDIO_HUMAN_INTERFACE, bus::hp_dio, human_interface_device) + +#endif // MAME_BUS_HPDIO_HUMAN_INTERFACE_H diff --git a/src/mame/drivers/hp9k_3xx.cpp b/src/mame/drivers/hp9k_3xx.cpp index c388cd710f8..4632301e262 100644 --- a/src/mame/drivers/hp9k_3xx.cpp +++ b/src/mame/drivers/hp9k_3xx.cpp @@ -57,30 +57,21 @@ #include "emu.h" #include "logmacro.h" #include "cpu/m68000/m68000.h" -#include "cpu/mcs48/mcs48.h" #include "machine/6840ptm.h" -#include "machine/tms9914.h" #include "sound/sn76496.h" #include "bus/hp_dio/hp_dio.h" #include "bus/hp_dio/hp98543.h" #include "bus/hp_dio/hp98544.h" -#include "bus/hp_hil/hp_hil.h" -#include "bus/hp_hil/hil_devices.h" #include "bus/hp_dio/hp98603a.h" #include "bus/hp_dio/hp98603b.h" #include "bus/hp_dio/hp98644.h" -#include "bus/ieee488/ieee488.h" +#include "bus/hp_dio/human_interface.h" + #include "screen.h" -#include "speaker.h" #include "softlist_dev.h" #define MAINCPU_TAG "maincpu" -#define IOCPU_TAG "iocpu" #define PTM6840_TAG "ptm" -#define MLC_TAG "mlc" -#define SN76494_TAG "sn76494" - -#define SN76494_CLOCK 333333 class hp9k3xx_state : public driver_device { @@ -88,10 +79,6 @@ public: hp9k3xx_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag), m_maincpu(*this, MAINCPU_TAG), - m_iocpu(*this, IOCPU_TAG), - m_mlc(*this, MLC_TAG), - m_sound(*this, SN76494_TAG), - m_tms9914(*this, "tms9914"), m_vram16(*this, "vram16"), m_vram(*this, "vram") { } @@ -108,10 +95,6 @@ public: private: required_device m_maincpu; - optional_device m_iocpu; - optional_device m_mlc; - optional_device m_sound; - optional_device m_tms9914; virtual void machine_reset() override; optional_shared_ptr m_vram16; @@ -125,16 +108,6 @@ private: DECLARE_READ32_MEMBER(buserror_r); DECLARE_WRITE32_MEMBER(buserror_w); - /* 8042 interface */ - DECLARE_WRITE8_MEMBER(iocpu_port1_w); - DECLARE_WRITE8_MEMBER(iocpu_port2_w); - DECLARE_READ8_MEMBER(iocpu_port1_r); - DECLARE_READ8_MEMBER(iocpu_test0_r); - - DECLARE_READ8_MEMBER(gpib_r); - DECLARE_WRITE8_MEMBER(gpib_w); - - DECLARE_WRITE_LINE_MEMBER(gpib_irq); DECLARE_WRITE32_MEMBER(led_w) { if (mem_mask != 0x000000ff) @@ -166,23 +139,18 @@ private: void hp9k380_map(address_map &map); void hp9k382_map(address_map &map); void hp9k3xx_common(address_map &map); - void iocpu_map(address_map &map); + + DECLARE_WRITE_LINE_MEMBER(dio_irq1_w) { m_maincpu->set_input_line_and_vector(M68K_IRQ_1, state, M68K_INT_ACK_AUTOVECTOR); }; + DECLARE_WRITE_LINE_MEMBER(dio_irq2_w) { m_maincpu->set_input_line_and_vector(M68K_IRQ_2, state, M68K_INT_ACK_AUTOVECTOR); }; + DECLARE_WRITE_LINE_MEMBER(dio_irq3_w) { m_maincpu->set_input_line_and_vector(M68K_IRQ_3, state, M68K_INT_ACK_AUTOVECTOR); }; + DECLARE_WRITE_LINE_MEMBER(dio_irq4_w) { m_maincpu->set_input_line_and_vector(M68K_IRQ_4, state, M68K_INT_ACK_AUTOVECTOR); }; + DECLARE_WRITE_LINE_MEMBER(dio_irq5_w) { m_maincpu->set_input_line_and_vector(M68K_IRQ_5, state, M68K_INT_ACK_AUTOVECTOR); }; + DECLARE_WRITE_LINE_MEMBER(dio_irq6_w) { m_maincpu->set_input_line_and_vector(M68K_IRQ_6, state, M68K_INT_ACK_AUTOVECTOR); }; + DECLARE_WRITE_LINE_MEMBER(dio_irq7_w) { m_maincpu->set_input_line_and_vector(M68K_IRQ_7, state, M68K_INT_ACK_AUTOVECTOR); }; DECLARE_WRITE_LINE_MEMBER(cpu_reset); - static constexpr uint8_t HIL_CS = 0x01; - static constexpr uint8_t HIL_WE = 0x02; - static constexpr uint8_t HIL_OE = 0x04; - static constexpr uint8_t LATCH_EN = 0x08; - static constexpr uint8_t KBD_RESET = 0x40; - static constexpr uint8_t SN76494_EN = 0x80; - - bool m_hil_read; - bool m_kbd_nmi; - uint8_t m_hil_data; - uint8_t m_latch_data; uint32_t m_lastpc; - bool gpib_irq_line; }; uint32_t hp9k3xx_state::hp_medres_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) @@ -215,9 +183,6 @@ void hp9k3xx_state::hp9k3xx_common(address_map &map) map(0x00000000, 0xffffffff).rw(FUNC(hp9k3xx_state::buserror_r), FUNC(hp9k3xx_state::buserror_w)); map(0x00000000, 0x0001ffff).rom().region("maincpu", 0).w(FUNC(hp9k3xx_state::led_w)); // writes to 1fffc are the LED - map(0x00428000, 0x00428003).rw(m_iocpu, FUNC(upi41_cpu_device::upi41_master_r), FUNC(upi41_cpu_device::upi41_master_w)).umask32(0x00ff00ff); - map(0x00470000, 0x0047001f).mirror(0x0000ffe0).rw(FUNC(hp9k3xx_state::gpib_r), FUNC(hp9k3xx_state::gpib_w)).umask16(0x00ff); - map(0x005f8000, 0x005f800f).rw(PTM6840_TAG, FUNC(ptm6840_device::read), FUNC(ptm6840_device::write)).umask32(0x00ff00ff); map(0x005f4000, 0x005f400f).ram(); // somehow coprocessor related - bootrom crashes if not present @@ -228,9 +193,6 @@ void hp9k3xx_state::hp9k310_map(address_map &map) { map(0x000000, 0x01ffff).rom().region("maincpu", 0).nopw(); // writes to 1fffc are the LED - map(0x428000, 0x428003).rw(m_iocpu, FUNC(upi41_cpu_device::upi41_master_r), FUNC(upi41_cpu_device::upi41_master_w)).umask16(0x00ff); - map(0x470000, 0x47001f).mirror(0x00ffe0).rw(FUNC(hp9k3xx_state::gpib_r), FUNC(hp9k3xx_state::gpib_w)).umask16(0x00ff); - map(0x510000, 0x510003).rw(FUNC(hp9k3xx_state::buserror16_r), FUNC(hp9k3xx_state::buserror16_w)); // no "Alpha display" map(0x538000, 0x538003).rw(FUNC(hp9k3xx_state::buserror16_r), FUNC(hp9k3xx_state::buserror16_w)); // no "Graphics" map(0x5c0000, 0x5c0003).rw(FUNC(hp9k3xx_state::buserror16_r), FUNC(hp9k3xx_state::buserror16_w)); // no add-on FP coprocessor @@ -306,10 +268,6 @@ void hp9k3xx_state::hp9k382_map(address_map &map) map(0x0051a000, 0x0051afff).rw(FUNC(hp9k3xx_state::buserror_r), FUNC(hp9k3xx_state::buserror_w)); // no "Alpha display" } -void hp9k3xx_state::iocpu_map(address_map &map) -{ -} - uint32_t hp9k3xx_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { return 0; @@ -321,7 +279,6 @@ INPUT_PORTS_END WRITE_LINE_MEMBER(hp9k3xx_state::cpu_reset) { - m_iocpu->reset(); } @@ -330,49 +287,6 @@ void hp9k3xx_state::machine_reset() m_maincpu->set_reset_callback(write_line_delegate(FUNC(hp9k3xx_state::cpu_reset), this)); } -WRITE_LINE_MEMBER(hp9k3xx_state::gpib_irq) -{ - gpib_irq_line = state; - m_maincpu->set_input_line(M68K_IRQ_3, state ? ASSERT_LINE : CLEAR_LINE); -} - -WRITE8_MEMBER(hp9k3xx_state::gpib_w) -{ - if (offset & 0x08) { - m_tms9914->reg8_w(space, offset & 0x07, data); - return; - } - LOG("gpib_w: %s %02X = %02X\n", machine().describe_context().c_str(), offset, data); -} - -READ8_MEMBER(hp9k3xx_state::gpib_r) -{ - uint8_t data = 0xff; - - if (offset & 0x8) { - data = m_tms9914->reg8_r(space, offset & 0x07); - return data; - } - - switch(offset) { - case 0: /* ID */ - data = 0x80; - break; - case 1: - /* Int control */ - data = 0x80 | (gpib_irq_line ? 0x40 : 0); - break; - case 2: - /* Address */ - data = (m_tms9914->cont_r() ? 0x0 : 0x40) | 0x81; - if (m_kbd_nmi) - data |= 0x04; - break; - } - LOG("gpib_r: %s %02X = %02X\n", machine().describe_context().c_str(), offset, data); - return data; -} - READ16_MEMBER(hp9k3xx_state::buserror16_r) { m_maincpu->set_input_line(M68K_LINE_BUSERROR, ASSERT_LINE); @@ -410,47 +324,6 @@ WRITE32_MEMBER(hp9k3xx_state::buserror_w) m_maincpu->set_input_line(M68K_LINE_BUSERROR, CLEAR_LINE); } -WRITE8_MEMBER(hp9k3xx_state::iocpu_port1_w) -{ - m_hil_data = data; -} - -WRITE8_MEMBER(hp9k3xx_state::iocpu_port2_w) -{ - if ((data & (HIL_CS|HIL_WE)) == 0) - m_mlc->write(space, (m_latch_data & 0xc0) >> 6, m_hil_data, 0xff); - - if ((data & SN76494_EN) == 0) - m_sound->write(m_hil_data); - - m_hil_read = ((data & (HIL_CS|HIL_OE)) == 0); - - if (!(data & LATCH_EN)) - m_latch_data = m_hil_data; - - m_maincpu->set_input_line(M68K_IRQ_1, data & 0x10 ? ASSERT_LINE : CLEAR_LINE); - - if (!(data & KBD_RESET)) { - m_maincpu->set_input_line(M68K_IRQ_7, ASSERT_LINE); - m_kbd_nmi = true; - } else { - m_maincpu->set_input_line(M68K_IRQ_7, CLEAR_LINE); - m_kbd_nmi = false; - } -} - -READ8_MEMBER(hp9k3xx_state::iocpu_port1_r) -{ - if (m_hil_read) - return m_mlc->read(space, (m_latch_data & 0xc0) >> 6, 0xff); - return 0xff; -} - -READ8_MEMBER(hp9k3xx_state::iocpu_test0_r) -{ - return !m_mlc->get_int(); -} - static void dio16_cards(device_slot_interface &device) { device.option_add("98543", HPDIO_98543); /* 98543 Medium Resolution Color Card */ @@ -458,53 +331,15 @@ static void dio16_cards(device_slot_interface &device) device.option_add("98603a", HPDIO_98603A); /* 98603A ROM BASIC (4.0) */ device.option_add("98603b", HPDIO_98603B); /* 98603B ROM BASIC (5.1) */ device.option_add("98644", HPDIO_98644); /* 98644 Async serial interface */ + device.option_add("human_interface", HPDIO_HUMAN_INTERFACE); } MACHINE_CONFIG_START(hp9k3xx_state::hp9k300) - MCFG_DEVICE_ADD(m_iocpu, I8042, 5000000) - MCFG_DEVICE_PROGRAM_MAP(iocpu_map) - MCFG_MCS48_PORT_P1_OUT_CB(WRITE8(*this, hp9k3xx_state, iocpu_port1_w)) - MCFG_MCS48_PORT_P2_OUT_CB(WRITE8(*this, hp9k3xx_state, iocpu_port2_w)) - MCFG_MCS48_PORT_P1_IN_CB(READ8(*this, hp9k3xx_state, iocpu_port1_r)) - MCFG_MCS48_PORT_T0_IN_CB(READ8(*this, hp9k3xx_state, iocpu_test0_r)) - - MCFG_DEVICE_ADD(m_mlc, HP_HIL_MLC, XTAL(8'000'000)) - MCFG_HP_HIL_SLOT_ADD(MLC_TAG, "hil1", hp_hil_devices, "hp_46021a") - ptm6840_device &ptm(PTM6840(config, PTM6840_TAG, 250000)); // from oscillator module next to the 6840 ptm.set_external_clocks(250000.0f, 0.0f, 250000.0f); ptm.o3_callback().set(PTM6840_TAG, FUNC(ptm6840_device::set_c2)); ptm.irq_callback().set_inputline("maincpu", M68K_IRQ_6); - SPEAKER(config, "mono").front_center(); - MCFG_DEVICE_ADD(SN76494_TAG, SN76494, SN76494_CLOCK) - MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.75) - - MCFG_DEVICE_ADD(m_tms9914, TMS9914, XTAL(5000000)) - MCFG_TMS9914_INT_WRITE_CB(WRITELINE(*this, hp9k3xx_state, gpib_irq)); - MCFG_TMS9914_DIO_READWRITE_CB(READ8(IEEE488_TAG, ieee488_device, dio_r), WRITE8(IEEE488_TAG, ieee488_device, host_dio_w)) - MCFG_TMS9914_EOI_WRITE_CB(WRITELINE(IEEE488_TAG, ieee488_device, host_eoi_w)) - MCFG_TMS9914_DAV_WRITE_CB(WRITELINE(IEEE488_TAG, ieee488_device, host_dav_w)) - MCFG_TMS9914_NRFD_WRITE_CB(WRITELINE(IEEE488_TAG, ieee488_device, host_nrfd_w)) - MCFG_TMS9914_NDAC_WRITE_CB(WRITELINE(IEEE488_TAG, ieee488_device, host_ndac_w)) - MCFG_TMS9914_IFC_WRITE_CB(WRITELINE(IEEE488_TAG, ieee488_device, host_ifc_w)) - MCFG_TMS9914_SRQ_WRITE_CB(WRITELINE(IEEE488_TAG, ieee488_device, host_srq_w)) - MCFG_TMS9914_ATN_WRITE_CB(WRITELINE(IEEE488_TAG, ieee488_device, host_atn_w)) - MCFG_TMS9914_REN_WRITE_CB(WRITELINE(IEEE488_TAG, ieee488_device, host_ren_w)) - - MCFG_IEEE488_SLOT_ADD("ieee0", 0, hp_ieee488_devices, "hp9122c") - MCFG_IEEE488_SLOT_ADD("ieee_rem", 0, remote488_devices, nullptr) - MCFG_IEEE488_BUS_ADD() - - MCFG_IEEE488_EOI_CALLBACK(WRITELINE(m_tms9914, tms9914_device, eoi_w)) - MCFG_IEEE488_DAV_CALLBACK(WRITELINE(m_tms9914, tms9914_device, dav_w)) - MCFG_IEEE488_NRFD_CALLBACK(WRITELINE(m_tms9914, tms9914_device, nrfd_w)) - MCFG_IEEE488_NDAC_CALLBACK(WRITELINE(m_tms9914, tms9914_device, ndac_w)) - MCFG_IEEE488_IFC_CALLBACK(WRITELINE(m_tms9914, tms9914_device, ifc_w)) - MCFG_IEEE488_SRQ_CALLBACK(WRITELINE(m_tms9914, tms9914_device, srq_w)) - MCFG_IEEE488_ATN_CALLBACK(WRITELINE(m_tms9914, tms9914_device, atn_w)) - MCFG_IEEE488_REN_CALLBACK(WRITELINE(m_tms9914, tms9914_device, ren_w)) - MCFG_SOFTWARE_LIST_ADD("flop_list", "hp9k3xx_flop") MACHINE_CONFIG_END @@ -516,6 +351,14 @@ MACHINE_CONFIG_START(hp9k3xx_state::hp9k310) bus::hp_dio::dio16_device &dio16(DIO16(config, "diobus", 0)); dio16.set_cputag(m_maincpu); + dio16.irq1_out_cb().set(FUNC(hp9k3xx_state::dio_irq1_w)); + dio16.irq2_out_cb().set(FUNC(hp9k3xx_state::dio_irq2_w)); + dio16.irq3_out_cb().set(FUNC(hp9k3xx_state::dio_irq3_w)); + dio16.irq4_out_cb().set(FUNC(hp9k3xx_state::dio_irq4_w)); + dio16.irq5_out_cb().set(FUNC(hp9k3xx_state::dio_irq5_w)); + dio16.irq6_out_cb().set(FUNC(hp9k3xx_state::dio_irq6_w)); + dio16.irq7_out_cb().set(FUNC(hp9k3xx_state::dio_irq7_w)); + DIO16_SLOT(config, "sl1", 0, "diobus", dio16_cards, "98544", false); DIO16_SLOT(config, "sl2", 0, "diobus", dio16_cards, "98603b", false); DIO16_SLOT(config, "sl3", 0, "diobus", dio16_cards, "98644", false); @@ -532,6 +375,15 @@ MACHINE_CONFIG_START(hp9k3xx_state::hp9k320) bus::hp_dio::dio16_device &dio32(DIO32(config, "diobus", 0)); dio32.set_cputag(m_maincpu); + dio32.irq1_out_cb().set(FUNC(hp9k3xx_state::dio_irq1_w)); + dio32.irq2_out_cb().set(FUNC(hp9k3xx_state::dio_irq2_w)); + dio32.irq3_out_cb().set(FUNC(hp9k3xx_state::dio_irq3_w)); + dio32.irq4_out_cb().set(FUNC(hp9k3xx_state::dio_irq4_w)); + dio32.irq5_out_cb().set(FUNC(hp9k3xx_state::dio_irq5_w)); + dio32.irq6_out_cb().set(FUNC(hp9k3xx_state::dio_irq6_w)); + dio32.irq7_out_cb().set(FUNC(hp9k3xx_state::dio_irq7_w)); + + DIO32_SLOT(config, "sl0", 0, "diobus", dio16_cards, "human_interface", true); DIO32_SLOT(config, "sl1", 0, "diobus", dio16_cards, "98544", false); DIO32_SLOT(config, "sl2", 0, "diobus", dio16_cards, "98603b", false); DIO32_SLOT(config, "sl3", 0, "diobus", dio16_cards, "98644", false); @@ -547,6 +399,15 @@ MACHINE_CONFIG_START(hp9k3xx_state::hp9k330) bus::hp_dio::dio16_device &dio32(DIO32(config, "diobus", 0)); dio32.set_cputag(m_maincpu); + dio32.irq1_out_cb().set(FUNC(hp9k3xx_state::dio_irq1_w)); + dio32.irq2_out_cb().set(FUNC(hp9k3xx_state::dio_irq2_w)); + dio32.irq3_out_cb().set(FUNC(hp9k3xx_state::dio_irq3_w)); + dio32.irq4_out_cb().set(FUNC(hp9k3xx_state::dio_irq4_w)); + dio32.irq5_out_cb().set(FUNC(hp9k3xx_state::dio_irq5_w)); + dio32.irq6_out_cb().set(FUNC(hp9k3xx_state::dio_irq6_w)); + dio32.irq7_out_cb().set(FUNC(hp9k3xx_state::dio_irq7_w)); + + DIO32_SLOT(config, "sl0", 0, "diobus", dio16_cards, "human_interface", true); DIO32_SLOT(config, "sl1", 0, "diobus", dio16_cards, "98544", false); DIO32_SLOT(config, "sl2", 0, "diobus", dio16_cards, "98603b", false); DIO32_SLOT(config, "sl3", 0, "diobus", dio16_cards, "98644", false); @@ -599,10 +460,6 @@ ROM_START( hp9k310 ) ROM_LOAD16_BYTE( "1818-3771.bin", 0x000001, 0x008000, CRC(b9e4e3ad) SHA1(ed6f1fad94a15d95362701dbe124b52877fc3ec4) ) ROM_LOAD16_BYTE( "1818-3772.bin", 0x000000, 0x008000, CRC(a3665919) SHA1(ec1bc7e5b7990a1b09af947a06401e8ed3cb0516) ) - ROM_REGION( 0x800, IOCPU_TAG, 0 ) - ROM_LOAD( "1820-4784_1.bin", 0x000000, 0x000800, CRC(e929044a) SHA1(90849a10bdb8c6e38e73ce027c9c0ad8b3956b1b) ) - ROM_LOAD( "1820-4784_2.bin", 0x000000, 0x000800, CRC(8defcf50) SHA1(d3abfea468a43db7c2369500a3e390e77a8e22e6) ) - ROM_REGION( 0x4000, "graphics", ROMREGION_ERASEFF | ROMREGION_BE ) ROM_LOAD16_BYTE( "98544_1818-1999.bin", 0x000000, 0x002000, CRC(8c7d6480) SHA1(d2bcfd39452c38bc652df39f84c7041cfdf6bd51) ) ROM_END @@ -613,18 +470,12 @@ ROM_START( hp9k320 ) ROM_LOAD16_BYTE( "5061-6539.bin", 0x000000, 0x004000, CRC(a7ff104c) SHA1(c640fe68314654716bd41b04c6a7f4e560036c7e) ) ROM_LOAD16_BYTE( "5061-6540.bin", 0x008001, 0x004000, CRC(4f6796d6) SHA1(fd254897ac1afb8628f40ea93213f60a082c8d36) ) ROM_LOAD16_BYTE( "5061-6541.bin", 0x008000, 0x004000, CRC(39d32998) SHA1(6de1bda75187b0878c03c074942b807cf2924f0e) ) - - ROM_REGION( 0x800, IOCPU_TAG, 0 ) - ROM_LOAD( "1820-4784.bin", 0x000000, 0x000800, CRC(e929044a) SHA1(90849a10bdb8c6e38e73ce027c9c0ad8b3956b1b) ) ROM_END ROM_START( hp9k330 ) ROM_REGION( 0x20000, MAINCPU_TAG, 0 ) ROM_LOAD16_BYTE( "1818-4416.bin", 0x000000, 0x010000, CRC(cd71e85e) SHA1(3e83a80682f733417fdc3720410e45a2cfdcf869) ) ROM_LOAD16_BYTE( "1818-4417.bin", 0x000001, 0x010000, CRC(374d49db) SHA1(a12cbf6c151e2f421da4571000b5dffa3ef403b3) ) - - ROM_REGION( 0x800, IOCPU_TAG, 0 ) - ROM_LOAD( "1820-4784.bin", 0x000000, 0x000800, CRC(e929044a) SHA1(90849a10bdb8c6e38e73ce027c9c0ad8b3956b1b) ) ROM_END ROM_START( hp9k332 ) @@ -632,9 +483,6 @@ ROM_START( hp9k332 ) ROM_LOAD16_BYTE( "1818-4796.bin", 0x000000, 0x010000, CRC(8a7642da) SHA1(7ba12adcea85916d18b021255391bec806c32e94) ) ROM_LOAD16_BYTE( "1818-4797.bin", 0x000001, 0x010000, CRC(98129eb1) SHA1(f3451a854060f1be1bee9f17c5c198b4b1cd61ac) ) - ROM_REGION( 0x800, IOCPU_TAG, 0 ) - ROM_LOAD( "1820-4784.bin", 0x000000, 0x000800, CRC(e929044a) SHA1(90849a10bdb8c6e38e73ce027c9c0ad8b3956b1b) ) - ROM_REGION( 0x4000, "graphics", ROMREGION_ERASEFF | ROMREGION_BE | ROMREGION_32BIT ) ROM_LOAD16_BYTE( "5180-0471.bin", 0x000001, 0x002000, CRC(7256af2e) SHA1(584e8d4dcae8c898c1438125dc9c4709631b32f7) ) ROM_END @@ -644,34 +492,23 @@ ROM_START( hp9k340 ) ROM_LOAD16_BYTE( "1818-4416.bin", 0x000000, 0x010000, CRC(cd71e85e) SHA1(3e83a80682f733417fdc3720410e45a2cfdcf869) ) ROM_LOAD16_BYTE( "1818-4417.bin", 0x000001, 0x010000, CRC(374d49db) SHA1(a12cbf6c151e2f421da4571000b5dffa3ef403b3) ) - ROM_REGION( 0x800, IOCPU_TAG, 0 ) - ROM_LOAD( "1820-4784.bin", 0x000000, 0x000800, CRC(e929044a) SHA1(90849a10bdb8c6e38e73ce027c9c0ad8b3956b1b) ) ROM_END ROM_START( hp9k370 ) ROM_REGION( 0x20000, MAINCPU_TAG, 0 ) ROM_LOAD16_BYTE( "1818-4416.bin", 0x000000, 0x010000, CRC(cd71e85e) SHA1(3e83a80682f733417fdc3720410e45a2cfdcf869) ) ROM_LOAD16_BYTE( "1818-4417.bin", 0x000001, 0x010000, CRC(374d49db) SHA1(a12cbf6c151e2f421da4571000b5dffa3ef403b3) ) - - ROM_REGION( 0x800, IOCPU_TAG, 0 ) - ROM_LOAD( "1820-4784.bin", 0x000000, 0x000800, CRC(e929044a) SHA1(90849a10bdb8c6e38e73ce027c9c0ad8b3956b1b) ) ROM_END ROM_START( hp9k380 ) ROM_REGION( 0x20000, MAINCPU_TAG, 0 ) ROM_LOAD16_WORD_SWAP( "1818-5062_98754_9000-380_27c210.bin", 0x000000, 0x020000, CRC(500a0797) SHA1(4c0a3929e45202a2689e353657e5c4b58ff9a1fd) ) - - ROM_REGION( 0x800, IOCPU_TAG, 0 ) - ROM_LOAD( "1820-4784.bin", 0x000000, 0x000800, CRC(e929044a) SHA1(90849a10bdb8c6e38e73ce027c9c0ad8b3956b1b) ) ROM_END ROM_START( hp9k382 ) ROM_REGION( 0x20000, MAINCPU_TAG, 0 ) ROM_LOAD16_WORD_SWAP( "1818-5468_27c1024.bin", 0x000000, 0x020000, CRC(d1d9ef13) SHA1(6bbb17b9adad402fbc516dc2f3143e9c38ceef8e) ) - ROM_REGION( 0x800, IOCPU_TAG, 0 ) - ROM_LOAD( "1820-4784.bin", 0x000000, 0x000800, CRC(e929044a) SHA1(90849a10bdb8c6e38e73ce027c9c0ad8b3956b1b) ) - ROM_REGION( 0x2000, "unknown", ROMREGION_ERASEFF | ROMREGION_BE | ROMREGION_32BIT ) ROM_LOAD( "1818-5282_8ce61e951207_28c64.bin", 0x000000, 0x002000, CRC(740442f3) SHA1(ab65bd4eec1024afb97fc2dd3bd3f017e90f49ae) ) ROM_END -- cgit v1.2.3 From ad3ad560a63a2c5a500917c4eebd2fd147ffb399 Mon Sep 17 00:00:00 2001 From: dxl <41547105+hp9k@users.noreply.github.com> Date: Tue, 9 Oct 2018 19:46:35 +0200 Subject: hp9k_3xx: add HP98620 DMA controller (#4094) * hp9k_3xx: add HP98620 DMA controller * hp98620: remove unused defines (nw) --- scripts/src/bus.lua | 2 + src/devices/bus/hp_dio/hp98620.cpp | 383 +++++++++++++++++++++++++++++++++++++ src/devices/bus/hp_dio/hp98620.h | 128 +++++++++++++ src/devices/bus/hp_dio/hp_dio.cpp | 20 +- src/devices/bus/hp_dio/hp_dio.h | 3 +- src/mame/drivers/hp9k_3xx.cpp | 20 +- 6 files changed, 531 insertions(+), 25 deletions(-) create mode 100644 src/devices/bus/hp_dio/hp98620.cpp create mode 100644 src/devices/bus/hp_dio/hp98620.h (limited to 'scripts/src') diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index 86fade73bff..92c516ecdf8 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -891,6 +891,8 @@ if (BUSES["HPDIO"]~=null) then MAME_DIR .. "src/devices/bus/hp_dio/hp98603a.h", MAME_DIR .. "src/devices/bus/hp_dio/hp98603b.cpp", MAME_DIR .. "src/devices/bus/hp_dio/hp98603b.h", + MAME_DIR .. "src/devices/bus/hp_dio/hp98620.cpp", + MAME_DIR .. "src/devices/bus/hp_dio/hp98620.h", MAME_DIR .. "src/devices/bus/hp_dio/hp98644.cpp", MAME_DIR .. "src/devices/bus/hp_dio/hp98644.h", MAME_DIR .. "src/devices/bus/hp_dio/human_interface.cpp", diff --git a/src/devices/bus/hp_dio/hp98620.cpp b/src/devices/bus/hp_dio/hp98620.cpp new file mode 100644 index 00000000000..457b2bb95bb --- /dev/null +++ b/src/devices/bus/hp_dio/hp98620.cpp @@ -0,0 +1,383 @@ +// license:BSD-3-Clause +// copyright-holders:Sven Schnelle +/*************************************************************************** + + HP98620 DMA controller + +***************************************************************************/ + +#include "emu.h" + +#define VERBOSE 0 +#include "logmacro.h" +#include "hp98620.h" + + +DEFINE_DEVICE_TYPE_NS(HPDIO_98620, bus::hp_dio, dio16_98620_device, "hp98620", "HP98620 DMA Controller") + +namespace bus { + namespace hp_dio { + +dio16_98620_device::dio16_98620_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + dio16_98620_device(mconfig, HPDIO_98620, tag, owner, clock) +{ +} + +dio16_98620_device::dio16_98620_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, type, tag, owner, clock), + device_dio32_card_interface(mconfig, *this), + m_irq_state(false) +{ +} + +static INPUT_PORTS_START(hp98620_port) +INPUT_PORTS_END + +ioport_constructor dio16_98620_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(hp98620_port); +} + +void dio16_98620_device::device_start() +{ + m_installed_io = false; + + save_item(NAME(m_regs[0].address)); + save_item(NAME(m_regs[0].tc)); + save_item(NAME(m_regs[0].control)); + save_item(NAME(m_regs[0].irq_level)); + save_item(NAME(m_regs[0].tsz)); + save_item(NAME(m_regs[0].subcount)); + save_item(NAME(m_regs[0].irq)); + save_item(NAME(m_regs[0].ie)); + save_item(NAME(m_regs[0].armed)); + save_item(NAME(m_regs[0].dma_out)); + save_item(NAME(m_regs[0].dma_pri)); + save_item(NAME(m_regs[0].lword)); + save_item(NAME(m_regs[0].word)); + + + save_item(NAME(m_regs[1].address)); + save_item(NAME(m_regs[1].tc)); + save_item(NAME(m_regs[1].control)); + save_item(NAME(m_regs[1].irq_level)); + save_item(NAME(m_regs[1].tsz)); + save_item(NAME(m_regs[1].subcount)); + save_item(NAME(m_regs[1].irq)); + save_item(NAME(m_regs[1].ie)); + save_item(NAME(m_regs[1].armed)); + save_item(NAME(m_regs[1].dma_out)); + save_item(NAME(m_regs[1].dma_pri)); + save_item(NAME(m_regs[1].lword)); + save_item(NAME(m_regs[1].word)); + + save_item(NAME(m_installed_io)); + save_item(NAME(m_control)); + save_item(NAME(m_data)); + save_item(NAME(m_irq_state)); + save_item(NAME(dmar)); +} + +void dio16_98620_device::map(address_map &map) +{ + +} +void dio16_98620_device::device_reset() +{ + if (!m_installed_io) + { + program_space()->install_readwrite_handler(0x500000, 0x50020f, + read16_delegate(FUNC(dio16_98620_device::dma_r), this), + write16_delegate(FUNC(dio16_98620_device::dma_w), this)); + m_installed_io = true; + } + m_control = 0; + m_irq_state = false; +} + +uint16_t dio16_98620_device::get_ctrl(const int channel) +{ + uint16_t ret = 0; + + if (m_regs[channel].ie) + ret |= REG_CONTROL_IE; + if (m_regs[channel].tsz == 2) + ret |= REG_CONTROL_WORD; + if (m_regs[channel].tsz == 4) + ret |= REG_1TQ4_CONTROL_LWORD; + if (m_regs[channel].dma_out) + ret |= REG_CONTROL_OUT; + if (m_regs[channel].dma_pri) + ret |= REG_CONTROL_PRI; + + ret |= ((m_regs[channel].irq_level-3) & REG_CONTROL_INT_MASK) << REG_CONTROL_INT_SHIFT; + + return ret; +} + +READ16_MEMBER(dio16_98620_device::dma_r) +{ + + uint16_t ret = 0; + + switch(offset << 1) { + case REG0_RESET_ARM_INT: + m_regs[0].irq = false; + m_regs[0].armed = false; + update_irq(); + ret = 0x00; + break; + case REG1_RESET_ARM_INT: + m_regs[1].irq = false; + m_regs[1].armed = false; + update_irq(); + ret = 0x00; + break; + case REG0_TRANSFER_COUNT: + ret = m_regs[0].tc & 0xffff; + break; + case REG1_TRANSFER_COUNT: + ret = m_regs[1].tc & 0xffff; + break; + case REG0_STATUS: + ret = 0; + if (m_regs[0].armed) + ret |= REG_STATUS_ARMED; + if (m_regs[0].irq) + ret |= REG_STATUS_INT; + break; + case REG1_STATUS: + ret = 0; + if (m_regs[1].armed) + ret |= REG_STATUS_ARMED; + if (m_regs[1].irq) + ret |= REG_STATUS_INT; + break; + case REG_1TQ4_ID_LOW: + ret = 0x3230; + break; + case REG_1TQ4_ID_HIGH: + ret = 0x4330; + break; + case REG0_1TQ4_ADDRESS_LOW: + ret = m_regs[0].address & 0xffff; + break; + case REG0_1TQ4_ADDRESS_HIGH: + ret = m_regs[0].address >> 16; + break; + case REG1_1TQ4_ADDRESS_LOW: + ret = m_regs[1].address & 0xffff; + break; + case REG1_1TQ4_ADDRESS_HIGH: + ret = m_regs[1].address >> 16; + break; + + case REG0_1TQ4_TRANSFER_COUNT_LOW: + ret = m_regs[0].tc & 0xffff; + break; + case REG0_1TQ4_TRANSFER_COUNT_HIGH: + ret = m_regs[0].tc >> 16; + break; + case REG1_1TQ4_TRANSFER_COUNT_LOW: + ret = m_regs[1].tc & 0xffff; + break; + case REG1_1TQ4_TRANSFER_COUNT_HIGH: + ret = m_regs[1].tc >> 16; + break; + case REG0_1TQ4_CONTROL: + ret = m_regs[0].control; + break; + case REG1_1TQ4_CONTROL: + ret = m_regs[1].control; + break; + case REG0_1TQ4_STATUS: + ret = 0; + break; + case REG1_1TQ4_STATUS: + ret = 0; + break; + default: + LOG("%s: unknown register read: %02X\n", __FUNCTION__, offset << 1); + break; + } + LOG("dma_r: offset=%02X ret=%02X\n", offset << 1, ret); + return ret; +} + +void dio16_98620_device::update_ctrl(const int channel, const uint16_t data, const bool is_1tq4) +{ + assert(channel < 2); + + m_regs[channel].control = data; + m_regs[channel].ie = data & REG_CONTROL_IE; + m_regs[channel].irq_level = 3 + ((data >> REG_CONTROL_INT_SHIFT) & REG_CONTROL_INT_MASK); + m_regs[channel].lword = (data & REG_1TQ4_CONTROL_LWORD) && is_1tq4; + m_regs[channel].word = data & REG_CONTROL_WORD; + m_regs[channel].dma_out = data & REG_CONTROL_OUT; + if (data & REG_1TQ4_CONTROL_LWORD) + m_regs[channel].tsz = 4; + else if (data & REG_CONTROL_WORD) + m_regs[channel].tsz = 2; + else + m_regs[channel].tsz = 1; + + if ((data & REG_1TQ4_CONTROL_START) || !is_1tq4) { + LOG("DMA Channel %d: addr %08x, tc %d, size %d, int %sabled on IRQ %d\n", channel, + m_regs[channel].address, + (m_regs[channel].tc+1)*m_regs[channel].tsz, + m_regs[channel].tsz, + m_regs[channel].ie ? "en" : "dis", + m_regs[channel].irq_level); + m_regs[channel].subcount = m_regs[channel].tsz-1; + m_regs[channel].armed = true; + m_regs[channel].irq = false; + if (dmar[channel]) + dma_transfer(channel); + + } +} +WRITE16_MEMBER(dio16_98620_device::dma_w) +{ + LOG("dma_w: offset=%02X, data=%02X\n", offset << 1, data); + + switch(offset << 1) { + case REG0_1TQ4_ADDRESS_HIGH: + case REG0_ADDRESS_HIGH: + m_regs[0].address &= 0xffff; + m_regs[0].address |= (data << 16); + break; + case REG0_1TQ4_ADDRESS_LOW: + case REG0_ADDRESS_LOW: + m_regs[0].address &= 0xffff0000; + m_regs[0].address |= data; + break; + case REG1_1TQ4_ADDRESS_HIGH: + case REG1_ADDRESS_HIGH: + m_regs[1].address &= 0xffff; + m_regs[1].address |= (data << 16); + break; + case REG1_1TQ4_ADDRESS_LOW: + case REG1_ADDRESS_LOW: + m_regs[1].address &= 0xffff0000; + m_regs[1].address |= data; + break; + case REG0_TRANSFER_COUNT: + m_regs[0].tc = data; + break; + case REG0_1TQ4_TRANSFER_COUNT_HIGH: + m_regs[0].tc &= 0xffff; + m_regs[0].tc |= (data << 16); + break; + case REG0_1TQ4_TRANSFER_COUNT_LOW: + m_regs[0].tc &= 0xffff0000; + m_regs[0].tc |= data; + break; + case REG1_1TQ4_TRANSFER_COUNT_HIGH: + m_regs[1].tc &= 0xffff; + m_regs[1].tc |= (data << 16); + break; + case REG1_1TQ4_TRANSFER_COUNT_LOW: + m_regs[1].tc &= 0xffff0000; + m_regs[1].tc |= data; + break; + case REG1_TRANSFER_COUNT: + m_regs[1].tc = data; + break; + + case REG0_CONTROL_ARM: + update_ctrl(0, data, false); + break; + + case REG1_CONTROL_ARM: + update_ctrl(1, data, false); + break; + + case REG0_1TQ4_CONTROL: + update_ctrl(0, data, true); + break; + + case REG1_1TQ4_CONTROL: + update_ctrl(1, data, true); + break; + + default: + LOG("%s: unknown register write: %02X\n", __FUNCTION__, offset << 1); + break; + } +} + +void dio16_98620_device::update_irq() +{ + irq3_out((m_regs[0].irq_level == 3 && m_regs[0].irq && m_regs[0].ie) || + (m_regs[1].irq_level == 3 && m_regs[1].irq && m_regs[1].ie)); + + irq4_out((m_regs[0].irq_level == 4 && m_regs[0].irq && m_regs[0].ie) || + (m_regs[1].irq_level == 4 && m_regs[1].irq && m_regs[1].ie)); + + irq5_out((m_regs[0].irq_level == 5 && m_regs[0].irq && m_regs[0].ie) || + (m_regs[1].irq_level == 5 && m_regs[1].irq && m_regs[1].ie)); + + irq6_out((m_regs[0].irq_level == 6 && m_regs[0].irq && m_regs[0].ie) || + (m_regs[1].irq_level == 6 && m_regs[1].irq && m_regs[1].ie)); + + irq7_out((m_regs[0].irq_level == 7 && m_regs[0].irq && m_regs[0].ie) || + (m_regs[1].irq_level == 7 && m_regs[1].irq && m_regs[1].ie)); +} + +void dio16_98620_device::dma_transfer(int channel) +{ + assert(channel < 2); + + if (!(m_regs[channel].armed)) + return; + + LOG("dma_transfer %s: tc %d/%d\n", m_regs[channel].dma_out ? "out" : "in", + m_regs[channel].tc, m_regs[channel].subcount); + + + if (m_regs[channel].dma_out) { + dmack_w_out(channel, program_space()->read_byte(m_regs[channel].address++)); + } else { + program_space()->write_byte(m_regs[channel].address++, dmack_r_out(channel)); + + } + + if (m_regs[channel].subcount == 0) { + if (m_regs[channel].tc-- == 0) { + LOG("DMA%d done\n", channel); + m_regs[channel].armed = false; + m_regs[channel].irq = true; + update_irq(); + return; + } + + m_regs[channel].subcount = m_regs[channel].tsz; + } + + m_regs[channel].subcount--; +} + +WRITE_LINE_MEMBER(dio16_98620_device::dmar0_in) +{ + LOG("%s: %d\n", __FUNCTION__, state); + dmar[0] = state; + if (!state) + return; + + dma_transfer(0); +} + +WRITE_LINE_MEMBER(dio16_98620_device::dmar1_in) +{ + LOG("%s: %d\n", __FUNCTION__, state); + dmar[1] = state; + + if (!state) + return; + + dma_transfer(1); +} + +} // namespace bus::hp_dio +} // namespace bus + diff --git a/src/devices/bus/hp_dio/hp98620.h b/src/devices/bus/hp_dio/hp98620.h new file mode 100644 index 00000000000..22b09c3732e --- /dev/null +++ b/src/devices/bus/hp_dio/hp98620.h @@ -0,0 +1,128 @@ +// license:BSD-3-Clause +// copyright-holders:Sven Schnelle + +#ifndef MAME_BUS_HPDIO_98620_H +#define MAME_BUS_HPDIO_98620_H + +#pragma once + +#include "hp_dio.h" + + +namespace bus { + namespace hp_dio { + +class dio16_98620_device : + public device_t, + public device_dio32_card_interface +{ +public: + // construction/destruction + dio16_98620_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + void map(address_map &map); +protected: + dio16_98620_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + + virtual ioport_constructor device_input_ports() const override; + + DECLARE_READ16_MEMBER(dma_r); + DECLARE_WRITE16_MEMBER(dma_w); + + DECLARE_WRITE_LINE_MEMBER(irq_w); + +private: + + static constexpr int REG0_RESET_ARM_INT = 0x00; + static constexpr int REG0_ADDRESS_HIGH = 0x00; + static constexpr int REG0_ADDRESS_LOW = 0x02; + static constexpr int REG0_TRANSFER_COUNT = 0x04; + static constexpr int REG0_CONTROL_ARM = 0x06; + static constexpr int REG0_STATUS = 0x06; + + static constexpr int REG1_RESET_ARM_INT = 0x08; + static constexpr int REG1_ADDRESS_HIGH = 0x08; + static constexpr int REG1_ADDRESS_LOW = 0x0a; + static constexpr int REG1_TRANSFER_COUNT = 0x0c; + static constexpr int REG1_CONTROL_ARM = 0x0e; + static constexpr int REG1_STATUS = 0x0e; + + static constexpr uint8_t REG_CONTROL_IE = 1 << 0; + static constexpr uint8_t REG_CONTROL_WORD = 1 << 1; + static constexpr uint8_t REG_CONTROL_OUT = 1 << 2; + static constexpr uint8_t REG_CONTROL_PRI = 1 << 3; + static constexpr uint8_t REG_CONTROL_INT_MASK = 0x7; + static constexpr int REG_CONTROL_INT_SHIFT = 4; + + + static constexpr uint8_t REG_STATUS_ARMED = 1 << 0; + static constexpr uint8_t REG_STATUS_INT = 1 << 1; + + /* general control registers */ + static constexpr int REG_1TQ4_ID_LOW = 0x10; + static constexpr int REG_1TQ4_ID_HIGH = 0x12; + + /* channel specific registers */ + static constexpr int REG0_1TQ4_ADDRESS_LOW = 0x100; + static constexpr int REG0_1TQ4_ADDRESS_HIGH = 0x102; + static constexpr int REG0_1TQ4_TRANSFER_COUNT_LOW = 0x104; + static constexpr int REG0_1TQ4_TRANSFER_COUNT_HIGH = 0x106; + static constexpr int REG0_1TQ4_CONTROL = 0x108; + static constexpr int REG0_1TQ4_STATUS = 0x10a; + + static constexpr uint16_t REG_1TQ4_CONTROL_LWORD = 1 << 8; + static constexpr uint16_t REG_1TQ4_CONTROL_START = 1 << 15; + + /* registers */ + static constexpr int REG1_1TQ4_ADDRESS_HIGH = 0x200; + static constexpr int REG1_1TQ4_ADDRESS_LOW = 0x202; + static constexpr int REG1_1TQ4_TRANSFER_COUNT_HIGH = 0x204; + static constexpr int REG1_1TQ4_TRANSFER_COUNT_LOW = 0x206; + static constexpr int REG1_1TQ4_CONTROL = 0x208; + static constexpr int REG1_1TQ4_STATUS = 0x20a; + + WRITE_LINE_MEMBER(dmar0_in) override; + WRITE_LINE_MEMBER(dmar1_in) override; + + void dma_transfer(int channel); + void update_irq(); + void update_ctrl(const int channel, const uint16_t data, const bool is_1tq4); + uint16_t get_ctrl(const int channel); + + bool m_installed_io; + uint8_t m_control; + uint8_t m_data; + bool m_irq_state; + + struct dma_regs { + uint32_t address; + uint32_t tc; + uint32_t control; + /* control register */ + int irq_level; + int tsz; + int subcount; + + bool irq; + bool ie; + bool armed; + + bool dma_out; + bool dma_pri; // TODO + bool lword; + bool word; + } m_regs[2]; + + bool dmar[2]; +}; +} +} + +DECLARE_DEVICE_TYPE_NS(HPDIO_98620, bus::hp_dio, dio16_98620_device) + +#endif // MAME_BUS_HPDIO_98620_H diff --git a/src/devices/bus/hp_dio/hp_dio.cpp b/src/devices/bus/hp_dio/hp_dio.cpp index b6a57b006ba..459172a4ffd 100644 --- a/src/devices/bus/hp_dio/hp_dio.cpp +++ b/src/devices/bus/hp_dio/hp_dio.cpp @@ -12,7 +12,9 @@ #include "hp98544.h" #include "hp98603a.h" #include "hp98603b.h" +#include "hp98620.h" #include "hp98644.h" +#include "human_interface.h" //************************************************************************** // GLOBAL VARIABLES @@ -350,11 +352,17 @@ void device_dio32_card_interface::interface_pre_start() } // namespace bus::hp_dio } // namespace bus -void hpdio_cards(device_slot_interface & device) +void dio16_cards(device_slot_interface & device) { - device.option_add("hp98543", HPDIO_98543); - device.option_add("hp98544", HPDIO_98544); - device.option_add("hp98603a", HPDIO_98603A); - device.option_add("hp98603b", HPDIO_98603B); - device.option_add("hp98644", HPDIO_98644); + device.option_add("98543", HPDIO_98543); + device.option_add("98544", HPDIO_98544); + device.option_add("98603a", HPDIO_98603A); + device.option_add("98603b", HPDIO_98603B); + device.option_add("98644", HPDIO_98644); + device.option_add("human_interface", HPDIO_HUMAN_INTERFACE); +} + +void dio32_cards(device_slot_interface & device) +{ + device.option_add("98620", HPDIO_98620); } diff --git a/src/devices/bus/hp_dio/hp_dio.h b/src/devices/bus/hp_dio/hp_dio.h index d44a9e3bf66..e7f09969ca8 100644 --- a/src/devices/bus/hp_dio/hp_dio.h +++ b/src/devices/bus/hp_dio/hp_dio.h @@ -290,6 +290,7 @@ DECLARE_DEVICE_TYPE_NS(DIO32, bus::hp_dio, dio32_device) DECLARE_DEVICE_TYPE_NS(DIO32_SLOT, bus::hp_dio, dio32_slot_device) DECLARE_DEVICE_TYPE_NS(DIO16, bus::hp_dio, dio16_device) -void hpdio_cards(device_slot_interface &device); +void dio16_cards(device_slot_interface &device); +void dio32_cards(device_slot_interface &device); #endif // MAME_BUS_HPDIO_HPDIO_H diff --git a/src/mame/drivers/hp9k_3xx.cpp b/src/mame/drivers/hp9k_3xx.cpp index 4632301e262..f3f3b2de349 100644 --- a/src/mame/drivers/hp9k_3xx.cpp +++ b/src/mame/drivers/hp9k_3xx.cpp @@ -58,14 +58,7 @@ #include "logmacro.h" #include "cpu/m68000/m68000.h" #include "machine/6840ptm.h" -#include "sound/sn76496.h" #include "bus/hp_dio/hp_dio.h" -#include "bus/hp_dio/hp98543.h" -#include "bus/hp_dio/hp98544.h" -#include "bus/hp_dio/hp98603a.h" -#include "bus/hp_dio/hp98603b.h" -#include "bus/hp_dio/hp98644.h" -#include "bus/hp_dio/human_interface.h" #include "screen.h" #include "softlist_dev.h" @@ -324,16 +317,6 @@ WRITE32_MEMBER(hp9k3xx_state::buserror_w) m_maincpu->set_input_line(M68K_LINE_BUSERROR, CLEAR_LINE); } -static void dio16_cards(device_slot_interface &device) -{ - device.option_add("98543", HPDIO_98543); /* 98543 Medium Resolution Color Card */ - device.option_add("98544", HPDIO_98544); /* 98544 High Resolution Monochrome Card */ - device.option_add("98603a", HPDIO_98603A); /* 98603A ROM BASIC (4.0) */ - device.option_add("98603b", HPDIO_98603B); /* 98603B ROM BASIC (5.1) */ - device.option_add("98644", HPDIO_98644); /* 98644 Async serial interface */ - device.option_add("human_interface", HPDIO_HUMAN_INTERFACE); -} - MACHINE_CONFIG_START(hp9k3xx_state::hp9k300) ptm6840_device &ptm(PTM6840(config, PTM6840_TAG, 250000)); // from oscillator module next to the 6840 ptm.set_external_clocks(250000.0f, 0.0f, 250000.0f); @@ -387,7 +370,8 @@ MACHINE_CONFIG_START(hp9k3xx_state::hp9k320) DIO32_SLOT(config, "sl1", 0, "diobus", dio16_cards, "98544", false); DIO32_SLOT(config, "sl2", 0, "diobus", dio16_cards, "98603b", false); DIO32_SLOT(config, "sl3", 0, "diobus", dio16_cards, "98644", false); - DIO32_SLOT(config, "sl4", 0, "diobus", dio16_cards, nullptr, false); + DIO32_SLOT(config, "sl4", 0, "diobus", dio32_cards, "98620", false); + DIO32_SLOT(config, "sl5", 0, "diobus", dio16_cards, nullptr, false); MACHINE_CONFIG_END MACHINE_CONFIG_START(hp9k3xx_state::hp9k330) -- cgit v1.2.3 From c0a6d6bf2350a1d4bcf887b4cde0d0cba891e1af Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Tue, 9 Oct 2018 20:11:24 +0200 Subject: hp9k_3xx: add HP98265A SCSI controller (nw) --- scripts/src/bus.lua | 2 + src/devices/bus/hp_dio/hp98265a.cpp | 308 ++++++++++++++++++++++++++++++++++++ src/devices/bus/hp_dio/hp98265a.h | 72 +++++++++ src/devices/bus/hp_dio/hp_dio.cpp | 2 + src/mame/drivers/hp9k_3xx.cpp | 3 +- 5 files changed, 386 insertions(+), 1 deletion(-) create mode 100644 src/devices/bus/hp_dio/hp98265a.cpp create mode 100644 src/devices/bus/hp_dio/hp98265a.h (limited to 'scripts/src') diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index 92c516ecdf8..84b5ea324c7 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -883,6 +883,8 @@ if (BUSES["HPDIO"]~=null) then files { MAME_DIR .. "src/devices/bus/hp_dio/hp_dio.cpp", MAME_DIR .. "src/devices/bus/hp_dio/hp_dio.h", + MAME_DIR .. "src/devices/bus/hp_dio/hp98265a.cpp", + MAME_DIR .. "src/devices/bus/hp_dio/hp98265a.h", MAME_DIR .. "src/devices/bus/hp_dio/hp98543.cpp", MAME_DIR .. "src/devices/bus/hp_dio/hp98543.h", MAME_DIR .. "src/devices/bus/hp_dio/hp98544.cpp", diff --git a/src/devices/bus/hp_dio/hp98265a.cpp b/src/devices/bus/hp_dio/hp98265a.cpp new file mode 100644 index 00000000000..78c2065a263 --- /dev/null +++ b/src/devices/bus/hp_dio/hp98265a.cpp @@ -0,0 +1,308 @@ +// license:BSD-3-Clause +// copyright-holders:Sven Schnelle +/*************************************************************************** + + HP98265A SCSI interface + +***************************************************************************/ + +#include "emu.h" + +#define VERBOSE 0 +#include "logmacro.h" +#include "hp98265a.h" +#include "machine/nscsi_bus.h" +#include "machine/nscsi_cd.h" +#include "machine/nscsi_hd.h" +#include "machine/mb87030.h" + +DEFINE_DEVICE_TYPE_NS(HPDIO_98265A, bus::hp_dio, dio16_98265a_device, "hp98265a", "HP98265A SCSI S16 Interface") + +namespace bus { + namespace hp_dio { + +static void scsi_devices(device_slot_interface &device) +{ + device.option_add("cdrom", NSCSI_CDROM); + device.option_add("harddisk", NSCSI_HARDDISK); +} + +void dio16_98265a_device::mb87030_scsi_adapter(device_t *device) +{ + mb87030_device &spc = downcast(*device); + spc.set_clock(8_MHz_XTAL); + + spc.out_irq_callback().set("^^", FUNC(dio16_98265a_device::irq_w)); + spc.out_dreq_callback().set("^^", FUNC(dio16_98265a_device::dmar0_w)); +} + +void dio16_98265a_device::device_add_mconfig(machine_config &config) +{ + NSCSI_BUS(config, m_scsibus, 0); + nscsi_connector &scsicon0(NSCSI_CONNECTOR(config, "scsibus:0", 0)); + scsi_devices(scsicon0); + scsicon0.set_default_option("harddisk"); + + scsi_devices(NSCSI_CONNECTOR(config, "scsibus:1", 0)); + scsi_devices(NSCSI_CONNECTOR(config, "scsibus:2", 0)); + scsi_devices(NSCSI_CONNECTOR(config, "scsibus:3", 0)); + scsi_devices(NSCSI_CONNECTOR(config, "scsibus:4", 0)); + + nscsi_connector &scsicon6(NSCSI_CONNECTOR(config, "scsibus:5", 0)); + scsi_devices(scsicon6); + scsicon6.set_default_option("cdrom"); + + scsi_devices(NSCSI_CONNECTOR(config, "scsibus:6", 0)); + nscsi_connector &scsicon7(NSCSI_CONNECTOR(config, "scsibus:7", 0)); + scsicon7.option_add_internal("mb87030", MB87030); + scsicon7.set_default_option("mb87030"); + scsicon7.set_fixed(true); + scsicon7.set_option_machine_config("mb87030", mb87030_scsi_adapter); +} + +dio16_98265a_device::dio16_98265a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + dio16_98265a_device(mconfig, HPDIO_98265A, tag, owner, clock) +{ +} + +dio16_98265a_device::dio16_98265a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, type, tag, owner, clock), + device_dio32_card_interface(mconfig, *this), + m_scsibus(*this, "scsibus"), + m_spc(*this, "scsibus:7:mb87030"), + m_sw1(*this, "SW1"), + m_sw2(*this, "SW2"), + m_irq_state(false) +{ +} + +constexpr int REG_SW1_INT_LEVEL_SHIFT = 0; +constexpr int REG_SW1_INT_LEVEL_MASK = 0x3; + +constexpr int REG_SW1_SELECT_CODE_SHIFT = 2; +constexpr int REG_SW1_SELECT_CODE_MASK = 0x1f; + +constexpr int REG_SW2_SCSI_ADDR_SHIFT = 0; +constexpr int REG_SW2_SCSI_ADDR_MASK = 0x07; + +constexpr int REG_SW2_SCSI_PARITY = 0x08; + +static INPUT_PORTS_START(hp98265a_port) + PORT_START("SW1") + PORT_DIPNAME(REG_SW1_INT_LEVEL_MASK << REG_SW1_INT_LEVEL_SHIFT, 0x01, "INT Level") + PORT_DIPSETTING(0 << REG_SW1_INT_LEVEL_SHIFT, "3") + PORT_DIPSETTING(1 << REG_SW1_INT_LEVEL_SHIFT, "4") + PORT_DIPSETTING(2 << REG_SW1_INT_LEVEL_SHIFT, "5") + PORT_DIPSETTING(3 << REG_SW1_INT_LEVEL_SHIFT, "6") + + PORT_DIPNAME(REG_SW1_SELECT_CODE_MASK << REG_SW1_SELECT_CODE_SHIFT, 0x0e << REG_SW1_SELECT_CODE_SHIFT, "Select code") + PORT_DIPSETTING(0 << REG_SW1_SELECT_CODE_SHIFT, "0") + PORT_DIPSETTING(1 << REG_SW1_SELECT_CODE_SHIFT, "1") + PORT_DIPSETTING(2 << REG_SW1_SELECT_CODE_SHIFT, "2") + PORT_DIPSETTING(3 << REG_SW1_SELECT_CODE_SHIFT, "3") + PORT_DIPSETTING(4 << REG_SW1_SELECT_CODE_SHIFT, "4") + PORT_DIPSETTING(5 << REG_SW1_SELECT_CODE_SHIFT, "5") + PORT_DIPSETTING(6 << REG_SW1_SELECT_CODE_SHIFT, "6") + PORT_DIPSETTING(7 << REG_SW1_SELECT_CODE_SHIFT, "7") + PORT_DIPSETTING(8 << REG_SW1_SELECT_CODE_SHIFT, "8") + PORT_DIPSETTING(9 << REG_SW1_SELECT_CODE_SHIFT, "9") + PORT_DIPSETTING(10 << REG_SW1_SELECT_CODE_SHIFT, "10") + PORT_DIPSETTING(11 << REG_SW1_SELECT_CODE_SHIFT, "11") + PORT_DIPSETTING(12 << REG_SW1_SELECT_CODE_SHIFT, "12") + PORT_DIPSETTING(13 << REG_SW1_SELECT_CODE_SHIFT, "13") + PORT_DIPSETTING(14 << REG_SW1_SELECT_CODE_SHIFT, "14") + PORT_DIPSETTING(15 << REG_SW1_SELECT_CODE_SHIFT, "15") + PORT_DIPSETTING(16 << REG_SW1_SELECT_CODE_SHIFT, "16") + PORT_DIPSETTING(17 << REG_SW1_SELECT_CODE_SHIFT, "17") + PORT_DIPSETTING(18 << REG_SW1_SELECT_CODE_SHIFT, "18") + PORT_DIPSETTING(19 << REG_SW1_SELECT_CODE_SHIFT, "19") + PORT_DIPSETTING(20 << REG_SW1_SELECT_CODE_SHIFT, "20") + PORT_DIPSETTING(21 << REG_SW1_SELECT_CODE_SHIFT, "21") + PORT_DIPSETTING(22 << REG_SW1_SELECT_CODE_SHIFT, "22") + PORT_DIPSETTING(23 << REG_SW1_SELECT_CODE_SHIFT, "23") + PORT_DIPSETTING(24 << REG_SW1_SELECT_CODE_SHIFT, "24") + PORT_DIPSETTING(25 << REG_SW1_SELECT_CODE_SHIFT, "25") + PORT_DIPSETTING(26 << REG_SW1_SELECT_CODE_SHIFT, "26") + PORT_DIPSETTING(27 << REG_SW1_SELECT_CODE_SHIFT, "27") + PORT_DIPSETTING(28 << REG_SW1_SELECT_CODE_SHIFT, "28") + PORT_DIPSETTING(29 << REG_SW1_SELECT_CODE_SHIFT, "29") + PORT_DIPSETTING(30 << REG_SW1_SELECT_CODE_SHIFT, "30") + PORT_DIPSETTING(31 << REG_SW1_SELECT_CODE_SHIFT, "31") + + PORT_START("SW2") + PORT_DIPNAME(REG_SW2_SCSI_ADDR_MASK << REG_SW2_SCSI_ADDR_SHIFT, 0x00, "SCSI Address") + PORT_DIPSETTING(0 << REG_SW2_SCSI_ADDR_SHIFT, "0") + PORT_DIPSETTING(1 << REG_SW2_SCSI_ADDR_SHIFT, "1") + PORT_DIPSETTING(2 << REG_SW2_SCSI_ADDR_SHIFT, "2") + PORT_DIPSETTING(3 << REG_SW2_SCSI_ADDR_SHIFT, "3") + PORT_DIPSETTING(4 << REG_SW2_SCSI_ADDR_SHIFT, "4") + PORT_DIPSETTING(5 << REG_SW2_SCSI_ADDR_SHIFT, "5") + PORT_DIPSETTING(6 << REG_SW2_SCSI_ADDR_SHIFT, "6") + PORT_DIPSETTING(7 << REG_SW2_SCSI_ADDR_SHIFT, "7") + + PORT_DIPNAME(REG_SW2_SCSI_PARITY, 0x00, "SCSI Parity") + PORT_DIPSETTING(0, "Off") + PORT_DIPSETTING(REG_SW2_SCSI_PARITY, "On") + +INPUT_PORTS_END + +ioport_constructor dio16_98265a_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(hp98265a_port); +} + +void dio16_98265a_device::device_start() +{ + save_item(NAME(m_irq_state)); + save_item(NAME(m_installed_io)); + save_item(NAME(m_control)); + save_item(NAME(m_dmar0)); + + m_installed_io = false; +} + +void dio16_98265a_device::map(address_map &map) +{ + +} + +void dio16_98265a_device::device_reset() +{ + uint8_t code = m_sw1->read() >> REG_SW1_SELECT_CODE_SHIFT; + code &= REG_SW1_SELECT_CODE_MASK; + + if (!m_installed_io) + { + program_space()->install_readwrite_handler( + 0x600000 + (code * 0x10000), + 0x6007ff + (code * 0x10000), + read16_delegate(FUNC(dio16_98265a_device::io_r), this), + write16_delegate(FUNC(dio16_98265a_device::io_w), this)); + program_space()->install_device(0x6e0020, 0x6e003f, *m_spc, &mb87030_device::map, 0x00ff00ff); + m_installed_io = true; + } + m_control = 0; + m_irq_state = false; + m_spc->reset_w(true); + m_spc->reset_w(false); +} + +int dio16_98265a_device::get_int_level() +{ + return (m_sw1->read() >> REG_SW1_INT_LEVEL_SHIFT) & + REG_SW1_INT_LEVEL_MASK; + +} +READ16_MEMBER(dio16_98265a_device::io_r) +{ + + uint16_t ret = 0xffff; + + switch(offset) { + case 0: /* ID */ + ret = 0x07; + break; + case 1: + ret = m_control | (m_irq_state ? 0x40 : 0) | (get_int_level() << 4); + break; + case 2: + ret = m_spc->data_read(); + break; + case 3: + ret = 0xe8; /* Flush/Configuration register */ + break; + } + LOG("io_r: offset=%02X ret=%02X\n",offset, ret); + return ret; +} + +WRITE16_MEMBER(dio16_98265a_device::io_w) +{ + LOG("io_w: offset=%02X, data=%02X\n", offset, data); + + switch(offset) { + case 0: + device_reset(); + break; + case 1: + if (data & 0x80) + update_irq(m_irq_state); + else + update_irq(false); + m_control = data & 0x8f; + update_dma(); + break; + case 2: + uint8_t val = 0; + if (data & 0x80) + val |= nscsi_device::S_REQ; + if (data & 0x40) + val |= nscsi_device::S_ACK; + if (data & 0x08) + val |= nscsi_device::S_BSY; + if (data & 0x04) + val |= nscsi_device::S_MSG; + if (data & 0x02) + val |= nscsi_device::S_CTL; + if (data & 0x01) + val |= nscsi_device::S_INP; + m_spc->ctrl_write(val, nscsi_device::S_ALL); + break; + } +} + +void dio16_98265a_device::update_irq(bool state) +{ + int irq_level = get_int_level(); + LOG("irq_w: %sassert %d\n", state ? "" : "de", irq_level+3); + + irq3_out(state && irq_level == 0); + irq4_out(state && irq_level == 1); + irq5_out(state && irq_level == 2); + irq6_out(state && irq_level == 3); +} + +WRITE_LINE_MEMBER(dio16_98265a_device::irq_w) +{ + LOG("%s: %s\n", __FUNCTION__, state ? "true" : "false"); + + if ((m_control & 0x80) && m_irq_state != state) + update_irq(state); + + m_irq_state = state; +} + +void dio16_98265a_device::dmack_w_in(int channel, uint8_t data) +{ + if(channel == 0 && !(m_control & REG_CONTROL_DE0)) + return; + if(channel == 1 && !(m_control & REG_CONTROL_DE1)) + return; + + m_spc->dma_w(data); +} + +uint8_t dio16_98265a_device::dmack_r_in(int channel) +{ + if(channel == 0 && !(m_control & REG_CONTROL_DE0)) + return 0xff; + if(channel == 1 && !(m_control & REG_CONTROL_DE1)) + return 0xff; + + return m_spc->dma_r(); +} + +void dio16_98265a_device::update_dma() +{ + dmar0_out((m_control & REG_CONTROL_DE0) && m_dmar0); + dmar1_out((m_control & REG_CONTROL_DE1) && m_dmar0); +} +WRITE_LINE_MEMBER(dio16_98265a_device::dmar0_w) +{ + m_dmar0 = state; + update_dma(); + +} + +} +} diff --git a/src/devices/bus/hp_dio/hp98265a.h b/src/devices/bus/hp_dio/hp98265a.h new file mode 100644 index 00000000000..34c7808dff4 --- /dev/null +++ b/src/devices/bus/hp_dio/hp98265a.h @@ -0,0 +1,72 @@ +// license:BSD-3-Clause +// copyright-holders:Sven Schnelle + +#ifndef MAME_BUS_HPDIO_98265A_H +#define MAME_BUS_HPDIO_98265A_H + +#pragma once + +#include "hp_dio.h" +#include "machine/mb87030.h" +#include "bus/scsi/scsi.h" +#include "bus/scsi/scsicd.h" + +namespace bus { + namespace hp_dio { + +class dio16_98265a_device : + public device_t, + public device_dio32_card_interface +{ +public: + // construction/destruction + dio16_98265a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + void mb87030(device_t *device); + void map(address_map &map); +protected: + dio16_98265a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + + virtual ioport_constructor device_input_ports() const override; + virtual void device_add_mconfig(machine_config &config) override; + + DECLARE_READ16_MEMBER(io_r); + DECLARE_WRITE16_MEMBER(io_w); + + void dmack_w_in(int channel, uint8_t data) override; + uint8_t dmack_r_in(int channel) override; + + DECLARE_WRITE_LINE_MEMBER(dmar0_w); + + DECLARE_WRITE_LINE_MEMBER(irq_w); + + required_device m_scsibus; + required_device m_spc; +private: + + static constexpr int REG_CONTROL_DE0 = (1 << 0); + static constexpr int REG_CONTROL_DE1 = (1 << 1); + + static void mb87030_scsi_adapter(device_t *device); + required_ioport m_sw1; + required_ioport m_sw2; + int get_int_level(); + void update_irq(bool state); + void update_dma(); + bool m_installed_io; + uint8_t m_control; + + bool m_irq_state; + bool m_dmar0; +}; +} +} + +DECLARE_DEVICE_TYPE_NS(HPDIO_98265A, bus::hp_dio, dio16_98265a_device) + +#endif // MAME_BUS_HPDIO_98265A_H diff --git a/src/devices/bus/hp_dio/hp_dio.cpp b/src/devices/bus/hp_dio/hp_dio.cpp index 459172a4ffd..c90a1e2c83a 100644 --- a/src/devices/bus/hp_dio/hp_dio.cpp +++ b/src/devices/bus/hp_dio/hp_dio.cpp @@ -8,6 +8,7 @@ #include "emu.h" #include "hp_dio.h" +#include "hp98265a.h" #include "hp98543.h" #include "hp98544.h" #include "hp98603a.h" @@ -364,5 +365,6 @@ void dio16_cards(device_slot_interface & device) void dio32_cards(device_slot_interface & device) { + device.option_add("98265a", HPDIO_98265A); device.option_add("98620", HPDIO_98620); } diff --git a/src/mame/drivers/hp9k_3xx.cpp b/src/mame/drivers/hp9k_3xx.cpp index 1c304fef149..12a16243e2b 100644 --- a/src/mame/drivers/hp9k_3xx.cpp +++ b/src/mame/drivers/hp9k_3xx.cpp @@ -386,7 +386,8 @@ MACHINE_CONFIG_START(hp9k3xx_state::hp9k320) DIO32_SLOT(config, "sl2", 0, "diobus", dio16_cards, "98603b", false); DIO32_SLOT(config, "sl3", 0, "diobus", dio16_cards, "98644", false); DIO32_SLOT(config, "sl4", 0, "diobus", dio32_cards, "98620", false); - DIO32_SLOT(config, "sl5", 0, "diobus", dio16_cards, nullptr, false); + DIO32_SLOT(config, "sl5", 0, "diobus", dio32_cards, "98265a", false); + DIO32_SLOT(config, "sl6", 0, "diobus", dio16_cards, nullptr, false); MACHINE_CONFIG_END MACHINE_CONFIG_START(hp9k3xx_state::hp9k330) -- cgit v1.2.3 From 10b6b71e1383a1062741809a023b4b383f0ad3e1 Mon Sep 17 00:00:00 2001 From: Patrick Mackinlay Date: Thu, 11 Oct 2018 17:44:08 +0700 Subject: pcat101: skeleton for IBM Model M PC/AT and PS/2 keyboard --- scripts/src/bus.lua | 2 + src/devices/bus/pc_kbd/keyboards.cpp | 2 + src/devices/bus/pc_kbd/keyboards.h | 1 + src/devices/bus/pc_kbd/pcat101.cpp | 241 +++++++++++++++++++++++++++++++++++ src/devices/bus/pc_kbd/pcat101.h | 59 +++++++++ 5 files changed, 305 insertions(+) create mode 100644 src/devices/bus/pc_kbd/pcat101.cpp create mode 100644 src/devices/bus/pc_kbd/pcat101.h (limited to 'scripts/src') diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index 84b5ea324c7..44bbb9f1502 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -1379,6 +1379,8 @@ if (BUSES["PC_KBD"]~=null) then MAME_DIR .. "src/devices/bus/pc_kbd/pcat84.h", MAME_DIR .. "src/devices/bus/pc_kbd/pcxt83.cpp", MAME_DIR .. "src/devices/bus/pc_kbd/pcxt83.h", + MAME_DIR .. "src/devices/bus/pc_kbd/pcat101.cpp", + MAME_DIR .. "src/devices/bus/pc_kbd/pcat101.h", } end diff --git a/src/devices/bus/pc_kbd/keyboards.cpp b/src/devices/bus/pc_kbd/keyboards.cpp index 7c9d32501fc..98be3e2e304 100644 --- a/src/devices/bus/pc_kbd/keyboards.cpp +++ b/src/devices/bus/pc_kbd/keyboards.cpp @@ -10,6 +10,7 @@ #include "pc83.h" #include "pcxt83.h" #include "pcat84.h" +#include "pcat101.h" void pc_xt_keyboards(device_slot_interface &device) { @@ -27,4 +28,5 @@ void pc_at_keyboards(device_slot_interface &device) device.option_add(STR_KBD_MICROSOFT_NATURAL, PC_KBD_MICROSOFT_NATURAL); device.option_add(STR_KBD_IBM_PC_AT_84, PC_KBD_IBM_PC_AT_84); device.option_add(STR_KBD_IBM_3270PC_122, PC_KBD_IBM_3270PC_122); + device.option_add(STR_KBD_IBM_PC_AT_101, PC_KBD_IBM_PC_AT_101); } diff --git a/src/devices/bus/pc_kbd/keyboards.h b/src/devices/bus/pc_kbd/keyboards.h index a4dc98432c7..ca106926499 100644 --- a/src/devices/bus/pc_kbd/keyboards.h +++ b/src/devices/bus/pc_kbd/keyboards.h @@ -27,6 +27,7 @@ void pc_xt_keyboards(device_slot_interface &device); #define STR_KBD_MICROSOFT_NATURAL "ms_naturl" #define STR_KBD_IBM_PC_AT_84 "pcat" #define STR_KBD_IBM_3270PC_122 "3270pc" +#define STR_KBD_IBM_PC_AT_101 "pcat101" void pc_at_keyboards(device_slot_interface &device); diff --git a/src/devices/bus/pc_kbd/pcat101.cpp b/src/devices/bus/pc_kbd/pcat101.cpp new file mode 100644 index 00000000000..a6e141c12e4 --- /dev/null +++ b/src/devices/bus/pc_kbd/pcat101.cpp @@ -0,0 +1,241 @@ +// license:BSD-3-Clause +// copyright-holders:Patrick Mackinlay + +/* + * IBM Model M PC/AT and PS/2 101-key keyboard emulation. + * + * Sources: + * + * https://clickykeyboards.com/ + * http://www.kbdbabel.org/schematic/kbdbabel_doc_ibm1394796.pdf + * http://ps-2.kev009.com/ohlandl/keyboard/Keyboard.html + * + * Part No Layout + * 1391401 US English 101-key + * + * TODO + * - matrix and mcu ports (skeleton only) + */ + +#include "emu.h" +#include "pcat101.h" + +DEFINE_DEVICE_TYPE(PC_KBD_IBM_PC_AT_101, ibm_pc_at_101_keyboard_device, "kb_pcat101", "IBM PC/AT Keyboard") + +ROM_START(ibm_pc_at_101_keyboard) + ROM_REGION(0x1000, "mcu", 0) + /* + * PCB + * 1394792 K27-1 + * EC 528739 4989 + * + * MCU + * ST (C)IBM 1984 + * C430 28940 + * EF6805U3P-B + * 1394080 + */ + ROM_LOAD("ef6805u3p-b__1394080.u2", 0x000, 0x1000, CRC(7d2a52f3) SHA1(ac739dc0408ea0b3be60f85b7a2eb822753a054c)) +ROM_END + +const tiny_rom_entry *ibm_pc_at_101_keyboard_device::device_rom_region() const +{ + return ROM_NAME(ibm_pc_at_101_keyboard); +} + +void ibm_pc_at_101_keyboard_device::device_add_mconfig(machine_config &config) +{ + M68705U3(config, m_maincpu, 0); + + //m_maincpu->portb_r_cb().set(FUNC(ibm_pc_at_101_keyboard_device::portb_r)); + //m_maincpu->portb_w_cb().set(FUNC(ibm_pc_at_101_keyboard_device::portb_w)); +} + +// FIXME: copied from ibm_pc_at_84_keyboard - probably completely wrong +INPUT_PORTS_START(ibm_pc_at_101_keyboard) + PORT_START("column00") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F9) PORT_CHAR(UCHAR_MAMEKEY(F9)) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7)) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5)) + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3)) + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1)) + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2)) + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED) + + PORT_START("column01") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F10) PORT_CHAR(UCHAR_MAMEKEY(F10)) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8)) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6)) + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4)) + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TAB) PORT_CHAR(UCHAR_MAMEKEY(TAB)) + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED) + + PORT_START("column02") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LALT) PORT_CHAR(UCHAR_MAMEKEY(LALT)) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_SHIFT_2) + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED) + + PORT_START("column03") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@') + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED) + + PORT_START("column04") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED) + + PORT_START("column05") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED) + + PORT_START("column06") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^') + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED) + + PORT_START("column07") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&') + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*') + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED) + + PORT_START("column08") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<') + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')') + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(') + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED) + + PORT_START("column09") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>') + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?') + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':') + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_') + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED) + + PORT_START("column10") + PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_CUSTOM) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('"') + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{') + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+') + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CAPSLOCK) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK)) + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1) + + PORT_START("column11") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}') + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`') PORT_CHAR('~') + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') PORT_CHAR('|') + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED) + + PORT_START("column12") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8) + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED) + + PORT_START("column13") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 1 End") PORT_CODE(KEYCODE_1_PAD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD)) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 4 " UTF8_LEFT) PORT_CODE(KEYCODE_4_PAD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD)) + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 7 Home") PORT_CODE(KEYCODE_7_PAD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD)) + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED) + + PORT_START("column14") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 0 Ins") PORT_CODE(KEYCODE_0_PAD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD)) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad . Del") PORT_CODE(KEYCODE_DEL_PAD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD)) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 2 " UTF8_DOWN) PORT_CODE(KEYCODE_2_PAD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD)) + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5_PAD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD)) + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 6 " UTF8_RIGHT) PORT_CODE(KEYCODE_6_PAD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD)) + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 8 " UTF8_UP) PORT_CODE(KEYCODE_8_PAD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD)) + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC)) + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_NUMLOCK) PORT_CHAR(UCHAR_MAMEKEY(NUMLOCK)) + + PORT_START("column15") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_PLUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(PLUS_PAD)) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 3 PgDn") PORT_CODE(KEYCODE_3_PAD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD)) + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD)) + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad * PrtSc") PORT_CODE(KEYCODE_ASTERISK) PORT_CHAR(UCHAR_MAMEKEY(ASTERISK)) + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 9 PgUp") PORT_CODE(KEYCODE_9_PAD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD)) + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Scroll Lock Break") PORT_CODE(KEYCODE_SCRLOCK) PORT_CHAR(UCHAR_MAMEKEY(SCRLOCK)) + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Sys Req") +INPUT_PORTS_END + +ioport_constructor ibm_pc_at_101_keyboard_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(ibm_pc_at_101_keyboard); +} + +ibm_pc_at_101_keyboard_device::ibm_pc_at_101_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, PC_KBD_IBM_PC_AT_101, tag, owner, clock) + , device_pc_kbd_interface(mconfig, *this) + , m_maincpu(*this, "mcu") + , m_column(*this, "column%02u", 0) + , m_leds(*this, "led%u", 0) +{ +} + +void ibm_pc_at_101_keyboard_device::device_start() +{ + set_pc_kbdc_device(); + + m_leds.resolve(); +} + +void ibm_pc_at_101_keyboard_device::device_reset() +{ + m_maincpu->reset(); +} diff --git a/src/devices/bus/pc_kbd/pcat101.h b/src/devices/bus/pc_kbd/pcat101.h new file mode 100644 index 00000000000..e727335aa77 --- /dev/null +++ b/src/devices/bus/pc_kbd/pcat101.h @@ -0,0 +1,59 @@ +// license:BSD-3-Clause +// copyright-holders:Patrick Mackinlay + +/* + * IBM Model M PC/AT and PS/2 101-key keyboard emulation. + */ + +#ifndef MAME_BUS_PC_KBD_PCAT101_H +#define MAME_BUS_PC_KBD_PCAT101_H + +#pragma once + +#include "cpu/m6805/m68705.h" +#include "pc_kbdc.h" +#include "machine/rescap.h" + +class ibm_pc_at_101_keyboard_device + : public device_t + , public device_pc_kbd_interface +{ +public: + // construction/destruction + ibm_pc_at_101_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + + // optional information overrides + virtual const tiny_rom_entry *device_rom_region() const override; + virtual void device_add_mconfig(machine_config &config) override; + virtual ioport_constructor device_input_ports() const override; + + // device_pc_kbd_interface overrides + virtual DECLARE_WRITE_LINE_MEMBER(clock_write) override { m_maincpu->set_input_line(M68705_IRQ_LINE, state); }; + virtual DECLARE_WRITE_LINE_MEMBER(data_write) override { }; + +private: + // ports A, C: matrix column + // port D: matrix row + // port B: clock/data and leds + + enum + { + LED_SCROLL = 0, + LED_NUM, + LED_CAPS + }; + + required_device m_maincpu; + required_ioport_array<16> m_column; + output_finder<3> m_leds; +}; + +// device type definition +DECLARE_DEVICE_TYPE(PC_KBD_IBM_PC_AT_101, ibm_pc_at_101_keyboard_device) + +#endif // MAME_BUS_PC_KBD_PCAT101_H -- cgit v1.2.3 From 75fde4b0f0fa52f3a28f28d535fc21049abd238a Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Thu, 11 Oct 2018 12:55:09 +0200 Subject: hp_hil: add HP 46060B mouse - move hle_device_base to it's own files - add hlemouse.{cpp,h} - add mouse device to hp_ipc and hp9k_3xx --- scripts/src/bus.lua | 4 + src/devices/bus/hp_dio/human_interface.cpp | 5 + src/devices/bus/hp_hil/hil_devices.cpp | 1 + src/devices/bus/hp_hil/hlebase.cpp | 152 ++++++++++++++++++ src/devices/bus/hp_hil/hlebase.h | 43 +++++ src/devices/bus/hp_hil/hlekbd.cpp | 249 ++++++++++------------------- src/devices/bus/hp_hil/hlekbd.h | 84 ++++++---- src/devices/bus/hp_hil/hlemouse.cpp | 127 +++++++++++++++ src/devices/bus/hp_hil/hlemouse.h | 52 ++++++ src/mame/drivers/hp_ipc.cpp | 1 + 10 files changed, 524 insertions(+), 194 deletions(-) create mode 100644 src/devices/bus/hp_hil/hlebase.cpp create mode 100644 src/devices/bus/hp_hil/hlebase.h create mode 100644 src/devices/bus/hp_hil/hlemouse.cpp create mode 100644 src/devices/bus/hp_hil/hlemouse.h (limited to 'scripts/src') diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index 84b5ea324c7..02a3afc5b83 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -869,6 +869,10 @@ if (BUSES["HPHIL"]~=null) then MAME_DIR .. "src/devices/bus/hp_hil/hp_hil.h", MAME_DIR .. "src/devices/bus/hp_hil/hil_devices.cpp", MAME_DIR .. "src/devices/bus/hp_hil/hil_devices.h", + MAME_DIR .. "src/devices/bus/hp_hil/hlebase.cpp", + MAME_DIR .. "src/devices/bus/hp_hil/hlebase.h", + MAME_DIR .. "src/devices/bus/hp_hil/hlemouse.cpp", + MAME_DIR .. "src/devices/bus/hp_hil/hlemouse.h", MAME_DIR .. "src/devices/bus/hp_hil/hlekbd.cpp", MAME_DIR .. "src/devices/bus/hp_hil/hlekbd.h", } diff --git a/src/devices/bus/hp_dio/human_interface.cpp b/src/devices/bus/hp_dio/human_interface.cpp index 7804377e46a..d35f8acf518 100644 --- a/src/devices/bus/hp_dio/human_interface.cpp +++ b/src/devices/bus/hp_dio/human_interface.cpp @@ -41,6 +41,11 @@ void human_interface_device::device_add_mconfig(machine_config &config) keyboard.set_default_option("hp_46021a"); keyboard.set_hp_hil_slot(this, "mlc"); + hp_hil_slot_device &mouse(HP_HIL_SLOT(config, "hil2", 0)); + hp_hil_devices(mouse); + mouse.set_default_option("hp_46060b"); + mouse.set_hp_hil_slot(this, "mlc"); + SPEAKER(config, "mono").front_center(); sn76494_device &sound(SN76494(config, "sn76494", 333333)); sound.add_route(ALL_OUTPUTS, "mono", 0.75); diff --git a/src/devices/bus/hp_hil/hil_devices.cpp b/src/devices/bus/hp_hil/hil_devices.cpp index 422ff680c4c..b7b6ae85513 100644 --- a/src/devices/bus/hp_hil/hil_devices.cpp +++ b/src/devices/bus/hp_hil/hil_devices.cpp @@ -10,4 +10,5 @@ void hp_hil_devices(device_slot_interface &device) { device.option_add(STR_KBD_HP_INTEGRAL, HP_IPC_HLE_KEYBOARD); device.option_add(STR_KBD_HP_46021A, HP_ITF_HLE_KEYBOARD); + device.option_add(STR_MOUSE_HP_46060B, HP_46060B_MOUSE); } diff --git a/src/devices/bus/hp_hil/hlebase.cpp b/src/devices/bus/hp_hil/hlebase.cpp new file mode 100644 index 00000000000..5ac421a2497 --- /dev/null +++ b/src/devices/bus/hp_hil/hlebase.cpp @@ -0,0 +1,152 @@ +// license:BSD-3-Cl ause +// copyright-holders:Sergey Svishchev +#include "emu.h" +#include "hlebase.h" +#include "hlekbd.h" + +//#define VERBOSE 1 +#include "logmacro.h" + +namespace bus { + namespace hp_hil { + +/*************************************************************************** + BASE HLE KEYBOARD DEVICE +***************************************************************************/ + +/*-------------------------------------------------- + hle_device_base::hle_device_base + designated device constructor +--------------------------------------------------*/ + +hle_device_base::hle_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, type, tag, owner, clock) + , device_hp_hil_interface(mconfig, *this) +{ } + + +/*-------------------------------------------------- + hle_device_base::~hle_device_base + destructor +--------------------------------------------------*/ + +hle_device_base::~hle_device_base() +{ } + + +/*-------------------------------------------------- + hle_device_base::device_start + perform expensive initialisations, allocate + resources, register for save state +--------------------------------------------------*/ + +void hle_device_base::device_start() +{ + set_hp_hil_mlc_device(); + + m_powerup = true; + m_passthru = false; +} + + +/*-------------------------------------------------- + hle_device_base::device_reset + perform startup tasks, also used for host + requested reset +--------------------------------------------------*/ + +void hle_device_base::device_reset() +{ +} + +bool hle_device_base::hil_write(uint16_t *pdata) +{ + int frames = 0; + uint8_t addr = (*pdata >> 8) & 7; + uint8_t data = *pdata & 0xff; + bool command = BIT(*pdata, 11); + + LOG("%d: rx from mlc %04X (%s addr %d, data %02X)\n", m_device_id, *pdata, + command ? "command" : "data", addr, data); + + if (!command) + goto out; + + if (addr != 0 && addr != m_device_id) + goto out; + + switch (data) + { + case HPHIL_IFC: + m_powerup = false; + break; + + case HPHIL_EPT: + m_passthru = true; + break; + + case HPHIL_ELB: + m_passthru = false; + break; + + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + m_device_id = data - 8; + m_device_id16 = (data - 8) << 8; + *pdata &= ~7; + *pdata += (data - 7); + break; + + case HPHIL_POL: + case HPHIL_POL+1: + case HPHIL_POL+2: + case HPHIL_POL+3: + case HPHIL_POL+4: + case HPHIL_POL+5: + case HPHIL_POL+6: + case HPHIL_POL+7: + case HPHIL_POL+8: + case HPHIL_POL+9: + case HPHIL_POL+10: + case HPHIL_POL+11: + case HPHIL_POL+12: + case HPHIL_POL+13: + case HPHIL_POL+14: + case HPHIL_POL+15: + frames = hil_poll(); + *pdata += frames; + break; + + case HPHIL_DSR: + m_device_id = m_device_id16 = 0; + m_powerup = true; + break; + + case HPHIL_IDD: + hil_idd(); + break; + + case HPHIL_DHR: + m_powerup = true; + m_passthru = false; + device_reset(); + return true; + break; + + default: + LOG("command %02X unknown\n", data); + break; + } +out: + if (!m_passthru) + m_hp_hil_mlc->hil_write(*pdata); + return m_passthru; +} + +} // namespace bus::hp_hil +} // namespace bus diff --git a/src/devices/bus/hp_hil/hlebase.h b/src/devices/bus/hp_hil/hlebase.h new file mode 100644 index 00000000000..58e320507fe --- /dev/null +++ b/src/devices/bus/hp_hil/hlebase.h @@ -0,0 +1,43 @@ +// license:BSD-3-Clause +// copyright-holders:Sergey Svishchev +#ifndef MAME_DEVICES_HP_HIL_HLEBASE_H +#define MAME_DEVICES_HP_HIL_HLEBASE_H + +#pragma once + +#include "hp_hil.h" +#include "machine/keyboard.h" + + +namespace bus { + namespace hp_hil { + +class hle_device_base + : public device_t + , public device_hp_hil_interface +{ +public: + virtual ~hle_device_base() override; + void transmit_byte(uint8_t byte); +protected: + // constructor/destructor + hle_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, uint32_t clock); + + // device overrides + virtual void device_start() override; + virtual void device_reset() override; + + // device_hp_hil_interface overrides + virtual bool hil_write(uint16_t *data) override; + virtual void hil_idd() = 0; + virtual int hil_poll() = 0; +private: + + + util::fifo m_fifo; +}; + +} // namespace bus::hp_hil +} // namespace bus + +#endif // MAME_DEVICES_HP_HIL_HLEBASE_H diff --git a/src/devices/bus/hp_hil/hlekbd.cpp b/src/devices/bus/hp_hil/hlekbd.cpp index 5cca998409d..4771243bef9 100644 --- a/src/devices/bus/hp_hil/hlekbd.cpp +++ b/src/devices/bus/hp_hil/hlekbd.cpp @@ -14,8 +14,8 @@ DEFINE_DEVICE_TYPE_NS(HP_IPC_HLE_KEYBOARD, bus::hp_hil, hle_hp_ipc_device, "hp_ipc_hle_kbd", "HP Integral Keyboard (HLE)") DEFINE_DEVICE_TYPE_NS(HP_ITF_HLE_KEYBOARD, bus::hp_hil, hle_hp_itf_device, "hp_itf_hle_kbd", "HP ITF Keyboard") - -namespace bus { namespace hp_hil { +namespace bus { + namespace hp_hil { namespace { @@ -408,205 +408,94 @@ INPUT_PORTS_START( itf_basic ) PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`') PORT_CHAR('~') INPUT_PORTS_END - - INPUT_PORTS_START( hle_hp_itf_device ) PORT_INCLUDE( itf_basic ) PORT_INCLUDE( itf_id ) INPUT_PORTS_END - } // anonymous namespace +void hle_hp_ipc_device::transmit_byte(uint8_t byte) +{ + if (!m_fifo.full()) { + m_fifo.enqueue(byte); + } +} + +void hle_hp_itf_device::transmit_byte(uint8_t byte) +{ + if (!m_fifo.full()) { + m_fifo.enqueue(byte); + } +} /*************************************************************************** - BASE HLE KEYBOARD DEVICE + HP INTEGRAL HLE KEYBOARD DEVICE ***************************************************************************/ /*-------------------------------------------------- - hle_device_base::hle_device_base - designated device constructor + hle_hp_ipc_device::hle_hp_ipc_device + abbreviated constructor --------------------------------------------------*/ -hle_device_base::hle_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, type, tag, owner, clock) - , device_hp_hil_interface(mconfig, *this) +hle_hp_ipc_device::hle_hp_ipc_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock) + : hle_device_base(mconfig, HP_IPC_HLE_KEYBOARD, tag, owner, clock) , device_matrix_keyboard_interface(mconfig, *this, "COL1", "COL2", "COL3", "COL4", "COL5", "COL6", "COL7", "COL8", "COL9", "COL10", "COL11", "COL12", "COL13", "COL14", "COL15") { } - -/*-------------------------------------------------- - hle_device_base::~hle_device_base - destructor ---------------------------------------------------*/ - -hle_device_base::~hle_device_base() -{ } - - -/*-------------------------------------------------- - hle_device_base::device_start - perform expensive initialisations, allocate - resources, register for save state ---------------------------------------------------*/ - -void hle_device_base::device_start() -{ - set_hp_hil_mlc_device(); - - m_powerup = true; - m_passthru = false; -} - - -/*-------------------------------------------------- - hle_device_base::device_reset - perform startup tasks, also used for host - requested reset ---------------------------------------------------*/ - -void hle_device_base::device_reset() +void hle_hp_ipc_device::device_reset() { m_fifo.clear(); - - // kick the base reset_key_state(); start_processing(attotime::from_hz(1'200)); } -// ' -bool hle_device_base::hil_write(uint16_t *pdata) +void hle_hp_ipc_device::hil_idd() { - int frames = 0; - uint8_t addr = (*pdata >> 8) & 7; - uint8_t data = *pdata & 0xff; - bool command = BIT(*pdata, 11); - - LOG("rx from mlc %04X (%s addr %d, data %02X)\n", *pdata, - command ? "command" : "data", addr, data); - if (!command) - goto out; - - if (addr != 0 && addr != m_device_id) - goto out; - - switch (data) - { - case HPHIL_IFC: - m_powerup = false; - break; - - case HPHIL_EPT: - m_passthru = true; - break; - - case HPHIL_ELB: - m_passthru = false; - break; - - case 0x09: - case 0x0a: - case 0x0b: - case 0x0c: - case 0x0d: - case 0x0e: - case 0x0f: - m_device_id = data - 8; - m_device_id16 = (data - 8) << 8; - *pdata &= ~7; - *pdata += (data - 7); - break; - - case HPHIL_POL: - if (!m_fifo.empty()) - { - - frames = 1; - m_hp_hil_mlc->hil_write(m_device_id16 | 0x40); // Keycode Set 1, no coordinate data - while (!m_fifo.empty()) - { - m_hp_hil_mlc->hil_write(m_device_id16 | m_fifo.dequeue()); - frames++; - } - } - m_hp_hil_mlc->hil_write(HPMLC_W1_C | (addr << 8) | HPHIL_POL | (frames)); - *pdata &= ~7; - *pdata += frames; - return true; - - case HPHIL_DSR: - m_device_id = m_device_id16 = 0; - m_powerup = true; - break; - - case HPHIL_IDD: - m_hp_hil_mlc->hil_write(0x0100 | ioport("COL0")->read()); - m_hp_hil_mlc->hil_write(m_device_id16 | 0); - break; - - case HPHIL_DHR: - m_powerup = true; - m_passthru = false; - device_reset(); - return true; - break; - - default: - LOG("command %02X unknown\n", data); - break; - } -out: - if (!m_passthru) { - m_hp_hil_mlc->hil_write(*pdata); - return false; - } - return true; -} - -void hle_device_base::transmit_byte(uint8_t byte) -{ - if (!m_fifo.full()) { - m_fifo.enqueue(byte); - } -// else -// printf("queuing fail (fifo full)\n"); + m_hp_hil_mlc->hil_write(0x0100 | ioport("COL0")->read()); + m_hp_hil_mlc->hil_write(m_device_id16 | 0); + return; } -/*-------------------------------------------------- - hle_device_base::key_make - handle a key being pressed ---------------------------------------------------*/ - -void hle_device_base::key_make(uint8_t row, uint8_t column) +void hle_hp_ipc_device::key_make(uint8_t row, uint8_t column) { transmit_byte((((row + 1) ^ 8) << 4) + (column << 1)); } -/*-------------------------------------------------- - hle_device_base::key_break - handle a key being released ---------------------------------------------------*/ - -void hle_device_base::key_break(uint8_t row, uint8_t column) +void hle_hp_ipc_device::key_break(uint8_t row, uint8_t column) { transmit_byte((((row + 1) ^ 8) << 4) + (column << 1) + 1); } +int hle_hp_ipc_device::hil_poll() +{ + int frames = 1; + if (m_fifo.empty()) + return frames; + + m_hp_hil_mlc->hil_write(m_device_id16 | 0x40); // Keycode Set 1, no coordinate data + while (!m_fifo.empty()) { + m_hp_hil_mlc->hil_write(m_device_id16 | m_fifo.dequeue()); + frames++; + } + return frames; +} -/*************************************************************************** - HP INTEGRAL HLE KEYBOARD DEVICE -***************************************************************************/ - -/*-------------------------------------------------- - hle_hp_ipc_device::hle_hp_ipc_device - abbreviated constructor ---------------------------------------------------*/ - -hle_hp_ipc_device::hle_hp_ipc_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock) - : hle_device_base(mconfig, HP_IPC_HLE_KEYBOARD, tag, owner, clock) -{ } - +int hle_hp_itf_device::hil_poll() +{ + int frames = 0; + if (m_fifo.empty()) + return frames; + LOG("KBD HAVE DATA\n"); + frames++; + m_hp_hil_mlc->hil_write(m_device_id16 | 0x40); // Keycode Set 1, no coordinate data + while (!m_fifo.empty()) { + m_hp_hil_mlc->hil_write(m_device_id16 | m_fifo.dequeue()); + frames++; + } + return frames; +} /*-------------------------------------------------- hle_hp_ipc_device::device_input_ports @@ -629,8 +518,28 @@ ioport_constructor hle_hp_ipc_device::device_input_ports() const hle_hp_itf_device::hle_hp_itf_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock) : hle_device_base(mconfig, HP_ITF_HLE_KEYBOARD, tag, owner, clock) + , device_matrix_keyboard_interface(mconfig, *this, "COL1", "COL2", "COL3", "COL4", "COL5", "COL6", "COL7", "COL8", "COL9", "COL10", "COL11", "COL12", "COL13", "COL14", "COL15") { } +void hle_hp_itf_device::device_reset() +{ + m_fifo.clear(); + reset_key_state(); + start_processing(attotime::from_hz(1'200)); +} + +void hle_hp_itf_device::key_make(uint8_t row, uint8_t column) +{ + LOG("make\n"); + transmit_byte((((row + 1) ^ 8) << 4) + (column << 1)); +} + + +void hle_hp_itf_device::key_break(uint8_t row, uint8_t column) +{ + LOG("break\n"); + transmit_byte((((row + 1) ^ 8) << 4) + (column << 1) + 1); +} /*-------------------------------------------------- hle_hp_itf_device::device_input_ports @@ -643,4 +552,12 @@ ioport_constructor hle_hp_itf_device::device_input_ports() const } -} } // namespace bus::hp_hil +void hle_hp_itf_device::hil_idd() +{ + m_hp_hil_mlc->hil_write(m_device_id16 | ioport("COL0")->read()); + m_hp_hil_mlc->hil_write(m_device_id16 | 0x04); + return; +} + +} // namespace bus::hp_hil +} // namespace bus diff --git a/src/devices/bus/hp_hil/hlekbd.h b/src/devices/bus/hp_hil/hlekbd.h index 837e8501933..714b0ba6d2b 100644 --- a/src/devices/bus/hp_hil/hlekbd.h +++ b/src/devices/bus/hp_hil/hlekbd.h @@ -6,64 +6,92 @@ #pragma once #include "hp_hil.h" +#include "hlebase.h" #include "machine/keyboard.h" -namespace bus { namespace hp_hil { +namespace bus { + namespace hp_hil { -class hle_device_base - : public device_t - , public device_hp_hil_interface - , protected device_matrix_keyboard_interface<15U> +class hle_hp_ipc_device + : public hle_device_base + , protected device_matrix_keyboard_interface<15U> { public: - virtual ~hle_device_base() override; - - static constexpr feature_type imperfect_features() { return feature::KEYBOARD; } - -protected: - // constructor/destructor - hle_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, uint32_t clock); + hle_hp_ipc_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock); - // device overrides - virtual void device_start() override; + virtual ioport_constructor device_input_ports() const override; virtual void device_reset() override; // device_matrix_keyboard_interface overrides virtual void key_make(uint8_t row, uint8_t column) override; virtual void key_break(uint8_t row, uint8_t column) override; - - // device_hp_hil_interface overrides - virtual bool hil_write(uint16_t *data) override; - + virtual int hil_poll() override; + virtual void hil_idd() override; private: - void transmit_byte(uint8_t byte); - util::fifo m_fifo; + void transmit_byte(uint8_t byte); }; - -class hle_hp_ipc_device : public hle_device_base +class hle_hp_itf_device + : public hle_device_base + , protected device_matrix_keyboard_interface<15U> { public: - hle_hp_ipc_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock); - + hle_hp_itf_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock); + virtual void device_reset() override; virtual ioport_constructor device_input_ports() const override; + + // device_matrix_keyboard_interface overrides + virtual void key_make(uint8_t row, uint8_t column) override; + virtual void key_break(uint8_t row, uint8_t column) override; + virtual int hil_poll() override; + virtual void hil_idd() override; +private: + util::fifo m_fifo; + void transmit_byte(uint8_t byte); }; -class hle_hp_itf_device : public hle_device_base + +class hle_hp_46060b_device + : public hle_device_base { public: - hle_hp_itf_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock); - + hle_hp_46060b_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock); + virtual void device_reset() override; virtual ioport_constructor device_input_ports() const override; + virtual int hil_poll() override; + virtual void hil_idd() override; + enum state_mask + { + MOUSE_YPOS = 0x000000ff, + MOUSE_XPOS = 0x0000ff00, + MOUSE_LBUTTON = 0x00010000, + MOUSE_MBUTTON = 0x00020000, + MOUSE_RBUTTON = 0x00040000, + + MOUSE_BUTTONS = 0x00070000 + }; + + DECLARE_INPUT_CHANGED_MEMBER(mouse_button); + DECLARE_INPUT_CHANGED_MEMBER(mouse_x); + DECLARE_INPUT_CHANGED_MEMBER(mouse_y); + + int8_t mouse_x_delta; + int8_t mouse_y_delta; + uint32_t mouse_buttons; + util::fifo m_fifo; + }; -} } // namespace bus::hp_hil + +} // namespace bus::hp_hil +} // namespace bus DECLARE_DEVICE_TYPE_NS(HP_IPC_HLE_KEYBOARD, bus::hp_hil, hle_hp_ipc_device); DECLARE_DEVICE_TYPE_NS(HP_ITF_HLE_KEYBOARD, bus::hp_hil, hle_hp_itf_device); +DECLARE_DEVICE_TYPE_NS(HP_46060B_MOUSE, bus::hp_hil, hle_hp_46060b_device); #endif // MAME_DEVICES_HP_HIL_HLEKBD_H diff --git a/src/devices/bus/hp_hil/hlemouse.cpp b/src/devices/bus/hp_hil/hlemouse.cpp new file mode 100644 index 00000000000..9fc6c9db985 --- /dev/null +++ b/src/devices/bus/hp_hil/hlemouse.cpp @@ -0,0 +1,127 @@ +// license:BSD-3-Clause +// copyright-holders:Sven Schnelle +#include "emu.h" +#include "hlekbd.h" + +#include "machine/keyboard.ipp" +//#define VERBOSE 1 +#include "logmacro.h" + +/*************************************************************************** + DEVICE TYPE GLOBALS +***************************************************************************/ + +DEFINE_DEVICE_TYPE_NS(HP_46060B_MOUSE, bus::hp_hil, hle_hp_46060b_device, "hp_46060b", "HP 46060B Mouse") + +namespace bus { + namespace hp_hil { + +namespace { + +/*************************************************************************** + INPUT PORT DEFINITIONS +***************************************************************************/ + +INPUT_PORTS_START( hle_hp_46060b_device ) + PORT_START("mouse_buttons") + PORT_BIT(hle_hp_46060b_device::MOUSE_LBUTTON, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Mouse Left Button") PORT_CODE(MOUSECODE_BUTTON1) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_hp_46060b_device, mouse_button, nullptr) + PORT_BIT(hle_hp_46060b_device::MOUSE_MBUTTON, IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_NAME("Mouse Middle Button") PORT_CODE(MOUSECODE_BUTTON3) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_hp_46060b_device, mouse_button, nullptr) + PORT_BIT(hle_hp_46060b_device::MOUSE_RBUTTON, IP_ACTIVE_HIGH, IPT_BUTTON3) PORT_NAME("Mouse Right Button") PORT_CODE(MOUSECODE_BUTTON2) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_hp_46060b_device, mouse_button, nullptr) + + PORT_START("mouse_x") + PORT_BIT(0xff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(50) PORT_KEYDELTA(0) PORT_PLAYER(1) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_hp_46060b_device, mouse_x, nullptr) + PORT_START("mouse_y") + PORT_BIT(0xff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(50) PORT_KEYDELTA(0) PORT_PLAYER(1) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_hp_46060b_device, mouse_y, nullptr) +INPUT_PORTS_END +} // anonymous namespace + +hle_hp_46060b_device::hle_hp_46060b_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock) + : hle_device_base(mconfig, HP_46060B_MOUSE, tag, owner, clock) +{ } + +void hle_hp_46060b_device::device_reset() +{ + m_fifo.clear(); +} + +int hle_hp_46060b_device::hil_poll() +{ + int frames = 0; + uint16_t reports = 0; + + if (mouse_x_delta || mouse_y_delta) + reports |= 2; + + if (!m_fifo.empty()) + reports |= 0x40; + + if (!reports) + return 0; + + m_hp_hil_mlc->hil_write(m_device_id16 | reports); // report X & Y data + frames++; + if (mouse_x_delta || mouse_y_delta) { + m_hp_hil_mlc->hil_write(m_device_id16 | (uint8_t)mouse_x_delta); + m_hp_hil_mlc->hil_write(m_device_id16 | (uint8_t)mouse_y_delta); + mouse_x_delta = 0; + mouse_y_delta = 0; + frames+=2; + } + + while (!m_fifo.empty()) { + m_hp_hil_mlc->hil_write(m_device_id16 | m_fifo.dequeue()); + frames++; + } + + return frames; +} + + +void hle_hp_46060b_device::hil_idd() +{ + m_hp_hil_mlc->hil_write(m_device_id16 | 0x68); + m_hp_hil_mlc->hil_write(m_device_id16 | 0x12); // report X & Y Axes + m_hp_hil_mlc->hil_write(m_device_id16 | 0xc2); // resolution Low + m_hp_hil_mlc->hil_write(m_device_id16 | 0x1e); // resolution High + return; +} + +ioport_constructor hle_hp_46060b_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(hle_hp_46060b_device); +} + +INPUT_CHANGED_MEMBER(hle_hp_46060b_device::mouse_y) +{ + int8_t delta = newval - oldval; + mouse_y_delta += -delta; +} + +INPUT_CHANGED_MEMBER(hle_hp_46060b_device::mouse_x) +{ + int8_t delta = newval - oldval; + mouse_x_delta += delta; +} + +INPUT_CHANGED_MEMBER(hle_hp_46060b_device::mouse_button) +{ + const ioport_value data = field.port().read(); + uint32_t _data = data & MOUSE_BUTTONS; + + switch(_data ^ mouse_buttons) { + case MOUSE_LBUTTON: + if (!m_fifo.full()) { + m_fifo.enqueue(_data ? 0x80 : 0x81); + } + break; + case MOUSE_RBUTTON: + if (!m_fifo.full()) { + m_fifo.enqueue(_data ? 0x82 : 0x83); + } + break; + } + mouse_buttons = data; +} + +} // namesapce bus::hp_hil +} // namespace bus diff --git a/src/devices/bus/hp_hil/hlemouse.h b/src/devices/bus/hp_hil/hlemouse.h new file mode 100644 index 00000000000..7abfc1d5192 --- /dev/null +++ b/src/devices/bus/hp_hil/hlemouse.h @@ -0,0 +1,52 @@ +// license:BSD-3-Clause +// copyright-holders:Sven Schnelle +#ifndef MAME_DEVICES_HP_HIL_HLEMOUSE_H +#define MAME_DEVICES_HP_HIL_HLEMOUSE_H + +#pragma once + +#include "hp_hil.h" +#include "hlebase.h" +#include "machine/keyboard.h" + + +namespace bus { + namespace hp_hil { + +class hle_hp_46060b_device + : public hle_device_base +{ +public: + hle_hp_46060b_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock); + virtual void device_reset() override; + virtual ioport_constructor device_input_ports() const override; + virtual int hil_poll() override; + virtual void hil_idd() override; + enum state_mask + { + MOUSE_YPOS = 0x000000ff, + MOUSE_XPOS = 0x0000ff00, + MOUSE_LBUTTON = 0x00010000, + MOUSE_MBUTTON = 0x00020000, + MOUSE_RBUTTON = 0x00040000, + + MOUSE_BUTTONS = 0x00070000 + }; + + DECLARE_INPUT_CHANGED_MEMBER(mouse_button); + DECLARE_INPUT_CHANGED_MEMBER(mouse_x); + DECLARE_INPUT_CHANGED_MEMBER(mouse_y); + + int8_t mouse_x_delta; + int8_t mouse_y_delta; + uint32_t mouse_buttons; + util::fifo m_fifo; + +}; + +} // namespace bus::hp_hil +} // namespace bus + +DECLARE_DEVICE_TYPE_NS(HP_46060B_MOUSE, bus::hp_hil, hle_hp_46060b_device); + +#endif // MAME_DEVICES_HP_HIL_HLEMOUSE_H diff --git a/src/mame/drivers/hp_ipc.cpp b/src/mame/drivers/hp_ipc.cpp index c28116b37a4..de97ac955c5 100644 --- a/src/mame/drivers/hp_ipc.cpp +++ b/src/mame/drivers/hp_ipc.cpp @@ -758,6 +758,7 @@ MACHINE_CONFIG_START(hp_ipc_state::hp_ipc_base) MCFG_HP_HIL_INT_CALLBACK(WRITELINE(*this, hp_ipc_state, irq_2)) MCFG_HP_HIL_NMI_CALLBACK(WRITELINE(*this, hp_ipc_state, irq_7)) MCFG_HP_HIL_SLOT_ADD("mlc", "hil1", hp_hil_devices, "hp_ipc_kbd") + MCFG_HP_HIL_SLOT_ADD("mlc", "hil2", hp_hil_devices, "hp_46060b") MCFG_DEVICE_ADD("hpib", TMS9914, 4_MHz_XTAL) MCFG_TMS9914_INT_WRITE_CB(WRITELINE(*this, hp_ipc_state, irq_3)) -- cgit v1.2.3 From c6900b12fde939126e89f4bea6744dbc2cb51ed4 Mon Sep 17 00:00:00 2001 From: AJR Date: Fri, 12 Oct 2018 22:45:15 -0400 Subject: New machines marked as NOT_WORKING ---------------------------------- Scientific Instruments Model 5500 Temperature Controller [ClawGrip] --- scripts/src/machine.lua | 12 +++ scripts/target/mame/mess.lua | 2 + src/devices/machine/x2201.cpp | 189 ++++++++++++++++++++++++++++++++++ src/devices/machine/x2201.h | 75 ++++++++++++++ src/mame/drivers/si5500.cpp | 232 ++++++++++++++++++++++++++++++++++++++++++ src/mame/mame.lst | 3 + src/mame/mess.flt | 1 + 7 files changed, 514 insertions(+) create mode 100644 src/devices/machine/x2201.cpp create mode 100644 src/devices/machine/x2201.h create mode 100644 src/mame/drivers/si5500.cpp (limited to 'scripts/src') diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua index 1c0ecc07b59..03ee38c0c90 100644 --- a/scripts/src/machine.lua +++ b/scripts/src/machine.lua @@ -2959,6 +2959,18 @@ if (MACHINES["WD7600"]~=null) then } end +--------------------------------------------------- +-- +--@src/devices/machine/x2201.h,MACHINES["X2201"] = true +--------------------------------------------------- + +if (MACHINES["X2201"]~=null) then + files { + MAME_DIR .. "src/devices/machine/x2201.cpp", + MAME_DIR .. "src/devices/machine/x2201.h", + } +end + --------------------------------------------------- -- --@src/devices/machine/x2212.h,MACHINES["X2212"] = true diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index 2c1b153eaf7..8fbb1a75114 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -618,6 +618,7 @@ MACHINES["WD11C00_17"] = true MACHINES["WD2010"] = true MACHINES["WD33C93"] = true MACHINES["WD7600"] = true +MACHINES["X2201"] = true MACHINES["X2212"] = true MACHINES["X76F041"] = true MACHINES["X76F100"] = true @@ -3808,6 +3809,7 @@ files { MAME_DIR .. "src/mame/drivers/sh4robot.cpp", MAME_DIR .. "src/mame/drivers/sansa_fuze.cpp", MAME_DIR .. "src/mame/drivers/scopus.cpp", + MAME_DIR .. "src/mame/drivers/si5500.cpp", MAME_DIR .. "src/mame/drivers/softbox.cpp", MAME_DIR .. "src/mame/includes/softbox.h", MAME_DIR .. "src/mame/drivers/squale.cpp", diff --git a/src/devices/machine/x2201.cpp b/src/devices/machine/x2201.cpp new file mode 100644 index 00000000000..eb7ebd50f05 --- /dev/null +++ b/src/devices/machine/x2201.cpp @@ -0,0 +1,189 @@ +// license:BSD-3-Clause +// copyright-holders:AJR +/********************************************************************** + + Xicor X2201 1024 x 1 bit Nonvolatile Static RAM + + This was Xicor's first NOVRAM product, combining static RAM with + an E²PROM overlay. Besides having separate data input and output + lines (and only one of each), its interface differs slightly from + the later NOVRAMs in requiring an active chip select during recall + and store operations. + + While US patent 4535411A suggests that this device was sometimes + used in groups of eight to simulate a byte-wide memory, the + emulation (for the most part) assumes each bit will be accessed + separately and packs them into bytes for storage efficiency. + +**********************************************************************/ + +#include "emu.h" +#include "machine/x2201.h" +#include + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +DEFINE_DEVICE_TYPE(X2201, x2201_device, "x2201", "Xicor X2201 1024x1 NOVRAM") + + +//************************************************************************** +// DEVICE CONSTRUCTION AND INITIALIZATION +//************************************************************************** + +//------------------------------------------------- +// x2201_device - constructor +//------------------------------------------------- + +x2201_device::x2201_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : device_t(mconfig, X2201, tag, owner, clock) + , device_nvram_interface(mconfig, *this) + , m_default_data(*this, DEVICE_SELF, 1024 / 8) + , m_cs(false) + , m_store(false) + , m_array_recall(false) +{ +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void x2201_device::device_start() +{ + // create arrays + m_ram = make_unique_clear(1024 / 8); + m_eeprom = std::make_unique(1028 / 8); + + // register state for saving + save_pointer(NAME(m_ram), 1024 / 8); + save_pointer(NAME(m_eeprom), 1024 / 8); + save_item(NAME(m_cs)); + save_item(NAME(m_store)); + save_item(NAME(m_array_recall)); +} + + +//************************************************************************** +// NVRAM INTERFACE +//************************************************************************** + +//------------------------------------------------- +// nvram_default - called to initialize NVRAM to +// its default state +//------------------------------------------------- + +void x2201_device::nvram_default() +{ + // erase to ones unless region overrides + if (m_default_data.found()) + std::copy_n(&m_default_data[0], 1024 / 8, &m_eeprom[0]); + else + std::fill_n(&m_eeprom[0], 1024 / 8, 0xff); +} + + +//------------------------------------------------- +// nvram_read - called to read NVRAM from the +// specified file +//------------------------------------------------- + +void x2201_device::nvram_read(emu_file &file) +{ + file.read(&m_eeprom[0], 1024 / 8); +} + + +//------------------------------------------------- +// nvram_write - called to write NVRAM to the +// specified file +//------------------------------------------------- + +void x2201_device::nvram_write(emu_file &file) +{ + file.write(&m_eeprom[0], 1024 / 8); +} + + +//************************************************************************** +// MEMORY ACCESS +//************************************************************************** + +//------------------------------------------------- +// read - read the addressed bit of RAM +//------------------------------------------------- + +u8 x2201_device::read(offs_t offset) +{ + return BIT(m_ram[(offset >> 3) & 127], offset & 7); +} + + +//------------------------------------------------- +// read_byte - read 8 bits of data from RAM +// (FIXME: remove once CRU reads are 1-bit) +//------------------------------------------------- + +u8 x2201_device::read_byte(offs_t offset) +{ + return m_ram[offset & 127]; +} + + +//------------------------------------------------- +// write - write one bit of data to RAM +//------------------------------------------------- + +void x2201_device::write(offs_t offset, u8 data) +{ + offs_t address = (offset >> 3) & 127; + if (BIT(data, 0)) + m_ram[address] |= 1 << (offset & 7); + else + m_ram[address] &= ~(1 << (offset & 7)); +} + + +//************************************************************************** +// CONTROL STROBES +//************************************************************************** + +//------------------------------------------------- +// cs_w - write to the CS line (active low) +//------------------------------------------------- + +WRITE_LINE_MEMBER(x2201_device::cs_w) +{ + m_cs = !state; +} + + +//------------------------------------------------- +// store_w - trigger to store RAM data in EEPROM +// (active low) +//------------------------------------------------- + +WRITE_LINE_MEMBER(x2201_device::store_w) +{ + if (m_cs && !state && !m_store) + std::copy_n(&m_ram[0], 1024 / 8, &m_eeprom[0]); + + m_array_recall = !state; +} + + +//------------------------------------------------- +// array_recall_w - trigger to pull EEPROM data +// into RAM (active low) +//------------------------------------------------- + +WRITE_LINE_MEMBER(x2201_device::array_recall_w) +{ + if (m_cs && !state && !m_array_recall) + std::copy_n(&m_eeprom[0], 1024 / 8, &m_ram[0]); + + m_array_recall = !state; +} diff --git a/src/devices/machine/x2201.h b/src/devices/machine/x2201.h new file mode 100644 index 00000000000..670c69b349c --- /dev/null +++ b/src/devices/machine/x2201.h @@ -0,0 +1,75 @@ +// license:BSD-3-Clause +// copyright-holders:AJR +/*************************************************************************** + + Xicor X2201 1024 x 1 bit Nonvolatile Static RAM + +**************************************************************************** + ____ ____ + A0 1 |* \_/ | 18 Vcc + A1 2 | | 17 A5 + A2 3 | | 16 A6 + A3 4 | | 15 A7 + A4 5 | X2201 | 14 A8 + DOut 6 | | 13 A9 + /STORE 7 | | 12 DIn + /WE 8 | | 11 /ARRAY RECALL + GND 9 |___________| 10 /CS + +***************************************************************************/ + +#ifndef MAME_MACHINE_X2201_H +#define MAME_MACHINE_X2201_H + +#pragma once + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> x2201_device + +class x2201_device : public device_t, public device_nvram_interface +{ +public: + // construction/destruction + x2201_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + + // read/write handlers + u8 read(offs_t offset); + u8 read_byte(offs_t offset); // hack + void write(offs_t offset, u8 data); + + // control lines + DECLARE_WRITE_LINE_MEMBER(cs_w); + DECLARE_WRITE_LINE_MEMBER(array_recall_w); + DECLARE_WRITE_LINE_MEMBER(store_w); + +protected: + // device-level overrides + virtual void device_start() override; + + // device_nvram_interface overrides + virtual void nvram_default() override; + virtual void nvram_read(emu_file &file) override; + virtual void nvram_write(emu_file &file) override; + +private: + // optional default data + optional_region_ptr m_default_data; + + // memory arrays + std::unique_ptr m_ram; + std::unique_ptr m_eeprom; + + // line state + bool m_cs; + bool m_store; + bool m_array_recall; +}; + +// device type definition +DECLARE_DEVICE_TYPE(X2201, x2201_device) + +#endif // MAME_MACHINE_X2201_H diff --git a/src/mame/drivers/si5500.cpp b/src/mame/drivers/si5500.cpp new file mode 100644 index 00000000000..692ba8b63b4 --- /dev/null +++ b/src/mame/drivers/si5500.cpp @@ -0,0 +1,232 @@ +// license:BSD-3-Clause +// copyright-holders:AJR +/***************************************************************************************** + + Skeleton driver for Scientific Instruments Model 5500 temperature controller. + +*****************************************************************************************/ + +#include "emu.h" +#include "cpu/tms9900/tms9980a.h" +#include "machine/74259.h" +//#include "machine/icl7104.h" +#include "machine/tms9901.h" +#include "machine/tms9902.h" +#include "machine/tms9914.h" +#include "machine/x2201.h" + +class si5500_state : public driver_device +{ +public: + si5500_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag) + , m_maincpu(*this, "maincpu") + , m_mainpsi(*this, "mainpsi") + , m_gpibpsi(*this, "gpibpsi") + , m_gpibc(*this, "gpibc") + , m_keyplatch(*this, "keyplatch") + , m_keypad(*this, "KEYPAD%u", 0U) + { + } + + void si5500(machine_config &config); + +protected: + virtual void machine_start() override; + +private: + void mainic_w(offs_t offset, u8 data); + DECLARE_WRITE_LINE_MEMBER(gpib_int_w); + DECLARE_WRITE_LINE_MEMBER(acc_int_w); + u8 gpibpsi_input_r(offs_t offset); + DECLARE_WRITE_LINE_MEMBER(gpibc_we_w); + DECLARE_WRITE_LINE_MEMBER(gpibc_dbin_w); + u8 keypad_r(); + + void mem_map(address_map &map); + void cru_map(address_map &map); + + required_device m_maincpu; + required_device m_mainpsi; + required_device m_gpibpsi; + required_device m_gpibc; + required_device m_keyplatch; + required_ioport_array<4> m_keypad; + + u8 m_gpib_data; +}; + +void si5500_state::machine_start() +{ + m_gpib_data = 0; + save_item(NAME(m_gpib_data)); +} + +void si5500_state::mainic_w(offs_t offset, u8 data) +{ + if (data) + m_maincpu->set_input_line(offset & 7, ASSERT_LINE); + else + m_maincpu->set_input_line(INT_9980A_CLEAR, CLEAR_LINE); +} + +WRITE_LINE_MEMBER(si5500_state::gpib_int_w) +{ + m_mainpsi->set_single_int(4, state); +} + +WRITE_LINE_MEMBER(si5500_state::acc_int_w) +{ + m_mainpsi->set_single_int(5, state); +} + +u8 si5500_state::gpibpsi_input_r(offs_t offset) +{ + if (offset == tms9901_device::P0_P7) + return m_gpib_data; + + return 0xff; +} + +WRITE_LINE_MEMBER(si5500_state::gpibc_we_w) +{ + if (!state) + { + u16 pio = m_gpibpsi->pio_outputs(); + m_gpibc->reg8_w(machine().dummy_space(), (pio >> 8) & 7, pio & 0xff); + } +} + +WRITE_LINE_MEMBER(si5500_state::gpibc_dbin_w) +{ + if (state) + { + u16 pio = m_gpibpsi->pio_outputs(); + m_gpib_data = m_gpibc->reg8_r(machine().dummy_space(), (pio >> 8) & 7); + } +} + +u8 si5500_state::keypad_r() +{ + u8 result = 0xff; + + for (int n = 0; n < 4; n++) + if (!BIT(m_keyplatch->output_state(), n)) + result &= m_keypad[n]->read(); + + return result; +} + +void si5500_state::mem_map(address_map &map) +{ + map(0x0000, 0x2fff).rom().region("program", 0); + map(0x3800, 0x3fff).ram(); +} + +void si5500_state::cru_map(address_map &map) +{ + // MAME currently has incompatible addressing for CRU reads and writes + map(0x00, 0x03).r(m_mainpsi, FUNC(tms9901_device::read)); + map(0x08, 0x0b).r("acc", FUNC(tms9902_device::cruread)); + map(0x0c, 0x0f).r("adpsi", FUNC(tms9901_device::read)); + map(0x16, 0x16).nopr(); + map(0x17, 0x17).r(FUNC(si5500_state::keypad_r)); + map(0x40, 0x43).r("nvrpsi", FUNC(tms9901_device::read)); + map(0x44, 0x47).r(m_gpibpsi, FUNC(tms9901_device::read)); + map(0x80, 0xff).r("novram", FUNC(x2201_device::read_byte)); + + map(0x000, 0x01f).w(m_mainpsi, FUNC(tms9901_device::write)); + map(0x040, 0x05f).w("acc", FUNC(tms9902_device::cruwrite)); + map(0x060, 0x07f).w("adpsi", FUNC(tms9901_device::write)); + map(0x080, 0x087).w("outlatch1", FUNC(ls259_device::write_d0)); + map(0x088, 0x08f).w("outlatch2", FUNC(ls259_device::write_d0)); + map(0x090, 0x097).w("outlatch3", FUNC(ls259_device::write_d0)); + map(0x0a0, 0x0a7).w("outlatch4", FUNC(ls259_device::write_d0)); + map(0x0a8, 0x0af).w("outlatch5", FUNC(ls259_device::write_d0)); + map(0x0b0, 0x0bf).w(m_keyplatch, FUNC(ls259_device::write_d0)); + map(0x200, 0x21f).w("nvrpsi", FUNC(tms9901_device::write)); + map(0x220, 0x23f).w(m_gpibpsi, FUNC(tms9901_device::write)); + map(0x400, 0x7ff).w("novram", FUNC(x2201_device::write)); +} + +static INPUT_PORTS_START(si5500) + PORT_START("KEYPAD0") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("7") PORT_CODE(KEYCODE_7) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("4") PORT_CODE(KEYCODE_4) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("1") PORT_CODE(KEYCODE_1) + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("0") PORT_CODE(KEYCODE_0) + PORT_BIT(0xf0, IP_ACTIVE_LOW, IPT_UNUSED) + + PORT_START("KEYPAD1") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("8") PORT_CODE(KEYCODE_8) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("5") PORT_CODE(KEYCODE_5) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("2") PORT_CODE(KEYCODE_2) + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Enter") PORT_CODE(KEYCODE_ENTER) + PORT_BIT(0xf0, IP_ACTIVE_LOW, IPT_UNUSED) + + PORT_START("KEYPAD2") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("9") PORT_CODE(KEYCODE_9) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("6") PORT_CODE(KEYCODE_6) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("3") PORT_CODE(KEYCODE_3) + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("#") PORT_CODE(KEYCODE_EQUALS) + PORT_BIT(0xf0, IP_ACTIVE_LOW, IPT_UNUSED) + + PORT_START("KEYPAD3") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("S") PORT_CODE(KEYCODE_S) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("M") PORT_CODE(KEYCODE_M) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("R") PORT_CODE(KEYCODE_R) + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("*") PORT_CODE(KEYCODE_MINUS) + PORT_BIT(0xf0, IP_ACTIVE_LOW, IPT_UNUSED) +INPUT_PORTS_END + +void si5500_state::si5500(machine_config &config) +{ + TMS9981(config, m_maincpu, 10_MHz_XTAL); + m_maincpu->set_addrmap(AS_PROGRAM, &si5500_state::mem_map); + m_maincpu->set_addrmap(AS_IO, &si5500_state::cru_map); + + TMS9901(config, m_mainpsi, 10_MHz_XTAL / 4); + m_mainpsi->intlevel_cb().set(FUNC(si5500_state::mainic_w)); + + tms9902_device &acc(TMS9902(config, "acc", 10_MHz_XTAL / 4)); + acc.int_cb().set(FUNC(si5500_state::acc_int_w)); + + TMS9901(config, "adpsi", 10_MHz_XTAL / 4); + + X2201(config, "novram"); + + tms9901_device &nvrpsi(TMS9901(config, "nvrpsi", 10_MHz_XTAL / 4)); + // P0-11 = inputs for DAC? + nvrpsi.p_out_cb(13).set("novram", FUNC(x2201_device::array_recall_w)); + nvrpsi.p_out_cb(14).set("novram", FUNC(x2201_device::store_w)); + nvrpsi.p_out_cb(15).set("novram", FUNC(x2201_device::cs_w)); + + TMS9901(config, m_gpibpsi, 10_MHz_XTAL / 4); + m_gpibpsi->p_out_cb(11).set(FUNC(si5500_state::gpibc_we_w)); + m_gpibpsi->p_out_cb(12).set(FUNC(si5500_state::gpibc_dbin_w)); + m_gpibpsi->read_cb().set(FUNC(si5500_state::gpibpsi_input_r)); + + TMS9914(config, m_gpibc, 10_MHz_XTAL / 4); + m_gpibc->int_write_cb().set(FUNC(si5500_state::gpib_int_w)); + + LS259(config, "outlatch1"); + LS259(config, "outlatch2"); + LS259(config, "outlatch3"); + LS259(config, "outlatch4"); + LS259(config, "outlatch5"); + LS259(config, m_keyplatch); +} + +// Board #1 (power): no digital ICs +// Board #2 (analog): TMS9901NL, ICL7104-16CPL, ICL8052ACPD, AD524AD, LF13509D +// Board #3 (output): X2201AD, 2x TMS9901NL, DAC1222LCN, TMS9914ANL, SN75162BN, DS75160AN +// Board #4: HM6116P-4, 3x TMS2532A-25JL, XTAL (10 MHz), TMS9981JDL, TMS9902ANL, TMS9901NL +// Back of front panel: 6x HD74LS259, HD74LS251 +ROM_START(si5500) + ROM_REGION(0x3000, "program", 0) + ROM_LOAD("m5500dl_7-9-86.u4", 0x0000, 0x1000, CRC(cfcff0fe) SHA1(94173b3b7513954221ce3402ea5b5c36dfa5a8da)) + ROM_LOAD("m5500dl_7-9-86.u5", 0x1000, 0x1000, CRC(a932e85a) SHA1(f7152ae78bad79b457bb739e7ecc4556ca33cbbc)) + ROM_LOAD("m5500dl_7-9-86.u6", 0x2000, 0x1000, CRC(3161347d) SHA1(fab6c228a21ef3ecce255079a48ef1697f2c7ccb)) +ROM_END + +COMP(1986, si5500, 0, 0, si5500, si5500, si5500_state, empty_init, "Scientific Instruments", "Model 5500 Temperature Controller", MACHINE_IS_SKELETON) diff --git a/src/mame/mame.lst b/src/mame/mame.lst index 8ac8cec8598..0ad67d597de 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -35027,6 +35027,9 @@ smssgamea shuuz // 136083 (c) 1990 shuuz2 // 136083 (c) 1990 +@source:si5500.cpp +si5500 // + @source:sidearms.cpp dyger // (c) 1989 Philko (NOT A CAPCOM GAME but runs on modified Sidearms hardware) dygera // (c) 1989 Philko (NOT A CAPCOM GAME but runs on modified Sidearms hardware) diff --git a/src/mame/mess.flt b/src/mame/mess.flt index dc33a8547e5..aed402e5a6a 100644 --- a/src/mame/mess.flt +++ b/src/mame/mess.flt @@ -650,6 +650,7 @@ segapm.cpp selz80.cpp sg1000.cpp sh4robot.cpp +si5500.cpp sitcom.cpp sk1.cpp slc1.cpp -- cgit v1.2.3 From cea5bbace487abdaa98256d794be347192873b19 Mon Sep 17 00:00:00 2001 From: Patrick Mackinlay Date: Thu, 18 Oct 2018 18:00:02 +0700 Subject: z8038: new device (nw) Zilog Z8038 FIO (FIFO Input/Output Interface Unit). Used to drive the parallel/printer port on the MIPS Rx2030. Passes basic diagnostic tests, but further work depends on progress in the mips.cpp driver. --- scripts/src/machine.lua | 12 + scripts/target/mame/mess.lua | 1 + src/devices/machine/z8038.cpp | 700 ++++++++++++++++++++++++++++++++++++++++++ src/devices/machine/z8038.h | 229 ++++++++++++++ 4 files changed, 942 insertions(+) create mode 100644 src/devices/machine/z8038.cpp create mode 100644 src/devices/machine/z8038.h (limited to 'scripts/src') diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua index 03ee38c0c90..ce7c2813b8f 100644 --- a/scripts/src/machine.lua +++ b/scripts/src/machine.lua @@ -3795,3 +3795,15 @@ if (MACHINES["SUN4C_MMU"]~=null) then MAME_DIR .. "src/devices/machine/sun4c_mmu.h", } end + +--------------------------------------------------- +-- +--@src/devices/machine/z8038.h,MACHINES["Z8038"] = true +--------------------------------------------------- + +if (MACHINES["Z8038"]~=null) then + files { + MAME_DIR .. "src/devices/machine/z8038.cpp", + MAME_DIR .. "src/devices/machine/z8038.h", + } +end diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index d0f914e1034..72c2dc1aace 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -671,6 +671,7 @@ MACHINES["IOPDMA"] = true MACHINES["IOPINTC"] = true MACHINES["IOPSIO2"] = true MACHINES["IOPTIMER"] = true +MACHINES["Z8038"] = true -------------------------------------------------- -- specify available bus cores diff --git a/src/devices/machine/z8038.cpp b/src/devices/machine/z8038.cpp new file mode 100644 index 00000000000..7cd55fb6d45 --- /dev/null +++ b/src/devices/machine/z8038.cpp @@ -0,0 +1,700 @@ +// license:BSD-3-Clause +// copyright-holders:Patrick Mackinlay + +/* + * An emulation of the Zilog Z8038 FIO FIFO Input/Output Interface Unit. + * + * Sources: + * + * http://datasheet.datasheetarchive.com/originals/scans/Scans-98/DSAIHSC00090399.pdf + * + * The external interface uses port number 1 and 2 per the documentation, while + * the implementation uses port number 0 and 1 for convenience. + * + * TODO + * - more i/o lines and handshake + * - Z-BUS interrupt/acknowledge + * - dma cycles + * - fifo save state + */ + +#include "emu.h" +#include "z8038.h" + +#define LOG_GENERAL (1U << 0) +#define LOG_REG (1U << 1) +#define LOG_FIFO (1U << 2) +#define LOG_INT (1U << 3) + +//#define VERBOSE (LOG_GENERAL|LOG_REG|LOG_FIFO|LOG_INT) + +#include "logmacro.h" + +DEFINE_DEVICE_TYPE(Z8038, z8038_device, "z8038", "FIFO Input/Output Interface Unit") + +z8038_device::z8038_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, Z8038, tag, owner, clock) + , m_out_int_cb{ *this, *this } + , m_out_E_cb(*this) + , m_out_F_cb(*this) + , m_out_H_cb(*this) + , m_out_J_cb(*this) +{ +} + +template void z8038_device::zbus_map(address_map &map) +{ + map(0x0, 0xf).rw(FUNC(z8038_device::zbus_reg_r), FUNC(z8038_device::zbus_reg_w)); + + // port 2 can not write to control register 2 + if (Port == 2) + map(0x9, 0x9).unmapw(); + + // Message In register is read-only + map(0xc, 0xc).unmapw(); +} + +// instantiate maps for port 1 and 2 +template void z8038_device::zbus_map<1>(address_map &map); +template void z8038_device::zbus_map<2>(address_map &map); + +void z8038_device::device_start() +{ + m_out_int_cb[0].resolve_safe(); + m_out_int_cb[1].resolve_safe(); + + m_out_E_cb.resolve_safe(); + m_out_F_cb.resolve_safe(); + m_out_H_cb.resolve_safe(); + m_out_J_cb.resolve_safe(); + + save_item(NAME(m_control_2)); + save_item(NAME(m_control_3)); + + for (u8 port = 0; port < 2; port++) + { + save_item(m_port[port].reg_state, "state", port + 1); + save_item(m_port[port].reg_pointer, "pointer", port + 1); + save_item(m_port[port].int_code, "int_code", port + 1); + save_item(m_port[port].int_asserted, "int_asserted", port + 1); + + save_item(m_port[port].control_0, "control_0", port + 1); + save_item(m_port[port].control_1, "control_1", port + 1); + save_item(m_port[port].interrupt_status, "interrupt_status", port + 1); + save_item(m_port[port].interrupt_vector, "interrupt_vector", port + 1); + save_item(m_port[port].byte_count, "byte_count", port + 1); + save_item(m_port[port].byte_count_comparison, "byte_count_comparison", port + 1); + save_item(m_port[port].message_in, "message_in", port + 1); + save_item(m_port[port].pattern_match, "pattern_match", port + 1); + save_item(m_port[port].pattern_mask, "pattern_mask", port + 1); + save_item(m_port[port].data_buffer, "data_buffer", port + 1); + } + + //save_item(NAME(m_fifo)); + + m_int_check = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(z8038_device::int_check), this)); + + // suppress startup interrupt line changes + m_port[0].int_asserted = false; + m_port[1].int_asserted = false; +} + +void z8038_device::device_reset() +{ + m_control_2 = 0; + + for (u8 port = 0; port < 2; port++) + { + m_port[port].reg_state = 0; + m_port[port].reg_pointer = 0; + m_port[port].int_code = 0; + m_port[port].control_0 = CR0_RESET; + set_int_state(port, false); + } +} + +u8 z8038_device::reg_r(u8 const port) +{ + /* + * The Port 2 CPU can determine when it is enabled by reading its Control + * Register 0, which is read as a "floating" data bus if not enabled or as + * 01H if enabled. + * + * FIXME: unsure what value to return for floating data bus + */ + if (port && !(m_control_2 & CR2_P2EN)) + return 0xff; + + // FIXME: reads from port 2 in i/o mode + if (port && (m_port[port].control_0 & CR0_P2M_IO)) + fatalerror("unexpected register read from Port 2 in i/o mode\n"); + + /* + * After reset is asserted, the only register that can be read from or + * written to is Control Register 0 (Control Register 0 will read a 01H). + */ + if (m_port[port].control_0 & CR0_RESET) + return m_port[port].control_0; + + u8 data = 0; + switch (m_port[port].reg_pointer) + { + case 0x0: data = control_0_r(port); break; + case 0x1: data = control_1_r(port); break; + case 0x2: data = interrupt_status_r<0>(port); break; + case 0x3: data = interrupt_status_r<1>(port); break; + case 0x4: data = interrupt_status_r<2>(port); break; + case 0x5: data = interrupt_status_r<3>(port); break; + case 0x6: data = interrupt_vector_r(port); break; + case 0x7: data = byte_count_r(port); break; + case 0x8: data = byte_count_comparison_r(port); break; + case 0x9: data = control_2_r(port); break; + case 0xa: data = control_3_r(port); break; + case 0xb: data = message_out_r(port); break; + case 0xc: data = message_in_r(port); break; + case 0xd: data = pattern_match_r(port); break; + case 0xe: data = pattern_mask_r(port); break; + case 0xf: data = fifo_r(port); break; + } + + m_port[port].reg_state = 0; + + LOGMASKED(LOG_REG, "reg_r port %d reg %d data 0x%02x\n", port + 1, m_port[port].reg_pointer, data); + + return data; +} + +void z8038_device::reg_w(u8 const port, u8 data) +{ + // check port 2 enabled + if (port && !(m_control_2 & CR2_P2EN)) + return; + + // FIXME: writes from port 2 in i/o mode + if (port && (m_port[port].control_0 & CR0_P2M_IO)) + fatalerror("unexpected register write from Port 2 in i/o mode\n"); + + /* + * If C/D̅ is 1, the next byte writes into Control Register 0. When in the + * reset state, a write should not be done when C/D̅ is 0. The reset state + * is exited by writing 00H when C/D̅ is 1. + */ + if (m_port[port].control_0 & CR0_RESET) + { + if (data == 0) + { + LOG("reg_w port %d reset state cleared\n", port + 1); + m_port[port].reg_pointer = 0; + m_port[port].reg_state = 0; + + m_port[port].control_0 = data; + } + + return; + } + + if (m_port[port].reg_state == 1) + { + switch (m_port[port].reg_pointer) + { + case 0x0: control_0_w(port, data); break; + case 0x1: control_1_w(port, data); break; + case 0x2: interrupt_status_w<0>(port, data); break; + case 0x3: interrupt_status_w<1>(port, data); break; + case 0x4: interrupt_status_w<2>(port, data); break; + case 0x5: interrupt_status_w<3>(port, data); break; + case 0x6: interrupt_vector_w(port, data); break; + case 0x7: break; // byte count register (read only) + case 0x8: byte_count_comparison_w(port, data); break; + case 0x9: control_2_w(port, data); break; + case 0xa: control_3_w(port, data); break; + case 0xb: message_out_w(port, data); break; + case 0xc: break; // message in register (read only) + case 0xd: pattern_match_w(port, data); break; + case 0xe: pattern_mask_w(port, data); break; + case 0xf: fifo_w(port, data); break; + } + + LOGMASKED(LOG_REG, "reg_w port %d reg %d data 0x%02x\n", port + 1, m_port[port].reg_pointer, data); + + // schedule interrupt check (don't duplicate for fifo) + if (m_port[port].reg_pointer != 0xf) + m_int_check->adjust(attotime::zero); + } + else + m_port[port].reg_pointer = data & 0xf; + + m_port[port].reg_state = !m_port[port].reg_state; +} + +u8 z8038_device::fifo_r(u8 const port) +{ + // check for underflow + if (!m_fifo.empty()) + { + m_port[port].data_buffer = m_fifo.dequeue(); + + fifo_update(); + + LOGMASKED(LOG_FIFO, "fifo_r port %d data 0x%02x\n", port + 1, m_port[port].data_buffer); + } + else + m_port[port].interrupt_status[2] |= (ISR2_UF | ISR2_EIP); + + // schedule interrupt check + m_int_check->adjust(attotime::zero); + + return m_port[port].data_buffer; +} + +void z8038_device::fifo_w(u8 const port, u8 data) +{ + // check for overflow + if (!m_fifo.full()) + { + m_port[port].data_buffer = data; + m_fifo.enqueue(m_port[port].data_buffer); + + fifo_update(); + + LOGMASKED(LOG_FIFO, "fifo_w port %d data 0x%02x\n", port + 1, m_port[port].data_buffer); + } + else + m_port[port].interrupt_status[2] |= (ISR2_OF | ISR2_EIP); + + // schedule interrupt check + m_int_check->adjust(attotime::zero); +} + +u8 z8038_device::control_1_r(u8 const port) +{ + /* + * Bit 5 (Message Register Out Full), if set, indicates that the CPU has + * placed a message in its Message Out register. This bit is reset when the + * receiving CPU reads the message in its Message In register. This bit is + * the other CPU's message IP bit and is a read-only bit. Bit 4 (Message + * Register Interrupt Under Service), if set, indicates that the other CPU + * has received a message in its Message In register. This bit is the + * message IUS (Interrupt Under Service) bit of the other CPU and is a + * read-only bit. + */ + u8 data = m_port[port].control_1; + + if (m_port[!port].interrupt_status[0] & ISR0_MIP) + data |= CR1_MMRF; + + if (m_port[!port].interrupt_status[0] & ISR0_MIUS) + data |= CR1_MMRUS; + + return data; +} + +u8 z8038_device::interrupt_vector_r(u8 const port) +{ + /* + * When MIE is 1, other than during an Interrupt Acknowledge cycle, the + * Interrupt Vector register always reflects the FIO status in these bits, + * regardless of whether or not the Vector Includes Status bit is set. + */ + if (m_port[port].control_0 & CR0_MIE) + return (m_port[port].interrupt_vector & 0xf1) | (m_port[port].int_code << 1); + else + return m_port[port].interrupt_vector; +} + +u8 z8038_device::byte_count_r(u8 const port) +{ + /* + * Bit 6 is reset upon completion of the CPU read of the Byte Count + * register. The ongoing count appears in t he Byte Count register after + * the read. + */ + if (m_port[port].control_1 & CR1_FBCR) + m_port[port].control_1 &= ~CR1_FBCR; + + return m_port[port].byte_count; +} + +u8 z8038_device::control_3_r(u8 const port) +{ + u8 const mask = (port == 0) ? 0xff : 0xf0; + + // return direction relative to controlling port + if (bool(m_control_3 & CR3_P2DIR) != bool(port)) + return (m_control_3 & mask) ^ CR3_DIR; + else + return (m_control_3 & mask); +} + +u8 z8038_device::message_in_r(u8 const port) +{ + /* + * When the Port 2 CPU reads the data from its Message In register, the + * Port 2 IP is cleared. + */ + m_port[port].interrupt_status[0] &= ~ISR0_MIP; + + return m_port[port].message_in; +} + +void z8038_device::control_0_w(u8 const port, u8 data) +{ + if (!(data & CR0_RESET)) + { + if (port == 0) + m_port[port].control_0 = data; + else + m_port[port].control_0 = (m_port[!port].control_0 & CR0_P2M) | (data & ~CR0_P2M); + } + else + port_reset(port); +} + +void z8038_device::control_1_w(u8 const port, u8 data) +{ + m_port[port].control_1 = data & CR1_WMASK; +} + +template void z8038_device::interrupt_status_w(u8 const port, u8 data) +{ + // high interrupt status + switch (data & ISR_HMASK) + { + case 0x20: m_port[port].interrupt_status[Number] &= ~(ISR_HIUS | ISR_HIP); break; + case 0x40: m_port[port].interrupt_status[Number] |= ISR_HIUS; break; + case 0x60: m_port[port].interrupt_status[Number] &= ~ISR_HIUS; break; + case 0x80: m_port[port].interrupt_status[Number] |= ISR_HIP; break; + case 0xa0: m_port[port].interrupt_status[Number] &= ~ISR_HIP; break; + case 0xc0: m_port[port].interrupt_status[Number] |= ISR_HIE; break; + case 0xe0: m_port[port].interrupt_status[Number] &= ~ISR_HIE; break; + } + + // low interrupt status + if (Number != 0) + { + switch (data & ISR_LMASK) + { + case 0x02: m_port[port].interrupt_status[Number] &= ~(ISR_LIUS | ISR_LIP); break; + case 0x04: m_port[port].interrupt_status[Number] |= ISR_LIUS; break; + case 0x06: m_port[port].interrupt_status[Number] &= ~ISR_LIUS; break; + case 0x08: m_port[port].interrupt_status[Number] |= ISR_LIP; break; + case 0x0a: m_port[port].interrupt_status[Number] &= ~ISR_LIP; break; + case 0x0c: m_port[port].interrupt_status[Number] |= ISR_LIE; break; + case 0x0e: m_port[port].interrupt_status[Number] &= ~ISR_LIE; break; + } + } +} + +// instantiate helpers for each interrupt status register +template void z8038_device::interrupt_status_w<0>(u8 const port, u8 data); +template void z8038_device::interrupt_status_w<1>(u8 const port, u8 data); +template void z8038_device::interrupt_status_w<2>(u8 const port, u8 data); +template void z8038_device::interrupt_status_w<3>(u8 const port, u8 data); + +void z8038_device::byte_count_comparison_w(u8 const port, u8 data) +{ + /* + * The largest programmable value is 7Fh (127 decimal). + */ + m_port[port].byte_count_comparison = data & 0x7f; + + // check byte count comparison + if (m_fifo.queue_length() == m_port[port].byte_count_comparison) + m_port[port].interrupt_status[2] |= ISR2_BCCIP; +} + +void z8038_device::control_2_w(u8 const port, u8 data) +{ + if (port == 0) + m_control_2 = data & CR2_WMASK; + else + logerror("cannot write to control register 2 from port 2\n"); +} + +void z8038_device::control_3_w(u8 const port, u8 data) +{ + if (m_port[port].control_0 & CR0_P2M_IO) + { + // update all except unused and input line bits + m_control_3 = data & ~(CR3_UNUSED | CR3_P2IN0); + + // update output lines + m_out_H_cb(m_control_3 & CR3_P2OUT1 ? 1 : 0); + m_out_J_cb(m_control_3 & CR3_P2OUT3 ? 1 : 0); + + // update clear if configured as output + if (!(m_control_3 & CR3_P2CLR)) + { + if (!(m_control_3 & CR3_CLR)) + fifo_clear(); + + m_out_E_cb(m_control_3 & CR3_CLR ? 1 : 0); + } + + // update direction if configured as output + if (!(m_control_3 & CR3_P2DIR)) + m_out_F_cb(m_control_3 & CR3_DIR ? 1 : 0); + + // TODO: resample input lines? + } + else + { + if (port == 0) + { + // flag interrupt pending if in control and changing direction + if (!(data & CR3_P2DIR) && ((data ^ m_control_3) & CR3_DIR)) + m_port[!port].interrupt_status[1] |= ISR1_DDCIP; + + // update clear and direction bits only if in control + u8 const mask = (CR3_P2CLR | CR3_P2DIR | CR3_P2OUT3 | CR3_P2OUT1) + | (data & CR3_P2CLR ? 0 : CR3_CLR) + | (data & CR3_P2DIR ? 0 : CR3_DIR); + + m_control_3 = (m_control_3 & ~mask) | (data & mask); + + // clear fifo + if (!(m_control_3 & (CR3_P2CLR | CR3_CLR))) + fifo_clear(); + } + else + { + // flag interrupt pending if in control and changing direction + if ((data & CR3_P2DIR) && ((data ^ m_control_3) & CR3_DIR)) + m_port[!port].interrupt_status[1] |= ISR1_DDCIP; + + // update clear and direction bits only if in control + u8 const mask = (m_control_3 & (CR3_P2CLR | CR3_P2DIR)) >> 1; + + m_control_3 = (m_control_3 & ~mask) | (data & mask); + + // clear fifo + if ((m_control_3 & CR3_P2CLR) && !(m_control_3 & CR3_CLR)) + fifo_clear(); + } + } +} + +void z8038_device::message_out_w(u8 const port, u8 data) +{ + /* + * When Port 1's CPU writes to the Message Out register which is also Port + * 2's Message In register, Port 2's Message Interrupt Pending bit is set. + */ + m_port[!port].message_in = data; + m_port[!port].interrupt_status[0] |= ISR0_MIP; +} + +WRITE_LINE_MEMBER(z8038_device::in_E) +{ + // check port 2 in i/o mode and pin 35 configured as input + if ((m_port[0].control_0 & CR0_P2M_IO) && (m_control_3 & CR3_P2CLR)) + { + // active low - clear fifo + if (!state) + { + m_control_3 &= ~CR3_CLR; + fifo_clear(); + } + else + m_control_3 |= CR3_CLR; + } +} + +WRITE_LINE_MEMBER(z8038_device::in_F) +{ + // check port 2 in i/o mode and pin 34 configured as input + if ((m_port[0].control_0 & CR0_P2M_IO) && (m_control_3 & CR3_P2DIR)) + { + // check for direction change and flag interrupt + if (bool(state) != bool(m_control_3 & CR3_DIR)) + { + if (state) + m_control_3 |= CR3_DIR; + else + m_control_3 &= ~CR3_DIR; + + // flag interrupt pending + m_port[0].interrupt_status[1] |= ISR1_DDCIP; + + // schedule interrupt check + m_int_check->adjust(attotime::zero); + } + } +} + +WRITE_LINE_MEMBER(z8038_device::in_G) +{ + // check port 2 in i/o mode + if (m_port[0].control_0 & CR0_P2M_IO) + { + if (state) + m_control_3 |= CR3_P2IN0; + else + m_control_3 &= ~CR3_P2IN0; + } +} + +void z8038_device::port_reset(u8 const port) +{ + LOG("port_reset port %d \n", port + 1); + + m_port[port].control_1 = 0; + if (port == 0) + { + m_port[port].control_0 = CR0_RESET; + + m_control_2 = 0; + m_control_3 = 0; + + fifo_clear(); + } + else + { + // port 2 mode is not reset + m_port[port].control_0 = CR0_RESET; + m_port[port].control_0 |= (m_port[!port].control_0 & CR0_P2M); + + /* + * It should be noted that if the Port 2 side is reset when it has + * control of the C̅L̅E̅A̅R̅ bit, the C̅L̅E̅A̅R̅ bit is also reset (0). It should + * be noted that if the Port 2 side is reset when it has control of the + * Data Direction bit, the Data Direction is also reset. + */ + if (m_control_3 & CR3_P2CLR) + { + m_control_3 &= ~CR3_CLR; + fifo_clear(); + } + + if (m_control_3 & CR3_P2DIR) + m_control_3 &= ~CR3_DIR; + } + + m_port[port].pattern_mask = 0; + m_port[port].interrupt_status[0] = 0; + /* + * All bits except D1 and D0 are cleared by reset. Bits D1 and D0 may be a 1 + * or 0 depending on whether a match condition exists or not. + */ + m_port[port].interrupt_status[1] = 0; // opt to ignore "random" pattern matches + m_port[port].interrupt_status[2] = 0; + + /* + * All bits except D0 are cleared by reset. + */ + m_port[port].interrupt_status[3] &= ~ISR3_BE; + + /* + * When Port 1 is reset, Port 2 is also reset. If Port 2 is reset by itself, + * Port 1 is not reset. + */ + if (port == 0) + port_reset(!port); +} + +void z8038_device::fifo_clear() +{ + m_fifo.clear(); + + // FIXME: should clearing the fifo trigger buffer empty interrupts? + m_port[0].interrupt_status[3] |= ISR3_BE; + m_port[0].interrupt_status[3] &= ~ISR3_BF; + m_port[1].interrupt_status[3] |= ISR3_BE; + m_port[1].interrupt_status[3] &= ~ISR3_BF; +} + +void z8038_device::fifo_update() +{ + for (u8 port = 0; port < 2; port++) + { + // update byte count + if (!(m_port[port].control_1 & CR1_FBCR)) + m_port[port].byte_count = m_fifo.queue_length(); + + // pattern match check + if ((m_port[port].data_buffer & ~m_port[port].pattern_mask) == (m_port[port].pattern_match & ~m_port[port].pattern_mask)) + m_port[port].interrupt_status[1] |= (ISR1_PMIP | ISR1_PMF); + else + m_port[port].interrupt_status[1] &= ~ISR1_PMF; + + // byte count comparison check + if (m_fifo.queue_length() == m_port[port].byte_count_comparison) + m_port[port].interrupt_status[2] |= ISR2_BCCIP; + + // buffer full check + // TODO: test full pin (pin 37) + if (m_fifo.full()) + m_port[port].interrupt_status[3] |= (ISR3_BF | ISR3_FIP); + + // buffer empty check + // TODO: test empty pin (pin 37) + if (m_fifo.empty()) + m_port[port].interrupt_status[3] |= (ISR3_BE | ISR3_EIP); + } +} + +TIMER_CALLBACK_MEMBER(z8038_device::int_check) +{ + for (u8 port = 0; port < 2; port++) + { + // check master interrupt enable + if (!(m_port[port].control_0 & CR0_MIE)) + { + set_int_state(port, false); + continue; + } + + // check any interrupts under service + if (std::any_of( + std::begin(m_port[port].interrupt_status), + std::end(m_port[port].interrupt_status), + [](u8 const val) { return bool(val & (ISR_HIUS | ISR_LIUS)); })) + continue; + + // check for enabled and pending interrupts in priority order + m_port[port].int_code = 7; + for (u8 &isr : m_port[port].interrupt_status) + { + // check high interrupt enable and pending + if ((isr & ISR_HIE) && (isr & ISR_HIP)) + { + // set interrupt under service + isr |= ISR_HIUS; + break; + } + m_port[port].int_code--; + + if (m_port[port].int_code != 6) + { + // check low interrupt enable and pending + if ((isr & ISR_LIE) && (isr & ISR_LIP)) + { + // set interrupt under service + isr |= ISR_LIUS; + break; + } + m_port[port].int_code--; + } + } + + if (m_port[port].int_code) + LOGMASKED(LOG_INT, "int_check port %d interrupt code %d detected\n", port + 1, m_port[port].int_code); + + // update interrupt state + set_int_state(port, bool(m_port[port].int_code)); + } +} + +void z8038_device::set_int_state(u8 const port, bool asserted) +{ + if (m_port[port].int_asserted != asserted) + { + LOGMASKED(LOG_INT, "set_int_state port %d interrupt %s\n", + port + 1, asserted ? "asserted" : "deasserted"); + + m_port[port].int_asserted = asserted; + + // line is active low + m_out_int_cb[port](asserted ? 0 : 1); + } +} diff --git a/src/devices/machine/z8038.h b/src/devices/machine/z8038.h new file mode 100644 index 00000000000..d3e1532c40d --- /dev/null +++ b/src/devices/machine/z8038.h @@ -0,0 +1,229 @@ +// license:BSD-3-Clause +// copyright-holders:Patrick Mackinlay + +#ifndef MAME_MACHINE_Z8038_H +#define MAME_MACHINE_Z8038_H + +#pragma once + +class z8038_device : public device_t +{ +public: + z8038_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + // port 1 and 2 I̅N̅T̅ output lines + template auto out_int_cb() { return m_out_int_cb[Port - 1].bind(); } + + // port 2 output lines + auto out_E() { return m_out_E_cb.bind(); } + auto out_F() { return m_out_F_cb.bind(); } + auto out_H() { return m_out_H_cb.bind(); } + auto out_J() { return m_out_J_cb.bind(); } + + // port 2 input lines + DECLARE_WRITE_LINE_MEMBER(in_E); // C̅L̅E̅A̅R̅ + DECLARE_WRITE_LINE_MEMBER(in_F); // Data Direction + DECLARE_WRITE_LINE_MEMBER(in_G); // IN0 + + // indirect register access + template u8 reg_r() { return reg_r(Port - 1); } + template void reg_w(u8 data) { reg_w(Port - 1, data); } + + // direct register access + template void zbus_map(address_map &map); + template u8 zbus_reg_r(offs_t offset) { m_port[Port - 1].reg_state = 1; m_port[Port - 1].reg_pointer = offset & 0xf; return reg_r(Port - 1); } + template void zbus_reg_w(offs_t offset, u8 data) { m_port[Port - 1].reg_state = 1; m_port[Port - 1].reg_pointer = offset & 0xf; reg_w(Port - 1, data); } + + // direct fifo access + template u8 fifo_r() { return fifo_r(Port - 1); } + template void fifo_w(u8 data) { fifo_w(Port - 1, data); } + +protected: + // standard device_interface overrides + virtual void device_start() override; + virtual void device_reset() override; + + // primary device read/write handlers + u8 reg_r(u8 const port); + void reg_w(u8 const port, u8 data); + u8 fifo_r(u8 const port); + void fifo_w(u8 const port, u8 data); + + // register read helpers + u8 control_0_r(u8 const port) { return m_port[port].control_0; } + u8 control_1_r(u8 const port); + template u8 interrupt_status_r(u8 const port) { return m_port[port].interrupt_status[Number]; } + u8 interrupt_vector_r(u8 const port); + u8 byte_count_r(u8 const port); + u8 byte_count_comparison_r(u8 const port) { return m_port[port].byte_count_comparison; } + u8 control_2_r(u8 const port) { return (port == 0) ? m_control_2 : 0; } + u8 control_3_r(u8 const port); + u8 message_out_r(u8 const port) { return m_port[!port].message_in; } + u8 message_in_r(u8 const port); + u8 pattern_match_r(u8 const port) { return m_port[port].pattern_match; } + u8 pattern_mask_r(u8 const port) { return m_port[port].pattern_mask; } + + // register write helpers + void control_0_w(u8 const port, u8 data); + void control_1_w(u8 const port, u8 data); + template void interrupt_status_w(u8 const port, u8 data); + void interrupt_vector_w(u8 const port, u8 data) { m_port[port].interrupt_vector = data; } + void byte_count_comparison_w(u8 const port, u8 data); + void control_2_w(u8 const port, u8 data); + void control_3_w(u8 const port, u8 data); + void message_out_w(u8 const port, u8 data); + void pattern_match_w(u8 const port, u8 data) { m_port[port].pattern_match = data; } + void pattern_mask_w(u8 const port, u8 data) { m_port[port].pattern_mask = data; } + + // other helpers + void port_reset(u8 const port); + void fifo_clear(); + void fifo_update(); + TIMER_CALLBACK_MEMBER(int_check); + void set_int_state(u8 const port, bool asserted); + +private: + enum control_0_mask : u8 + { + CR0_RESET = 0x01, // reset port + CR0_RJA = 0x02, // right-justify address + CR0_P2M = 0x0c, // port 2 mode (read-only from port 2 side) + CR0_VIS = 0x10, // vector includes status + CR0_NV = 0x20, // no vector on interrupt + CR0_DLC = 0x40, // disable lower daisy chain + CR0_MIE = 0x80, // master interrupt enable + }; + enum control_0_p2mode_mask : u8 + { + CR0_P2M_ZBUSCPU = 0x00, // z-bus cpu + CR0_P2M_NZBUSCPU = 0x04, // non z-bus cpu + CR0_P2M_3WHSIO = 0x08, // 3-wire handshake i/o + CR0_P2M_2WHSIO = 0x0c, // 2-wire handshake i/o + + CR0_P2M_IO = 0x08, // i/o mode + }; + enum control_1_mask : u8 + { + CR1_RWE = 0x01, // R̅E̅Q̅U̅E̅S̅T̅ or W̅A̅I̅T̅ enable + CR1_RWS = 0x02, // R̅E̅Q̅U̅E̅S̅T̅ or W̅A̅I̅T̅ select + CR1_SDBC = 0x04, // start dma on byte count + CR1_SDPM = 0x08, // stop dma on pattern match + CR1_MMRUS = 0x10, // message mailbox register under service (read only) + CR1_MMRF = 0x20, // message mailbox register full (read only) + CR1_FBCR = 0x40, // freeze byte count register + + CR1_WMASK = 0x4f, + }; + enum control_2_mask : u8 + { + CR2_P2EN = 0x01, // port 2 side enable + CR2_P2HE = 0x02, // port 2 side handshake enable + + CR2_WMASK = 0x03, + }; + enum control_3_mask : u8 + { + CR3_P2IN0 = 0x01, // port 2 input line 0 + CR3_P2OUT1 = 0x02, // port 2 output line 1 + CR3_UNUSED = 0x04, // not used (mut be programmed 0) + CR3_P2OUT3 = 0x08, // port 2 output line 3 + CR3_DIR = 0x10, // data direction + CR3_P2DIR = 0x20, // port 2 controls direction + CR3_CLR = 0x40, // clear fifo (active low) + CR3_P2CLR = 0x80, // port 2 controls clear + }; + enum interrupt_status_0_mask : u8 + { + ISR0_MIP = 0x20, // message interrupt pending + ISR0_MIE = 0x40, // message interrupt enable + ISR0_MIUS = 0x80, // message interrupt under service + + ISR0_WMASK = 0xe0 + }; + enum interrupt_status_1_mask : u8 + { + ISR1_PMF = 0x01, // pattern match flag + ISR1_PMIP = 0x02, // pattern match interrupt pending + ISR1_PMIE = 0x04, // pattern match interrupt enable + ISR1_PMIUS = 0x08, // pattern match interrupt under service + ISR1_DDCIP = 0x20, // data direction change interrupt pending + ISR1_DDCIE = 0x40, // data direction change interrupt enable + ISR1_DDCIUS = 0x80, // data direction change interrupt under service + }; + enum interrupt_status_2_mask : u8 + { + ISR2_UF = 0x01, // underflow error + ISR2_EIP = 0x02, // error interrupt pending + ISR2_EIE = 0x04, // error interrupt enable + ISR2_EIUS = 0x08, // error interrupt under service + ISR2_OF = 0x10, // overflow error + ISR2_BCCIP = 0x20, // byte count compare interrupt pending + ISR2_BCCIE = 0x40, // byte count compare interrupt enable + ISR2_BCCIUS = 0x80, // byte count compare interrupt under service + }; + enum interrupt_status_3_mask : u8 + { + ISR3_BE = 0x01, // buffer empty + ISR3_EIP = 0x02, // empty interrupt pending + ISR3_EIE = 0x04, // empty interrupt enable + ISR3_EIUS = 0x08, // empty interrupt under service + ISR3_BF = 0x10, // buffer full + ISR3_FIP = 0x20, // full interrupt pending + ISR3_FIE = 0x40, // full interrupt enable + ISR3_FIUS = 0x80, // full interrupt under service + }; + + // generic interrupt status bit names + enum interrupt_status_mask : u8 + { + ISR_LIP = 0x02, // low interrupt pending + ISR_LIE = 0x04, // low interrupt enable + ISR_LIUS = 0x08, // low interrupt under service + ISR_HIP = 0x20, // high interrupt pending + ISR_HIE = 0x40, // high interrupt enable + ISR_HIUS = 0x80, // high interrupt under service + + ISR_LMASK = 0x0e, + ISR_HMASK = 0xe0, + }; + + devcb_write_line m_out_int_cb[2]; + devcb_write_line m_out_E_cb; // pin number 35 + devcb_write_line m_out_F_cb; // pin number 34 + devcb_write_line m_out_H_cb; // pin number 32 + devcb_write_line m_out_J_cb; // pin number 30 + + emu_timer *m_int_check; + + // registers largely or entirely controlled by port 1 + u8 m_control_2; + u8 m_control_3; + + struct port_state + { + // non-register, per-port state + u8 reg_state; + u8 reg_pointer; + u8 int_code; + bool int_asserted; + + // accessible registers + u8 control_0; + u8 control_1; + u8 interrupt_status[4]; + u8 interrupt_vector; + u8 byte_count; + u8 byte_count_comparison; + u8 message_in; + u8 pattern_match; + u8 pattern_mask; + u8 data_buffer; + } + m_port[2]; + + util::fifo m_fifo; +}; + +DECLARE_DEVICE_TYPE(Z8038, z8038_device) + +#endif // MAME_MACHINE_Z8038_H -- cgit v1.2.3