diff options
author | 2024-07-01 22:16:03 +0100 | |
---|---|---|
committer | 2024-07-01 22:18:56 +0100 | |
commit | bf1822976ce7117fa0469c15a519a18d6bdba59f (patch) | |
tree | 26516b347660bf5c2a9a91e8b1c6b89fe03db3b4 | |
parent | 50805594da028fa8295835d4e31de2d1b9dcf385 (diff) |
Systems promoted to working
---------------------------
Micro-Professor 1 Plus [Nigel Barnes]
New working clones
------------------
MT-80Z [anonymous]
New systems marked not working
------------------------------
Robot Training Arm CS-113 [anonymous]
multitech/mpf1: Added expansion and ROM U7 slots.
- Added ROM software list.
multitech/mpf1p: Replaced bad dump of monitor ROM.
- Corrected layout to use 14 seg LED's.
- Added keyboard.
- Added expansion and ROM U3 slots.
- Added ROM software list.
bus/mpf1: Added Micro-Professor 1 expansion boards:
- Multitech EPB-MPF (Eprom Programmer Board)
- Multitech EPB-MPF-IBP (Eprom Programmer Board)
- Multitech IOM-MPF-IP (I/O and Memory Board)
- Multitech PRT-MPF (Printer)
- Multitech PRT-MPF-IP (Printer)
- Multitech SGB-MPF (Sound Generation Board)
- Multitech SSB-MPF (Speech Synthesizer Board)
- Multitech TVA-MPF-IP (Video Board)
- Bardehle VIDEO-MPF-I (Video Board)
-rw-r--r-- | scripts/src/bus.lua | 26 | ||||
-rw-r--r-- | src/devices/bus/mpf1/epb.cpp | 131 | ||||
-rw-r--r-- | src/devices/bus/mpf1/epb.h | 14 | ||||
-rw-r--r-- | src/devices/bus/mpf1/iom.cpp | 145 | ||||
-rw-r--r-- | src/devices/bus/mpf1/iom.h | 13 | ||||
-rw-r--r-- | src/devices/bus/mpf1/prt.cpp | 138 | ||||
-rw-r--r-- | src/devices/bus/mpf1/prt.h | 14 | ||||
-rw-r--r-- | src/devices/bus/mpf1/sgb.cpp | 73 | ||||
-rw-r--r-- | src/devices/bus/mpf1/sgb.h | 13 | ||||
-rw-r--r-- | src/devices/bus/mpf1/slot.cpp | 126 | ||||
-rw-r--r-- | src/devices/bus/mpf1/slot.h | 122 | ||||
-rw-r--r-- | src/devices/bus/mpf1/ssb.cpp | 93 | ||||
-rw-r--r-- | src/devices/bus/mpf1/ssb.h | 13 | ||||
-rw-r--r-- | src/devices/bus/mpf1/tva.cpp | 85 | ||||
-rw-r--r-- | src/devices/bus/mpf1/tva.h | 13 | ||||
-rw-r--r-- | src/devices/bus/mpf1/vid.cpp | 158 | ||||
-rw-r--r-- | src/devices/bus/mpf1/vid.h | 13 | ||||
-rw-r--r-- | src/mame/layout/mpf1p.lay | 114 | ||||
-rw-r--r-- | src/mame/layout/mt80z.lay | 77 | ||||
-rw-r--r-- | src/mame/mame.lst | 10 | ||||
-rw-r--r-- | src/mame/multitech/mpf1.cpp | 391 | ||||
-rw-r--r-- | src/mame/multitech/mpf1.h | 88 | ||||
-rw-r--r-- | src/mame/multitech/mpf1p.cpp | 396 |
23 files changed, 1947 insertions, 319 deletions
diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index 7ef89b621a3..10ea963a65d 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -1902,6 +1902,32 @@ end --------------------------------------------------- -- +--@src/devices/bus/mpf1/slot.h,BUSES["MPF1"] = true +--------------------------------------------------- + +if (BUSES["MPF1"]~=null) then + files { + MAME_DIR .. "src/devices/bus/mpf1/slot.cpp", + MAME_DIR .. "src/devices/bus/mpf1/slot.h", + MAME_DIR .. "src/devices/bus/mpf1/epb.cpp", + MAME_DIR .. "src/devices/bus/mpf1/epb.h", + MAME_DIR .. "src/devices/bus/mpf1/iom.cpp", + MAME_DIR .. "src/devices/bus/mpf1/iom.h", + MAME_DIR .. "src/devices/bus/mpf1/prt.cpp", + MAME_DIR .. "src/devices/bus/mpf1/prt.h", + MAME_DIR .. "src/devices/bus/mpf1/sgb.cpp", + MAME_DIR .. "src/devices/bus/mpf1/sgb.h", + MAME_DIR .. "src/devices/bus/mpf1/ssb.cpp", + MAME_DIR .. "src/devices/bus/mpf1/ssb.h", + MAME_DIR .. "src/devices/bus/mpf1/tva.cpp", + MAME_DIR .. "src/devices/bus/mpf1/tva.h", + MAME_DIR .. "src/devices/bus/mpf1/vid.cpp", + MAME_DIR .. "src/devices/bus/mpf1/vid.h", + } +end + +--------------------------------------------------- +-- --@src/devices/bus/msx/ctrl/ctrl.h,BUSES["MSX_CTRL"] = true --------------------------------------------------- diff --git a/src/devices/bus/mpf1/epb.cpp b/src/devices/bus/mpf1/epb.cpp new file mode 100644 index 00000000000..718f904965d --- /dev/null +++ b/src/devices/bus/mpf1/epb.cpp @@ -0,0 +1,131 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/*************************************************************************** + + Multitech Eprom Programmer Board + + EPB-MPF : + MPF-1B : ADDR 9000 GO + + EPB-MPF-IBP : + MPF-1P : G 9000 + MPF-1B : ADDR 9800 GO + +***************************************************************************/ + +#include "emu.h" +#include "epb.h" +#include "machine/i8255.h" + + +namespace { + +//------------------------------------------------- +// rom_region - device-specific ROM region +//------------------------------------------------- + +ROM_START( mpf_epb ) + ROM_REGION(0x0800, "rom", 0) + ROM_LOAD("epb-ib.u8", 0x0000, 0x0800, CRC(bbd854f5) SHA1(489e597c12a14a1cf9568d18b299e4f4ae656f71)) +ROM_END + +ROM_START( mpf_epb_ibp ) + ROM_REGION(0x1000, "rom", 0) + ROM_LOAD("ebp-ibp.u8", 0x0000, 0x1000, CRC(0156387a) SHA1(296842ee5bac23f41f46534663d4f0bfc04075cf)) +ROM_END + + +//------------------------------------------------- +// mpf_epb_device - constructor +//------------------------------------------------- + +class mpf_epb_device : public device_t, public device_mpf1_exp_interface +{ +public: + static constexpr feature_type unemulated_features() { return feature::ROM; } + + mpf_epb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : mpf_epb_device(mconfig, MPF_EPB, tag, owner, clock) + { + } + +protected: + mpf_epb_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_mpf1_exp_interface(mconfig, *this) + , m_rom(*this, "rom") + , m_ppi(*this, "ppi") + { + } + + virtual void device_add_mconfig(machine_config &config) override + { + I8255(config, m_ppi); + } + + virtual const tiny_rom_entry *device_rom_region() const override + { + return ROM_NAME( mpf_epb ); + } + + virtual void device_start() override + { + m_ram = make_unique_clear<uint8_t[]>(0x1000); + + // register for save states + save_pointer(NAME(m_ram), 0x1000); + } + + virtual void device_reset() override + { + program_space().install_ram(0x8000, 0x8fff, m_ram.get()); + program_space().install_rom(0x9000, 0x97ff, m_rom->base()); + + io_space().install_readwrite_handler(0xcc, 0xcf, emu::rw_delegate(*m_ppi, FUNC(i8255_device::read)), emu::rw_delegate(*m_ppi, FUNC(i8255_device::write))); + } + + required_memory_region m_rom; + required_device<i8255_device> m_ppi; + + std::unique_ptr<uint8_t[]> m_ram; +}; + + +// ======================> mpf_epb_ibp_device + +class mpf_epb_ibp_device : public mpf_epb_device +{ +public: + mpf_epb_ibp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : mpf_epb_device(mconfig, MPF_EPB_IBP, tag, owner, clock) + { + } + +protected: + virtual const tiny_rom_entry *device_rom_region() const override + { + return ROM_NAME( mpf_epb_ibp ); + } + + virtual void device_start() override + { + m_ram = make_unique_clear<uint8_t[]>(0x1800); + + // register for save states + save_pointer(NAME(m_ram), 0x1800); + } + + virtual void device_reset() override + { + program_space().install_rom(0x9000, 0x9fff, m_rom->base()); + program_space().install_ram(0xd800, 0xefff, m_ram.get()); + + io_space().install_readwrite_handler(0x70, 0x7f, emu::rw_delegate(*m_ppi, FUNC(i8255_device::read)), emu::rw_delegate(*m_ppi, FUNC(i8255_device::write))); + } +}; + +} // anonymous namespace + + +DEFINE_DEVICE_TYPE_PRIVATE(MPF_EPB, device_mpf1_exp_interface, mpf_epb_device, "mpf1_epb", "Multitech EPB-MPF (Eprom Programmer Board)") +DEFINE_DEVICE_TYPE_PRIVATE(MPF_EPB_IBP, device_mpf1_exp_interface, mpf_epb_ibp_device, "mpf1_epb_ibp", "Multitech EPB-MPF-IBP (Eprom Programmer Board)") diff --git a/src/devices/bus/mpf1/epb.h b/src/devices/bus/mpf1/epb.h new file mode 100644 index 00000000000..d52d52099e3 --- /dev/null +++ b/src/devices/bus/mpf1/epb.h @@ -0,0 +1,14 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +#ifndef MAME_BUS_MPF1_EPB_H +#define MAME_BUS_MPF1_EPB_H + +#pragma once + +#include "slot.h" + + +DECLARE_DEVICE_TYPE(MPF_EPB, device_mpf1_exp_interface) +DECLARE_DEVICE_TYPE(MPF_EPB_IBP, device_mpf1_exp_interface) + +#endif // MAME_BUS_MPF1_EPB_H diff --git a/src/devices/bus/mpf1/iom.cpp b/src/devices/bus/mpf1/iom.cpp new file mode 100644 index 00000000000..e7b2df0213f --- /dev/null +++ b/src/devices/bus/mpf1/iom.cpp @@ -0,0 +1,145 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/*************************************************************************** + + Multitech I/O and Memory Board + + PIO Application Example : G B000 + CTC Application Example : G B100 + 8251 Application Example : G B300 + +***************************************************************************/ + +#include "emu.h" +#include "iom.h" +#include "machine/i8251.h" +#include "machine/z80ctc.h" +#include "machine/z80pio.h" +#include "bus/rs232/rs232.h" + + +namespace { + +//------------------------------------------------- +// rom_region - device-specific ROM region +//------------------------------------------------- + +ROM_START(mpf_iom_ip) + ROM_REGION(0x1000, "rom", 0) + ROM_LOAD("ip-iom.bin", 0x0000, 0x1000, CRC(bf789c58) SHA1(2c3c26290e041e913d00d7e0d65d53480e27187c)) +ROM_END + + +//------------------------------------------------- +// input_ports - device-specific input ports +//------------------------------------------------- + +static INPUT_PORTS_START(mpf_iom_ip) + PORT_START("DIPSW") + PORT_DIPNAME(0xf, 0xa, "Baud Rate") + PORT_DIPSETTING(0x0, "50") + PORT_DIPSETTING(0x1, "75") + PORT_DIPSETTING(0x2, "110") + PORT_DIPSETTING(0x3, "150") + PORT_DIPSETTING(0x4, "200") + PORT_DIPSETTING(0x5, "300") + PORT_DIPSETTING(0x6, "600") + PORT_DIPSETTING(0x7, "1200") + PORT_DIPSETTING(0x8, "2400") + PORT_DIPSETTING(0x9, "4800") + PORT_DIPSETTING(0xa, "9600") +INPUT_PORTS_END + + +static DEVICE_INPUT_DEFAULTS_START( terminal ) + DEVICE_INPUT_DEFAULTS( "RS232_TXBAUD", 0xff, RS232_BAUD_9600 ) + DEVICE_INPUT_DEFAULTS( "RS232_RXBAUD", 0xff, RS232_BAUD_9600 ) + DEVICE_INPUT_DEFAULTS( "RS232_DATABITS", 0xff, RS232_DATABITS_7 ) + DEVICE_INPUT_DEFAULTS( "RS232_PARITY", 0xff, RS232_PARITY_EVEN ) + DEVICE_INPUT_DEFAULTS( "RS232_STOPBITS", 0xff, RS232_STOPBITS_1 ) +DEVICE_INPUT_DEFAULTS_END + + +//------------------------------------------------- +// mpf_iom_device - constructor +//------------------------------------------------- + +class mpf_iom_device : public device_t, public device_mpf1_exp_interface +{ +public: + mpf_iom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, MPF_IOM_IP, tag, owner, clock) + , device_mpf1_exp_interface(mconfig, *this) + , m_rom(*this, "rom") + , m_ctc(*this, "ctc") + , m_pio(*this, "pio") + , m_usart(*this, "uart") + { + } + +protected: + virtual void device_add_mconfig(machine_config &config) override + { + Z80PIO(config, m_pio, DERIVED_CLOCK(1, 1)); + m_pio->out_int_callback().set(DEVICE_SELF_OWNER, FUNC(mpf1_exp_device::int_w)); + + Z80CTC(config, m_ctc, DERIVED_CLOCK(1, 1)); + m_ctc->set_clk<2>(DERIVED_CLOCK(1, 1)); + m_ctc->zc_callback<2>().set(m_usart, FUNC(i8251_device::write_txc)); + m_ctc->zc_callback<2>().append(m_usart, FUNC(i8251_device::write_rxc)); + m_ctc->intr_callback().set(DEVICE_SELF_OWNER, FUNC(mpf1_exp_device::int_w)); + + I8251(config, m_usart, DERIVED_CLOCK(1, 1)); + m_usart->rxrdy_handler().set(m_ctc, FUNC(z80ctc_device::trg3)); + m_usart->txd_handler().set("rs232", FUNC(rs232_port_device::write_txd)); + m_usart->dtr_handler().set("rs232", FUNC(rs232_port_device::write_dtr)); + m_usart->rts_handler().set("rs232", FUNC(rs232_port_device::write_rts)); + + rs232_port_device &rs232(RS232_PORT(config, "rs232", default_rs232_devices, nullptr)); + rs232.rxd_handler().set(m_usart, FUNC(i8251_device::write_rxd)); + rs232.cts_handler().set(m_usart, FUNC(i8251_device::write_cts)); + rs232.dsr_handler().set(m_usart, FUNC(i8251_device::write_dsr)); + rs232.set_option_device_input_defaults("terminal", DEVICE_INPUT_DEFAULTS_NAME(terminal)); + } + + virtual const tiny_rom_entry *device_rom_region() const override + { + return ROM_NAME(mpf_iom_ip); + } + + virtual ioport_constructor device_input_ports() const override + { + return INPUT_PORTS_NAME(mpf_iom_ip); + } + + virtual void device_start() override + { + m_ram = make_unique_clear<uint8_t[]>(0x1800); + + save_pointer(NAME(m_ram), 0x1800); + } + + virtual void device_reset() override + { + program_space().install_rom(0xb000, 0xbfff, m_rom->base()); + program_space().install_ram(0xd800, 0xefff, m_ram.get()); + + io_space().install_readwrite_handler(0x60, 0x61, emu::rw_delegate(*m_usart, FUNC(i8251_device::read)), emu::rw_delegate(*m_usart, FUNC(i8251_device::write))); + io_space().install_readwrite_handler(0x64, 0x67, emu::rw_delegate(*m_ctc, FUNC(z80ctc_device::read)), emu::rw_delegate(*m_ctc, FUNC(z80ctc_device::write))); + io_space().install_readwrite_handler(0x68, 0x6b, emu::rw_delegate(*m_pio, FUNC(z80pio_device::read)), emu::rw_delegate(*m_pio, FUNC(z80pio_device::write))); + io_space().install_read_port(0x6c, 0x6c, "DIPSW"); + } + +private: + required_memory_region m_rom; + required_device<z80ctc_device> m_ctc; + required_device<z80pio_device> m_pio; + required_device<i8251_device> m_usart; + + std::unique_ptr<uint8_t[]> m_ram; +}; + +} // anonymous namespace + + +DEFINE_DEVICE_TYPE_PRIVATE(MPF_IOM_IP, device_mpf1_exp_interface, mpf_iom_device, "mpf1_iom_ip", "Multitech IOM-MPF-IP (I/O and Memory Board)") diff --git a/src/devices/bus/mpf1/iom.h b/src/devices/bus/mpf1/iom.h new file mode 100644 index 00000000000..02fb9ff496d --- /dev/null +++ b/src/devices/bus/mpf1/iom.h @@ -0,0 +1,13 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +#ifndef MAME_BUS_MPF1_IOM_H +#define MAME_BUS_MPF1_IOM_H + +#pragma once + +#include "slot.h" + + +DECLARE_DEVICE_TYPE(MPF_IOM_IP, device_mpf1_exp_interface) + +#endif // MAME_BUS_MPF1_IOM_H diff --git a/src/devices/bus/mpf1/prt.cpp b/src/devices/bus/mpf1/prt.cpp new file mode 100644 index 00000000000..1962d2dcad9 --- /dev/null +++ b/src/devices/bus/mpf1/prt.cpp @@ -0,0 +1,138 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/*************************************************************************** + + Multitech Printer + + PRT-MPF : + Printer driver utility : ADDR 65AC GO + Z80-Disassembler listing utility : ADDR 6000 GO + Memory dump utility : ADDR 6300 GO + BASIC program listing utility : ADDR 6400 GO + Printer line feed : ADDR 6500 GO + + PRT-MPF-IP : Address Mnemonic Function + 6A00 SHIFT Drive the thermal head shift right + 6A10 PLINEFD Line feed + 6A30 PLINE Drive the paper vertically by two lines + 6A40 MTPPRT Print out the contents of the line buffer + +***************************************************************************/ + +#include "emu.h" +#include "prt.h" +#include "bus/generic/carts.h" +#include "bus/generic/slot.h" + + +namespace { + +//------------------------------------------------- +// rom_region - device-specific ROM region +//------------------------------------------------- + +ROM_START( mpf_prt ) + ROM_REGION(0x1000, "u5", 0) + ROM_LOAD("prt-ib.u5", 0x0000, 0x1000, CRC(730f2fb0) SHA1(f31536ee9dbb9babb9ce16a7490db654ca0b5749)) +ROM_END + +ROM_START( mpf_prt_ip ) + ROM_REGION(0x1000, "u5", 0) + ROM_LOAD("prt-ip_v1.1.u5", 0x0000, 0x1000, CRC(4dd2a4eb) SHA1(6a3e7daa7834d67fd572261ed4a9a62c4594fe3f)) +ROM_END + + +//------------------------------------------------- +// mpf_prt_device - constructor +//------------------------------------------------- + +class mpf_prt_device : public device_t, public device_mpf1_exp_interface +{ +public: + static constexpr feature_type unemulated_features() { return feature::PRINTER; } + + mpf_prt_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : mpf_prt_device(mconfig, MPF_PRT, tag, owner, clock) + { + } + +protected: + mpf_prt_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_mpf1_exp_interface(mconfig, *this) + , m_rom_u5(*this, "u5") + , m_rom_u6(*this, "u6") + { + } + + virtual void device_add_mconfig(machine_config &config) override + { + // TODO: Seikosha MTP201A thermal printer + + GENERIC_SOCKET(config, "u6", generic_linear_slot, nullptr, "bin,rom"); + } + + virtual const tiny_rom_entry *device_rom_region() const override + { + return ROM_NAME( mpf_prt ); + } + + virtual void device_start() override { } + virtual void device_reset() override + { + program_space().install_rom(0x6000, 0x6fff, m_rom_u5->base()); + program_space().install_read_handler(0x7000, 0x7fff, emu::rw_delegate(*m_rom_u6, FUNC(generic_slot_device::read_rom))); + + io_space().install_write_handler(0xca, 0xca, emu::rw_delegate(*this, FUNC(mpf_prt_device::prt_w))); + io_space().install_read_handler(0xcb, 0xcb, emu::rw_delegate(*this, FUNC(mpf_prt_device::prt_r))); + } + +private: + required_memory_region m_rom_u5; + required_device<generic_slot_device> m_rom_u6; + + uint8_t prt_r() + { + uint8_t data = 0x00; + + // bit 0 TGP + // bit 1 HP + + return data; + } + + void prt_w(uint8_t data) + { + // bit 0 TH7 + // bit 1 TH6 + // bit 2 TH5 + // bit 3 TH4 + // bit 4 TH3 + // bit 5 TH2 + // bit 6 TH1 + // bit 7 MOTOR + } +}; + + +class mpf_prt_ip_device : public mpf_prt_device +{ +public: + mpf_prt_ip_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : mpf_prt_device(mconfig, MPF_PRT_IP, tag, owner, clock) + { + } + +protected: + virtual const tiny_rom_entry *device_rom_region() const override + { + return ROM_NAME( mpf_prt_ip ); + } + +}; + +} // anonymous namespace + + +DEFINE_DEVICE_TYPE_PRIVATE(MPF_PRT, device_mpf1_exp_interface, mpf_prt_device, "mpf1_prt", "Multitech PRT-MPF (Printer)") +DEFINE_DEVICE_TYPE_PRIVATE(MPF_PRT_IP, device_mpf1_exp_interface, mpf_prt_ip_device, "mpf1_prt_ip", "Multitech PRT-MPF-IP (Printer)") diff --git a/src/devices/bus/mpf1/prt.h b/src/devices/bus/mpf1/prt.h new file mode 100644 index 00000000000..fb465fe356f --- /dev/null +++ b/src/devices/bus/mpf1/prt.h @@ -0,0 +1,14 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +#ifndef MAME_BUS_MPF1_PRT_H +#define MAME_BUS_MPF1_PRT_H + +#pragma once + +#include "slot.h" + + +DECLARE_DEVICE_TYPE(MPF_PRT, device_mpf1_exp_interface) +DECLARE_DEVICE_TYPE(MPF_PRT_IP, device_mpf1_exp_interface) + +#endif // MAME_BUS_MPF1_PRT_H diff --git a/src/devices/bus/mpf1/sgb.cpp b/src/devices/bus/mpf1/sgb.cpp new file mode 100644 index 00000000000..9866c05844d --- /dev/null +++ b/src/devices/bus/mpf1/sgb.cpp @@ -0,0 +1,73 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/*************************************************************************** + + Multitech Sound Generation Board + + Piano : ADDR C200 GO + +***************************************************************************/ + +#include "emu.h" +#include "sgb.h" +#include "sound/ay8910.h" +#include "speaker.h" + + +namespace { + +//------------------------------------------------- +// rom_region - device-specific ROM region +//------------------------------------------------- + +ROM_START( mpf_sgb ) + ROM_REGION(0x1000, "rom", 0) + ROM_LOAD("sgb-mpf.bin", 0x0000, 0x1000, CRC(2d51d964) SHA1(13f3c7243d691b66ad5f0dcbbc16488c8905a394)) +ROM_END + + +//------------------------------------------------- +// mpf_sgb_device - constructor +//------------------------------------------------- + +class mpf_sgb_device : public device_t, public device_mpf1_exp_interface +{ +public: + mpf_sgb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, MPF_SGB, tag, owner, clock) + , device_mpf1_exp_interface(mconfig, *this) + , m_rom(*this, "rom") + , m_ay(*this, "ay8910") + { + } + +protected: + virtual void device_add_mconfig(machine_config &config) override + { + SPEAKER(config, "mono").front_center(); + AY8910(config, m_ay, DERIVED_CLOCK(1, 1)).add_route(ALL_OUTPUTS, "mono", 1.0); + } + + virtual const tiny_rom_entry *device_rom_region() const override + { + return ROM_NAME( mpf_sgb ); + } + + virtual void device_start() override { } + virtual void device_reset() override + { + program_space().install_rom(0xc000, 0xcfff, m_rom->base()); + + io_space().install_read_handler(0xc1, 0xc1, emu::rw_delegate(*m_ay, FUNC(ay8910_device::data_r))); + io_space().install_write_handler(0xc2, 0xc3, emu::rw_delegate(*m_ay, FUNC(ay8910_device::data_address_w))); + } + +private: + required_memory_region m_rom; + required_device<ay8910_device> m_ay; +}; + +} // anonymous namespace + + +DEFINE_DEVICE_TYPE_PRIVATE(MPF_SGB, device_mpf1_exp_interface, mpf_sgb_device, "mpf1_sgb", "Multitech SGB-MPF (Sound Generation Board)") diff --git a/src/devices/bus/mpf1/sgb.h b/src/devices/bus/mpf1/sgb.h new file mode 100644 index 00000000000..4ae172a62cf --- /dev/null +++ b/src/devices/bus/mpf1/sgb.h @@ -0,0 +1,13 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +#ifndef MAME_BUS_MPF1_SGB_H +#define MAME_BUS_MPF1_SGB_H + +#pragma once + +#include "slot.h" + + +DECLARE_DEVICE_TYPE(MPF_SGB, device_mpf1_exp_interface) + +#endif // MAME_BUS_MPF1_SGB_H diff --git a/src/devices/bus/mpf1/slot.cpp b/src/devices/bus/mpf1/slot.cpp new file mode 100644 index 00000000000..d1470beb862 --- /dev/null +++ b/src/devices/bus/mpf1/slot.cpp @@ -0,0 +1,126 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/*************************************************************************** + + Micro-Professor Expansion Slot + +***************************************************************************/ + +#include "emu.h" +#include "slot.h" + +// supported devices +#include "epb.h" +#include "iom.h" +#include "prt.h" +#include "sgb.h" +#include "ssb.h" +#include "tva.h" +#include "vid.h" + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +DEFINE_DEVICE_TYPE(MPF1_EXP, mpf1_exp_device, "mpf_exp", "Micro-Professor Expansion Slot") + + +//************************************************************************** +// SLOT DEVICE +//************************************************************************** + +//------------------------------------------------- +// mpf1_exp_device - constructor +//------------------------------------------------- + +mpf1_exp_device::mpf1_exp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, MPF1_EXP, tag, owner, clock) + , device_single_card_slot_interface<device_mpf1_exp_interface>(mconfig, *this) + , m_program(*this, finder_base::DUMMY_TAG, -1) + , m_io(*this, finder_base::DUMMY_TAG, -1) + , m_card(nullptr) + , m_int_handler(*this) + , m_nmi_handler(*this) + , m_wait_handler(*this) +{ +} + +//------------------------------------------------- +// device_config_complete - perform any +// operations now that the configuration is +// complete +//------------------------------------------------- + +void mpf1_exp_device::device_config_complete() +{ + // for pass-through connectors, use the parent slot's spaces + if (dynamic_cast<device_mpf1_exp_interface *>(owner()) != nullptr) + { + auto parent = dynamic_cast<mpf1_exp_device *>(owner()->owner()); + if (parent != nullptr) + { + if (m_program.finder_tag() == finder_base::DUMMY_TAG) + m_program.set_tag(parent->m_program, parent->m_program.spacenum()); + if (m_io.finder_tag() == finder_base::DUMMY_TAG) + m_io.set_tag(parent->m_io, parent->m_io.spacenum()); + } + } +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void mpf1_exp_device::device_start() +{ + m_card = get_card_device(); +} + + +//************************************************************************** +// CARD INTERFACE +//************************************************************************** + +//------------------------------------------------- +// device_mpf1_exp_interface - constructor +//------------------------------------------------- + +device_mpf1_exp_interface::device_mpf1_exp_interface(const machine_config &mconfig, device_t &device) + : device_interface(device, "mpf1exp") + , m_slot(dynamic_cast<mpf1_exp_device *>(device.owner())) +{ +} + + +//************************************************************************** +// SLOT INTERFACE +//************************************************************************** + +void mpf1_exp_devices(device_slot_interface &device) +{ + device.option_add("epb", MPF_EPB); + device.option_add("epb_ibp", MPF_EPB_IBP); + device.option_add("prt", MPF_PRT); + device.option_add("sgb", MPF_SGB); + device.option_add("ssb", MPF_SSB); + //device.option_add("vid", MPF_VID); +} + +void mpf1p_exp_devices(device_slot_interface &device) +{ + device.option_add("epb_ibp", MPF_EPB_IBP); + //device.option_add("epb_ip", MPF_EPB_IP); + device.option_add("iom_ip", MPF_IOM_IP); + device.option_add("prt_ip", MPF_PRT_IP); + //device.option_add("sgb_ip", MPF_SGB_IP); + //device.option_add("ssb_ip", MPF_SSB_IP); + device.option_add("tva", MPF_TVA_IP); + device.option_add("vid", MPF_VID); +} + +void mpf1_88_exp_devices(device_slot_interface &device) +{ + //device.option_add("epb_i88", MPF_EPB_I88); + //device.option_add("prt_i88", MPF_PRT_I88); +} diff --git a/src/devices/bus/mpf1/slot.h b/src/devices/bus/mpf1/slot.h new file mode 100644 index 00000000000..7e2c338d361 --- /dev/null +++ b/src/devices/bus/mpf1/slot.h @@ -0,0 +1,122 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/*************************************************************************** + + Micro-Professor Expansion Slot + + 60-pin slot + + +5V 1 2 D7 + +5V 3 4 D6 + GND 5 6 D5 + GND 7 8 D4 + GND 9 10 D3 + GND 11 12 D2 + GND 13 14 D1 + GND 15 16 D0 + GND 17 18 A15 + A14 19 20 A13 + A12 21 22 A11 + A10 23 24 A9 + A8 25 26 A7 + A6 27 28 A5 + A4 29 30 A3 + A2 31 32 A1 + A0 33 34 /RESET + GND 35 36 /RFSH + GND 37 38 /M1 + GND 39 40 /BUSACK + GND 41 42 /WR + GND 43 44 /RD + GND 45 46 /IORQ + GND 47 48 /MREQ + GND 49 50 /HALT + GND 51 52 /NMI + GND 53 54 /INT + GND 55 56 /WAIT + GND 57 58 /BUSREQ + GND 59 60 SYSCLK + +***************************************************************************/ + +#ifndef MAME_BUS_MPF1_SLOT_H +#define MAME_BUS_MPF1_SLOT_H + +#pragma once + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +class device_mpf1_exp_interface; + +class mpf1_exp_device : public device_t, public device_single_card_slot_interface<device_mpf1_exp_interface> +{ + friend class device_mpf1_exp_interface; +public: + // construction/destruction + template <typename T> + mpf1_exp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&opts, const char *dflt) + : mpf1_exp_device(mconfig, tag, owner, clock) + { + option_reset(); + opts(*this); + set_default_option(dflt); + set_fixed(false); + } + + mpf1_exp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + template <typename T> void set_program_space(T &&tag, int spacenum) { m_program.set_tag(std::forward<T>(tag), spacenum); } + template <typename T> void set_io_space(T &&tag, int spacenum) { m_io.set_tag(std::forward<T>(tag), spacenum); } + + // callbacks + auto int_handler() { return m_int_handler.bind(); } + auto nmi_handler() { return m_nmi_handler.bind(); } + auto wait_handler() { return m_wait_handler.bind(); } + + // called from card device + void int_w(int state) { m_int_handler(state); } + void nmi_w(int state) { m_nmi_handler(state); } + void wait_w(int state) { m_wait_handler(state); } + +protected: + // device-level overrides + virtual void device_config_complete() override; + virtual void device_start() override; + + required_address_space m_program; + required_address_space m_io; + + device_mpf1_exp_interface *m_card; + +private: + devcb_write_line m_int_handler; + devcb_write_line m_nmi_handler; + devcb_write_line m_wait_handler; +}; + + +class device_mpf1_exp_interface : public device_interface +{ +public: + // construction/destruction + device_mpf1_exp_interface(const machine_config &mconfig, device_t &device); + +protected: + address_space &program_space() { return *m_slot->m_program; } + address_space &io_space() { return *m_slot->m_io; } + + mpf1_exp_device *m_slot; +}; + +// device type definition +DECLARE_DEVICE_TYPE(MPF1_EXP, mpf1_exp_device) + +// supported devices +void mpf1_exp_devices(device_slot_interface &device); +void mpf1p_exp_devices(device_slot_interface &device); +void mpf1_88_exp_devices(device_slot_interface &device); + +#endif // MAME_BUS_MPF1_SLOT_H diff --git a/src/devices/bus/mpf1/ssb.cpp b/src/devices/bus/mpf1/ssb.cpp new file mode 100644 index 00000000000..1c6a00dd3d7 --- /dev/null +++ b/src/devices/bus/mpf1/ssb.cpp @@ -0,0 +1,93 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/*************************************************************************** + + Multitech Speech Synthesizer Board + + PROG 1 : Time-clock program ADDR 5000 GO + CHECK-CODE : Self-test, speak all vocabulary ADDR 51DC GO + PROG 2 : Speech program utility ADDR 5200 GO + + TODO: improve VSP READY callback to Z80 WAIT, currently VSP FIFO overflows. + +***************************************************************************/ + +#include "emu.h" +#include "ssb.h" +#include "machine/spchrom.h" +#include "sound/tms5220.h" +#include "bus/generic/carts.h" +#include "bus/generic/slot.h" +#include "speaker.h" + + +namespace { + +//------------------------------------------------- +// rom_region - device-specific ROM region +//------------------------------------------------- + +ROM_START( mpf_ssb ) + ROM_REGION(0x1000, "u5", 0) + ROM_LOAD("ssb-mpf.bin", 0x0000, 0x1000, CRC(f926334f) SHA1(35847f8164eed4c0794a8b74e5d7fa972b10eb90)) +ROM_END + + +//------------------------------------------------- +// mpf_ssb_device - constructor +//------------------------------------------------- + +class mpf_ssb_device : public device_t, public device_mpf1_exp_interface +{ +public: + static constexpr feature_type imperfect_features() { return feature::SOUND; } + + mpf_ssb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, MPF_SSB, tag, owner, clock) + , device_mpf1_exp_interface(mconfig, *this) + , m_rom_u5(*this, "u5") + , m_rom_u4(*this, "u4") + , m_rom_u3(*this, "u3") + , m_vsp(*this, "vsp") + { + } + +protected: + virtual void device_add_mconfig(machine_config &config) override + { + SPEAKER(config, "mono").front_center(); + + TMS5200(config, m_vsp, 640000); + m_vsp->ready_cb().set(DEVICE_SELF_OWNER, FUNC(mpf1_exp_device::wait_w)); + m_vsp->add_route(ALL_OUTPUTS, "mono", 0.5); + + GENERIC_SOCKET(config, "u4", generic_linear_slot, nullptr, "bin,rom"); + GENERIC_SOCKET(config, "u3", generic_linear_slot, nullptr, "bin,rom"); + } + + virtual const tiny_rom_entry *device_rom_region() const override + { + return ROM_NAME( mpf_ssb ); + } + + virtual void device_start() override { } + virtual void device_reset() override + { + program_space().install_rom(0x5000, 0x5fff, m_rom_u5->base()); + program_space().install_read_handler(0x6000, 0x6fff, emu::rw_delegate(*m_rom_u4, FUNC(generic_slot_device::read_rom))); + program_space().install_read_handler(0x7000, 0x7fff, emu::rw_delegate(*m_rom_u3, FUNC(generic_slot_device::read_rom))); + + io_space().install_readwrite_handler(0xfe, 0xfe, emu::rw_delegate(*m_vsp, FUNC(tms5200_device::status_r)), emu::rw_delegate(*m_vsp, FUNC(tms5200_device::data_w))); + } + +private: + required_memory_region m_rom_u5; + required_device<generic_slot_device> m_rom_u4; + required_device<generic_slot_device> m_rom_u3; + required_device<tms5200_device> m_vsp; +}; + +} // anonymous namespace + + +DEFINE_DEVICE_TYPE_PRIVATE(MPF_SSB, device_mpf1_exp_interface, mpf_ssb_device, "mpf1_ssb", "Multitech SSB-MPF (Speech Synthesizer Board)") diff --git a/src/devices/bus/mpf1/ssb.h b/src/devices/bus/mpf1/ssb.h new file mode 100644 index 00000000000..00a618f842a --- /dev/null +++ b/src/devices/bus/mpf1/ssb.h @@ -0,0 +1,13 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +#ifndef MAME_BUS_MPF1_SSB_H +#define MAME_BUS_MPF1_SSB_H + +#pragma once + +#include "slot.h" + + +DECLARE_DEVICE_TYPE(MPF_SSB, device_mpf1_exp_interface) + +#endif // MAME_BUS_MPF1_SSB_H diff --git a/src/devices/bus/mpf1/tva.cpp b/src/devices/bus/mpf1/tva.cpp new file mode 100644 index 00000000000..206ff6cea6f --- /dev/null +++ b/src/devices/bus/mpf1/tva.cpp @@ -0,0 +1,85 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/*************************************************************************** + + Multitech TVA-MPF-IP + + TODO: + - no known documentation so emulation not verified. + +***************************************************************************/ + +#include "emu.h" +#include "tva.h" +#include "screen.h" +#include "video/ef9365.h" + + +namespace { + +//------------------------------------------------- +// rom_region - device-specific ROM region +//------------------------------------------------- + +ROM_START( mpf_tva ) + ROM_REGION(0x1000, "rom", 0) + ROM_LOAD("tva.bin", 0x0000, 0x1000, CRC(a9d4f261) SHA1(3a5b0dba5d1e2edda8563b55010c86efd1548d0b)) +ROM_END + + +//------------------------------------------------- +// mpf_tva_ip_device - constructor +//------------------------------------------------- + +class mpf_tva_ip_device : public device_t, public device_mpf1_exp_interface +{ +public: + static constexpr feature_type imperfect_features() { return feature::GRAPHICS; } + + mpf_tva_ip_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, MPF_TVA_IP, tag, owner, clock) + , device_mpf1_exp_interface(mconfig, *this) + , m_rom(*this, "rom") + , m_gdp(*this, "ef9367") + { + } + +protected: + virtual void device_add_mconfig(machine_config &config) override + { + screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); + screen.set_size(512, 312); + screen.set_visarea(0, 512 - 1, 0, 256 - 1); + screen.set_refresh_hz(50); + screen.set_screen_update("ef9367", FUNC(ef9365_device::screen_update)); + PALETTE(config, "palette", palette_device::MONOCHROME); + + EF9365(config, m_gdp, 1750000); // EF9367 + m_gdp->set_screen("screen"); + m_gdp->set_palette_tag("palette"); + m_gdp->set_nb_bitplanes(1); + m_gdp->set_display_mode(ef9365_device::DISPLAY_MODE_512x256); + m_gdp->irq_handler().set(DEVICE_SELF_OWNER, FUNC(mpf1_exp_device::int_w)); + } + + virtual const tiny_rom_entry *device_rom_region() const override + { + return ROM_NAME( mpf_tva ); + } + + virtual void device_start() override { } + virtual void device_reset() override + { + program_space().install_rom(0xa000, 0xafff, m_rom->base()); + program_space().install_readwrite_handler(0xafe0, 0xafef, emu::rw_delegate(*m_gdp, FUNC(ef9365_device::data_r)), emu::rw_delegate(*m_gdp, FUNC(ef9365_device::data_w))); + } + +private: + required_memory_region m_rom; + required_device<ef9365_device> m_gdp; +}; + +} // anonymous namespace + + +DEFINE_DEVICE_TYPE_PRIVATE(MPF_TVA_IP, device_mpf1_exp_interface, mpf_tva_ip_device, "mpf1_tva_ip", "Multitech TVA-MPF-IP (Video Board)") diff --git a/src/devices/bus/mpf1/tva.h b/src/devices/bus/mpf1/tva.h new file mode 100644 index 00000000000..9810d876923 --- /dev/null +++ b/src/devices/bus/mpf1/tva.h @@ -0,0 +1,13 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +#ifndef MAME_BUS_MPF1_TVA_H +#define MAME_BUS_MPF1_TVA_H + +#pragma once + +#include "slot.h" + + +DECLARE_DEVICE_TYPE(MPF_TVA_IP, device_mpf1_exp_interface) + +#endif // MAME_BUS_MPF1_TVA_H diff --git a/src/devices/bus/mpf1/vid.cpp b/src/devices/bus/mpf1/vid.cpp new file mode 100644 index 00000000000..4ef0634a51c --- /dev/null +++ b/src/devices/bus/mpf1/vid.cpp @@ -0,0 +1,158 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/*************************************************************************** + + Bardehle Electronics VIDEO-MPF-I + +***************************************************************************/ + +#include "emu.h" +#include "vid.h" +#include "video/mc6845.h" +#include "emupal.h" +#include "screen.h" + + +namespace { + +//------------------------------------------------- +// rom_region - device-specific ROM region +//------------------------------------------------- + +ROM_START( mpf_vid ) + ROM_REGION(0x0800, "rom", 0) + ROM_SYSTEM_BIOS(0, "20", "2.0") + ROMX_LOAD("vidmon_v20.bin", 0x0000, 0x0800, CRC(3a2293a0) SHA1(281092d82a272383b584b31064421296add20c46), ROM_BIOS(0)) + + ROM_REGION(0x0800, "chargen", 0) + ROM_LOAD("vidchar.bin", 0x0000, 0x0800, CRC(d56211f9) SHA1(9cf717de353b86c38f94b805d31a16d8079896af)) +ROM_END + + +//------------------------------------------------- +// gfx_layout mpf_vid_charlayout +//------------------------------------------------- + +static const gfx_layout mpf_vid_charlayout = +{ + 8, 12, /* 8 x 12 characters */ + 128, /* 128 characters */ + 1, /* 1 bits per pixel */ + { 0 }, /* no bitplanes */ + /* x offsets */ + { 0, 1, 2, 3, 4, 5, 6, 7 }, + /* y offsets */ + { 0 * 8, 1 * 8, 2 * 8, 3 * 8, 4 * 8, 5 * 8, 6 * 8, 7 * 8, 8 * 8, 9 * 8, 10 * 8, 11 * 8 }, + 8 * 16 /* every char takes 16 bytes */ +}; + +//------------------------------------------------- +// GFXDECODE( gfx_mpf_vid ) +//------------------------------------------------- + +static GFXDECODE_START(gfx_mpf_vid) + GFXDECODE_ENTRY("chargen", 0, mpf_vid_charlayout, 0, 1) +GFXDECODE_END + + +//------------------------------------------------- +// mpf_vid_device - constructor +//------------------------------------------------- + +class mpf_vid_device : public device_t, public device_mpf1_exp_interface +{ +public: + static constexpr feature_type imperfect_features() { return feature::GRAPHICS; } + + mpf_vid_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, MPF_VID, tag, owner, clock) + , device_mpf1_exp_interface(mconfig, *this) + , m_rom(*this, "rom") + , m_chargen(*this, "chargen") + , m_crtc(*this, "mc6845") + , m_palette(*this, "palette") + { + } + +protected: + virtual void device_add_mconfig(machine_config &config) override + { + screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); + screen.set_raw(8_MHz_XTAL, 512, 0, 320, 326, 0, 240); + screen.set_screen_update("mc6845", FUNC(mc6845_device::screen_update)); + + GFXDECODE(config, "gfxdecode", m_palette, gfx_mpf_vid); + PALETTE(config, m_palette, palette_device::MONOCHROME); + + MC6845(config, m_crtc, 8_MHz_XTAL / 8); // UM6845 + m_crtc->set_screen("screen"); + m_crtc->set_show_border_area(false); + m_crtc->set_char_width(8); + m_crtc->set_update_row_callback(FUNC(mpf_vid_device::crtc_update_row)); + } + + virtual const tiny_rom_entry *device_rom_region() const override + { + return ROM_NAME( mpf_vid ); + } + + virtual void device_start() override + { + m_videoram = make_unique_clear<uint8_t[]>(0x0800); + + save_pointer(NAME(m_videoram), 0x0800); + } + + virtual void device_reset() override + { + program_space().install_ram(0x4000, 0x47ff, 0x800, m_videoram.get()); + program_space().install_rom(0xa000, 0xa7ff, m_rom->base()); + + io_space().nop_read(0xf0, 0xf0); // TODO: UM6845 Status Register (b7 must be high) + io_space().install_write_handler(0xf0, 0xf0, emu::rw_delegate(*m_crtc, FUNC(mc6845_device::address_w))); + io_space().install_readwrite_handler(0xf1, 0xf1, emu::rw_delegate(*m_crtc, FUNC(mc6845_device::register_r)), emu::rw_delegate(*m_crtc, FUNC(mc6845_device::register_w))); + } + +private: + required_memory_region m_rom; + required_memory_region m_chargen; + required_device<mc6845_device> m_crtc; + required_device<palette_device> m_palette; + + MC6845_UPDATE_ROW(crtc_update_row); + + std::unique_ptr<uint8_t[]> m_videoram; +}; + + +//************************************************************************** +// IMPLEMENTATION +//************************************************************************** + +MC6845_UPDATE_ROW(mpf_vid_device::crtc_update_row) +{ + uint32_t *p = &bitmap.pix(y); + + for (int column = 0; column < x_count; column++) + { + uint8_t code = m_videoram[(ma + column) & 0x7ff]; + uint16_t addr = (code << 4) | (ra & 0x0f); + uint8_t data = m_chargen->base()[addr & 0x7ff]; + + if (column == cursor_x) + { + data = 0xff; + } + + for (int bit = 0; bit < 8; bit++) + { + *p++ = m_palette->pen(BIT(code, 7) ? !BIT(data, 7) : BIT(data, 7)); + data <<= 1; + } + } +} + +} // anonymous namespace + + +DEFINE_DEVICE_TYPE_PRIVATE(MPF_VID, device_mpf1_exp_interface, mpf_vid_device, "mpf1_vid", "Bardehle VIDEO-MPF-I (Video Board)") diff --git a/src/devices/bus/mpf1/vid.h b/src/devices/bus/mpf1/vid.h new file mode 100644 index 00000000000..83573004514 --- /dev/null +++ b/src/devices/bus/mpf1/vid.h @@ -0,0 +1,13 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +#ifndef MAME_BUS_MPF1_VID_H +#define MAME_BUS_MPF1_VID_H + +#pragma once + +#include "slot.h" + + +DECLARE_DEVICE_TYPE(MPF_VID, device_mpf1_exp_interface) + +#endif // MAME_BUS_MPF1_VID_H diff --git a/src/mame/layout/mpf1p.lay b/src/mame/layout/mpf1p.lay index fb787457be6..7f9608383eb 100644 --- a/src/mame/layout/mpf1p.lay +++ b/src/mame/layout/mpf1p.lay @@ -16,9 +16,9 @@ license:CC0-1.0 </element> <element name="digit" defstate="0"> - <led16seg> - <color red="0.0" green="1.0" blue="1.0" /> - </led16seg> + <led14segsc> + <color red="0.0" green="1.0" blue="1.0" /> + </led14segsc> </element> <element name="dot" defstate="0"> @@ -41,59 +41,59 @@ license:CC0-1.0 <element name="digit1" ref="digit"> <bounds x="20" y="0" width="20" height="30" /> </element> - <element name="digit2" ref="digit"> - <bounds x="40" y="0" width="20" height="30" /> - </element> - <element name="digit3" ref="digit"> - <bounds x="60" y="0" width="20" height="30" /> - </element> - <element name="digit4" ref="digit"> - <bounds x="80" y="0" width="20" height="30" /> - </element> - <element name="digit5" ref="digit"> - <bounds x="100" y="0" width="20" height="30" /> - </element> - <element name="digit6" ref="digit"> - <bounds x="120" y="0" width="20" height="30" /> - </element> - <element name="digit7" ref="digit"> - <bounds x="140" y="0" width="20" height="30" /> - </element> - <element name="digit8" ref="digit"> - <bounds x="160" y="0" width="20" height="30" /> - </element> - <element name="digit9" ref="digit"> - <bounds x="180" y="0" width="20" height="30" /> - </element> - <element name="digit10" ref="digit"> - <bounds x="200" y="0" width="20" height="30" /> - </element> - <element name="digit11" ref="digit"> - <bounds x="220" y="0" width="20" height="30" /> - </element> - <element name="digit12" ref="digit"> - <bounds x="240" y="0" width="20" height="30" /> - </element> - <element name="digit13" ref="digit"> - <bounds x="260" y="0" width="20" height="30" /> - </element> - <element name="digit14" ref="digit"> - <bounds x="280" y="0" width="20" height="30" /> - </element> - <element name="digit15" ref="digit"> - <bounds x="300" y="0" width="20" height="30" /> - </element> - <element name="digit16" ref="digit"> - <bounds x="320" y="0" width="20" height="30" /> - </element> - <element name="digit17" ref="digit"> - <bounds x="340" y="0" width="20" height="30" /> - </element> - <element name="digit18" ref="digit"> - <bounds x="360" y="0" width="20" height="30" /> - </element> - <element name="digit19" ref="digit"> - <bounds x="380" y="0" width="20" height="30" /> - </element> + <element name="digit2" ref="digit"> + <bounds x="40" y="0" width="20" height="30" /> + </element> + <element name="digit3" ref="digit"> + <bounds x="60" y="0" width="20" height="30" /> + </element> + <element name="digit4" ref="digit"> + <bounds x="80" y="0" width="20" height="30" /> + </element> + <element name="digit5" ref="digit"> + <bounds x="100" y="0" width="20" height="30" /> + </element> + <element name="digit6" ref="digit"> + <bounds x="120" y="0" width="20" height="30" /> + </element> + <element name="digit7" ref="digit"> + <bounds x="140" y="0" width="20" height="30" /> + </element> + <element name="digit8" ref="digit"> + <bounds x="160" y="0" width="20" height="30" /> + </element> + <element name="digit9" ref="digit"> + <bounds x="180" y="0" width="20" height="30" /> + </element> + <element name="digit10" ref="digit"> + <bounds x="200" y="0" width="20" height="30" /> + </element> + <element name="digit11" ref="digit"> + <bounds x="220" y="0" width="20" height="30" /> + </element> + <element name="digit12" ref="digit"> + <bounds x="240" y="0" width="20" height="30" /> + </element> + <element name="digit13" ref="digit"> + <bounds x="260" y="0" width="20" height="30" /> + </element> + <element name="digit14" ref="digit"> + <bounds x="280" y="0" width="20" height="30" /> + </element> + <element name="digit15" ref="digit"> + <bounds x="300" y="0" width="20" height="30" /> + </element> + <element name="digit16" ref="digit"> + <bounds x="320" y="0" width="20" height="30" /> + </element> + <element name="digit17" ref="digit"> + <bounds x="340" y="0" width="20" height="30" /> + </element> + <element name="digit18" ref="digit"> + <bounds x="360" y="0" width="20" height="30" /> + </element> + <element name="digit19" ref="digit"> + <bounds x="380" y="0" width="20" height="30" /> + </element> </view> </mamelayout> diff --git a/src/mame/layout/mt80z.lay b/src/mame/layout/mt80z.lay new file mode 100644 index 00000000000..8e856d41ffc --- /dev/null +++ b/src/mame/layout/mt80z.lay @@ -0,0 +1,77 @@ +<?xml version="1.0"?> +<!-- +license:CC0-1.0 +--> +<mamelayout version="2"> + <element name="ledred" defstate="0"> + <disk state="1"> + <color red="1.0" green="0.0" blue="0.0" /> + </disk> + </element> + + <element name="ledgreen" defstate="0"> + <disk state="1"> + <color red="0.0" green="1.0" blue="0.0" /> + </disk> + </element> + + <element name="digit" defstate="0"> + <led7seg> + <color red="0.75" green="0.0" blue="0.0" /> + </led7seg> + </element> + + <element name="dot" defstate="0"> + <disk state="1"> + <color red="0.75" green="0.0" blue="0.0" /> + </disk> + </element> + + <view name="Default Layout"> + <element name="led0" ref="ledgreen"> + <bounds x="277" y="375" width="15" height="15" /> + </element> + <element name="led1" ref="ledred"> + <bounds x="277" y="394" width="15" height="15" /> + </element> + + <element name="digit0" ref="digit"> + <bounds x="19" y="377" width="28" height="38" /> + </element> + <element name="digit1" ref="digit"> + <bounds x="58" y="377" width="28" height="38" /> + </element> + <element name="digit2" ref="digit"> + <bounds x="96" y="377" width="28" height="38" /> + </element> + <element name="digit3" ref="digit"> + <bounds x="134" y="377" width="28" height="38" /> + </element> + <element name="digit4" ref="digit"> + <bounds x="185" y="377" width="28" height="38" /> + </element> + <element name="digit5" ref="digit"> + <bounds x="223" y="377" width="28" height="38" /> + </element> + + <element name="led2" ref="dot"> + <bounds x="43" y="409" width="4" height="5" /> + </element> + <element name="led3" ref="dot"> + <bounds x="82" y="409" width="4" height="5" /> + </element> + <element name="led4" ref="dot"> + <bounds x="120" y="409" width="4" height="5" /> + </element> + <element name="led5" ref="dot"> + <bounds x="158" y="409" width="4" height="5" /> + </element> + <element name="led6" ref="dot"> + <bounds x="209" y="409" width="4" height="5" /> + </element> + <element name="led7" ref="dot"> + <bounds x="247" y="409" width="4" height="5" /> + </element> + + </view> +</mamelayout> diff --git a/src/mame/mame.lst b/src/mame/mame.lst index 1d433262fc3..cb94b0dd175 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -32686,9 +32686,13 @@ mkit09 // mkit09a // @source:multitech/mpf1.cpp -mpf1 // 1979 Multitech Micro Professor 1 -mpf1b // 1979 Multitech Micro Professor 1B -mpf1p // +cs113 // 198? Sciento Robot Arm +mpf1 // 1981 Multitech Micro-Professor 1 +mpf1b // 1982 Multitech Micro-Professor 1B +mt80z // 1982 MT-80Z + +@source:multitech/mpf1p.cpp +mpf1p // 1983 Multitech Micro-Professor 1P @source:multitech/mpf1_88.cpp mpf1_88 // 1985 Multitech Micro-Professor I/88 diff --git a/src/mame/multitech/mpf1.cpp b/src/mame/multitech/mpf1.cpp index 4c689a84eab..cd72bf8ff2f 100644 --- a/src/mame/multitech/mpf1.cpp +++ b/src/mame/multitech/mpf1.cpp @@ -35,26 +35,93 @@ Now press up-arrow to confirm the data has been entered. TODO: - - - remove halt callback - crt board - - speech board - - printers - clickable artwork - - video board (has 6845) - - mpf1p has 49-key keyboard - computer can't keep up with paste - paste only set up for mpf1 */ #include "emu.h" -#include "mpf1.h" +#include "cpu/z80/z80.h" +#include "machine/i8255.h" +#include "machine/timer.h" +#include "machine/z80ctc.h" +#include "machine/z80daisy.h" +#include "machine/z80pio.h" +#include "sound/spkrdev.h" + +#include "bus/generic/carts.h" +#include "bus/generic/slot.h" +#include "bus/mpf1/slot.h" +#include "imagedev/cassette.h" + +#include "softlist_dev.h" #include "speaker.h" #include "mpf1.lh" #include "mpf1b.lh" -#include "mpf1p.lh" +#include "mt80z.lh" + + +namespace { + +class mpf1_state : public driver_device +{ +public: + mpf1_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag) + , m_maincpu(*this, "maincpu") + , m_speaker(*this, "speaker") + , m_cassette(*this, "cassette") + , m_rom_region(*this, "maincpu") + , m_rom_u7(*this, "rom_u7") + , m_pc(*this, "PC%u", 0U) + , m_special(*this, "SPECIAL") + , m_digits(*this, "digit%u", 0U) + , m_leds(*this, "led%u", 0U) + { } + + void mpf1(machine_config &config); + void mpf1b(machine_config &config); + void mt80z(machine_config &config); + + DECLARE_INPUT_CHANGED_MEMBER( trigger_special ); + +protected: + virtual void machine_start() override; + virtual void machine_reset() override; + +private: + required_device<z80_device> m_maincpu; + required_device<speaker_sound_device> m_speaker; + required_device<cassette_image_device> m_cassette; + required_region_ptr<uint8_t> m_rom_region; + required_device<generic_slot_device> m_rom_u7; + required_ioport_array<6> m_pc; + required_ioport m_special; + output_finder<6> m_digits; + output_finder<2> m_leds; + + void mpf1_io_map(address_map &map); + void mpf1_map(address_map &map); + void mpf1_step(address_map &map); + + uint8_t rom_r(offs_t offset); + uint8_t step_r(offs_t offset); + uint8_t ppi_pa_r(); + void ppi_pb_w(uint8_t data); + void ppi_pc_w(uint8_t data); + + int m_break = 0; + int m_m1 = 0; + + uint8_t m_lednum = 0; + + emu_timer *m_led_refresh_timer = nullptr; + + TIMER_CALLBACK_MEMBER(led_refresh); +}; /* Address Maps */ @@ -63,6 +130,7 @@ void mpf1_state::mpf1_map(address_map &map) map.unmap_value_high(); map(0x0000, 0x0fff).rom(); map(0x1800, 0x1fff).ram(); + map(0x2000, 0x2fff).r(FUNC(mpf1_state::rom_r)); } void mpf1_state::mpf1_step(address_map &map) @@ -70,87 +138,50 @@ void mpf1_state::mpf1_step(address_map &map) map(0x0000, 0xffff).r(FUNC(mpf1_state::step_r)); } -void mpf1_state::mpf1b_map(address_map &map) -{ - map.unmap_value_high(); - map(0x0000, 0x0fff).rom(); - map(0x1800, 0x1fff).ram(); - map(0x2000, 0x2fff).rom(); - map(0x5000, 0x6fff).rom(); -} - -void mpf1_state::mpf1p_map(address_map &map) -{ - map(0x0000, 0x1fff).rom(); - map(0x6000, 0x6fff).rom(); - map(0xf000, 0xffff).ram(); -} - void mpf1_state::mpf1_io_map(address_map &map) { map.unmap_value_high(); map.global_mask(0xff); - map(0x00, 0x03).mirror(0x3c).rw(I8255A_TAG, FUNC(i8255_device::read), FUNC(i8255_device::write)); - map(0x40, 0x43).mirror(0x3c).rw(m_ctc, FUNC(z80ctc_device::read), FUNC(z80ctc_device::write)); - map(0x80, 0x83).mirror(0x3c).rw(Z80PIO_TAG, FUNC(z80pio_device::read), FUNC(z80pio_device::write)); + map(0x00, 0x03).mirror(0x3c).rw("ppi", FUNC(i8255_device::read), FUNC(i8255_device::write)); + map(0x40, 0x43).mirror(0x3c).rw("ctc", FUNC(z80ctc_device::read), FUNC(z80ctc_device::write)); + map(0x80, 0x83).mirror(0x3c).rw("pio", FUNC(z80pio_device::read), FUNC(z80pio_device::write)); } -void mpf1_state::mpf1b_io_map(address_map &map) +uint8_t mpf1_state::rom_r(offs_t offset) { - map.unmap_value_high(); - map.global_mask(0xff); - map(0x00, 0x03).mirror(0x3c).rw(I8255A_TAG, FUNC(i8255_device::read), FUNC(i8255_device::write)); - map(0x40, 0x43).mirror(0x3c).rw(m_ctc, FUNC(z80ctc_device::read), FUNC(z80ctc_device::write)); - map(0x80, 0x83).mirror(0x3c).rw(Z80PIO_TAG, FUNC(z80pio_device::read), FUNC(z80pio_device::write)); - map(0xfe, 0xfe).mirror(0x01).rw(TMS5220_TAG, FUNC(tms5220_device::status_r), FUNC(tms5220_device::data_w)); -} - -void mpf1_state::mpf1p_io_map(address_map &map) -{ - map.unmap_value_high(); - map.global_mask(0xff); - map(0x00, 0x03).mirror(0x3c).rw(I8255A_TAG, FUNC(i8255_device::read), FUNC(i8255_device::write)); - map(0x40, 0x43).mirror(0x3c).rw(m_ctc, FUNC(z80ctc_device::read), FUNC(z80ctc_device::write)); - map(0x80, 0x83).mirror(0x3c).rw(Z80PIO_TAG, FUNC(z80pio_device::read), FUNC(z80pio_device::write)); + if (m_rom_u7->exists()) + return m_rom_u7->read_rom(offset & 0x1fff); + else + return m_rom_region[offset + 0x2000]; } /* Input Ports */ -INPUT_CHANGED_MEMBER( mpf1_state::trigger_nmi ) -{ - m_maincpu->set_input_line(INPUT_LINE_NMI, newval ? CLEAR_LINE : ASSERT_LINE); -} - -INPUT_CHANGED_MEMBER( mpf1_state::trigger_irq ) -{ - m_maincpu->set_input_line(INPUT_LINE_IRQ0, newval ? CLEAR_LINE : ASSERT_LINE); -} - -INPUT_CHANGED_MEMBER( mpf1_state::trigger_res ) +INPUT_CHANGED_MEMBER( mpf1_state::trigger_special ) { - m_maincpu->set_input_line(INPUT_LINE_RESET, newval ? CLEAR_LINE : ASSERT_LINE); + m_maincpu->set_input_line(param, newval ? CLEAR_LINE : ASSERT_LINE); } static INPUT_PORTS_START( mpf1 ) PORT_START("PC0") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("3 HL") PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("7 HL'") PORT_CODE(KEYCODE_7) PORT_CHAR('7') - PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("B I*IF") PORT_CODE(KEYCODE_B) PORT_CHAR('B') - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F *PNC'") PORT_CODE(KEYCODE_F) PORT_CHAR('F') + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("B I.IF") PORT_CODE(KEYCODE_B) PORT_CHAR('B') + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F .PNC'") PORT_CODE(KEYCODE_F) PORT_CHAR('F') PORT_BIT( 0xf0, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_START("PC1") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("2 DE") PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("6 DE'") PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("A SP") PORT_CODE(KEYCODE_A) PORT_CHAR('A') - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("E SZ*H'") PORT_CODE(KEYCODE_E) PORT_CHAR('E') + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("E SZ.H'") PORT_CODE(KEYCODE_E) PORT_CHAR('E') PORT_BIT( 0xf0, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_START("PC2") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("1 BC") PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("5 BC'") PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("9 IY") PORT_CODE(KEYCODE_9) PORT_CHAR('9') - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("D *PNC") PORT_CODE(KEYCODE_D) PORT_CHAR('D') + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("D .PNC") PORT_CODE(KEYCODE_D) PORT_CHAR('D') PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("STEP") PORT_CODE(KEYCODE_F1) PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("TAPE RD") PORT_CODE(KEYCODE_F5) PORT_BIT( 0xc0, IP_ACTIVE_LOW, IPT_UNUSED ) @@ -159,7 +190,7 @@ static INPUT_PORTS_START( mpf1 ) PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("0 AF") PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("4 AF'") PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("8 IX") PORT_CODE(KEYCODE_8) PORT_CHAR('8') - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("C SZ*H") PORT_CODE(KEYCODE_C) PORT_CHAR('C') + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("C SZ.H") PORT_CODE(KEYCODE_C) PORT_CHAR('C') PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("GO") PORT_CODE(KEYCODE_X) PORT_CHAR('X') PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("TAPE WR") PORT_CODE(KEYCODE_F6) PORT_BIT( 0xc0, IP_ACTIVE_LOW, IPT_UNUSED ) @@ -184,9 +215,9 @@ static INPUT_PORTS_START( mpf1 ) PORT_START("SPECIAL") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("USER KEY") PORT_CODE(KEYCODE_U) - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("MONI") PORT_CODE(KEYCODE_M) PORT_CHANGED_MEMBER(DEVICE_SELF, mpf1_state, trigger_nmi, 0) - PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("INTR") PORT_CODE(KEYCODE_I) PORT_CHANGED_MEMBER(DEVICE_SELF, mpf1_state, trigger_irq, 0) - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("RESET") PORT_CODE(KEYCODE_F3) PORT_CHANGED_MEMBER(DEVICE_SELF, mpf1_state, trigger_res, 0) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("MONI") PORT_CODE(KEYCODE_M) PORT_CHANGED_MEMBER(DEVICE_SELF, mpf1_state, trigger_special, INPUT_LINE_NMI) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("INTR") PORT_CODE(KEYCODE_I) PORT_CHANGED_MEMBER(DEVICE_SELF, mpf1_state, trigger_special, INPUT_LINE_IRQ0) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("RESET") PORT_CODE(KEYCODE_F3) PORT_CHANGED_MEMBER(DEVICE_SELF, mpf1_state, trigger_special, INPUT_LINE_RESET) INPUT_PORTS_END static INPUT_PORTS_START( mpf1b ) @@ -223,30 +254,89 @@ static INPUT_PORTS_START( mpf1b ) PORT_BIT( 0xc0, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_START("PC4") - PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("IF/\xE2\x88\xA7") PORT_CODE(KEYCODE_PGUP) - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("TO/\xE2\x86\x93") PORT_CODE(KEYCODE_T) PORT_CODE(KEYCODE_DOWN) - PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("THEN/\xE2\x88\xA8") PORT_CODE(KEYCODE_PGDN) + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"IF/\u2227") PORT_CODE(KEYCODE_PGUP) // U+2227 = ∧ + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"TO/\u21e9") PORT_CODE(KEYCODE_T) PORT_CODE(KEYCODE_DOWN) // U+21E9 = ⇩ + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"THEN/\u2228") PORT_CODE(KEYCODE_PGDN) // U+2228 = ∨ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("GOTO") PORT_CODE(KEYCODE_G) - PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("RET/\xE2\x89\x81") PORT_CODE(KEYCODE_R) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("RET/~") PORT_CODE(KEYCODE_R) PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("GOSUB") PORT_CODE(KEYCODE_O) PORT_BIT( 0xc0, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_START("PC5") - PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("FOR/\xE2\x86\x91") PORT_CODE(KEYCODE_H) PORT_CODE(KEYCODE_UP) + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"FOR/\u21e7") PORT_CODE(KEYCODE_H) PORT_CODE(KEYCODE_UP) // U+21E7 = ⇧ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("LIST") PORT_CODE(KEYCODE_L) PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("NEW") PORT_CODE(KEYCODE_N) PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("ENTER") PORT_CODE(KEYCODE_ENTER) - PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("CLR/\xE2\x86\x92") PORT_CODE(KEYCODE_INSERT) PORT_CODE(KEYCODE_RIGHT) - PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("DEL/\xE2\x86\x90") PORT_CODE(KEYCODE_DEL) PORT_CODE(KEYCODE_LEFT) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"CLR/\u21e8") PORT_CODE(KEYCODE_INSERT) PORT_CODE(KEYCODE_RIGHT) // U+21E8 = ⇨ + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"DEL/\u21e6") PORT_CODE(KEYCODE_DEL) PORT_CODE(KEYCODE_LEFT) // U+21E6 = ⇦ PORT_BIT( 0xc0, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_START("SPECIAL") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("SHIFT") PORT_CODE(KEYCODE_LSHIFT) - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("MONI") PORT_CODE(KEYCODE_M) PORT_CHANGED_MEMBER(DEVICE_SELF, mpf1_state, trigger_nmi, 0) - PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("INTR") PORT_CODE(KEYCODE_I) PORT_CHANGED_MEMBER(DEVICE_SELF, mpf1_state, trigger_irq, 0) - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("RESET") PORT_CODE(KEYCODE_F3) PORT_CHANGED_MEMBER(DEVICE_SELF, mpf1_state, trigger_res, 0) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("MONI") PORT_CODE(KEYCODE_M) PORT_CHANGED_MEMBER(DEVICE_SELF, mpf1_state, trigger_special, INPUT_LINE_NMI) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("INTR") PORT_CODE(KEYCODE_I) PORT_CHANGED_MEMBER(DEVICE_SELF, mpf1_state, trigger_special, INPUT_LINE_IRQ0) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("RESET") PORT_CODE(KEYCODE_F3) PORT_CHANGED_MEMBER(DEVICE_SELF, mpf1_state, trigger_special, INPUT_LINE_RESET) +INPUT_PORTS_END + +static INPUT_PORTS_START( mt80z ) + PORT_START("PC0") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("GO") PORT_CODE(KEYCODE_X) PORT_CHAR('X') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("DUMP") PORT_CODE(KEYCODE_F6) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("COPY") PORT_CODE(KEYCODE_QUOTE) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("NEXT") PORT_CODE(KEYCODE_UP) PORT_CHAR('^') + PORT_BIT( 0xf0, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("PC1") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("STEP") PORT_CODE(KEYCODE_F1) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("LOAD") PORT_CODE(KEYCODE_F5) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("DEL") PORT_CODE(KEYCODE_SLASH) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("PREV") PORT_CODE(KEYCODE_DOWN) PORT_CHAR('V') + PORT_BIT( 0xf0, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("PC2") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("PC") PORT_CODE(KEYCODE_P) PORT_CHAR('P') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("CLR BRK PT") PORT_CODE(KEYCODE_N) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("INS") PORT_CODE(KEYCODE_COLON) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("DATA") PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("9 IY") PORT_CODE(KEYCODE_9) PORT_CHAR('9') + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("C SZ.H") PORT_CODE(KEYCODE_C) PORT_CHAR('C') + PORT_BIT( 0xc0, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("PC3") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("REG") PORT_CODE(KEYCODE_COMMA) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("SET BRK PT") PORT_CODE(KEYCODE_H) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("RELA") PORT_CODE(KEYCODE_RCONTROL) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("ADDR") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("D .PNC") PORT_CODE(KEYCODE_D) PORT_CHAR('D') + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("8 IX") PORT_CODE(KEYCODE_8) PORT_CHAR('8') + PORT_BIT( 0xc0, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("PC4") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("6 DE'") PORT_CODE(KEYCODE_6) PORT_CHAR('6') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("3 HL") PORT_CODE(KEYCODE_3) PORT_CHAR('3') + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("7 HL'") PORT_CODE(KEYCODE_7) PORT_CHAR('7') + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F .PNC'") PORT_CODE(KEYCODE_F) PORT_CHAR('F') + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("5 BC'") PORT_CODE(KEYCODE_5) PORT_CHAR('5') + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("4 AF'") PORT_CODE(KEYCODE_4) PORT_CHAR('4') + PORT_BIT( 0xc0, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("PC5") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("2 DE") PORT_CODE(KEYCODE_2) PORT_CHAR('2') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("A SP") PORT_CODE(KEYCODE_A) PORT_CHAR('A') + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("B I.IF") PORT_CODE(KEYCODE_B) PORT_CHAR('B') + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("E SZ.H'") PORT_CODE(KEYCODE_E) PORT_CHAR('E') + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("1 BC") PORT_CODE(KEYCODE_1) PORT_CHAR('1') + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("0 AF") PORT_CODE(KEYCODE_0) PORT_CHAR('0') + PORT_BIT( 0xc0, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("SPECIAL") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("USER KEY") PORT_CODE(KEYCODE_U) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("BREAK") PORT_CODE(KEYCODE_M) PORT_CHANGED_MEMBER(DEVICE_SELF, mpf1_state, trigger_special, INPUT_LINE_NMI) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("INTR") PORT_CODE(KEYCODE_I) PORT_CHANGED_MEMBER(DEVICE_SELF, mpf1_state, trigger_special, INPUT_LINE_IRQ0) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("RESET") PORT_CODE(KEYCODE_F3) PORT_CHANGED_MEMBER(DEVICE_SELF, mpf1_state, trigger_special, INPUT_LINE_RESET) INPUT_PORTS_END + /* Intel 8255A Interface */ TIMER_CALLBACK_MEMBER(mpf1_state::led_refresh) @@ -269,14 +359,14 @@ uint8_t mpf1_state::ppi_pa_r() data &= m_special->read() & 1 ? 0xff : 0xbf; /* bit 7, tape input */ - data |= ((m_cassette)->input() > 0) ? 0x80 : 0; + data |= (m_cassette->input() > 0) ? 0x80 : 0x00; return data; } void mpf1_state::ppi_pb_w(uint8_t data) { - /* swap bits around for the mame 7-segment emulation */ + /* swap bits around for the 7-segment emulation */ uint8_t led_data = bitswap<8>(data, 6, 1, 2, 0, 7, 5, 4, 3); /* timer to update segments */ @@ -301,7 +391,7 @@ void mpf1_state::ppi_pc_w(uint8_t data) /* bit 7, tape output, tone and led */ m_leds[0] = !BIT(data, 7); m_speaker->level_w(BIT(data, 7)); - m_cassette->output( BIT(data, 7) ? 1.0 : -1.0); + m_cassette->output(BIT(data, 7) ? 1.0 : -1.0); } uint8_t mpf1_state::step_r(offs_t offset) @@ -314,27 +404,21 @@ uint8_t mpf1_state::step_r(offs_t offset) m_maincpu->set_input_line(INPUT_LINE_NMI, ASSERT_LINE); } - return m_program->read_byte(offset); + return m_maincpu->space(AS_PROGRAM).read_byte(offset); } + /* Z80 Daisy Chain */ static const z80_daisy_config mpf1_daisy_chain[] = { - { Z80CTC_TAG }, - { Z80PIO_TAG }, + { "ctc" }, + { "pio" }, { nullptr } }; -/* Machine Initialization */ -TIMER_DEVICE_CALLBACK_MEMBER(mpf1_state::check_halt_callback) -{ - // halt-LED; the red one, is turned on when the processor is halted - // TODO: processor seems to halt, but restarts(?) at 0x0000 after a while -> fix - int64_t led_halt = m_maincpu->state_int(Z80_HALT); - m_leds[1] = led_halt; -} +/* Machine Initialization */ void mpf1_state::machine_start() { @@ -353,25 +437,27 @@ void mpf1_state::machine_reset() m_lednum = 0; } + /* Machine Drivers */ void mpf1_state::mpf1(machine_config &config) { /* basic machine hardware */ - Z80(config, m_maincpu, XTAL(3'579'545)/2); + Z80(config, m_maincpu, 3.579545_MHz_XTAL / 2); m_maincpu->set_addrmap(AS_PROGRAM, &mpf1_state::mpf1_map); m_maincpu->set_addrmap(AS_OPCODES, &mpf1_state::mpf1_step); m_maincpu->set_addrmap(AS_IO, &mpf1_state::mpf1_io_map); + m_maincpu->halt_cb().set_output("led1"); m_maincpu->set_daisy_config(mpf1_daisy_chain); /* devices */ - z80pio_device& pio(Z80PIO(config, Z80PIO_TAG, XTAL(3'579'545)/2)); + z80pio_device &pio(Z80PIO(config, "pio", 3.579545_MHz_XTAL / 2)); pio.out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0); - Z80CTC(config, m_ctc, XTAL(3'579'545)/2); - m_ctc->intr_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0); + z80ctc_device &ctc(Z80CTC(config, "ctc", 3.579545_MHz_XTAL / 2)); + ctc.intr_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0); - i8255_device &ppi(I8255A(config, I8255A_TAG)); + i8255_device &ppi(I8255A(config, "ppi")); ppi.in_pa_callback().set(FUNC(mpf1_state::ppi_pa_r)); ppi.out_pb_callback().set(FUNC(mpf1_state::ppi_pb_w)); ppi.out_pc_callback().set(FUNC(mpf1_state::ppi_pc_w)); @@ -386,107 +472,70 @@ void mpf1_state::mpf1(machine_config &config) SPEAKER(config, "mono").front_center(); SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.25); - TIMER(config, "halt_timer").configure_periodic(FUNC(mpf1_state::check_halt_callback), attotime::from_hz(1)); + /* expansion */ + mpf1_exp_device &exp(MPF1_EXP(config, "exp", 3.579545_MHz_XTAL / 2, mpf1_exp_devices, nullptr)); + exp.set_program_space(m_maincpu, AS_PROGRAM); + exp.set_io_space(m_maincpu, AS_IO); + exp.int_handler().set_inputline(m_maincpu, INPUT_LINE_IRQ0); + exp.nmi_handler().set_inputline(m_maincpu, INPUT_LINE_NMI); + exp.wait_handler().set_inputline(m_maincpu, Z80_INPUT_LINE_WAIT); + + GENERIC_SOCKET(config, m_rom_u7, generic_linear_slot, "mpf1_rom", "bin,rom"); + + SOFTWARE_LIST(config, "rom_ls").set_original("mpf1_rom").set_filter("IA"); } void mpf1_state::mpf1b(machine_config &config) { - /* basic machine hardware */ - Z80(config, m_maincpu, XTAL(3'579'545)/2); - m_maincpu->set_addrmap(AS_PROGRAM, &mpf1_state::mpf1b_map); - m_maincpu->set_addrmap(AS_OPCODES, &mpf1_state::mpf1_step); - m_maincpu->set_addrmap(AS_IO, &mpf1_state::mpf1b_io_map); - m_maincpu->set_daisy_config(mpf1_daisy_chain); - - /* devices */ - z80pio_device& pio(Z80PIO(config, Z80PIO_TAG, XTAL(3'579'545)/2)); - pio.out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0); - - Z80CTC(config, m_ctc, XTAL(3'579'545)/2); - m_ctc->intr_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0); - - i8255_device &ppi(I8255A(config, I8255A_TAG)); - ppi.in_pa_callback().set(FUNC(mpf1_state::ppi_pa_r)); - ppi.out_pb_callback().set(FUNC(mpf1_state::ppi_pb_w)); - ppi.out_pc_callback().set(FUNC(mpf1_state::ppi_pc_w)); + mpf1(config); - CASSETTE(config, m_cassette); - m_cassette->set_default_state(CASSETTE_STOPPED | CASSETTE_SPEAKER_ENABLED | CASSETTE_MOTOR_ENABLED); - - /* video hardware */ config.set_default_layout(layout_mpf1b); - /* sound hardware */ - SPEAKER(config, "mono").front_center(); - SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.25); - - TMS5220(config, TMS5220_TAG, 680000L).add_route(ALL_OUTPUTS, "mono", 0.50); - - TIMER(config, "halt_timer").configure_periodic(FUNC(mpf1_state::check_halt_callback), attotime::from_hz(1)); + subdevice<software_list_device>("rom_ls")->set_filter("IA,IB"); } -void mpf1_state::mpf1p(machine_config &config) +void mpf1_state::mt80z(machine_config &config) { - /* basic machine hardware */ - Z80(config, m_maincpu, 2500000); - m_maincpu->set_addrmap(AS_PROGRAM, &mpf1_state::mpf1p_map); - m_maincpu->set_addrmap(AS_OPCODES, &mpf1_state::mpf1_step); - m_maincpu->set_addrmap(AS_IO, &mpf1_state::mpf1p_io_map); - m_maincpu->set_daisy_config(mpf1_daisy_chain); - - /* video hardware */ - config.set_default_layout(layout_mpf1p); - - /* devices */ - z80pio_device& pio(Z80PIO(config, Z80PIO_TAG, 2500000)); - pio.out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0); - - Z80CTC(config, m_ctc, 2500000); - m_ctc->intr_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0); - - i8255_device &ppi(I8255A(config, I8255A_TAG)); - ppi.in_pa_callback().set(FUNC(mpf1_state::ppi_pa_r)); - ppi.out_pb_callback().set(FUNC(mpf1_state::ppi_pb_w)); - ppi.out_pc_callback().set(FUNC(mpf1_state::ppi_pc_w)); + mpf1b(config); - CASSETTE(config, m_cassette); - m_cassette->set_default_state(CASSETTE_STOPPED | CASSETTE_SPEAKER_ENABLED | CASSETTE_MOTOR_ENABLED); + config.set_default_layout(layout_mt80z); - /* sound hardware */ - SPEAKER(config, "mono").front_center(); - SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.25); - - TIMER(config, "halt_timer").configure_periodic(FUNC(mpf1_state::check_halt_callback), attotime::from_hz(1)); + // TODO: MT-80Z expansion board with switches (DIPs) and indicators (LEDs). } -/* ROMs */ ROM_START( mpf1 ) - ROM_REGION( 0x10000, Z80_TAG, 0 ) - ROM_LOAD( "mpf.u6", 0x0000, 0x1000, CRC(b60249ce) SHA1(78e0e8874d1497fabfdd6378266d041175e3797f) ) + ROM_REGION(0x3000, "maincpu", ROMREGION_ERASEFF) + ROM_LOAD("mpf1.u6", 0x0000, 0x0800, CRC(820030b1) SHA1(f618e2044b8f6e055e4d9a4c719b53bf16e22330)) ROM_END ROM_START( mpf1b ) - ROM_REGION( 0x10000, Z80_TAG, 0 ) - ROM_LOAD( "c55167.u6", 0x0000, 0x1000, CRC(28b06dac) SHA1(99cfbab739d71a914c39302d384d77bddc4b705b) ) - ROM_LOAD( "basic.u7", 0x2000, 0x1000, CRC(d276ed6b) SHA1(a45fb98961be5e5396988498c6ed589a35398dcf) ) - ROM_LOAD( "ssb-mpf.u", 0x5000, 0x1000, CRC(f926334f) SHA1(35847f8164eed4c0794a8b74e5d7fa972b10eb90) ) - ROM_LOAD( "prt-mpf.u5", 0x6000, 0x1000, CRC(730f2fb0) SHA1(f31536ee9dbb9babb9ce16a7490db654ca0b5749) ) + ROM_REGION(0x3000, "maincpu", ROMREGION_ERASEFF) + ROM_SYSTEM_BIOS(0, "basic", "BASIC") + ROMX_LOAD("mpf1b.u6", 0x0000, 0x1000, CRC(28b06dac) SHA1(99cfbab739d71a914c39302d384d77bddc4b705b), ROM_BIOS(0)) + ROMX_LOAD("unknown.u7", 0x2000, 0x1000, CRC(d276ed6b) SHA1(a45fb98961be5e5396988498c6ed589a35398dcf), ROM_BIOS(0)) // TODO: this was previously labelled as BASIC, it's not and is unknown. + ROM_SYSTEM_BIOS(1, "olsl1", "OLS-L1") + ROMX_LOAD("ols_l1.u6", 0x0000, 0x1000, CRC(b60249ce) SHA1(78e0e8874d1497fabfdd6378266d041175e3797f), ROM_BIOS(1)) + ROM_SYSTEM_BIOS(2, "olsl2", "OLS-L2") + ROMX_LOAD("ols_l1-3.u6", 0x0000, 0x1000, CRC(2f038b4b) SHA1(58ba895d2683d26d48da36afdcee9f1dae2f7b7c), ROM_BIOS(2)) + ROMX_LOAD("ols_l2.u7", 0x2000, 0x1000, CRC(77e51dde) SHA1(45d2c4b520291d5a346a0c3567bcb4b4406675f9), ROM_BIOS(2)) +ROM_END + +ROM_START( cs113 ) + ROM_REGION(0x3000, "maincpu", ROMREGION_ERASEFF) + ROM_LOAD("cs113.bin", 0x0000, 0x2000, CRC(d293a83b) SHA1(890e8b478e38fed6326b4151bf68c587f82f6a94)) ROM_END -ROM_START( mpf1p ) - ROM_REGION( 0x10000, Z80_TAG, 0 ) - ROM_LOAD( "mpf1pmon.bin", 0x0000, 0x2000, BAD_DUMP CRC(91ace7d3) SHA1(22e3c16a81ac09f37741ad1b526a4456b2ba9493) ) // A9 stuck low when dumped - ROM_LOAD( "prt-mpf-ip.u5", 0x6000, 0x1000, CRC(4dd2a4eb) SHA1(6a3e7daa7834d67fd572261ed4a9a62c4594fe3f) ) +ROM_START( mt80z ) + ROM_REGION(0x3000, "maincpu", ROMREGION_ERASEFF) + ROM_LOAD("fox.u6", 0x0000, 0x0800, CRC(298ffc59) SHA1(26d144aa63581407dd2f14437646afd807d2bb34)) ROM_END -/* System Drivers */ +} // anonymous namespace -void mpf1_state::init_mpf1() -{ - m_program = &m_maincpu->space(AS_PROGRAM); -} -COMP( 1979, mpf1, 0, 0, mpf1, mpf1, mpf1_state, init_mpf1, "Multitech", "Micro Professor 1", 0 ) -COMP( 1979, mpf1b, mpf1, 0, mpf1b,mpf1b, mpf1_state, init_mpf1, "Multitech", "Micro Professor 1B", 0 ) -COMP( 1982, mpf1p, mpf1, 0, mpf1p,mpf1b, mpf1_state, init_mpf1, "Multitech", "Micro Professor 1 Plus", MACHINE_NOT_WORKING ) +/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */ +COMP( 1981, mpf1, 0, 0, mpf1, mpf1, mpf1_state, empty_init, "Multitech", "Micro-Professor 1", 0 ) +COMP( 1982, mpf1b, mpf1, 0, mpf1b, mpf1b, mpf1_state, empty_init, "Multitech", "Micro-Professor 1B", 0 ) +COMP( 198?, cs113, 0, 0, mpf1, mpf1, mpf1_state, empty_init, "Sciento b.v.", "Robot Training Arm CS-113", MACHINE_NOT_WORKING ) +COMP( 1982, mt80z, mpf1, 0, mt80z, mt80z, mpf1_state, empty_init, "E&L Instruments", "MT-80Z", 0 ) diff --git a/src/mame/multitech/mpf1.h b/src/mame/multitech/mpf1.h deleted file mode 100644 index 72e6cfea8e6..00000000000 --- a/src/mame/multitech/mpf1.h +++ /dev/null @@ -1,88 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Wilbert Pol, Curt Coder -#ifndef MAME_MULTITECH_MPF1_H -#define MAME_MULTITECH_MPF1_H - -#pragma once - - -#include "machine/spchrom.h" -#include "cpu/z80/z80.h" -#include "machine/z80daisy.h" -#include "imagedev/cassette.h" -#include "machine/i8255.h" -#include "machine/timer.h" -#include "machine/z80ctc.h" -#include "machine/z80pio.h" -#include "sound/spkrdev.h" -#include "sound/tms5220.h" - -#define Z80_TAG "u1" -#define Z80CTC_TAG "u11" -#define Z80PIO_TAG "u10" -#define I8255A_TAG "u14" -#define TMS5220_TAG "tms5220" - -class mpf1_state : public driver_device -{ -public: - mpf1_state(const machine_config &mconfig, device_type type, const char *tag) - : driver_device(mconfig, type, tag), - m_maincpu(*this, Z80_TAG), - m_ctc(*this, Z80CTC_TAG), - m_speaker(*this, "speaker"), - m_cassette(*this, "cassette"), - m_pc(*this, "PC%u", 0U), - m_special(*this, "SPECIAL"), - m_digits(*this, "digit%u", 0U), - m_leds(*this, "led%u", 0U) - { } - - void mpf1p(machine_config &config); - void mpf1b(machine_config &config); - void mpf1(machine_config &config); - - void init_mpf1(); - - DECLARE_INPUT_CHANGED_MEMBER( trigger_nmi ); - DECLARE_INPUT_CHANGED_MEMBER( trigger_irq ); - DECLARE_INPUT_CHANGED_MEMBER( trigger_res ); - -private: - required_device<z80_device> m_maincpu; - required_device<z80ctc_device> m_ctc; - required_device<speaker_sound_device> m_speaker; - required_device<cassette_image_device> m_cassette; - required_ioport_array<6> m_pc; - required_ioport m_special; - output_finder<6> m_digits; - output_finder<2> m_leds; - - virtual void machine_start() override; - virtual void machine_reset() override; - - uint8_t step_r(offs_t offset); - uint8_t ppi_pa_r(); - void ppi_pb_w(uint8_t data); - void ppi_pc_w(uint8_t data); - - int m_break = 0; - int m_m1 = 0; - - uint8_t m_lednum = 0; - - emu_timer *m_led_refresh_timer = nullptr; - address_space *m_program = nullptr; - - TIMER_CALLBACK_MEMBER(led_refresh); - TIMER_DEVICE_CALLBACK_MEMBER(check_halt_callback); - void mpf1_io_map(address_map &map); - void mpf1_map(address_map &map); - void mpf1_step(address_map &map); - void mpf1b_io_map(address_map &map); - void mpf1b_map(address_map &map); - void mpf1p_io_map(address_map &map); - void mpf1p_map(address_map &map); -}; - -#endif // MAME_MULTITECH_MPF1_H diff --git a/src/mame/multitech/mpf1p.cpp b/src/mame/multitech/mpf1p.cpp new file mode 100644 index 00000000000..e8e1c061364 --- /dev/null +++ b/src/mame/multitech/mpf1p.cpp @@ -0,0 +1,396 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/************************************************\ +* Multitech Micro Professor 1 Plus * +* * +* CPU: Z80 @ 1.79 MHz * +* ROM: 8-kilobyte ROM monitor * +* RAM: 4 kilobytes * +* Input: 49 key keyboard * +* Storage: Cassette tape * +* Video: 20x 16-segment LED display * +* Sound: Speaker * +\************************************************/ + +#include "emu.h" +#include "cpu/z80/z80.h" +#include "machine/i8255.h" +#include "machine/timer.h" +#include "sound/spkrdev.h" + +#include "bus/generic/carts.h" +#include "bus/generic/slot.h" +#include "bus/mpf1/slot.h" +#include "imagedev/cassette.h" + +#include "softlist_dev.h" +#include "speaker.h" + +#include "mpf1p.lh" + + +namespace { + +class mpf1p_state : public driver_device +{ +public: + mpf1p_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag) + , m_maincpu(*this, "maincpu") + , m_speaker(*this, "speaker") + , m_cassette(*this, "cassette") + , m_key(*this, "PC%u", 1U) + , m_special(*this, "SPECIAL") + , m_digits(*this, "digit%u", 0U) + , m_leds(*this, "led%u", 0U) + { } + + void mpf1p(machine_config &config); + + DECLARE_INPUT_CHANGED_MEMBER( trigger_res ); + +protected: + virtual void machine_start() override; + +private: + required_device<z80_device> m_maincpu; + required_device<speaker_sound_device> m_speaker; + required_device<cassette_image_device> m_cassette; + required_ioport_array<20> m_key; + required_ioport m_special; + output_finder<20> m_digits; + output_finder<2> m_leds; + + void mpf1_step(address_map &map); + void mpf1p_io_map(address_map &map); + void mpf1p_map(address_map &map); + + uint8_t step_r(offs_t offset); + + uint8_t ppi1_pc_r(); + void ppi1_pa_w(uint8_t data); + void ppi1_pb_w(uint8_t data); + void ppi1_pc_w(uint8_t data); + + uint8_t ppi2_pc_r(); + void ppi2_pa_w(uint8_t data); + void ppi2_pb_w(uint8_t data); + void ppi2_pc_w(uint8_t data); + + int m_break = 0; + int m_m1 = 0; + + uint32_t m_lednum = 0; + uint16_t m_led_data = 0; + + void led_refresh(uint16_t data); +}; + + +void mpf1p_state::mpf1p_map(address_map &map) +{ + map.unmap_value_high(); + map(0x0000, 0x1fff).rom().region("rom_u2", 0); + map(0x2000, 0x3fff).r("rom_u3", FUNC(generic_slot_device::read_rom)); + map(0xf000, 0xffff).ram(); +} + +void mpf1p_state::mpf1_step(address_map &map) +{ + map(0x0000, 0xffff).r(FUNC(mpf1p_state::step_r)); +} + +void mpf1p_state::mpf1p_io_map(address_map &map) +{ + map.unmap_value_high(); + map.global_mask(0xff); + map(0x80, 0x83).mirror(0x0c).rw("ppi_1", FUNC(i8255_device::read), FUNC(i8255_device::write)); + map(0x90, 0x93).mirror(0x0c).rw("ppi_2", FUNC(i8255_device::read), FUNC(i8255_device::write)); +} + + +INPUT_CHANGED_MEMBER( mpf1p_state::trigger_res ) +{ + m_maincpu->set_input_line(INPUT_LINE_RESET, newval ? CLEAR_LINE : ASSERT_LINE); +} + +static INPUT_PORTS_START( mpf1p ) + PORT_START("PC1") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_A) PORT_CHAR('A') + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') + PORT_BIT( 0xf8, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("PC2") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_S) PORT_CHAR('S') + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) + PORT_BIT( 0xf8, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("PC3") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_D) PORT_CHAR('D') + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) + PORT_BIT( 0xf8, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("PC4") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F) PORT_CHAR('F') + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) + PORT_BIT( 0xf8, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("PC5") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_G) PORT_CHAR('G') + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP)) + PORT_BIT( 0xf8, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("PC6") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_H) PORT_CHAR('H') + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) + PORT_BIT( 0xf8, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("PC7") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('\'') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_J) PORT_CHAR('J') + PORT_BIT( 0xfc, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("PC8") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_K) PORT_CHAR('K') PORT_CHAR('^') + PORT_BIT( 0xfc, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("PC9") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_L) PORT_CHAR('L') PORT_CHAR('@') + PORT_BIT( 0xfc, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("PC10") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR('*') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COLON) PORT_CHAR(':') PORT_CHAR(';') + PORT_BIT( 0xfc, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("PC11") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Q) PORT_CHAR('Q') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Z) PORT_CHAR('Z') + PORT_BIT( 0xfc, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("PC12") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_W) PORT_CHAR('W') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_X) PORT_CHAR('X') + PORT_BIT( 0xfc, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("PC13") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_E) PORT_CHAR('E') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_C) PORT_CHAR('C') + PORT_BIT( 0xfc, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("PC14") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_R) PORT_CHAR('R') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_V) PORT_CHAR('V') + PORT_BIT( 0xfc, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("PC15") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_T) PORT_CHAR('T') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_B) PORT_CHAR('B') + PORT_BIT( 0xfc, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("PC16") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Y) PORT_CHAR('Y') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_N) PORT_CHAR('N') + PORT_BIT( 0xfc, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("PC17") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_U) PORT_CHAR('U') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_M) PORT_CHAR('M') + PORT_BIT( 0xfc, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("PC18") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_I) PORT_CHAR('I') PORT_CHAR('-') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<') + PORT_BIT( 0xfc, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("PC19") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_O) PORT_CHAR('O') PORT_CHAR('=') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>') + PORT_BIT( 0xfc, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("PC20") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_P) PORT_CHAR('P') PORT_CHAR('+') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('?') PORT_CHAR('/') + PORT_BIT( 0xfc, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("SPECIAL") + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("SHIFT") PORT_CODE(KEYCODE_LSHIFT) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("CONTROL") PORT_CODE(KEYCODE_LCONTROL) + PORT_BIT( 0xcf, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("RESET") + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("RESET") PORT_CODE(KEYCODE_F3) PORT_CHANGED_MEMBER(DEVICE_SELF, mpf1p_state, trigger_res, 0) +INPUT_PORTS_END + + +void mpf1p_state::led_refresh(uint16_t data) +{ + for (int digit = 0; digit < 20; digit++) + { + if (!BIT(m_lednum, digit)) + m_digits[digit] = data ^ 0xffff; + } +} + + +uint8_t mpf1p_state::ppi1_pc_r() +{ + uint8_t data = 0xff; + + // bit 4 and 5, shift and control keys + data &= m_special->read(); + + return data; +} + +void mpf1p_state::ppi1_pa_w(uint8_t data) +{ + m_lednum = (m_lednum & 0xffffff00) | data; + + led_refresh(m_led_data); +} + +void mpf1p_state::ppi1_pb_w(uint8_t data) +{ + m_lednum = (m_lednum & 0xffff00ff) | (data << 8); + + led_refresh(m_led_data); +} + +void mpf1p_state::ppi1_pc_w(uint8_t data) +{ + m_lednum = (m_lednum & 0xfff0ffff) | (data << 16); + + led_refresh(m_led_data); +} + +uint8_t mpf1p_state::ppi2_pc_r() +{ + uint8_t data = 0xf7; + + // bit 0 to 2, keyboard rows 0 to 20 + for (int row = 0; row < 20; row++) + if (!BIT(m_lednum, row)) + data &= m_key[row]->read(); + + // bit 3, tape input + data |= (m_cassette->input() > 0) ? 0x08 : 0x00; + + return data; +} + +void mpf1p_state::ppi2_pa_w(uint8_t data) +{ + m_led_data = (m_led_data & 0xff00) | data; +} + +void mpf1p_state::ppi2_pb_w(uint8_t data) +{ + // swap bits around for the 14-segment emulation + data = bitswap<8>(data, 7, 6, 4, 2, 3, 5, 1, 0); + + m_led_data = (m_led_data & 0x00ff) | (data << 8); +} + +void mpf1p_state::ppi2_pc_w(uint8_t data) +{ + // bit 4, monitor break control + m_break = BIT(data, 4); + + if (m_break) + { + m_m1 = 0; + m_maincpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE); + } + + // bit 5, tape output, tone and led + m_leds[0] = !BIT(data, 5); + m_speaker->level_w(BIT(data, 5)); + m_cassette->output(BIT(data, 5) ? 1.0 : -1.0); +} + + +uint8_t mpf1p_state::step_r(offs_t offset) +{ + if (!m_break) + { + m_m1++; + + if (m_m1 == 5) + m_maincpu->set_input_line(INPUT_LINE_NMI, ASSERT_LINE); + } + + return m_maincpu->space(AS_PROGRAM).read_byte(offset); +} + + +void mpf1p_state::machine_start() +{ + m_digits.resolve(); + m_leds.resolve(); + + // register for state saving */ + save_item(NAME(m_break)); + save_item(NAME(m_m1)); + save_item(NAME(m_lednum)); +} + + +void mpf1p_state::mpf1p(machine_config &config) +{ + Z80(config, m_maincpu, 3.579545_MHz_XTAL/2); + m_maincpu->set_addrmap(AS_PROGRAM, &mpf1p_state::mpf1p_map); + m_maincpu->set_addrmap(AS_OPCODES, &mpf1p_state::mpf1_step); + m_maincpu->set_addrmap(AS_IO, &mpf1p_state::mpf1p_io_map); + m_maincpu->halt_cb().set_output("led1"); + + config.set_default_layout(layout_mpf1p); + + i8255_device &ppi_1(I8255A(config, "ppi_1")); + ppi_1.out_pa_callback().set(FUNC(mpf1p_state::ppi1_pa_w)); + ppi_1.out_pb_callback().set(FUNC(mpf1p_state::ppi1_pb_w)); + ppi_1.out_pc_callback().set(FUNC(mpf1p_state::ppi1_pc_w)); + ppi_1.in_pc_callback().set(FUNC(mpf1p_state::ppi1_pc_r)); + + i8255_device &ppi_2(I8255A(config, "ppi_2")); + ppi_2.out_pa_callback().set(FUNC(mpf1p_state::ppi2_pa_w)); + ppi_2.out_pb_callback().set(FUNC(mpf1p_state::ppi2_pb_w)); + ppi_2.out_pc_callback().set(FUNC(mpf1p_state::ppi2_pc_w)); + ppi_2.in_pc_callback().set(FUNC(mpf1p_state::ppi2_pc_r)); + + CASSETTE(config, m_cassette); + m_cassette->set_default_state(CASSETTE_STOPPED | CASSETTE_SPEAKER_ENABLED | CASSETTE_MOTOR_ENABLED); + + SPEAKER(config, "mono").front_center(); + SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.25); + + mpf1_exp_device &exp(MPF1_EXP(config, "exp", 3.579545_MHz_XTAL/2, mpf1p_exp_devices, nullptr)); + exp.set_program_space(m_maincpu, AS_PROGRAM); + exp.set_io_space(m_maincpu, AS_IO); + exp.int_handler().set_inputline(m_maincpu, INPUT_LINE_IRQ0); + exp.nmi_handler().set_inputline(m_maincpu, INPUT_LINE_NMI); + exp.wait_handler().set_inputline(m_maincpu, Z80_INPUT_LINE_WAIT); + + GENERIC_SOCKET(config, "rom_u3", generic_linear_slot, "mpf1_rom", "bin,rom"); + + SOFTWARE_LIST(config, "rom_ls").set_original("mpf1_rom").set_filter("IP"); +} + +} // anonymous namespace + + +ROM_START( mpf1p ) + ROM_REGION(0x2000, "rom_u2", 0) + ROM_LOAD("mpf-1p_v1.1.u2", 0x0000, 0x2000, CRC(8bb241d3) SHA1(a05cf397452fe6a03e1ea9320985654f5910b20f)) +ROM_END + +// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS +COMP( 1983, mpf1p, 0, 0, mpf1p, mpf1p, mpf1p_state, empty_init, "Multitech", "Micro-Professor 1 Plus", 0 ) |