summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author AJR <ajrhacker@users.noreply.github.com>2020-04-29 11:12:52 -0400
committer AJR <ajrhacker@users.noreply.github.com>2020-04-29 11:16:14 -0400
commit9556e3a5bd047e3045879aca399a3e4a46585007 (patch)
tree3ccf4966b5b6f19789a9f0bdc5fa8877cd0f7885
parentb403d9be2d478e74fece3af6fee969637581e175 (diff)
New working machines
-------------------- MDT 60 Video Display Terminal [Bitsavers, AJR] z29: Add skeleton for undumped keyboard; try (and fail) to make this work with the MDT 60 keyboard instead z22: Separate driver (nw)
-rw-r--r--scripts/src/bus.lua17
-rw-r--r--scripts/target/mame/mess.lua2
-rw-r--r--src/devices/bus/z29_kbd/he191_3425.cpp240
-rw-r--r--src/devices/bus/z29_kbd/he191_3425.h58
-rw-r--r--src/devices/bus/z29_kbd/keyboard.cpp117
-rw-r--r--src/devices/bus/z29_kbd/keyboard.h104
-rw-r--r--src/devices/bus/z29_kbd/md_kbd.cpp277
-rw-r--r--src/devices/bus/z29_kbd/md_kbd.h61
-rw-r--r--src/mame/drivers/mdt60.cpp250
-rw-r--r--src/mame/drivers/z22.cpp215
-rw-r--r--src/mame/drivers/z29.cpp36
-rw-r--r--src/mame/mame.lst4
-rw-r--r--src/mame/mess.flt1
13 files changed, 1185 insertions, 197 deletions
diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua
index 2c708f35b4d..14e6b6187f6 100644
--- a/scripts/src/bus.lua
+++ b/scripts/src/bus.lua
@@ -2200,6 +2200,23 @@ end
---------------------------------------------------
--
+--@src/devices/bus/z29_kbd/keyboard.h,BUSES["Z29_KBD"] = true
+---------------------------------------------------
+
+if (BUSES["Z29_KBD"]~=null) then
+ files {
+ MAME_DIR .. "src/devices/bus/z29_kbd/keyboard.cpp",
+ MAME_DIR .. "src/devices/bus/z29_kbd/keyboard.h",
+ MAME_DIR .. "src/devices/bus/z29_kbd/he191_3425.cpp",
+ MAME_DIR .. "src/devices/bus/z29_kbd/he191_3425.h",
+ MAME_DIR .. "src/devices/bus/z29_kbd/md_kbd.cpp",
+ MAME_DIR .. "src/devices/bus/z29_kbd/md_kbd.h",
+ }
+end
+
+
+---------------------------------------------------
+--
--@src/devices/bus/z88/z88.h,BUSES["Z88"] = true
---------------------------------------------------
diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua
index 396ed5572b6..db3a00a065b 100644
--- a/scripts/target/mame/mess.lua
+++ b/scripts/target/mame/mess.lua
@@ -918,6 +918,7 @@ BUSES["VTECH_MEMEXP"] = true
BUSES["WANGPC"] = true
BUSES["WSWAN"] = true
BUSES["X68K"] = true
+BUSES["Z29_KBD"] = true
BUSES["Z88"] = true
BUSES["ZORRO"] = true
@@ -4179,6 +4180,7 @@ createMESSProjects(_target, _subtarget, "zenith")
files {
MAME_DIR .. "src/mame/drivers/mdt60.cpp",
MAME_DIR .. "src/mame/drivers/z100.cpp",
+ MAME_DIR .. "src/mame/drivers/z22.cpp",
MAME_DIR .. "src/mame/drivers/z29.cpp",
}
diff --git a/src/devices/bus/z29_kbd/he191_3425.cpp b/src/devices/bus/z29_kbd/he191_3425.cpp
new file mode 100644
index 00000000000..69ea07f76d1
--- /dev/null
+++ b/src/devices/bus/z29_kbd/he191_3425.cpp
@@ -0,0 +1,240 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ Heath HE 191-3425 keyboard
+
+ This 91-key detached keyboard is standard issue for the H-29 (Z-29)
+ terminal. It is also specified for the MDT 60 in its schematics.
+
+ Since the 8021 MCU is not dumped, emulation is more or less a stub.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "he191_3425.h"
+
+#include "cpu/mcs48/mcs48.h"
+#include "machine/rescap.h"
+#include "speaker.h"
+
+
+DEFINE_DEVICE_TYPE(HE191_3425, he191_3425_device, "he191_3425", "Heath HE 191-3425 Keyboard")
+
+he191_3425_device::he191_3425_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, HE191_3425, tag, owner, clock)
+ , device_z29_keyboard_interface(mconfig, *this)
+ , m_mcu(*this, "mcu")
+ , m_buzzer(*this, "buzzer")
+ , m_matrix(*this, {"B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "B11", "B13", "B14"})
+ , m_modifiers(*this, "MODIFIERS")
+ , m_leds(*this, "led%u", 1U)
+ , m_select(0)
+ , m_recv_data(true)
+{
+}
+
+void he191_3425_device::device_resolve_objects()
+{
+ m_leds.resolve();
+}
+
+void he191_3425_device::device_start()
+{
+ m_leds[0] = 1; // L1: Power
+
+ save_item(NAME(m_select));
+ save_item(NAME(m_recv_data));
+}
+
+void he191_3425_device::receive_data(bool state)
+{
+ machine().scheduler().synchronize(timer_expired_delegate(FUNC(he191_3425_device::receive_data_synced), this), state);
+}
+
+TIMER_CALLBACK_MEMBER(he191_3425_device::receive_data_synced)
+{
+ m_recv_data = param;
+}
+
+u8 he191_3425_device::mcu_pa_r()
+{
+ return m_select < 12 ? m_matrix[m_select]->read() : 0xff;
+}
+
+void he191_3425_device::mcu_pb_w(u8 data)
+{
+ transmit_data(!BIT(data, 3));
+ m_leds[1] = !BIT(data, 4); // L2: Keyboard Lock
+ m_leds[2] = !BIT(data, 5); // L3: Off/Line
+ m_leds[3] = !BIT(data, 6); // L4: Caps Lock
+ m_buzzer->set_state(BIT(data, 7));
+}
+
+void he191_3425_device::mcu_pc_w(u8 data)
+{
+ m_select = data & 0xf;
+}
+
+READ_LINE_MEMBER(he191_3425_device::mcu_t1_r)
+{
+ return m_recv_data;
+}
+
+WRITE_LINE_MEMBER(he191_3425_device::shift_reset)
+{
+ m_mcu->set_input_line(INPUT_LINE_RESET, (m_modifiers->read() & 0x06) != 0x00 ? CLEAR_LINE : ASSERT_LINE);
+ reset_from_keyboard((m_modifiers->read() & 0x06) != 0x00);
+}
+
+
+static INPUT_PORTS_START(he191_3425)
+ PORT_START("B1")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD)) PORT_CODE(KEYCODE_ENTER_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD)) PORT_CODE(KEYCODE_DEL_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD)) PORT_CODE(KEYCODE_0_PAD)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('`') PORT_CHAR('~') PORT_CODE(KEYCODE_BACKSLASH)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('0') PORT_CHAR(')') PORT_CODE(KEYCODE_0)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('o') PORT_CHAR('O') PORT_CODE(KEYCODE_O)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(';') PORT_CHAR(':') PORT_CODE(KEYCODE_COLON)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('/') PORT_CHAR('?') PORT_CODE(KEYCODE_SLASH)
+
+ PORT_START("B2")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 3 DL") PORT_CHAR(UCHAR_MAMEKEY(3_PAD)) PORT_CODE(KEYCODE_3_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD)) PORT_CODE(KEYCODE_2_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 1 IL") PORT_CHAR(UCHAR_MAMEKEY(1_PAD)) PORT_CODE(KEYCODE_1_PAD)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F9)) PORT_CODE(KEYCODE_F9)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('9') PORT_CHAR('(') PORT_CODE(KEYCODE_9)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('i') PORT_CHAR('I') PORT_CODE(KEYCODE_I)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('l') PORT_CHAR('L') PORT_CODE(KEYCODE_L)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('.') PORT_CHAR('>') PORT_CODE(KEYCODE_STOP)
+
+ PORT_START("B3")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD)) PORT_CODE(KEYCODE_6_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD)) PORT_CODE(KEYCODE_5_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD)) PORT_CODE(KEYCODE_4_PAD)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F8)) PORT_CODE(KEYCODE_F8)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('8') PORT_CHAR('*') PORT_CODE(KEYCODE_8)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('u') PORT_CHAR('U') PORT_CODE(KEYCODE_U)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('k') PORT_CHAR('K') PORT_CODE(KEYCODE_K)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(',') PORT_CHAR('<') PORT_CODE(KEYCODE_COMMA)
+
+ PORT_START("B4")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 9 DC") PORT_CHAR(UCHAR_MAMEKEY(9_PAD)) PORT_CODE(KEYCODE_9_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD)) PORT_CODE(KEYCODE_8_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 7 IC") PORT_CHAR(UCHAR_MAMEKEY(7_PAD)) PORT_CODE(KEYCODE_7_PAD)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F7)) PORT_CODE(KEYCODE_F7)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('7') PORT_CHAR('&') PORT_CODE(KEYCODE_7)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('y') PORT_CHAR('Y') PORT_CODE(KEYCODE_Y)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('j') PORT_CHAR('J') PORT_CODE(KEYCODE_J)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('m') PORT_CHAR('M') PORT_CODE(KEYCODE_M)
+
+ PORT_START("B5")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Help") PORT_CODE(KEYCODE_F10)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Line Feed") PORT_CHAR(0x0a) PORT_CODE(KEYCODE_RALT)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Space Bar") PORT_CHAR(' ') PORT_CODE(KEYCODE_SPACE)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F6)) PORT_CODE(KEYCODE_F6)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('6') PORT_CHAR('^') PORT_CODE(KEYCODE_6)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('t') PORT_CHAR('T') PORT_CODE(KEYCODE_T)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('h') PORT_CHAR('H') PORT_CODE(KEYCODE_H)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('n') PORT_CHAR('N') PORT_CODE(KEYCODE_N)
+
+ PORT_START("B6")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('\\') PORT_CHAR('|') PORT_CODE(KEYCODE_RCONTROL) // to right of Return key
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Return") PORT_CHAR(0x0d) PORT_CODE(KEYCODE_ENTER)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('\'') PORT_CHAR('"') PORT_CODE(KEYCODE_QUOTE)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F5)) PORT_CODE(KEYCODE_F5)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('5') PORT_CHAR('%') PORT_CODE(KEYCODE_5)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('r') PORT_CHAR('R') PORT_CODE(KEYCODE_R)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('g') PORT_CHAR('G') PORT_CODE(KEYCODE_G)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('b') PORT_CHAR('B') PORT_CODE(KEYCODE_B)
+
+ PORT_START("B7")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(']') PORT_CHAR('}') PORT_CODE(KEYCODE_CLOSEBRACE)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('[') PORT_CHAR('{') PORT_CODE(KEYCODE_OPENBRACE)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('p') PORT_CHAR('P') PORT_CODE(KEYCODE_P)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F4)) PORT_CODE(KEYCODE_F4)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('4') PORT_CHAR('$') PORT_CODE(KEYCODE_4)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('e') PORT_CHAR('E') PORT_CODE(KEYCODE_E)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('f') PORT_CHAR('F') PORT_CODE(KEYCODE_F)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('v') PORT_CHAR('V') PORT_CODE(KEYCODE_V)
+
+ PORT_START("B8")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Delete") PORT_CHAR(UCHAR_MAMEKEY(DEL)) PORT_CODE(KEYCODE_DEL) // to right of `/~ key
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(HOME)) PORT_CODE(KEYCODE_F11)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) PORT_CODE(KEYCODE_DOWN) // between +/= and Back Space keys
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F3)) PORT_CODE(KEYCODE_F3)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('3') PORT_CHAR('#') PORT_CODE(KEYCODE_3)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('w') PORT_CHAR('W') PORT_CODE(KEYCODE_W)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('d') PORT_CHAR('D') PORT_CODE(KEYCODE_D)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('c') PORT_CHAR('C') PORT_CODE(KEYCODE_C)
+
+ PORT_START("B9")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Back Space") PORT_CHAR(0x08) PORT_CODE(KEYCODE_BACKSPACE)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('=') PORT_CHAR('+') PORT_CODE(KEYCODE_EQUALS)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('-') PORT_CHAR('_') PORT_CODE(KEYCODE_MINUS)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F2)) PORT_CODE(KEYCODE_F2)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('2') PORT_CHAR('@') PORT_CODE(KEYCODE_2)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('q') PORT_CHAR('Q') PORT_CODE(KEYCODE_Q)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('s') PORT_CHAR('S') PORT_CODE(KEYCODE_S)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('x') PORT_CHAR('X') PORT_CODE(KEYCODE_X)
+
+ PORT_START("B11")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) PORT_CODE(KEYCODE_RIGHT)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(UP)) PORT_CODE(KEYCODE_UP)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) PORT_CODE(KEYCODE_LEFT) // to right of Home key
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F1)) PORT_CODE(KEYCODE_F1)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('1') PORT_CHAR('!') PORT_CODE(KEYCODE_1)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Tab") PORT_CHAR('\t') PORT_CODE(KEYCODE_TAB)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('a') PORT_CHAR('A') PORT_CODE(KEYCODE_A)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('z') PORT_CHAR('Z') PORT_CODE(KEYCODE_Z)
+
+ PORT_START("B13")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(COMMA_PAD)) PORT_CODE(KEYCODE_PLUS_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD)) PORT_CODE(KEYCODE_MINUS_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("No Scroll") PORT_CODE(KEYCODE_LALT)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Set Up") PORT_CODE(KEYCODE_ESC)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Esc") PORT_CHAR(0x1b) PORT_CODE(KEYCODE_TILDE)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Erase") PORT_CODE(KEYCODE_F12)
+
+ PORT_START("B14")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK)) PORT_CODE(KEYCODE_CAPSLOCK)
+ PORT_BIT(0xfe, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("MODIFIERS")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ctrl") PORT_CHAR(UCHAR_SHIFT_2) PORT_CODE(KEYCODE_LCONTROL)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Shift") PORT_CHAR(UCHAR_SHIFT_1) PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) PORT_WRITE_LINE_MEMBER(he191_3425_device, shift_reset)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Break Reset") PORT_CODE(KEYCODE_PAUSE) PORT_WRITE_LINE_MEMBER(he191_3425_device, shift_reset) // to right of Back Space key
+ PORT_BIT(0xf8, IP_ACTIVE_LOW, IPT_UNUSED)
+INPUT_PORTS_END
+
+ioport_constructor he191_3425_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(he191_3425);
+}
+
+void he191_3425_device::device_add_mconfig(machine_config &config)
+{
+ i8021_device &mcu(I8021(config, m_mcu, 3.579545_MHz_XTAL));
+ mcu.bus_in_cb().set(FUNC(he191_3425_device::mcu_pa_r));
+ mcu.p1_in_cb().set_ioport("MODIFIERS");
+ mcu.p1_out_cb().set(FUNC(he191_3425_device::mcu_pb_w));
+ mcu.p2_out_cb().set(FUNC(he191_3425_device::mcu_pc_w));
+ mcu.t1_in_cb().set(FUNC(he191_3425_device::mcu_t1_r));
+
+ SPEAKER(config, "speaker").front_center();
+ BEEP(config, m_buzzer, 1'000'000'000 / PERIOD_OF_555_ASTABLE_NSEC(RES_R(510), RES_R(510), CAP_U(1)));
+ m_buzzer->add_route(ALL_OUTPUTS, "speaker", 1.0);
+}
+
+ROM_START(he191_3425)
+ ROM_REGION(0x400, "mcu", ROMREGION_ERASE00)
+ ROM_LOAD("p8021h-2155_444-100.z1", 0x000, 0x400, NO_DUMP)
+ROM_END
+
+const tiny_rom_entry *he191_3425_device::device_rom_region() const
+{
+ return ROM_NAME(he191_3425);
+}
diff --git a/src/devices/bus/z29_kbd/he191_3425.h b/src/devices/bus/z29_kbd/he191_3425.h
new file mode 100644
index 00000000000..cf0129936fb
--- /dev/null
+++ b/src/devices/bus/z29_kbd/he191_3425.h
@@ -0,0 +1,58 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_BUS_Z29_KBD_HE191_3425_H
+#define MAME_BUS_Z29_KBD_HE191_3425_H
+
+#pragma once
+
+#include "bus/z29_kbd/keyboard.h"
+#include "sound/beep.h"
+
+
+class he191_3425_device : public device_t, public device_z29_keyboard_interface
+{
+public:
+ // device type constructor
+ he191_3425_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ // miscellanous handlers
+ DECLARE_WRITE_LINE_MEMBER(shift_reset);
+
+protected:
+ // device-level overrides
+ virtual void device_resolve_objects() override;
+ virtual void device_start() override;
+ virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ // device_z29_keyboard_interface overrides
+ virtual void receive_data(bool state) override;
+
+private:
+ // MCU port handlers
+ u8 mcu_pa_r();
+ void mcu_pb_w(u8 data);
+ void mcu_pc_w(u8 data);
+ DECLARE_READ_LINE_MEMBER(mcu_t1_r);
+
+ // misc. helpers
+ TIMER_CALLBACK_MEMBER(receive_data_synced);
+
+ // object finders
+ required_device<cpu_device> m_mcu;
+ required_device<beep_device> m_buzzer;
+ required_ioport_array<12> m_matrix;
+ required_ioport m_modifiers;
+ output_finder<4> m_leds;
+
+ // internal state
+ u8 m_select;
+ bool m_recv_data;
+};
+
+// device type declaration
+DECLARE_DEVICE_TYPE(HE191_3425, he191_3425_device)
+
+#endif // MAME_BUS_Z29_KBD_HE191_3425_H
diff --git a/src/devices/bus/z29_kbd/keyboard.cpp b/src/devices/bus/z29_kbd/keyboard.cpp
new file mode 100644
index 00000000000..637bc8d4389
--- /dev/null
+++ b/src/devices/bus/z29_kbd/keyboard.cpp
@@ -0,0 +1,117 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ Zenith Z-29 keyboard port
+
+ This supports the custom serial interface for the H-29/Z-29 and other
+ early Heath/Zenith terminals with detachable keyboards. (Keyboards for
+ later Zenith terminals such as the Z-49 use a standard asynchronous
+ serial protocol.)
+
+ All printable characters outside of the numeric keypad use standard
+ ASCII codes, as do Back Space, Line Feed, Return, Esc and Del. The
+ following codes are assigned to other keys:
+
+ 80 Up
+ 81 Down
+ 82 Left
+ 83 Right
+ 84 Home
+ 85 Erase
+ 86 Help
+ 87 No Scroll
+ 88 Set Up
+ 89 Break
+ 8A Caps Lock
+ 8B Tab
+ 8C Space Bar
+ 8F (Power On)
+ 90 0 (Keypad)
+ 91 1 (Keypad)
+ 92 2 (Keypad)
+ 93 3 (Keypad)
+ 94 4 (Keypad)
+ 95 5 (Keypad)
+ 96 6 (Keypad)
+ 97 7 (Keypad)
+ 98 8 (Keypad)
+ 99 9 (Keypad)
+ 9A . (Keypad)
+ 9B Enter (Keypad)
+ 9C - (Keypad)
+ 9D , (Keypad)
+ 9F 80 F1
+ 9F 81 F2
+ 9F 82 F3
+ 9F 83 F4
+ 9F 84 F5
+ 9F 85 F6
+ 9F 86 F7
+ 9F 87 F8
+ 9F 88 F9
+
+ Bit 6 is set in these codes when pressed with Shift, and bit 5 when
+ pressed with Ctrl.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "keyboard.h"
+
+#include "he191_3425.h"
+#include "md_kbd.h"
+
+//**************************************************************************
+// Z-29 KEYBOARD PORT DEVICE
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(Z29_KEYBOARD, z29_keyboard_port_device, "z29_kbd", "Z-29 Keyboard Port")
+
+z29_keyboard_port_device::z29_keyboard_port_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, Z29_KEYBOARD, tag, owner, clock)
+ , device_single_card_slot_interface<device_z29_keyboard_interface>(mconfig, *this)
+ , m_keyin_callback(*this)
+ , m_reset_callback(*this)
+ , m_kbd(nullptr)
+{
+}
+
+void z29_keyboard_port_device::device_config_complete()
+{
+ m_kbd = get_card_device();
+}
+
+void z29_keyboard_port_device::device_resolve_objects()
+{
+ m_keyin_callback.resolve_safe();
+ m_reset_callback.resolve_safe();
+}
+
+void z29_keyboard_port_device::device_start()
+{
+}
+
+//**************************************************************************
+// Z-29 KEYBOARD INTERFACE
+//**************************************************************************
+
+device_z29_keyboard_interface::device_z29_keyboard_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device, "z29kbd")
+ , m_port(device, DEVICE_SELF_OWNER)
+{
+}
+
+device_z29_keyboard_interface::~device_z29_keyboard_interface()
+{
+}
+
+//**************************************************************************
+// KEYBOARD OPTIONS
+//**************************************************************************
+
+void z29_keyboards(device_slot_interface &slot)
+{
+ slot.option_add("heath", HE191_3425);
+ slot.option_add("md", MD_KEYBOARD);
+}
diff --git a/src/devices/bus/z29_kbd/keyboard.h b/src/devices/bus/z29_kbd/keyboard.h
new file mode 100644
index 00000000000..501d8bbe569
--- /dev/null
+++ b/src/devices/bus/z29_kbd/keyboard.h
@@ -0,0 +1,104 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ Zenith Z-29 keyboard port
+
+***************************************************************************/
+
+#ifndef MAME_BUS_Z29_KBD_KEYBOARD_H
+#define MAME_BUS_Z29_KBD_KEYBOARD_H
+
+#pragma once
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// forward declaration
+class device_z29_keyboard_interface;
+
+// ======================> z29_keyboard_port_device
+
+class z29_keyboard_port_device : public device_t, public device_single_card_slot_interface<device_z29_keyboard_interface>
+{
+ friend class device_z29_keyboard_interface;
+
+public:
+ // construction/destruction
+ z29_keyboard_port_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+ template <typename T>
+ z29_keyboard_port_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&opts, const char *dflt)
+ : z29_keyboard_port_device(mconfig, tag, owner, 0U)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ }
+
+ // callback configuration
+ auto keyin_callback() { return m_keyin_callback.bind(); }
+ auto reset_callback() { return m_reset_callback.bind(); }
+
+ // line handler
+ inline DECLARE_WRITE_LINE_MEMBER(keyout_w);
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete() override;
+ virtual void device_resolve_objects() override;
+ virtual void device_start() override;
+
+ // called from keyboard
+ void transmit_data(bool state) { m_keyin_callback(state); }
+ void reset_from_keyboard(bool state) { m_reset_callback(state); }
+
+private:
+ // line callbacks
+ devcb_write_line m_keyin_callback;
+ devcb_write_line m_reset_callback;
+
+ // selected keyboard
+ device_z29_keyboard_interface *m_kbd;
+};
+
+// ======================> device_z29_keyboard_interface
+
+class device_z29_keyboard_interface : public device_interface
+{
+ friend class z29_keyboard_port_device;
+
+protected:
+ // construction/destruction
+ device_z29_keyboard_interface(const machine_config &mconfig, device_t &device);
+ virtual ~device_z29_keyboard_interface();
+
+ void transmit_data(bool state) { m_port->transmit_data(state); }
+ void reset_from_keyboard(bool state) { m_port->reset_from_keyboard(state); }
+
+ virtual void receive_data(bool state) = 0;
+
+private:
+ // parent port
+ required_device<z29_keyboard_port_device> m_port;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(Z29_KEYBOARD, z29_keyboard_port_device)
+
+// standard options
+extern void z29_keyboards(device_slot_interface &slot);
+
+//**************************************************************************
+// INLINE FUNCTIONS
+//**************************************************************************
+
+WRITE_LINE_MEMBER(z29_keyboard_port_device::keyout_w)
+{
+ if (m_kbd != nullptr)
+ m_kbd->receive_data(state);
+}
+
+#endif // MAME_BUS_Z29_KBD_KEYBOARD_H
diff --git a/src/devices/bus/z29_kbd/md_kbd.cpp b/src/devices/bus/z29_kbd/md_kbd.cpp
new file mode 100644
index 00000000000..1a313af10ce
--- /dev/null
+++ b/src/devices/bus/z29_kbd/md_kbd.cpp
@@ -0,0 +1,277 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ Micro-Decision keyboard
+
+ This 93-key keyboard was obtained with a Morrow MD3-P. The unit part
+ number is unknown, but "DEKU-0224-PHM-B" and "I/F PCB FOR 14515B" are
+ silkscreened on the component board.
+
+ Like the original Z-29 keyboard, it may also have been designed by
+ Heath/Zenith. It is missing the Erase, Set Up and Break keys (though
+ the first two are still recognized by the program), but has five
+ additional function keys instead.
+
+ Some clumsy coding suggests that the program was originally designed
+ for an 8048 operating in single-chip mode, with the 14515B and LS175
+ having being added to latch outputs also sent to the upper half of
+ Port 2.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "md_kbd.h"
+
+#include "machine/rescap.h"
+#include "speaker.h"
+
+
+DEFINE_DEVICE_TYPE(MD_KEYBOARD, md_keyboard_device, "md_kbd", "Micro-Decision Keyboard")
+
+md_keyboard_device::md_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MD_KEYBOARD, tag, owner, clock)
+ , device_z29_keyboard_interface(mconfig, *this)
+ , m_mcu(*this, "mcu")
+ , m_buzzer(*this, "buzzer")
+ , m_matrix(*this, "S%u", 0U)
+ , m_leds(*this, "led%u", 1U)
+ , m_14515b_select(0)
+ , m_ls175_clock(true)
+ , m_recv_data(true)
+{
+}
+
+void md_keyboard_device::device_resolve_objects()
+{
+ m_leds.resolve();
+}
+
+void md_keyboard_device::device_start()
+{
+ save_item(NAME(m_14515b_select));
+ save_item(NAME(m_ls175_clock));
+ save_item(NAME(m_recv_data));
+}
+
+void md_keyboard_device::device_reset()
+{
+ ls175_w(0);
+}
+
+void md_keyboard_device::receive_data(bool state)
+{
+ machine().scheduler().synchronize(timer_expired_delegate(FUNC(md_keyboard_device::receive_data_synced), this), state);
+}
+
+TIMER_CALLBACK_MEMBER(md_keyboard_device::receive_data_synced)
+{
+ m_recv_data = param;
+}
+
+void md_keyboard_device::ls175_w(u8 data)
+{
+ m_leds[0] = !BIT(data, 7); // Caps Lock
+ m_leds[1] = !BIT(data, 5); // Keyboard lock?
+ m_buzzer->set_state(BIT(data, 6));
+}
+
+u8 md_keyboard_device::mcu_p1_r()
+{
+ return 0xc0 | m_matrix[m_14515b_select]->read();
+}
+
+void md_keyboard_device::mcu_p1_w(u8 data)
+{
+ transmit_data(!BIT(data, 7));
+ if (!m_ls175_clock && BIT(data, 6))
+ ls175_w(m_mcu->p2_r());
+ m_ls175_clock = BIT(data, 6);
+}
+
+READ_LINE_MEMBER(md_keyboard_device::mcu_t1_r)
+{
+ return m_recv_data;
+}
+
+void md_keyboard_device::mcu_movx_w(u8 data)
+{
+ m_14515b_select = (data >> 4) & 0x0f;
+}
+
+void md_keyboard_device::prog_map(address_map &map)
+{
+ map(0x000, 0xfff).rom().region("program", 0);
+}
+
+void md_keyboard_device::ext_map(address_map &map)
+{
+ map(0x00, 0x00).mirror(0xff).w(FUNC(md_keyboard_device::mcu_movx_w));
+}
+
+
+static INPUT_PORTS_START(md_kbd)
+
+ PORT_START("S0")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('q') PORT_CHAR('Q') PORT_CODE(KEYCODE_Q)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('g') PORT_CHAR('G') PORT_CODE(KEYCODE_G)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(';') PORT_CHAR(':') PORT_CODE(KEYCODE_COLON)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD)) PORT_CODE(KEYCODE_0_PAD)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('0') PORT_CHAR(')') PORT_CODE(KEYCODE_0)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Erase") // not actually on keyboard?
+
+ PORT_START("S1")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('w') PORT_CHAR('W') PORT_CODE(KEYCODE_W)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('b') PORT_CHAR('B') PORT_CODE(KEYCODE_B)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(']') PORT_CHAR('}') PORT_CODE(KEYCODE_CLOSEBRACE)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD)) PORT_CODE(KEYCODE_9_PAD)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('9') PORT_CHAR('(') PORT_CODE(KEYCODE_9)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Help") PORT_CODE(KEYCODE_F12)
+
+ PORT_START("S2")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('e') PORT_CHAR('E') PORT_CODE(KEYCODE_E)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('n') PORT_CHAR('N') PORT_CODE(KEYCODE_N)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('[') PORT_CHAR('{') PORT_CODE(KEYCODE_OPENBRACE)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD)) PORT_CODE(KEYCODE_8_PAD)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('8') PORT_CHAR('*') PORT_CODE(KEYCODE_8)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Home Clear") PORT_CHAR(UCHAR_MAMEKEY(HOME)) PORT_CODE(KEYCODE_F11)
+
+ PORT_START("S3")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('r') PORT_CHAR('R') PORT_CODE(KEYCODE_R)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('m') PORT_CHAR('M') PORT_CODE(KEYCODE_M)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('-') PORT_CHAR('_') PORT_CODE(KEYCODE_MINUS)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD)) PORT_CODE(KEYCODE_7_PAD)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('7') PORT_CHAR('&') PORT_CODE(KEYCODE_7)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("S4")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('f') PORT_CHAR('F') PORT_CODE(KEYCODE_F)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('l') PORT_CHAR('L') PORT_CODE(KEYCODE_L)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('=') PORT_CHAR('+') PORT_CODE(KEYCODE_EQUALS)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD)) PORT_CODE(KEYCODE_6_PAD)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('6') PORT_CHAR('^') PORT_CODE(KEYCODE_6)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("No Scroll") PORT_CODE(KEYCODE_ESC)
+
+ PORT_START("S5")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('d') PORT_CHAR('D') PORT_CODE(KEYCODE_D)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('k') PORT_CHAR('K') PORT_CODE(KEYCODE_K)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('`') PORT_CHAR('~') PORT_CODE(KEYCODE_BACKSLASH) // to right of +/=
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD)) PORT_CODE(KEYCODE_5_PAD)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('5') PORT_CHAR('%') PORT_CODE(KEYCODE_5)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Caps Lock") PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK)) PORT_CODE(KEYCODE_CAPSLOCK)
+
+ PORT_START("S6")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('s') PORT_CHAR('S') PORT_CODE(KEYCODE_S)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('j') PORT_CHAR('J') PORT_CODE(KEYCODE_J)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('\'') PORT_CHAR('"') PORT_CODE(KEYCODE_QUOTE)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD)) PORT_CODE(KEYCODE_4_PAD)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('4') PORT_CHAR('$') PORT_CODE(KEYCODE_4)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Del") PORT_CHAR(UCHAR_MAMEKEY(DEL)) PORT_CODE(KEYCODE_DEL)
+
+ PORT_START("S7")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('a') PORT_CHAR('A') PORT_CODE(KEYCODE_A)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('h') PORT_CHAR('H') PORT_CODE(KEYCODE_H)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('p') PORT_CHAR('P') PORT_CODE(KEYCODE_P)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD)) PORT_CODE(KEYCODE_3_PAD)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('3') PORT_CHAR('#') PORT_CODE(KEYCODE_3)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(UP)) PORT_CODE(KEYCODE_UP)
+
+ PORT_START("S8")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('z') PORT_CHAR('Z') PORT_CODE(KEYCODE_Z)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('t') PORT_CHAR('T') PORT_CODE(KEYCODE_T)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('o') PORT_CHAR('O') PORT_CODE(KEYCODE_O)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD)) PORT_CODE(KEYCODE_2_PAD)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('2') PORT_CHAR('@') PORT_CODE(KEYCODE_2)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) PORT_CODE(KEYCODE_DOWN)
+
+ PORT_START("S9")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('x') PORT_CHAR('X') PORT_CODE(KEYCODE_X)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('y') PORT_CHAR('Y') PORT_CODE(KEYCODE_Y)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('\\') PORT_CHAR('|') PORT_CODE(KEYCODE_RCONTROL)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD)) PORT_CODE(KEYCODE_1_PAD)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('1') PORT_CHAR('!') PORT_CODE(KEYCODE_1)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) PORT_CODE(KEYCODE_RIGHT)
+
+ PORT_START("S10")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('c') PORT_CHAR('C') PORT_CODE(KEYCODE_C)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('u') PORT_CHAR('U') PORT_CODE(KEYCODE_U)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(',') PORT_CHAR('<') PORT_CODE(KEYCODE_COMMA)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(COMMA_PAD)) PORT_CODE(KEYCODE_PLUS_PAD)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Esc") PORT_CHAR(0x1b) PORT_CODE(KEYCODE_TILDE)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) PORT_CODE(KEYCODE_LEFT)
+
+ PORT_START("S11")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('v') PORT_CHAR('V') PORT_CODE(KEYCODE_V)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('i') PORT_CHAR('I') PORT_CODE(KEYCODE_I)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('.') PORT_CHAR('>') PORT_CODE(KEYCODE_STOP)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD)) PORT_CODE(KEYCODE_DEL_PAD)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Tab") PORT_CHAR('\t') PORT_CODE(KEYCODE_TAB)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('/') PORT_CHAR('?') PORT_CODE(KEYCODE_SLASH)
+
+ PORT_START("S12")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(' ') PORT_CODE(KEYCODE_SPACE)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Return") PORT_CHAR(0x0d) PORT_CODE(KEYCODE_ENTER)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad Enter +") PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD)) PORT_CODE(KEYCODE_ENTER_PAD)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD)) PORT_CODE(KEYCODE_MINUS_PAD)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Line Feed") PORT_CHAR(0x0a) PORT_CODE(KEYCODE_RALT)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Back Space") PORT_CHAR(0x08) PORT_CODE(KEYCODE_BACKSPACE)
+
+ PORT_START("S13")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F1)) PORT_CODE(KEYCODE_F1)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F2)) PORT_CODE(KEYCODE_F2)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F3)) PORT_CODE(KEYCODE_F3)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F4)) PORT_CODE(KEYCODE_F4)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F5)) PORT_CODE(KEYCODE_F5)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F6)) PORT_CODE(KEYCODE_F6)
+
+ PORT_START("S14")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F7)) PORT_CODE(KEYCODE_F7)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F8)) PORT_CODE(KEYCODE_F8)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F9)) PORT_CODE(KEYCODE_F9)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F10)) PORT_CODE(KEYCODE_F10)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("FA") PORT_CHAR(UCHAR_MAMEKEY(F11))
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("FB") PORT_CHAR(UCHAR_MAMEKEY(F12))
+
+ PORT_START("S15")
+ 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_KEYBOARD) PORT_NAME("Setup") // not actually on keyboard?
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("FD") PORT_CHAR(UCHAR_MAMEKEY(F14))
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("FC") PORT_CHAR(UCHAR_MAMEKEY(F13))
+
+ PORT_START("MODIFIERS")
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ctrl") PORT_CHAR(UCHAR_SHIFT_2) PORT_CODE(KEYCODE_LCONTROL)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Shift") PORT_CHAR(UCHAR_SHIFT_1) PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT)
+INPUT_PORTS_END
+
+ioport_constructor md_keyboard_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(md_kbd);
+}
+
+void md_keyboard_device::device_add_mconfig(machine_config &config)
+{
+ // U4 is M5L8048-052P (internal ROM likely unused), but location is silkscreened "8035"
+ I8035(config, m_mcu, 3.579545_MHz_XTAL); // "CSA 3 58MT" resonator
+ m_mcu->set_addrmap(AS_PROGRAM, &md_keyboard_device::prog_map);
+ m_mcu->set_addrmap(AS_IO, &md_keyboard_device::ext_map);
+ m_mcu->p1_in_cb().set(FUNC(md_keyboard_device::mcu_p1_r));
+ m_mcu->p1_out_cb().set(FUNC(md_keyboard_device::mcu_p1_w));
+ m_mcu->p2_in_cb().set_ioport("MODIFIERS");
+ m_mcu->t1_in_cb().set(FUNC(md_keyboard_device::mcu_t1_r));
+
+ SPEAKER(config, "speaker").front_center();
+ BEEP(config, m_buzzer, 1'000'000'000 / PERIOD_OF_555_ASTABLE_NSEC(RES_R(510), RES_R(510), CAP_U(1)));
+ m_buzzer->add_route(ALL_OUTPUTS, "speaker", 1.0);
+}
+
+ROM_START(md_kbd)
+ ROM_REGION(0x1000, "program", 0)
+ ROM_LOAD("kb-rom_rev_3.4_27d4.u5", 0x0000, 0x1000, CRC(c34b606b) SHA1(20cf62fc31257b6c3e767152086f2604fead97bd)) // location marked "2716/2732"
+ROM_END
+
+const tiny_rom_entry *md_keyboard_device::device_rom_region() const
+{
+ return ROM_NAME(md_kbd);
+}
diff --git a/src/devices/bus/z29_kbd/md_kbd.h b/src/devices/bus/z29_kbd/md_kbd.h
new file mode 100644
index 00000000000..8a81b9a461d
--- /dev/null
+++ b/src/devices/bus/z29_kbd/md_kbd.h
@@ -0,0 +1,61 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_BUS_Z29_KBD_MD_KBD_H
+#define MAME_BUS_Z29_KBD_MD_KBD_H
+
+#pragma once
+
+#include "keyboard.h"
+#include "cpu/mcs48/mcs48.h"
+#include "sound/beep.h"
+
+class md_keyboard_device : public device_t, public device_z29_keyboard_interface
+{
+public:
+ // device type constructor
+ md_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_resolve_objects() override;
+ 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;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ // device_z29_keyboard_interface overrides
+ virtual void receive_data(bool state) override;
+
+private:
+ // MCU handlers
+ u8 mcu_p1_r();
+ void mcu_p1_w(u8 data);
+ DECLARE_READ_LINE_MEMBER(mcu_t1_r);
+ void mcu_movx_w(u8 data);
+
+ // misc. helpers
+ TIMER_CALLBACK_MEMBER(receive_data_synced);
+ void ls175_w(u8 data);
+
+ // address maps
+ void prog_map(address_map &map);
+ void ext_map(address_map &map);
+
+ // object finders
+ required_device<mcs48_cpu_device> m_mcu;
+ required_device<beep_device> m_buzzer;
+ required_ioport_array<16> m_matrix;
+ output_finder<2> m_leds;
+
+ // internal state
+ u8 m_14515b_select;
+ bool m_ls175_clock;
+ bool m_recv_data;
+};
+
+// device type declaration
+DECLARE_DEVICE_TYPE(MD_KEYBOARD, md_keyboard_device)
+
+#endif // MAME_BUS_Z29_KBD_MD_KBD_H
diff --git a/src/mame/drivers/mdt60.cpp b/src/mame/drivers/mdt60.cpp
index 493ee5daf07..90ef746f92a 100644
--- a/src/mame/drivers/mdt60.cpp
+++ b/src/mame/drivers/mdt60.cpp
@@ -2,58 +2,41 @@
// copyright-holders:AJR
/**************************************************************************
- Skeleton driver for MDT 60 and related Zenith terminals.
-
MDT 60 was designed by Zenith for use with Morrow's Micro-Decision
computers as a low-cost terminal with limited features. It appears
to be a stripped-down version of some previously designed terminal,
with the auxiliary port omitted from the Morrow version even though
- the schematics published by Morrow include it. Morrow's schematics
- also include the same keyboard used by the Z-29, though the actual
- keyboard found with one unit was different.
+ the schematics published in its service manual include it. These
+ schematics also include the same keyboard used by the Z-29, though
+ the actual keyboard found with one unit was different.
**************************************************************************/
#include "emu.h"
#include "bus/rs232/rs232.h"
+#include "bus/z29_kbd/keyboard.h"
#include "cpu/m6502/m6502.h"
-#include "machine/eepromser.h"
#include "machine/i8251.h"
-#include "machine/pit8253.h"
#include "video/mc6845.h"
#include "screen.h"
-class mdt60_base_state : public driver_device
+class mdt60_state : public driver_device
{
public:
- mdt60_base_state(const machine_config &mconfig, device_type type, const char *tag)
+ mdt60_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_maincpu(*this, "maincpu")
+ , m_keyboard(*this, "keyboard")
, m_crtc(*this, "crtc")
, m_uart(*this, "uart%u", 0U)
, m_charram(*this, "charram")
- {
- }
-
-protected:
- MC6845_ON_UPDATE_ADDR_CHANGED(update_cb);
-
- required_device<cpu_device> m_maincpu;
- required_device<r6545_1_device> m_crtc;
- optional_device_array<i8251_device, 2> m_uart;
- required_shared_ptr<u8> m_charram;
-};
-
-class mdt60_state : public mdt60_base_state
-{
-public:
- mdt60_state(const machine_config &mconfig, device_type type, const char *tag)
- : mdt60_base_state(mconfig, type, tag)
, m_charrom(*this, "charrom")
, m_attrram(*this, "attrram")
, m_dip0(*this, "DIP0")
+ , m_baud_timer(nullptr)
, m_keyin(false)
- , m_reverse(false)
+ , m_output_reg(0x3f)
+ , m_timer_output(false)
{
}
@@ -65,6 +48,8 @@ protected:
private:
MC6845_UPDATE_ROW(update_row);
+ MC6845_ON_UPDATE_ADDR_CHANGED(update_cb);
+ TIMER_CALLBACK_MEMBER(baud_timer);
DECLARE_WRITE_LINE_MEMBER(keyin_w);
u8 dip0_r(offs_t offset);
@@ -72,54 +57,30 @@ private:
void mem_map(address_map &map);
+ required_device<cpu_device> m_maincpu;
+ required_device<z29_keyboard_port_device> m_keyboard;
+ required_device<r6545_1_device> m_crtc;
+ optional_device_array<i8251_device, 2> m_uart;
+ required_shared_ptr<u8> m_charram;
required_region_ptr<u8> m_charrom;
required_shared_ptr<u8> m_attrram;
required_ioport m_dip0;
- bool m_keyin;
- bool m_reverse;
-};
-
-class z22_state : public mdt60_base_state
-{
-public:
- z22_state(const machine_config &mconfig, device_type type, const char *tag)
- : mdt60_base_state(mconfig, type, tag)
- , m_eeprom(*this, "eeprom")
- , m_fontram(*this, "fontram")
- , m_eeprom_clk(false)
- {
- }
-
- void z22(machine_config &config);
-
-protected:
- virtual void machine_start() override;
-
-private:
- MC6845_UPDATE_ROW(update_row);
+ emu_timer *m_baud_timer;
- u8 status_r();
- void control_w(u8 data);
- DECLARE_WRITE_LINE_MEMBER(eeprom_clock_w);
-
- void mem_map(address_map &map);
-
- required_device<eeprom_serial_93cxx_device> m_eeprom;
- required_shared_ptr<u8> m_fontram;
-
- bool m_eeprom_clk;
+ bool m_keyin;
+ u8 m_output_reg;
+ bool m_timer_output;
};
void mdt60_state::machine_start()
{
- save_item(NAME(m_keyin));
- save_item(NAME(m_reverse));
-}
+ m_baud_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(mdt60_state::baud_timer), this));
+ m_baud_timer->adjust(attotime::zero);
-void z22_state::machine_start()
-{
- save_item(NAME(m_eeprom_clk));
+ save_item(NAME(m_keyin));
+ save_item(NAME(m_output_reg));
+ save_item(NAME(m_timer_output));
}
void mdt60_state::machine_reset()
@@ -128,6 +89,23 @@ void mdt60_state::machine_reset()
}
+TIMER_CALLBACK_MEMBER(mdt60_state::baud_timer)
+{
+ m_timer_output = !m_timer_output;
+
+ // LS352 multiplexer has inverting outputs
+ m_uart[0]->write_rxc(!m_timer_output);
+ m_uart[0]->write_txc(!m_timer_output);
+
+ constexpr auto time_base = 16.5888_MHz_XTAL / 9;
+ if ((m_output_reg & 0x06) == 0x00)
+ m_baud_timer->adjust(attotime::from_ticks(m_timer_output ? 2 : 4, time_base));
+ else if ((m_output_reg & 0x06) == 0x06)
+ m_baud_timer->adjust(attotime::from_ticks(48, time_base));
+ else
+ m_baud_timer->adjust(attotime::from_ticks(3 * (m_output_reg & 0x06), time_base));
+}
+
MC6845_UPDATE_ROW(mdt60_state::update_row)
{
u32 *pix = &bitmap.pix32(y);
@@ -147,7 +125,7 @@ MC6845_UPDATE_ROW(mdt60_state::update_row)
rgb_t fg = BIT(adata, 1) ? rgb_t::white() : rgb_t(0xc0, 0xc0, 0xc0);
rgb_t bg = rgb_t::black();
- if (m_reverse)
+ if (BIT(m_output_reg, 5))
std::swap(fg, bg);
for (int n = 8; n >= 0; n--)
@@ -155,27 +133,7 @@ MC6845_UPDATE_ROW(mdt60_state::update_row)
}
}
-MC6845_UPDATE_ROW(z22_state::update_row)
-{
- u32 *pix = &bitmap.pix32(y);
-
- for (unsigned x = 0; x < x_count; x++)
- {
- u8 cdata = m_charram[(ma + x) & 0x7ff];
- u16 dots = m_fontram[(cdata & 0x7f) << 4 | ra] << 1;
-
- if (x == cursor_x)
- dots = ~dots;
-
- rgb_t fg = rgb_t::white();
- rgb_t bg = rgb_t::black();
-
- for (int n = 8; n >= 0; n--)
- *pix++ = BIT(dots, n) ? fg : bg;
- }
-}
-
-MC6845_ON_UPDATE_ADDR_CHANGED(mdt60_base_state::update_cb)
+MC6845_ON_UPDATE_ADDR_CHANGED(mdt60_state::update_cb)
{
}
@@ -190,9 +148,9 @@ u8 mdt60_state::dip0_r(offs_t offset)
{
u8 buffer = 0xff;
if (!BIT(offset, 0))
- buffer &= m_dip0->read() | 0x80;
+ buffer &= m_dip0->read() >> 1 | 0x80;
if (!BIT(offset, 1))
- buffer &= m_dip0->read() >> 7 | 0xfe;
+ buffer &= m_dip0->read() | 0xfe;
if (!m_keyin)
buffer &= 0x7f;
return buffer;
@@ -200,29 +158,11 @@ u8 mdt60_state::dip0_r(offs_t offset)
void mdt60_state::reg_w(u8 data)
{
- //m_keyboard->keyout_w(BIT(data, 0));
- m_reverse = BIT(data, 5);
-}
+ if (BIT(data, 0) != BIT(m_output_reg, 0))
+ m_keyboard->keyout_w(BIT(data, 0));
-u8 z22_state::status_r()
-{
- u8 result = 0;
- if (m_eeprom_clk)
- result |= 0x02;
- if (!m_eeprom->do_read())
- result |= 0x01;
- return result;
-}
-
-void z22_state::control_w(u8 data)
-{
- m_eeprom->di_write(!BIT(data, 7));
- m_eeprom->cs_write(BIT(data, 6));
-}
-
-WRITE_LINE_MEMBER(z22_state::eeprom_clock_w)
-{
- m_eeprom_clk = state;
+ // Bits 1–2 & 3–4 select 1 of 4 baud rates for each UART; bit 5 selects inverse video
+ m_output_reg = data & 0x3f;
}
void mdt60_state::mem_map(address_map &map)
@@ -240,23 +180,9 @@ void mdt60_state::mem_map(address_map &map)
map(0xe000, 0xefff).mirror(0x1000).rom().region("coderom", 0);
}
-void z22_state::mem_map(address_map &map)
-{
- map(0x0000, 0x07ff).ram();
- map(0x2000, 0x27ff).ram().share("charram");
- map(0x4000, 0x4001).rw(m_uart[1], FUNC(i8251_device::read), FUNC(i8251_device::write));
- map(0x6000, 0x67ff).ram().share("fontram");
- map(0x8000, 0x8001).rw(m_uart[0], FUNC(i8251_device::read), FUNC(i8251_device::write));
- map(0x8800, 0x8800).rw(m_crtc, FUNC(r6545_1_device::status_r), FUNC(r6545_1_device::address_w));
- map(0x8801, 0x8801).rw(m_crtc, FUNC(r6545_1_device::register_r), FUNC(r6545_1_device::register_w));
- map(0x9000, 0x9003).w("pit", FUNC(pit8254_device::write));
- map(0xa000, 0xa000).rw(FUNC(z22_state::status_r), FUNC(z22_state::control_w));
- map(0xc000, 0xffff).rom().region("program", 0);
-}
-
static INPUT_PORTS_START(mdt60)
- PORT_START("DIP0") // TODO: verify bit assignments
+ PORT_START("DIP0")
PORT_DIPNAME(0x03, 0x01, "Baud Rate") PORT_DIPLOCATION("SW1:1,2")
PORT_DIPSETTING(0x03, "300")
PORT_DIPSETTING(0x02, "1200")
@@ -284,9 +210,6 @@ static INPUT_PORTS_START(mdt60)
PORT_BIT(0xff, 0xff, IPT_UNUSED) // SW2 is unpopulated
INPUT_PORTS_END
-static INPUT_PORTS_START(z22)
-INPUT_PORTS_END
-
// XTAL frequency is specified as 16.589 MHz on actual parts as well as in MDT 60 schematics.
// This has been assumed to be a lower-precision specification of the common 16.5888 MHz value.
@@ -297,71 +220,30 @@ void mdt60_state::mdt60(machine_config &config)
I8251(config, m_uart[0], 16.5888_MHz_XTAL / 9); // TMP8251AP (U19)
m_uart[0]->rxrdy_handler().set_inputline(m_maincpu, m6512_device::NMI_LINE);
- m_uart[0]->txd_handler().set("computer", FUNC(rs232_port_device::write_txd));
- m_uart[0]->dtr_handler().set("computer", FUNC(rs232_port_device::write_dtr));
- m_uart[0]->rts_handler().set("computer", FUNC(rs232_port_device::write_rts));
-
- // UART 1 (at U28) is unpopulated and not used by code
-
- screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
- screen.set_color(rgb_t::amber());
- screen.set_raw(16.5888_MHz_XTAL, 918, 0, 720, 301, 0, 288);
- screen.set_screen_update(m_crtc, FUNC(r6545_1_device::screen_update));
-
- R6545_1(config, m_crtc, 16.5888_MHz_XTAL / 9); // R6545-1AP
- m_crtc->set_screen("screen");
- m_crtc->set_show_border_area(false);
- m_crtc->set_char_width(9);
- m_crtc->set_update_row_callback(FUNC(mdt60_state::update_row));
- m_crtc->set_on_update_addr_change_callback(FUNC(mdt60_state::update_cb));
-
- rs232_port_device &computer(RS232_PORT(config, "computer", default_rs232_devices, nullptr));
- computer.rxd_handler().set(m_uart[0], FUNC(i8251_device::write_rxd));
- computer.dsr_handler().set(m_uart[0], FUNC(i8251_device::write_dsr));
- computer.cts_handler().set(m_uart[0], FUNC(i8251_device::write_cts));
-}
-
-void z22_state::z22(machine_config &config)
-{
- M6512(config, m_maincpu, 16.5888_MHz_XTAL / 9); // R6512AP
- m_maincpu->set_addrmap(AS_PROGRAM, &z22_state::mem_map);
-
- I8251(config, m_uart[0], 16.5888_MHz_XTAL / 9); // NEC D8251AC (U33) + Intel P8251A (U35)
- m_uart[0]->rxrdy_handler().set_inputline(m_maincpu, m6512_device::NMI_LINE);
m_uart[0]->txd_handler().set("comm", FUNC(rs232_port_device::write_txd));
m_uart[0]->dtr_handler().set("comm", FUNC(rs232_port_device::write_dtr));
m_uart[0]->rts_handler().set("comm", FUNC(rs232_port_device::write_rts));
- I8251(config, m_uart[1], 16.5888_MHz_XTAL / 9);
-
- EEPROM_93C06_16BIT(config, m_eeprom); // NMC9306 (U27)
+ // UART 1 (at U28) is unpopulated and not used by code
- pit8254_device &pit(PIT8254(config, "pit")); // Intel P8254
- pit.set_clk<0>(16.5888_MHz_XTAL / 9);
- pit.set_clk<1>(16.5888_MHz_XTAL / 9);
- pit.set_clk<2>(16.5888_MHz_XTAL / 9);
- pit.out_handler<0>().set(m_uart[1], FUNC(i8251_device::write_rxc));
- pit.out_handler<0>().append(m_uart[1], FUNC(i8251_device::write_txc));
- pit.out_handler<0>().append(m_eeprom, FUNC(eeprom_serial_93cxx_device::clk_write)); // weird synchronous clocking
- pit.out_handler<0>().append(FUNC(z22_state::eeprom_clock_w));
- pit.out_handler<1>().set(m_uart[0], FUNC(i8251_device::write_rxc));
- pit.out_handler<2>().set(m_uart[0], FUNC(i8251_device::write_txc)); // or the other way around?
+ Z29_KEYBOARD(config, m_keyboard, z29_keyboards, "md");
+ m_keyboard->keyin_callback().set(FUNC(mdt60_state::keyin_w)).invert();
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
screen.set_color(rgb_t::amber());
- screen.set_raw(16.5888_MHz_XTAL, 873, 0, 720, 317, 0, 300);
+ screen.set_raw(16.5888_MHz_XTAL, 918, 0, 720, 301, 0, 288);
screen.set_screen_update(m_crtc, FUNC(r6545_1_device::screen_update));
R6545_1(config, m_crtc, 16.5888_MHz_XTAL / 9); // R6545-1AP
m_crtc->set_screen("screen");
m_crtc->set_show_border_area(false);
m_crtc->set_char_width(9);
- m_crtc->set_update_row_callback(FUNC(z22_state::update_row));
- m_crtc->set_on_update_addr_change_callback(FUNC(z22_state::update_cb));
-
- // TODO: onboard buzzer
+ m_crtc->set_update_row_callback(FUNC(mdt60_state::update_row));
+ m_crtc->set_on_update_addr_change_callback(FUNC(mdt60_state::update_cb));
+ // LPEN is tied to GND (code uses this to determine CRTC type)
- rs232_port_device &comm(RS232_PORT(config, "comm", default_rs232_devices, nullptr));
+ rs232_port_device &comm(RS232_PORT(config, "comm", default_rs232_devices, "loopback"));
+ // Service Manual suggests shorting pins with a bent paper clip if no DB-25 loopback connector is available ;-)
comm.rxd_handler().set(m_uart[0], FUNC(i8251_device::write_rxd));
comm.dsr_handler().set(m_uart[0], FUNC(i8251_device::write_dsr));
comm.cts_handler().set(m_uart[0], FUNC(i8251_device::write_cts));
@@ -370,17 +252,11 @@ void z22_state::z22(machine_config &config)
ROM_START(mdt60)
ROM_REGION(0x1000, "coderom", 0)
+ // "ROM REV. 1.7 -- Copyright (C) 1983 by Morrow Designs, Inc."
ROM_LOAD("vb-rom_1.7_bcfd.u9", 0x0000, 0x1000, CRC(3902f7b3) SHA1(ee0ce7f68efe20efe1ab8a44888e276f08fe2d07))
ROM_REGION(0x1000, "charrom", 0)
ROM_LOAD("char_gen_b207.u6", 0x0000, 0x1000, CRC(b19432da) SHA1(fa73641c08b778f19a17676a7f4074f69b7b55dd))
ROM_END
-ROM_START(z22)
- ROM_REGION(0x4000, "program", 0)
- ROM_LOAD("u39.bin", 0x0000, 0x2000, CRC(2f62c1f8) SHA1(448581d987fee6b4303e481e78f46d3255baccbb)) // D2764A-3
- ROM_LOAD("u38.bin", 0x2000, 0x2000, CRC(f0bfe9b5) SHA1(8807841b28549d0ddf30275fc6035a66093f8768)) // D2764A-3
-ROM_END
-
-SYST(1983, mdt60, 0, 0, mdt60, mdt60, mdt60_state, empty_init, "Morrow", "MDT 60 Video Display Terminal", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
-SYST(1984, z22, 0, 0, z22, z22, z22_state, empty_init, "Zenith Data Systems", "Z-22 Terminal", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
+SYST(1983, mdt60, 0, 0, mdt60, mdt60, mdt60_state, empty_init, "Morrow Designs", "MDT 60 Video Display Terminal", MACHINE_SUPPORTS_SAVE)
diff --git a/src/mame/drivers/z22.cpp b/src/mame/drivers/z22.cpp
new file mode 100644
index 00000000000..7421bf9ad16
--- /dev/null
+++ b/src/mame/drivers/z22.cpp
@@ -0,0 +1,215 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/**************************************************************************
+
+ Skeleton driver for Zenith Z-22 terminal.
+
+ Despite featuring much of the same hardware as the MDT 60, with the
+ CPU, CRTC and UART types and even dot clock frequency being identical,
+ much else is different: a serial EEPROM replaces DIP switches, an 8254
+ generates baud rates, fonts are uploaded to RAM, and the serial
+ keyboard protocol is incompatible.
+
+**************************************************************************/
+
+#include "emu.h"
+#include "bus/rs232/rs232.h"
+#include "cpu/m6502/m6502.h"
+#include "machine/eepromser.h"
+#include "machine/i8251.h"
+#include "machine/pit8253.h"
+#include "video/mc6845.h"
+#include "screen.h"
+
+class z22_state : public driver_device
+{
+public:
+ z22_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_uart(*this, "uart%u", 0U)
+ , m_eeprom(*this, "eeprom")
+ , m_dispram(*this, "dispram")
+ , m_fontram(*this, "fontram")
+ , m_eeprom_clk(false)
+ {
+ }
+
+ void z22(machine_config &config);
+
+protected:
+ virtual void machine_start() override;
+ virtual void machine_reset() override;
+
+private:
+ MC6845_UPDATE_ROW(update_row);
+ MC6845_ON_UPDATE_ADDR_CHANGED(update_cb);
+
+ u8 irq_ack_r();
+ u8 status_r();
+ void control_w(u8 data);
+
+ DECLARE_WRITE_LINE_MEMBER(eeprom_clock_w);
+
+ void mem_map(address_map &map);
+
+ required_device<cpu_device> m_maincpu;
+ required_device<r6545_1_device> m_crtc;
+ optional_device_array<i8251_device, 2> m_uart;
+ required_device<eeprom_serial_93cxx_device> m_eeprom;
+ required_shared_ptr<u8> m_dispram;
+ required_shared_ptr<u8> m_fontram;
+
+ bool m_eeprom_clk;
+};
+
+void z22_state::machine_start()
+{
+ save_item(NAME(m_eeprom_clk));
+}
+
+void z22_state::machine_reset()
+{
+ control_w(0);
+}
+
+
+MC6845_UPDATE_ROW(z22_state::update_row)
+{
+ u32 *pix = &bitmap.pix32(y);
+
+ for (unsigned x = 0; x < x_count; x++)
+ {
+ u8 cdata = m_dispram[(ma + x) & 0x7ff];
+ u16 dots = m_fontram[(cdata & 0x7f) << 4 | ra] << 1;
+
+ if (x == cursor_x)
+ dots = ~dots;
+
+ rgb_t fg = rgb_t::white();
+ rgb_t bg = rgb_t::black();
+
+ for (int n = 8; n >= 0; n--)
+ *pix++ = BIT(dots, n) ? fg : bg;
+ }
+}
+
+MC6845_ON_UPDATE_ADDR_CHANGED(z22_state::update_cb)
+{
+}
+
+
+u8 z22_state::irq_ack_r()
+{
+ if (!machine().side_effects_disabled())
+ m_maincpu->set_input_line(m6512_device::IRQ_LINE, CLEAR_LINE);
+ return 0xff;
+}
+
+u8 z22_state::status_r()
+{
+ u8 result = 0;
+ if (!m_eeprom->do_read())
+ result |= 0x01;
+ if (m_eeprom_clk)
+ result |= 0x02;
+ // TODO: bit 7 = received keyboard data
+ return result;
+}
+
+void z22_state::control_w(u8 data)
+{
+ m_eeprom->di_write(!BIT(data, 7));
+ m_eeprom->cs_write(BIT(data, 6));
+ //m_keyboard->keyout_w(BIT(data, 0));
+}
+
+WRITE_LINE_MEMBER(z22_state::eeprom_clock_w)
+{
+ m_eeprom_clk = state;
+ if (state)
+ m_maincpu->set_input_line(m6512_device::IRQ_LINE, ASSERT_LINE);
+}
+
+void z22_state::mem_map(address_map &map)
+{
+ map(0x0000, 0x07ff).ram();
+ map(0x2000, 0x27ff).ram().share("dispram");
+ map(0x4000, 0x4001).rw(m_uart[1], FUNC(i8251_device::read), FUNC(i8251_device::write));
+ map(0x6000, 0x67ff).ram().share("fontram");
+ map(0x8000, 0x8001).rw(m_uart[0], FUNC(i8251_device::read), FUNC(i8251_device::write));
+ map(0x8800, 0x8800).rw(m_crtc, FUNC(r6545_1_device::status_r), FUNC(r6545_1_device::address_w));
+ map(0x8801, 0x8801).rw(m_crtc, FUNC(r6545_1_device::register_r), FUNC(r6545_1_device::register_w));
+ map(0x9000, 0x9003).w("pit", FUNC(pit8254_device::write));
+ map(0x9800, 0x9800).r(FUNC(z22_state::irq_ack_r));
+ map(0xa000, 0xa000).rw(FUNC(z22_state::status_r), FUNC(z22_state::control_w));
+ map(0xc000, 0xffff).rom().region("program", 0);
+}
+
+
+static INPUT_PORTS_START(z22)
+INPUT_PORTS_END
+
+// XTAL frequency is specified as 16.589 MHz on actual parts. As with the MDT 60, this
+// has been assumed to be a lower-precision specification of the common 16.5888 MHz value.
+
+void z22_state::z22(machine_config &config)
+{
+ M6512(config, m_maincpu, 16.5888_MHz_XTAL / 9); // R6512AP
+ m_maincpu->set_addrmap(AS_PROGRAM, &z22_state::mem_map);
+
+ I8251(config, m_uart[0], 16.5888_MHz_XTAL / 9); // NEC D8251AC (U33) + Intel P8251A (U35)
+ m_uart[0]->rxrdy_handler().set_inputline(m_maincpu, m6512_device::NMI_LINE);
+ m_uart[0]->txd_handler().set("comm", FUNC(rs232_port_device::write_txd));
+ m_uart[0]->dtr_handler().set("comm", FUNC(rs232_port_device::write_dtr));
+ m_uart[0]->rts_handler().set("comm", FUNC(rs232_port_device::write_rts));
+
+ I8251(config, m_uart[1], 16.5888_MHz_XTAL / 9);
+ m_uart[1]->txd_handler().set("printer", FUNC(rs232_port_device::write_txd));
+
+ EEPROM_93C06_16BIT(config, m_eeprom); // NMC9306 (U27)
+
+ pit8254_device &pit(PIT8254(config, "pit")); // Intel P8254
+ pit.set_clk<0>(16.5888_MHz_XTAL / 9);
+ pit.set_clk<1>(16.5888_MHz_XTAL / 9);
+ pit.set_clk<2>(16.5888_MHz_XTAL / 9);
+ pit.out_handler<0>().set(m_eeprom, FUNC(eeprom_serial_93cxx_device::clk_write)); // weird synchronous clocking
+ pit.out_handler<0>().append(FUNC(z22_state::eeprom_clock_w));
+ pit.out_handler<1>().set(m_uart[0], FUNC(i8251_device::write_rxc));
+ pit.out_handler<2>().set(m_uart[0], FUNC(i8251_device::write_txc)); // or the other way around?
+ pit.out_handler<2>().append(m_uart[1], FUNC(i8251_device::write_txc));
+
+ // TODO: Keyboard (asynchronous serial, like Z-49?)
+
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.set_color(rgb_t::amber());
+ screen.set_raw(16.5888_MHz_XTAL, 873, 0, 720, 317, 0, 300);
+ screen.set_screen_update(m_crtc, FUNC(r6545_1_device::screen_update));
+
+ R6545_1(config, m_crtc, 16.5888_MHz_XTAL / 9); // R6545-1AP
+ m_crtc->set_screen("screen");
+ m_crtc->set_show_border_area(false);
+ m_crtc->set_char_width(9);
+ m_crtc->set_update_row_callback(FUNC(z22_state::update_row));
+ m_crtc->set_on_update_addr_change_callback(FUNC(z22_state::update_cb));
+
+ // TODO: onboard buzzer
+
+ rs232_port_device &comm(RS232_PORT(config, "comm", default_rs232_devices, nullptr));
+ comm.rxd_handler().set(m_uart[0], FUNC(i8251_device::write_rxd));
+ comm.dsr_handler().set(m_uart[0], FUNC(i8251_device::write_dsr));
+ comm.cts_handler().set(m_uart[0], FUNC(i8251_device::write_cts));
+
+ rs232_port_device &printer(RS232_PORT(config, "printer", default_rs232_devices, nullptr));
+ printer.dsr_handler().set(m_uart[1], FUNC(i8251_device::write_dsr));
+}
+
+
+ROM_START(z22)
+ ROM_REGION(0x4000, "program", 0)
+ ROM_LOAD("u39.bin", 0x0000, 0x2000, CRC(2f62c1f8) SHA1(448581d987fee6b4303e481e78f46d3255baccbb)) // D2764A-3
+ ROM_LOAD("u38.bin", 0x2000, 0x2000, CRC(f0bfe9b5) SHA1(8807841b28549d0ddf30275fc6035a66093f8768)) // D2764A-3
+ROM_END
+
+SYST(1984, z22, 0, 0, z22, z22, z22_state, empty_init, "Zenith Data Systems", "Z-22 Terminal", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
diff --git a/src/mame/drivers/z29.cpp b/src/mame/drivers/z29.cpp
index b491c3abe06..37098f75af6 100644
--- a/src/mame/drivers/z29.cpp
+++ b/src/mame/drivers/z29.cpp
@@ -8,8 +8,8 @@
#include "emu.h"
//#include "bus/rs232/rs232.h"
+#include "bus/z29_kbd/keyboard.h"
#include "cpu/mcs51/mcs51.h"
-#include "cpu/mcs48/mcs48.h"
#include "machine/x2212.h"
#include "video/i8275.h"
#include "screen.h"
@@ -20,11 +20,14 @@ public:
z29_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_maincpu(*this, "maincpu")
+ , m_keyboard(*this, "keyboard")
, m_crtc(*this, "crtc%u", 1U)
, m_nvram(*this, "nvram")
, m_charmem(*this, "charmem")
, m_attrmem(*this, "attrmem")
, m_chargen(*this, "chargen")
+ , m_dmatype(true)
+ , m_keyin(true)
{
}
@@ -34,8 +37,10 @@ protected:
virtual void machine_start() override;
private:
+ DECLARE_WRITE_LINE_MEMBER(keyin_w);
+ u8 p1_r();
void p3_w(u8 data);
- DECLARE_READ8_MEMBER(bs_24k_r);
+ u8 bs_24k_r(offs_t offset);
void crtc_w(offs_t offset, u8 data);
void latch_12k_w(u8 data);
@@ -43,6 +48,7 @@ private:
void ext_map(address_map &map);
required_device<mcs51_cpu_device> m_maincpu;
+ required_device<z29_keyboard_port_device> m_keyboard;
required_device_array<i8276_device, 2> m_crtc;
required_device<x2210_device> m_nvram;
@@ -51,11 +57,23 @@ private:
required_region_ptr<u8> m_chargen;
bool m_dmatype;
+ bool m_keyin;
};
void z29_state::machine_start()
{
save_item(NAME(m_dmatype));
+ save_item(NAME(m_keyin));
+}
+
+WRITE_LINE_MEMBER(z29_state::keyin_w)
+{
+ m_keyin = state;
+}
+
+u8 z29_state::p1_r()
+{
+ return m_keyin ? 0xfd : 0xff;
}
void z29_state::p3_w(u8 data)
@@ -63,7 +81,7 @@ void z29_state::p3_w(u8 data)
m_dmatype = BIT(data, 4);
}
-READ8_MEMBER(z29_state::bs_24k_r)
+u8 z29_state::bs_24k_r(offs_t offset)
{
if (!machine().side_effects_disabled())
{
@@ -122,11 +140,16 @@ void z29_state::z29(machine_config &config)
I8031(config, m_maincpu, 14.784_MHz_XTAL / 2); // Intel P8031AH
m_maincpu->set_addrmap(AS_PROGRAM, &z29_state::prg_map);
m_maincpu->set_addrmap(AS_IO, &z29_state::ext_map);
- m_maincpu->port_in_cb<1>().set_constant(0xfd); // hack around keyboard not working
+ m_maincpu->port_in_cb<1>().set(FUNC(z29_state::p1_r));
+ m_maincpu->port_out_cb<1>().set(m_keyboard, FUNC(z29_keyboard_port_device::keyout_w)).bit(0).invert();
m_maincpu->port_out_cb<3>().set(FUNC(z29_state::p3_w));
X2210(config, m_nvram);
+ Z29_KEYBOARD(config, m_keyboard, z29_keyboards, /*"heath"*/ "md");
+ m_keyboard->keyin_callback().set(FUNC(z29_state::keyin_w));
+ m_keyboard->reset_callback().set_inputline(m_maincpu, INPUT_LINE_RESET).invert();
+
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
screen.set_raw(14.784_MHz_XTAL, 880, 0, 640, 280, 0, 250);
screen.set_screen_update("crtc1", FUNC(i8276_device::screen_update));
@@ -136,8 +159,6 @@ void z29_state::z29(machine_config &config)
m_crtc[0]->irq_wr_callback().set_inputline(m_maincpu, MCS51_INT1_LINE);
I8276(config, m_crtc[1], 14.784_MHz_XTAL / 8).set_character_width(8);
-
- I8021(config, "kbdmcu", 3.579545_MHz_XTAL).set_disable();
}
@@ -148,9 +169,6 @@ ROM_START(z29) // All EPROMs on 85-2835-1 terminal board are HN482732AG-30
ROM_REGION(0x1000, "chargen", 0)
ROM_LOAD("u429.bin", 0x0000, 0x1000, CRC(5e3bc5bf) SHA1(18d73e3d74a9768bee8b063ea45891f955558ae7))
-
- ROM_REGION(0x400, "kbdmcu", 0)
- ROM_LOAD("444-100.bin", 0x000, 0x400, NO_DUMP)
ROM_END
diff --git a/src/mame/mame.lst b/src/mame/mame.lst
index 89dc8475b88..76cb5890925 100644
--- a/src/mame/mame.lst
+++ b/src/mame/mame.lst
@@ -21873,7 +21873,6 @@ fl100 // (c) 198? Grundig
@source:mdt60.cpp
mdt60 //
-z22 //
@source:meadows.cpp
bowl3d // [1978?]
@@ -41792,6 +41791,9 @@ z1013k69 //
z1013k76 //
z1013s60 //
+@source:z22.cpp
+z22 //
+
@source:z29.cpp
z29 //
diff --git a/src/mame/mess.flt b/src/mame/mess.flt
index 147370eecfa..299c05b17c8 100644
--- a/src/mame/mess.flt
+++ b/src/mame/mess.flt
@@ -1075,6 +1075,7 @@ ymtx81z.cpp
ymvl70.cpp
z100.cpp
z1013.cpp
+z22.cpp
z29.cpp
z80dev.cpp
z80ne.cpp