summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/trainer/mk14.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/trainer/mk14.cpp')
-rw-r--r--src/mame/trainer/mk14.cpp475
1 files changed, 475 insertions, 0 deletions
diff --git a/src/mame/trainer/mk14.cpp b/src/mame/trainer/mk14.cpp
new file mode 100644
index 00000000000..24723af302d
--- /dev/null
+++ b/src/mame/trainer/mk14.cpp
@@ -0,0 +1,475 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic, Robbbert
+/*********************************************************************************************************************************
+
+Science of Cambridge MK-14
+
+2009-11-20 Skeleton driver.
+2016-08-21 Working
+
+Keys:
+
+UP: MEM increments the currently displayed address, (and goes into data entry mode in V1 bios).
+= : TERM changes to "data entry" mode. In this mode, entering hex digits will change the byte at the currently displayed address
+- : ABORT changes to "address entry" mode. In this mode, entering hex digits will change the address.
+X : GO runs the program from the currently displayed address. On exit, the instruction after the program is displayed
+
+Pasting:
+ 0-F : as is
+ MEM : ^
+ TERM: =
+ AB : -
+ GO : X
+
+Example program: ("organ" from p82 of the manual)
+-F20=C4^0D^35^C4^00^31^C4^08^C8^F6^C5^01^E4^FF^98^08^8F^00^06^E4^07^07^90^EB^B8^E6^9C^EE^90^E5^-F20X
+Pressing keys will produce different tones.
+
+*********************************************************************************************************************************/
+
+#include "emu.h"
+
+#include "cpu/scmp/scmp.h"
+#include "imagedev/cassette.h"
+#include "imagedev/snapquik.h"
+#include "machine/ins8154.h"
+#include "sound/dac.h"
+#include "video/pwm.h"
+
+#include "emupal.h"
+#include "screen.h"
+#include "softlist_dev.h"
+#include "speaker.h"
+
+#include "mk14.lh"
+#include "mk14vdu.lh"
+
+namespace {
+
+class mk14_state : public driver_device
+{
+public:
+ mk14_state(const machine_config &mconfig, device_type type, const char *tag)
+ : driver_device(mconfig, type, tag)
+ , m_maincpu(*this, "maincpu")
+ , m_cass(*this, "cassette")
+ , m_dac(*this, "dac")
+ , m_display(*this, "display")
+ , m_io_keyboard(*this, "X%u", 0U)
+ { }
+
+ void mk14(machine_config &config);
+
+protected:
+ uint8_t keyboard_r(offs_t offset);
+ void display_w(offs_t offset, uint8_t data);
+ void port_a_w(uint8_t data);
+ void cass_w(int state);
+ int cass_r();
+ void mk14_map(address_map &map) ATTR_COLD;
+
+ DECLARE_QUICKLOAD_LOAD_MEMBER(quickload_cb);
+
+ required_device<scmp_device> m_maincpu;
+ required_device<cassette_image_device> m_cass;
+ required_device<dac_bit_interface> m_dac;
+ required_device<pwm_display_device> m_display;
+ required_ioport_array<8> m_io_keyboard;
+};
+
+class mk14vdu_state : public mk14_state
+{
+public:
+ mk14vdu_state(const machine_config &mconfig, device_type type, const char *tag)
+ : mk14_state(mconfig, type, tag)
+ , m_screen(*this, "screen")
+ , m_palette(*this, "palette")
+ , m_chargen(*this, "chargen")
+ , m_cfg_ps(*this, "CFG_PS")
+ , m_cfg_vdu(*this, "CFG_VDU")
+ { }
+
+ void mk14vdu(machine_config &config);
+
+private:
+ void mk14vdu_map(address_map &map) ATTR_COLD;
+
+ uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+ void draw_page_character(int page, uint16_t addr, int invert, bitmap_rgb32 &bitmap);
+ void draw_page_graphics(int page, uint16_t addr, int invert, bitmap_rgb32 &bitmap);
+
+ required_device<screen_device> m_screen;
+ required_device<palette_device> m_palette;
+ required_region_ptr<uint8_t> m_chargen;
+ required_ioport m_cfg_ps;
+ required_ioport m_cfg_vdu;
+};
+
+/*
+000-1FF 512 byte SCIOS ROM Decoded by 0xxx
+200-3FF ROM Shadow / Expansion RAM
+400-5FF ROM Shadow / Expansion RAM
+600-7FF ROM Shadow / Expansion RAM
+800-87F I/O Ports Decoded by 1xx0
+880-8FF 128 bytes I/O chip RAM Decoded by 1xx0
+900-9FF Keyboard & Display Decoded by 1x01
+A00-AFF I/O Port & RAM Shadow
+B00-BFF 256 bytes RAM (Extended) / VDU RAM Decoded by 1011
+C00-CFF I/O Port & RAM Shadow
+D00-DFF Keyboard & Display Shadow
+E00-EFF I/O Port & RAM Shadow
+F00-FFF 256 bytes RAM (Standard) / VDU RAM Decoded by 1111
+*/
+
+
+uint8_t mk14_state::keyboard_r(offs_t offset)
+{
+ if (offset < 8)
+ return m_io_keyboard[offset]->read();
+ else
+ return 0xff;
+}
+
+void mk14_state::display_w(offs_t offset, uint8_t data)
+{
+ if (offset < 8 )
+ m_display->matrix(1 << offset, data);
+}
+
+void mk14_state::mk14_map(address_map &map)
+{
+ map.unmap_value_high();
+ map.global_mask(0x0fff);
+ map(0x000, 0x1ff).mirror(0x600).rom(); // ROM
+ map(0x800, 0x87f).mirror(0x600).rw("ic8", FUNC(ins8154_device::read_io), FUNC(ins8154_device::write_io)); // I/O
+ map(0x880, 0x8ff).mirror(0x600).rw("ic8", FUNC(ins8154_device::read_ram), FUNC(ins8154_device::write_ram)); // 128 bytes I/O chip RAM
+ map(0x900, 0x9ff).mirror(0x400).rw(FUNC(mk14_state::keyboard_r), FUNC(mk14_state::display_w));
+ map(0xb00, 0xbff).ram(); // VDU RAM
+ map(0xf00, 0xfff).ram(); // Standard RAM
+}
+
+void mk14vdu_state::mk14vdu_map(address_map &map)
+{
+ mk14_map(map);
+ map(0x200, 0x7ff).ram(); // Expansion RAM
+}
+
+/* Input ports */
+static INPUT_PORTS_START( mk14 )
+ PORT_START("X0")
+ PORT_BIT(0x0f, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A) PORT_CHAR('A')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("8") PORT_CODE(KEYCODE_8) PORT_CHAR('8')
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("0") PORT_CODE(KEYCODE_0) PORT_CHAR('0')
+ PORT_START("X1")
+ PORT_BIT(0x0f, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B) PORT_CHAR('B')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("9") PORT_CODE(KEYCODE_9) PORT_CHAR('9')
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("1") PORT_CODE(KEYCODE_1) PORT_CHAR('1')
+ PORT_START("X2")
+ PORT_BIT(0x0f, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C") PORT_CODE(KEYCODE_C) PORT_CHAR('C')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("GO") PORT_CODE(KEYCODE_X) PORT_CHAR('X')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("2") PORT_CODE(KEYCODE_2) PORT_CHAR('2')
+ PORT_START("X3")
+ PORT_BIT(0x0f, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D") PORT_CODE(KEYCODE_D) PORT_CHAR('D')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("MEM") PORT_CODE(KEYCODE_UP) PORT_CHAR('^')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("3") PORT_CODE(KEYCODE_3) PORT_CHAR('3')
+ PORT_START("X4")
+ PORT_BIT(0x0f, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("ABORT") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("4") PORT_CODE(KEYCODE_4) PORT_CHAR('4')
+ PORT_START("X5")
+ PORT_BIT(0x0f, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("5") PORT_CODE(KEYCODE_5) PORT_CHAR('5')
+ PORT_START("X6")
+ PORT_BIT(0x0f, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E") PORT_CODE(KEYCODE_E) PORT_CHAR('E')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("6") PORT_CODE(KEYCODE_6) PORT_CHAR('6')
+ PORT_START("X7")
+ PORT_BIT(0x0f, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F) PORT_CHAR('F')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("TERM") PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("7") PORT_CODE(KEYCODE_7) PORT_CHAR('7')
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( mk14vdu )
+ PORT_INCLUDE(mk14)
+
+ PORT_START("CFG_PS")
+ PORT_CONFNAME(0x0f, 0x02, "Page Select")
+ PORT_CONFSETTING(0x00, "000")
+ PORT_CONFSETTING(0x01, "100")
+ PORT_CONFSETTING(0x02, "200")
+ PORT_CONFSETTING(0x03, "300")
+ PORT_CONFSETTING(0x04, "400")
+ PORT_CONFSETTING(0x05, "500")
+ PORT_CONFSETTING(0x06, "600")
+ PORT_CONFSETTING(0x07, "700")
+ PORT_CONFSETTING(0x08, "800")
+ PORT_CONFSETTING(0x09, "900")
+ PORT_CONFSETTING(0x0a, "A00")
+ PORT_CONFSETTING(0x0b, "B00")
+ PORT_CONFSETTING(0x0c, "C00")
+ PORT_CONFSETTING(0x0d, "D00")
+ PORT_CONFSETTING(0x0e, "E00")
+ PORT_CONFSETTING(0x0f, "F00")
+ PORT_CONFNAME(0xf0, 0x10, "Top Page > Page Select")
+ PORT_CONFSETTING(0x00, "None")
+ PORT_CONFSETTING(0x10, "PS1")
+ PORT_CONFSETTING(0x20, "PS2")
+ PORT_CONFSETTING(0x40, "PS3")
+ PORT_CONFSETTING(0x80, "PS4")
+ PORT_START("CFG_VDU")
+ PORT_CONFNAME(0x01, 0x01, "Reverse Pages")
+ PORT_CONFSETTING(0x00, DEF_STR( Yes ))
+ PORT_CONFSETTING(0x01, DEF_STR( No ))
+ PORT_CONFNAME(0x22, 0x00, "Video Mode")
+ PORT_CONFSETTING(0x00, "Character (Low)" )
+ PORT_CONFSETTING(0x02, "Graphics (High)" )
+ PORT_CONFSETTING(0x20, "Mixed (Top Page)" )
+ PORT_CONFNAME(0x44, 0x04, "Invert Video")
+ PORT_CONFSETTING(0x00, "Inverted (Low)" )
+ PORT_CONFSETTING(0x04, "Normal (High)")
+ PORT_CONFSETTING(0x40, "Mixed (Top Page)" )
+INPUT_PORTS_END
+
+void mk14_state::port_a_w(uint8_t data)
+{
+}
+
+void mk14_state::cass_w(int state)
+{
+ m_cass->output(state ? -1.0 : +1.0);
+ m_dac->write(state);
+}
+
+int mk14_state::cass_r()
+{
+ return (m_cass->input() > 0.03) ? 1 : 0;
+}
+
+//-------------------------------------------------
+// gfx_layout acorn_vdu80_charlayout
+//-------------------------------------------------
+
+static const gfx_layout mk14vdu_charlayout =
+{
+ 5, 7, /* 5 x 7 characters */
+ 64, /* 64 characters */
+ 1, /* 1 bits per pixel */
+ { 0 }, /* no bitplanes */
+ /* x offsets */
+ { 3, 4, 5, 6, 7 },
+ /* y offsets */
+ { 0 * 8, 1 * 8, 2 * 8, 3 * 8, 4 * 8, 5 * 8, 6 * 8 },
+ 8 * 8 /* every char takes 8 bytes */
+};
+
+//-------------------------------------------------
+// GFXDECODE( gfx_mk14vdu )
+//-------------------------------------------------
+
+static GFXDECODE_START(gfx_mk14vdu)
+ GFXDECODE_ENTRY("chargen", 0, mk14vdu_charlayout, 0, 1)
+GFXDECODE_END
+
+uint32_t mk14vdu_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
+ for (int page = 0; page < 2; page++)
+ {
+ // top page adjusted with reverse pages
+ bool top_page = BIT(m_cfg_vdu->read(), 0) ? (page == 1) : (page == 0);
+
+ // page select
+ uint16_t addr = BIT(m_cfg_ps->read(), 0, 4) << 8;
+ if (top_page)
+ addr |= (BIT(m_cfg_ps->read(), 4, 4) << 8);
+
+ // invert video
+ int invert = BIT(m_cfg_vdu->read(), 6) ? !top_page : !BIT(m_cfg_vdu->read(), 2);
+
+ // character/graphic mode
+ if (BIT(m_cfg_vdu->read(), 5) ? top_page : BIT(m_cfg_vdu->read(), 1))
+ draw_page_graphics(page, addr, invert, bitmap);
+ else
+ draw_page_character(page, addr, invert, bitmap);
+ }
+ return 0;
+}
+
+void mk14vdu_state::draw_page_character(int page, uint16_t addr, int invert, bitmap_rgb32 &bitmap)
+{
+ address_space &space = m_maincpu->space(AS_PROGRAM);
+
+ const pen_t *pens = m_palette->pens();
+
+ for (int y = 0; y < 128; y++)
+ {
+ uint16_t videoram_addr = addr + ((y >> 3) * 16);
+
+ int x = 0;
+
+ for (int sx = 0; sx < 16; sx++)
+ {
+ uint8_t videoram_data = space.read_byte(videoram_addr++);
+ uint16_t const charrom_addr = ((videoram_data & 0x3f) << 3) | (y % 8);
+ uint8_t charrom_data = m_chargen[charrom_addr];
+
+ for (int bit = 0; bit < 8; bit++)
+ {
+ // invert single character (implemented in some replica boards)
+ int color = BIT(charrom_data, 6) ^ invert ^ BIT(videoram_data, 7);
+ bitmap.pix(y + (page * 128), x++) = pens[color];
+ charrom_data <<= 1;
+ }
+ }
+ }
+}
+
+void mk14vdu_state::draw_page_graphics(int page, uint16_t addr, int invert, bitmap_rgb32 &bitmap)
+{
+ address_space &space = m_maincpu->space(AS_PROGRAM);
+
+ const pen_t *pens = m_palette->pens();
+
+ for (int y = 0; y < 128; y++)
+ {
+ uint16_t videoram_addr = addr + ((y >> 2) * 8);
+
+ int x = 0;
+
+ for (int sx = 0; sx < 8; sx++)
+ {
+ uint8_t videoram_data = space.read_byte(videoram_addr++);
+
+ for (int bit = 0; bit < 8; bit++)
+ {
+ int color = BIT(videoram_data, 7) ^ invert;
+ bitmap.pix(y + (page * 128), x++) = pens[color];
+ bitmap.pix(y + (page * 128), x++) = pens[color];
+ videoram_data <<= 1;
+ }
+ }
+ }
+}
+
+QUICKLOAD_LOAD_MEMBER(mk14_state::quickload_cb)
+{
+ if (image.software_entry() == nullptr)
+ return std::make_pair(image_error::UNSUPPORTED, "Unsupported quickload format");
+
+ uint16_t const size = image.length();
+ int load_addr, exec_addr;
+ sscanf(image.get_feature("load"), "%x", &load_addr);
+ sscanf(image.get_feature("exec"), "%x", &exec_addr);
+
+ for (uint16_t i = 0; i < size; i++)
+ {
+ uint8_t data;
+
+ if (image.fread(&data, 1) != 1)
+ return std::make_pair(image_error::UNSPECIFIED, std::string());
+ m_maincpu->space(AS_PROGRAM).write_byte(load_addr + i, data);
+ }
+
+ m_maincpu->set_pc(exec_addr);
+
+ return std::make_pair(std::error_condition(), std::string());
+}
+
+void mk14_state::mk14(machine_config &config)
+{
+ // IC1 1SP-8A/600 (8060) SC/MP Microprocessor
+ INS8060(config, m_maincpu, 4.433619_MHz_XTAL / 2);
+ m_maincpu->flag_out().set(FUNC(mk14_state::cass_w));
+ m_maincpu->s_out().set_nop();
+ m_maincpu->s_in().set(FUNC(mk14_state::cass_r));
+ m_maincpu->sense_a().set_constant(0);
+ m_maincpu->sense_b().set(FUNC(mk14_state::cass_r));
+ m_maincpu->halt().set_nop();
+ m_maincpu->set_addrmap(AS_PROGRAM, &mk14_state::mk14_map);
+
+ config.set_default_layout(layout_mk14);
+ PWM_DISPLAY(config, m_display).set_size(8, 8);
+ m_display->set_segmask(0xff, 0xff);
+
+ SPEAKER(config, "speaker").front_center();
+ DAC_1BIT(config, m_dac, 0).add_route(ALL_OUTPUTS, "speaker", 0.25);
+ ZN425E(config, "dac8", 0).add_route(ALL_OUTPUTS, "speaker", 0.5); // Ferranti ZN425E
+
+ ins8154_device &ic8(INS8154(config, "ic8"));
+ ic8.out_a().set(FUNC(mk14_state::port_a_w));
+ ic8.out_b().set("dac8", FUNC(dac_byte_interface::data_w));
+
+ CASSETTE(config, m_cass);
+ m_cass->set_default_state(CASSETTE_STOPPED | CASSETTE_SPEAKER_ENABLED | CASSETTE_MOTOR_ENABLED);
+ m_cass->add_route(ALL_OUTPUTS, "speaker", 0.05);
+
+ quickload_image_device &quickload(QUICKLOAD(config, "quickload", "bin"));
+ quickload.set_load_callback(FUNC(mk14_state::quickload_cb));
+ quickload.set_interface("mk14_quik");
+
+ SOFTWARE_LIST(config, "quik_ls").set_original("mk14_quik");
+}
+
+void mk14vdu_state::mk14vdu(machine_config &config)
+{
+ mk14(config);
+
+ m_maincpu->set_clock(4_MHz_XTAL / 2);
+ m_maincpu->set_addrmap(AS_PROGRAM, &mk14vdu_state::mk14vdu_map);
+
+ SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
+ m_screen->set_raw(4_MHz_XTAL, 256, 0, 128, 312, 0, 256);
+ m_screen->set_screen_update(FUNC(mk14vdu_state::screen_update));
+ config.set_default_layout(layout_mk14vdu);
+
+ GFXDECODE(config, "gfxdecode", m_palette, gfx_mk14vdu);
+ PALETTE(config, m_palette, palette_device::MONOCHROME);
+
+ subdevice<software_list_device>("quik_ls")->set_filter("VDU");
+}
+
+/* ROM definition */
+ROM_START( mk14 )
+ ROM_REGION( 0x200, "maincpu", 0 )
+ // IC2,3 74S571 512 x 4 bit ROM
+ ROM_DEFAULT_BIOS("v2")
+ ROM_SYSTEM_BIOS(0, "v2", "SCIOS V2")
+ ROMX_LOAD( "scios_v2.bin", 0x0000, 0x0200, CRC(8b667daa) SHA1(802dc637ce5391a2a6627f76f919b12a869b56ef), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "v1", "SCIOS V1")
+ ROMX_LOAD( "scios_v1.bin", 0x0000, 0x0200, CRC(3d2477e7) SHA1(795829a2025e24d87a413e245d72a284f872e0db), ROM_BIOS(1))
+ROM_END
+
+ROM_START( mk14vdu )
+ ROM_REGION( 0x200, "maincpu", 0 )
+ // IC2,3 74S571 512 x 4 bit ROM
+ ROM_DEFAULT_BIOS("v2")
+ ROM_SYSTEM_BIOS(0, "v2", "SCIOS V2")
+ ROMX_LOAD( "scios_v2.bin", 0x0000, 0x0200, CRC(8b667daa) SHA1(802dc637ce5391a2a6627f76f919b12a869b56ef), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "v1", "SCIOS V1")
+ ROMX_LOAD( "scios_v1.bin", 0x0000, 0x0200, CRC(3d2477e7) SHA1(795829a2025e24d87a413e245d72a284f872e0db), ROM_BIOS(1))
+
+ ROM_REGION( 0x200, "chargen", 0 )
+ ROM_LOAD( "dm8678cab.bin", 0x0000, 0x0200, CRC(8da502e7) SHA1(30d2dd9658823cdc2b2f6ef37f5a05d6f3e0db76))
+ROM_END
+
+} // Anonymous namespace
+
+// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
+COMP( 1977, mk14, 0, 0, mk14, mk14, mk14_state, empty_init, "Science of Cambridge", "MK-14", MACHINE_SUPPORTS_SAVE )
+COMP( 1978, mk14vdu, mk14, 0, mk14vdu, mk14vdu, mk14vdu_state, empty_init, "Science of Cambridge", "MK-14 VDU", MACHINE_SUPPORTS_SAVE )