From 7961501b4da1b4b1dafa1492989791ab0f7fa32b Mon Sep 17 00:00:00 2001 From: Mark Garlanger Date: Sat, 25 May 2024 14:17:40 -0500 Subject: heathkit & zenith: Merge Heath and Zenith, since they're the same company (#12362) * heathkit/ & zenith/: Merge Heath and Zenith, since they're the same company * Add readme file * Fix Z29 company and full name * Update ROM descriptions for consistency --- src/mame/heathkit/et3400.cpp | 268 --- src/mame/heathkit/h17_fdc.cpp | 290 --- src/mame/heathkit/h17_fdc.h | 90 - src/mame/heathkit/h19.cpp | 72 - src/mame/heathkit/h8.cpp | 417 ----- src/mame/heathkit/h89.cpp | 1007 ----------- src/mame/heathkit/h_88_cass.cpp | 166 -- src/mame/heathkit/h_88_cass.h | 53 - src/mame/heathkit/intr_cntrl.cpp | 222 --- src/mame/heathkit/intr_cntrl.h | 133 -- src/mame/heathkit/sigmasoft_parallel_port.cpp | 165 -- src/mame/heathkit/sigmasoft_parallel_port.h | 67 - src/mame/heathkit/tlb.cpp | 2032 ---------------------- src/mame/heathkit/tlb.h | 477 ----- src/mame/heathkit/z37_fdc.cpp | 235 --- src/mame/heathkit/z37_fdc.h | 78 - src/mame/heathzenith/README.md | 53 + src/mame/heathzenith/et3400.cpp | 268 +++ src/mame/heathzenith/h17_fdc.cpp | 290 +++ src/mame/heathzenith/h17_fdc.h | 90 + src/mame/heathzenith/h19.cpp | 73 + src/mame/heathzenith/h8.cpp | 417 +++++ src/mame/heathzenith/h89.cpp | 1031 +++++++++++ src/mame/heathzenith/h_88_cass.cpp | 166 ++ src/mame/heathzenith/h_88_cass.h | 53 + src/mame/heathzenith/intr_cntrl.cpp | 222 +++ src/mame/heathzenith/intr_cntrl.h | 133 ++ src/mame/heathzenith/mdt60.cpp | 269 +++ src/mame/heathzenith/sigmasoft_parallel_port.cpp | 165 ++ src/mame/heathzenith/sigmasoft_parallel_port.h | 67 + src/mame/heathzenith/tlb.cpp | 2032 ++++++++++++++++++++++ src/mame/heathzenith/tlb.h | 477 +++++ src/mame/heathzenith/z100.cpp | 910 ++++++++++ src/mame/heathzenith/z22.cpp | 221 +++ src/mame/heathzenith/z29.cpp | 180 ++ src/mame/heathzenith/z37_fdc.cpp | 235 +++ src/mame/heathzenith/z37_fdc.h | 78 + src/mame/mame.lst | 37 +- src/mame/zenith/mdt60.cpp | 269 --- src/mame/zenith/z100.cpp | 910 ---------- src/mame/zenith/z22.cpp | 221 --- src/mame/zenith/z29.cpp | 180 -- 42 files changed, 7449 insertions(+), 7370 deletions(-) delete mode 100644 src/mame/heathkit/et3400.cpp delete mode 100644 src/mame/heathkit/h17_fdc.cpp delete mode 100644 src/mame/heathkit/h17_fdc.h delete mode 100644 src/mame/heathkit/h19.cpp delete mode 100644 src/mame/heathkit/h8.cpp delete mode 100644 src/mame/heathkit/h89.cpp delete mode 100644 src/mame/heathkit/h_88_cass.cpp delete mode 100644 src/mame/heathkit/h_88_cass.h delete mode 100644 src/mame/heathkit/intr_cntrl.cpp delete mode 100644 src/mame/heathkit/intr_cntrl.h delete mode 100644 src/mame/heathkit/sigmasoft_parallel_port.cpp delete mode 100644 src/mame/heathkit/sigmasoft_parallel_port.h delete mode 100644 src/mame/heathkit/tlb.cpp delete mode 100644 src/mame/heathkit/tlb.h delete mode 100644 src/mame/heathkit/z37_fdc.cpp delete mode 100644 src/mame/heathkit/z37_fdc.h create mode 100644 src/mame/heathzenith/README.md create mode 100644 src/mame/heathzenith/et3400.cpp create mode 100644 src/mame/heathzenith/h17_fdc.cpp create mode 100644 src/mame/heathzenith/h17_fdc.h create mode 100644 src/mame/heathzenith/h19.cpp create mode 100644 src/mame/heathzenith/h8.cpp create mode 100644 src/mame/heathzenith/h89.cpp create mode 100644 src/mame/heathzenith/h_88_cass.cpp create mode 100644 src/mame/heathzenith/h_88_cass.h create mode 100644 src/mame/heathzenith/intr_cntrl.cpp create mode 100644 src/mame/heathzenith/intr_cntrl.h create mode 100644 src/mame/heathzenith/mdt60.cpp create mode 100644 src/mame/heathzenith/sigmasoft_parallel_port.cpp create mode 100644 src/mame/heathzenith/sigmasoft_parallel_port.h create mode 100644 src/mame/heathzenith/tlb.cpp create mode 100644 src/mame/heathzenith/tlb.h create mode 100644 src/mame/heathzenith/z100.cpp create mode 100644 src/mame/heathzenith/z22.cpp create mode 100644 src/mame/heathzenith/z29.cpp create mode 100644 src/mame/heathzenith/z37_fdc.cpp create mode 100644 src/mame/heathzenith/z37_fdc.h delete mode 100644 src/mame/zenith/mdt60.cpp delete mode 100644 src/mame/zenith/z100.cpp delete mode 100644 src/mame/zenith/z22.cpp delete mode 100644 src/mame/zenith/z29.cpp diff --git a/src/mame/heathkit/et3400.cpp b/src/mame/heathkit/et3400.cpp deleted file mode 100644 index 86eec309cb8..00000000000 --- a/src/mame/heathkit/et3400.cpp +++ /dev/null @@ -1,268 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Robbbert -/*************************************************************************** - -ET-3400 - -2009-05-12 Skeleton driver. -2016-04-29 Added Accessory. - -ETA-3400 Memory I/O Accessory -- Provides Tiny Basic, a Terminal, a Serial Interface, a Cassette - interface, and 1k to 4k of expansion RAM. All parts are working. -- The roms are U105 (Monitor), U106 (Tiny Basic), both type NMOS2316E, - and U108 (address decoder PROM). -- Navigating: - LED to Monitor: D1400 - Monitor to Basic: G 1C00 - Monitor to LED: G FC00 - Basic to Monitor: BYE -- All commands in Basic and Monitor are UPPERCASE only. -- Terminal is defaulted to 9600 baud, 7 bits, 2 stop bits. - - -****************************************************************************/ - -#include "emu.h" -#include "cpu/m6800/m6800.h" -#include "machine/74259.h" -#include "machine/6821pia.h" -#include "bus/rs232/rs232.h" -#include "imagedev/cassette.h" -#include "speaker.h" - -#include "et3400.lh" - -namespace { - -class et3400_state : public driver_device -{ -public: - et3400_state(const machine_config &mconfig, device_type type, const char *tag) - : driver_device(mconfig, type, tag) - , m_maincpu(*this, "maincpu") - , m_pia(*this, "pia") - , m_displatch(*this, "displatch%u", 1) - , m_rs232(*this, "rs232") - , m_cass(*this, "cassette") - , m_x(*this, "X%u", 0U) - , m_digit(*this, "digit%u", 1U) - { } - - void et3400(machine_config &config); - - void reset_key_w(int state); - void segment_test_w(int state); - -private: - - virtual void machine_start() override; - - uint8_t keypad_r(offs_t offset); - void display_w(offs_t offset, uint8_t data); - template void led_w(uint8_t data); - uint8_t pia_ar(); - void pia_aw(uint8_t data); - uint8_t pia_br(); - void pia_bw(uint8_t data); - - void mem_map(address_map &map); - - required_device m_maincpu; - required_device m_pia; - required_device_array m_displatch; - required_device m_rs232; - required_device m_cass; - required_ioport_array<3> m_x; - output_finder<6> m_digit; -}; - - - -void et3400_state::machine_start() -{ - m_digit.resolve(); -} - - -uint8_t et3400_state::keypad_r(offs_t offset) -{ - uint8_t data = 0xff; - - if (~offset & 4) data &= m_x[2]->read(); - if (~offset & 2) data &= m_x[1]->read(); - if (~offset & 1) data &= m_x[0]->read(); - - return data; -} - -void et3400_state::display_w(offs_t offset, uint8_t data) -{ - // A6-A4 decoded by IC22 (74LS42); D0 inverted by one gate of IC21 (74S00) - uint8_t digit = (offset >> 4) & 7; - if (digit >= 1 && digit <= 6) - m_displatch[digit - 1]->write_bit(offset & 7, !BIT(data, 0)); -} - -template -void et3400_state::led_w(uint8_t data) -{ - // This computer sets each segment, one at a time. - m_digit[Digit - 1] = bitswap<8>(~data, 7, 0, 1, 2, 3, 4, 5, 6); -} - -// d1,2,3 = Baud rate -// d4 = gnd -// d7 = rs232 in -uint8_t et3400_state::pia_ar() -{ - return ioport("BAUD")->read() | (m_rs232->rxd_r() << 7); -} - -// d0 = rs232 out -void et3400_state::pia_aw(uint8_t data) -{ - m_rs232->write_txd(BIT(data, 0)); -} - -// d7 = cass in -uint8_t et3400_state::pia_br() -{ - return (m_cass->input() > +0.0) << 7; -} - -// d0 = cass out -void et3400_state::pia_bw(uint8_t data) -{ - m_cass->output(BIT(data, 0) ? -1.0 : +1.0); -} - - -void et3400_state::mem_map(address_map &map) -{ - map.unmap_value_high(); - map(0x0000, 0x0fff).ram(); - map(0x1000, 0x1003).mirror(0x03fc).rw(m_pia, FUNC(pia6821_device::read), FUNC(pia6821_device::write)); - map(0x1400, 0x23ff).rom().region("roms", 0); - map(0xc000, 0xc0ff).r(FUNC(et3400_state::keypad_r)); - map(0xc100, 0xc1ff).w(FUNC(et3400_state::display_w)); - map(0xfc00, 0xffff).rom().region("roms", 0x1000); -} - -void et3400_state::reset_key_w(int state) -{ - // delivered through MC6875 (or 74LS241 on ET-3400A) - m_maincpu->set_input_line(INPUT_LINE_RESET, state ? CLEAR_LINE : ASSERT_LINE); - - // PIA also uses reset line - if (!state) - m_pia->reset(); -} - -void et3400_state::segment_test_w(int state) -{ - for (int d = 0; d < 6; d++) - m_displatch[d]->clear_w(state); -} - -/* Input ports */ -static INPUT_PORTS_START( et3400 ) - PORT_START("X0") - PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("D DO") PORT_CODE(KEYCODE_D) PORT_CHAR('D') - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("A AUTO") PORT_CODE(KEYCODE_A) PORT_CHAR('A') - PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("7 RTI") PORT_CODE(KEYCODE_7) PORT_CHAR('7') - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("4 INDEX") PORT_CODE(KEYCODE_4) PORT_CHAR('4') - PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("1 ACCA") PORT_CODE(KEYCODE_1) PORT_CHAR('1') - PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("0") PORT_CODE(KEYCODE_0) PORT_CHAR('0') - PORT_BIT( 0xc0, 0xc0, IPT_UNUSED ) - - PORT_START("X1") - PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("E EXAM") PORT_CODE(KEYCODE_E) PORT_CHAR('E') - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("B BACK") PORT_CODE(KEYCODE_B) PORT_CHAR('B') - PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("8 SS") PORT_CODE(KEYCODE_8) PORT_CHAR('8') - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("5 CC") PORT_CODE(KEYCODE_5) PORT_CHAR('5') - PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("2 ACCB") PORT_CODE(KEYCODE_2) PORT_CHAR('2') - PORT_BIT( 0xe0, 0xe0, IPT_UNUSED ) - - PORT_START("X2") - PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("F FWD") PORT_CODE(KEYCODE_F) PORT_CHAR('F') - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("C CHAN") PORT_CODE(KEYCODE_C) PORT_CHAR('C') - PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("9 BR") PORT_CODE(KEYCODE_9) PORT_CHAR('9') - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("6 SP") PORT_CODE(KEYCODE_6) PORT_CHAR('6') - PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("3 PC") PORT_CODE(KEYCODE_3) PORT_CHAR('3') - PORT_BIT( 0xe0, 0xe0, IPT_UNUSED ) - - PORT_START("BAUD") - PORT_DIPNAME( 0x0E, 0x02, "Baud Rate" ) - PORT_DIPSETTING( 0x0E, "110" ) - PORT_DIPSETTING( 0x00, "300" ) - PORT_DIPSETTING( 0x0A, "600" ) - PORT_DIPSETTING( 0x08, "1200" ) - PORT_DIPSETTING( 0x06, "2400" ) - PORT_DIPSETTING( 0x04, "4800" ) - PORT_DIPSETTING( 0x02, "9600" ) - - PORT_START("RESET") // RESET is directly next to 0, but electrically separate from key matrix - PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("RESET") PORT_CODE(KEYCODE_STOP) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, et3400_state, reset_key_w) - - PORT_START("TEST") // No input mechanism for "Segment Test" defined other than shorting pins together - PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Segment Test") PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, et3400_state, segment_test_w) -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_NONE ) - DEVICE_INPUT_DEFAULTS( "RS232_STOPBITS", 0xff, RS232_STOPBITS_2 ) -DEVICE_INPUT_DEFAULTS_END - -void et3400_state::et3400(machine_config &config) -{ - /* basic machine hardware */ - M6800(config, m_maincpu, XTAL(4'000'000) / 4 ); // 1MHz with memory i/o accessory, or 500khz without it - m_maincpu->set_addrmap(AS_PROGRAM, &et3400_state::mem_map); - - /* video hardware */ - config.set_default_layout(layout_et3400); - - // Devices - PIA6821(config, m_pia); - m_pia->writepa_handler().set(FUNC(et3400_state::pia_aw)); - m_pia->writepb_handler().set(FUNC(et3400_state::pia_bw)); - m_pia->readpa_handler().set(FUNC(et3400_state::pia_ar)); - m_pia->readpb_handler().set(FUNC(et3400_state::pia_br)); - - RS232_PORT(config, m_rs232, default_rs232_devices, "terminal").set_option_device_input_defaults("terminal", DEVICE_INPUT_DEFAULTS_NAME(terminal)); - - for (std::size_t i = 0; i < 6; i++) - LS259(config, m_displatch[i]); - - m_displatch[0]->parallel_out_cb().set(FUNC(et3400_state::led_w<1>)); - m_displatch[1]->parallel_out_cb().set(FUNC(et3400_state::led_w<2>)); - m_displatch[2]->parallel_out_cb().set(FUNC(et3400_state::led_w<3>)); - m_displatch[3]->parallel_out_cb().set(FUNC(et3400_state::led_w<4>)); - m_displatch[4]->parallel_out_cb().set(FUNC(et3400_state::led_w<5>)); - m_displatch[5]->parallel_out_cb().set(FUNC(et3400_state::led_w<6>)); - - SPEAKER(config, "mono").front_center(); - - CASSETTE(config, m_cass); - m_cass->set_default_state(CASSETTE_STOPPED | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_ENABLED); - m_cass->add_route(ALL_OUTPUTS, "mono", 0.05); -} - -/* ROM definition */ -ROM_START( et3400 ) - ROM_REGION( 0x1420, "roms", 0 ) - ROM_LOAD( "monitor.u105", 0x0000, 0x0800, CRC(e4142682) SHA1(785966018dd6eb097ed9bd5c7def2354ab4347db) ) - ROM_LOAD( "basic.u106", 0x0800, 0x0800, CRC(bbd6a801) SHA1(088da24bd4d923d4f196b993154c538835d10605) ) - ROM_LOAD( "et3400.ic12", 0x1000, 0x0400, CRC(2eff1f58) SHA1(38b655de7393d7a92b08276f7c14a99eaa2a4a9f) ) - ROM_LOAD_OPTIONAL("prom.u108", 0x1400, 0x0020, CRC(273025c3) SHA1(136c1cdce2a4a796c1c46e8ea4f798cdee4b549b) ) // not used -ROM_END - -} // Anonymous namespace - -/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */ -COMP( 1976, et3400, 0, 0, et3400, et3400, et3400_state, empty_init, "Heath Company", "Heathkit Model ET-3400 Microprocessor Trainer", MACHINE_SUPPORTS_SAVE ) diff --git a/src/mame/heathkit/h17_fdc.cpp b/src/mame/heathkit/h17_fdc.cpp deleted file mode 100644 index 7499368cd70..00000000000 --- a/src/mame/heathkit/h17_fdc.cpp +++ /dev/null @@ -1,290 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Mark Garlanger -/*************************************************************************** - - Heathkit H-17 Floppy controller - - This was an option for both the Heathkit H8 and H89 computer systems. - - TODO - - define hard-sectored disk format - - incoming floppy data should drive receive clock of the ami 2350. - -****************************************************************************/ - -#include "emu.h" -#include "h17_fdc.h" - -#define LOG_REG (1U << 1) // Register setup -#define LOG_LINES (1U << 2) // Control lines -#define LOG_DRIVE (1U << 3) // Drive select -#define LOG_FUNC (1U << 4) // Function calls - -//#define VERBOSE (LOG_GENERAL | LOG_REG | LOG_LINES | LOG_DRIVE | LOG_FUNC) - -#include "logmacro.h" - -#define LOGREG(...) LOGMASKED(LOG_REG, __VA_ARGS__) -#define LOGLINES(...) LOGMASKED(LOG_LINES, __VA_ARGS__) -#define LOGDRIVE(...) LOGMASKED(LOG_DRIVE, __VA_ARGS__) -#define LOGFUNC(...) LOGMASKED(LOG_FUNC, __VA_ARGS__) - -#ifdef _MSC_VER -#define FUNCNAME __func__ -#else -#define FUNCNAME __PRETTY_FUNCTION__ -#endif - - -DEFINE_DEVICE_TYPE(HEATH_H17_FDC, heath_h17_fdc_device, "heath_h17_fdc", "Heath H-17 Hard-sectored Controller"); - - -heath_h17_fdc_device::heath_h17_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock): - device_t(mconfig, HEATH_H17_FDC, tag, owner, 0), - m_floppy_ram_wp(*this), - m_s2350(*this, "s2350"), - m_floppies(*this, "floppy%u", 0U), - m_tx_timer(*this, "tx_timer"), - m_floppy(nullptr) -{ -} - -void heath_h17_fdc_device::write(offs_t reg, u8 val) -{ - LOGFUNC("%s: reg: %d val: 0x%02x\n", FUNCNAME, reg, val); - - switch (reg) - { - case 0: // data port - m_s2350->transmitter_holding_reg_w(val); - break; - case 1: // fill character - m_s2350->transmit_fill_reg_w(val); - break; - case 2: // sync port - m_s2350->receiver_sync_reg_w(val); - break; - case 3: // control port - ctrl_w(val); - break; - } -} - -void heath_h17_fdc_device::set_floppy(floppy_image_device *floppy) -{ - if (m_floppy == floppy) - { - return; - } - - LOGDRIVE("%s: selecting new drive\n", FUNCNAME); - - m_floppy = floppy; - - // set any latched signals - { - m_floppy->ss_w(m_side); - } -} - -void heath_h17_fdc_device::side_select_w(int state) -{ - m_side = BIT(state, 0); - - if (m_floppy) - { - m_floppy->ss_w(m_side); - } -} - -void heath_h17_fdc_device::dir_w(int state) -{ - if (m_floppy) - { - LOGFUNC("%s: step dir: 0x%02x\n", FUNCNAME, state); - - m_floppy->dir_w(state); - } -} - -void heath_h17_fdc_device::step_w(int state) -{ - if (m_floppy) - { - LOGFUNC("%s: step dir: 0x%02x\n", FUNCNAME, state); - - m_floppy->stp_w(state); - } -} - -void heath_h17_fdc_device::set_motor(bool motor_on) -{ - if (m_motor_on == motor_on) - { - return; - } - - m_motor_on = motor_on; - - for (auto &elem : m_floppies) - { - floppy_image_device *floppy = elem->get_device(); - if (floppy) - { - LOGFUNC("%s: motor: %d\n", FUNCNAME, motor_on); - - floppy->mon_w(!motor_on); - } - } -} - -void heath_h17_fdc_device::ctrl_w(u8 val) -{ - m_write_gate = bool(BIT(val, CTRL_WRITE_GATE)); - - set_motor(bool(BIT(val, CTRL_MOTOR_ON))); - - if (BIT(val, CTRL_DRIVE_SELECT_0)) - { - LOGFUNC("%s: set drive 0\n", FUNCNAME); - - set_floppy(m_floppies[0]->get_device()); - } - else if (BIT(val, CTRL_DRIVE_SELECT_1)) - { - LOGFUNC("%s: set drive 1\n", FUNCNAME); - - set_floppy(m_floppies[1]->get_device()); - } - else if (BIT(val, CTRL_DRIVE_SELECT_2)) - { - LOGFUNC("%s: set drive 2\n", FUNCNAME); - - set_floppy(m_floppies[2]->get_device()); - } - else - { - LOGFUNC("%s: set drive none\n", FUNCNAME); - - set_floppy(nullptr); - } - - dir_w(!BIT(val, CTRL_DIRECTION)); - - step_w(!BIT(val, CTRL_STEP_COMMAND)); - - m_floppy_ram_wp(BIT(val, CTRL_WRITE_ENABLE_RAM)); -} - -u8 heath_h17_fdc_device::read(offs_t reg) -{ - // default return for the h89 - u8 val = 0xff; - - switch (reg) - { - case 0: // data port - val = m_s2350->receiver_output_reg_r(); - break; - case 1: // status port - val = m_s2350->status_word_r(); - break; - case 2: // sync port - val = m_s2350->receiver_sync_search(); - break; - case 3: // floppy status port - val = floppy_status_r(); - break; - } - - LOGREG("%s: reg: %d val: 0x%02x\n", FUNCNAME, reg, val); - - return val; -} - -u8 heath_h17_fdc_device::floppy_status_r() -{ - u8 val = 0; - - // statuses from the floppy drive - if (m_floppy) - { - // index/sector hole - val |= m_floppy->idx_r() ? 0x00 : 0x01; - - // track 0 - val |= m_floppy->trk00_r() ? 0x00 : 0x02; - - // disk is write-protected - val |= m_floppy->wpt_r() ? 0x00 : 0x04; - } - else - { - LOGREG("%s: no drive selected\n", FUNCNAME); - } - - // status from USRT - val |= m_sync_char_received ? 0x08 : 0x00; - - LOGFUNC("%s: val: 0x%02x\n", FUNCNAME, val); - - return val; -} - -void heath_h17_fdc_device::device_start() -{ - save_item(NAME(m_motor_on)); - save_item(NAME(m_write_gate)); - save_item(NAME(m_sync_char_received)); - save_item(NAME(m_step_direction)); - save_item(NAME(m_side)); -} - -void heath_h17_fdc_device::device_reset() -{ - LOGFUNC("%s\n", FUNCNAME); - - m_motor_on = false; - m_write_gate = false; - m_sync_char_received = false; - - m_tx_timer->adjust(attotime::from_hz(USRT_TX_CLOCK), 0, attotime::from_hz(USRT_TX_CLOCK)); -} - -static void h17_floppies(device_slot_interface &device) -{ - // H-17-1 - device.option_add("ssdd", FLOPPY_525_SSDD); - - // Future plans - test and verify higher capacity drives with LLC's BIOS-80 for CP/M and an HUG's enhanced HDOS driver - // - FLOPPY_525_SSQD - // - FLOPPY_525_DD - // - FLOPPY_525_QD (H-17-4) -} - -TIMER_DEVICE_CALLBACK_MEMBER(heath_h17_fdc_device::tx_timer_cb) -{ - m_s2350->tcp_w(); -} - -void heath_h17_fdc_device::device_add_mconfig(machine_config &config) -{ - S2350(config, m_s2350, 0); - m_s2350->sync_character_received_cb().set(FUNC(heath_h17_fdc_device::sync_character_received)); - - for (int i = 0; i < MAX_FLOPPY_DRIVES; i++) - { - // TODO -> add (and define) heath hard-sectored floppy formats. - FLOPPY_CONNECTOR(config, m_floppies[i], h17_floppies, "ssdd", floppy_image_device::default_fm_floppy_formats); - m_floppies[i]->enable_sound(true); - } - - TIMER(config, m_tx_timer).configure_generic(FUNC(heath_h17_fdc_device::tx_timer_cb)); -} - -void heath_h17_fdc_device::sync_character_received(int state) -{ - LOGFUNC("%s: state: %d\n", FUNCNAME, state); - - m_sync_char_received = bool(!BIT(state, 0)); -} diff --git a/src/mame/heathkit/h17_fdc.h b/src/mame/heathkit/h17_fdc.h deleted file mode 100644 index 75dd4460e93..00000000000 --- a/src/mame/heathkit/h17_fdc.h +++ /dev/null @@ -1,90 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Mark Garlanger -/*************************************************************************** - - Heathkit H-17 Floppy Disk Controller - - - Model number: H-88-1 - - TODO - - Mame core must support hard-sectored disk images. - - used floppy clock bits to clock USRT received clock. - - Add support for a heath hard-sectored disk support (h17disk). - -****************************************************************************/ - -#ifndef MAME_HEATHKIT_H17_FDC_H -#define MAME_HEATHKIT_H17_FDC_H - -#pragma once - -#include "imagedev/floppy.h" -#include "machine/s2350.h" - - -class heath_h17_fdc_device : public device_t -{ -public: - heath_h17_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); - - auto floppy_ram_wp_cb() { return m_floppy_ram_wp.bind(); } - - void write(offs_t reg, u8 val); - u8 read(offs_t reg); - - void side_select_w(int state); - -protected: - static constexpr u8 MAX_FLOPPY_DRIVES = 3; - - virtual void device_start() override; - virtual void device_reset() override; - virtual void device_add_mconfig(machine_config &config) override; - - void ctrl_w(u8 val); - u8 floppy_status_r(); - - void set_floppy(floppy_image_device *floppy); - void step_w(int state); - void dir_w(int state); - void set_motor(bool motor_on); - - void sync_character_received(int state); - - TIMER_DEVICE_CALLBACK_MEMBER(tx_timer_cb); - - devcb_write_line m_floppy_ram_wp; - - required_device m_s2350; - required_device_array m_floppies; - required_device m_tx_timer; - - bool m_motor_on; - bool m_write_gate; - bool m_sync_char_received; - u8 m_step_direction; - u8 m_side; - - floppy_image_device *m_floppy; - - /// write bit control port - static constexpr u8 CTRL_WRITE_GATE = 0; - static constexpr u8 CTRL_DRIVE_SELECT_0 = 1; - static constexpr u8 CTRL_DRIVE_SELECT_1 = 2; - static constexpr u8 CTRL_DRIVE_SELECT_2 = 3; - static constexpr u8 CTRL_MOTOR_ON = 4; // Controls all the drives - static constexpr u8 CTRL_DIRECTION = 5; // (0 = out) - static constexpr u8 CTRL_STEP_COMMAND = 6; // (Active high) - static constexpr u8 CTRL_WRITE_ENABLE_RAM = 7; // 0 - write protected - - // USRT clock - static constexpr XTAL USRT_BASE_CLOCK = XTAL(12'288'000) / 6 / 16; - static constexpr u32 USRT_TX_CLOCK = USRT_BASE_CLOCK.value(); -}; - - -DECLARE_DEVICE_TYPE(HEATH_H17_FDC, heath_h17_fdc_device) - - -#endif // MAME_HEATHKIT_H17_FDC_H diff --git a/src/mame/heathkit/h19.cpp b/src/mame/heathkit/h19.cpp deleted file mode 100644 index 1982df0a520..00000000000 --- a/src/mame/heathkit/h19.cpp +++ /dev/null @@ -1,72 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Mark Garlanger -/*************************************************************************** - - Heathkit H19 - - A smart terminal designed and manufactured by Heath Company. This - is identical to the Zenith Data Systems Z-19. - -****************************************************************************/ - -#include "emu.h" - -#include "tlb.h" -#include "bus/rs232/rs232.h" - -#include "h19.lh" - - -namespace { - -class h19_state : public driver_device -{ -public: - h19_state(const machine_config &mconfig, device_type type, const char *tag) : - driver_device(mconfig, type, tag), - m_tlbc(*this, "tlbc") - { - } - - void h19(machine_config &config); - -private: - required_device m_tlbc; - -}; - -static void tlb_options(device_slot_interface &device) -{ - device.option_add("heath", HEATH_TLB); - device.option_add("gp19", HEATH_GP19); - device.option_add("imaginator", HEATH_IMAGINATOR); - device.option_add("super19", HEATH_SUPER19); - device.option_add("superset", HEATH_SUPERSET); - device.option_add("ultrarom", HEATH_ULTRA); - device.option_add("watzman", HEATH_WATZ); -} - -void h19_state::h19(machine_config &config) -{ - config.set_default_layout(layout_h19); - - HEATH_TLB_CONNECTOR(config, m_tlbc, tlb_options, "heath"); - m_tlbc->serial_data_callback().set("dte", FUNC(rs232_port_device::write_txd)); - m_tlbc->dtr_callback().set("dte", FUNC(rs232_port_device::write_dtr)); - m_tlbc->rts_callback().set("dte", FUNC(rs232_port_device::write_rts)); - - rs232_port_device &dte(RS232_PORT(config, "dte", default_rs232_devices, "loopback")); - dte.rxd_handler().set(m_tlbc, FUNC(heath_tlb_connector::serial_in_w)); - dte.dcd_handler().set(m_tlbc, FUNC(heath_tlb_connector::rlsd_in_w)); - dte.dsr_handler().set(m_tlbc, FUNC(heath_tlb_connector::dsr_in_w)); - dte.cts_handler().set(m_tlbc, FUNC(heath_tlb_connector::cts_in_w)); -} - -// ROM definition -ROM_START( h19 ) -ROM_END - -} // anonymous namespace - -// year name parent compat machine input class init company fullname flags -COMP( 1979, h19, 0, 0, h19, 0, h19_state, empty_init, "Heath Company", "Heathkit H-19", MACHINE_SUPPORTS_SAVE ) diff --git a/src/mame/heathkit/h8.cpp b/src/mame/heathkit/h8.cpp deleted file mode 100644 index 236ce61f9bd..00000000000 --- a/src/mame/heathkit/h8.cpp +++ /dev/null @@ -1,417 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Robbbert -/*************************************************************************** - - Heathkit H8 - - 2009-05-12 Skeleton driver. - - This system uses Octal rather than the usual hexadecimal. - -STATUS: - It runs, keyboard works, you can enter data. - -Meaning of LEDs: - PWR = power is turned on - MON = controls should work - RUN = CPU is running (not halted) - ION = Interrupts are enabled - -Pasting: - 0-F : as is - + : ^ - - : V - MEM : - - ALTER : = - - Addresses must have all 6 digits entered. - Data must have all 3 digits entered. - System has a short beep for each key, and a slightly longer beep - for each group of 3 digits. The largest number allowed is 377 (=0xFF). - -Test Paste: - -041000=123 245 333 144 255 366 077=-041000 - Now press up-arrow to confirm the data has been entered. - -Official test program from pages 4 to 8 of the operator's manual: - -040100=076 002 062 010 040 006 004 041 170 040 021 013 040 016 011 176 - 022 043 023 015 302 117 040 016 003 076 377 315 053 000 015 302 - 131 040 005 302 112 040 076 062 315 140 002 076 062 315 053 000 - 076 062 315 140 002 303 105 040 377 262 270 272 275 377 222 200 - 377 237 244 377 272 230 377 220 326 302 377 275 272 271 271 373 - 271 240 377 236 376 362 236 376 362 236 376 362 R6=040100=4 - - -****************************************************************************/ - -#include "emu.h" - -#include "cpu/i8085/i8085.h" -#include "machine/i8251.h" -#include "machine/clock.h" -#include "machine/timer.h" -#include "imagedev/cassette.h" -#include "sound/beep.h" -#include "speaker.h" - -#include "formats/h8_cas.h" -#include "h8.lh" - -namespace { - -class h8_state : public driver_device -{ -public: - h8_state(const machine_config &mconfig, device_type type, const char *tag) - : driver_device(mconfig, type, tag) - , m_maincpu(*this, "maincpu") - , m_uart(*this, "uart") - , m_cass(*this, "cassette") - , m_beep(*this, "beeper") - , m_io_keyboard(*this, "X%u", 0U) - , m_digits(*this, "digit%u", 0U) - , m_mon_led(*this, "mon_led") - , m_pwr_led(*this, "pwr_led") - , m_ion_led(*this, "ion_led") - , m_run_led(*this, "run_led") - { } - - void h8(machine_config &config); - - DECLARE_INPUT_CHANGED_MEMBER(button_0); - -protected: - virtual void machine_reset() override; - virtual void machine_start() override; - -private: - u8 portf0_r(); - void portf0_w(u8 data); - void portf1_w(u8 data); - void h8_status_callback(u8 data); - void h8_inte_callback(int state); - TIMER_DEVICE_CALLBACK_MEMBER(h8_irq_pulse); - TIMER_DEVICE_CALLBACK_MEMBER(kansas_r); - TIMER_DEVICE_CALLBACK_MEMBER(kansas_w); - - void io_map(address_map &map); - void mem_map(address_map &map); - - u8 m_digit = 0U; - u8 m_segment = 0U; - u8 m_irq_ctl = 0U; - bool m_ff_b = 0; - u8 m_cass_data[4]{}; - bool m_cassbit = 0; - bool m_cassold = 0; - - // clocks - static constexpr XTAL H8_CLOCK = XTAL(12'288'000) / 6; // 2.048 MHz - static constexpr XTAL H8_BEEP_FRQ = H8_CLOCK / 2048; // 1 kHz - static constexpr XTAL H8_IRQ_PULSE = H8_BEEP_FRQ / 2; - - required_device m_maincpu; - required_device m_uart; - required_device m_cass; - required_device m_beep; - required_ioport_array<2> m_io_keyboard; - output_finder<16> m_digits; - output_finder<> m_mon_led; - output_finder<> m_pwr_led; - output_finder<> m_ion_led; - output_finder<> m_run_led; -}; - - -TIMER_DEVICE_CALLBACK_MEMBER(h8_state::h8_irq_pulse) -{ - if (BIT(m_irq_ctl, 0)) - m_maincpu->set_input_line_and_vector(INPUT_LINE_IRQ0, ASSERT_LINE, 0xcf); // I8080 -} - -u8 h8_state::portf0_r() -{ - // reads the keyboard - - // The following not emulated, can occur any time even if keyboard not being scanned - // - if 0 and RTM pressed, causes int10 - // - if 0 and RST pressed, resets cpu - - u8 i,keyin,data = 0xff; - - keyin = m_io_keyboard[0]->read(); - if (keyin != 0xff) - { - for (i = 1; i < 8; i++) - if (!BIT(keyin,i)) - data &= ~(i<<1); - data &= 0xfe; - } - - keyin = m_io_keyboard[1]->read(); - if (keyin != 0xff) - { - for (i = 1; i < 8; i++) - if (!BIT(keyin,i)) - data &= ~(i<<5); - data &= 0xef; - } - return data; -} - -void h8_state::portf0_w(u8 data) -{ - // this will always turn off int10 that was set by the timer - // d0-d3 = digit select - // d4 = int20 is allowed - // d5 = mon led - // d6 = int10 is allowed - // d7 = beeper enable - - m_digit = data & 15; - if (m_digit) m_digits[m_digit] = m_segment; - - m_mon_led = !BIT(data, 5); - m_beep->set_state(!BIT(data, 7)); - - m_maincpu->set_input_line(INPUT_LINE_IRQ0, CLEAR_LINE); - m_irq_ctl &= 0xf0; - if (BIT(data, 6)) m_irq_ctl |= 1; - if (!BIT(data, 4)) m_irq_ctl |= 2; -} - -void h8_state::portf1_w(u8 data) -{ - //d7 segment dot - //d6 segment f - //d5 segment e - //d4 segment d - //d3 segment c - //d2 segment b - //d1 segment a - //d0 segment g - - m_segment = 0xff ^ bitswap<8>(data, 7, 0, 6, 5, 4, 3, 2, 1); - if (m_digit) m_digits[m_digit] = m_segment; -} - -void h8_state::mem_map(address_map &map) -{ - map.unmap_value_high(); - map(0x0000, 0x0fff).rom(); // main rom - map(0x1400, 0x17ff).ram(); // fdc ram - map(0x1800, 0x1fff).rom(); // fdc rom - map(0x2000, 0x9fff).ram(); // main ram -} - -void h8_state::io_map(address_map &map) -{ - map.unmap_value_high(); - map.global_mask(0xff); - map(0xf0, 0xf0).rw(FUNC(h8_state::portf0_r), FUNC(h8_state::portf0_w)); - map(0xf1, 0xf1).w(FUNC(h8_state::portf1_w)); - map(0xf8, 0xf9).rw(m_uart, FUNC(i8251_device::read), FUNC(i8251_device::write)); - // optional connection to a serial terminal @ 600 baud - //map(0xfa, 0xfb).rw("uart1", FUNC(i8251_device::read), FUNC(i8251_device::write)); -} - -/* Input ports */ -static INPUT_PORTS_START( h8 ) - PORT_START("X0") - PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("0") PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHANGED_MEMBER(DEVICE_SELF, h8_state, button_0, 0) - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("1 SP") PORT_CODE(KEYCODE_1) PORT_CHAR('1') - PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("2 AF") PORT_CODE(KEYCODE_2) PORT_CHAR('2') - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("3 BC") PORT_CODE(KEYCODE_3) PORT_CHAR('3') - PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("4 DE GO") PORT_CODE(KEYCODE_4) PORT_CHAR('4') - PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("5 HL IN") PORT_CODE(KEYCODE_5) PORT_CHAR('5') - PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("6 PC OUT") PORT_CODE(KEYCODE_6) PORT_CHAR('6') - PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("7 SI") PORT_CODE(KEYCODE_7) PORT_CHAR('7') - - PORT_START("X1") - PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("8 LOAD") PORT_CODE(KEYCODE_8) PORT_CHAR('8') - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("9 DUMP") PORT_CODE(KEYCODE_9) PORT_CHAR('9') - PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("+") PORT_CODE(KEYCODE_UP) PORT_CHAR('^') - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("-") PORT_CODE(KEYCODE_DOWN) PORT_CHAR('V') - PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("* CANCEL") PORT_CODE(KEYCODE_ESC) PORT_CHAR('Q') - PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("/ ALTER RST") PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') - PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("# MEM RTM") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') - PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(". REG") PORT_CODE(KEYCODE_R) PORT_CHAR('R') -INPUT_PORTS_END - -INPUT_CHANGED_MEMBER(h8_state::button_0) -{ - if (newval) - { - u8 data = m_io_keyboard[1]->read() ^ 0xff; - if (BIT(data, 5)) - m_maincpu->reset(); - else - if (BIT(data, 6)) - m_maincpu->set_input_line_and_vector(INPUT_LINE_IRQ0, ASSERT_LINE, 0xcf); // INT 10 // I8080 - } -} - -void h8_state::machine_reset() -{ - m_pwr_led = 0; - m_irq_ctl = 1; - m_cassbit = 1; - m_cass_data[0] = 0; - m_cass_data[1] = 0; - m_uart->write_cts(0); - m_uart->write_dsr(0); - m_uart->write_rxd(0); - m_cass_data[3] = 0; - m_ff_b = 1; -} - -void h8_state::machine_start() -{ - m_digits.resolve(); - m_mon_led.resolve(); - m_pwr_led.resolve(); - m_ion_led.resolve(); - m_run_led.resolve(); - - save_item(NAME(m_digit)); - save_item(NAME(m_segment)); - save_item(NAME(m_irq_ctl)); - save_item(NAME(m_ff_b)); - save_item(NAME(m_cass_data)); - save_item(NAME(m_cassbit)); - save_item(NAME(m_cassold)); -} - -void h8_state::h8_inte_callback(int state) -{ - // operate the ION LED - m_ion_led = !state; - m_irq_ctl &= 0x7f | ((state) ? 0 : 0x80); -} - -void h8_state::h8_status_callback(u8 data) -{ -/* This is rather messy, but basically there are 2 D flipflops, one drives the other, -the data is /INTE while the clock is /M1. If the system is in Single Instruction mode, -a int20 (output of 2nd flipflop) will occur after 4 M1 steps, to pause the running program. -But, all of this can only occur if bit 4 of port F0 is low. */ - - bool state = (data & i8080_cpu_device::STATUS_M1) ? 0 : 1; - bool c,a = BIT(m_irq_ctl, 7); - - if (BIT(m_irq_ctl, 1)) - { - if (!state) // rising pulse to push data through flipflops - { - c = !m_ff_b; // from /Q of 2nd flipflop - m_ff_b = a; // from Q of 1st flipflop - if (c) - m_maincpu->set_input_line_and_vector(INPUT_LINE_IRQ0, ASSERT_LINE, 0xd7); // I8080 - } - } - else - { // flipflops are 'set' - c = 0; - m_ff_b = 1; - } - - - // operate the RUN LED - m_run_led = state; -} - -TIMER_DEVICE_CALLBACK_MEMBER(h8_state::kansas_w) -{ - m_cass_data[3]++; - - if (m_cassbit != m_cassold) - { - m_cass_data[3] = 0; - m_cassold = m_cassbit; - } - - if (m_cassbit) - m_cass->output(BIT(m_cass_data[3], 0) ? -1.0 : +1.0); // 2400Hz - else - m_cass->output(BIT(m_cass_data[3], 1) ? -1.0 : +1.0); // 1200Hz -} - -TIMER_DEVICE_CALLBACK_MEMBER(h8_state::kansas_r) -{ - /* cassette - turn 1200/2400Hz to a bit */ - m_cass_data[1]++; - u8 cass_ws = (m_cass->input() > +0.03) ? 1 : 0; - - if (cass_ws != m_cass_data[0]) - { - m_cass_data[0] = cass_ws; - m_uart->write_rxd((m_cass_data[1] < 12) ? 1 : 0); - m_cass_data[1] = 0; - } -} - -void h8_state::h8(machine_config &config) -{ - /* basic machine hardware */ - I8080(config, m_maincpu, H8_CLOCK); - m_maincpu->set_addrmap(AS_PROGRAM, &h8_state::mem_map); - m_maincpu->set_addrmap(AS_IO, &h8_state::io_map); - m_maincpu->out_status_func().set(FUNC(h8_state::h8_status_callback)); - m_maincpu->out_inte_func().set(FUNC(h8_state::h8_inte_callback)); - - /* video hardware */ - config.set_default_layout(layout_h8); - - /* sound hardware */ - SPEAKER(config, "mono").front_center(); - BEEP(config, m_beep, H8_BEEP_FRQ).add_route(ALL_OUTPUTS, "mono", 1.00); - - /* Devices */ - I8251(config, m_uart, 0); - m_uart->txd_handler().set([this] (bool state) { m_cassbit = state; }); - - clock_device &cassette_clock(CLOCK(config, "cassette_clock", 4800)); - cassette_clock.signal_handler().set(m_uart, FUNC(i8251_device::write_txc)); - cassette_clock.signal_handler().append(m_uart, FUNC(i8251_device::write_rxc)); - - CASSETTE(config, m_cass); - m_cass->set_formats(h8_cassette_formats); - m_cass->set_default_state(CASSETTE_STOPPED | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_ENABLED); - m_cass->add_route(ALL_OUTPUTS, "mono", 0.05); - m_cass->set_interface("h8_cass"); - - TIMER(config, "kansas_w").configure_periodic(FUNC(h8_state::kansas_w), attotime::from_hz(4800)); - TIMER(config, "kansas_r").configure_periodic(FUNC(h8_state::kansas_r), attotime::from_hz(40000)); - TIMER(config, "h8_timer").configure_periodic(FUNC(h8_state::h8_irq_pulse), attotime::from_hz(H8_IRQ_PULSE)); -} - -/* ROM definition */ -ROM_START( h8 ) - ROM_REGION( 0x2000, "maincpu", ROMREGION_ERASEFF ) - // H17 fdc bios - needed by bios2&3 - ROM_LOAD( "2716_444-19_h17.rom", 0x1800, 0x0800, CRC(26e80ae3) SHA1(0c0ee95d7cb1a760f924769e10c0db1678f2435c)) - - ROM_SYSTEM_BIOS(0, "bios0", "Standard") - ROMX_LOAD( "2708_444-13_pam8.rom", 0x0000, 0x0400, CRC(e0745513) SHA1(0e170077b6086be4e5cd10c17e012c0647688c39), ROM_BIOS(0) ) - - ROM_SYSTEM_BIOS(1, "bios1", "Alternate") - ROMX_LOAD( "2708_444-13_pam8go.rom", 0x0000, 0x0400, CRC(9dbad129) SHA1(72421102b881706877f50537625fc2ab0b507752), ROM_BIOS(1) ) - - ROM_SYSTEM_BIOS(2, "bios2", "Disk OS") - ROMX_LOAD( "2716_444-13_pam8at.rom", 0x0000, 0x0800, CRC(fd95ddc1) SHA1(eb1f272439877239f745521139402f654e5403af), ROM_BIOS(2) ) - - ROM_SYSTEM_BIOS(3, "bios3", "Disk OS Alt") - ROMX_LOAD( "2732_444-70_xcon8.rom", 0x0000, 0x1000, CRC(b04368f4) SHA1(965244277a3a8039a987e4c3593b52196e39b7e7), ROM_BIOS(3) ) - - // this one runs off into the weeds - ROM_SYSTEM_BIOS(4, "bios4", "not working") - ROMX_LOAD( "2732_444-140_pam37.rom", 0x0000, 0x1000, CRC(53a540db) SHA1(90082d02ffb1d27e8172b11fff465bd24343486e), ROM_BIOS(4) ) -ROM_END - -} // anonymous namespace - - -/* Driver */ - -/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS, INIT COMPANY FULLNAME FLAGS */ -COMP( 1977, h8, 0, 0, h8, h8, h8_state, empty_init, "Heath Company", "Heathkit H8 Digital Computer", MACHINE_SUPPORTS_SAVE ) diff --git a/src/mame/heathkit/h89.cpp b/src/mame/heathkit/h89.cpp deleted file mode 100644 index 50154f85382..00000000000 --- a/src/mame/heathkit/h89.cpp +++ /dev/null @@ -1,1007 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Sandro Ronco, Mark Garlanger -/*************************************************************************** - - Heathkit H89 - - Heath Company made several very similar systems, including - - H88 - kit, came with a cassette interface board instead of floppy controller - - H89 - kit, came with a hard-sectored floppy disk controller - - WH89 - was factory assembled - - Heath's parent company Zenith, also sold systems under the Zenith Data - Systems brand. These were all factory assembled - - Z-89 - same as Heath's H89, but assembled - - Z-90 - came with a soft-sectored floppy disk controller - - Monitor Commands (for MTR-90): - B Boot - C Convert (number) - G Go (address) - I In (address) - O Out (address,data) - R Radix (H/O) - S Substitute (address) - T Test Memory - V View - - Monitor Commands (for MTR-88) - B Boot - D Dump - dump a program to cassette - G Go (address) - L Load - load a program from cassette - P Program Counter (address) - select an address in the PC - S Substitute - inspect or change memory - - Monitor Commands (for MTR-89) - B Boot - G Go (address) - P Program Counter (address) - select an address in the PC - S Substitute - inspect or change memory - -****************************************************************************/ - -#include "emu.h" - -#include "h_88_cass.h" -#include "intr_cntrl.h" -#include "sigmasoft_parallel_port.h" -#include "tlb.h" -#include "z37_fdc.h" - -#include "cpu/z80/z80.h" -#include "machine/ins8250.h" -#include "machine/ram.h" -#include "machine/timer.h" - -#include "softlist_dev.h" - -#include "h89.lh" - - -// Single Step -#define LOG_SS (1U << 1) - -// #define VERBOSE ( LOG_SS ) -#include "logmacro.h" - -#define LOGSS(...) LOGMASKED(LOG_SS, __VA_ARGS__) - - -namespace { - -/** - * Base Heathkit H89 functionality - */ -class h89_base_state : public driver_device -{ -protected: - h89_base_state(const machine_config &mconfig, device_type type, const char *tag): - driver_device(mconfig, type, tag), - m_maincpu(*this, "maincpu"), - m_maincpu_region(*this, "maincpu"), - m_mem_view(*this, "rom_bank"), - m_ram(*this, RAM_TAG), - m_floppy_ram(*this, "floppyram"), - m_tlbc(*this, "tlbc"), - m_intr_socket(*this, "intr_socket"), - m_console(*this, "console"), - m_serial1(*this, "serial1"), - m_serial2(*this, "serial2"), - m_serial3(*this, "serial3"), - m_config(*this, "CONFIG") - { - } - - void h89_base(machine_config &config); - - required_device m_maincpu; - required_memory_region m_maincpu_region; - memory_view m_mem_view; - required_device m_ram; - required_shared_ptr m_floppy_ram; - required_device m_tlbc; - required_device m_intr_socket; - required_device m_console; - required_device m_serial1; - required_device m_serial2; - required_device m_serial3; - required_ioport m_config; - memory_access<16, 0, 0, ENDIANNESS_LITTLE>::specific m_program; - - // General Purpose Port (GPP) - u8 m_gpp; - - bool m_rom_enabled; - bool m_timer_intr_enabled; - bool m_single_step_enabled; - bool m_floppy_ram_wp; - - // single step flags - bool m_555a_latch; - bool m_555b_latch; - bool m_556b_latch; - - u32 m_cpu_speed_multiplier; - - // Clocks - static constexpr XTAL H89_CLOCK = XTAL(12'288'000) / 6; - static constexpr XTAL INS8250_CLOCK = XTAL(1'843'200); - - static constexpr u8 GPP_SINGLE_STEP_BIT = 0; - static constexpr u8 GPP_ENABLE_TIMER_INTERRUPT_BIT = 1; - static constexpr u8 GPP_SPEED_SELECT_BIT = 4; - static constexpr u8 GPP_DISABLE_ROM_BIT = 5; - static constexpr u8 GPP_H17_SIDE_SELECT_BIT = 6; - - void update_mem_view(); - - void update_gpp(u8 gpp); - void port_f2_w(u8 data); - - virtual void machine_start() override; - virtual void machine_reset() override; - TIMER_DEVICE_CALLBACK_MEMBER(h89_irq_timer); - - void h89_mem(address_map &map); - void map_fetch(address_map &map); - u8 m1_r(offs_t offset); - - void h89_base_io(address_map &map); - - u8 raise_NMI_r(); - void raise_NMI_w(u8 data); - void console_intr(int data); - void reset_line(int data); - void reset_single_step_state(); -}; - -/** - * Heathkit H88 - * - BIOS MTR-88 - * - H-88-5 Cassette Interface Board - * - */ -class h88_state : public h89_base_state -{ -public: - h88_state(const machine_config &mconfig, device_type type, const char *tag): - h89_base_state(mconfig, type, tag), - m_cassette(*this, "h_88_5") - { - } - - void h88(machine_config &config); - -protected: - required_device m_cassette; - - void h88_io(address_map &map); -}; - - -/** - * Heathkit H89 - * - Z-89-37 Soft-sectored Floppy Controller - * - */ -class h89_state : public h89_base_state -{ -public: - h89_state(const machine_config &mconfig, device_type type, const char *tag): - h89_base_state(mconfig, type, tag), - m_h37(*this, "h37") - { - } - - void h89(machine_config &config); - -protected: - required_device m_h37; - - void h89_io(address_map &map); -}; - - -class h89_sigmasoft_state : public h89_state -{ -public: - h89_sigmasoft_state(const machine_config &mconfig, device_type type, const char *tag): - h89_state(mconfig, type, tag), - m_sigma_parallel(*this, "sigma_parallel") - { - } - - void h89_sigmasoft(machine_config &config); - -protected: - required_device m_sigma_parallel; - - void h89_sigmasoft_io(address_map &map); -}; - - -/* - The H89 supported 16K, 32K, 48K, or 64K of RAM. The first 8K of address space - is reserved for the monitor ROM, floppy ROM, and scratch pad RAM. For 16k-48K - sizes, the upper 8k of memory is remapped to the first 8K when the ROM is disabled. - For systems with 64K of RAM, the upper half of the expansion board is permanently - mapped to the lower 8K. Even when ROM is mapped, any writes will still occur - to the RAM. - - H89 Lower 8K address map - - HDOS Mode CP/M Mode - ------------------- 0x2000 (8k) ---------------- - | Floppy ROM | | | - ------------------- 0x1800 (6k) | | - | Floppy RAM | | | - ------------------- 0x1400 (5k) | RAM | - | Open | | | - ------------------- 0x1000 (4k) | | - | MTR-90 ROM | | | - -................-- 0x0800 (2k) | | - | MTR(88/89) ROM | | | - ------------------- 0x0000 (0k) ---------------- - - - 16K RAM Example - - HDOS CP/M - ------------- 24k - | RAM | ------+ - ------------- 16k | ------------- 16k - | RAM | -------------> | RAM | - ------------- 8k | ------------- 8k - | ROM | +------> | RAM | - ------------- 0k ------------- 0k - -*/ -void h89_base_state::h89_mem(address_map &map) -{ - map.unmap_value_high(); - - map(0x0000, 0xffff).view(m_mem_view); - - // View 0 - ROM / Floppy RAM R/O - // View 1 - ROM / Floppy RAM R/W - // monitor ROM - m_mem_view[0](0x0000, 0x0fff).rom().region("maincpu", 0).unmapw(); - m_mem_view[1](0x0000, 0x0fff).rom().region("maincpu", 0).unmapw(); - - // Floppy RAM - m_mem_view[0](0x1400, 0x17ff).readonly().share(m_floppy_ram); - m_mem_view[1](0x1400, 0x17ff).ram().share(m_floppy_ram); - - // Floppy ROM - m_mem_view[0](0x1800, 0x1fff).rom().region("maincpu", 0x1800).unmapw(); - m_mem_view[1](0x1800, 0x1fff).rom().region("maincpu", 0x1800).unmapw(); -} - -void h89_base_state::map_fetch(address_map &map) -{ - map(0x0000, 0xffff).r(FUNC(h89_base_state::m1_r)); -} - -u8 h89_base_state::m1_r(offs_t offset) -{ - u8 data = m_program.read_byte(offset); - - if (!machine().side_effects_disabled() && m_single_step_enabled && !m_556b_latch) - { - LOGSS("single step m1_r - data: 0x%02x, 555a: %d, 555b: %d, 556b: %d\n", data, m_555a_latch, m_555b_latch, m_556b_latch); - - if (!m_555a_latch) - { - // Wait for EI instruction - if (data == 0xfb) - { - m_555a_latch = true; - } - } - else if (!m_555b_latch) - { - m_555b_latch = true; - } - else if (!m_556b_latch) - { - m_556b_latch = true; - - m_intr_socket->set_irq_level(2, ASSERT_LINE); - } - } - - return data; -} - -/* - PORT - Use | Hex | Octal - --------------------------+-------+--------- - Not specified, available | 0-77 | 0-167 - Disk I/O #1 | 78-7B | 170-173 - Disk I/O #2 | 7C-7F | 174-177 - Not specified, reserved | 80-CF | 200-317 - DCE Serial I/O | D0-D7 | 320-327 - DTE Serial I/O | D8-DF | 330-337 - DCE Serial I/O | EO-E7 | 340-347 - Console I/O | E8-EF | 350-357 - NMI | F0-F1 | 360-361 - General purpose port | F2 | 362 - Cassette I/O(MTR-88) | F8-F9 | 370-371 - NMI | FA-FB | 372-373 - - Disk I/O #1 - 0170-0173 (0x78-0x7b) - Heath Options - - H37 5-1/4" Soft-sectored Controller - Requires MTR-90 ROM - - H47 Dual 8" Drives - Requires MTR-89 or MTR-90 ROM - - H67 8" Hard disk + 8" Floppy Drives - Requires MTR-90 ROM - - Disk I/O #2 - 0174-0177 (0x7c-0x7f) - Heath Options - - 5-1/4" Hard-sectored Controller - supported by all ROMs - - H47 Dual 8" Drives - Requires MTR-89 or MTR-90 ROM - - H67 8" Hard disk + 8" Floppy Drives - MTR-90 ROM - -*/ -void h89_base_state::h89_base_io(address_map &map) -{ - map.unmap_value_high(); - map.global_mask(0xff); - - // 8250 UART DCE 0320 (0xd0) - map(0xd0, 0xd7).rw(m_serial1, FUNC(ins8250_device::ins8250_r), FUNC(ins8250_device::ins8250_w)); - // 8250 UART DTE 0330 (0xd8) - typically used for modem - map(0xd8, 0xdf).rw(m_serial2, FUNC(ins8250_device::ins8250_r), FUNC(ins8250_device::ins8250_w)); - // 8250 UART DCE 0340 (0xe0) - typically used for printer - map(0xe0, 0xe7).rw(m_serial3, FUNC(ins8250_device::ins8250_r), FUNC(ins8250_device::ins8250_w)); - - // 8250 UART console - this connects internally to the Terminal Logic board that is also used in the H19. - map(0xe8, 0xef).rw(m_console, FUNC(ins8250_device::ins8250_r), FUNC(ins8250_device::ins8250_w)); - - // ports defined on the H8. On the H89, access to these addresses causes a NMI - map(0xf0, 0xf1).rw(FUNC(h89_base_state::raise_NMI_r),FUNC(h89_base_state::raise_NMI_w)); - - // General Purpose Port (GPP) - map(0xf2, 0xf2).w(FUNC(h89_base_state::port_f2_w)).portr("SW501"); - - // port defined on the H8. On the H89, access to these addresses causes a NMI - map(0xfa, 0xfb).rw(FUNC(h89_base_state::raise_NMI_r), FUNC(h89_base_state::raise_NMI_w)); -} - -void h88_state::h88_io(address_map &map) -{ - h89_base_state::h89_base_io(map); - - // Cassette I/O (uses 0xf8 - 0xf9) - Requires MTR-88 ROM - map(0xf8, 0xf9).rw(m_cassette, FUNC(heath_h_88_cass_device::read), FUNC(heath_h_88_cass_device::write)); -} - -void h89_state::h89_io(address_map &map) -{ - h89_base_state::h89_base_io(map); - - // H37 5-1/4" Soft-sectored Controller - Requires MTR-90 ROM - map(0x78, 0x7b).rw(m_h37, FUNC(heath_z37_fdc_device::read), FUNC(heath_z37_fdc_device::write)); -} - -void h89_sigmasoft_state::h89_sigmasoft_io(address_map &map) -{ - h89_io(map); - - // Add SigmaSoft parallel port board, required for IGC graphics - map(0x08,0x0f).rw(m_sigma_parallel, FUNC(sigmasoft_parallel_port::read), FUNC(sigmasoft_parallel_port::write)); -} - - -// Input ports -static INPUT_PORTS_START( h88 ) - - PORT_START("SW501") - // MTR-88 (444-40) - PORT_DIPUNUSED_DIPLOC(0x01, 0x00, "SW501:1") - PORT_DIPUNUSED_DIPLOC(0x02, 0x00, "SW501:2") - PORT_DIPUNUSED_DIPLOC(0x04, 0x00, "SW501:3") - PORT_DIPUNUSED_DIPLOC(0x08, 0x00, "SW501:4") - PORT_DIPUNUSED_DIPLOC(0x10, 0x00, "SW501:5") - PORT_DIPNAME( 0x20, 0x20, "Perform memory test at start" ) PORT_DIPLOCATION("SW501:6") - PORT_DIPSETTING( 0x20, DEF_STR( No ) ) - PORT_DIPSETTING( 0x00, DEF_STR( Yes ) ) - PORT_DIPNAME( 0xc0, 0x00, "Console Baud rate" ) PORT_DIPLOCATION("SW501:7,8") - PORT_DIPSETTING( 0x00, "9600" ) - PORT_DIPSETTING( 0x40, "19200" ) - PORT_DIPSETTING( 0x80, "38400" ) - PORT_DIPSETTING( 0xc0, "57600" ) - - PORT_START("CONFIG") - PORT_CONFNAME( 0x03, 0x00, "CPU Clock Speed Upgrade") - PORT_CONFSETTING( 0x00, DEF_STR( None ) ) - PORT_CONFSETTING( 0x01, "2 / 4 MHz") - PORT_CONFSETTING( 0x02, "2 / 6 MHz") - -INPUT_PORTS_END - - -static INPUT_PORTS_START( h89 ) - - PORT_START("SW501") - // Generic definition - PORT_DIPNAME( 0x01, 0x00, "Switch 0" ) PORT_DIPLOCATION("SW501:1") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x00) - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x01, DEF_STR( On ) ) - PORT_DIPNAME( 0x02, 0x00, "Switch 1" ) PORT_DIPLOCATION("SW501:2") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x00) - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x02, DEF_STR( On ) ) - PORT_DIPNAME( 0x04, 0x00, "Switch 2" ) PORT_DIPLOCATION("SW501:3") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x00) - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x04, DEF_STR( On ) ) - PORT_DIPNAME( 0x08, 0x00, "Switch 3" ) PORT_DIPLOCATION("SW501:4") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x00) - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x08, DEF_STR( On ) ) - PORT_DIPNAME( 0x10, 0x00, "Switch 4" ) PORT_DIPLOCATION("SW501:5") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x00) - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x10, DEF_STR( On ) ) - PORT_DIPNAME( 0x20, 0x20, "Switch 5" ) PORT_DIPLOCATION("SW501:6") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x00) - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x20, DEF_STR( On ) ) - PORT_DIPNAME( 0x40, 0x00, "Switch 6" ) PORT_DIPLOCATION("SW501:7") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x00) - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x40, DEF_STR( On ) ) - PORT_DIPNAME( 0x80, 0x00, "Switch 7" ) PORT_DIPLOCATION("SW501:8") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x00) - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x80, DEF_STR( On ) ) - - // MTR-90 (444-84 or 444-142) - PORT_DIPNAME( 0x03, 0x00, "Disk I/O #2" ) PORT_DIPLOCATION("SW501:1,2") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x04) - PORT_DIPSETTING( 0x00, "H-88-1 (Not yet implemented)" ) - PORT_DIPSETTING( 0x01, "H/Z-47 (Not yet implemented)" ) - PORT_DIPSETTING( 0x02, "Z-67 (Not yet implemented)" ) - PORT_DIPSETTING( 0x03, "Undefined" ) - PORT_DIPNAME( 0x0c, 0x00, "Disk I/O #1" ) PORT_DIPLOCATION("SW501:3,4") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x04) - PORT_DIPSETTING( 0x00, "H-89-37" ) - PORT_DIPSETTING( 0x04, "H/Z-47 (Not yet implemented)" ) - PORT_DIPSETTING( 0x08, "Z-67 (Not yet implemented)" ) - PORT_DIPSETTING( 0x0c, "Undefined" ) - PORT_DIPNAME( 0x10, 0x00, "Primary Boot from" ) PORT_DIPLOCATION("SW501:5") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x04) - PORT_DIPSETTING( 0x00, "Disk I/O #2" ) - PORT_DIPSETTING( 0x10, "Disk I/O #1" ) - PORT_DIPNAME( 0x20, 0x20, "Perform memory test at start" ) PORT_DIPLOCATION("SW501:6") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x04) - PORT_DIPSETTING( 0x20, DEF_STR( No ) ) - PORT_DIPSETTING( 0x00, DEF_STR( Yes ) ) - PORT_DIPNAME( 0x40, 0x00, "Console Baud rate" ) PORT_DIPLOCATION("SW501:7") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x04) - PORT_DIPSETTING( 0x00, "9600" ) - PORT_DIPSETTING( 0x40, "19200" ) - PORT_DIPNAME( 0x80, 0x00, "Boot mode" ) PORT_DIPLOCATION("SW501:8") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x04) - PORT_DIPSETTING( 0x00, DEF_STR( Normal ) ) - PORT_DIPSETTING( 0x80, "Auto" ) - - // MTR-89 (444-62) - PORT_DIPNAME( 0x03, 0x00, "Disk I/O #2" ) PORT_DIPLOCATION("SW501:1,2") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x08) - PORT_DIPSETTING( 0x00, "H-88-1" ) - PORT_DIPSETTING( 0x01, "H/Z-47" ) - PORT_DIPSETTING( 0x02, "Undefined" ) - PORT_DIPSETTING( 0x03, "Undefined" ) - PORT_DIPNAME( 0x0c, 0x00, "Disk I/O #1" ) PORT_DIPLOCATION("SW501:3,4") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x08) - PORT_DIPSETTING( 0x00, "Unused" ) - PORT_DIPSETTING( 0x04, "H/Z-47" ) - PORT_DIPSETTING( 0x08, "Undefined" ) - PORT_DIPSETTING( 0x0c, "Undefined" ) - PORT_DIPNAME( 0x10, 0x00, "Primary Boot from" ) PORT_DIPLOCATION("SW501:5") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x08) - PORT_DIPSETTING( 0x00, "Disk I/O #2" ) - PORT_DIPSETTING( 0x10, "Disk I/O #1" ) - PORT_DIPNAME( 0x20, 0x20, "Perform memory test at start" ) PORT_DIPLOCATION("SW501:6") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x08) - PORT_DIPSETTING( 0x20, DEF_STR( No ) ) - PORT_DIPSETTING( 0x00, DEF_STR( Yes ) ) - PORT_DIPNAME( 0x40, 0x00, "Console Baud rate" ) PORT_DIPLOCATION("SW501:7") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x08) - PORT_DIPSETTING( 0x00, "9600" ) - PORT_DIPSETTING( 0x40, "19200" ) - PORT_DIPNAME( 0x80, 0x00, "Boot mode" ) PORT_DIPLOCATION("SW501:8") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x08) - PORT_DIPSETTING( 0x00, DEF_STR( Normal ) ) - PORT_DIPSETTING( 0x80, "Auto" ) - - // MMS 444-84B (and possibly 444-84A) - PORT_DIPNAME( 0x03, 0x00, "Disk I/O #2" ) PORT_DIPLOCATION("SW501:1,2") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x0c) - PORT_DIPSETTING( 0x00, "H-88-1" ) - PORT_DIPSETTING( 0x01, "H/Z-47 (Not yet implemented)" ) - PORT_DIPSETTING( 0x02, "MMS 77320 SASI or Z-67 (Not yet implemented)" ) - PORT_DIPSETTING( 0x03, "MMS 77422 Network Controller" ) - PORT_DIPNAME( 0x0c, 0x00, "Disk I/O #1" ) PORT_DIPLOCATION("SW501:3,4") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x0c) - PORT_DIPSETTING( 0x00, "H-89-37" ) - PORT_DIPSETTING( 0x04, "H/Z-47 (Not yet implemented)" ) - PORT_DIPSETTING( 0x08, "MMS 77320 SASI or Z-67 (Not yet implemented)" ) - PORT_DIPSETTING( 0x0c, "MMS 77422 Network Controller" ) - PORT_DIPNAME( 0x70, 0x00, "Default Boot Device" ) PORT_DIPLOCATION("SW501:5,6,7") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x0c) - PORT_DIPSETTING( 0x00, "MMS 77316 Dbl Den 5\"" ) - PORT_DIPSETTING( 0x10, "MMS 77316 Dbl Den 8\"" ) - PORT_DIPSETTING( 0x20, "Disk Device at 0x7C" ) - PORT_DIPSETTING( 0x30, "Disk Device at 0x78" ) - PORT_DIPSETTING( 0x40, "reserved for future use" ) - PORT_DIPSETTING( 0x50, "reserved for future use" ) - PORT_DIPSETTING( 0x60, "MMS Network (77422)" ) - PORT_DIPSETTING( 0x70, "Use MMS I/O board Config Port" ) - PORT_DIPNAME( 0x80, 0x00, "Boot mode" ) PORT_DIPLOCATION("SW501:8") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x0c) - PORT_DIPSETTING( 0x00, DEF_STR( Normal ) ) - PORT_DIPSETTING( 0x80, "Auto" ) - - // Kres KMR-100 - PORT_DIPNAME( 0x0f, 0x00, "Default Boot Device" ) PORT_DIPLOCATION("SW501:1,2,3,4") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x10) - PORT_DIPSETTING( 0x00, "H-17 hard-sectored 5\" floppy units 0-2" ) - PORT_DIPSETTING( 0x01, "H-37 soft-sectored 5\" floppy units 0-3" ) - PORT_DIPSETTING( 0x02, "Corvus hard disk/Magnolia interface, partitions 0-8" ) - PORT_DIPSETTING( 0x03, "CDR 5\"/8\" double density floppy, units 0-3" ) - PORT_DIPSETTING( 0x04, "H-47 8\" floppy at port 0x78/0170, units 0-3" ) - PORT_DIPSETTING( 0x05, "H-47 8\" floppy at port 0x7c/0174, units 0-3" ) - PORT_DIPSETTING( 0x06, "Reserved" ) - PORT_DIPSETTING( 0x07, "Help - lists boot devices" ) - PORT_DIPSETTING( 0x08, "Reserved" ) - PORT_DIPSETTING( 0x09, "SASI controller or Z-67 at port 0x78/0170, units 0-7" ) - PORT_DIPSETTING( 0x0a, "SASI controller or Z-67 at port 0x7c/0174, units 0-7" ) - PORT_DIPSETTING( 0x0b, "Livingston 8\" single density floppy, units 0-3" ) - PORT_DIPSETTING( 0x0c, "Magnolia 5\"/8\" double density floppy, units 0-3 (8\"), 4-7 (5\")" ) - PORT_DIPSETTING( 0x0d, "Reserved" ) - PORT_DIPSETTING( 0x0e, "Reserved" ) - PORT_DIPSETTING( 0x0f, "Magnolia 128K pseudo disk, banks 0-1" ) - PORT_DIPNAME( 0x10, 0x00, "Map ROM into RAM on boot" ) PORT_DIPLOCATION("SW501:5") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x10) - PORT_DIPSETTING( 0x00, DEF_STR( Yes ) ) - PORT_DIPSETTING( 0x10, DEF_STR( No ) ) - PORT_DIPNAME( 0x20, 0x20, "Perform memory test at start" ) PORT_DIPLOCATION("SW501:6") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x10) - PORT_DIPSETTING( 0x20, DEF_STR( No ) ) - PORT_DIPSETTING( 0x00, DEF_STR( Yes ) ) - PORT_DIPNAME( 0x40, 0x00, "Have a LLL controller installed" ) PORT_DIPLOCATION("SW501:7") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x10) - PORT_DIPSETTING( 0x00, DEF_STR( No ) ) - PORT_DIPSETTING( 0x40, DEF_STR( Yes ) ) - PORT_DIPNAME( 0x80, 0x00, "Boot mode" ) PORT_DIPLOCATION("SW501:8") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x10) - PORT_DIPSETTING( 0x00, DEF_STR( Normal ) ) - PORT_DIPSETTING( 0x80, "Auto" ) - - // Ultimeth MTRHEX-4k - // (values based on testing and comparison with the Kres KMR-100 ROM which was also written by Ultimeth) - PORT_DIPNAME( 0x0f, 0x00, "Default Boot Device" ) PORT_DIPLOCATION("SW501:1,2,3,4") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x14) - PORT_DIPSETTING( 0x00, "H-17 hard-sectored 5\" floppy" ) - PORT_DIPSETTING( 0x01, "H-37 soft-sectored 5\" floppy" ) - PORT_DIPSETTING( 0x02, "? Corvus hard disk/Magnolia interface" ) - PORT_DIPSETTING( 0x03, "? CDR 5\"/8\" double density floppy" ) - PORT_DIPSETTING( 0x04, "? H-47 8\" floppy at port 0x78/0170" ) - PORT_DIPSETTING( 0x05, "? H-47 8\" floppy at port 0x7c/0174" ) - PORT_DIPSETTING( 0x06, "? Reserved" ) - PORT_DIPSETTING( 0x07, "? Reserved" ) - PORT_DIPSETTING( 0x08, "? Reserved" ) - PORT_DIPSETTING( 0x09, "? SASI controller or Z-67 at port 0x78/0170" ) - PORT_DIPSETTING( 0x0a, "? SASI controller or Z-67 at port 0x7c/0174" ) - PORT_DIPSETTING( 0x0b, "? Livingston 8\" single density floppy" ) - PORT_DIPSETTING( 0x0c, "? Magnolia 5\"/8\" double density floppy" ) - PORT_DIPSETTING( 0x0d, "? Reserved" ) - PORT_DIPSETTING( 0x0e, "? Reserved" ) - PORT_DIPSETTING( 0x0f, "? Magnolia 128K pseudo disk" ) - PORT_DIPNAME( 0x10, 0x00, "? Map ROM into RAM on boot" ) PORT_DIPLOCATION("SW501:5") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x14) - PORT_DIPSETTING( 0x00, "? Yes" ) - PORT_DIPSETTING( 0x10, "? No" ) - PORT_DIPNAME( 0x20, 0x20, "Perform memory test at start" ) PORT_DIPLOCATION("SW501:6") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x14) - PORT_DIPSETTING( 0x20, DEF_STR( No ) ) - PORT_DIPSETTING( 0x00, DEF_STR( Yes ) ) - PORT_DIPNAME( 0x40, 0x00, "? Have a LLL controller installed" ) PORT_DIPLOCATION("SW501:7") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x14) - PORT_DIPSETTING( 0x00, "? No" ) - PORT_DIPSETTING( 0x40, "? Yes" ) - PORT_DIPNAME( 0x80, 0x00, "Boot mode" ) PORT_DIPLOCATION("SW501:8") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x14) - PORT_DIPSETTING( 0x00, DEF_STR( Normal ) ) - PORT_DIPSETTING( 0x80, "Auto" ) - - // Ultimeth MTRHEX-2k - PORT_DIPNAME( 0x03, 0x00, "Default Boot Device" ) PORT_DIPLOCATION("SW501:1,2") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x18) - PORT_DIPSETTING( 0x00, "H-17 hard-sectored 5\" floppy" ) - PORT_DIPSETTING( 0x01, "H-47 8\" floppy at port 0x78/0170" ) - PORT_DIPSETTING( 0x02, "H-47 8\" floppy at port 0x7c/0174" ) - PORT_DIPSETTING( 0x03, "Magnolia 5\"/8\" double density floppy" ) - PORT_DIPUNUSED_DIPLOC(0x04, 0x00, "SW501:3") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x18) - PORT_DIPUNUSED_DIPLOC(0x08, 0x00, "SW501:4") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x18) - PORT_DIPUNUSED_DIPLOC(0x10, 0x00, "SW501:5") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x18) - PORT_DIPNAME( 0x20, 0x20, "Perform memory test at start" ) PORT_DIPLOCATION("SW501:6") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x18) - PORT_DIPSETTING( 0x20, DEF_STR( No ) ) - PORT_DIPSETTING( 0x00, DEF_STR( Yes ) ) - PORT_DIPNAME( 0x40, 0x00, "Boot mode" ) PORT_DIPLOCATION("SW501:7") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x18) - PORT_DIPSETTING( 0x00, DEF_STR( Normal ) ) - PORT_DIPSETTING( 0x40, "Auto" ) - PORT_DIPNAME( 0x80, 0x00, "Baud Rate" ) PORT_DIPLOCATION("SW501:8") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x18) - PORT_DIPSETTING( 0x00, "9600" ) - PORT_DIPSETTING( 0x80, "19200" ) - - - PORT_START("CONFIG") - PORT_CONFNAME(0x03, 0x00, "CPU Clock Speed Upgrade") - PORT_CONFSETTING( 0x00, DEF_STR( None ) ) - PORT_CONFSETTING( 0x01, "2 / 4 MHz") - PORT_CONFSETTING( 0x02, "2 / 6 MHz") - PORT_CONFNAME(0x3c, 0x04, "Switch SW501 Definitions") - PORT_CONFSETTING( 0x00, "Generic" ) - PORT_CONFSETTING( 0x04, "Heath MTR-90") - PORT_CONFSETTING( 0x08, "Heath MTR-89") - PORT_CONFSETTING( 0x0c, "MMS 444-84B/444-84A") - PORT_CONFSETTING( 0x10, "Kres KMR-100") - PORT_CONFSETTING( 0x14, "Ultimeth MTRHEX-4k") - PORT_CONFSETTING( 0x18, "Ultimeth MTRHEX-2k") - -INPUT_PORTS_END - - -void h89_base_state::machine_start() -{ - save_item(NAME(m_gpp)); - save_item(NAME(m_rom_enabled)); - save_item(NAME(m_timer_intr_enabled)); - save_item(NAME(m_single_step_enabled)); - save_item(NAME(m_floppy_ram_wp)); - save_item(NAME(m_cpu_speed_multiplier)); - save_item(NAME(m_555a_latch)); - save_item(NAME(m_555b_latch)); - save_item(NAME(m_556b_latch)); - - m_maincpu->space(AS_PROGRAM).specific(m_program); - - // update RAM mappings based on RAM size - u8 *m_ram_ptr = m_ram->pointer(); - u32 ram_size = m_ram->size(); - - if (ram_size == 0x10000) - { - // system has a full 64k - m_maincpu->space(AS_PROGRAM).install_ram(0x2000, 0xffff, m_ram_ptr); - - // install shadow writing to RAM when in ROM mode - m_mem_view[0].install_writeonly(0x0000, 0x1fff, m_ram_ptr + 0xe000); - m_mem_view[1].install_writeonly(0x0000, 0x1fff, m_ram_ptr + 0xe000); - - // Only the CP/M - Org 0 view will have RAM at the lower 8k - m_mem_view[2].install_ram(0x0000, 0x1fff, m_ram_ptr + 0xe000); - } - else - { - // less than 64k - - // for views with ROM visible, the top of memory is 8k higher than - // the memory size, since the base starts at 8k. - u32 ram_top = ram_size + 0x1fff; - - m_mem_view[0].install_ram(0x2000, ram_top, m_ram_ptr); - m_mem_view[1].install_ram(0x2000, ram_top, m_ram_ptr); - - // when ROM is not active, memory still starts at 8k, but is 8k smaller - m_mem_view[2].install_ram(0x2000, ram_size - 1, m_ram_ptr); - - // remap the top 8k down to addr 0 - m_mem_view[2].install_ram(0x0000, 0x1fff, m_ram_ptr + ram_size - 0x2000); - } -} - -void h89_base_state::machine_reset() -{ - m_rom_enabled = true; - m_timer_intr_enabled = true; - m_single_step_enabled = false; - m_floppy_ram_wp = false; - reset_single_step_state(); - - ioport_value const cfg(m_config->read()); - - // CPU clock speed - const u8 selected_clock_upgrade = cfg & 0x3; - - switch (selected_clock_upgrade) - { - case 0x01: - // 4 MHz was offered by several companies including Kres, ANAPRO, and an article - // in REMark magazine. - m_cpu_speed_multiplier = 2; - break; - case 0x02: - // 6 MHz was offered by at least ANAPRO, and a how to article in CHUG newsletter - m_cpu_speed_multiplier = 3; - break; - case 0x00: - default: - // No speed upgrade installed - Standard Clock - m_cpu_speed_multiplier = 1; - break; - } - - update_gpp(0); - update_mem_view(); -} - -u8 h89_base_state::raise_NMI_r() -{ - m_maincpu->pulse_input_line(INPUT_LINE_NMI, attotime::from_usec(2)); - - return 0x00; -} - -void h89_base_state::raise_NMI_w(u8) -{ - m_maincpu->pulse_input_line(INPUT_LINE_NMI, attotime::from_usec(2)); -} - -void h89_base_state::console_intr(int data) -{ - m_intr_socket->set_irq_level(3, data); -} - -void h89_base_state::reset_line(int data) -{ - if (bool(data)) - { - reset(); - } - m_maincpu->set_input_line(INPUT_LINE_RESET, data); -} - -TIMER_DEVICE_CALLBACK_MEMBER(h89_base_state::h89_irq_timer) -{ - if (m_timer_intr_enabled) - { - m_intr_socket->set_irq_level(1, ASSERT_LINE); - } -} - -void h89_base_state::update_mem_view() -{ - m_mem_view.select(m_rom_enabled ? (m_floppy_ram_wp ? 0 : 1) : 2); -} - -void h89_base_state::reset_single_step_state() -{ - LOGSS("reset_single_step_state\n"); - m_555a_latch = false; - m_555b_latch = false; - m_556b_latch = false; - m_intr_socket->set_irq_level(2, CLEAR_LINE); -} - -// General Purpose Port -// -// Bit OUTPUT -// --------------------- -// 0 Single-step enable -// 1 2 mSec interrupt enable -// 2 Latched bit MEM 1 H on memory exp connector -// 3 Not used -// 4 Latched bit MEM 0 H on memory expansion connector (Commonly used for Speed upgrades) -// 5 ORG-0 (CP/M map) -// 6 Latched bit I/O 0 on I/O exp connector -// 7 Latched bit I/O 1 on I/O exp connector -// -void h89_base_state::update_gpp(u8 gpp) -{ - u8 changed_gpp = gpp ^ m_gpp; - - m_gpp = gpp; - - m_timer_intr_enabled = bool(BIT(m_gpp, GPP_ENABLE_TIMER_INTERRUPT_BIT)); - - if (BIT(changed_gpp, GPP_SINGLE_STEP_BIT)) - { - LOGSS("single step enable: %d\n", BIT(m_gpp, GPP_SINGLE_STEP_BIT)); - m_single_step_enabled = bool(BIT(m_gpp, GPP_SINGLE_STEP_BIT)); - - if (!m_single_step_enabled) - { - reset_single_step_state(); - } - } - - if (BIT(changed_gpp, GPP_DISABLE_ROM_BIT)) - { - m_rom_enabled = BIT(m_gpp, GPP_DISABLE_ROM_BIT) == 0; - - update_mem_view(); - } - - if (BIT(changed_gpp, GPP_SPEED_SELECT_BIT)) - { - m_maincpu->set_clock(BIT(m_gpp, GPP_SPEED_SELECT_BIT) ? - H89_CLOCK * m_cpu_speed_multiplier : H89_CLOCK); - } -} - -// General Purpose Port -void h89_base_state::port_f2_w(u8 data) -{ - update_gpp(data); - - m_intr_socket->set_irq_level(1, CLEAR_LINE); -} - -static void tlb_options(device_slot_interface &device) -{ - device.option_add("heath", HEATH_TLB); - device.option_add("gp19", HEATH_GP19); - device.option_add("imaginator", HEATH_IMAGINATOR); - device.option_add("super19", HEATH_SUPER19); - device.option_add("superset", HEATH_SUPERSET); - device.option_add("ultrarom", HEATH_ULTRA); - device.option_add("watzman", HEATH_WATZ); -} - - -static void sigma_tlb_options(device_slot_interface *device) -{ - device->option_reset(); - device->option_add("igc", HEATH_IGC); - device->option_add("igc_super19", HEATH_IGC_SUPER19); - device->option_add("igc_ultrarom", HEATH_IGC_ULTRA); - device->option_add("igc_watzman", HEATH_IGC_WATZ); - device->set_default_option("igc"); -} - -static void intr_ctrl_options(device_slot_interface &device) -{ - device.option_add("original", HEATH_INTR_CNTRL); - device.option_add("h37", HEATH_Z37_INTR_CNTRL); -} - -void h89_base_state::h89_base(machine_config &config) -{ - config.set_default_layout(layout_h89); - - // basic machine hardware - Z80(config, m_maincpu, H89_CLOCK); - m_maincpu->set_m1_map(&h89_base_state::map_fetch); - m_maincpu->set_memory_map(&h89_base_state::h89_mem); - m_maincpu->set_irq_acknowledge_callback("intr_socket", FUNC(heath_intr_socket::irq_callback)); - - RAM(config, m_ram).set_default_size("64K").set_extra_options("16K,32K,48K").set_default_value(0x00); - - HEATH_INTR_SOCKET(config, m_intr_socket, intr_ctrl_options, nullptr); - m_intr_socket->irq_line_cb().set_inputline(m_maincpu, INPUT_LINE_IRQ0); - - INS8250(config, m_console, INS8250_CLOCK); - m_console->out_int_callback().set(FUNC(h89_base_state::console_intr)); - - HEATH_TLB_CONNECTOR(config, m_tlbc, tlb_options, "heath"); - - // Connect the console port on CPU board to TLB connector - m_console->out_tx_callback().set(m_tlbc, FUNC(heath_tlb_connector::serial_in_w)); - m_console->out_rts_callback().set(m_tlbc, FUNC(heath_tlb_connector::cts_in_w)); - m_console->out_dtr_callback().set(m_tlbc, FUNC(heath_tlb_connector::dsr_in_w)); - m_tlbc->serial_data_callback().set(m_console, FUNC(ins8250_uart_device::rx_w)); - m_tlbc->rts_callback().set(m_console, FUNC(ins8250_uart_device::cts_w)); - m_tlbc->dtr_callback().set(m_console, FUNC(ins8250_uart_device::dsr_w)); - - m_tlbc->reset_cb().set(FUNC(h89_base_state::reset_line)); - - // H-88-3 3-port serial board - INS8250(config, m_serial1, INS8250_CLOCK); - INS8250(config, m_serial2, INS8250_CLOCK); - INS8250(config, m_serial3, INS8250_CLOCK); - - // H89 interrupt interval is 2mSec - TIMER(config, "irq_timer", 0).configure_periodic(FUNC(h89_base_state::h89_irq_timer), attotime::from_msec(2)); -} - -void h88_state::h88(machine_config &config) -{ - h89_base(config); - - m_maincpu->set_io_map(&h88_state::h88_io); - - m_intr_socket->set_default_option("original"); - m_intr_socket->set_fixed(true); - - SOFTWARE_LIST(config, "cass_list").set_original("h88_cass"); - - // H-88-5 Cassette interface board - HEATH_H88_CASS(config, m_cassette, H89_CLOCK); -} - -void h89_state::h89(machine_config &config) -{ - h89_base(config); - - m_maincpu->set_io_map(&h89_state::h89_io); - - m_intr_socket->set_default_option("h37"); - m_intr_socket->set_fixed(true); - - // Z-89-37 Soft-sectored controller - HEATH_Z37_FDC(config, m_h37); - m_h37->drq_cb().set(m_intr_socket, FUNC(heath_intr_socket::set_drq)); - m_h37->irq_cb().set(m_intr_socket, FUNC(heath_intr_socket::set_irq)); - m_h37->block_interrupt_cb().set(m_intr_socket, FUNC(heath_intr_socket::block_interrupts)); -} - -void h89_sigmasoft_state::h89_sigmasoft(machine_config & config) -{ - h89(config); - m_maincpu->set_addrmap(AS_IO, &h89_sigmasoft_state::h89_sigmasoft_io); - - sigma_tlb_options(m_tlbc); - - SIGMASOFT_PARALLEL_PORT(config, m_sigma_parallel); - m_sigma_parallel->ctrl_r_cb().set(m_tlbc, FUNC(heath_tlb_connector::sigma_ctrl_r)); - m_sigma_parallel->video_mem_r_cb().set(m_tlbc, FUNC(heath_tlb_connector::sigma_video_mem_r)); - m_sigma_parallel->video_mem_cb().set(m_tlbc, FUNC(heath_tlb_connector::sigma_video_mem_w)); - m_sigma_parallel->io_lo_cb().set(m_tlbc, FUNC(heath_tlb_connector::sigma_io_lo_addr_w)); - m_sigma_parallel->io_hi_cb().set(m_tlbc, FUNC(heath_tlb_connector::sigma_io_hi_addr_w)); - m_sigma_parallel->window_lo_cb().set(m_tlbc, FUNC(heath_tlb_connector::sigma_window_lo_addr_w)); - m_sigma_parallel->window_hi_cb().set(m_tlbc, FUNC(heath_tlb_connector::sigma_window_hi_addr_w)); - m_sigma_parallel->ctrl_cb().set(m_tlbc, FUNC(heath_tlb_connector::sigma_ctrl_w)); -} - - -// ROM definition -ROM_START( h88 ) - ROM_REGION( 0x2000, "maincpu", ROMREGION_ERASEFF ) - - ROM_LOAD( "2716_444-19_h17.u520", 0x1800, 0x0800, CRC(26e80ae3) SHA1(0c0ee95d7cb1a760f924769e10c0db1678f2435c)) - - ROM_LOAD("2716_444-40_mtr88.u518", 0x0000, 0x0800, CRC(093afb79) SHA1(bcc1569ad9da7babf0a4199cab96d8cd59b2dd78)) -ROM_END - -// ROM definition -ROM_START( h89 ) - ROM_REGION( 0x2000, "maincpu", ROMREGION_ERASEFF ) - ROM_DEFAULT_BIOS("mtr90") - - ROM_LOAD( "2716_444-19_h17.u520", 0x1800, 0x0800, CRC(26e80ae3) SHA1(0c0ee95d7cb1a760f924769e10c0db1678f2435c)) - - ROM_SYSTEM_BIOS(0, "mtr90", "MTR-90 (444-142)") - ROMX_LOAD("2732_444-142_mtr90.u518", 0x0000, 0x1000, CRC(c4ff47c5) SHA1(d6f3d71ff270a663003ec18a3ed1fa49f627123a), ROM_BIOS(0)) - - ROM_SYSTEM_BIOS(1, "mtr89", "MTR-89 (444-62)") - ROMX_LOAD("2716_444-62_mtr89.u518", 0x0000, 0x0800, CRC(8f507972) SHA1(ac6c6c1344ee4e09fb60d53c85c9b761217fe9dc), ROM_BIOS(1)) - - ROM_SYSTEM_BIOS(2, "mms84b", "MMS 444-84B") - ROMX_LOAD("2732_444_84b_mms.u518", 0x0000, 0x1000, CRC(7e75d6f4) SHA1(baf34e036388d1a191197e31f8a93209f04fc58b), ROM_BIOS(2)) - - ROM_SYSTEM_BIOS(3, "kmr-100", "Kres KMR-100 V3.a.02") - ROMX_LOAD("2732_kmr100_v3_a_02.u518", 0x0000, 0x1000, CRC(fd491592) SHA1(3d5803f95c38b237b07cd230353cd9ddc9858c13), ROM_BIOS(3)) - - ROM_SYSTEM_BIOS(4, "mtrhex_4k", "Ultimeth 4k ROM") - ROMX_LOAD("2732_mtrhex_4k.u518", 0x0000, 0x1000, CRC(e26b29a9) SHA1(ba13d6c9deef682a9a8262bc910d46b577929a13), ROM_BIOS(4)) - - ROM_SYSTEM_BIOS(5, "mtr90-84", "Heath's MTR-90 (444-84 - Superseded by 444-142)") - ROMX_LOAD("2732_444-84_mtr90.u518", 0x0000, 0x1000, CRC(f10fca03) SHA1(c4a978153af0f2dfcc9ba05be4c1033d33fee30b), ROM_BIOS(5)) - - ROM_SYSTEM_BIOS(6, "mms84a", "MMS 444-84A (Superseded by MMS 444-84B)") - ROMX_LOAD("2732_444_84a_mms.u518", 0x0000, 0x1000, CRC(0e541a7e) SHA1(b1deb620fc89c1068e2e663e14be69d1f337a4b9), ROM_BIOS(6)) - - ROM_SYSTEM_BIOS(7, "mtrhex", "Ultimeth 2k ROM") - ROMX_LOAD("2716_mtrhex.u518", 0x0000, 0x0800, CRC(842a306a) SHA1(ddbc2b8bb127464af9eda8e7c56e6be7c8b43a16), ROM_BIOS(7)) -ROM_END - -ROM_START( h89_sigmasoft ) - ROM_REGION( 0x2000, "maincpu", ROMREGION_ERASEFF ) - ROM_DEFAULT_BIOS("mtr90") - - ROM_LOAD( "2716_444-19_h17.u520", 0x1800, 0x0800, CRC(26e80ae3) SHA1(0c0ee95d7cb1a760f924769e10c0db1678f2435c)) - - ROM_SYSTEM_BIOS(0, "mtr90", "MTR-90 (444-142)") - ROMX_LOAD("2732_444-142_mtr90.u518", 0x0000, 0x1000, CRC(c4ff47c5) SHA1(d6f3d71ff270a663003ec18a3ed1fa49f627123a), ROM_BIOS(0)) - - ROM_SYSTEM_BIOS(1, "mtr89", "MTR-89 (444-62)") - ROMX_LOAD("2716_444-62_mtr89.u518", 0x0000, 0x0800, CRC(8f507972) SHA1(ac6c6c1344ee4e09fb60d53c85c9b761217fe9dc), ROM_BIOS(1)) - - ROM_SYSTEM_BIOS(2, "mms84b", "MMS 444-84B") - ROMX_LOAD("2732_444_84b_mms.u518", 0x0000, 0x1000, CRC(7e75d6f4) SHA1(baf34e036388d1a191197e31f8a93209f04fc58b), ROM_BIOS(2)) - - ROM_SYSTEM_BIOS(3, "kmr-100", "Kres KMR-100 V3.a.02") - ROMX_LOAD("2732_kmr100_v3_a_02.u518", 0x0000, 0x1000, CRC(fd491592) SHA1(3d5803f95c38b237b07cd230353cd9ddc9858c13), ROM_BIOS(3)) - - ROM_SYSTEM_BIOS(4, "mtrhex_4k", "Ultimeth ROM") - ROMX_LOAD("2732_mtrhex_4k.u518", 0x0000, 0x1000, CRC(e26b29a9) SHA1(ba13d6c9deef682a9a8262bc910d46b577929a13), ROM_BIOS(4)) - - ROM_SYSTEM_BIOS(5, "mtr90-84", "Heath's MTR-90 (444-84 - Superseded by 444-142)") - ROMX_LOAD("2732_444-84_mtr90.u518", 0x0000, 0x1000, CRC(f10fca03) SHA1(c4a978153af0f2dfcc9ba05be4c1033d33fee30b), ROM_BIOS(5)) - - ROM_SYSTEM_BIOS(6, "mms84a", "MMS 444-84A (Superseded by MMS 444-84B)") - ROMX_LOAD("2732_444_84a_mms.u518", 0x0000, 0x1000, CRC(0e541a7e) SHA1(b1deb620fc89c1068e2e663e14be69d1f337a4b9), ROM_BIOS(6)) - - ROM_SYSTEM_BIOS(7, "mtrhex", "Ultimeth 2k ROM") - ROMX_LOAD("2716_mtrhex.u518", 0x0000, 0x0800, CRC(842a306a) SHA1(ddbc2b8bb127464af9eda8e7c56e6be7c8b43a16), ROM_BIOS(7)) -ROM_END - -} // anonymous namespace - - -// year name parent compat machine input class init company fullname flags -COMP( 1979, h88, h89, 0, h88, h88, h88_state, empty_init, "Heath Company", "Heathkit H88", MACHINE_SUPPORTS_SAVE) -COMP( 1979, h89, 0, 0, h89, h89, h89_state, empty_init, "Heath Company", "Heathkit H89", MACHINE_SUPPORTS_SAVE) -COMP( 1984, h89_sigmasoft, h89, 0, h89_sigmasoft, h89, h89_sigmasoft_state, empty_init, "Heath Company", "Heathkit H89 with SigmaSoft IGC", MACHINE_SUPPORTS_SAVE) diff --git a/src/mame/heathkit/h_88_cass.cpp b/src/mame/heathkit/h_88_cass.cpp deleted file mode 100644 index e67b72a4a7b..00000000000 --- a/src/mame/heathkit/h_88_cass.cpp +++ /dev/null @@ -1,166 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Mark Garlanger -/*************************************************************************** - - Heathkit H-88-5 Cassette Interface Card - - Came standard on the H88 computer and was on option for other H89 class - systems. - -****************************************************************************/ - -#include "emu.h" - -#include "h_88_cass.h" - -#include "machine/clock.h" - -#include "speaker.h" - -#define LOG_REG (1U << 1) -#define LOG_LINES (1U << 2) -#define LOG_CASS (1U << 3) -#define LOG_FUNC (1U << 4) -//#define VERBOSE (0xff) - -#include "logmacro.h" - -#define LOGREG(...) LOGMASKED(LOG_REG, __VA_ARGS__) -#define LOGLINES(...) LOGMASKED(LOG_LINES, __VA_ARGS__) -#define LOGCASS(...) LOGMASKED(LOG_CASS, __VA_ARGS__) -#define LOGFUNC(...) LOGMASKED(LOG_FUNC, __VA_ARGS__) - -#ifdef _MSC_VER -#define FUNCNAME __func__ -#else -#define FUNCNAME __PRETTY_FUNCTION__ -#endif - -DEFINE_DEVICE_TYPE(HEATH_H88_CASS, heath_h_88_cass_device, "heath_h_88_cass_device", "Heath H-88-5 Cassette Interface"); - -heath_h_88_cass_device::heath_h_88_cass_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock): - device_t(mconfig, HEATH_H88_CASS, tag, owner, 0), - m_uart(*this, "uart"), - m_cass_player(*this, "cassette_player"), - m_cass_recorder(*this, "cassette_recorder") -{ -} - -void heath_h_88_cass_device::write(offs_t reg, u8 val) -{ - LOGREG("%s: reg: %d val: 0x%02x\n", FUNCNAME, reg, val); - - m_uart->write(reg, val); -} - -u8 heath_h_88_cass_device::read(offs_t reg) -{ - u8 val = m_uart->read(reg); - - LOGREG("%s: reg: %d val: 0x%02x\n", FUNCNAME, reg, val); - - return val; -} - -TIMER_DEVICE_CALLBACK_MEMBER(heath_h_88_cass_device::kansas_w) -{ - m_cass_data[3]++; - - if (m_cassbit != m_cassold) - { - LOGCASS("%s: m_cassbit changed : %d\n", FUNCNAME, m_cassbit); - m_cass_data[3] = 0; - m_cassold = m_cassbit; - } - - LOGCASS("%s: m_cassbit: %d\n", FUNCNAME, m_cassbit); - // 2400Hz -> 0 - // 1200Hz -> 1 - const int bit_pos = m_cassbit ? 0 : 1; - - m_cass_recorder->output(BIT(m_cass_data[3], bit_pos) ? -1.0 : +1.0); -} - -TIMER_DEVICE_CALLBACK_MEMBER(heath_h_88_cass_device::kansas_r) -{ - // cassette - turn 1200/2400Hz to a bit - m_cass_data[1]++; - u8 cass_ws = (m_cass_player->input() > +0.03) ? 1 : 0; - - LOGCASS("%s: cass_ws: %d\n", FUNCNAME, cass_ws); - - if (cass_ws != m_cass_data[0]) - { - LOGCASS("%s: cass_ws has changed value\n", FUNCNAME); - m_cass_data[0] = cass_ws; - m_uart->write_rxd((m_cass_data[1] < 12) ? 1 : 0); - m_cass_data[1] = 0; - } -} - -void heath_h_88_cass_device::uart_rts(u8 data) -{ - LOGLINES("%s: data: %d\n", FUNCNAME, data); - - m_cass_player->change_state(bool(data) ? CASSETTE_STOPPED : CASSETTE_PLAY, CASSETTE_MASK_UISTATE); -} - -void heath_h_88_cass_device::uart_tx_empty(u8 data) -{ - LOGLINES("%s: data: %d\n", FUNCNAME, data); - - m_cass_recorder->change_state(bool(data) ? CASSETTE_STOPPED : CASSETTE_RECORD, CASSETTE_MASK_UISTATE); -} - -void heath_h_88_cass_device::device_start() -{ - save_item(NAME(m_cass_data)); - save_item(NAME(m_cassbit)); - save_item(NAME(m_cassold)); -} - -void heath_h_88_cass_device::device_reset() -{ - LOGFUNC("%s\n", FUNCNAME); - - // cassette - m_cassbit = 1; - m_cassold = 0; - m_cass_data[0] = 0; - m_cass_data[1] = 0; - m_cass_data[2] = 0; - m_cass_data[3] = 0; - - m_uart->write_cts(0); - m_uart->write_dsr(0); - m_uart->write_rxd(0); -} - -void heath_h_88_cass_device::device_add_mconfig(machine_config &config) -{ - I8251(config, m_uart, 0); - m_uart->txd_handler().set([this] (bool state) { m_cassbit = state; }); - m_uart->rts_handler().set(FUNC(heath_h_88_cass_device::uart_rts)); - m_uart->txempty_handler().set(FUNC(heath_h_88_cass_device::uart_tx_empty)); - - clock_device &cassette_clock(CLOCK(config, "cassette_clock", 4800)); - cassette_clock.signal_handler().set(m_uart, FUNC(i8251_device::write_txc)); - cassette_clock.signal_handler().append(m_uart, FUNC(i8251_device::write_rxc)); - - SPEAKER(config, "mono").front_right(); - - CASSETTE(config, m_cass_player); - m_cass_player->set_formats(h8_cassette_formats); - m_cass_player->set_default_state(CASSETTE_STOPPED | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_ENABLED); - m_cass_player->add_route(ALL_OUTPUTS, "mono", 0.15); - m_cass_player->set_interface("h88_cass_player"); - - CASSETTE(config, m_cass_recorder); - m_cass_recorder->set_formats(h8_cassette_formats); - m_cass_recorder->set_default_state(CASSETTE_STOPPED | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_ENABLED); - m_cass_recorder->add_route(ALL_OUTPUTS, "mono", 0.15); - m_cass_recorder->set_interface("h88_cass_recorder"); - - TIMER(config, "kansas_w").configure_periodic(FUNC(heath_h_88_cass_device::kansas_w), attotime::from_hz(4800)); - TIMER(config, "kansas_r").configure_periodic(FUNC(heath_h_88_cass_device::kansas_r), attotime::from_hz(40000)); -} diff --git a/src/mame/heathkit/h_88_cass.h b/src/mame/heathkit/h_88_cass.h deleted file mode 100644 index f3a7a22196f..00000000000 --- a/src/mame/heathkit/h_88_cass.h +++ /dev/null @@ -1,53 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Mark Garlanger -/*************************************************************************** - - Heathkit H-88-5 Cassette Interface card - -****************************************************************************/ - -#ifndef MAME_HEATHKIT_H_88_CASS_H -#define MAME_HEATHKIT_H_88_CASS_H - -#pragma once - -#include "imagedev/cassette.h" -#include "machine/i8251.h" -#include "machine/timer.h" - -#include "formats/h8_cas.h" - - -class heath_h_88_cass_device : public device_t -{ -public: - heath_h_88_cass_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); - - void write(offs_t reg, u8 val); - u8 read(offs_t reg); - -protected: - - virtual void device_start() override; - virtual void device_reset() override; - virtual void device_add_mconfig(machine_config &config) override; - - void uart_rts(u8 data); - void uart_tx_empty(u8 data); - - TIMER_DEVICE_CALLBACK_MEMBER(kansas_r); - TIMER_DEVICE_CALLBACK_MEMBER(kansas_w); - - required_device m_uart; - required_device m_cass_player; - required_device m_cass_recorder; - - u8 m_cass_data[4]; - bool m_cassbit; - bool m_cassold; -}; - -DECLARE_DEVICE_TYPE(HEATH_H88_CASS, heath_h_88_cass_device) - - -#endif // MAME_HEATHKIT_H_88_CASS_H diff --git a/src/mame/heathkit/intr_cntrl.cpp b/src/mame/heathkit/intr_cntrl.cpp deleted file mode 100644 index 2ebb46701da..00000000000 --- a/src/mame/heathkit/intr_cntrl.cpp +++ /dev/null @@ -1,222 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Mark Garlanger -/*************************************************************************** - - Heathkit Interrupt controller for H89 - -****************************************************************************/ - -#include "emu.h" - -#include "intr_cntrl.h" - -DEFINE_DEVICE_TYPE(HEATH_INTR_CNTRL, heath_intr_cntrl, "heath_intr_cntrl", "Heath H/Z-89 Interrupt Controller"); -DEFINE_DEVICE_TYPE(HEATH_Z37_INTR_CNTRL, z37_intr_cntrl, "heath_z37_intr_cntrl", "Heath H/Z-89 with Z-37 Interrupt Controller"); - -DEFINE_DEVICE_TYPE(HEATH_INTR_SOCKET, heath_intr_socket, "heath_intr_socket", "Heath Interrupt Socket"); - -/** - * Heath interrupt interface - */ -device_heath_intr_interface::device_heath_intr_interface(const machine_config &mconfig, device_t &device) : - device_interface(device, "heathintrdevice"), - m_socket(dynamic_cast(device.owner())) -{ -} - -/** - * Original Heath interrrupt controller - * - */ -heath_intr_cntrl::heath_intr_cntrl(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock): - heath_intr_cntrl(mconfig, HEATH_INTR_CNTRL, tag, owner, clock) -{ -} - -heath_intr_cntrl::heath_intr_cntrl(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock): - device_t(mconfig, type, tag, owner, 0), - device_heath_intr_interface(mconfig, *this) -{ -} - -void heath_intr_cntrl::device_start() -{ - save_item(NAME(m_intr_lines)); - - m_intr_lines = 0; -} - -void heath_intr_cntrl::update_intr_line() -{ - if (m_socket) - { - m_socket->raise_irq((m_intr_lines == 0) ? 0 : 1); - } -} - -void heath_intr_cntrl::set_irq_level(u8 level, int data) -{ - // only 0 to 7 is valid - level &= 0x7; - - if (data == 0) - { - m_intr_lines &= ~(1 << level); - } - else - { - m_intr_lines |= 1 << level; - } - - update_intr_line(); -} - -u8 heath_intr_cntrl::get_instruction() -{ - - // determine top priority instruction - if (!m_intr_lines) - { - // should not occur. - // NO-OP ? - logerror("get instruct: bad m_intr_lines\n"); - - return 0x00; - } - - // ideally this would be handled with a function like ffs() - u8 level = 0; - u8 mask = 0x01; - - while (mask) - { - if (m_intr_lines & mask) - { - break; - } - level++; - mask <<= 1; - } - - if (level > 7) - { - logerror("bad level: %d\n", level); - } - - // return RST based on level - return 0xc7 | ((level & 0x7) << 3); -} - -/** - * Interrupt controller for the Z37 soft-sectored controller. - * - * It will take control of the interrupt system and block all other - * interrupts while it is waiting for Z37 events. - */ -z37_intr_cntrl::z37_intr_cntrl(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock): - heath_intr_cntrl(mconfig, HEATH_Z37_INTR_CNTRL, tag, owner, clock) -{ -} - -void z37_intr_cntrl::update_intr_line() -{ - m_socket->raise_irq( - (m_irq_raised || m_drq_raised || - (!m_intr_blocked && (m_intr_lines != 0))) ? 1 : 0); -} - -u8 z37_intr_cntrl::get_instruction() -{ - - if (m_drq_raised) - { - // EI - return 0xfb; - } - - if (m_irq_raised) - { - // RST 20H (Interrupt 4) - return 0xe7; - } - - if (!m_intr_blocked) - { - return heath_intr_cntrl::get_instruction(); - } - - // shouldn't get here - NO-OP? - logerror("Warning: z37 intr get_instruction: fd: %d dr: %d ib: %d\n", m_irq_raised, m_drq_raised, m_intr_blocked); - return 0x00; -} - -void z37_intr_cntrl::set_drq(int state) -{ - m_drq_raised = bool(state); - - update_intr_line(); -} - - -void z37_intr_cntrl::set_irq(int state) -{ - m_irq_raised = bool(state); - - update_intr_line(); -} - -void z37_intr_cntrl::device_start() -{ - heath_intr_cntrl::device_start(); - - save_item(NAME(m_intr_blocked)); - save_item(NAME(m_drq_raised)); - save_item(NAME(m_irq_raised)); - - m_intr_blocked = false; - m_drq_raised = false; - m_irq_raised = false; -} - -void z37_intr_cntrl::block_interrupts(u8 data) -{ - m_intr_blocked = bool(data); - - update_intr_line(); -} - - -/** - * Heath Interrupt socket - * - * Allows choice of interrupt controllers for Heath 8-bit computers. - */ -heath_intr_socket::heath_intr_socket(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : - device_t(mconfig, HEATH_INTR_SOCKET, tag, owner, clock), - device_single_card_slot_interface(mconfig, *this), - m_irq_line(*this), - m_cntrl(nullptr) -{ -} - -heath_intr_socket::~heath_intr_socket() -{ -} - -void heath_intr_socket::device_start() -{ - m_cntrl = get_card_device(); -} - -IRQ_CALLBACK_MEMBER(heath_intr_socket::irq_callback) -{ - // assume NO-OP - u8 instr = 0x00; - - if (m_cntrl) - { - instr = m_cntrl->get_instruction(); - } - - return instr; -} diff --git a/src/mame/heathkit/intr_cntrl.h b/src/mame/heathkit/intr_cntrl.h deleted file mode 100644 index b5fc10cbf82..00000000000 --- a/src/mame/heathkit/intr_cntrl.h +++ /dev/null @@ -1,133 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Mark Garlanger -/*************************************************************************** - - Heathkit Interrupt Controllers - - Interrupt controllers for the Heath H89. - -****************************************************************************/ - -#ifndef MAME_HEATHKIT_INTR_CNTRL_H -#define MAME_HEATHKIT_INTR_CNTRL_H - -#pragma once - -class heath_intr_socket; - -class device_heath_intr_interface : public device_interface -{ -public: - virtual void set_irq_level(u8 level, int state) = 0; - - virtual void set_drq(int state) {} - virtual void set_irq(int state) {} - virtual void block_interrupts(u8 data) {} - -protected: - device_heath_intr_interface(const machine_config &mconfig, device_t &device); - - virtual u8 get_instruction() = 0; - - heath_intr_socket *const m_socket; - - friend heath_intr_socket; -}; - - -/** - * Heath original interrupt controller - * - */ -class heath_intr_cntrl : public device_t, - public device_heath_intr_interface -{ -public: - heath_intr_cntrl(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); - - virtual void set_irq_level(u8 level, int state) override; - -protected: - heath_intr_cntrl(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock = 0); - - virtual u8 get_instruction() override; - virtual void update_intr_line(); - - virtual void device_start() override; - - u8 m_intr_lines; -}; - -/** - * Interrupt controller when the Z37 soft-sectored controller is installed. - * - */ -class z37_intr_cntrl : public heath_intr_cntrl -{ -public: - z37_intr_cntrl(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); - - virtual void set_drq(int state) override; - virtual void set_irq(int state) override; - virtual void block_interrupts(u8 data) override; - -protected: - virtual u8 get_instruction() override; - virtual void update_intr_line() override; - - virtual void device_start() override; - -private: - bool m_intr_blocked; - bool m_drq_raised; - bool m_irq_raised; -}; - -DECLARE_DEVICE_TYPE(HEATH_INTR_CNTRL, heath_intr_cntrl) -DECLARE_DEVICE_TYPE(HEATH_Z37_INTR_CNTRL, z37_intr_cntrl) - - -class heath_intr_socket : public device_t, - public device_single_card_slot_interface -{ -public: - - template - heath_intr_socket(const machine_config &mconfig, const char *tag, device_t *owner, T &&opts, const char *dflt, bool fixed = false) : - heath_intr_socket(mconfig, tag, owner, 0) - { - option_reset(); - opts(*this); - set_default_option(dflt); - set_fixed(fixed); - } - - heath_intr_socket(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); - virtual ~heath_intr_socket(); - - auto irq_line_cb() { return m_irq_line.bind(); } - - // required operation - void set_irq_level(u8 level, int state) { if (m_cntrl) { m_cntrl->set_irq_level(level, state); }} - - IRQ_CALLBACK_MEMBER(irq_callback); - - void raise_irq(int state) { m_irq_line(state); } - - void set_irq(int state) { if (m_cntrl) { m_cntrl->set_irq(state); } } - void set_drq(int state) { if (m_cntrl) { m_cntrl->set_drq(state); } } - void block_interrupts(u8 data) { if (m_cntrl) { m_cntrl->block_interrupts(data); } } - -protected: - - virtual void device_start() override; - - devcb_write8 m_irq_line; - - device_heath_intr_interface *m_cntrl; -}; - - -DECLARE_DEVICE_TYPE(HEATH_INTR_SOCKET, heath_intr_socket) - -#endif // MAME_HEATHKIT_H89_INTR_CNTRL_H diff --git a/src/mame/heathkit/sigmasoft_parallel_port.cpp b/src/mame/heathkit/sigmasoft_parallel_port.cpp deleted file mode 100644 index a412f204245..00000000000 --- a/src/mame/heathkit/sigmasoft_parallel_port.cpp +++ /dev/null @@ -1,165 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Mark Garlanger -/*************************************************************************** - - SigmaSoft Universal Parallel Interface Board - - -****************************************************************************/ - -#include "emu.h" - -#include "sigmasoft_parallel_port.h" - -// -// Logging defines -// -#define LOG_REG (1U << 1) // Shows register setup -#define LOG_FUNC (1U << 2) // Function calls - -#define VERBOSE (0) - -#include "logmacro.h" - -#define LOGREG(...) LOGMASKED(LOG_REG, __VA_ARGS__) -#define LOGFUNC(...) LOGMASKED(LOG_FUNC, __VA_ARGS__) - -#ifdef _MSC_VER -#define FUNCNAME __func__ -#else -#define FUNCNAME __PRETTY_FUNCTION__ -#endif - - -DEFINE_DEVICE_TYPE(SIGMASOFT_PARALLEL_PORT, sigmasoft_parallel_port, "sigmasoft_parallel_port", "SigmaSoft Universal Parallel Board"); - -sigmasoft_parallel_port::sigmasoft_parallel_port(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock): - device_t(mconfig, SIGMASOFT_PARALLEL_PORT, tag, owner, clock), - m_ctrl_r(*this, 0x00), - m_video_mem_r(*this, 0x00), - m_video_mem_w(*this), - m_io_lo_addr(*this), - m_io_hi_addr(*this), - m_window_lo_addr(*this), - m_window_hi_addr(*this), - m_ctrl_w(*this) -{ -} - -void sigmasoft_parallel_port::video_mem_w(u8 val) -{ - m_video_mem_w(val); -} - -void sigmasoft_parallel_port::io_lo_addr_w(u8 val) -{ - m_io_lo_addr(val); -} - -void sigmasoft_parallel_port::io_hi_addr_w(u8 val) -{ - m_io_hi_addr(val); -} - -void sigmasoft_parallel_port::window_lo_addr_w(u8 val) -{ - m_window_lo_addr(val); -} - -void sigmasoft_parallel_port::window_hi_addr_w(u8 val) -{ - m_window_hi_addr(val); -} - -void sigmasoft_parallel_port::ctrl_w(u8 val) -{ - m_ctrl_w(val); -} - -void sigmasoft_parallel_port::write(offs_t reg, u8 val) -{ - LOGFUNC("%s: reg: %d val: %d\n", FUNCNAME, reg, val); - - switch (reg) - { - case 0: - video_mem_w(val); - break; - case 1: - io_lo_addr_w(val); - break; - case 2: - io_hi_addr_w(val); - break; - case 3: - window_lo_addr_w(val); - break; - case 4: - window_hi_addr_w(val); - break; - case 5: - ctrl_w(val); - break; - case 6: - // TODO - Centronics interface - break; - case 7: - // TODO - Centronics interface - break; - } -} - -u8 sigmasoft_parallel_port::video_mem_r() -{ - // get video memory value from igc device - return m_video_mem_r(); -} - -u8 sigmasoft_parallel_port::ctrl_r() -{ - // get control register from igc device - return m_ctrl_r(); -} - -u8 sigmasoft_parallel_port::read(offs_t reg) -{ - // default return for the h89 - u8 value = 0xff; - - switch (reg) - { - case 0: - value = video_mem_r(); - break; - case 1: - // TODO - Light Pen Low address - break; - case 2: - // TODO - Light Pen High address - break; - case 3: - // TODO - Left input device - break; - case 4: - // TODO - Right input device - break; - case 5: - // Control Register - value = ctrl_r(); - break; - case 6: - // TODO - Centronics interface - break; - case 7: - // TODO - Centronics interface - break; - } - - LOGFUNC("%s: reg: %d val: %d\n", FUNCNAME, reg, value); - - return value; -} - -void sigmasoft_parallel_port::device_start() -{ -} diff --git a/src/mame/heathkit/sigmasoft_parallel_port.h b/src/mame/heathkit/sigmasoft_parallel_port.h deleted file mode 100644 index 15837bf577b..00000000000 --- a/src/mame/heathkit/sigmasoft_parallel_port.h +++ /dev/null @@ -1,67 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Mark Garlanger -/*************************************************************************** - - SigmaSoft Universal Parallel Interface Board - -****************************************************************************/ - -#ifndef MAME_HEATHKIT_SIGMASOFT_PARALLEL_PORT_H -#define MAME_HEATHKIT_SIGMASOFT_PARALLEL_PORT_H - -#pragma once - - -class sigmasoft_parallel_port : public device_t -{ -public: - sigmasoft_parallel_port(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); - - void write(offs_t reg, u8 val); - u8 read(offs_t reg); - - auto ctrl_r_cb() { return m_ctrl_r.bind(); } - auto video_mem_r_cb() { return m_video_mem_r.bind(); } - - auto video_mem_cb() { return m_video_mem_w.bind(); } - auto io_lo_cb() { return m_io_lo_addr.bind(); } - auto io_hi_cb() { return m_io_hi_addr.bind(); } - auto window_lo_cb() { return m_window_lo_addr.bind(); } - auto window_hi_cb() { return m_window_hi_addr.bind(); } - auto ctrl_cb() { return m_ctrl_w.bind(); } - -protected: - - virtual void device_start() override; - - u8 video_mem_r(); - void video_mem_w(u8 val); - - void io_lo_addr_w(u8 val); - void io_hi_addr_w(u8 val); - - void window_lo_addr_w(u8 val); - void window_hi_addr_w(u8 val); - - void ctrl_w(u8 val); - u8 ctrl_r(); - -private: - - // Reads - devcb_read8 m_ctrl_r; - devcb_read8 m_video_mem_r; - - // Writes - devcb_write8 m_video_mem_w; - devcb_write8 m_io_lo_addr; - devcb_write8 m_io_hi_addr; - devcb_write8 m_window_lo_addr; - devcb_write8 m_window_hi_addr; - devcb_write8 m_ctrl_w; -}; - -DECLARE_DEVICE_TYPE(SIGMASOFT_PARALLEL_PORT, sigmasoft_parallel_port) - - -#endif // MAME_HEATHKIT_SIGMASOFT_PARALLEL_PORT_H diff --git a/src/mame/heathkit/tlb.cpp b/src/mame/heathkit/tlb.cpp deleted file mode 100644 index ccafa639363..00000000000 --- a/src/mame/heathkit/tlb.cpp +++ /dev/null @@ -1,2032 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Mark Garlanger -/*************************************************************************** - - Heathkit Terminal Logic Board (TLB) - - The board used in the H19 smart terminal designed and manufactured - by Heath Company. (and the identical Z19 sold by Zenith Data Systems) - This board is also used the Heath's H89 / H88, and ZDS's Z-89 and Z-90. - - The keyboard consists of a 9x10 matrix connected to a MM5740AAC/N - mask-programmed keyboard controller. The output of this passes - through a rom. - - Input can also come from the serial port. - - Known Issues: - - With gp19 - - 49/50 row mode only shows half the screen. - - In 49/50 row mode, character descenders are cut off. - - Screen saver does not disable the screen - - With Superset - - Screensaver freezes the screen instead of blanking the screen - - Not Currently Implemented - - With Imaginator I-100 - - Support for Tektronics Emulation (missing ROM image) - - With SigmaSoft IGC - - Interlace video support (with higher resolution) - - Joystick support - - Centronics support - - Lightpen support - - Alternate Font ROM support (missing ROM image) - - With Super19 - - Interlace video - - Alternate Font19 alt 128 mode and extended 256 mode (missing ROM images) - - ANSI character set selection (missing ROM image) - - light pen support - - With UltraROM - - Interace mode - -****************************************************************************/ -/*************************************************************************** - - Memory Layout - - The U435 three-to-eight line decoder uses A14 and A15 to generate - three memory address spaces: - - Address Description - ---------------------------------------------------- - 0x0000 Program ROM - 0x4000 Scratchpad RAM - 0xF800 (0xC000) Display Memory - - - Port Layout - - Only address lines A5, A6, A7 are used by the U442 three-to-eight - line decoder - - Address Description - ---------------------------------------------------- - 0x00 Power-up configuration (primary - SW401) - 0x20 Power-up configuration (secondary - SW402) - 0x40 INS8250 ACE (communications) - 0x60 MC6845 CRT controller - 0x80 MM5740 Keyboard encoder - 0xA0 Keyboard status - 0xC0 Trigger key click - 0xE0 Trigger bell - -****************************************************************************/ - -#include "emu.h" - -#include "tlb.h" - -#include - -#define LOG_REG (1U << 1) // Shows register setup - -//#define VERBOSE (LOG_REG) - -#include "logmacro.h" - -#define LOGREG(...) LOGMASKED(LOG_REG, __VA_ARGS__) - -#ifdef _MSC_VER -#define FUNCNAME __func__ -#else -#define FUNCNAME __PRETTY_FUNCTION__ -#endif - -// Clocks -static constexpr XTAL MASTER_CLOCK = XTAL(12'288'000); - -// DOT clocks -static constexpr XTAL BASE_DOT_CLOCK = MASTER_CLOCK; -static constexpr XTAL GP19_DOT_CLOCK_1 = XTAL(20'282'000); // 132 columns -static constexpr XTAL GP19_DOT_CLOCK_2 = XTAL(12'292'000); // 80 columns -static constexpr XTAL GP19_DOT_CLOCK_3 = XTAL(10'644'000); // Graphics mode - -// Standard H19 used a 2.048 MHz clock for Z80 -static constexpr XTAL H19_CLOCK = MASTER_CLOCK / 6; -static constexpr XTAL H19_3MHZ = MASTER_CLOCK / 4; -static constexpr XTAL H19_4MHZ = MASTER_CLOCK / 3; -static constexpr XTAL H19_6MHZ = MASTER_CLOCK / 2; - -static constexpr XTAL INS8250_CLOCK = MASTER_CLOCK / 4; - -// Beep Frequency is 1 KHz -static constexpr XTAL H19_BEEP_FRQ = (H19_CLOCK / 2048); - -// Capacitor value in pF -static constexpr u32 H19_KEY_DEBOUNCE_CAPACITOR = 5000; -static const u32 MM5740_CLOCK = mm5740_device::calc_effective_clock_key_debounce(H19_KEY_DEBOUNCE_CAPACITOR); - -// Keyboard flag masks -static constexpr u8 KB_STATUS_SHIFT_KEYS_MASK = 0x01; -static constexpr u8 KB_STATUS_CONTROL_KEY_MASK = 0x10; -static constexpr u8 KB_STATUS_KEYBOARD_STROBE_MASK = 0x80; - -DEFINE_DEVICE_TYPE(HEATH_TLB_CONNECTOR, heath_tlb_connector, "heath_tlb_connector", "Heath Terminal Logic board connector abstraction") - -DEFINE_DEVICE_TYPE(HEATH_TLB, heath_tlb_device, "heath_tlb", "Heath Terminal Logic Board") -DEFINE_DEVICE_TYPE(HEATH_SUPER19, heath_super19_tlb_device, "heath_super19_tlb", "Heath Terminal Logic Board w/Super19 ROM") -DEFINE_DEVICE_TYPE(HEATH_SUPERSET, heath_superset_tlb_device, "heath_superset_tlb", "Heath Terminal Logic Board w/Superset ROM") -DEFINE_DEVICE_TYPE(HEATH_ULTRA, heath_ultra_tlb_device, "heath_ultra_tlb", "Heath Terminal Logic Board w/Ultra ROM") -DEFINE_DEVICE_TYPE(HEATH_WATZ, heath_watz_tlb_device, "heath_watz_tlb", "Heath Terminal Logic Board w/Watzman ROM") -DEFINE_DEVICE_TYPE(HEATH_GP19, heath_gp19_tlb_device, "heath_gp19_tlb", "Heath Terminal Logic Board plus Northwest Digital Systems GP-19") -DEFINE_DEVICE_TYPE(HEATH_IMAGINATOR, heath_imaginator_tlb_device, "heath_imaginator_tlb", "Heath Terminal Logic Board plus Cleveland Codonics Imaginator I-100") - -// Devices for the terminal boards compatible with SigmaSoft IGC -DEFINE_DEVICE_TYPE(HEATH_IGC, heath_igc_tlb_device, "heath_igc_tlb_device", "Heath Terminal Logic Board plus SigmaSoft Interactive Graphics Controller") -DEFINE_DEVICE_TYPE(HEATH_IGC_SUPER19, heath_igc_super19_tlb_device, "heath_igc_super19_tlb_device", "Heath Terminal Logic Board w/ Super19 ROM plus SigmaSoft Interactive Graphics Controller") -DEFINE_DEVICE_TYPE(HEATH_IGC_ULTRA, heath_igc_ultra_tlb_device, "heath_igc_ultra_tlb_device", "Heath Terminal Logic Board w/ Ultra ROM plus SigmaSoft Interactive Graphics Controller") -DEFINE_DEVICE_TYPE(HEATH_IGC_WATZ, heath_igc_watz_tlb_device, "heath_igc_watz_tlb_device", "Heath Terminal Logic Board w/Watzman ROM plus SigmaSoft Interactive Graphics Controller") - - -device_heath_tlb_card_interface::device_heath_tlb_card_interface(const machine_config &mconfig, device_t &device) : - device_interface(device, "heathtlbdevice"), - m_slot(dynamic_cast(device.owner())) -{ -} - - -/** - * original Heath H19 functionality - */ -heath_tlb_device::heath_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : - heath_tlb_device(mconfig, HEATH_TLB, tag, owner, clock) -{ -} - -heath_tlb_device::heath_tlb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) : - device_t(mconfig, type, tag, owner, clock), - device_heath_tlb_card_interface(mconfig, *this), - m_maincpu(*this, "maincpu"), - m_screen(*this, "screen"), - m_palette(*this, "palette"), - m_crtc(*this, "crtc"), - m_p_videoram(*this, "videoram"), - m_p_chargen(*this, "chargen"), - m_config(*this, "CONFIG"), - m_ace(*this, "ins8250"), - m_beep(*this, "beeper"), - m_mm5740(*this, "mm5740"), - m_kbdrom(*this, "keyboard"), - m_kbspecial(*this, "MODIFIERS"), - m_repeat_clock(*this, "repeatclock") -{ -} - -void heath_tlb_device::check_beep_state() -{ - if (!m_key_click_active && !m_bell_active) - { - m_beep->set_state(0); - } -} - -TIMER_CALLBACK_MEMBER(heath_tlb_device::key_click_off) -{ - m_key_click_active = false; - - check_beep_state(); -} - -TIMER_CALLBACK_MEMBER(heath_tlb_device::bell_off) -{ - m_bell_active = false; - - check_beep_state(); -} - -void heath_tlb_device::mem_map(address_map &map) -{ - map.unmap_value_high(); - - // H19 ROM - map(0x0000, 0x0fff).mirror(0x3000).rom(); - - // Scratchpad memory - map(0x4000, 0x40ff).mirror(0x3f00).ram(); - - // Video Memory - map(0xc000, 0xc7ff).mirror(0x3800).ram().share(m_p_videoram); -} - -void heath_tlb_device::io_map(address_map &map) -{ - map.unmap_value_high(); - map.global_mask(0xff); - map(0x00, 0x00).mirror(0x1f).portr("SW401"); - map(0x20, 0x20).mirror(0x1f).portr("SW402"); - map(0x40, 0x47).mirror(0x18).rw(m_ace, FUNC(ins8250_device::ins8250_r), FUNC(ins8250_device::ins8250_w)); - map(0x60, 0x60).mirror(0x1a).select(0x04).w(FUNC(heath_tlb_device::crtc_addr_w)); - map(0x61, 0x61).mirror(0x1a).select(0x04).rw(FUNC(heath_tlb_device::crtc_reg_r), FUNC(heath_tlb_device::crtc_reg_w)); - map(0x80, 0x80).mirror(0x1f).r(FUNC(heath_tlb_device::kbd_key_r)); - map(0xa0, 0xa0).mirror(0x1f).r(FUNC(heath_tlb_device::kbd_flags_r)); - map(0xc0, 0xc0).mirror(0x1f).w(FUNC(heath_tlb_device::key_click_w)); - map(0xe0, 0xe0).mirror(0x1f).w(FUNC(heath_tlb_device::bell_w)); -} - -void heath_tlb_device::device_start() -{ - save_item(NAME(m_transchar)); - save_item(NAME(m_strobe)); - save_item(NAME(m_key_click_active)); - save_item(NAME(m_bell_active)); - save_item(NAME(m_reset_pending)); - save_item(NAME(m_right_shift)); - save_item(NAME(m_reset_key)); - save_item(NAME(m_keyboard_irq_raised)); - save_item(NAME(m_serial_irq_raised)); - save_item(NAME(m_break_key_irq_raised)); - save_item(NAME(m_allow_vsync_nmi)); - - m_strobe = false; - m_key_click_active = false; - m_bell_active = false; - m_reset_pending = false; - m_right_shift = false; - m_reset_key = false; - m_keyboard_irq_raised = false; - m_serial_irq_raised = false; - m_break_key_irq_raised = false; - m_allow_vsync_nmi = false; - - m_key_click_timer = timer_alloc(FUNC(heath_tlb_device::key_click_off), this); - m_bell_timer = timer_alloc(FUNC(heath_tlb_device::bell_off), this); - - // Flip bits in font ROM to avoid having to flip them during scan out since some - // boards with graphics has the pixel graphic reversed from the font layout. Doing - // it for all devices for consistency. - for (size_t i = 0; i < m_p_chargen.length(); i++) - { - m_p_chargen[i] = bitswap<8>(m_p_chargen[i], 0, 1, 2, 3, 4, 5, 6, 7); - } -} - -void heath_tlb_device::device_reset() -{ - m_strobe = false; - m_key_click_active = false; - m_bell_active = false; - m_allow_vsync_nmi = false; - - ioport_value const cfg(m_config->read()); - - // CPU clock speed - switch (BIT(cfg, 0, 2)) - { - case 0x01: - m_maincpu->set_clock(H19_3MHZ); - break; - case 0x02: - m_maincpu->set_clock(H19_4MHZ); - break; - case 0x03: - m_maincpu->set_clock(H19_6MHZ); - break; - case 0x00: - default: - // Standard Clock - m_maincpu->set_clock(H19_CLOCK); - break; - } - - // Set screen color - switch (BIT(cfg, 2, 2)) - { - case 0x01: - m_screen->set_color(rgb_t::white()); - break; - case 0x02: - m_screen->set_color(rgb_t::amber()); - break; - case 0x00: - default: - m_screen->set_color(rgb_t::green()); - break; - } -} - -void heath_tlb_device::key_click_w(u8 data) -{ - // Keyclick - 6 mSec - m_beep->set_state(1); - m_key_click_active = true; - m_key_click_timer->adjust(attotime::from_msec(6)); -} - -void heath_tlb_device::bell_w(u8 data) -{ - // Bell (^G) - 200 mSec - m_beep->set_state(1); - m_bell_active = true; - m_bell_timer->adjust(attotime::from_msec(200)); -} - -/** - * MM5740 B Mapping to the ROM address - */ -u16 heath_tlb_device::translate_mm5740_b(u16 b) -{ - return bitswap<9>(b, 7, 6, 8, 5, 4, 3, 2, 1, 0); -} - -u8 heath_tlb_device::kbd_key_r() -{ - m_strobe = false; - m_keyboard_irq_raised = false; - - set_irq_line(); - - // high bit is for control key pressed, this is handled in the ROM, - // no processing needed. - return m_transchar; -} - -u8 heath_tlb_device::kbd_flags_r() -{ - u16 modifiers = m_kbspecial->read(); - u8 rv = modifiers & 0x7e; - - // check both shifts - if ((modifiers & 0x120) != 0x120) - { - rv |= KB_STATUS_SHIFT_KEYS_MASK; - } - - if (!m_strobe) - { - rv |= KB_STATUS_KEYBOARD_STROBE_MASK; - } - - return rv; -} - -int heath_tlb_device::mm5740_shift_r() -{ - return ((m_kbspecial->read() & 0x120) != 0x120) ? 1 : 0; -} - -int heath_tlb_device::mm5740_control_r() -{ - return (m_kbspecial->read() & KB_STATUS_CONTROL_KEY_MASK) ? 0 : 1; -} - -void heath_tlb_device::mm5740_data_ready_w(int state) -{ - if (state) - { - u8 *decode = m_kbdrom->base(); - - m_transchar = decode[translate_mm5740_b(m_mm5740->b_r())]; - m_strobe = true; - m_keyboard_irq_raised = true; - - set_irq_line(); - } -} - -void heath_tlb_device::crtc_addr_w(offs_t reg, u8 val) -{ - m_allow_vsync_nmi = bool(BIT(reg, 2)); - - m_crtc->address_w(val); -} - -u8 heath_tlb_device::crtc_reg_r(offs_t reg) -{ - if (!machine().side_effects_disabled()) - { - m_allow_vsync_nmi = bool(BIT(reg, 2)); - } - - return m_crtc->register_r(); -} - -void heath_tlb_device::crtc_reg_w(offs_t reg, u8 val) -{ - m_allow_vsync_nmi = bool(BIT(reg, 2)); - - m_crtc->register_w(val); -} - -void heath_tlb_device::crtc_vsync_w(int val) -{ - m_maincpu->set_input_line(INPUT_LINE_NMI, m_allow_vsync_nmi ? val : CLEAR_LINE); -} - -void heath_tlb_device::serial_irq_w(int state) -{ - m_serial_irq_raised = bool(state); - - set_irq_line(); -} - -void heath_tlb_device::set_irq_line() -{ - m_maincpu->set_input_line(INPUT_LINE_IRQ0, - (m_keyboard_irq_raised || m_serial_irq_raised || m_break_key_irq_raised) ? - ASSERT_LINE : CLEAR_LINE); -} - -void heath_tlb_device::check_for_reset() -{ - if (m_reset_key && m_right_shift) - { - m_reset_pending = true; - m_slot->reset_out(1); - m_maincpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); - } - else if (m_reset_pending) - { - m_reset_pending = false; - reset(); - m_maincpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE); - m_slot->reset_out(0); - } -} - -void heath_tlb_device::reset_key_w(int state) -{ - m_reset_key = (state == 0); - - check_for_reset(); -} - -void heath_tlb_device::right_shift_w(int state) -{ - m_right_shift = (state == 0); - - check_for_reset(); -} - -void heath_tlb_device::repeat_key_w(int state) -{ - // when repeat key pressed, set duty cycle to 50%, else 0%. - m_repeat_clock->set_duty_cycle(state == 0 ? 0.5 : 0); -} - -void heath_tlb_device::break_key_w(int state) -{ - m_break_key_irq_raised = (state == 0); - - set_irq_line(); -} - -MC6845_UPDATE_ROW(heath_tlb_device::crtc_update_row) -{ - rgb_t const *const palette = m_palette->palette()->entry_list_raw(); - u32 *p = &bitmap.pix(y); - - if (de) - { - for (int x = 0; x < x_count; x++) - { - u8 inv = (x == cursor_x) ? 0xff : 0; - u8 chr = m_p_videoram[(ma + x) & 0x7ff]; - - if (chr & 0x80) - { - inv ^= 0xff; - chr &= 0x7f; - } - - // get pattern of pixels for that character scanline - u8 const gfx = m_p_chargen[(chr << 4) | ra] ^ inv; - - // Display a scanline of a character (8 pixels) - for (int b = 0; 8 > b; ++b) - { - *p++ = palette[BIT(gfx, b)]; - } - } - } - else - { - std::fill_n(p, x_count * 8, palette[0]); - } -} - - -// F4 Character Displayer -static const gfx_layout h19_charlayout = -{ - 8, 10, // 8 x 10 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 }, - 8*16 // every char takes 16 bytes -}; - -static GFXDECODE_START( gfx_h19 ) - GFXDECODE_ENTRY("chargen", 0x0000, h19_charlayout, 0, 1) -GFXDECODE_END - - -// Input ports -static INPUT_PORTS_START( tlb ) - - PORT_START("MODIFIERS") - // bit 0 - 0x001 connects to B8 of MM5740 - low if either shift key is - PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("CapsLock") PORT_CODE(KEYCODE_CAPSLOCK) PORT_TOGGLE - PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Break") PORT_CODE(KEYCODE_PAUSE) PORT_WRITE_LINE_MEMBER(heath_tlb_device, break_key_w) - PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("OffLine") PORT_CODE(KEYCODE_F12) PORT_TOGGLE - PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("CTRL") PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_MAMEKEY(LCONTROL)) - PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("LeftShift") PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1) - PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Repeat") PORT_CODE(KEYCODE_RALT) PORT_WRITE_LINE_MEMBER(heath_tlb_device, repeat_key_w) - // bit 7 - 0x080 is low if any key is pressed - PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("RightShift") PORT_CODE(KEYCODE_RSHIFT) PORT_WRITE_LINE_MEMBER(heath_tlb_device, right_shift_w) - PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Reset") PORT_CODE(KEYCODE_F10) PORT_WRITE_LINE_MEMBER(heath_tlb_device, reset_key_w) - - PORT_START("X1") - PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("/") PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?') - PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_UNUSED) - PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_UNUSED) - PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_UNUSED) - PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("k_X2") - PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_UNUSED) - PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-0") PORT_CODE(KEYCODE_0_PAD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD)) - PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-.") PORT_CODE(KEYCODE_DEL_PAD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD)) - PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-Enter") PORT_CODE(KEYCODE_ENTER_PAD) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD)) - PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_UNUSED) - - PORT_START("X2") - PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("; :") PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':') - PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("' \"") PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('"') - PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("{ }") PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('{') PORT_CHAR('}') - PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Return") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) - PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_UNUSED) - PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_UNUSED) - PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-1 IL") PORT_CODE(KEYCODE_1_PAD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD)) - PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-2 Down") PORT_CODE(KEYCODE_2_PAD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD)) - PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-3 DL") PORT_CODE(KEYCODE_3_PAD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD)) - PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_UNUSED) - - PORT_START("X3") - PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("P") PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') - PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("[ ]") PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR(']') - PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("\\ |") PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') PORT_CHAR('|') - PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Line Feed") PORT_CODE(KEYCODE_RWIN) PORT_CHAR(10) - PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("DEL") PORT_CODE(KEYCODE_DEL) PORT_CHAR(127) - PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_UNUSED) - PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-4 LEFT") PORT_CODE(KEYCODE_4_PAD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD)) - PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-5 HOME") PORT_CODE(KEYCODE_5_PAD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD)) - PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-6 RIGHT") PORT_CODE(KEYCODE_6_PAD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD)) - PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_UNUSED) - - PORT_START("X4") - PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("0 )") PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')') - PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("- _") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_') - PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("= +") PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+') - PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("` ~") PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`') PORT_CHAR('~') - PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Back Space") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8) - PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("k_X1") - PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-7 IC") PORT_CODE(KEYCODE_7_PAD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD)) - PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-8 UP") PORT_CODE(KEYCODE_8_PAD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD)) - PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-9 DC") PORT_CODE(KEYCODE_9_PAD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD)) - PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_UNUSED) - - PORT_START("X5") - PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F1") PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1)) - PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F2") PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2)) - PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F3") PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3)) - PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F4") PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4)) - PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F5") PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5)) - PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Erase") PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6)) - PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Blue") PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7)) - PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Red") PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8)) - PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Gray") PORT_CODE(KEYCODE_F9) PORT_CHAR(UCHAR_MAMEKEY(F9)) - PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_UNUSED) - - PORT_START("X6") - PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Z") PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') - PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("X") PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') - PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C") PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') - PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("V") PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') - PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') - PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("N") PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') - PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("M") PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') - PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(", <") PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<') - PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(". >") PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>') - PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Space") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') - - PORT_START("X7") - PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') - PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("S") PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') - PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D") PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') - PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') - PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G") PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') - PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("H") PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') - PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("J") PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') - PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("K") PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') - PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("L") PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') - PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Scroll") PORT_CODE(KEYCODE_F11) - - PORT_START("X8") - PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Q") PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') - PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("W") PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') - PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E") PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') - PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("R") PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') - PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("T") PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') - PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Y") PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') - PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("U") PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') - PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("I") PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') - PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("O") PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') - PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Tab") PORT_CODE(KEYCODE_TAB) PORT_CHAR(9) - - PORT_START("X9") - PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("1 !") PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') - PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("2 @") PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@') - PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("3 #") PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') - PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("4 $") PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') - PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("5 %") PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') - PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("6 ^") PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^') - PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("7 &") PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&') - PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("8 *") PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*') - PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("9 (") PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(') - PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Esc") PORT_CODE(KEYCODE_ESC) PORT_CHAR(27) - - PORT_START("SW401") - PORT_DIPNAME( 0x0f, 0x0c, "Baud Rate") PORT_DIPLOCATION("SW401:1,2,3,4") - PORT_DIPSETTING( 0x01, "110") - PORT_DIPSETTING( 0x02, "150") - PORT_DIPSETTING( 0x03, "300") - PORT_DIPSETTING( 0x04, "600") - PORT_DIPSETTING( 0x05, "1200") - PORT_DIPSETTING( 0x06, "1800") - PORT_DIPSETTING( 0x07, "2000") - PORT_DIPSETTING( 0x08, "2400") - PORT_DIPSETTING( 0x09, "3600") - PORT_DIPSETTING( 0x0a, "4800") - PORT_DIPSETTING( 0x0b, "7200") - PORT_DIPSETTING( 0x0c, "9600") - PORT_DIPSETTING( 0x0d, "19200") - PORT_DIPNAME( 0x30, 0x00, "Parity") PORT_DIPLOCATION("SW401:5,6") - PORT_DIPSETTING( 0x00, DEF_STR( None ) ) - PORT_DIPSETTING( 0x10, "Odd") - PORT_DIPSETTING( 0x20, DEF_STR( None ) ) - PORT_DIPSETTING( 0x30, "Even") - PORT_DIPNAME( 0x40, 0x00, "Parity Type") PORT_DIPLOCATION("SW401:7") - PORT_DIPSETTING( 0x00, DEF_STR( Normal ) ) - PORT_DIPSETTING( 0x40, "Stick") - PORT_DIPNAME( 0x80, 0x80, "Duplex") PORT_DIPLOCATION("SW401:8") - PORT_DIPSETTING( 0x00, "Half") - PORT_DIPSETTING( 0x80, "Full") - - PORT_START("SW402") - PORT_DIPNAME( 0x01, 0x00, "Cursor") PORT_DIPLOCATION("SW402:1") - PORT_DIPSETTING( 0x00, "Underline") - PORT_DIPSETTING( 0x01, "Block") - PORT_DIPNAME( 0x02, 0x00, "Keyclick") PORT_DIPLOCATION("SW402:2") - PORT_DIPSETTING( 0x02, DEF_STR( No ) ) - PORT_DIPSETTING( 0x00, DEF_STR( Yes ) ) - PORT_DIPNAME( 0x04, 0x00, "Wrap at EOL") PORT_DIPLOCATION("SW402:3") - PORT_DIPSETTING( 0x00, DEF_STR( No ) ) - PORT_DIPSETTING( 0x04, DEF_STR( Yes ) ) - PORT_DIPNAME( 0x08, 0x00, "Auto LF on CR") PORT_DIPLOCATION("SW402:4") - PORT_DIPSETTING( 0x00, DEF_STR( No ) ) - PORT_DIPSETTING( 0x08, DEF_STR( Yes ) ) - PORT_DIPNAME( 0x10, 0x00, "Auto CR on LF") PORT_DIPLOCATION("SW402:5") - PORT_DIPSETTING( 0x00, DEF_STR( No ) ) - PORT_DIPSETTING( 0x10, DEF_STR( Yes ) ) - PORT_DIPNAME( 0x20, 0x00, "Mode") PORT_DIPLOCATION("SW402:6") - PORT_DIPSETTING( 0x00, "Heath/VT52") - PORT_DIPSETTING( 0x20, "ANSI") - PORT_DIPNAME( 0x40, 0x00, "Keypad Shifted") PORT_DIPLOCATION("SW402:7") - PORT_DIPSETTING( 0x00, DEF_STR( No ) ) - PORT_DIPSETTING( 0x40, DEF_STR( Yes ) ) - PORT_DIPNAME( 0x80, 0x00, "Refresh") PORT_DIPLOCATION("SW402:8") - PORT_DIPSETTING( 0x00, "60Hz") - PORT_DIPSETTING( 0x80, "50Hz") - - PORT_START("CONFIG") - PORT_CONFNAME(0x03, 0x00, "CPU Clock") - PORT_CONFSETTING( 0x00, "2 MHz") - PORT_CONFSETTING( 0x01, "3 MHz") - PORT_CONFSETTING( 0x02, "4 MHz") - PORT_CONFSETTING( 0x03, "6 MHz") - PORT_CONFNAME(0x0C, 0x00, "CRT Color") - PORT_CONFSETTING( 0x00, "Green") - PORT_CONFSETTING( 0x04, "White") - PORT_CONFSETTING( 0x08, "Amber") -INPUT_PORTS_END - - -static INPUT_PORTS_START( super19 ) - PORT_INCLUDE( tlb ) - - PORT_MODIFY("SW401") - PORT_DIPNAME( 0x0f, 0x0c, "Baud Rate") PORT_DIPLOCATION("SW401:1,2,3,4") - PORT_DIPSETTING( 0x01, "110") - PORT_DIPSETTING( 0x02, "150") - PORT_DIPSETTING( 0x03, "300") - PORT_DIPSETTING( 0x04, "600") - PORT_DIPSETTING( 0x05, "1200") - PORT_DIPSETTING( 0x06, "1800") - PORT_DIPSETTING( 0x07, "2000") - PORT_DIPSETTING( 0x08, "2400") - PORT_DIPSETTING( 0x09, "3600") - PORT_DIPSETTING( 0x0a, "4800") - PORT_DIPSETTING( 0x0b, "7200") - PORT_DIPSETTING( 0x0c, "9600") - PORT_DIPSETTING( 0x0d, "19200") - PORT_DIPSETTING( 0x0e, "38400") - PORT_DIPNAME( 0x70, 0x00, "8 bit mode") PORT_DIPLOCATION("SW401:5,6,7") - PORT_DIPSETTING( 0x00, "Mode A/0 - 8th bit ignored, sent as 0") - PORT_DIPSETTING( 0x10, "Mode B/1 - 8th bit ignored, sent as 1") - PORT_DIPSETTING( 0x20, "Mode C/2 - 8 bit escape mode") - PORT_DIPSETTING( 0x30, "Mode D/3 - 8 bit escape mode, invert 8th bit") - PORT_DIPSETTING( 0x40, "Mode E/4 - 8 bit data mode") - PORT_DIPSETTING( 0x50, "Mode F/5 - 8 bit data mode, invert 8th bit") - PORT_DIPSETTING( 0x60, "7 bit data with odd parity, 8th bit ignored on input") - PORT_DIPSETTING( 0x70, "7 bit data with even parity, 8th bit ignored on input") - PORT_DIPNAME( 0x80, 0x80, "Duplex") PORT_DIPLOCATION("SW401:8") - PORT_DIPSETTING( 0x00, "Half") - PORT_DIPSETTING( 0x80, "Full") - - PORT_MODIFY("SW402") - PORT_DIPNAME( 0x02, 0x00, "Transmit mode") PORT_DIPLOCATION("SW402:2") - PORT_DIPSETTING( 0x00, DEF_STR( Normal ) ) - PORT_DIPSETTING( 0x02, "Slow") - PORT_DIPNAME( 0x80, 0x00, "DEC Keypad Codes") PORT_DIPLOCATION("SW402:8") - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x80, DEF_STR( On ) ) -INPUT_PORTS_END - - -static INPUT_PORTS_START( superset ) - PORT_INCLUDE( tlb ) - - PORT_MODIFY("SW401") - PORT_DIPNAME( 0x0f, 0x0c, "Baud Rate") PORT_DIPLOCATION("SW401:1,2,3,4") - PORT_DIPSETTING( 0x00, "75") - PORT_DIPSETTING( 0x01, "110") - PORT_DIPSETTING( 0x02, "150") - PORT_DIPSETTING( 0x03, "300") - PORT_DIPSETTING( 0x04, "600") - PORT_DIPSETTING( 0x05, "1200") - PORT_DIPSETTING( 0x06, "1800") - PORT_DIPSETTING( 0x07, "2000") - PORT_DIPSETTING( 0x08, "2400") - PORT_DIPSETTING( 0x09, "3600") - PORT_DIPSETTING( 0x0a, "4800") - PORT_DIPSETTING( 0x0b, "7200") - PORT_DIPSETTING( 0x0c, "9600") - PORT_DIPSETTING( 0x0d, "19200") - PORT_DIPSETTING( 0x0e, "38400") - PORT_DIPSETTING( 0x0f, "134.5") - PORT_DIPNAME( 0x10, 0x10, "Duplex") PORT_DIPLOCATION("SW401:5") - PORT_DIPSETTING( 0x00, "Half") - PORT_DIPSETTING( 0x80, "Full") - PORT_DIPNAME( 0x20, 0x00, "Word Length") PORT_DIPLOCATION("SW401:6") - PORT_DIPSETTING( 0x00, "8-bit" ) - PORT_DIPSETTING( 0x20, "7-bit" ) - PORT_DIPNAME( 0x40, 0x00, "Parity Type") PORT_DIPLOCATION("SW401:7") - PORT_DIPSETTING( 0x00, DEF_STR( None ) ) - PORT_DIPSETTING( 0x40, "Even") - PORT_DIPNAME( 0x80, 0x80, "Parity") PORT_DIPLOCATION("SW401:8") - PORT_DIPSETTING( 0x00, "Disabled") - PORT_DIPSETTING( 0x80, "Enabled") -INPUT_PORTS_END - - -static INPUT_PORTS_START( ultra19 ) - PORT_INCLUDE( tlb ) - - PORT_MODIFY("SW401") - PORT_DIPNAME( 0x07, 0x05, "Baud Rate") PORT_DIPLOCATION("SW401:1,2,3") - PORT_DIPSETTING( 0x00, "110") - PORT_DIPSETTING( 0x01, "300") - PORT_DIPSETTING( 0x02, "1200") - PORT_DIPSETTING( 0x03, "2400") - PORT_DIPSETTING( 0x04, "4800") - PORT_DIPSETTING( 0x05, "9600") - PORT_DIPSETTING( 0x06, "19200") - PORT_DIPSETTING( 0x07, "38400") - PORT_DIPNAME( 0x08, 0x00, "Parity") PORT_DIPLOCATION("SW401:4") - PORT_DIPSETTING( 0x00, "Disabled") - PORT_DIPSETTING( 0x08, "Enabled") - PORT_DIPNAME( 0x10, 0x00, "Parity Type") PORT_DIPLOCATION("SW401:5") - PORT_DIPSETTING( 0x00, "Odd") - PORT_DIPSETTING( 0x10, "Even") - PORT_DIPNAME( 0x20, 0x00, "Data Size") PORT_DIPLOCATION("SW401:6") - PORT_DIPSETTING( 0x00, "8-bit") - PORT_DIPSETTING( 0x20, "7-bit") - PORT_DIPNAME( 0x40, 0x40, "Duplex") PORT_DIPLOCATION("SW401:7") - PORT_DIPSETTING( 0x00, "Half") - PORT_DIPSETTING( 0x40, "Full") - PORT_DIPNAME( 0x80, 0x80, "Software Handshaking") PORT_DIPLOCATION("SW401:8") - PORT_DIPSETTING( 0x00, "Enabled") - PORT_DIPSETTING( 0x80, "Disabled") - - PORT_MODIFY("SW402") - PORT_DIPNAME( 0x08, 0x00, "Keypad Shifted") PORT_DIPLOCATION("SW402:4") - PORT_DIPSETTING( 0x00, DEF_STR( No ) ) - PORT_DIPSETTING( 0x08, DEF_STR( Yes ) ) - PORT_DIPNAME( 0x10, 0x00, "Default Key Values") PORT_DIPLOCATION("SW402:5") - PORT_DIPSETTING( 0x00, "HDOS Values") - PORT_DIPSETTING( 0x10, "CP/M Values") - PORT_DIPNAME( 0x60, 0x60, "Cursor Blink") PORT_DIPLOCATION("SW402:6,7") - PORT_DIPSETTING( 0x00, "Steady") - PORT_DIPSETTING( 0x20, "Invisible") - PORT_DIPSETTING( 0x40, "Fast Blink") - PORT_DIPSETTING( 0x60, "Slow Blink") - PORT_DIPNAME( 0x80, 0x00, "Interlace Scan Mode") PORT_DIPLOCATION("SW402:8") - PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x80, DEF_STR( On ) ) -INPUT_PORTS_END - - -static INPUT_PORTS_START( watz19 ) - PORT_INCLUDE( tlb ) - - PORT_MODIFY("SW401") - PORT_DIPNAME( 0x0f, 0x0c, "Baud Rate") PORT_DIPLOCATION("SW401:1,2,3,4") - PORT_DIPSETTING( 0x00, "75") - PORT_DIPSETTING( 0x01, "110") - PORT_DIPSETTING( 0x02, "150") - PORT_DIPSETTING( 0x03, "300") - PORT_DIPSETTING( 0x04, "600") - PORT_DIPSETTING( 0x05, "1200") - PORT_DIPSETTING( 0x06, "1800") - PORT_DIPSETTING( 0x07, "2000") - PORT_DIPSETTING( 0x08, "2400") - PORT_DIPSETTING( 0x09, "3600") - PORT_DIPSETTING( 0x0a, "4800") - PORT_DIPSETTING( 0x0b, "7200") - PORT_DIPSETTING( 0x0c, "9600") - PORT_DIPSETTING( 0x0d, "19200") - PORT_DIPSETTING( 0x0e, "38400") - PORT_DIPSETTING( 0x0f, "134.5") - PORT_DIPNAME( 0x40, 0x00, "Word Size") PORT_DIPLOCATION("SW401:7") - PORT_DIPSETTING( 0x00, "8-bit Word") - PORT_DIPSETTING( 0x40, "7-bit Word") - PORT_DIPNAME( 0x80, 0x80, "Duplex") PORT_DIPLOCATION("SW401:8") - PORT_DIPSETTING( 0x00, "Half") - PORT_DIPSETTING( 0x80, "Full") -INPUT_PORTS_END - - -static INPUT_PORTS_START( gp19 ) - PORT_INCLUDE( tlb ) - - PORT_MODIFY("SW402") - PORT_DIPNAME( 0x80, 0x00, "Automatic Holdscreen") PORT_DIPLOCATION("SW402:8") - PORT_DIPSETTING( 0x00, "Disabled (VT100 mode)") - PORT_DIPSETTING( 0x80, "Enabled (Z19 mode)") - - PORT_START("SW1") - PORT_DIPNAME( 0x03, 0x01, "Trailing Characters for Tektronix Message") PORT_DIPLOCATION("SW1:1,2") - PORT_DIPSETTING( 0x00, DEF_STR( None ) ) - PORT_DIPSETTING( 0x01, "CR") - PORT_DIPSETTING( 0x02, DEF_STR( None ) ) - PORT_DIPSETTING( 0x03, "CR,EOT") - PORT_DIPNAME( 0x04, 0x01, "Shift Key") PORT_DIPLOCATION("SW1:3") - PORT_DIPSETTING( 0x00, DEF_STR( Normal ) ) - PORT_DIPSETTING( 0x04, "Shift key inverts CAPS LOCK") - PORT_DIPNAME( 0x08, 0x00, "Terminal Transmission Rate") PORT_DIPLOCATION("SW1:4") - PORT_DIPSETTING( 0x00, "Only limited by baud rate") - PORT_DIPSETTING( 0x08, "One character per 16.7 msec") - PORT_DIPNAME( 0x10, 0x10, "Character Set") PORT_DIPLOCATION("SW1:5") - PORT_DIPSETTING( 0x00, "VT100") - PORT_DIPSETTING( 0x10, "Zenith") - PORT_DIPNAME( 0x20, 0x00, "ANSI Mode") PORT_DIPLOCATION("SW1:6") - PORT_DIPSETTING( 0x00, "Zenith ANSI") - PORT_DIPSETTING( 0x20, "EDT compatible") - PORT_DIPNAME( 0x40, 0x00, "Tektronix Character Wrap") PORT_DIPLOCATION("SW1:7") - PORT_DIPSETTING( 0x00, "Column 74") - PORT_DIPSETTING( 0x40, "Column 73") - PORT_DIPNAME( 0x80, 0x00, "Blank Screen") PORT_DIPLOCATION("SW1:8") - PORT_DIPSETTING( 0x00, "After 10 mins") - PORT_DIPSETTING( 0x80, "Never") -INPUT_PORTS_END - - -ROM_START( h19 ) - // Original terminal code - ROM_REGION( 0x1000, "maincpu", ROMREGION_ERASEFF ) - ROM_LOAD( "2732_444-46_h19code.u437", 0x0000, 0x1000, CRC(f4447da0) SHA1(fb4093d5b763be21a9580a0defebed664b1f7a7b)) - - // Original font - ROM_REGION( 0x0800, "chargen", 0 ) - ROM_LOAD( "2716_444-29_h19font.u420", 0x0000, 0x0800, CRC(d595ac1d) SHA1(130fb4ea8754106340c318592eec2d8a0deaf3d0)) - - // Original keyboard - ROM_REGION( 0x0800, "keyboard", 0 ) - ROM_LOAD( "2716_444-37_h19keyb.u445", 0x0000, 0x0800, CRC(5c3e6972) SHA1(df49ce64ae48652346a91648c58178a34fb37d3c)) -ROM_END - -ROM_START( super19 ) - // Super-19 ROM - ROM_REGION( 0x1000, "maincpu", ROMREGION_ERASEFF ) - ROM_LOAD( "2732_super19_h447.u437", 0x0000, 0x1000, CRC(6c51aaa6) SHA1(5e368b39fe2f1af44a905dc474663198ab630117)) - - // Original font - ROM_REGION( 0x0800, "chargen", 0 ) - ROM_LOAD( "2716_444-29_h19font.u420", 0x0000, 0x0800, CRC(d595ac1d) SHA1(130fb4ea8754106340c318592eec2d8a0deaf3d0)) - - // Original keyboard - ROM_REGION( 0x0800, "keyboard", 0 ) - ROM_LOAD( "2716_444-37_h19keyb.u445", 0x0000, 0x0800, CRC(5c3e6972) SHA1(df49ce64ae48652346a91648c58178a34fb37d3c)) -ROM_END - -ROM_START( superset ) - // SuperSet ROM - ROM_REGION( 0x4000, "maincpu", ROMREGION_ERASEFF ) - ROM_LOAD( "27256_101-402_superset_code.u437", 0x0000, 0x2000, CRC(a6896076) SHA1(a4e2d25028dc75a665c3f5a830a4e8cdecbd481c)) - // 1st 8k is unused, so overwrite it, with the next 16k (but only first 8k is valid) - ROM_CONTINUE(0x0000, 0x4000) - // overwrite at 8k starting address with the last 8k of the chip. - ROM_CONTINUE(0x2000, 0x2000) - - // Superset SUPERFONT - ROM_REGION( 0x8000, "chargen", 0 ) - ROM_LOAD( "27256_101-431_superset_font.u420", 0x0000, 0x8000, CRC(4c0688f6) SHA1(be6059913420ad66f5c839d619fdcb164ffae85a)) - - // Superset Keyboard - ROM_REGION( 0x0800, "keyboard", 0 ) - ROM_LOAD( "2716_101-422_superset_kbd.u445", 0x0000, 0x0800, CRC(549d15b3) SHA1(981962e5e05bbdc5a66b0e86870853ce5596e877)) -ROM_END - -ROM_START( watz19 ) - ROM_REGION( 0x1000, "maincpu", ROMREGION_ERASEFF ) - ROM_DEFAULT_BIOS("watzman-a") - - // Watzman ROM - ROM_SYSTEM_BIOS(0, "watzman", "Watzman") - ROMX_LOAD("watzman.u437", 0x0000, 0x1000, CRC(8168b6dc) SHA1(bfaebb9d766edbe545d24bc2b6630be4f3aa0ce9), ROM_BIOS(0)) - - ROM_SYSTEM_BIOS(1, "watzman-a", "Watzman w/clock persists after reset") - ROMX_LOAD("watzman-a.u437", 0x0000, 0x1000, CRC(1f7553e9) SHA1(ac6ddb12b4fb46c1a0ad08ee43978ad3153b51aa), ROM_BIOS(1)) - - // Original font - ROM_REGION( 0x0800, "chargen", 0 ) - ROM_LOAD( "2716_444-29_h19font.u420", 0x0000, 0x0800, CRC(d595ac1d) SHA1(130fb4ea8754106340c318592eec2d8a0deaf3d0)) - - // Watzman keyboard - ROM_REGION( 0x0800, "keyboard", 0 ) - ROM_LOAD( "keybd.u445", 0x0000, 0x0800, CRC(58dc8217) SHA1(1b23705290bdf9fc6342065c6a528c04bff67b13)) -ROM_END - -ROM_START( ultra19 ) - // Ultra ROM - ROM_REGION( 0x1000, "maincpu", ROMREGION_ERASEFF ) - ROM_LOAD( "2532_h19_ultra_firmware.u437", 0x0000, 0x1000, CRC(8ad4cdb4) SHA1(d6e1fc37a1f52abfce5e9adb1819e0030bed1df3)) - - // Original font - ROM_REGION( 0x0800, "chargen", 0 ) - ROM_LOAD( "2716_444-29_h19font.u420", 0x0000, 0x0800, CRC(d595ac1d) SHA1(130fb4ea8754106340c318592eec2d8a0deaf3d0)) - - // Ultra keyboard - ROM_REGION( 0x0800, "keyboard", 0 ) - ROM_LOAD( "2716_h19_ultra_keyboard.u445", 0x0000, 0x0800, CRC(76130c92) SHA1(ca39c602af48505139d2750a084b5f8f0e662ff7)) -ROM_END - -ROM_START( gp19 ) - // GP-19 ROMs - ROM_REGION( 0x3000, "maincpu", ROMREGION_ERASEFF ) - ROM_LOAD( "gp19_rom_1_ver_1_1.u26", 0x0000, 0x1000, CRC(7cbe8e0d) SHA1(977df895b067fa4e4646b4518cffb08d4e6bb6e0)) - ROM_LOAD( "gp19_rom_2_ver_1_1.u25", 0x1000, 0x1000, CRC(a85e3bc4) SHA1(f64e851c5d3ef98a9a48e0fc482baa576773ff43)) - ROM_LOAD( "gp19_rom_3_ver_1_1.u24", 0x2000, 0x1000, CRC(878f577c) SHA1(0756435914dcfb981de4e40d5f81af3e0f5bb1c5)) - - // GP-19 font - ROM_REGION( 0x1000, "chargen", 0 ) - ROM_LOAD( "gp19_char_gen_cg_1.u21", 0x0000, 0x1000, CRC(49ec9242) SHA1(770a8c7b5b15bcfe465fd84326d0ae3dcaa85311)) - - // Original keyboard - ROM_REGION( 0x0800, "keyboard", 0 ) - ROM_LOAD( "2716_444-37_h19keyb.u445", 0x0000, 0x0800, CRC(5c3e6972) SHA1(df49ce64ae48652346a91648c58178a34fb37d3c)) -ROM_END - -ROM_START( imaginator ) - // Program code - ROM_REGION( 0x4000, "maincpu", ROMREGION_ERASEFF ) - // Original terminal code - ROM_LOAD( "2732_444-46_h19code.u437", 0x0000, 0x1000, CRC(f4447da0) SHA1(fb4093d5b763be21a9580a0defebed664b1f7a7b)) - // Imaginator ROMs - ROM_LOAD( "2732_imaginator_gpc_rev_1.2_pn_9000_0002.u9a", 0x2000, 0x1000, CRC(507bb13f) SHA1(5b210f8d77e22fdf063f611eb5c29636cdb01250)) - - // Original font - ROM_REGION( 0x0800, "chargen", 0 ) - ROM_LOAD( "2716_444-29_h19font.u420", 0x0000, 0x0800, CRC(d595ac1d) SHA1(130fb4ea8754106340c318592eec2d8a0deaf3d0)) - - // Original keyboard - ROM_REGION( 0x0800, "keyboard", 0 ) - ROM_LOAD( "2716_444-37_h19keyb.u445", 0x0000, 0x0800, CRC(5c3e6972) SHA1(df49ce64ae48652346a91648c58178a34fb37d3c)) -ROM_END - - -ioport_constructor heath_tlb_device::device_input_ports() const -{ - return INPUT_PORTS_NAME(tlb); -} - -const tiny_rom_entry *heath_tlb_device::device_rom_region() const -{ - return ROM_NAME(h19); -} - -void heath_tlb_device::serial_out_b(int data) -{ - m_slot->serial_out_b(data); -} - -void heath_tlb_device::dtr_out(int data) -{ - m_slot->dtr_out(data); -} - -void heath_tlb_device::rts_out(int data) -{ - m_slot->rts_out(data); -} - -void heath_tlb_device::serial_in_w(int state) -{ - m_ace->rx_w(state); -} - -void heath_tlb_device::rlsd_in_w(int state) -{ - m_ace->dcd_w(state); -} - -void heath_tlb_device::dsr_in_w(int state) -{ - m_ace->dsr_w(state); -} - -void heath_tlb_device::cts_in_w(int state) -{ - m_ace->cts_w(state); -} - -void heath_tlb_device::device_add_mconfig(machine_config &config) -{ - // basic machine hardware - Z80(config, m_maincpu, H19_CLOCK); - m_maincpu->set_addrmap(AS_PROGRAM, &heath_tlb_device::mem_map); - m_maincpu->set_addrmap(AS_IO, &heath_tlb_device::io_map); - - // video hardware - SCREEN(config, m_screen, SCREEN_TYPE_RASTER, rgb_t::green()); - // based on the H19 ROM code for 60 Hz - m_screen->set_raw(BASE_DOT_CLOCK, 768, 32, 672, 270, 0, 250); - m_screen->set_screen_update("crtc", FUNC(mc6845_device::screen_update)); - - GFXDECODE(config, "gfxdecode", m_palette, gfx_h19); - PALETTE(config, "palette", palette_device::MONOCHROME); - - // MC 6845 uses a character clock, divide the DOT clock by 8. - MC6845(config, m_crtc, BASE_DOT_CLOCK / 8); - 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(heath_tlb_device::crtc_update_row)); - // frame pulse - m_crtc->out_vsync_callback().set(FUNC(heath_tlb_device::crtc_vsync_w)); - - // serial port - INS8250(config, m_ace, INS8250_CLOCK); - m_ace->out_int_callback().set(FUNC(heath_tlb_device::serial_irq_w)); - m_ace->out_tx_callback().set(FUNC(heath_tlb_device::serial_out_b)); - m_ace->out_dtr_callback().set(FUNC(heath_tlb_device::dtr_out)); - m_ace->out_rts_callback().set(FUNC(heath_tlb_device::rts_out)); - - // keyboard - MM5740(config, m_mm5740, MM5740_CLOCK); - m_mm5740->x_cb<1>().set_ioport("X1"); - m_mm5740->x_cb<2>().set_ioport("X2"); - m_mm5740->x_cb<3>().set_ioport("X3"); - m_mm5740->x_cb<4>().set_ioport("X4"); - m_mm5740->x_cb<5>().set_ioport("X5"); - m_mm5740->x_cb<6>().set_ioport("X6"); - m_mm5740->x_cb<7>().set_ioport("X7"); - m_mm5740->x_cb<8>().set_ioport("X8"); - m_mm5740->x_cb<9>().set_ioport("X9"); - m_mm5740->shift_cb().set(FUNC(heath_tlb_device::mm5740_shift_r)); - m_mm5740->control_cb().set(FUNC(heath_tlb_device::mm5740_control_r)); - m_mm5740->data_ready_cb().set(FUNC(heath_tlb_device::mm5740_data_ready_w)); - - // sound hardware - SPEAKER(config, "mono").front_center(); - BEEP(config, m_beep, H19_BEEP_FRQ).add_route(ALL_OUTPUTS, "mono", 0.05); - - // clock for repeat key - CLOCK(config, m_repeat_clock, 40); - m_repeat_clock->set_duty_cycle(0); - m_repeat_clock->signal_handler().set(m_mm5740, FUNC(mm5740_device::repeat_line_w)); -} - - -/** - * Super-19 ROM - * - * Developed by ATG Systems - */ -heath_super19_tlb_device::heath_super19_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : - heath_tlb_device(mconfig, HEATH_SUPER19, tag, owner, clock) -{ -} - -const tiny_rom_entry *heath_super19_tlb_device::device_rom_region() const -{ - return ROM_NAME(super19); -} - -ioport_constructor heath_super19_tlb_device::device_input_ports() const -{ - return INPUT_PORTS_NAME(super19); -} - - -/** - * Superset ROM - * - * Developed by TMSI - */ -heath_superset_tlb_device::heath_superset_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : - heath_tlb_device(mconfig, HEATH_SUPERSET, tag, owner, clock), - m_selected_char_set(0) -{ -} - -void heath_superset_tlb_device::device_add_mconfig(machine_config &config) -{ - heath_tlb_device::device_add_mconfig(config); - - // part of the Superset upgrade was to upgrade the CPU to 3 MHz. - m_maincpu->set_clock(H19_3MHZ); - m_maincpu->set_addrmap(AS_PROGRAM, &heath_superset_tlb_device::mem_map); - m_maincpu->set_addrmap(AS_IO, &heath_superset_tlb_device::io_map); - - // per line updates are needed for onscreen menu to display properly - m_screen->set_video_attributes(VIDEO_UPDATE_SCANLINE); - - m_crtc->set_update_row_callback(FUNC(heath_superset_tlb_device::crtc_update_row)); - - // link up the serial port outputs to font chip. - m_ace->out_dtr_callback().set(FUNC(heath_superset_tlb_device::dtr_internal)); - m_ace->out_out1_callback().set(FUNC(heath_superset_tlb_device::out1_internal)); - m_ace->out_out2_callback().set(FUNC(heath_superset_tlb_device::out2_internal)); -} - -void heath_superset_tlb_device::device_start() -{ - heath_tlb_device::device_start(); - - save_item(NAME(m_selected_char_set)); - - m_selected_char_set = 0; -} - -void heath_superset_tlb_device::mem_map(address_map &map) -{ - heath_tlb_device::mem_map(map); - - // update rom space for the 16k ROM. - map(0x0000, 0x3fff).rom(); - - // page 2 memory - map(0x8000, 0x87ff).ram(); -} - -void heath_superset_tlb_device::io_map(address_map &map) -{ - heath_tlb_device::io_map(map); - - map(0x61, 0x61).mirror(0x12).select(0x0c).rw(FUNC(heath_superset_tlb_device::crtc_reg_r), FUNC(heath_superset_tlb_device::crtc_reg_w)); -} - -const tiny_rom_entry *heath_superset_tlb_device::device_rom_region() const -{ - return ROM_NAME(superset); -} - -ioport_constructor heath_superset_tlb_device::device_input_ports() const -{ - return INPUT_PORTS_NAME(superset); -} - -u8 heath_superset_tlb_device::crtc_reg_r(offs_t reg) -{ - if (!machine().side_effects_disabled()) - { - m_reverse_video_disabled = bool(BIT(reg, 3)); - } - - return heath_tlb_device::crtc_reg_r(reg); -} - -void heath_superset_tlb_device::crtc_reg_w(offs_t reg, u8 val) -{ - m_reverse_video_disabled = bool(BIT(reg, 3)); - - heath_tlb_device::crtc_reg_w(reg, val); -} - -MC6845_UPDATE_ROW(heath_superset_tlb_device::crtc_update_row) -{ - rgb_t const *const palette = m_palette->palette()->entry_list_raw(); - u32 *p = &bitmap.pix(y); - - if (de) - { - for (int x = 0; x < x_count; x++) - { - u8 inv = (x == cursor_x) ? 0xff : 0; - u8 chr = m_p_videoram[(ma + x) & 0x7ff]; - u16 char_set_base_offset = (m_selected_char_set << 11); - - if (chr & 0x80) - { - if (m_reverse_video_disabled) - { - // set A13 - char_set_base_offset |= 0x2000; - } - else - { - inv ^= 0xff; - } - - chr &= 0x7f; - } - - // get pattern of pixels for the character scanline - u8 const gfx = m_p_chargen[char_set_base_offset | (chr << 4) | ra] ^ inv; - - // Display a scanline of a character (8 pixels) - for (int b = 0; 8 > b; ++b) - { - *p++ = palette[BIT(gfx, b)]; - } - } - } - else - { - std::fill_n(p, bitmap.rowpixels(), palette[0]); - } -} - -// DTR (pin 33) to A14 (pin 27) of 27256 ROM -void heath_superset_tlb_device::dtr_internal(int data) -{ - m_selected_char_set = (m_selected_char_set & 0x03) | ((data & 0x01) << 3); -} - -// OUT1 (pin 34) to A12 (pin 2) of 27256 ROM -void heath_superset_tlb_device::out1_internal(int data) -{ - m_selected_char_set = (m_selected_char_set & 0x09) | ((data & 0x01) << 1); -} - -// OUT2 (pin 31) to A11? on board -void heath_superset_tlb_device::out2_internal(int data) -{ - m_selected_char_set = (m_selected_char_set & 0x0a) | (data & 0x01); -} - - -/** - * Watzman ROM - * - * Developed by Barry Watzman, sold by HUG (Heath Users Group) -*/ -heath_watz_tlb_device::heath_watz_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : - heath_tlb_device(mconfig, HEATH_WATZ, tag, owner, clock) -{ -} - -const tiny_rom_entry *heath_watz_tlb_device::device_rom_region() const -{ - return ROM_NAME(watz19); -} - -ioport_constructor heath_watz_tlb_device::device_input_ports() const -{ - return INPUT_PORTS_NAME(watz19); -} - - -/** - * UltraROM - * - * Developed by William G. Parrott, III, sold by Software Wizardry, Inc. - */ -heath_ultra_tlb_device::heath_ultra_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : - heath_tlb_device(mconfig, HEATH_ULTRA, tag, owner, clock) -{ -} - -void heath_ultra_tlb_device::device_add_mconfig(machine_config &config) -{ - heath_tlb_device::device_add_mconfig(config); - - m_maincpu->set_addrmap(AS_PROGRAM, &heath_ultra_tlb_device::mem_map); -} - -void heath_ultra_tlb_device::mem_map(address_map &map) -{ - heath_tlb_device::mem_map(map); - - // update rom mirror setting to allow page 2 memory - map(0x0000, 0x0fff).mirror(0x2000).rom(); - - // Page 2 memory - map(0x1000, 0x1fff).mirror(0x2000).ram(); -} - -const tiny_rom_entry *heath_ultra_tlb_device::device_rom_region() const -{ - return ROM_NAME(ultra19); -} - -ioport_constructor heath_ultra_tlb_device::device_input_ports() const -{ - return INPUT_PORTS_NAME(ultra19); -} - - -/** - * Northwest Digital Systems GP-19 add-in board - */ -heath_gp19_tlb_device::heath_gp19_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : - heath_tlb_device(mconfig, HEATH_GP19, tag, owner, clock) -{ -} - -void heath_gp19_tlb_device::device_add_mconfig(machine_config &config) -{ - heath_tlb_device::device_add_mconfig(config); - - m_maincpu->set_addrmap(AS_PROGRAM, &heath_gp19_tlb_device::mem_map); - m_maincpu->set_addrmap(AS_IO, &heath_gp19_tlb_device::io_map); - - m_crtc->set_update_row_callback(FUNC(heath_gp19_tlb_device::crtc_update_row)); - m_crtc->set_clock(GP19_DOT_CLOCK_2 / 8); - - m_screen->set_raw(GP19_DOT_CLOCK_2, 776, 32, 672, 264, 10, 250); -} - -void heath_gp19_tlb_device::device_start() -{ - heath_tlb_device::device_start(); - - save_item(NAME(m_char_gen_a11)); - save_item(NAME(m_graphic_mode)); - save_item(NAME(m_col_132)); - save_item(NAME(m_reverse_video)); - - m_char_gen_a11 = false; - m_graphic_mode = false; - m_col_132 = false; - m_reverse_video = false; -} - -void heath_gp19_tlb_device::mem_map(address_map &map) -{ - // ROMs 1, 2, 3 - map(0x0000, 0x02fff).rom(); - - // Optional external board - Program ROM 4(not aware if any ever existed), external I/O - // map(0x3000, 0x03fff).rom(); - - map(0x4000, 0x40ff).mirror(0x3f00).ram(); - map(0x6000, 0x67ff).mirror(0x1800).ram(); - map(0x8000, 0xbfff).mirror(0x4000).ram().share(m_p_videoram); -} - -void heath_gp19_tlb_device::io_map(address_map &map) -{ - heath_tlb_device::io_map(map); - - // Latch U5 - map(0x68, 0x68).mirror(0x07).w(FUNC(heath_gp19_tlb_device::latch_u5_w)); - - // Switch on GP-19 board - map(0x70, 0x70).mirror(0x07).portr("SW1"); - - // Optional Auxiliary I/O connector(not aware if any ever existed) - // map(0x78, 0x78).mirror(0x07); -} - -/** - * U5 Latch - * - * Q0 Graph/character H - * Q1 132/80 columns H - * Q2 Reverse Screen H - * Q3 Alt Character L - * Q4-Q7 LED indicators (debug LEDs on circuit board) - */ -void heath_gp19_tlb_device::latch_u5_w(u8 data) -{ - m_graphic_mode = bool(BIT(data, 0)); - m_col_132 = bool(BIT(data, 1)); - m_reverse_video = bool(BIT(data, 2)); - m_char_gen_a11 = bool(BIT(data, 3)); - - // TODO handle LED indicators - - if (m_graphic_mode) - { - m_crtc->set_clock(GP19_DOT_CLOCK_3 / 8); - } - else if (m_col_132) - { - m_crtc->set_clock(GP19_DOT_CLOCK_1 / 8); - } - else - { - m_crtc->set_clock(GP19_DOT_CLOCK_2 / 8); - } -} - -MC6845_UPDATE_ROW(heath_gp19_tlb_device::crtc_update_row) -{ - rgb_t const *const palette = m_palette->palette()->entry_list_raw(); - u32 *p = &bitmap.pix(y); - - if (de) - { - u8 screen_inv = m_reverse_video ? 0xff : 0x00; - - if (m_graphic_mode) - { - for (int x = 0; x < x_count; x++) - { - u8 const gfx = m_p_videoram[((ma << 1) + (ra * x_count) + x) & 0x3fff] ^ screen_inv; - - for (int b = 0; 8 > b; ++b) - { - *p++ = palette[BIT(gfx, b)]; - } - } - } - else - { - u16 const base = m_char_gen_a11 ? 0x800 : 0x0; - - for (int x = 0; x < x_count; x++) - { - u8 inv = (x == cursor_x) ? 0xff : 0; - u8 chr = m_p_videoram[(ma + x) & 0x3fff]; - - if (chr & 0x80) - { - inv ^= 0xff; - chr &= 0x7f; - } - - inv ^= screen_inv; - - // select proper character set - u8 const gfx = m_p_chargen[base | (chr << 4) | ra] ^ inv; - - // Display a scanline of a character (8 pixels) - for (int b = 0; 8 > b; ++b) - { - *p++ = palette[BIT(gfx, b)]; - } - } - } - } - else - { - std::fill_n(p, x_count * 8, palette[0]); - } -} - -const tiny_rom_entry *heath_gp19_tlb_device::device_rom_region() const -{ - return ROM_NAME(gp19); -} - -ioport_constructor heath_gp19_tlb_device::device_input_ports() const -{ - return INPUT_PORTS_NAME(gp19); -} - - -/** - * Cleveland Codonics Imaginator-100 (I-100) add-in board - * - * Memory Range Description - * ----------------------------------------------------------------- - * 0x0000-0x1fff Program ROM (Heath TLB board) - * 0x2000-0x3fff Graphics Command Processor(GCP) ROM (I-100) - * 0x4000-0x5fff Scratchpad RAM (Heath TLB board) - * 0x6000-0x7fff Graphics Scratchpad R/W RAM (I-100) - * 0x8000-0xbfff Graphics Display R/W RAM(I-100) - * 0xc000-0xdfff Optional Graphics Command Processor memory (I-100) - * 0xe000-0xffff Display Memory (Heath TLB board) - * - * New interrupt source - * - horizontal retrace interrupt - * - */ -heath_imaginator_tlb_device::heath_imaginator_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : - heath_tlb_device(mconfig, HEATH_IMAGINATOR, tag, owner, clock), - m_mem_bank(*this, "membank"), - m_p_graphic_ram(*this, "graphicram") -{ -} - -void heath_imaginator_tlb_device::device_add_mconfig(machine_config &config) -{ - heath_tlb_device::device_add_mconfig(config); - - m_maincpu->set_addrmap(AS_PROGRAM, &heath_imaginator_tlb_device::mem_map); - m_maincpu->set_addrmap(AS_IO, &heath_imaginator_tlb_device::io_map); - m_maincpu->set_irq_acknowledge_callback(FUNC(heath_imaginator_tlb_device::irq_ack_cb)); - - m_crtc->out_hsync_callback().set(FUNC(heath_imaginator_tlb_device::crtc_hsync_w)); -} - -void heath_imaginator_tlb_device::device_start() -{ - heath_tlb_device::device_start(); - - save_item(NAME(m_im2_val)); - save_item(NAME(m_alphanumeric_mode_active)); - save_item(NAME(m_graphics_mode_active)); - save_item(NAME(m_allow_tlb_interrupts)); - save_item(NAME(m_allow_imaginator_interrupts)); - save_item(NAME(m_hsync_irq_raised)); - - m_mem_bank->configure_entries(0, 2, memregion("maincpu")->base(), 0x2000); - - m_maincpu->space(AS_PROGRAM).install_readwrite_tap(0x8000, 0xbfff, "irq_update", - [this] (offs_t offset, u8 &data, u8 mem_mask) { if (!machine().side_effects_disabled()) { tap_8000h(); } }, - [this] (offs_t offset, u8 &data, u8 mem_mask) { if (!machine().side_effects_disabled()) { tap_8000h(); } }); -} - -void heath_imaginator_tlb_device::device_reset() -{ - heath_tlb_device::device_reset(); - - m_mem_bank->set_entry(1); - m_tap_6000h.remove(); - m_tap_6000h = m_maincpu->space(AS_PROGRAM).install_readwrite_tap(0x6000, 0x7fff, "mem_map_update", - [this] (offs_t offset, u8 &data, u8 mem_mask) { if (!machine().side_effects_disabled()) { tap_6000h(); } }, - [this] (offs_t offset, u8 &data, u8 mem_mask) { if (!machine().side_effects_disabled()) { tap_6000h(); } }); - - m_alphanumeric_mode_active = true; - m_graphics_mode_active = false; - - m_hsync_irq_raised = false; - - allow_tlb_intr(); -} - -void heath_imaginator_tlb_device::mem_map(address_map &map) -{ - map.unmap_value_high(); - - map(0x0000, 0x1fff).bankr(m_mem_bank); - - // Normal spot of the GCP ROM - map(0x2000, 0x3fff).rom(); - - // TLB Scratchpad - map(0x4000, 0x40ff).mirror(0x1f00).ram(); - - // GCP Scratchpad - map(0x6000, 0x607f).mirror(0x1f80).ram(); - - // Graphics RAM - map(0x8000, 0xbfff).ram().share(m_p_graphic_ram); - - // optional Graphics Command Processor (GCP) - // map(0xc000, 0xdfff); - - // Alphanumeric RAM - map(0xe000, 0xe7ff).mirror(0x1800).ram().share(m_p_videoram); -} - -void heath_imaginator_tlb_device::tap_6000h() -{ - m_mem_bank->set_entry(0); - m_tap_6000h.remove(); -} - -void heath_imaginator_tlb_device::tap_8000h() -{ - if (!m_allow_tlb_interrupts) - { - allow_tlb_intr(); - - set_irq_line(); - } -} - -void heath_imaginator_tlb_device::allow_tlb_intr() -{ - m_allow_tlb_interrupts = true; - m_allow_imaginator_interrupts = false; - m_im2_val = 0x02; -} - -void heath_imaginator_tlb_device::allow_hsync_intr() -{ - m_allow_tlb_interrupts = false; - m_allow_imaginator_interrupts = true; - m_im2_val = 0x00; -} - -/** - * An input/output request (IORQ) is sent to the TERMINAL LOGIC board only when - * both IORQ (pin 20 of U7) AND A4 are low. - */ -void heath_imaginator_tlb_device::io_map(address_map &map) -{ - heath_tlb_device::io_map(map); - - // interrupt routing - map(0x10, 0x10).select(0x08).mirror(0x07).w(FUNC(heath_imaginator_tlb_device::config_irq_w)); - - // display enabling (graphics or alphanumeric) - map(0x30, 0x30).select(0xc0).mirror(0x0f).w(FUNC(heath_imaginator_tlb_device::display_enable_w)); - - // Avoids writes to TLB when a4 is high on unused - map(0x50, 0x50).select(0x80).mirror(0x0f).w(FUNC(heath_imaginator_tlb_device::nop_w)); -} - -IRQ_CALLBACK_MEMBER(heath_imaginator_tlb_device::irq_ack_cb) -{ - return m_im2_val; -} - -void heath_imaginator_tlb_device::config_irq_w(offs_t reg, u8 val) -{ - if (BIT(reg, 3)) - { - allow_tlb_intr(); - } - else - { - allow_hsync_intr(); - } - - set_irq_line(); -} - -void heath_imaginator_tlb_device::display_enable_w(offs_t reg, u8 val) -{ - m_alphanumeric_mode_active = bool(BIT(reg, 7)); - m_graphics_mode_active = bool(BIT(reg, 6)); -} - -void heath_imaginator_tlb_device::nop_w(offs_t, u8) -{ -} - -const tiny_rom_entry *heath_imaginator_tlb_device::device_rom_region() const -{ - return ROM_NAME(imaginator); -} - -MC6845_UPDATE_ROW(heath_imaginator_tlb_device::crtc_update_row) -{ - rgb_t const *const palette = m_palette->palette()->entry_list_raw(); - u32 *p = &bitmap.pix(y); - - if (de) - { - for (int x = 0; x < x_count; x++) - { - u8 output = 0x00; - - if (m_alphanumeric_mode_active) - { - u8 inv = (x == cursor_x) ? 0xff : 0; - u8 chr = m_p_videoram[(ma + x) & 0x7ff]; - - if (chr & 0x80) - { - inv ^= 0xff; - chr &= 0x7f; - } - - output |= m_p_chargen[(chr << 4) | ra] ^ inv; - } - - if (m_graphics_mode_active && (x > 7 ) && (x < 73)) - { - output |= m_p_graphic_ram[((y * 64) + (x - 8)) & 0x3fff]; - } - - for (int b = 0; 8 > b; ++b) - { - *p++ = palette[BIT(output, b)]; - } - } - } - else - { - std::fill_n(p, x_count * 8, palette[0]); - } -} - -void heath_imaginator_tlb_device::crtc_hsync_w(int val) -{ - m_hsync_irq_raised = bool(val); - - set_irq_line(); -} - -void heath_imaginator_tlb_device::set_irq_line() -{ - m_maincpu->set_input_line(INPUT_LINE_IRQ0, - (m_allow_imaginator_interrupts && m_hsync_irq_raised) || - (m_allow_tlb_interrupts && (m_keyboard_irq_raised || m_serial_irq_raised || m_break_key_irq_raised)) ? - ASSERT_LINE : CLEAR_LINE); -} - - -/** - * SigmaSoft Interactive Graphics Controller (IGC) - * - * - */ -heath_igc_tlb_device::heath_igc_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : - heath_tlb_device(mconfig, HEATH_IGC, tag, owner, clock) -{ -} - -heath_igc_tlb_device::heath_igc_tlb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) : - heath_tlb_device(mconfig, type, tag, owner, clock) -{ -} - -void heath_igc_tlb_device::device_add_mconfig(machine_config &config) -{ - heath_tlb_device::device_add_mconfig(config); - - m_crtc->set_update_row_callback(FUNC(heath_igc_tlb_device::crtc_update_row)); -} - -void heath_igc_tlb_device::device_start() -{ - heath_tlb_device::device_start(); - - m_p_graphic_ram = make_unique_clear(0x3ffff); - save_pointer(NAME(m_p_graphic_ram), 0x3ffff); - - save_item(NAME(m_data_reg)); - save_item(NAME(m_pixel_video_enabled)); - save_item(NAME(m_character_video_disabled)); - save_item(NAME(m_video_invert_enabled)); - save_item(NAME(m_alternate_character_set_enabled)); - save_item(NAME(m_video_fill_enabled)); - save_item(NAME(m_read_address_increment_disabled)); - save_item(NAME(m_memory_bank_select)); - save_item(NAME(m_io_address)); - save_item(NAME(m_window_address)); -} - -void heath_igc_tlb_device::device_reset() -{ - heath_tlb_device::device_reset(); - - sigma_ctrl_w(0); - m_data_reg = 0x00; - m_io_address = 0x0000; - m_window_address = 0x0000; -} - -void heath_igc_tlb_device::sigma_ctrl_w(u8 data) -{ - LOGREG("%s: data: %02x\n", FUNCNAME, data); - - m_pixel_video_enabled = bool(BIT(data, 0)); - m_character_video_disabled = bool(BIT(data, 1)); - m_video_invert_enabled = bool(BIT(data, 2)); - m_alternate_character_set_enabled = bool(BIT(data, 3)); - m_video_fill_enabled = bool(BIT(data, 4)); - m_read_address_increment_disabled = bool(BIT(data, 5)); - - m_memory_bank_select = bitswap<2>(data, 6, 7); - - if (m_video_fill_enabled) - { - std::fill_n(&m_p_graphic_ram[(m_memory_bank_select << 16) & 0x3ffff], 0x10000, m_data_reg); - } -} - -u8 heath_igc_tlb_device::sigma_ctrl_r() -{ - u8 ret_val = 0x00; - - ret_val |= m_pixel_video_enabled ? 0x01 : 0x00; - ret_val |= m_character_video_disabled ? 0x02 : 0x00; - ret_val |= m_video_invert_enabled ? 0x04 : 0x00; - ret_val |= m_alternate_character_set_enabled ? 0x08 : 0x00; - ret_val |= m_video_fill_enabled ? 0x10 : 0x00; - ret_val |= m_read_address_increment_disabled ? 0x20 : 0x00; - - ret_val |= bitswap<2>(m_memory_bank_select, 0, 1) << 6; - - LOGREG("%s: ret_val: %02x\n", FUNCNAME, ret_val); - - return ret_val; -} - -void heath_igc_tlb_device::sigma_video_mem_w(u8 data) -{ - LOGREG("%s: data: %02x\n", FUNCNAME, data); - - m_data_reg = data; - - m_p_graphic_ram[(m_memory_bank_select << 16) + m_io_address++] = data; -} - -u8 heath_igc_tlb_device::sigma_video_mem_r() -{ - // control whether m_io_address is incremented during a read - u32 addr = (m_read_address_increment_disabled || machine().side_effects_disabled()) ? - ((m_memory_bank_select << 16) + m_io_address) : - ((m_memory_bank_select << 16) + m_io_address++); - - return m_p_graphic_ram[addr]; -} - -void heath_igc_tlb_device::sigma_io_lo_addr_w(u8 data) -{ - LOGREG("%s: data: %02x\n", FUNCNAME, data); - - m_io_address = (m_io_address & 0xff00) | data; -} - -void heath_igc_tlb_device::sigma_io_hi_addr_w(u8 data) -{ - LOGREG("%s: data: %02x\n", FUNCNAME, data); - - m_io_address = (data << 8) | (m_io_address & 0x00ff); -} - -void heath_igc_tlb_device::sigma_window_lo_addr_w(u8 data) -{ - LOGREG("%s: data: %02x\n", FUNCNAME, data); - - m_window_address = (m_window_address & 0xff00) | data; -} - -void heath_igc_tlb_device::sigma_window_hi_addr_w(u8 data) -{ - LOGREG("%s: data: %02x\n", FUNCNAME, data); - - m_window_address = (data << 8) | (m_window_address & 0x00ff); -} - -MC6845_UPDATE_ROW(heath_igc_tlb_device::crtc_update_row) -{ - rgb_t const *const palette = m_palette->palette()->entry_list_raw(); - u32 *p = &bitmap.pix(y); - - if (de) - { - u8 video_invert = m_video_invert_enabled ? 0xff : 0; - - for (int x = 0; x < x_count; x++) - { - u8 output = 0x00; - - if (!m_character_video_disabled) - { - u8 inv = (x == cursor_x) ? 0xff : 0; - u8 chr = m_p_videoram[(ma + x) & 0x7ff]; - - if (chr & 0x80) - { - inv ^= 0xff; - chr &= 0x7f; - } - - // TODO handle alt font - output |= m_p_chargen[(chr << 4) | ra] ^ inv; - } - - if (m_pixel_video_enabled) - { - output |= m_p_graphic_ram[(((y * 80) + x) + m_window_address) & 0xffff]; - } - - output ^= video_invert; - - for (int b = 0; 8 > b; ++b) - { - *p++ = palette[BIT(output, b)]; - } - } - } - else - { - std::fill_n(p, x_count * 8, palette[0]); - } -} - - -/** - * SigmaSoft and Systems IGC plus TLB with Super-19 ROM - * - */ -heath_igc_super19_tlb_device::heath_igc_super19_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : - heath_igc_tlb_device(mconfig, HEATH_IGC_SUPER19, tag, owner, clock) -{ -} - -const tiny_rom_entry *heath_igc_super19_tlb_device::device_rom_region() const -{ - return ROM_NAME(super19); -} - -ioport_constructor heath_igc_super19_tlb_device::device_input_ports() const -{ - return INPUT_PORTS_NAME(super19); -} - - -/** - * SigmaSoft and Systems IGC plus TLB with UltraROM - * - */ -heath_igc_ultra_tlb_device::heath_igc_ultra_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : - heath_igc_tlb_device(mconfig, HEATH_IGC_ULTRA, tag, owner, clock) -{ -} - -void heath_igc_ultra_tlb_device::device_add_mconfig(machine_config &config) -{ - heath_tlb_device::device_add_mconfig(config); - - m_maincpu->set_addrmap(AS_PROGRAM, &heath_igc_ultra_tlb_device::mem_map); -} - -void heath_igc_ultra_tlb_device::mem_map(address_map &map) -{ - heath_tlb_device::mem_map(map); - - // update rom mirror setting to allow page 2 memory - map(0x0000, 0x0fff).mirror(0x2000).rom(); - - // Page 2 memory - map(0x1000, 0x1fff).mirror(0x2000).ram(); -} - -const tiny_rom_entry *heath_igc_ultra_tlb_device::device_rom_region() const -{ - return ROM_NAME(ultra19); -} - -ioport_constructor heath_igc_ultra_tlb_device::device_input_ports() const -{ - return INPUT_PORTS_NAME(ultra19); -} - - -/** - * SigmaSoft and Systems IGC plus TLB with Watzman ROM - * - */ -heath_igc_watz_tlb_device::heath_igc_watz_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : - heath_igc_tlb_device(mconfig, HEATH_IGC_WATZ, tag, owner, clock) -{ -} - -const tiny_rom_entry *heath_igc_watz_tlb_device::device_rom_region() const -{ - return ROM_NAME(watz19); -} - -ioport_constructor heath_igc_watz_tlb_device::device_input_ports() const -{ - return INPUT_PORTS_NAME(watz19); -} - - -/** - * Terminal Logic Board Connector - * - */ -heath_tlb_connector::heath_tlb_connector(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : - device_t(mconfig, HEATH_TLB_CONNECTOR, tag, owner, clock), - device_single_card_slot_interface(mconfig, *this), - m_write_sd(*this), - m_dtr_cb(*this), - m_rts_cb(*this), - m_reset(*this), - m_tlb(nullptr) -{ -} - -heath_tlb_connector::~heath_tlb_connector() -{ -} - -void heath_tlb_connector::device_start() -{ - m_tlb = get_card_device(); -} diff --git a/src/mame/heathkit/tlb.h b/src/mame/heathkit/tlb.h deleted file mode 100644 index 4763f5ffe98..00000000000 --- a/src/mame/heathkit/tlb.h +++ /dev/null @@ -1,477 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Mark Garlanger -/*************************************************************************** - - Heathkit Terminal Logic Board (TLB) - -****************************************************************************/ - -#ifndef MAME_HEATHKIT_TLB_H -#define MAME_HEATHKIT_TLB_H - -#pragma once - -#include "cpu/z80/z80.h" -#include "machine/clock.h" -#include "machine/ins8250.h" -#include "machine/mm5740.h" -#include "sound/beep.h" -#include "video/mc6845.h" - -#include "emupal.h" -#include "screen.h" -#include "speaker.h" - - -class heath_tlb_connector; - -class device_heath_tlb_card_interface : public device_interface -{ -public: - - // required operation - virtual void serial_in_w(int state) = 0; - - // optional operations - virtual void rlsd_in_w(int state) {} - virtual void dsr_in_w(int state) {} - virtual void cts_in_w(int state) {} - - // optional SigmaSet operations - virtual void sigma_ctrl_w(u8 data) {} - virtual u8 sigma_ctrl_r() { return 0x00; } - virtual u8 sigma_video_mem_r() { return 0x00; } - virtual void sigma_video_mem_w(u8 val) {} - virtual void sigma_io_lo_addr_w(u8 val) {} - virtual void sigma_io_hi_addr_w(u8 val) {} - virtual void sigma_window_lo_addr_w(u8 val) {} - virtual void sigma_window_hi_addr_w(u8 val) {} - -protected: - device_heath_tlb_card_interface(const machine_config &mconfig, device_t &device); - - heath_tlb_connector *const m_slot; -}; - - -/** - * Standard Heath Terminal logic board - */ -class heath_tlb_device : public device_t, - public device_heath_tlb_card_interface -{ -public: - heath_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); - - // 8250 UART - virtual void serial_in_w(int state) override; - virtual void rlsd_in_w(int state) override; - virtual void dsr_in_w(int state) override; - virtual void cts_in_w(int state) override; - void serial_irq_w(int state); - - // Keyboard - void reset_key_w(int state); - void right_shift_w(int state); - void repeat_key_w(int state); - void break_key_w(int state); - -protected: - heath_tlb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock = 0); - - virtual ioport_constructor device_input_ports() const override; - virtual const tiny_rom_entry *device_rom_region() const override; - virtual void device_start() override; - virtual void device_reset() override; - virtual void device_add_mconfig(machine_config &config) override; - - void mem_map(address_map &map); - void io_map(address_map &map); - - - // interrupt related - virtual void set_irq_line(); - - // reset - void check_for_reset(); - - // sound/speaker - void check_beep_state(); - void key_click_w(u8 data); - void bell_w(u8 data); - TIMER_CALLBACK_MEMBER(key_click_off); - TIMER_CALLBACK_MEMBER(bell_off); - - // keyboard - u8 kbd_key_r(); - u8 kbd_flags_r(); - u16 translate_mm5740_b(u16 b); - int mm5740_shift_r(); - int mm5740_control_r(); - void mm5740_data_ready_w(int state); - - // serial port - void serial_out_b(int data); - void dtr_out(int data); - void rts_out(int data); - - // crtc - void crtc_addr_w(offs_t reg, u8 val); - virtual u8 crtc_reg_r(offs_t reg); - virtual void crtc_reg_w(offs_t reg, u8 val); - void crtc_vsync_w(int val); - virtual MC6845_UPDATE_ROW(crtc_update_row); - - required_device m_maincpu; - required_device m_screen; - required_device m_palette; - required_device m_crtc; - required_shared_ptr m_p_videoram; - required_region_ptr m_p_chargen; - required_ioport m_config; - required_device m_ace; - required_device m_beep; - required_device m_mm5740; - required_memory_region m_kbdrom; - required_ioport m_kbspecial; - required_device m_repeat_clock; - - emu_timer *m_key_click_timer; - emu_timer *m_bell_timer; - - u8 m_transchar; - bool m_strobe; - bool m_key_click_active; - bool m_bell_active; - bool m_reset_pending; - bool m_right_shift; - bool m_reset_key; - bool m_keyboard_irq_raised; - bool m_serial_irq_raised; - bool m_break_key_irq_raised; - bool m_allow_vsync_nmi; -}; - -/** - * Heath TLB with Super19 ROM - */ -class heath_super19_tlb_device : public heath_tlb_device -{ -public: - heath_super19_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); - -protected: - virtual const tiny_rom_entry *device_rom_region() const override; - virtual ioport_constructor device_input_ports() const override; -}; - -/** - * Heath TLB with Superset ROM - */ -class heath_superset_tlb_device : public heath_tlb_device -{ -public: - heath_superset_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); - -protected: - virtual const tiny_rom_entry *device_rom_region() const override; - virtual ioport_constructor device_input_ports() const override; - - virtual void device_start() override; - virtual void device_add_mconfig(machine_config &config) override; - - void mem_map(address_map &map); - void io_map(address_map &map); - - virtual MC6845_UPDATE_ROW(crtc_update_row) override; - - void dtr_internal(int data); - void out1_internal(int data); - void out2_internal(int data); - - virtual u8 crtc_reg_r(offs_t reg) override; - virtual void crtc_reg_w(offs_t reg, u8 val) override; - - u8 m_selected_char_set; - bool m_reverse_video_disabled; -}; - -/** - * Heath TLB with Watzman (HUG) ROM - */ -class heath_watz_tlb_device : public heath_tlb_device -{ -public: - heath_watz_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); - -protected: - virtual const tiny_rom_entry *device_rom_region() const override; - virtual ioport_constructor device_input_ports() const override; -}; - -/** - * Heath TLB with Ultra ROM - */ -class heath_ultra_tlb_device : public heath_tlb_device -{ -public: - heath_ultra_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); - -protected: - virtual const tiny_rom_entry *device_rom_region() const override; - virtual ioport_constructor device_input_ports() const override; - virtual void device_add_mconfig(machine_config &config) override; - - void mem_map(address_map &map); -}; - -/** - * Heath TLB plus Northwest Digital Systems GP-19 - */ -class heath_gp19_tlb_device : public heath_tlb_device -{ -public: - heath_gp19_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); - - static constexpr feature_type imperfect_features() { return feature::GRAPHICS; } - -protected: - virtual const tiny_rom_entry *device_rom_region() const override; - virtual ioport_constructor device_input_ports() const override; - - virtual void device_start() override; - virtual void device_add_mconfig(machine_config &config) override; - - void mem_map(address_map &map); - void io_map(address_map &map); - - void latch_u5_w(u8 data); - - virtual MC6845_UPDATE_ROW(crtc_update_row) override; - - bool m_char_gen_a11; - bool m_graphic_mode; - bool m_col_132; - bool m_reverse_video; -}; - -/** - * Heath TLB plus Cleveland Codonics Imaginator-100 - */ -class heath_imaginator_tlb_device : public heath_tlb_device -{ -public: - heath_imaginator_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); - -protected: - virtual const tiny_rom_entry *device_rom_region() const override; - - virtual void device_start() override; - virtual void device_reset() override; - virtual void device_add_mconfig(machine_config &config) override; - - void mem_map(address_map &map); - void io_map(address_map &map); - - virtual MC6845_UPDATE_ROW(crtc_update_row) override; - void crtc_hsync_w(int val); - - IRQ_CALLBACK_MEMBER(irq_ack_cb); - - void tap_6000h(); - void tap_8000h(); - - void allow_tlb_intr(); - void allow_hsync_intr(); - - void display_enable_w(offs_t reg, u8 val); - void config_irq_w(offs_t reg, u8 val); - void nop_w(offs_t reg, u8 val); - virtual void set_irq_line() override; - - required_memory_bank m_mem_bank; - required_shared_ptr m_p_graphic_ram; - memory_passthrough_handler m_tap_6000h; - - u8 m_im2_val; - - bool m_alphanumeric_mode_active; - bool m_graphics_mode_active; - - bool m_allow_tlb_interrupts; - bool m_allow_imaginator_interrupts; - - bool m_hsync_irq_raised; -}; - -/** - * Heath TLB plus SigmaSoft Interactive Graphics Controller - */ -class heath_igc_tlb_device : public heath_tlb_device -{ -public: - heath_igc_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); - - virtual void sigma_ctrl_w(u8 data) override; - virtual u8 sigma_ctrl_r() override; - - virtual u8 sigma_video_mem_r() override; - virtual void sigma_video_mem_w(u8 val) override; - - virtual void sigma_io_lo_addr_w(u8 val) override; - virtual void sigma_io_hi_addr_w(u8 val) override; - - virtual void sigma_window_lo_addr_w(u8 val) override; - virtual void sigma_window_hi_addr_w(u8 val) override; - -protected: - heath_igc_tlb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock = 0); - - virtual void device_start() override; - virtual void device_reset() override; - virtual void device_add_mconfig(machine_config &config) override; - - virtual MC6845_UPDATE_ROW(crtc_update_row) override; - - std::unique_ptr m_p_graphic_ram; - - // Control Register - bool m_pixel_video_enabled; - bool m_character_video_disabled; - bool m_video_invert_enabled; - bool m_alternate_character_set_enabled; - bool m_video_fill_enabled; - bool m_read_address_increment_disabled; - u8 m_memory_bank_select; - - u8 m_data_reg; - - u16 m_io_address; - u16 m_window_address; -}; - -/** - * Heath TLB with the super19 ROM plus SigmaSoft Interactive Graphics Controller - */ -class heath_igc_super19_tlb_device : public heath_igc_tlb_device -{ -public: - heath_igc_super19_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); - -protected: - virtual const tiny_rom_entry *device_rom_region() const override; - virtual ioport_constructor device_input_ports() const override; -}; - -/** - * Heath TLB with the ultrarom plus SigmaSoft Interactive Graphics Controller - */ -class heath_igc_ultra_tlb_device : public heath_igc_tlb_device -{ -public: - heath_igc_ultra_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); - -protected: - virtual const tiny_rom_entry *device_rom_region() const override; - virtual ioport_constructor device_input_ports() const override; - virtual void device_add_mconfig(machine_config &config) override; - - void mem_map(address_map &map); -}; - -/** - * Heath TLB with the watzman ROM plus SigmaSoft Interactive Graphics Controller - */ -class heath_igc_watz_tlb_device : public heath_igc_tlb_device -{ -public: - heath_igc_watz_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); - -protected: - virtual const tiny_rom_entry *device_rom_region() const override; - virtual ioport_constructor device_input_ports() const override; -}; - -// Options for the standard H89 class of systems -DECLARE_DEVICE_TYPE(HEATH_TLB, heath_tlb_device) -DECLARE_DEVICE_TYPE(HEATH_GP19, heath_gp19_tlb_device) -DECLARE_DEVICE_TYPE(HEATH_IMAGINATOR, heath_imaginator_tlb_device) -DECLARE_DEVICE_TYPE(HEATH_SUPER19, heath_super19_tlb_device) -DECLARE_DEVICE_TYPE(HEATH_SUPERSET, heath_superset_tlb_device) -DECLARE_DEVICE_TYPE(HEATH_WATZ, heath_watz_tlb_device) -DECLARE_DEVICE_TYPE(HEATH_ULTRA, heath_ultra_tlb_device) - -// Options for the H89 with the SigmaSoft IGC graphics installed -DECLARE_DEVICE_TYPE(HEATH_IGC, heath_igc_tlb_device) -DECLARE_DEVICE_TYPE(HEATH_IGC_SUPER19, heath_igc_super19_tlb_device) -DECLARE_DEVICE_TYPE(HEATH_IGC_ULTRA, heath_igc_ultra_tlb_device) -DECLARE_DEVICE_TYPE(HEATH_IGC_WATZ, heath_igc_watz_tlb_device) - -/** - * Connector for the Terminal Logic Board in an H-89 class computer - */ -class heath_tlb_connector : public device_t, - public device_single_card_slot_interface -{ -public: - - template - heath_tlb_connector(const machine_config &mconfig, const char *tag, device_t *owner, T &&opts, const char *dflt, bool fixed = false) : - heath_tlb_connector(mconfig, tag, owner, 0) - { - option_reset(); - opts(*this); - set_default_option(dflt); - set_fixed(fixed); - } - - heath_tlb_connector(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); - virtual ~heath_tlb_connector(); - - // computer interface - auto serial_data_callback() { return m_write_sd.bind(); } - auto dtr_callback() { return m_dtr_cb.bind(); } - auto rts_callback() { return m_rts_cb.bind(); } - auto reset_cb() { return m_reset.bind(); } - - // card interface - void serial_in_w(int state) { if (m_tlb) m_tlb->serial_in_w(state); } - void rlsd_in_w(int state) { if (m_tlb) m_tlb->rlsd_in_w(state); } - void dsr_in_w(int state) { if (m_tlb) m_tlb->dsr_in_w(state); } - void cts_in_w(int state) { if (m_tlb) m_tlb->cts_in_w(state); } - - // signals out from the tlb - void serial_out_b(int data) { m_write_sd(data); } - void dtr_out(int data) { m_dtr_cb(data); } - void rts_out(int data) { m_rts_cb(data); } - void reset_out(int data) { m_reset(data); } - - // optional SigmaSet IGC operations - u8 sigma_ctrl_r() { return (m_tlb) ? m_tlb->sigma_ctrl_r() : 0x00; } - void sigma_ctrl_w(u8 data) { if (m_tlb) m_tlb->sigma_ctrl_w(data); } - - u8 sigma_video_mem_r() { return (m_tlb) ? m_tlb->sigma_video_mem_r() : 0x00; } - void sigma_video_mem_w(u8 val) { if (m_tlb) m_tlb->sigma_video_mem_w(val); } - - void sigma_io_lo_addr_w(u8 val) { if (m_tlb) m_tlb->sigma_io_lo_addr_w(val); } - void sigma_io_hi_addr_w(u8 val) { if (m_tlb) m_tlb->sigma_io_hi_addr_w(val); } - - void sigma_window_lo_addr_w(u8 val) { if (m_tlb) m_tlb->sigma_window_lo_addr_w(val); } - void sigma_window_hi_addr_w(u8 val) { if (m_tlb) m_tlb->sigma_window_hi_addr_w(val); } - -protected: - virtual void device_start() override; - - devcb_write_line m_write_sd; - devcb_write_line m_dtr_cb; - devcb_write_line m_rts_cb; - devcb_write_line m_reset; - - device_heath_tlb_card_interface *m_tlb; -}; - - -// device type definition -DECLARE_DEVICE_TYPE(HEATH_TLB_CONNECTOR, heath_tlb_connector) - -#endif // MAME_HEATHKIT_TLB_H diff --git a/src/mame/heathkit/z37_fdc.cpp b/src/mame/heathkit/z37_fdc.cpp deleted file mode 100644 index 669bd5b8722..00000000000 --- a/src/mame/heathkit/z37_fdc.cpp +++ /dev/null @@ -1,235 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Mark Garlanger -/*************************************************************************** - - Heathkit Z-37 Floppy controller - - This was an option for both the Heathkit H8 and H89 computer systems. - -****************************************************************************/ - -#include "emu.h" - -#include "z37_fdc.h" - -#define LOG_REG (1U << 1) // Shows register setup -#define LOG_LINES (1U << 2) // Show control lines -#define LOG_DRIVE (1U << 3) // Show drive select -#define LOG_FUNC (1U << 4) // Function calls - -#define VERBOSE (0) - -#include "logmacro.h" - -#define LOGREG(...) LOGMASKED(LOG_REG, __VA_ARGS__) -#define LOGLINES(...) LOGMASKED(LOG_LINES, __VA_ARGS__) -#define LOGDRIVE(...) LOGMASKED(LOG_DRIVE, __VA_ARGS__) -#define LOGFUNC(...) LOGMASKED(LOG_FUNC, __VA_ARGS__) - -#ifdef _MSC_VER -#define FUNCNAME __func__ -#else -#define FUNCNAME __PRETTY_FUNCTION__ -#endif - -DEFINE_DEVICE_TYPE(HEATH_Z37_FDC, heath_z37_fdc_device, "heath_z37_fdc", "Heath H/Z-37 Soft-sectored Controller"); - -heath_z37_fdc_device::heath_z37_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock): - device_t(mconfig, HEATH_Z37_FDC, tag, owner, 0), - m_irq_cb(*this), - m_drq_cb(*this), - m_block_interrupt_cb(*this), - m_fdc(*this, "z37_fdc"), - m_floppies(*this, "z37_fdc:%u", 0U) -{ -} - - -void heath_z37_fdc_device::ctrl_w(u8 val) -{ - bool motor_on = bool(BIT(val, ctrl_MotorsOn_c)); - - m_irq_allowed = bool(BIT(val, ctrl_EnableIntReq_c)); - m_drq_allowed = bool(BIT(val, ctrl_EnableDrqInt_c)); - m_fdc->dden_w(BIT(~val, ctrl_SetMFMRecording_c)); - - LOGREG("%s: motor on: %d, intrq allowed: %d, drq allowed: %d\n", - FUNCNAME, motor_on, m_irq_allowed, m_drq_allowed); - - if (m_drq_allowed) - { - m_block_interrupt_cb(1); - } - else - { - m_block_interrupt_cb(0); - m_drq_cb(0); - } - - if (BIT(val, ctrl_Drive_0_c)) - { - m_fdc->set_floppy(m_floppies[0]->get_device()); - LOGDRIVE("Drive selected: 0\n"); - } - else if (BIT(val, ctrl_Drive_1_c)) - { - m_fdc->set_floppy(m_floppies[1]->get_device()); - LOGDRIVE("Drive selected: 1\n"); - } - else if (BIT(val, ctrl_Drive_2_c)) - { - m_fdc->set_floppy(m_floppies[2]->get_device()); - LOGDRIVE("Drive selected: 2\n"); - } - else if (BIT(val, ctrl_Drive_3_c)) - { - m_fdc->set_floppy(m_floppies[3]->get_device()); - LOGDRIVE("Drive selected: 3\n"); - } - else - { - m_fdc->set_floppy(nullptr); - LOGDRIVE("Drive selected: none\n"); - } - - for (auto &elem : m_floppies) - { - floppy_image_device *floppy = elem->get_device(); - if (floppy) - { - floppy->mon_w(!motor_on); - } - } -} - -void heath_z37_fdc_device::intf_w(u8 val) -{ - m_access_track_sector = bool(BIT(val, if_SelectSectorTrack_c)); - - LOGREG("access track/sector: %d\n", m_access_track_sector); -} - -void heath_z37_fdc_device::cmd_w(u8 val) -{ - m_access_track_sector ? m_fdc->sector_w(val) : m_fdc->cmd_w(val); -} - -u8 heath_z37_fdc_device::stat_r() -{ - return m_access_track_sector ? m_fdc->sector_r() : m_fdc->status_r(); -} - -void heath_z37_fdc_device::data_w(u8 val) -{ - m_access_track_sector ? m_fdc->track_w(val) : m_fdc->data_w(val); -} - -u8 heath_z37_fdc_device::data_r() -{ - return m_access_track_sector ? m_fdc->track_r() : m_fdc->data_r(); -} - -void heath_z37_fdc_device::write(offs_t reg, u8 val) -{ - LOGFUNC("%s: reg: %d val: %d\n", FUNCNAME, reg, val); - - switch (reg) - { - case 0: - ctrl_w(val); - break; - case 1: - intf_w(val); - break; - case 2: - cmd_w(val); - break; - case 3: - data_w(val); - break; - } -} - -u8 heath_z37_fdc_device::read(offs_t reg) -{ - // default return for the h89 - u8 value = 0xff; - - switch (reg) - { - case 0: - case 1: - // read not supported on these addresses - break; - case 2: - value = stat_r(); - break; - case 3: - value = data_r(); - break; - } - - LOGFUNC("%s: reg: %d val: %d\n", FUNCNAME, reg, value); - - return value; -} - -void heath_z37_fdc_device::device_start() -{ - save_item(NAME(m_irq_allowed)); - save_item(NAME(m_drq_allowed)); - save_item(NAME(m_access_track_sector)); -} - -void heath_z37_fdc_device::device_reset() -{ - m_irq_allowed = false; - m_drq_allowed = false; - m_access_track_sector = false; - - m_irq_cb(0); - m_drq_cb(0); - m_block_interrupt_cb(0); -} - -static void z37_floppies(device_slot_interface &device) -{ - // H-17-1 -- SS 48tpi - device.option_add("ssdd", FLOPPY_525_SSDD); - // SS 96tpi - device.option_add("ssqd", FLOPPY_525_SSQD); - // DS 48tpi - device.option_add("dd", FLOPPY_525_DD); - // H-17-4 / H-17-5 -- DS 96tpi - device.option_add("qd", FLOPPY_525_QD); -} - -void heath_z37_fdc_device::device_add_mconfig(machine_config &config) -{ - FD1797(config, m_fdc, 16_MHz_XTAL / 16); - m_fdc->intrq_wr_callback().set(FUNC(heath_z37_fdc_device::set_irq)); - m_fdc->drq_wr_callback().set(FUNC(heath_z37_fdc_device::set_drq)); - - FLOPPY_CONNECTOR(config, m_floppies[0], z37_floppies, "qd", floppy_image_device::default_mfm_floppy_formats); - m_floppies[0]->enable_sound(true); - FLOPPY_CONNECTOR(config, m_floppies[1], z37_floppies, "qd", floppy_image_device::default_mfm_floppy_formats); - m_floppies[1]->enable_sound(true); - FLOPPY_CONNECTOR(config, m_floppies[2], z37_floppies, "qd", floppy_image_device::default_mfm_floppy_formats); - m_floppies[2]->enable_sound(true); - FLOPPY_CONNECTOR(config, m_floppies[3], z37_floppies, nullptr, floppy_image_device::default_mfm_floppy_formats); - m_floppies[3]->enable_sound(true); -} - -void heath_z37_fdc_device::set_irq(int state) -{ - LOGLINES("set irq, allowed: %d state: %d\n", m_irq_allowed, state); - - m_irq_cb(m_irq_allowed ? state : CLEAR_LINE); -} - -void heath_z37_fdc_device::set_drq(int state) -{ - LOGLINES("set drq, allowed: %d state: %d\n", m_irq_allowed, state); - - m_drq_cb(m_drq_allowed ? state : CLEAR_LINE); -} diff --git a/src/mame/heathkit/z37_fdc.h b/src/mame/heathkit/z37_fdc.h deleted file mode 100644 index 1d758882470..00000000000 --- a/src/mame/heathkit/z37_fdc.h +++ /dev/null @@ -1,78 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Mark Garlanger -/*************************************************************************** - - Heathkit Z-37 Floppy Disk Controller - -****************************************************************************/ - -#ifndef MAME_HEATHKIT_Z37_FDC_H -#define MAME_HEATHKIT_Z37_FDC_H - -#pragma once - -#include "imagedev/floppy.h" -#include "machine/wd_fdc.h" - - -class heath_z37_fdc_device : public device_t -{ -public: - heath_z37_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); - - void write(offs_t reg, u8 val); - u8 read(offs_t reg); - auto irq_cb() { return m_irq_cb.bind(); } - auto drq_cb() { return m_drq_cb.bind(); } - - auto block_interrupt_cb() { return m_block_interrupt_cb.bind(); } - -protected: - - virtual void device_start() override; - virtual void device_reset() override; - virtual void device_add_mconfig(machine_config &config) override; - - void ctrl_w(u8 val); - - void intf_w(u8 val); - - void cmd_w(u8 val); - u8 stat_r(); - - void data_w(u8 val); - u8 data_r(); - - void set_irq(int state); - void set_drq(int state); - -private: - devcb_write_line m_irq_cb; - devcb_write_line m_drq_cb; - devcb_write_line m_block_interrupt_cb; - - required_device m_fdc; - required_device_array m_floppies; - - bool m_irq_allowed; - bool m_drq_allowed; - bool m_access_track_sector; - - /// Bits set in cmd_ControlPort_c - DK.CON - static constexpr u8 ctrl_EnableIntReq_c = 0; - static constexpr u8 ctrl_EnableDrqInt_c = 1; - static constexpr u8 ctrl_SetMFMRecording_c = 2; - static constexpr u8 ctrl_MotorsOn_c = 3; - static constexpr u8 ctrl_Drive_0_c = 4; - static constexpr u8 ctrl_Drive_1_c = 5; - static constexpr u8 ctrl_Drive_2_c = 6; - static constexpr u8 ctrl_Drive_3_c = 7; - - /// Bits to set alternate registers on InterfaceControl_c - DK.INT - static constexpr u8 if_SelectSectorTrack_c = 0; -}; - -DECLARE_DEVICE_TYPE(HEATH_Z37_FDC, heath_z37_fdc_device) - - -#endif // MAME_HEATHKIT_Z37_FDC_H diff --git a/src/mame/heathzenith/README.md b/src/mame/heathzenith/README.md new file mode 100644 index 00000000000..c61679c5639 --- /dev/null +++ b/src/mame/heathzenith/README.md @@ -0,0 +1,53 @@ +# Heath Company / Zenith Data Systems + +## History +When Heath Company first developed their computers, Heath Company was owned by Schlumberger. In October 1979, Heath was sold to Zenith, which then created the [Zenith Data Systems](https://en.wikipedia.org/wiki/Zenith_Data_Systems) division for all the computer related products. The division was headquartered in the +Heath plant. + +## Models +Prior to the Zenith purchase, Heath offered both kits and assembled products. For kits, model number starts an "H" and the assembled products started with "WH". The "W" was referred to as "Wired". After the acquisition, kit naming remained the same. The assembled products were rebranded as Zenith or ZDS (Zenith Data Systems) and model number starts with "Z". For example, prior to the acquisition, the models were H89 and WH89. After the acquisition, the models were H-89 and Z-89. + +The systems were basically identical other than being either a kit or assembled. The combined company continued to make many of their new products available as both a kit and assembled. + +### H8 +An 8080 based system released in 1977 by Heath Company. + +### H11 / H11A / WH11 +A PDP-11 compatible system released by Heath Company in 1977. This system is not currently emulated in MAME. + +### H/Z-89 Series (H88, H88A, H-89, H-89A, WH89, Z-89, Z-90) +A Z80-based computer introduced in 1979 by Heath Company. Shares same cabinet as the H-19 terminal. + +#### Heath H89 add-on cards +##### H-88-3 Serial port +3 port serial card. Based on the 8250 UART. + +##### H-88-1 (not currently implemented) +5.25" Hard-sectored disk controller. Connects with internal drives and external H-17, H-77, and Z-87 drives. + +##### Z-89-37 +5.25" Soft-sectored disk controller. Connects with internal drives and external H-17, H/Z-37 H-77, and Z-87 drives. + +##### Z-89-47 (not currently implemented) +8" Interface card for the H/Z-47 and REMEX Floppy drives. + +##### Z-89-67 (not currently implemented) +Interface card for the Z-67 - SASI 10M Winchester Drive & 8" Floppy. + +#### H88 / H88A +The H88 came standard with a cassette interface board, and supported adding a H-88-1 hard-sectored controller. It came with the MTR-88 ROM. ROM/System could be upgraded to support MTR-89 or MTR-90 and their supported cards. + +#### H89 / H89A / WH89 / Z-89 +These systems came with the MTR-89 ROM. It came with the H-88-1 hard-sectored controller. It also supported the Z-89-47 interface card. ROM/System could be upgraded to support MTR-90 and their supported cards. + +#### Z-90 +The Z-90 came standard with the Z-89-37 soft-sectored controller. It has the MTR-90 ROM. Supported all of Heath's disk drive add-on cards: H-88-1, Z-89-37, Z-89-47, and Z-89-67, although at most only 2 could be installed at the same time. + +### H19 (Z-19) +A Z80-based terminal introduced in 1979 by Heath Company. + +### H22 +A 6512-based terminal. + +### H/Z-100 Series +A dual processor (8088 and 8085) computer. It could run 8-bit and 16-bit software. \ No newline at end of file diff --git a/src/mame/heathzenith/et3400.cpp b/src/mame/heathzenith/et3400.cpp new file mode 100644 index 00000000000..86eec309cb8 --- /dev/null +++ b/src/mame/heathzenith/et3400.cpp @@ -0,0 +1,268 @@ +// license:BSD-3-Clause +// copyright-holders:Robbbert +/*************************************************************************** + +ET-3400 + +2009-05-12 Skeleton driver. +2016-04-29 Added Accessory. + +ETA-3400 Memory I/O Accessory +- Provides Tiny Basic, a Terminal, a Serial Interface, a Cassette + interface, and 1k to 4k of expansion RAM. All parts are working. +- The roms are U105 (Monitor), U106 (Tiny Basic), both type NMOS2316E, + and U108 (address decoder PROM). +- Navigating: + LED to Monitor: D1400 + Monitor to Basic: G 1C00 + Monitor to LED: G FC00 + Basic to Monitor: BYE +- All commands in Basic and Monitor are UPPERCASE only. +- Terminal is defaulted to 9600 baud, 7 bits, 2 stop bits. + + +****************************************************************************/ + +#include "emu.h" +#include "cpu/m6800/m6800.h" +#include "machine/74259.h" +#include "machine/6821pia.h" +#include "bus/rs232/rs232.h" +#include "imagedev/cassette.h" +#include "speaker.h" + +#include "et3400.lh" + +namespace { + +class et3400_state : public driver_device +{ +public: + et3400_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag) + , m_maincpu(*this, "maincpu") + , m_pia(*this, "pia") + , m_displatch(*this, "displatch%u", 1) + , m_rs232(*this, "rs232") + , m_cass(*this, "cassette") + , m_x(*this, "X%u", 0U) + , m_digit(*this, "digit%u", 1U) + { } + + void et3400(machine_config &config); + + void reset_key_w(int state); + void segment_test_w(int state); + +private: + + virtual void machine_start() override; + + uint8_t keypad_r(offs_t offset); + void display_w(offs_t offset, uint8_t data); + template void led_w(uint8_t data); + uint8_t pia_ar(); + void pia_aw(uint8_t data); + uint8_t pia_br(); + void pia_bw(uint8_t data); + + void mem_map(address_map &map); + + required_device m_maincpu; + required_device m_pia; + required_device_array m_displatch; + required_device m_rs232; + required_device m_cass; + required_ioport_array<3> m_x; + output_finder<6> m_digit; +}; + + + +void et3400_state::machine_start() +{ + m_digit.resolve(); +} + + +uint8_t et3400_state::keypad_r(offs_t offset) +{ + uint8_t data = 0xff; + + if (~offset & 4) data &= m_x[2]->read(); + if (~offset & 2) data &= m_x[1]->read(); + if (~offset & 1) data &= m_x[0]->read(); + + return data; +} + +void et3400_state::display_w(offs_t offset, uint8_t data) +{ + // A6-A4 decoded by IC22 (74LS42); D0 inverted by one gate of IC21 (74S00) + uint8_t digit = (offset >> 4) & 7; + if (digit >= 1 && digit <= 6) + m_displatch[digit - 1]->write_bit(offset & 7, !BIT(data, 0)); +} + +template +void et3400_state::led_w(uint8_t data) +{ + // This computer sets each segment, one at a time. + m_digit[Digit - 1] = bitswap<8>(~data, 7, 0, 1, 2, 3, 4, 5, 6); +} + +// d1,2,3 = Baud rate +// d4 = gnd +// d7 = rs232 in +uint8_t et3400_state::pia_ar() +{ + return ioport("BAUD")->read() | (m_rs232->rxd_r() << 7); +} + +// d0 = rs232 out +void et3400_state::pia_aw(uint8_t data) +{ + m_rs232->write_txd(BIT(data, 0)); +} + +// d7 = cass in +uint8_t et3400_state::pia_br() +{ + return (m_cass->input() > +0.0) << 7; +} + +// d0 = cass out +void et3400_state::pia_bw(uint8_t data) +{ + m_cass->output(BIT(data, 0) ? -1.0 : +1.0); +} + + +void et3400_state::mem_map(address_map &map) +{ + map.unmap_value_high(); + map(0x0000, 0x0fff).ram(); + map(0x1000, 0x1003).mirror(0x03fc).rw(m_pia, FUNC(pia6821_device::read), FUNC(pia6821_device::write)); + map(0x1400, 0x23ff).rom().region("roms", 0); + map(0xc000, 0xc0ff).r(FUNC(et3400_state::keypad_r)); + map(0xc100, 0xc1ff).w(FUNC(et3400_state::display_w)); + map(0xfc00, 0xffff).rom().region("roms", 0x1000); +} + +void et3400_state::reset_key_w(int state) +{ + // delivered through MC6875 (or 74LS241 on ET-3400A) + m_maincpu->set_input_line(INPUT_LINE_RESET, state ? CLEAR_LINE : ASSERT_LINE); + + // PIA also uses reset line + if (!state) + m_pia->reset(); +} + +void et3400_state::segment_test_w(int state) +{ + for (int d = 0; d < 6; d++) + m_displatch[d]->clear_w(state); +} + +/* Input ports */ +static INPUT_PORTS_START( et3400 ) + PORT_START("X0") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("D DO") PORT_CODE(KEYCODE_D) PORT_CHAR('D') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("A AUTO") PORT_CODE(KEYCODE_A) PORT_CHAR('A') + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("7 RTI") PORT_CODE(KEYCODE_7) PORT_CHAR('7') + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("4 INDEX") PORT_CODE(KEYCODE_4) PORT_CHAR('4') + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("1 ACCA") PORT_CODE(KEYCODE_1) PORT_CHAR('1') + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("0") PORT_CODE(KEYCODE_0) PORT_CHAR('0') + PORT_BIT( 0xc0, 0xc0, IPT_UNUSED ) + + PORT_START("X1") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("E EXAM") PORT_CODE(KEYCODE_E) PORT_CHAR('E') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("B BACK") PORT_CODE(KEYCODE_B) PORT_CHAR('B') + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("8 SS") PORT_CODE(KEYCODE_8) PORT_CHAR('8') + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("5 CC") PORT_CODE(KEYCODE_5) PORT_CHAR('5') + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("2 ACCB") PORT_CODE(KEYCODE_2) PORT_CHAR('2') + PORT_BIT( 0xe0, 0xe0, IPT_UNUSED ) + + PORT_START("X2") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("F FWD") PORT_CODE(KEYCODE_F) PORT_CHAR('F') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("C CHAN") PORT_CODE(KEYCODE_C) PORT_CHAR('C') + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("9 BR") PORT_CODE(KEYCODE_9) PORT_CHAR('9') + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("6 SP") PORT_CODE(KEYCODE_6) PORT_CHAR('6') + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("3 PC") PORT_CODE(KEYCODE_3) PORT_CHAR('3') + PORT_BIT( 0xe0, 0xe0, IPT_UNUSED ) + + PORT_START("BAUD") + PORT_DIPNAME( 0x0E, 0x02, "Baud Rate" ) + PORT_DIPSETTING( 0x0E, "110" ) + PORT_DIPSETTING( 0x00, "300" ) + PORT_DIPSETTING( 0x0A, "600" ) + PORT_DIPSETTING( 0x08, "1200" ) + PORT_DIPSETTING( 0x06, "2400" ) + PORT_DIPSETTING( 0x04, "4800" ) + PORT_DIPSETTING( 0x02, "9600" ) + + PORT_START("RESET") // RESET is directly next to 0, but electrically separate from key matrix + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("RESET") PORT_CODE(KEYCODE_STOP) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, et3400_state, reset_key_w) + + PORT_START("TEST") // No input mechanism for "Segment Test" defined other than shorting pins together + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Segment Test") PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, et3400_state, segment_test_w) +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_NONE ) + DEVICE_INPUT_DEFAULTS( "RS232_STOPBITS", 0xff, RS232_STOPBITS_2 ) +DEVICE_INPUT_DEFAULTS_END + +void et3400_state::et3400(machine_config &config) +{ + /* basic machine hardware */ + M6800(config, m_maincpu, XTAL(4'000'000) / 4 ); // 1MHz with memory i/o accessory, or 500khz without it + m_maincpu->set_addrmap(AS_PROGRAM, &et3400_state::mem_map); + + /* video hardware */ + config.set_default_layout(layout_et3400); + + // Devices + PIA6821(config, m_pia); + m_pia->writepa_handler().set(FUNC(et3400_state::pia_aw)); + m_pia->writepb_handler().set(FUNC(et3400_state::pia_bw)); + m_pia->readpa_handler().set(FUNC(et3400_state::pia_ar)); + m_pia->readpb_handler().set(FUNC(et3400_state::pia_br)); + + RS232_PORT(config, m_rs232, default_rs232_devices, "terminal").set_option_device_input_defaults("terminal", DEVICE_INPUT_DEFAULTS_NAME(terminal)); + + for (std::size_t i = 0; i < 6; i++) + LS259(config, m_displatch[i]); + + m_displatch[0]->parallel_out_cb().set(FUNC(et3400_state::led_w<1>)); + m_displatch[1]->parallel_out_cb().set(FUNC(et3400_state::led_w<2>)); + m_displatch[2]->parallel_out_cb().set(FUNC(et3400_state::led_w<3>)); + m_displatch[3]->parallel_out_cb().set(FUNC(et3400_state::led_w<4>)); + m_displatch[4]->parallel_out_cb().set(FUNC(et3400_state::led_w<5>)); + m_displatch[5]->parallel_out_cb().set(FUNC(et3400_state::led_w<6>)); + + SPEAKER(config, "mono").front_center(); + + CASSETTE(config, m_cass); + m_cass->set_default_state(CASSETTE_STOPPED | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_ENABLED); + m_cass->add_route(ALL_OUTPUTS, "mono", 0.05); +} + +/* ROM definition */ +ROM_START( et3400 ) + ROM_REGION( 0x1420, "roms", 0 ) + ROM_LOAD( "monitor.u105", 0x0000, 0x0800, CRC(e4142682) SHA1(785966018dd6eb097ed9bd5c7def2354ab4347db) ) + ROM_LOAD( "basic.u106", 0x0800, 0x0800, CRC(bbd6a801) SHA1(088da24bd4d923d4f196b993154c538835d10605) ) + ROM_LOAD( "et3400.ic12", 0x1000, 0x0400, CRC(2eff1f58) SHA1(38b655de7393d7a92b08276f7c14a99eaa2a4a9f) ) + ROM_LOAD_OPTIONAL("prom.u108", 0x1400, 0x0020, CRC(273025c3) SHA1(136c1cdce2a4a796c1c46e8ea4f798cdee4b549b) ) // not used +ROM_END + +} // Anonymous namespace + +/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */ +COMP( 1976, et3400, 0, 0, et3400, et3400, et3400_state, empty_init, "Heath Company", "Heathkit Model ET-3400 Microprocessor Trainer", MACHINE_SUPPORTS_SAVE ) diff --git a/src/mame/heathzenith/h17_fdc.cpp b/src/mame/heathzenith/h17_fdc.cpp new file mode 100644 index 00000000000..7499368cd70 --- /dev/null +++ b/src/mame/heathzenith/h17_fdc.cpp @@ -0,0 +1,290 @@ +// license:BSD-3-Clause +// copyright-holders:Mark Garlanger +/*************************************************************************** + + Heathkit H-17 Floppy controller + + This was an option for both the Heathkit H8 and H89 computer systems. + + TODO + - define hard-sectored disk format + - incoming floppy data should drive receive clock of the ami 2350. + +****************************************************************************/ + +#include "emu.h" +#include "h17_fdc.h" + +#define LOG_REG (1U << 1) // Register setup +#define LOG_LINES (1U << 2) // Control lines +#define LOG_DRIVE (1U << 3) // Drive select +#define LOG_FUNC (1U << 4) // Function calls + +//#define VERBOSE (LOG_GENERAL | LOG_REG | LOG_LINES | LOG_DRIVE | LOG_FUNC) + +#include "logmacro.h" + +#define LOGREG(...) LOGMASKED(LOG_REG, __VA_ARGS__) +#define LOGLINES(...) LOGMASKED(LOG_LINES, __VA_ARGS__) +#define LOGDRIVE(...) LOGMASKED(LOG_DRIVE, __VA_ARGS__) +#define LOGFUNC(...) LOGMASKED(LOG_FUNC, __VA_ARGS__) + +#ifdef _MSC_VER +#define FUNCNAME __func__ +#else +#define FUNCNAME __PRETTY_FUNCTION__ +#endif + + +DEFINE_DEVICE_TYPE(HEATH_H17_FDC, heath_h17_fdc_device, "heath_h17_fdc", "Heath H-17 Hard-sectored Controller"); + + +heath_h17_fdc_device::heath_h17_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock): + device_t(mconfig, HEATH_H17_FDC, tag, owner, 0), + m_floppy_ram_wp(*this), + m_s2350(*this, "s2350"), + m_floppies(*this, "floppy%u", 0U), + m_tx_timer(*this, "tx_timer"), + m_floppy(nullptr) +{ +} + +void heath_h17_fdc_device::write(offs_t reg, u8 val) +{ + LOGFUNC("%s: reg: %d val: 0x%02x\n", FUNCNAME, reg, val); + + switch (reg) + { + case 0: // data port + m_s2350->transmitter_holding_reg_w(val); + break; + case 1: // fill character + m_s2350->transmit_fill_reg_w(val); + break; + case 2: // sync port + m_s2350->receiver_sync_reg_w(val); + break; + case 3: // control port + ctrl_w(val); + break; + } +} + +void heath_h17_fdc_device::set_floppy(floppy_image_device *floppy) +{ + if (m_floppy == floppy) + { + return; + } + + LOGDRIVE("%s: selecting new drive\n", FUNCNAME); + + m_floppy = floppy; + + // set any latched signals + { + m_floppy->ss_w(m_side); + } +} + +void heath_h17_fdc_device::side_select_w(int state) +{ + m_side = BIT(state, 0); + + if (m_floppy) + { + m_floppy->ss_w(m_side); + } +} + +void heath_h17_fdc_device::dir_w(int state) +{ + if (m_floppy) + { + LOGFUNC("%s: step dir: 0x%02x\n", FUNCNAME, state); + + m_floppy->dir_w(state); + } +} + +void heath_h17_fdc_device::step_w(int state) +{ + if (m_floppy) + { + LOGFUNC("%s: step dir: 0x%02x\n", FUNCNAME, state); + + m_floppy->stp_w(state); + } +} + +void heath_h17_fdc_device::set_motor(bool motor_on) +{ + if (m_motor_on == motor_on) + { + return; + } + + m_motor_on = motor_on; + + for (auto &elem : m_floppies) + { + floppy_image_device *floppy = elem->get_device(); + if (floppy) + { + LOGFUNC("%s: motor: %d\n", FUNCNAME, motor_on); + + floppy->mon_w(!motor_on); + } + } +} + +void heath_h17_fdc_device::ctrl_w(u8 val) +{ + m_write_gate = bool(BIT(val, CTRL_WRITE_GATE)); + + set_motor(bool(BIT(val, CTRL_MOTOR_ON))); + + if (BIT(val, CTRL_DRIVE_SELECT_0)) + { + LOGFUNC("%s: set drive 0\n", FUNCNAME); + + set_floppy(m_floppies[0]->get_device()); + } + else if (BIT(val, CTRL_DRIVE_SELECT_1)) + { + LOGFUNC("%s: set drive 1\n", FUNCNAME); + + set_floppy(m_floppies[1]->get_device()); + } + else if (BIT(val, CTRL_DRIVE_SELECT_2)) + { + LOGFUNC("%s: set drive 2\n", FUNCNAME); + + set_floppy(m_floppies[2]->get_device()); + } + else + { + LOGFUNC("%s: set drive none\n", FUNCNAME); + + set_floppy(nullptr); + } + + dir_w(!BIT(val, CTRL_DIRECTION)); + + step_w(!BIT(val, CTRL_STEP_COMMAND)); + + m_floppy_ram_wp(BIT(val, CTRL_WRITE_ENABLE_RAM)); +} + +u8 heath_h17_fdc_device::read(offs_t reg) +{ + // default return for the h89 + u8 val = 0xff; + + switch (reg) + { + case 0: // data port + val = m_s2350->receiver_output_reg_r(); + break; + case 1: // status port + val = m_s2350->status_word_r(); + break; + case 2: // sync port + val = m_s2350->receiver_sync_search(); + break; + case 3: // floppy status port + val = floppy_status_r(); + break; + } + + LOGREG("%s: reg: %d val: 0x%02x\n", FUNCNAME, reg, val); + + return val; +} + +u8 heath_h17_fdc_device::floppy_status_r() +{ + u8 val = 0; + + // statuses from the floppy drive + if (m_floppy) + { + // index/sector hole + val |= m_floppy->idx_r() ? 0x00 : 0x01; + + // track 0 + val |= m_floppy->trk00_r() ? 0x00 : 0x02; + + // disk is write-protected + val |= m_floppy->wpt_r() ? 0x00 : 0x04; + } + else + { + LOGREG("%s: no drive selected\n", FUNCNAME); + } + + // status from USRT + val |= m_sync_char_received ? 0x08 : 0x00; + + LOGFUNC("%s: val: 0x%02x\n", FUNCNAME, val); + + return val; +} + +void heath_h17_fdc_device::device_start() +{ + save_item(NAME(m_motor_on)); + save_item(NAME(m_write_gate)); + save_item(NAME(m_sync_char_received)); + save_item(NAME(m_step_direction)); + save_item(NAME(m_side)); +} + +void heath_h17_fdc_device::device_reset() +{ + LOGFUNC("%s\n", FUNCNAME); + + m_motor_on = false; + m_write_gate = false; + m_sync_char_received = false; + + m_tx_timer->adjust(attotime::from_hz(USRT_TX_CLOCK), 0, attotime::from_hz(USRT_TX_CLOCK)); +} + +static void h17_floppies(device_slot_interface &device) +{ + // H-17-1 + device.option_add("ssdd", FLOPPY_525_SSDD); + + // Future plans - test and verify higher capacity drives with LLC's BIOS-80 for CP/M and an HUG's enhanced HDOS driver + // - FLOPPY_525_SSQD + // - FLOPPY_525_DD + // - FLOPPY_525_QD (H-17-4) +} + +TIMER_DEVICE_CALLBACK_MEMBER(heath_h17_fdc_device::tx_timer_cb) +{ + m_s2350->tcp_w(); +} + +void heath_h17_fdc_device::device_add_mconfig(machine_config &config) +{ + S2350(config, m_s2350, 0); + m_s2350->sync_character_received_cb().set(FUNC(heath_h17_fdc_device::sync_character_received)); + + for (int i = 0; i < MAX_FLOPPY_DRIVES; i++) + { + // TODO -> add (and define) heath hard-sectored floppy formats. + FLOPPY_CONNECTOR(config, m_floppies[i], h17_floppies, "ssdd", floppy_image_device::default_fm_floppy_formats); + m_floppies[i]->enable_sound(true); + } + + TIMER(config, m_tx_timer).configure_generic(FUNC(heath_h17_fdc_device::tx_timer_cb)); +} + +void heath_h17_fdc_device::sync_character_received(int state) +{ + LOGFUNC("%s: state: %d\n", FUNCNAME, state); + + m_sync_char_received = bool(!BIT(state, 0)); +} diff --git a/src/mame/heathzenith/h17_fdc.h b/src/mame/heathzenith/h17_fdc.h new file mode 100644 index 00000000000..75dd4460e93 --- /dev/null +++ b/src/mame/heathzenith/h17_fdc.h @@ -0,0 +1,90 @@ +// license:BSD-3-Clause +// copyright-holders:Mark Garlanger +/*************************************************************************** + + Heathkit H-17 Floppy Disk Controller + + + Model number: H-88-1 + + TODO + - Mame core must support hard-sectored disk images. + - used floppy clock bits to clock USRT received clock. + - Add support for a heath hard-sectored disk support (h17disk). + +****************************************************************************/ + +#ifndef MAME_HEATHKIT_H17_FDC_H +#define MAME_HEATHKIT_H17_FDC_H + +#pragma once + +#include "imagedev/floppy.h" +#include "machine/s2350.h" + + +class heath_h17_fdc_device : public device_t +{ +public: + heath_h17_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + + auto floppy_ram_wp_cb() { return m_floppy_ram_wp.bind(); } + + void write(offs_t reg, u8 val); + u8 read(offs_t reg); + + void side_select_w(int state); + +protected: + static constexpr u8 MAX_FLOPPY_DRIVES = 3; + + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_add_mconfig(machine_config &config) override; + + void ctrl_w(u8 val); + u8 floppy_status_r(); + + void set_floppy(floppy_image_device *floppy); + void step_w(int state); + void dir_w(int state); + void set_motor(bool motor_on); + + void sync_character_received(int state); + + TIMER_DEVICE_CALLBACK_MEMBER(tx_timer_cb); + + devcb_write_line m_floppy_ram_wp; + + required_device m_s2350; + required_device_array m_floppies; + required_device m_tx_timer; + + bool m_motor_on; + bool m_write_gate; + bool m_sync_char_received; + u8 m_step_direction; + u8 m_side; + + floppy_image_device *m_floppy; + + /// write bit control port + static constexpr u8 CTRL_WRITE_GATE = 0; + static constexpr u8 CTRL_DRIVE_SELECT_0 = 1; + static constexpr u8 CTRL_DRIVE_SELECT_1 = 2; + static constexpr u8 CTRL_DRIVE_SELECT_2 = 3; + static constexpr u8 CTRL_MOTOR_ON = 4; // Controls all the drives + static constexpr u8 CTRL_DIRECTION = 5; // (0 = out) + static constexpr u8 CTRL_STEP_COMMAND = 6; // (Active high) + static constexpr u8 CTRL_WRITE_ENABLE_RAM = 7; // 0 - write protected + + // USRT clock + static constexpr XTAL USRT_BASE_CLOCK = XTAL(12'288'000) / 6 / 16; + static constexpr u32 USRT_TX_CLOCK = USRT_BASE_CLOCK.value(); +}; + + +DECLARE_DEVICE_TYPE(HEATH_H17_FDC, heath_h17_fdc_device) + + +#endif // MAME_HEATHKIT_H17_FDC_H diff --git a/src/mame/heathzenith/h19.cpp b/src/mame/heathzenith/h19.cpp new file mode 100644 index 00000000000..a3b0fe21fa7 --- /dev/null +++ b/src/mame/heathzenith/h19.cpp @@ -0,0 +1,73 @@ +// license:BSD-3-Clause +// copyright-holders:Mark Garlanger +/*************************************************************************** + + Heathkit H19 + Zenith Data Systems Z-19 + + A smart terminal designed and manufactured by Heath Company. This + is identical to the Zenith Data Systems Z-19. + +****************************************************************************/ + +#include "emu.h" + +#include "tlb.h" +#include "bus/rs232/rs232.h" + +#include "h19.lh" + + +namespace { + +class h19_state : public driver_device +{ +public: + h19_state(const machine_config &mconfig, device_type type, const char *tag) : + driver_device(mconfig, type, tag), + m_tlbc(*this, "tlbc") + { + } + + void h19(machine_config &config); + +private: + required_device m_tlbc; + +}; + +static void tlb_options(device_slot_interface &device) +{ + device.option_add("heath", HEATH_TLB); + device.option_add("gp19", HEATH_GP19); + device.option_add("imaginator", HEATH_IMAGINATOR); + device.option_add("super19", HEATH_SUPER19); + device.option_add("superset", HEATH_SUPERSET); + device.option_add("ultrarom", HEATH_ULTRA); + device.option_add("watzman", HEATH_WATZ); +} + +void h19_state::h19(machine_config &config) +{ + config.set_default_layout(layout_h19); + + HEATH_TLB_CONNECTOR(config, m_tlbc, tlb_options, "heath"); + m_tlbc->serial_data_callback().set("dte", FUNC(rs232_port_device::write_txd)); + m_tlbc->dtr_callback().set("dte", FUNC(rs232_port_device::write_dtr)); + m_tlbc->rts_callback().set("dte", FUNC(rs232_port_device::write_rts)); + + rs232_port_device &dte(RS232_PORT(config, "dte", default_rs232_devices, "loopback")); + dte.rxd_handler().set(m_tlbc, FUNC(heath_tlb_connector::serial_in_w)); + dte.dcd_handler().set(m_tlbc, FUNC(heath_tlb_connector::rlsd_in_w)); + dte.dsr_handler().set(m_tlbc, FUNC(heath_tlb_connector::dsr_in_w)); + dte.cts_handler().set(m_tlbc, FUNC(heath_tlb_connector::cts_in_w)); +} + +// ROM definition +ROM_START( h19 ) +ROM_END + +} // anonymous namespace + +// year name parent compat machine input class init company fullname flags +COMP( 1979, h19, 0, 0, h19, 0, h19_state, empty_init, "Heath Company", "H-19 Terminal", MACHINE_SUPPORTS_SAVE ) diff --git a/src/mame/heathzenith/h8.cpp b/src/mame/heathzenith/h8.cpp new file mode 100644 index 00000000000..236ce61f9bd --- /dev/null +++ b/src/mame/heathzenith/h8.cpp @@ -0,0 +1,417 @@ +// license:BSD-3-Clause +// copyright-holders:Robbbert +/*************************************************************************** + + Heathkit H8 + + 2009-05-12 Skeleton driver. + + This system uses Octal rather than the usual hexadecimal. + +STATUS: + It runs, keyboard works, you can enter data. + +Meaning of LEDs: + PWR = power is turned on + MON = controls should work + RUN = CPU is running (not halted) + ION = Interrupts are enabled + +Pasting: + 0-F : as is + + : ^ + - : V + MEM : - + ALTER : = + + Addresses must have all 6 digits entered. + Data must have all 3 digits entered. + System has a short beep for each key, and a slightly longer beep + for each group of 3 digits. The largest number allowed is 377 (=0xFF). + +Test Paste: + -041000=123 245 333 144 255 366 077=-041000 + Now press up-arrow to confirm the data has been entered. + +Official test program from pages 4 to 8 of the operator's manual: + -040100=076 002 062 010 040 006 004 041 170 040 021 013 040 016 011 176 + 022 043 023 015 302 117 040 016 003 076 377 315 053 000 015 302 + 131 040 005 302 112 040 076 062 315 140 002 076 062 315 053 000 + 076 062 315 140 002 303 105 040 377 262 270 272 275 377 222 200 + 377 237 244 377 272 230 377 220 326 302 377 275 272 271 271 373 + 271 240 377 236 376 362 236 376 362 236 376 362 R6=040100=4 + + +****************************************************************************/ + +#include "emu.h" + +#include "cpu/i8085/i8085.h" +#include "machine/i8251.h" +#include "machine/clock.h" +#include "machine/timer.h" +#include "imagedev/cassette.h" +#include "sound/beep.h" +#include "speaker.h" + +#include "formats/h8_cas.h" +#include "h8.lh" + +namespace { + +class h8_state : public driver_device +{ +public: + h8_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag) + , m_maincpu(*this, "maincpu") + , m_uart(*this, "uart") + , m_cass(*this, "cassette") + , m_beep(*this, "beeper") + , m_io_keyboard(*this, "X%u", 0U) + , m_digits(*this, "digit%u", 0U) + , m_mon_led(*this, "mon_led") + , m_pwr_led(*this, "pwr_led") + , m_ion_led(*this, "ion_led") + , m_run_led(*this, "run_led") + { } + + void h8(machine_config &config); + + DECLARE_INPUT_CHANGED_MEMBER(button_0); + +protected: + virtual void machine_reset() override; + virtual void machine_start() override; + +private: + u8 portf0_r(); + void portf0_w(u8 data); + void portf1_w(u8 data); + void h8_status_callback(u8 data); + void h8_inte_callback(int state); + TIMER_DEVICE_CALLBACK_MEMBER(h8_irq_pulse); + TIMER_DEVICE_CALLBACK_MEMBER(kansas_r); + TIMER_DEVICE_CALLBACK_MEMBER(kansas_w); + + void io_map(address_map &map); + void mem_map(address_map &map); + + u8 m_digit = 0U; + u8 m_segment = 0U; + u8 m_irq_ctl = 0U; + bool m_ff_b = 0; + u8 m_cass_data[4]{}; + bool m_cassbit = 0; + bool m_cassold = 0; + + // clocks + static constexpr XTAL H8_CLOCK = XTAL(12'288'000) / 6; // 2.048 MHz + static constexpr XTAL H8_BEEP_FRQ = H8_CLOCK / 2048; // 1 kHz + static constexpr XTAL H8_IRQ_PULSE = H8_BEEP_FRQ / 2; + + required_device m_maincpu; + required_device m_uart; + required_device m_cass; + required_device m_beep; + required_ioport_array<2> m_io_keyboard; + output_finder<16> m_digits; + output_finder<> m_mon_led; + output_finder<> m_pwr_led; + output_finder<> m_ion_led; + output_finder<> m_run_led; +}; + + +TIMER_DEVICE_CALLBACK_MEMBER(h8_state::h8_irq_pulse) +{ + if (BIT(m_irq_ctl, 0)) + m_maincpu->set_input_line_and_vector(INPUT_LINE_IRQ0, ASSERT_LINE, 0xcf); // I8080 +} + +u8 h8_state::portf0_r() +{ + // reads the keyboard + + // The following not emulated, can occur any time even if keyboard not being scanned + // - if 0 and RTM pressed, causes int10 + // - if 0 and RST pressed, resets cpu + + u8 i,keyin,data = 0xff; + + keyin = m_io_keyboard[0]->read(); + if (keyin != 0xff) + { + for (i = 1; i < 8; i++) + if (!BIT(keyin,i)) + data &= ~(i<<1); + data &= 0xfe; + } + + keyin = m_io_keyboard[1]->read(); + if (keyin != 0xff) + { + for (i = 1; i < 8; i++) + if (!BIT(keyin,i)) + data &= ~(i<<5); + data &= 0xef; + } + return data; +} + +void h8_state::portf0_w(u8 data) +{ + // this will always turn off int10 that was set by the timer + // d0-d3 = digit select + // d4 = int20 is allowed + // d5 = mon led + // d6 = int10 is allowed + // d7 = beeper enable + + m_digit = data & 15; + if (m_digit) m_digits[m_digit] = m_segment; + + m_mon_led = !BIT(data, 5); + m_beep->set_state(!BIT(data, 7)); + + m_maincpu->set_input_line(INPUT_LINE_IRQ0, CLEAR_LINE); + m_irq_ctl &= 0xf0; + if (BIT(data, 6)) m_irq_ctl |= 1; + if (!BIT(data, 4)) m_irq_ctl |= 2; +} + +void h8_state::portf1_w(u8 data) +{ + //d7 segment dot + //d6 segment f + //d5 segment e + //d4 segment d + //d3 segment c + //d2 segment b + //d1 segment a + //d0 segment g + + m_segment = 0xff ^ bitswap<8>(data, 7, 0, 6, 5, 4, 3, 2, 1); + if (m_digit) m_digits[m_digit] = m_segment; +} + +void h8_state::mem_map(address_map &map) +{ + map.unmap_value_high(); + map(0x0000, 0x0fff).rom(); // main rom + map(0x1400, 0x17ff).ram(); // fdc ram + map(0x1800, 0x1fff).rom(); // fdc rom + map(0x2000, 0x9fff).ram(); // main ram +} + +void h8_state::io_map(address_map &map) +{ + map.unmap_value_high(); + map.global_mask(0xff); + map(0xf0, 0xf0).rw(FUNC(h8_state::portf0_r), FUNC(h8_state::portf0_w)); + map(0xf1, 0xf1).w(FUNC(h8_state::portf1_w)); + map(0xf8, 0xf9).rw(m_uart, FUNC(i8251_device::read), FUNC(i8251_device::write)); + // optional connection to a serial terminal @ 600 baud + //map(0xfa, 0xfb).rw("uart1", FUNC(i8251_device::read), FUNC(i8251_device::write)); +} + +/* Input ports */ +static INPUT_PORTS_START( h8 ) + PORT_START("X0") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("0") PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHANGED_MEMBER(DEVICE_SELF, h8_state, button_0, 0) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("1 SP") PORT_CODE(KEYCODE_1) PORT_CHAR('1') + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("2 AF") PORT_CODE(KEYCODE_2) PORT_CHAR('2') + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("3 BC") PORT_CODE(KEYCODE_3) PORT_CHAR('3') + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("4 DE GO") PORT_CODE(KEYCODE_4) PORT_CHAR('4') + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("5 HL IN") PORT_CODE(KEYCODE_5) PORT_CHAR('5') + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("6 PC OUT") PORT_CODE(KEYCODE_6) PORT_CHAR('6') + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("7 SI") PORT_CODE(KEYCODE_7) PORT_CHAR('7') + + PORT_START("X1") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("8 LOAD") PORT_CODE(KEYCODE_8) PORT_CHAR('8') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("9 DUMP") PORT_CODE(KEYCODE_9) PORT_CHAR('9') + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("+") PORT_CODE(KEYCODE_UP) PORT_CHAR('^') + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("-") PORT_CODE(KEYCODE_DOWN) PORT_CHAR('V') + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("* CANCEL") PORT_CODE(KEYCODE_ESC) PORT_CHAR('Q') + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("/ ALTER RST") PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("# MEM RTM") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(". REG") PORT_CODE(KEYCODE_R) PORT_CHAR('R') +INPUT_PORTS_END + +INPUT_CHANGED_MEMBER(h8_state::button_0) +{ + if (newval) + { + u8 data = m_io_keyboard[1]->read() ^ 0xff; + if (BIT(data, 5)) + m_maincpu->reset(); + else + if (BIT(data, 6)) + m_maincpu->set_input_line_and_vector(INPUT_LINE_IRQ0, ASSERT_LINE, 0xcf); // INT 10 // I8080 + } +} + +void h8_state::machine_reset() +{ + m_pwr_led = 0; + m_irq_ctl = 1; + m_cassbit = 1; + m_cass_data[0] = 0; + m_cass_data[1] = 0; + m_uart->write_cts(0); + m_uart->write_dsr(0); + m_uart->write_rxd(0); + m_cass_data[3] = 0; + m_ff_b = 1; +} + +void h8_state::machine_start() +{ + m_digits.resolve(); + m_mon_led.resolve(); + m_pwr_led.resolve(); + m_ion_led.resolve(); + m_run_led.resolve(); + + save_item(NAME(m_digit)); + save_item(NAME(m_segment)); + save_item(NAME(m_irq_ctl)); + save_item(NAME(m_ff_b)); + save_item(NAME(m_cass_data)); + save_item(NAME(m_cassbit)); + save_item(NAME(m_cassold)); +} + +void h8_state::h8_inte_callback(int state) +{ + // operate the ION LED + m_ion_led = !state; + m_irq_ctl &= 0x7f | ((state) ? 0 : 0x80); +} + +void h8_state::h8_status_callback(u8 data) +{ +/* This is rather messy, but basically there are 2 D flipflops, one drives the other, +the data is /INTE while the clock is /M1. If the system is in Single Instruction mode, +a int20 (output of 2nd flipflop) will occur after 4 M1 steps, to pause the running program. +But, all of this can only occur if bit 4 of port F0 is low. */ + + bool state = (data & i8080_cpu_device::STATUS_M1) ? 0 : 1; + bool c,a = BIT(m_irq_ctl, 7); + + if (BIT(m_irq_ctl, 1)) + { + if (!state) // rising pulse to push data through flipflops + { + c = !m_ff_b; // from /Q of 2nd flipflop + m_ff_b = a; // from Q of 1st flipflop + if (c) + m_maincpu->set_input_line_and_vector(INPUT_LINE_IRQ0, ASSERT_LINE, 0xd7); // I8080 + } + } + else + { // flipflops are 'set' + c = 0; + m_ff_b = 1; + } + + + // operate the RUN LED + m_run_led = state; +} + +TIMER_DEVICE_CALLBACK_MEMBER(h8_state::kansas_w) +{ + m_cass_data[3]++; + + if (m_cassbit != m_cassold) + { + m_cass_data[3] = 0; + m_cassold = m_cassbit; + } + + if (m_cassbit) + m_cass->output(BIT(m_cass_data[3], 0) ? -1.0 : +1.0); // 2400Hz + else + m_cass->output(BIT(m_cass_data[3], 1) ? -1.0 : +1.0); // 1200Hz +} + +TIMER_DEVICE_CALLBACK_MEMBER(h8_state::kansas_r) +{ + /* cassette - turn 1200/2400Hz to a bit */ + m_cass_data[1]++; + u8 cass_ws = (m_cass->input() > +0.03) ? 1 : 0; + + if (cass_ws != m_cass_data[0]) + { + m_cass_data[0] = cass_ws; + m_uart->write_rxd((m_cass_data[1] < 12) ? 1 : 0); + m_cass_data[1] = 0; + } +} + +void h8_state::h8(machine_config &config) +{ + /* basic machine hardware */ + I8080(config, m_maincpu, H8_CLOCK); + m_maincpu->set_addrmap(AS_PROGRAM, &h8_state::mem_map); + m_maincpu->set_addrmap(AS_IO, &h8_state::io_map); + m_maincpu->out_status_func().set(FUNC(h8_state::h8_status_callback)); + m_maincpu->out_inte_func().set(FUNC(h8_state::h8_inte_callback)); + + /* video hardware */ + config.set_default_layout(layout_h8); + + /* sound hardware */ + SPEAKER(config, "mono").front_center(); + BEEP(config, m_beep, H8_BEEP_FRQ).add_route(ALL_OUTPUTS, "mono", 1.00); + + /* Devices */ + I8251(config, m_uart, 0); + m_uart->txd_handler().set([this] (bool state) { m_cassbit = state; }); + + clock_device &cassette_clock(CLOCK(config, "cassette_clock", 4800)); + cassette_clock.signal_handler().set(m_uart, FUNC(i8251_device::write_txc)); + cassette_clock.signal_handler().append(m_uart, FUNC(i8251_device::write_rxc)); + + CASSETTE(config, m_cass); + m_cass->set_formats(h8_cassette_formats); + m_cass->set_default_state(CASSETTE_STOPPED | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_ENABLED); + m_cass->add_route(ALL_OUTPUTS, "mono", 0.05); + m_cass->set_interface("h8_cass"); + + TIMER(config, "kansas_w").configure_periodic(FUNC(h8_state::kansas_w), attotime::from_hz(4800)); + TIMER(config, "kansas_r").configure_periodic(FUNC(h8_state::kansas_r), attotime::from_hz(40000)); + TIMER(config, "h8_timer").configure_periodic(FUNC(h8_state::h8_irq_pulse), attotime::from_hz(H8_IRQ_PULSE)); +} + +/* ROM definition */ +ROM_START( h8 ) + ROM_REGION( 0x2000, "maincpu", ROMREGION_ERASEFF ) + // H17 fdc bios - needed by bios2&3 + ROM_LOAD( "2716_444-19_h17.rom", 0x1800, 0x0800, CRC(26e80ae3) SHA1(0c0ee95d7cb1a760f924769e10c0db1678f2435c)) + + ROM_SYSTEM_BIOS(0, "bios0", "Standard") + ROMX_LOAD( "2708_444-13_pam8.rom", 0x0000, 0x0400, CRC(e0745513) SHA1(0e170077b6086be4e5cd10c17e012c0647688c39), ROM_BIOS(0) ) + + ROM_SYSTEM_BIOS(1, "bios1", "Alternate") + ROMX_LOAD( "2708_444-13_pam8go.rom", 0x0000, 0x0400, CRC(9dbad129) SHA1(72421102b881706877f50537625fc2ab0b507752), ROM_BIOS(1) ) + + ROM_SYSTEM_BIOS(2, "bios2", "Disk OS") + ROMX_LOAD( "2716_444-13_pam8at.rom", 0x0000, 0x0800, CRC(fd95ddc1) SHA1(eb1f272439877239f745521139402f654e5403af), ROM_BIOS(2) ) + + ROM_SYSTEM_BIOS(3, "bios3", "Disk OS Alt") + ROMX_LOAD( "2732_444-70_xcon8.rom", 0x0000, 0x1000, CRC(b04368f4) SHA1(965244277a3a8039a987e4c3593b52196e39b7e7), ROM_BIOS(3) ) + + // this one runs off into the weeds + ROM_SYSTEM_BIOS(4, "bios4", "not working") + ROMX_LOAD( "2732_444-140_pam37.rom", 0x0000, 0x1000, CRC(53a540db) SHA1(90082d02ffb1d27e8172b11fff465bd24343486e), ROM_BIOS(4) ) +ROM_END + +} // anonymous namespace + + +/* Driver */ + +/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS, INIT COMPANY FULLNAME FLAGS */ +COMP( 1977, h8, 0, 0, h8, h8, h8_state, empty_init, "Heath Company", "Heathkit H8 Digital Computer", MACHINE_SUPPORTS_SAVE ) diff --git a/src/mame/heathzenith/h89.cpp b/src/mame/heathzenith/h89.cpp new file mode 100644 index 00000000000..65827b00adc --- /dev/null +++ b/src/mame/heathzenith/h89.cpp @@ -0,0 +1,1031 @@ +// license:BSD-3-Clause +// copyright-holders:Sandro Ronco, Mark Garlanger +/*************************************************************************** + + Heathkit H89 + + Heath Company made several very similar systems, including + - H88 - kit, came with a cassette interface board instead of floppy controller + - H89 - kit, came with a hard-sectored floppy disk controller + - WH89 - was factory assembled + + Heath's parent company Zenith, also sold systems under the Zenith Data + Systems brand. These were all factory assembled + - Z-89 - same as Heath's H89, but assembled + - Z-90 - came with a soft-sectored floppy disk controller + + Monitor Commands (for MTR-90): + B Boot + C Convert (number) + G Go (address) + I In (address) + O Out (address,data) + R Radix (H/O) + S Substitute (address) + T Test Memory + V View + + Monitor Commands (for MTR-88) + B Boot + D Dump - dump a program to cassette + G Go (address) + L Load - load a program from cassette + P Program Counter (address) - select an address in the PC + S Substitute - inspect or change memory + + Monitor Commands (for MTR-89) + B Boot + G Go (address) + P Program Counter (address) - select an address in the PC + S Substitute - inspect or change memory + +****************************************************************************/ + +#include "emu.h" + +#include "h_88_cass.h" +#include "intr_cntrl.h" +#include "sigmasoft_parallel_port.h" +#include "tlb.h" +#include "z37_fdc.h" + +#include "cpu/z80/z80.h" +#include "machine/ins8250.h" +#include "machine/ram.h" +#include "machine/timer.h" + +#include "softlist_dev.h" + +#include "h89.lh" + + +// Single Step +#define LOG_SS (1U << 1) + +// #define VERBOSE ( LOG_SS ) +#include "logmacro.h" + +#define LOGSS(...) LOGMASKED(LOG_SS, __VA_ARGS__) + + +namespace { + +/** + * Base Heathkit H89 functionality + */ +class h89_base_state : public driver_device +{ +protected: + h89_base_state(const machine_config &mconfig, device_type type, const char *tag): + driver_device(mconfig, type, tag), + m_maincpu(*this, "maincpu"), + m_maincpu_region(*this, "maincpu"), + m_mem_view(*this, "rom_bank"), + m_ram(*this, RAM_TAG), + m_floppy_ram(*this, "floppyram"), + m_tlbc(*this, "tlbc"), + m_intr_socket(*this, "intr_socket"), + m_console(*this, "console"), + m_serial1(*this, "serial1"), + m_serial2(*this, "serial2"), + m_serial3(*this, "serial3"), + m_config(*this, "CONFIG") + { + } + + void h89_base(machine_config &config); + + required_device m_maincpu; + required_memory_region m_maincpu_region; + memory_view m_mem_view; + required_device m_ram; + required_shared_ptr m_floppy_ram; + required_device m_tlbc; + required_device m_intr_socket; + required_device m_console; + required_device m_serial1; + required_device m_serial2; + required_device m_serial3; + required_ioport m_config; + memory_access<16, 0, 0, ENDIANNESS_LITTLE>::specific m_program; + + // General Purpose Port (GPP) + u8 m_gpp; + + bool m_rom_enabled; + bool m_timer_intr_enabled; + bool m_single_step_enabled; + bool m_floppy_ram_wp; + + // single step flags + bool m_555a_latch; + bool m_555b_latch; + bool m_556b_latch; + + u32 m_cpu_speed_multiplier; + + // Clocks + static constexpr XTAL H89_CLOCK = XTAL(12'288'000) / 6; + static constexpr XTAL INS8250_CLOCK = XTAL(1'843'200); + + static constexpr u8 GPP_SINGLE_STEP_BIT = 0; + static constexpr u8 GPP_ENABLE_TIMER_INTERRUPT_BIT = 1; + static constexpr u8 GPP_SPEED_SELECT_BIT = 4; + static constexpr u8 GPP_DISABLE_ROM_BIT = 5; + static constexpr u8 GPP_H17_SIDE_SELECT_BIT = 6; + + void update_mem_view(); + + void update_gpp(u8 gpp); + void port_f2_w(u8 data); + + virtual void machine_start() override; + virtual void machine_reset() override; + TIMER_DEVICE_CALLBACK_MEMBER(h89_irq_timer); + + void h89_mem(address_map &map); + void map_fetch(address_map &map); + u8 m1_r(offs_t offset); + + void h89_base_io(address_map &map); + + u8 raise_NMI_r(); + void raise_NMI_w(u8 data); + void console_intr(int data); + void reset_line(int data); + void reset_single_step_state(); +}; + +/** + * Heathkit H88 + * - BIOS MTR-88 + * - H-88-5 Cassette Interface Board + * + */ +class h88_state : public h89_base_state +{ +public: + h88_state(const machine_config &mconfig, device_type type, const char *tag): + h89_base_state(mconfig, type, tag), + m_cassette(*this, "h_88_5") + { + } + + void h88(machine_config &config); + +protected: + required_device m_cassette; + + void h88_io(address_map &map); +}; + + +/** + * Heathkit H89 + * - Z-89-37 Soft-sectored Floppy Controller + * + */ +class h89_state : public h89_base_state +{ +public: + h89_state(const machine_config &mconfig, device_type type, const char *tag): + h89_base_state(mconfig, type, tag), + m_h37(*this, "h37") + { + } + + void h89(machine_config &config); + +protected: + required_device m_h37; + + void h89_io(address_map &map); +}; + + +class h89_sigmasoft_state : public h89_state +{ +public: + h89_sigmasoft_state(const machine_config &mconfig, device_type type, const char *tag): + h89_state(mconfig, type, tag), + m_sigma_parallel(*this, "sigma_parallel") + { + } + + void h89_sigmasoft(machine_config &config); + +protected: + required_device m_sigma_parallel; + + void h89_sigmasoft_io(address_map &map); +}; + + +/* + The H89 supported 16K, 32K, 48K, or 64K of RAM. The first 8K of address space + is reserved for the monitor ROM, floppy ROM, and scratch pad RAM. For 16k-48K + sizes, the upper 8k of memory is remapped to the first 8K when the ROM is disabled. + For systems with 64K of RAM, the upper half of the expansion board is permanently + mapped to the lower 8K. Even when ROM is mapped, any writes will still occur + to the RAM. + + H89 Lower 8K address map + + HDOS Mode CP/M Mode + ------------------- 0x2000 (8k) ---------------- + | Floppy ROM | | | + ------------------- 0x1800 (6k) | | + | Floppy RAM | | | + ------------------- 0x1400 (5k) | RAM | + | Open | | | + ------------------- 0x1000 (4k) | | + | MTR-90 ROM | | | + -................-- 0x0800 (2k) | | + | MTR(88/89) ROM | | | + ------------------- 0x0000 (0k) ---------------- + + + 16K RAM Example + + HDOS CP/M + ------------- 24k + | RAM | ------+ + ------------- 16k | ------------- 16k + | RAM | -------------> | RAM | + ------------- 8k | ------------- 8k + | ROM | +------> | RAM | + ------------- 0k ------------- 0k + +*/ +void h89_base_state::h89_mem(address_map &map) +{ + map.unmap_value_high(); + + map(0x0000, 0xffff).view(m_mem_view); + + // View 0 - ROM / Floppy RAM R/O + // View 1 - ROM / Floppy RAM R/W + // monitor ROM + m_mem_view[0](0x0000, 0x0fff).rom().region("maincpu", 0).unmapw(); + m_mem_view[1](0x0000, 0x0fff).rom().region("maincpu", 0).unmapw(); + + // Floppy RAM + m_mem_view[0](0x1400, 0x17ff).readonly().share(m_floppy_ram); + m_mem_view[1](0x1400, 0x17ff).ram().share(m_floppy_ram); + + // Floppy ROM + m_mem_view[0](0x1800, 0x1fff).rom().region("maincpu", 0x1800).unmapw(); + m_mem_view[1](0x1800, 0x1fff).rom().region("maincpu", 0x1800).unmapw(); +} + +void h89_base_state::map_fetch(address_map &map) +{ + map(0x0000, 0xffff).r(FUNC(h89_base_state::m1_r)); +} + +u8 h89_base_state::m1_r(offs_t offset) +{ + u8 data = m_program.read_byte(offset); + + if (!machine().side_effects_disabled() && m_single_step_enabled && !m_556b_latch) + { + LOGSS("single step m1_r - data: 0x%02x, 555a: %d, 555b: %d, 556b: %d\n", data, m_555a_latch, m_555b_latch, m_556b_latch); + + if (!m_555a_latch) + { + // Wait for EI instruction + if (data == 0xfb) + { + m_555a_latch = true; + } + } + else if (!m_555b_latch) + { + m_555b_latch = true; + } + else if (!m_556b_latch) + { + m_556b_latch = true; + + m_intr_socket->set_irq_level(2, ASSERT_LINE); + } + } + + return data; +} + +/* + PORT + Use | Hex | Octal + --------------------------+-------+--------- + Not specified, available | 0-77 | 0-167 + Disk I/O #1 | 78-7B | 170-173 + Disk I/O #2 | 7C-7F | 174-177 + Not specified, reserved | 80-CF | 200-317 + DCE Serial I/O | D0-D7 | 320-327 + DTE Serial I/O | D8-DF | 330-337 + DCE Serial I/O | EO-E7 | 340-347 + Console I/O | E8-EF | 350-357 + NMI | F0-F1 | 360-361 + General purpose port | F2 | 362 + Cassette I/O(MTR-88) | F8-F9 | 370-371 + NMI | FA-FB | 372-373 + + Disk I/O #1 - 0170-0173 (0x78-0x7b) + Heath Options + - H37 5-1/4" Soft-sectored Controller - Requires MTR-90 ROM + - H47 Dual 8" Drives - Requires MTR-89 or MTR-90 ROM + - H67 8" Hard disk + 8" Floppy Drives - Requires MTR-90 ROM + + Disk I/O #2 - 0174-0177 (0x7c-0x7f) + Heath Options + - 5-1/4" Hard-sectored Controller - supported by all ROMs + - H47 Dual 8" Drives - Requires MTR-89 or MTR-90 ROM + - H67 8" Hard disk + 8" Floppy Drives - MTR-90 ROM + +*/ +void h89_base_state::h89_base_io(address_map &map) +{ + map.unmap_value_high(); + map.global_mask(0xff); + + // 8250 UART DCE 0320 (0xd0) + map(0xd0, 0xd7).rw(m_serial1, FUNC(ins8250_device::ins8250_r), FUNC(ins8250_device::ins8250_w)); + // 8250 UART DTE 0330 (0xd8) - typically used for modem + map(0xd8, 0xdf).rw(m_serial2, FUNC(ins8250_device::ins8250_r), FUNC(ins8250_device::ins8250_w)); + // 8250 UART DCE 0340 (0xe0) - typically used for printer + map(0xe0, 0xe7).rw(m_serial3, FUNC(ins8250_device::ins8250_r), FUNC(ins8250_device::ins8250_w)); + + // 8250 UART console - this connects internally to the Terminal Logic board that is also used in the H19. + map(0xe8, 0xef).rw(m_console, FUNC(ins8250_device::ins8250_r), FUNC(ins8250_device::ins8250_w)); + + // ports defined on the H8. On the H89, access to these addresses causes a NMI + map(0xf0, 0xf1).rw(FUNC(h89_base_state::raise_NMI_r),FUNC(h89_base_state::raise_NMI_w)); + + // General Purpose Port (GPP) + map(0xf2, 0xf2).w(FUNC(h89_base_state::port_f2_w)).portr("SW501"); + + // port defined on the H8. On the H89, access to these addresses causes a NMI + map(0xfa, 0xfb).rw(FUNC(h89_base_state::raise_NMI_r), FUNC(h89_base_state::raise_NMI_w)); +} + +void h88_state::h88_io(address_map &map) +{ + h89_base_state::h89_base_io(map); + + // Cassette I/O (uses 0xf8 - 0xf9) - Requires MTR-88 ROM + map(0xf8, 0xf9).rw(m_cassette, FUNC(heath_h_88_cass_device::read), FUNC(heath_h_88_cass_device::write)); +} + +void h89_state::h89_io(address_map &map) +{ + h89_base_state::h89_base_io(map); + + // H37 5-1/4" Soft-sectored Controller - Requires MTR-90 ROM + map(0x78, 0x7b).rw(m_h37, FUNC(heath_z37_fdc_device::read), FUNC(heath_z37_fdc_device::write)); +} + +void h89_sigmasoft_state::h89_sigmasoft_io(address_map &map) +{ + h89_io(map); + + // Add SigmaSoft parallel port board, required for IGC graphics + map(0x08,0x0f).rw(m_sigma_parallel, FUNC(sigmasoft_parallel_port::read), FUNC(sigmasoft_parallel_port::write)); +} + + +// Input ports +static INPUT_PORTS_START( h88 ) + + PORT_START("SW501") + // MTR-88 (444-40) + PORT_DIPUNUSED_DIPLOC(0x01, 0x00, "SW501:1") + PORT_DIPUNUSED_DIPLOC(0x02, 0x00, "SW501:2") + PORT_DIPUNUSED_DIPLOC(0x04, 0x00, "SW501:3") + PORT_DIPUNUSED_DIPLOC(0x08, 0x00, "SW501:4") + PORT_DIPUNUSED_DIPLOC(0x10, 0x00, "SW501:5") + PORT_DIPNAME( 0x20, 0x20, "Perform memory test at start" ) PORT_DIPLOCATION("SW501:6") + PORT_DIPSETTING( 0x20, DEF_STR( No ) ) + PORT_DIPSETTING( 0x00, DEF_STR( Yes ) ) + PORT_DIPNAME( 0xc0, 0x00, "Console Baud rate" ) PORT_DIPLOCATION("SW501:7,8") + PORT_DIPSETTING( 0x00, "9600" ) + PORT_DIPSETTING( 0x40, "19200" ) + PORT_DIPSETTING( 0x80, "38400" ) + PORT_DIPSETTING( 0xc0, "57600" ) + + PORT_START("CONFIG") + PORT_CONFNAME( 0x03, 0x00, "CPU Clock Speed Upgrade") + PORT_CONFSETTING( 0x00, DEF_STR( None ) ) + PORT_CONFSETTING( 0x01, "2 / 4 MHz") + PORT_CONFSETTING( 0x02, "2 / 6 MHz") + +INPUT_PORTS_END + + +static INPUT_PORTS_START( h89 ) + + PORT_START("SW501") + // Generic definition + PORT_DIPNAME( 0x01, 0x00, "Switch 0" ) PORT_DIPLOCATION("SW501:1") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x00) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x01, DEF_STR( On ) ) + PORT_DIPNAME( 0x02, 0x00, "Switch 1" ) PORT_DIPLOCATION("SW501:2") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x00) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x02, DEF_STR( On ) ) + PORT_DIPNAME( 0x04, 0x00, "Switch 2" ) PORT_DIPLOCATION("SW501:3") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x00) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x04, DEF_STR( On ) ) + PORT_DIPNAME( 0x08, 0x00, "Switch 3" ) PORT_DIPLOCATION("SW501:4") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x00) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x08, DEF_STR( On ) ) + PORT_DIPNAME( 0x10, 0x00, "Switch 4" ) PORT_DIPLOCATION("SW501:5") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x00) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x10, DEF_STR( On ) ) + PORT_DIPNAME( 0x20, 0x20, "Switch 5" ) PORT_DIPLOCATION("SW501:6") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x00) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x20, DEF_STR( On ) ) + PORT_DIPNAME( 0x40, 0x00, "Switch 6" ) PORT_DIPLOCATION("SW501:7") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x00) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x40, DEF_STR( On ) ) + PORT_DIPNAME( 0x80, 0x00, "Switch 7" ) PORT_DIPLOCATION("SW501:8") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x00) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x80, DEF_STR( On ) ) + + // MTR-90 (444-84 or 444-142) + PORT_DIPNAME( 0x03, 0x00, "Disk I/O #2" ) PORT_DIPLOCATION("SW501:1,2") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x04) + PORT_DIPSETTING( 0x00, "H-88-1 (Not yet implemented)" ) + PORT_DIPSETTING( 0x01, "H/Z-47 (Not yet implemented)" ) + PORT_DIPSETTING( 0x02, "Z-67 (Not yet implemented)" ) + PORT_DIPSETTING( 0x03, "Undefined" ) + PORT_DIPNAME( 0x0c, 0x00, "Disk I/O #1" ) PORT_DIPLOCATION("SW501:3,4") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x04) + PORT_DIPSETTING( 0x00, "H-89-37" ) + PORT_DIPSETTING( 0x04, "H/Z-47 (Not yet implemented)" ) + PORT_DIPSETTING( 0x08, "Z-67 (Not yet implemented)" ) + PORT_DIPSETTING( 0x0c, "Undefined" ) + PORT_DIPNAME( 0x10, 0x00, "Primary Boot from" ) PORT_DIPLOCATION("SW501:5") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x04) + PORT_DIPSETTING( 0x00, "Disk I/O #2" ) + PORT_DIPSETTING( 0x10, "Disk I/O #1" ) + PORT_DIPNAME( 0x20, 0x20, "Perform memory test at start" ) PORT_DIPLOCATION("SW501:6") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x04) + PORT_DIPSETTING( 0x20, DEF_STR( No ) ) + PORT_DIPSETTING( 0x00, DEF_STR( Yes ) ) + PORT_DIPNAME( 0x40, 0x00, "Console Baud rate" ) PORT_DIPLOCATION("SW501:7") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x04) + PORT_DIPSETTING( 0x00, "9600" ) + PORT_DIPSETTING( 0x40, "19200" ) + PORT_DIPNAME( 0x80, 0x00, "Boot mode" ) PORT_DIPLOCATION("SW501:8") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x04) + PORT_DIPSETTING( 0x00, DEF_STR( Normal ) ) + PORT_DIPSETTING( 0x80, "Auto" ) + + // MTR-89 (444-62) + PORT_DIPNAME( 0x03, 0x00, "Disk I/O #2" ) PORT_DIPLOCATION("SW501:1,2") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x08) + PORT_DIPSETTING( 0x00, "H-88-1" ) + PORT_DIPSETTING( 0x01, "H/Z-47" ) + PORT_DIPSETTING( 0x02, "Undefined" ) + PORT_DIPSETTING( 0x03, "Undefined" ) + PORT_DIPNAME( 0x0c, 0x00, "Disk I/O #1" ) PORT_DIPLOCATION("SW501:3,4") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x08) + PORT_DIPSETTING( 0x00, "Unused" ) + PORT_DIPSETTING( 0x04, "H/Z-47" ) + PORT_DIPSETTING( 0x08, "Undefined" ) + PORT_DIPSETTING( 0x0c, "Undefined" ) + PORT_DIPNAME( 0x10, 0x00, "Primary Boot from" ) PORT_DIPLOCATION("SW501:5") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x08) + PORT_DIPSETTING( 0x00, "Disk I/O #2" ) + PORT_DIPSETTING( 0x10, "Disk I/O #1" ) + PORT_DIPNAME( 0x20, 0x20, "Perform memory test at start" ) PORT_DIPLOCATION("SW501:6") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x08) + PORT_DIPSETTING( 0x20, DEF_STR( No ) ) + PORT_DIPSETTING( 0x00, DEF_STR( Yes ) ) + PORT_DIPNAME( 0x40, 0x00, "Console Baud rate" ) PORT_DIPLOCATION("SW501:7") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x08) + PORT_DIPSETTING( 0x00, "9600" ) + PORT_DIPSETTING( 0x40, "19200" ) + PORT_DIPNAME( 0x80, 0x00, "Boot mode" ) PORT_DIPLOCATION("SW501:8") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x08) + PORT_DIPSETTING( 0x00, DEF_STR( Normal ) ) + PORT_DIPSETTING( 0x80, "Auto" ) + + // MMS 444-84B (and possibly 444-84A) + PORT_DIPNAME( 0x03, 0x00, "Disk I/O #2" ) PORT_DIPLOCATION("SW501:1,2") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x0c) + PORT_DIPSETTING( 0x00, "H-88-1" ) + PORT_DIPSETTING( 0x01, "H/Z-47 (Not yet implemented)" ) + PORT_DIPSETTING( 0x02, "MMS 77320 SASI or Z-67 (Not yet implemented)" ) + PORT_DIPSETTING( 0x03, "MMS 77422 Network Controller" ) + PORT_DIPNAME( 0x0c, 0x00, "Disk I/O #1" ) PORT_DIPLOCATION("SW501:3,4") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x0c) + PORT_DIPSETTING( 0x00, "H-89-37" ) + PORT_DIPSETTING( 0x04, "H/Z-47 (Not yet implemented)" ) + PORT_DIPSETTING( 0x08, "MMS 77320 SASI or Z-67 (Not yet implemented)" ) + PORT_DIPSETTING( 0x0c, "MMS 77422 Network Controller" ) + PORT_DIPNAME( 0x70, 0x00, "Default Boot Device" ) PORT_DIPLOCATION("SW501:5,6,7") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x0c) + PORT_DIPSETTING( 0x00, "MMS 77316 Dbl Den 5\"" ) + PORT_DIPSETTING( 0x10, "MMS 77316 Dbl Den 8\"" ) + PORT_DIPSETTING( 0x20, "Disk Device at 0x7C" ) + PORT_DIPSETTING( 0x30, "Disk Device at 0x78" ) + PORT_DIPSETTING( 0x40, "reserved for future use" ) + PORT_DIPSETTING( 0x50, "reserved for future use" ) + PORT_DIPSETTING( 0x60, "MMS Network (77422)" ) + PORT_DIPSETTING( 0x70, "Use MMS I/O board Config Port" ) + PORT_DIPNAME( 0x80, 0x00, "Boot mode" ) PORT_DIPLOCATION("SW501:8") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x0c) + PORT_DIPSETTING( 0x00, DEF_STR( Normal ) ) + PORT_DIPSETTING( 0x80, "Auto" ) + + // Kres KMR-100 + PORT_DIPNAME( 0x0f, 0x00, "Default Boot Device" ) PORT_DIPLOCATION("SW501:1,2,3,4") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x10) + PORT_DIPSETTING( 0x00, "H-17 hard-sectored 5\" floppy units 0-2" ) + PORT_DIPSETTING( 0x01, "H-37 soft-sectored 5\" floppy units 0-3" ) + PORT_DIPSETTING( 0x02, "Corvus hard disk/Magnolia interface, partitions 0-8" ) + PORT_DIPSETTING( 0x03, "CDR 5\"/8\" double density floppy, units 0-3" ) + PORT_DIPSETTING( 0x04, "H-47 8\" floppy at port 0x78/0170, units 0-3" ) + PORT_DIPSETTING( 0x05, "H-47 8\" floppy at port 0x7c/0174, units 0-3" ) + PORT_DIPSETTING( 0x06, "Reserved" ) + PORT_DIPSETTING( 0x07, "Help - lists boot devices" ) + PORT_DIPSETTING( 0x08, "Reserved" ) + PORT_DIPSETTING( 0x09, "SASI controller or Z-67 at port 0x78/0170, units 0-7" ) + PORT_DIPSETTING( 0x0a, "SASI controller or Z-67 at port 0x7c/0174, units 0-7" ) + PORT_DIPSETTING( 0x0b, "Livingston 8\" single density floppy, units 0-3" ) + PORT_DIPSETTING( 0x0c, "Magnolia 5\"/8\" double density floppy, units 0-3 (8\"), 4-7 (5\")" ) + PORT_DIPSETTING( 0x0d, "Reserved" ) + PORT_DIPSETTING( 0x0e, "Reserved" ) + PORT_DIPSETTING( 0x0f, "Magnolia 128K pseudo disk, banks 0-1" ) + PORT_DIPNAME( 0x10, 0x00, "Map ROM into RAM on boot" ) PORT_DIPLOCATION("SW501:5") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x10) + PORT_DIPSETTING( 0x00, DEF_STR( Yes ) ) + PORT_DIPSETTING( 0x10, DEF_STR( No ) ) + PORT_DIPNAME( 0x20, 0x20, "Perform memory test at start" ) PORT_DIPLOCATION("SW501:6") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x10) + PORT_DIPSETTING( 0x20, DEF_STR( No ) ) + PORT_DIPSETTING( 0x00, DEF_STR( Yes ) ) + PORT_DIPNAME( 0x40, 0x00, "Have a LLL controller installed" ) PORT_DIPLOCATION("SW501:7") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x10) + PORT_DIPSETTING( 0x00, DEF_STR( No ) ) + PORT_DIPSETTING( 0x40, DEF_STR( Yes ) ) + PORT_DIPNAME( 0x80, 0x00, "Boot mode" ) PORT_DIPLOCATION("SW501:8") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x10) + PORT_DIPSETTING( 0x00, DEF_STR( Normal ) ) + PORT_DIPSETTING( 0x80, "Auto" ) + + // Ultimeth MTRHEX-4k + // (values based on testing and comparison with the Kres KMR-100 ROM which was also written by Ultimeth) + PORT_DIPNAME( 0x0f, 0x00, "Default Boot Device" ) PORT_DIPLOCATION("SW501:1,2,3,4") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x14) + PORT_DIPSETTING( 0x00, "H-17 hard-sectored 5\" floppy" ) + PORT_DIPSETTING( 0x01, "H-37 soft-sectored 5\" floppy" ) + PORT_DIPSETTING( 0x02, "? Corvus hard disk/Magnolia interface" ) + PORT_DIPSETTING( 0x03, "? CDR 5\"/8\" double density floppy" ) + PORT_DIPSETTING( 0x04, "? H-47 8\" floppy at port 0x78/0170" ) + PORT_DIPSETTING( 0x05, "? H-47 8\" floppy at port 0x7c/0174" ) + PORT_DIPSETTING( 0x06, "? Reserved" ) + PORT_DIPSETTING( 0x07, "? Reserved" ) + PORT_DIPSETTING( 0x08, "? Reserved" ) + PORT_DIPSETTING( 0x09, "? SASI controller or Z-67 at port 0x78/0170" ) + PORT_DIPSETTING( 0x0a, "? SASI controller or Z-67 at port 0x7c/0174" ) + PORT_DIPSETTING( 0x0b, "? Livingston 8\" single density floppy" ) + PORT_DIPSETTING( 0x0c, "? Magnolia 5\"/8\" double density floppy" ) + PORT_DIPSETTING( 0x0d, "? Reserved" ) + PORT_DIPSETTING( 0x0e, "? Reserved" ) + PORT_DIPSETTING( 0x0f, "? Magnolia 128K pseudo disk" ) + PORT_DIPNAME( 0x10, 0x00, "? Map ROM into RAM on boot" ) PORT_DIPLOCATION("SW501:5") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x14) + PORT_DIPSETTING( 0x00, "? Yes" ) + PORT_DIPSETTING( 0x10, "? No" ) + PORT_DIPNAME( 0x20, 0x20, "Perform memory test at start" ) PORT_DIPLOCATION("SW501:6") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x14) + PORT_DIPSETTING( 0x20, DEF_STR( No ) ) + PORT_DIPSETTING( 0x00, DEF_STR( Yes ) ) + PORT_DIPNAME( 0x40, 0x00, "? Have a LLL controller installed" ) PORT_DIPLOCATION("SW501:7") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x14) + PORT_DIPSETTING( 0x00, "? No" ) + PORT_DIPSETTING( 0x40, "? Yes" ) + PORT_DIPNAME( 0x80, 0x00, "Boot mode" ) PORT_DIPLOCATION("SW501:8") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x14) + PORT_DIPSETTING( 0x00, DEF_STR( Normal ) ) + PORT_DIPSETTING( 0x80, "Auto" ) + + // Ultimeth MTRHEX-2k + PORT_DIPNAME( 0x03, 0x00, "Default Boot Device" ) PORT_DIPLOCATION("SW501:1,2") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x18) + PORT_DIPSETTING( 0x00, "H-17 hard-sectored 5\" floppy" ) + PORT_DIPSETTING( 0x01, "H-47 8\" floppy at port 0x78/0170" ) + PORT_DIPSETTING( 0x02, "H-47 8\" floppy at port 0x7c/0174" ) + PORT_DIPSETTING( 0x03, "Magnolia 5\"/8\" double density floppy" ) + PORT_DIPUNUSED_DIPLOC(0x04, 0x00, "SW501:3") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x18) + PORT_DIPUNUSED_DIPLOC(0x08, 0x00, "SW501:4") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x18) + PORT_DIPUNUSED_DIPLOC(0x10, 0x00, "SW501:5") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x18) + PORT_DIPNAME( 0x20, 0x20, "Perform memory test at start" ) PORT_DIPLOCATION("SW501:6") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x18) + PORT_DIPSETTING( 0x20, DEF_STR( No ) ) + PORT_DIPSETTING( 0x00, DEF_STR( Yes ) ) + PORT_DIPNAME( 0x40, 0x00, "Boot mode" ) PORT_DIPLOCATION("SW501:7") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x18) + PORT_DIPSETTING( 0x00, DEF_STR( Normal ) ) + PORT_DIPSETTING( 0x40, "Auto" ) + PORT_DIPNAME( 0x80, 0x00, "Baud Rate" ) PORT_DIPLOCATION("SW501:8") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x18) + PORT_DIPSETTING( 0x00, "9600" ) + PORT_DIPSETTING( 0x80, "19200" ) + + + PORT_START("CONFIG") + PORT_CONFNAME(0x03, 0x00, "CPU Clock Speed Upgrade") + PORT_CONFSETTING( 0x00, DEF_STR( None ) ) + PORT_CONFSETTING( 0x01, "2 / 4 MHz") + PORT_CONFSETTING( 0x02, "2 / 6 MHz") + PORT_CONFNAME(0x3c, 0x04, "Switch SW501 Definitions") + PORT_CONFSETTING( 0x00, "Generic" ) + PORT_CONFSETTING( 0x04, "Heath MTR-90") + PORT_CONFSETTING( 0x08, "Heath MTR-89") + PORT_CONFSETTING( 0x0c, "MMS 444-84B/444-84A") + PORT_CONFSETTING( 0x10, "Kres KMR-100") + PORT_CONFSETTING( 0x14, "Ultimeth MTRHEX-4k") + PORT_CONFSETTING( 0x18, "Ultimeth MTRHEX-2k") + +INPUT_PORTS_END + + +void h89_base_state::machine_start() +{ + save_item(NAME(m_gpp)); + save_item(NAME(m_rom_enabled)); + save_item(NAME(m_timer_intr_enabled)); + save_item(NAME(m_single_step_enabled)); + save_item(NAME(m_floppy_ram_wp)); + save_item(NAME(m_cpu_speed_multiplier)); + save_item(NAME(m_555a_latch)); + save_item(NAME(m_555b_latch)); + save_item(NAME(m_556b_latch)); + + m_maincpu->space(AS_PROGRAM).specific(m_program); + + // update RAM mappings based on RAM size + u8 *m_ram_ptr = m_ram->pointer(); + u32 ram_size = m_ram->size(); + + if (ram_size == 0x10000) + { + // system has a full 64k + m_maincpu->space(AS_PROGRAM).install_ram(0x2000, 0xffff, m_ram_ptr); + + // install shadow writing to RAM when in ROM mode + m_mem_view[0].install_writeonly(0x0000, 0x1fff, m_ram_ptr + 0xe000); + m_mem_view[1].install_writeonly(0x0000, 0x1fff, m_ram_ptr + 0xe000); + + // Only the CP/M - Org 0 view will have RAM at the lower 8k + m_mem_view[2].install_ram(0x0000, 0x1fff, m_ram_ptr + 0xe000); + } + else + { + // less than 64k + + // for views with ROM visible, the top of memory is 8k higher than + // the memory size, since the base starts at 8k. + u32 ram_top = ram_size + 0x1fff; + + m_mem_view[0].install_ram(0x2000, ram_top, m_ram_ptr); + m_mem_view[1].install_ram(0x2000, ram_top, m_ram_ptr); + + // when ROM is not active, memory still starts at 8k, but is 8k smaller + m_mem_view[2].install_ram(0x2000, ram_size - 1, m_ram_ptr); + + // remap the top 8k down to addr 0 + m_mem_view[2].install_ram(0x0000, 0x1fff, m_ram_ptr + ram_size - 0x2000); + } +} + +void h89_base_state::machine_reset() +{ + m_rom_enabled = true; + m_timer_intr_enabled = true; + m_single_step_enabled = false; + m_floppy_ram_wp = false; + reset_single_step_state(); + + ioport_value const cfg(m_config->read()); + + // CPU clock speed + const u8 selected_clock_upgrade = cfg & 0x3; + + switch (selected_clock_upgrade) + { + case 0x01: + // 4 MHz was offered by several companies including Kres, ANAPRO, and an article + // in REMark magazine. + m_cpu_speed_multiplier = 2; + break; + case 0x02: + // 6 MHz was offered by at least ANAPRO, and a how to article in CHUG newsletter + m_cpu_speed_multiplier = 3; + break; + case 0x00: + default: + // No speed upgrade installed - Standard Clock + m_cpu_speed_multiplier = 1; + break; + } + + update_gpp(0); + update_mem_view(); +} + +u8 h89_base_state::raise_NMI_r() +{ + m_maincpu->pulse_input_line(INPUT_LINE_NMI, attotime::from_usec(2)); + + return 0x00; +} + +void h89_base_state::raise_NMI_w(u8) +{ + m_maincpu->pulse_input_line(INPUT_LINE_NMI, attotime::from_usec(2)); +} + +void h89_base_state::console_intr(int data) +{ + m_intr_socket->set_irq_level(3, data); +} + +void h89_base_state::reset_line(int data) +{ + if (bool(data)) + { + reset(); + } + m_maincpu->set_input_line(INPUT_LINE_RESET, data); +} + +TIMER_DEVICE_CALLBACK_MEMBER(h89_base_state::h89_irq_timer) +{ + if (m_timer_intr_enabled) + { + m_intr_socket->set_irq_level(1, ASSERT_LINE); + } +} + +void h89_base_state::update_mem_view() +{ + m_mem_view.select(m_rom_enabled ? (m_floppy_ram_wp ? 0 : 1) : 2); +} + +void h89_base_state::reset_single_step_state() +{ + LOGSS("reset_single_step_state\n"); + m_555a_latch = false; + m_555b_latch = false; + m_556b_latch = false; + m_intr_socket->set_irq_level(2, CLEAR_LINE); +} + +// General Purpose Port +// +// Bit OUTPUT +// --------------------- +// 0 Single-step enable +// 1 2 mSec interrupt enable +// 2 Latched bit MEM 1 H on memory exp connector +// 3 Not used +// 4 Latched bit MEM 0 H on memory expansion connector (Commonly used for Speed upgrades) +// 5 ORG-0 (CP/M map) +// 6 Latched bit I/O 0 on I/O exp connector +// 7 Latched bit I/O 1 on I/O exp connector +// +void h89_base_state::update_gpp(u8 gpp) +{ + u8 changed_gpp = gpp ^ m_gpp; + + m_gpp = gpp; + + m_timer_intr_enabled = bool(BIT(m_gpp, GPP_ENABLE_TIMER_INTERRUPT_BIT)); + + if (BIT(changed_gpp, GPP_SINGLE_STEP_BIT)) + { + LOGSS("single step enable: %d\n", BIT(m_gpp, GPP_SINGLE_STEP_BIT)); + m_single_step_enabled = bool(BIT(m_gpp, GPP_SINGLE_STEP_BIT)); + + if (!m_single_step_enabled) + { + reset_single_step_state(); + } + } + + if (BIT(changed_gpp, GPP_DISABLE_ROM_BIT)) + { + m_rom_enabled = BIT(m_gpp, GPP_DISABLE_ROM_BIT) == 0; + + update_mem_view(); + } + + if (BIT(changed_gpp, GPP_SPEED_SELECT_BIT)) + { + m_maincpu->set_clock(BIT(m_gpp, GPP_SPEED_SELECT_BIT) ? + H89_CLOCK * m_cpu_speed_multiplier : H89_CLOCK); + } +} + +// General Purpose Port +void h89_base_state::port_f2_w(u8 data) +{ + update_gpp(data); + + m_intr_socket->set_irq_level(1, CLEAR_LINE); +} + +static void tlb_options(device_slot_interface &device) +{ + device.option_add("heath", HEATH_TLB); + device.option_add("gp19", HEATH_GP19); + device.option_add("imaginator", HEATH_IMAGINATOR); + device.option_add("super19", HEATH_SUPER19); + device.option_add("superset", HEATH_SUPERSET); + device.option_add("ultrarom", HEATH_ULTRA); + device.option_add("watzman", HEATH_WATZ); +} + + +static void sigma_tlb_options(device_slot_interface *device) +{ + device->option_reset(); + device->option_add("igc", HEATH_IGC); + device->option_add("igc_super19", HEATH_IGC_SUPER19); + device->option_add("igc_ultrarom", HEATH_IGC_ULTRA); + device->option_add("igc_watzman", HEATH_IGC_WATZ); + device->set_default_option("igc"); +} + +static void intr_ctrl_options(device_slot_interface &device) +{ + device.option_add("original", HEATH_INTR_CNTRL); + device.option_add("h37", HEATH_Z37_INTR_CNTRL); +} + +void h89_base_state::h89_base(machine_config &config) +{ + config.set_default_layout(layout_h89); + + // basic machine hardware + Z80(config, m_maincpu, H89_CLOCK); + m_maincpu->set_m1_map(&h89_base_state::map_fetch); + m_maincpu->set_memory_map(&h89_base_state::h89_mem); + m_maincpu->set_irq_acknowledge_callback("intr_socket", FUNC(heath_intr_socket::irq_callback)); + + RAM(config, m_ram).set_default_size("64K").set_extra_options("16K,32K,48K").set_default_value(0x00); + + HEATH_INTR_SOCKET(config, m_intr_socket, intr_ctrl_options, nullptr); + m_intr_socket->irq_line_cb().set_inputline(m_maincpu, INPUT_LINE_IRQ0); + + INS8250(config, m_console, INS8250_CLOCK); + m_console->out_int_callback().set(FUNC(h89_base_state::console_intr)); + + HEATH_TLB_CONNECTOR(config, m_tlbc, tlb_options, "heath"); + + // Connect the console port on CPU board to TLB connector + m_console->out_tx_callback().set(m_tlbc, FUNC(heath_tlb_connector::serial_in_w)); + m_console->out_rts_callback().set(m_tlbc, FUNC(heath_tlb_connector::cts_in_w)); + m_console->out_dtr_callback().set(m_tlbc, FUNC(heath_tlb_connector::dsr_in_w)); + m_tlbc->serial_data_callback().set(m_console, FUNC(ins8250_uart_device::rx_w)); + m_tlbc->rts_callback().set(m_console, FUNC(ins8250_uart_device::cts_w)); + m_tlbc->dtr_callback().set(m_console, FUNC(ins8250_uart_device::dsr_w)); + + m_tlbc->reset_cb().set(FUNC(h89_base_state::reset_line)); + + // H-88-3 3-port serial board + INS8250(config, m_serial1, INS8250_CLOCK); + INS8250(config, m_serial2, INS8250_CLOCK); + INS8250(config, m_serial3, INS8250_CLOCK); + + // H89 interrupt interval is 2mSec + TIMER(config, "irq_timer", 0).configure_periodic(FUNC(h89_base_state::h89_irq_timer), attotime::from_msec(2)); +} + +void h88_state::h88(machine_config &config) +{ + h89_base(config); + + m_maincpu->set_io_map(&h88_state::h88_io); + + m_intr_socket->set_default_option("original"); + m_intr_socket->set_fixed(true); + + SOFTWARE_LIST(config, "cass_list").set_original("h88_cass"); + + // H-88-5 Cassette interface board + HEATH_H88_CASS(config, m_cassette, H89_CLOCK); +} + +void h89_state::h89(machine_config &config) +{ + h89_base(config); + + m_maincpu->set_io_map(&h89_state::h89_io); + + m_intr_socket->set_default_option("h37"); + m_intr_socket->set_fixed(true); + + // Z-89-37 Soft-sectored controller + HEATH_Z37_FDC(config, m_h37); + m_h37->drq_cb().set(m_intr_socket, FUNC(heath_intr_socket::set_drq)); + m_h37->irq_cb().set(m_intr_socket, FUNC(heath_intr_socket::set_irq)); + m_h37->block_interrupt_cb().set(m_intr_socket, FUNC(heath_intr_socket::block_interrupts)); +} + +void h89_sigmasoft_state::h89_sigmasoft(machine_config & config) +{ + h89(config); + m_maincpu->set_addrmap(AS_IO, &h89_sigmasoft_state::h89_sigmasoft_io); + + sigma_tlb_options(m_tlbc); + + SIGMASOFT_PARALLEL_PORT(config, m_sigma_parallel); + m_sigma_parallel->ctrl_r_cb().set(m_tlbc, FUNC(heath_tlb_connector::sigma_ctrl_r)); + m_sigma_parallel->video_mem_r_cb().set(m_tlbc, FUNC(heath_tlb_connector::sigma_video_mem_r)); + m_sigma_parallel->video_mem_cb().set(m_tlbc, FUNC(heath_tlb_connector::sigma_video_mem_w)); + m_sigma_parallel->io_lo_cb().set(m_tlbc, FUNC(heath_tlb_connector::sigma_io_lo_addr_w)); + m_sigma_parallel->io_hi_cb().set(m_tlbc, FUNC(heath_tlb_connector::sigma_io_hi_addr_w)); + m_sigma_parallel->window_lo_cb().set(m_tlbc, FUNC(heath_tlb_connector::sigma_window_lo_addr_w)); + m_sigma_parallel->window_hi_cb().set(m_tlbc, FUNC(heath_tlb_connector::sigma_window_hi_addr_w)); + m_sigma_parallel->ctrl_cb().set(m_tlbc, FUNC(heath_tlb_connector::sigma_ctrl_w)); +} + + +ROM_START( h88 ) + ROM_REGION( 0x2000, "maincpu", ROMREGION_ERASEFF ) + + ROM_LOAD( "2716_444-19_h17.u520", 0x1800, 0x0800, CRC(26e80ae3) SHA1(0c0ee95d7cb1a760f924769e10c0db1678f2435c)) + + ROM_LOAD("2716_444-40_mtr88.u518", 0x0000, 0x0800, CRC(093afb79) SHA1(bcc1569ad9da7babf0a4199cab96d8cd59b2dd78)) +ROM_END + +ROM_START( h89 ) + ROM_REGION( 0x2000, "maincpu", ROMREGION_ERASEFF ) + ROM_DEFAULT_BIOS("mtr90") + + ROM_LOAD( "2716_444-19_h17.u520", 0x1800, 0x0800, CRC(26e80ae3) SHA1(0c0ee95d7cb1a760f924769e10c0db1678f2435c)) + + ROM_SYSTEM_BIOS(0, "mtr90", "Zenith Data Systems MTR-90 (444-142)") + ROMX_LOAD("2732_444-142_mtr90.u518", 0x0000, 0x1000, CRC(c4ff47c5) SHA1(d6f3d71ff270a663003ec18a3ed1fa49f627123a), ROM_BIOS(0)) + + ROM_SYSTEM_BIOS(1, "mtr89", "Heath MTR-89 (444-62)") + ROMX_LOAD("2716_444-62_mtr89.u518", 0x0000, 0x0800, CRC(8f507972) SHA1(ac6c6c1344ee4e09fb60d53c85c9b761217fe9dc), ROM_BIOS(1)) + + ROM_SYSTEM_BIOS(2, "mms84b", "Magnolia MicroSystems 444-84B") + ROMX_LOAD("2732_444_84b_mms.u518", 0x0000, 0x1000, CRC(7e75d6f4) SHA1(baf34e036388d1a191197e31f8a93209f04fc58b), ROM_BIOS(2)) + + ROM_SYSTEM_BIOS(3, "kmr-100", "Kres KMR-100 V3.a.02") + ROMX_LOAD("2732_kmr100_v3_a_02.u518", 0x0000, 0x1000, CRC(fd491592) SHA1(3d5803f95c38b237b07cd230353cd9ddc9858c13), ROM_BIOS(3)) + + ROM_SYSTEM_BIOS(4, "mtrhex_4k", "Ultimeth 4k ROM") + ROMX_LOAD("2732_mtrhex_4k.u518", 0x0000, 0x1000, CRC(e26b29a9) SHA1(ba13d6c9deef682a9a8262bc910d46b577929a13), ROM_BIOS(4)) + + ROM_SYSTEM_BIOS(5, "mtr90-84", "Zenith Data Systems MTR-90 (444-84 - Superseded by 444-142)") + ROMX_LOAD("2732_444-84_mtr90.u518", 0x0000, 0x1000, CRC(f10fca03) SHA1(c4a978153af0f2dfcc9ba05be4c1033d33fee30b), ROM_BIOS(5)) + + ROM_SYSTEM_BIOS(6, "mms84a", "Magnolia MicroSystems 444-84A (Superseded by MMS 444-84B)") + ROMX_LOAD("2732_444_84a_mms.u518", 0x0000, 0x1000, CRC(0e541a7e) SHA1(b1deb620fc89c1068e2e663e14be69d1f337a4b9), ROM_BIOS(6)) + + ROM_SYSTEM_BIOS(7, "mtrhex", "Ultimeth 2k ROM") + ROMX_LOAD("2716_mtrhex.u518", 0x0000, 0x0800, CRC(842a306a) SHA1(ddbc2b8bb127464af9eda8e7c56e6be7c8b43a16), ROM_BIOS(7)) +ROM_END + +ROM_START( h89_sigmasoft ) + ROM_REGION( 0x2000, "maincpu", ROMREGION_ERASEFF ) + ROM_DEFAULT_BIOS("mtr90") + + ROM_LOAD( "2716_444-19_h17.u520", 0x1800, 0x0800, CRC(26e80ae3) SHA1(0c0ee95d7cb1a760f924769e10c0db1678f2435c)) + + ROM_SYSTEM_BIOS(0, "mtr90", "Zenith Data Systems MTR-90 (444-142)") + ROMX_LOAD("2732_444-142_mtr90.u518", 0x0000, 0x1000, CRC(c4ff47c5) SHA1(d6f3d71ff270a663003ec18a3ed1fa49f627123a), ROM_BIOS(0)) + + ROM_SYSTEM_BIOS(1, "mtr89", "Heath MTR-89 (444-62)") + ROMX_LOAD("2716_444-62_mtr89.u518", 0x0000, 0x0800, CRC(8f507972) SHA1(ac6c6c1344ee4e09fb60d53c85c9b761217fe9dc), ROM_BIOS(1)) + + ROM_SYSTEM_BIOS(2, "mms84b", "Magnolia MicroSystems 444-84B") + ROMX_LOAD("2732_444_84b_mms.u518", 0x0000, 0x1000, CRC(7e75d6f4) SHA1(baf34e036388d1a191197e31f8a93209f04fc58b), ROM_BIOS(2)) + + ROM_SYSTEM_BIOS(3, "kmr-100", "Kres KMR-100 V3.a.02") + ROMX_LOAD("2732_kmr100_v3_a_02.u518", 0x0000, 0x1000, CRC(fd491592) SHA1(3d5803f95c38b237b07cd230353cd9ddc9858c13), ROM_BIOS(3)) + + ROM_SYSTEM_BIOS(4, "mtrhex_4k", "Ultimeth 4k ROM") + ROMX_LOAD("2732_mtrhex_4k.u518", 0x0000, 0x1000, CRC(e26b29a9) SHA1(ba13d6c9deef682a9a8262bc910d46b577929a13), ROM_BIOS(4)) + + ROM_SYSTEM_BIOS(5, "mtr90-84", "Zenith Data Systems MTR-90 (444-84 - Superseded by 444-142)") + ROMX_LOAD("2732_444-84_mtr90.u518", 0x0000, 0x1000, CRC(f10fca03) SHA1(c4a978153af0f2dfcc9ba05be4c1033d33fee30b), ROM_BIOS(5)) + + ROM_SYSTEM_BIOS(6, "mms84a", "Magnolia MicroSystems 444-84A (Superseded by MMS 444-84B)") + ROMX_LOAD("2732_444_84a_mms.u518", 0x0000, 0x1000, CRC(0e541a7e) SHA1(b1deb620fc89c1068e2e663e14be69d1f337a4b9), ROM_BIOS(6)) + + ROM_SYSTEM_BIOS(7, "mtrhex", "Ultimeth 2k ROM") + ROMX_LOAD("2716_mtrhex.u518", 0x0000, 0x0800, CRC(842a306a) SHA1(ddbc2b8bb127464af9eda8e7c56e6be7c8b43a16), ROM_BIOS(7)) +ROM_END + +ROM_START( z90 ) + ROM_REGION( 0x2000, "maincpu", ROMREGION_ERASEFF ) + ROM_DEFAULT_BIOS("mtr90") + + ROM_LOAD( "2716_444-19_h17.u520", 0x1800, 0x0800, CRC(26e80ae3) SHA1(0c0ee95d7cb1a760f924769e10c0db1678f2435c)) + + ROM_SYSTEM_BIOS(0, "mtr90", "Zenith Data Systems MTR-90 (444-142)") + ROMX_LOAD("2732_444-142_mtr90.u518", 0x0000, 0x1000, CRC(c4ff47c5) SHA1(d6f3d71ff270a663003ec18a3ed1fa49f627123a), ROM_BIOS(0)) + + ROM_SYSTEM_BIOS(1, "mms84b", "Magnolia MicroSystems 444-84B") + ROMX_LOAD("2732_444_84b_mms.u518", 0x0000, 0x1000, CRC(7e75d6f4) SHA1(baf34e036388d1a191197e31f8a93209f04fc58b), ROM_BIOS(1)) + + ROM_SYSTEM_BIOS(2, "kmr-100", "Kres KMR-100 V3.a.02") + ROMX_LOAD("2732_kmr100_v3_a_02.u518", 0x0000, 0x1000, CRC(fd491592) SHA1(3d5803f95c38b237b07cd230353cd9ddc9858c13), ROM_BIOS(2)) + + ROM_SYSTEM_BIOS(3, "mtrhex_4k", "Ultimeth 4k ROM") + ROMX_LOAD("2732_mtrhex_4k.u518", 0x0000, 0x1000, CRC(e26b29a9) SHA1(ba13d6c9deef682a9a8262bc910d46b577929a13), ROM_BIOS(3)) + + ROM_SYSTEM_BIOS(4, "mtr90-84", "Zenith Data Systems MTR-90 (444-84 - Superseded by 444-142)") + ROMX_LOAD("2732_444-84_mtr90.u518", 0x0000, 0x1000, CRC(f10fca03) SHA1(c4a978153af0f2dfcc9ba05be4c1033d33fee30b), ROM_BIOS(4)) + + ROM_SYSTEM_BIOS(5, "mms84a", "Magnolia MicroSystems 444-84A (Superseded by MMS 444-84B)") + ROMX_LOAD("2732_444_84a_mms.u518", 0x0000, 0x1000, CRC(0e541a7e) SHA1(b1deb620fc89c1068e2e663e14be69d1f337a4b9), ROM_BIOS(5)) +ROM_END + +} // anonymous namespace + + +// year name parent compat machine input class init company fullname flags +COMP( 1979, h88, h89, 0, h88, h88, h88_state, empty_init, "Heath Company", "H-88", MACHINE_SUPPORTS_SAVE) +COMP( 1979, h89, 0, 0, h89, h89, h89_state, empty_init, "Heath Company", "H-89", MACHINE_SUPPORTS_SAVE) +COMP( 1981, z90, h89, 0, h89, h89, h89_state, empty_init, "Zenith Data Systems", "Z-90", MACHINE_SUPPORTS_SAVE) +COMP( 1984, h89_sigmasoft, h89, 0, h89_sigmasoft, h89, h89_sigmasoft_state, empty_init, "Heath Company", "H-89 with SigmaSoft IGC", MACHINE_SUPPORTS_SAVE) diff --git a/src/mame/heathzenith/h_88_cass.cpp b/src/mame/heathzenith/h_88_cass.cpp new file mode 100644 index 00000000000..e67b72a4a7b --- /dev/null +++ b/src/mame/heathzenith/h_88_cass.cpp @@ -0,0 +1,166 @@ +// license:BSD-3-Clause +// copyright-holders:Mark Garlanger +/*************************************************************************** + + Heathkit H-88-5 Cassette Interface Card + + Came standard on the H88 computer and was on option for other H89 class + systems. + +****************************************************************************/ + +#include "emu.h" + +#include "h_88_cass.h" + +#include "machine/clock.h" + +#include "speaker.h" + +#define LOG_REG (1U << 1) +#define LOG_LINES (1U << 2) +#define LOG_CASS (1U << 3) +#define LOG_FUNC (1U << 4) +//#define VERBOSE (0xff) + +#include "logmacro.h" + +#define LOGREG(...) LOGMASKED(LOG_REG, __VA_ARGS__) +#define LOGLINES(...) LOGMASKED(LOG_LINES, __VA_ARGS__) +#define LOGCASS(...) LOGMASKED(LOG_CASS, __VA_ARGS__) +#define LOGFUNC(...) LOGMASKED(LOG_FUNC, __VA_ARGS__) + +#ifdef _MSC_VER +#define FUNCNAME __func__ +#else +#define FUNCNAME __PRETTY_FUNCTION__ +#endif + +DEFINE_DEVICE_TYPE(HEATH_H88_CASS, heath_h_88_cass_device, "heath_h_88_cass_device", "Heath H-88-5 Cassette Interface"); + +heath_h_88_cass_device::heath_h_88_cass_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock): + device_t(mconfig, HEATH_H88_CASS, tag, owner, 0), + m_uart(*this, "uart"), + m_cass_player(*this, "cassette_player"), + m_cass_recorder(*this, "cassette_recorder") +{ +} + +void heath_h_88_cass_device::write(offs_t reg, u8 val) +{ + LOGREG("%s: reg: %d val: 0x%02x\n", FUNCNAME, reg, val); + + m_uart->write(reg, val); +} + +u8 heath_h_88_cass_device::read(offs_t reg) +{ + u8 val = m_uart->read(reg); + + LOGREG("%s: reg: %d val: 0x%02x\n", FUNCNAME, reg, val); + + return val; +} + +TIMER_DEVICE_CALLBACK_MEMBER(heath_h_88_cass_device::kansas_w) +{ + m_cass_data[3]++; + + if (m_cassbit != m_cassold) + { + LOGCASS("%s: m_cassbit changed : %d\n", FUNCNAME, m_cassbit); + m_cass_data[3] = 0; + m_cassold = m_cassbit; + } + + LOGCASS("%s: m_cassbit: %d\n", FUNCNAME, m_cassbit); + // 2400Hz -> 0 + // 1200Hz -> 1 + const int bit_pos = m_cassbit ? 0 : 1; + + m_cass_recorder->output(BIT(m_cass_data[3], bit_pos) ? -1.0 : +1.0); +} + +TIMER_DEVICE_CALLBACK_MEMBER(heath_h_88_cass_device::kansas_r) +{ + // cassette - turn 1200/2400Hz to a bit + m_cass_data[1]++; + u8 cass_ws = (m_cass_player->input() > +0.03) ? 1 : 0; + + LOGCASS("%s: cass_ws: %d\n", FUNCNAME, cass_ws); + + if (cass_ws != m_cass_data[0]) + { + LOGCASS("%s: cass_ws has changed value\n", FUNCNAME); + m_cass_data[0] = cass_ws; + m_uart->write_rxd((m_cass_data[1] < 12) ? 1 : 0); + m_cass_data[1] = 0; + } +} + +void heath_h_88_cass_device::uart_rts(u8 data) +{ + LOGLINES("%s: data: %d\n", FUNCNAME, data); + + m_cass_player->change_state(bool(data) ? CASSETTE_STOPPED : CASSETTE_PLAY, CASSETTE_MASK_UISTATE); +} + +void heath_h_88_cass_device::uart_tx_empty(u8 data) +{ + LOGLINES("%s: data: %d\n", FUNCNAME, data); + + m_cass_recorder->change_state(bool(data) ? CASSETTE_STOPPED : CASSETTE_RECORD, CASSETTE_MASK_UISTATE); +} + +void heath_h_88_cass_device::device_start() +{ + save_item(NAME(m_cass_data)); + save_item(NAME(m_cassbit)); + save_item(NAME(m_cassold)); +} + +void heath_h_88_cass_device::device_reset() +{ + LOGFUNC("%s\n", FUNCNAME); + + // cassette + m_cassbit = 1; + m_cassold = 0; + m_cass_data[0] = 0; + m_cass_data[1] = 0; + m_cass_data[2] = 0; + m_cass_data[3] = 0; + + m_uart->write_cts(0); + m_uart->write_dsr(0); + m_uart->write_rxd(0); +} + +void heath_h_88_cass_device::device_add_mconfig(machine_config &config) +{ + I8251(config, m_uart, 0); + m_uart->txd_handler().set([this] (bool state) { m_cassbit = state; }); + m_uart->rts_handler().set(FUNC(heath_h_88_cass_device::uart_rts)); + m_uart->txempty_handler().set(FUNC(heath_h_88_cass_device::uart_tx_empty)); + + clock_device &cassette_clock(CLOCK(config, "cassette_clock", 4800)); + cassette_clock.signal_handler().set(m_uart, FUNC(i8251_device::write_txc)); + cassette_clock.signal_handler().append(m_uart, FUNC(i8251_device::write_rxc)); + + SPEAKER(config, "mono").front_right(); + + CASSETTE(config, m_cass_player); + m_cass_player->set_formats(h8_cassette_formats); + m_cass_player->set_default_state(CASSETTE_STOPPED | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_ENABLED); + m_cass_player->add_route(ALL_OUTPUTS, "mono", 0.15); + m_cass_player->set_interface("h88_cass_player"); + + CASSETTE(config, m_cass_recorder); + m_cass_recorder->set_formats(h8_cassette_formats); + m_cass_recorder->set_default_state(CASSETTE_STOPPED | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_ENABLED); + m_cass_recorder->add_route(ALL_OUTPUTS, "mono", 0.15); + m_cass_recorder->set_interface("h88_cass_recorder"); + + TIMER(config, "kansas_w").configure_periodic(FUNC(heath_h_88_cass_device::kansas_w), attotime::from_hz(4800)); + TIMER(config, "kansas_r").configure_periodic(FUNC(heath_h_88_cass_device::kansas_r), attotime::from_hz(40000)); +} diff --git a/src/mame/heathzenith/h_88_cass.h b/src/mame/heathzenith/h_88_cass.h new file mode 100644 index 00000000000..f3a7a22196f --- /dev/null +++ b/src/mame/heathzenith/h_88_cass.h @@ -0,0 +1,53 @@ +// license:BSD-3-Clause +// copyright-holders:Mark Garlanger +/*************************************************************************** + + Heathkit H-88-5 Cassette Interface card + +****************************************************************************/ + +#ifndef MAME_HEATHKIT_H_88_CASS_H +#define MAME_HEATHKIT_H_88_CASS_H + +#pragma once + +#include "imagedev/cassette.h" +#include "machine/i8251.h" +#include "machine/timer.h" + +#include "formats/h8_cas.h" + + +class heath_h_88_cass_device : public device_t +{ +public: + heath_h_88_cass_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + + void write(offs_t reg, u8 val); + u8 read(offs_t reg); + +protected: + + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_add_mconfig(machine_config &config) override; + + void uart_rts(u8 data); + void uart_tx_empty(u8 data); + + TIMER_DEVICE_CALLBACK_MEMBER(kansas_r); + TIMER_DEVICE_CALLBACK_MEMBER(kansas_w); + + required_device m_uart; + required_device m_cass_player; + required_device m_cass_recorder; + + u8 m_cass_data[4]; + bool m_cassbit; + bool m_cassold; +}; + +DECLARE_DEVICE_TYPE(HEATH_H88_CASS, heath_h_88_cass_device) + + +#endif // MAME_HEATHKIT_H_88_CASS_H diff --git a/src/mame/heathzenith/intr_cntrl.cpp b/src/mame/heathzenith/intr_cntrl.cpp new file mode 100644 index 00000000000..2ebb46701da --- /dev/null +++ b/src/mame/heathzenith/intr_cntrl.cpp @@ -0,0 +1,222 @@ +// license:BSD-3-Clause +// copyright-holders:Mark Garlanger +/*************************************************************************** + + Heathkit Interrupt controller for H89 + +****************************************************************************/ + +#include "emu.h" + +#include "intr_cntrl.h" + +DEFINE_DEVICE_TYPE(HEATH_INTR_CNTRL, heath_intr_cntrl, "heath_intr_cntrl", "Heath H/Z-89 Interrupt Controller"); +DEFINE_DEVICE_TYPE(HEATH_Z37_INTR_CNTRL, z37_intr_cntrl, "heath_z37_intr_cntrl", "Heath H/Z-89 with Z-37 Interrupt Controller"); + +DEFINE_DEVICE_TYPE(HEATH_INTR_SOCKET, heath_intr_socket, "heath_intr_socket", "Heath Interrupt Socket"); + +/** + * Heath interrupt interface + */ +device_heath_intr_interface::device_heath_intr_interface(const machine_config &mconfig, device_t &device) : + device_interface(device, "heathintrdevice"), + m_socket(dynamic_cast(device.owner())) +{ +} + +/** + * Original Heath interrrupt controller + * + */ +heath_intr_cntrl::heath_intr_cntrl(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock): + heath_intr_cntrl(mconfig, HEATH_INTR_CNTRL, tag, owner, clock) +{ +} + +heath_intr_cntrl::heath_intr_cntrl(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock): + device_t(mconfig, type, tag, owner, 0), + device_heath_intr_interface(mconfig, *this) +{ +} + +void heath_intr_cntrl::device_start() +{ + save_item(NAME(m_intr_lines)); + + m_intr_lines = 0; +} + +void heath_intr_cntrl::update_intr_line() +{ + if (m_socket) + { + m_socket->raise_irq((m_intr_lines == 0) ? 0 : 1); + } +} + +void heath_intr_cntrl::set_irq_level(u8 level, int data) +{ + // only 0 to 7 is valid + level &= 0x7; + + if (data == 0) + { + m_intr_lines &= ~(1 << level); + } + else + { + m_intr_lines |= 1 << level; + } + + update_intr_line(); +} + +u8 heath_intr_cntrl::get_instruction() +{ + + // determine top priority instruction + if (!m_intr_lines) + { + // should not occur. + // NO-OP ? + logerror("get instruct: bad m_intr_lines\n"); + + return 0x00; + } + + // ideally this would be handled with a function like ffs() + u8 level = 0; + u8 mask = 0x01; + + while (mask) + { + if (m_intr_lines & mask) + { + break; + } + level++; + mask <<= 1; + } + + if (level > 7) + { + logerror("bad level: %d\n", level); + } + + // return RST based on level + return 0xc7 | ((level & 0x7) << 3); +} + +/** + * Interrupt controller for the Z37 soft-sectored controller. + * + * It will take control of the interrupt system and block all other + * interrupts while it is waiting for Z37 events. + */ +z37_intr_cntrl::z37_intr_cntrl(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock): + heath_intr_cntrl(mconfig, HEATH_Z37_INTR_CNTRL, tag, owner, clock) +{ +} + +void z37_intr_cntrl::update_intr_line() +{ + m_socket->raise_irq( + (m_irq_raised || m_drq_raised || + (!m_intr_blocked && (m_intr_lines != 0))) ? 1 : 0); +} + +u8 z37_intr_cntrl::get_instruction() +{ + + if (m_drq_raised) + { + // EI + return 0xfb; + } + + if (m_irq_raised) + { + // RST 20H (Interrupt 4) + return 0xe7; + } + + if (!m_intr_blocked) + { + return heath_intr_cntrl::get_instruction(); + } + + // shouldn't get here - NO-OP? + logerror("Warning: z37 intr get_instruction: fd: %d dr: %d ib: %d\n", m_irq_raised, m_drq_raised, m_intr_blocked); + return 0x00; +} + +void z37_intr_cntrl::set_drq(int state) +{ + m_drq_raised = bool(state); + + update_intr_line(); +} + + +void z37_intr_cntrl::set_irq(int state) +{ + m_irq_raised = bool(state); + + update_intr_line(); +} + +void z37_intr_cntrl::device_start() +{ + heath_intr_cntrl::device_start(); + + save_item(NAME(m_intr_blocked)); + save_item(NAME(m_drq_raised)); + save_item(NAME(m_irq_raised)); + + m_intr_blocked = false; + m_drq_raised = false; + m_irq_raised = false; +} + +void z37_intr_cntrl::block_interrupts(u8 data) +{ + m_intr_blocked = bool(data); + + update_intr_line(); +} + + +/** + * Heath Interrupt socket + * + * Allows choice of interrupt controllers for Heath 8-bit computers. + */ +heath_intr_socket::heath_intr_socket(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + device_t(mconfig, HEATH_INTR_SOCKET, tag, owner, clock), + device_single_card_slot_interface(mconfig, *this), + m_irq_line(*this), + m_cntrl(nullptr) +{ +} + +heath_intr_socket::~heath_intr_socket() +{ +} + +void heath_intr_socket::device_start() +{ + m_cntrl = get_card_device(); +} + +IRQ_CALLBACK_MEMBER(heath_intr_socket::irq_callback) +{ + // assume NO-OP + u8 instr = 0x00; + + if (m_cntrl) + { + instr = m_cntrl->get_instruction(); + } + + return instr; +} diff --git a/src/mame/heathzenith/intr_cntrl.h b/src/mame/heathzenith/intr_cntrl.h new file mode 100644 index 00000000000..b5fc10cbf82 --- /dev/null +++ b/src/mame/heathzenith/intr_cntrl.h @@ -0,0 +1,133 @@ +// license:BSD-3-Clause +// copyright-holders:Mark Garlanger +/*************************************************************************** + + Heathkit Interrupt Controllers + + Interrupt controllers for the Heath H89. + +****************************************************************************/ + +#ifndef MAME_HEATHKIT_INTR_CNTRL_H +#define MAME_HEATHKIT_INTR_CNTRL_H + +#pragma once + +class heath_intr_socket; + +class device_heath_intr_interface : public device_interface +{ +public: + virtual void set_irq_level(u8 level, int state) = 0; + + virtual void set_drq(int state) {} + virtual void set_irq(int state) {} + virtual void block_interrupts(u8 data) {} + +protected: + device_heath_intr_interface(const machine_config &mconfig, device_t &device); + + virtual u8 get_instruction() = 0; + + heath_intr_socket *const m_socket; + + friend heath_intr_socket; +}; + + +/** + * Heath original interrupt controller + * + */ +class heath_intr_cntrl : public device_t, + public device_heath_intr_interface +{ +public: + heath_intr_cntrl(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + + virtual void set_irq_level(u8 level, int state) override; + +protected: + heath_intr_cntrl(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock = 0); + + virtual u8 get_instruction() override; + virtual void update_intr_line(); + + virtual void device_start() override; + + u8 m_intr_lines; +}; + +/** + * Interrupt controller when the Z37 soft-sectored controller is installed. + * + */ +class z37_intr_cntrl : public heath_intr_cntrl +{ +public: + z37_intr_cntrl(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + + virtual void set_drq(int state) override; + virtual void set_irq(int state) override; + virtual void block_interrupts(u8 data) override; + +protected: + virtual u8 get_instruction() override; + virtual void update_intr_line() override; + + virtual void device_start() override; + +private: + bool m_intr_blocked; + bool m_drq_raised; + bool m_irq_raised; +}; + +DECLARE_DEVICE_TYPE(HEATH_INTR_CNTRL, heath_intr_cntrl) +DECLARE_DEVICE_TYPE(HEATH_Z37_INTR_CNTRL, z37_intr_cntrl) + + +class heath_intr_socket : public device_t, + public device_single_card_slot_interface +{ +public: + + template + heath_intr_socket(const machine_config &mconfig, const char *tag, device_t *owner, T &&opts, const char *dflt, bool fixed = false) : + heath_intr_socket(mconfig, tag, owner, 0) + { + option_reset(); + opts(*this); + set_default_option(dflt); + set_fixed(fixed); + } + + heath_intr_socket(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + virtual ~heath_intr_socket(); + + auto irq_line_cb() { return m_irq_line.bind(); } + + // required operation + void set_irq_level(u8 level, int state) { if (m_cntrl) { m_cntrl->set_irq_level(level, state); }} + + IRQ_CALLBACK_MEMBER(irq_callback); + + void raise_irq(int state) { m_irq_line(state); } + + void set_irq(int state) { if (m_cntrl) { m_cntrl->set_irq(state); } } + void set_drq(int state) { if (m_cntrl) { m_cntrl->set_drq(state); } } + void block_interrupts(u8 data) { if (m_cntrl) { m_cntrl->block_interrupts(data); } } + +protected: + + virtual void device_start() override; + + devcb_write8 m_irq_line; + + device_heath_intr_interface *m_cntrl; +}; + + +DECLARE_DEVICE_TYPE(HEATH_INTR_SOCKET, heath_intr_socket) + +#endif // MAME_HEATHKIT_H89_INTR_CNTRL_H diff --git a/src/mame/heathzenith/mdt60.cpp b/src/mame/heathzenith/mdt60.cpp new file mode 100644 index 00000000000..039ee3f02b0 --- /dev/null +++ b/src/mame/heathzenith/mdt60.cpp @@ -0,0 +1,269 @@ +// license:BSD-3-Clause +// copyright-holders:AJR +/************************************************************************** + + 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 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/i8251.h" +#include "video/mc6845.h" +#include "screen.h" + + +namespace { + +class mdt60_state : public driver_device +{ +public: + 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") + , m_charrom(*this, "charrom") + , m_attrram(*this, "attrram") + , m_dip0(*this, "DIP0") + , m_baud_timer(nullptr) + , m_keyin(false) + , m_output_reg(0x3f) + , m_timer_output(false) + { + } + + void mdt60(machine_config &mconfig); + +protected: + virtual void machine_start() override; + virtual void machine_reset() override; + +private: + MC6845_UPDATE_ROW(update_row); + MC6845_ON_UPDATE_ADDR_CHANGED(update_cb); + TIMER_CALLBACK_MEMBER(baud_timer); + + void keyin_w(int state); + u8 dip0_r(offs_t offset); + void reg_w(u8 data); + + void mem_map(address_map &map); + + required_device m_maincpu; + required_device m_keyboard; + required_device m_crtc; + optional_device_array m_uart; + required_shared_ptr m_charram; + required_region_ptr m_charrom; + required_shared_ptr m_attrram; + required_ioport m_dip0; + + emu_timer *m_baud_timer; + + bool m_keyin; + u8 m_output_reg; + bool m_timer_output; +}; + +void mdt60_state::machine_start() +{ + m_baud_timer = timer_alloc(FUNC(mdt60_state::baud_timer), this); + m_baud_timer->adjust(attotime::zero); + + save_item(NAME(m_keyin)); + save_item(NAME(m_output_reg)); + save_item(NAME(m_timer_output)); +} + +void mdt60_state::machine_reset() +{ + reg_w(0); +} + + +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.pix(y); + + for (unsigned x = 0; x < x_count; x++) + { + u8 cdata = m_charram[(ma + x) & 0x7ff]; + u8 adata = m_attrram[(ma + x) & 0x3ff] >> (BIT(ma + x, 10) ? 4 : 0); + u16 dots = m_charrom[cdata << 4 | ra] << 1 | BIT(adata, 3); + + if (x == cursor_x) + dots = ~dots; + if (BIT(adata, 2)) + dots = ~dots; + if (BIT(adata, 0) && (ra & 0xb) == 0xa) + dots = ~dots; + + rgb_t fg = BIT(adata, 1) ? rgb_t::white() : rgb_t(0xc0, 0xc0, 0xc0); + rgb_t bg = rgb_t::black(); + if (BIT(m_output_reg, 5)) + std::swap(fg, bg); + + for (int n = 8; n >= 0; n--) + *pix++ = BIT(dots, n) ? fg : bg; + } +} + +MC6845_ON_UPDATE_ADDR_CHANGED(mdt60_state::update_cb) +{ +} + + +void mdt60_state::keyin_w(int state) +{ + m_keyin = state; + m_maincpu->set_input_line(m6502_device::IRQ_LINE, state ? ASSERT_LINE : CLEAR_LINE); +} + +u8 mdt60_state::dip0_r(offs_t offset) +{ + u8 buffer = 0xff; + if (!BIT(offset, 0)) + buffer &= m_dip0->read() >> 1 | 0x80; + if (!BIT(offset, 1)) + buffer &= m_dip0->read() | 0xfe; + if (!m_keyin) + buffer &= 0x7f; + return buffer; +} + +void mdt60_state::reg_w(u8 data) +{ + if (BIT(data, 0) != BIT(m_output_reg, 0)) + m_keyboard->keyout_w(BIT(data, 0)); + + // 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) +{ + map(0x0000, 0x03ff).mirror(0x1800).ram(); + map(0x0400, 0x07ff).mirror(0x1800).ram().share("attrram"); + map(0x2000, 0x27ff).mirror(0x1800).ram().share("charram"); + map(0x4000, 0x4000).mirror(0x1ffe).rw(m_crtc, FUNC(r6545_1_device::status_r), FUNC(r6545_1_device::address_w)); + map(0x4001, 0x4001).mirror(0x1ffe).rw(m_crtc, FUNC(r6545_1_device::register_r), FUNC(r6545_1_device::register_w)); + map(0x6000, 0x6001).mirror(0x1ffe).rw(m_uart[0], FUNC(i8251_device::read), FUNC(i8251_device::write)); + //map(0x8000, 0x8001).mirror(0x1ffe).rw(m_uart[1], FUNC(i8251_device::read), FUNC(i8251_device::write)); + map(0xa000, 0xa003).mirror(0x1ffc).r(FUNC(mdt60_state::dip0_r)); + map(0xa000, 0xa000).mirror(0x1fff).w(FUNC(mdt60_state::reg_w)); + //map(0xc000, 0xc000).mirror(0x1fff).portr("DIP1"); + map(0xe000, 0xefff).mirror(0x1000).rom().region("coderom", 0); +} + + +static INPUT_PORTS_START(mdt60) + PORT_START("DIP0") + PORT_DIPNAME(0x03, 0x01, "Baud Rate") PORT_DIPLOCATION("SW1:1,2") + PORT_DIPSETTING(0x03, "300") + PORT_DIPSETTING(0x02, "1200") + PORT_DIPSETTING(0x01, "9600") + PORT_DIPSETTING(0x00, "19200") + PORT_DIPNAME(0x0c, 0x00, "Parity") PORT_DIPLOCATION("SW1:3,4") + PORT_DIPSETTING(0x04, "Odd") + PORT_DIPSETTING(0x0c, "Even") + PORT_DIPSETTING(0x00, "Mark") + PORT_DIPSETTING(0x08, "Space") + PORT_DIPNAME(0x70, 0x00, "Character Set") PORT_DIPLOCATION("SW1:5,6,7") + PORT_DIPSETTING(0x00, "U.S.") + PORT_DIPSETTING(0x10, "U.K.") + PORT_DIPSETTING(0x20, "French") + PORT_DIPSETTING(0x30, "German") + PORT_DIPSETTING(0x40, "Spanish") + PORT_DIPSETTING(0x50, "Danish/Norwegian") + PORT_DIPSETTING(0x60, "Swedish/Finnish") + PORT_DIPSETTING(0x70, "Italian") + PORT_DIPNAME(0x80, 0x80, "Function Key Sequence Type") PORT_DIPLOCATION("SW1:8") + PORT_DIPSETTING(0x80, "Morrow (FS)") + PORT_DIPSETTING(0x00, "TeleVideo (SOH...CR)") + + PORT_START("DIP1") + PORT_BIT(0xff, 0xff, IPT_UNUSED) // SW2 is unpopulated (as is LS244 at U20) +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. + +void mdt60_state::mdt60(machine_config &config) +{ + M6512(config, m_maincpu, 16.5888_MHz_XTAL / 9); // R6512AP + m_maincpu->set_addrmap(AS_PROGRAM, &mdt60_state::mem_map); + + 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("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)); + + // UART 1 (at U28) is unpopulated and not used by code + + Z29_KEYBOARD(config, m_keyboard, z29_keyboards, "md"); + m_keyboard->keyin_callback().set(FUNC(mdt60_state::keyin_w)).invert(); + // Reset output (pin 2) is not connected + + 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)); + // LPEN is tied to GND (code uses this to determine CRTC type) + + 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)); +} + + +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 + +} // anonymous namespace + + +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/heathzenith/sigmasoft_parallel_port.cpp b/src/mame/heathzenith/sigmasoft_parallel_port.cpp new file mode 100644 index 00000000000..a412f204245 --- /dev/null +++ b/src/mame/heathzenith/sigmasoft_parallel_port.cpp @@ -0,0 +1,165 @@ +// license:BSD-3-Clause +// copyright-holders:Mark Garlanger +/*************************************************************************** + + SigmaSoft Universal Parallel Interface Board + + +****************************************************************************/ + +#include "emu.h" + +#include "sigmasoft_parallel_port.h" + +// +// Logging defines +// +#define LOG_REG (1U << 1) // Shows register setup +#define LOG_FUNC (1U << 2) // Function calls + +#define VERBOSE (0) + +#include "logmacro.h" + +#define LOGREG(...) LOGMASKED(LOG_REG, __VA_ARGS__) +#define LOGFUNC(...) LOGMASKED(LOG_FUNC, __VA_ARGS__) + +#ifdef _MSC_VER +#define FUNCNAME __func__ +#else +#define FUNCNAME __PRETTY_FUNCTION__ +#endif + + +DEFINE_DEVICE_TYPE(SIGMASOFT_PARALLEL_PORT, sigmasoft_parallel_port, "sigmasoft_parallel_port", "SigmaSoft Universal Parallel Board"); + +sigmasoft_parallel_port::sigmasoft_parallel_port(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock): + device_t(mconfig, SIGMASOFT_PARALLEL_PORT, tag, owner, clock), + m_ctrl_r(*this, 0x00), + m_video_mem_r(*this, 0x00), + m_video_mem_w(*this), + m_io_lo_addr(*this), + m_io_hi_addr(*this), + m_window_lo_addr(*this), + m_window_hi_addr(*this), + m_ctrl_w(*this) +{ +} + +void sigmasoft_parallel_port::video_mem_w(u8 val) +{ + m_video_mem_w(val); +} + +void sigmasoft_parallel_port::io_lo_addr_w(u8 val) +{ + m_io_lo_addr(val); +} + +void sigmasoft_parallel_port::io_hi_addr_w(u8 val) +{ + m_io_hi_addr(val); +} + +void sigmasoft_parallel_port::window_lo_addr_w(u8 val) +{ + m_window_lo_addr(val); +} + +void sigmasoft_parallel_port::window_hi_addr_w(u8 val) +{ + m_window_hi_addr(val); +} + +void sigmasoft_parallel_port::ctrl_w(u8 val) +{ + m_ctrl_w(val); +} + +void sigmasoft_parallel_port::write(offs_t reg, u8 val) +{ + LOGFUNC("%s: reg: %d val: %d\n", FUNCNAME, reg, val); + + switch (reg) + { + case 0: + video_mem_w(val); + break; + case 1: + io_lo_addr_w(val); + break; + case 2: + io_hi_addr_w(val); + break; + case 3: + window_lo_addr_w(val); + break; + case 4: + window_hi_addr_w(val); + break; + case 5: + ctrl_w(val); + break; + case 6: + // TODO - Centronics interface + break; + case 7: + // TODO - Centronics interface + break; + } +} + +u8 sigmasoft_parallel_port::video_mem_r() +{ + // get video memory value from igc device + return m_video_mem_r(); +} + +u8 sigmasoft_parallel_port::ctrl_r() +{ + // get control register from igc device + return m_ctrl_r(); +} + +u8 sigmasoft_parallel_port::read(offs_t reg) +{ + // default return for the h89 + u8 value = 0xff; + + switch (reg) + { + case 0: + value = video_mem_r(); + break; + case 1: + // TODO - Light Pen Low address + break; + case 2: + // TODO - Light Pen High address + break; + case 3: + // TODO - Left input device + break; + case 4: + // TODO - Right input device + break; + case 5: + // Control Register + value = ctrl_r(); + break; + case 6: + // TODO - Centronics interface + break; + case 7: + // TODO - Centronics interface + break; + } + + LOGFUNC("%s: reg: %d val: %d\n", FUNCNAME, reg, value); + + return value; +} + +void sigmasoft_parallel_port::device_start() +{ +} diff --git a/src/mame/heathzenith/sigmasoft_parallel_port.h b/src/mame/heathzenith/sigmasoft_parallel_port.h new file mode 100644 index 00000000000..15837bf577b --- /dev/null +++ b/src/mame/heathzenith/sigmasoft_parallel_port.h @@ -0,0 +1,67 @@ +// license:BSD-3-Clause +// copyright-holders:Mark Garlanger +/*************************************************************************** + + SigmaSoft Universal Parallel Interface Board + +****************************************************************************/ + +#ifndef MAME_HEATHKIT_SIGMASOFT_PARALLEL_PORT_H +#define MAME_HEATHKIT_SIGMASOFT_PARALLEL_PORT_H + +#pragma once + + +class sigmasoft_parallel_port : public device_t +{ +public: + sigmasoft_parallel_port(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + + void write(offs_t reg, u8 val); + u8 read(offs_t reg); + + auto ctrl_r_cb() { return m_ctrl_r.bind(); } + auto video_mem_r_cb() { return m_video_mem_r.bind(); } + + auto video_mem_cb() { return m_video_mem_w.bind(); } + auto io_lo_cb() { return m_io_lo_addr.bind(); } + auto io_hi_cb() { return m_io_hi_addr.bind(); } + auto window_lo_cb() { return m_window_lo_addr.bind(); } + auto window_hi_cb() { return m_window_hi_addr.bind(); } + auto ctrl_cb() { return m_ctrl_w.bind(); } + +protected: + + virtual void device_start() override; + + u8 video_mem_r(); + void video_mem_w(u8 val); + + void io_lo_addr_w(u8 val); + void io_hi_addr_w(u8 val); + + void window_lo_addr_w(u8 val); + void window_hi_addr_w(u8 val); + + void ctrl_w(u8 val); + u8 ctrl_r(); + +private: + + // Reads + devcb_read8 m_ctrl_r; + devcb_read8 m_video_mem_r; + + // Writes + devcb_write8 m_video_mem_w; + devcb_write8 m_io_lo_addr; + devcb_write8 m_io_hi_addr; + devcb_write8 m_window_lo_addr; + devcb_write8 m_window_hi_addr; + devcb_write8 m_ctrl_w; +}; + +DECLARE_DEVICE_TYPE(SIGMASOFT_PARALLEL_PORT, sigmasoft_parallel_port) + + +#endif // MAME_HEATHKIT_SIGMASOFT_PARALLEL_PORT_H diff --git a/src/mame/heathzenith/tlb.cpp b/src/mame/heathzenith/tlb.cpp new file mode 100644 index 00000000000..ccafa639363 --- /dev/null +++ b/src/mame/heathzenith/tlb.cpp @@ -0,0 +1,2032 @@ +// license:BSD-3-Clause +// copyright-holders:Mark Garlanger +/*************************************************************************** + + Heathkit Terminal Logic Board (TLB) + + The board used in the H19 smart terminal designed and manufactured + by Heath Company. (and the identical Z19 sold by Zenith Data Systems) + This board is also used the Heath's H89 / H88, and ZDS's Z-89 and Z-90. + + The keyboard consists of a 9x10 matrix connected to a MM5740AAC/N + mask-programmed keyboard controller. The output of this passes + through a rom. + + Input can also come from the serial port. + + Known Issues: + - With gp19 + - 49/50 row mode only shows half the screen. + - In 49/50 row mode, character descenders are cut off. + - Screen saver does not disable the screen + - With Superset + - Screensaver freezes the screen instead of blanking the screen + + Not Currently Implemented + - With Imaginator I-100 + - Support for Tektronics Emulation (missing ROM image) + - With SigmaSoft IGC + - Interlace video support (with higher resolution) + - Joystick support + - Centronics support + - Lightpen support + - Alternate Font ROM support (missing ROM image) + - With Super19 + - Interlace video + - Alternate Font19 alt 128 mode and extended 256 mode (missing ROM images) + - ANSI character set selection (missing ROM image) + - light pen support + - With UltraROM + - Interace mode + +****************************************************************************/ +/*************************************************************************** + + Memory Layout + + The U435 three-to-eight line decoder uses A14 and A15 to generate + three memory address spaces: + + Address Description + ---------------------------------------------------- + 0x0000 Program ROM + 0x4000 Scratchpad RAM + 0xF800 (0xC000) Display Memory + + + Port Layout + + Only address lines A5, A6, A7 are used by the U442 three-to-eight + line decoder + + Address Description + ---------------------------------------------------- + 0x00 Power-up configuration (primary - SW401) + 0x20 Power-up configuration (secondary - SW402) + 0x40 INS8250 ACE (communications) + 0x60 MC6845 CRT controller + 0x80 MM5740 Keyboard encoder + 0xA0 Keyboard status + 0xC0 Trigger key click + 0xE0 Trigger bell + +****************************************************************************/ + +#include "emu.h" + +#include "tlb.h" + +#include + +#define LOG_REG (1U << 1) // Shows register setup + +//#define VERBOSE (LOG_REG) + +#include "logmacro.h" + +#define LOGREG(...) LOGMASKED(LOG_REG, __VA_ARGS__) + +#ifdef _MSC_VER +#define FUNCNAME __func__ +#else +#define FUNCNAME __PRETTY_FUNCTION__ +#endif + +// Clocks +static constexpr XTAL MASTER_CLOCK = XTAL(12'288'000); + +// DOT clocks +static constexpr XTAL BASE_DOT_CLOCK = MASTER_CLOCK; +static constexpr XTAL GP19_DOT_CLOCK_1 = XTAL(20'282'000); // 132 columns +static constexpr XTAL GP19_DOT_CLOCK_2 = XTAL(12'292'000); // 80 columns +static constexpr XTAL GP19_DOT_CLOCK_3 = XTAL(10'644'000); // Graphics mode + +// Standard H19 used a 2.048 MHz clock for Z80 +static constexpr XTAL H19_CLOCK = MASTER_CLOCK / 6; +static constexpr XTAL H19_3MHZ = MASTER_CLOCK / 4; +static constexpr XTAL H19_4MHZ = MASTER_CLOCK / 3; +static constexpr XTAL H19_6MHZ = MASTER_CLOCK / 2; + +static constexpr XTAL INS8250_CLOCK = MASTER_CLOCK / 4; + +// Beep Frequency is 1 KHz +static constexpr XTAL H19_BEEP_FRQ = (H19_CLOCK / 2048); + +// Capacitor value in pF +static constexpr u32 H19_KEY_DEBOUNCE_CAPACITOR = 5000; +static const u32 MM5740_CLOCK = mm5740_device::calc_effective_clock_key_debounce(H19_KEY_DEBOUNCE_CAPACITOR); + +// Keyboard flag masks +static constexpr u8 KB_STATUS_SHIFT_KEYS_MASK = 0x01; +static constexpr u8 KB_STATUS_CONTROL_KEY_MASK = 0x10; +static constexpr u8 KB_STATUS_KEYBOARD_STROBE_MASK = 0x80; + +DEFINE_DEVICE_TYPE(HEATH_TLB_CONNECTOR, heath_tlb_connector, "heath_tlb_connector", "Heath Terminal Logic board connector abstraction") + +DEFINE_DEVICE_TYPE(HEATH_TLB, heath_tlb_device, "heath_tlb", "Heath Terminal Logic Board") +DEFINE_DEVICE_TYPE(HEATH_SUPER19, heath_super19_tlb_device, "heath_super19_tlb", "Heath Terminal Logic Board w/Super19 ROM") +DEFINE_DEVICE_TYPE(HEATH_SUPERSET, heath_superset_tlb_device, "heath_superset_tlb", "Heath Terminal Logic Board w/Superset ROM") +DEFINE_DEVICE_TYPE(HEATH_ULTRA, heath_ultra_tlb_device, "heath_ultra_tlb", "Heath Terminal Logic Board w/Ultra ROM") +DEFINE_DEVICE_TYPE(HEATH_WATZ, heath_watz_tlb_device, "heath_watz_tlb", "Heath Terminal Logic Board w/Watzman ROM") +DEFINE_DEVICE_TYPE(HEATH_GP19, heath_gp19_tlb_device, "heath_gp19_tlb", "Heath Terminal Logic Board plus Northwest Digital Systems GP-19") +DEFINE_DEVICE_TYPE(HEATH_IMAGINATOR, heath_imaginator_tlb_device, "heath_imaginator_tlb", "Heath Terminal Logic Board plus Cleveland Codonics Imaginator I-100") + +// Devices for the terminal boards compatible with SigmaSoft IGC +DEFINE_DEVICE_TYPE(HEATH_IGC, heath_igc_tlb_device, "heath_igc_tlb_device", "Heath Terminal Logic Board plus SigmaSoft Interactive Graphics Controller") +DEFINE_DEVICE_TYPE(HEATH_IGC_SUPER19, heath_igc_super19_tlb_device, "heath_igc_super19_tlb_device", "Heath Terminal Logic Board w/ Super19 ROM plus SigmaSoft Interactive Graphics Controller") +DEFINE_DEVICE_TYPE(HEATH_IGC_ULTRA, heath_igc_ultra_tlb_device, "heath_igc_ultra_tlb_device", "Heath Terminal Logic Board w/ Ultra ROM plus SigmaSoft Interactive Graphics Controller") +DEFINE_DEVICE_TYPE(HEATH_IGC_WATZ, heath_igc_watz_tlb_device, "heath_igc_watz_tlb_device", "Heath Terminal Logic Board w/Watzman ROM plus SigmaSoft Interactive Graphics Controller") + + +device_heath_tlb_card_interface::device_heath_tlb_card_interface(const machine_config &mconfig, device_t &device) : + device_interface(device, "heathtlbdevice"), + m_slot(dynamic_cast(device.owner())) +{ +} + + +/** + * original Heath H19 functionality + */ +heath_tlb_device::heath_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + heath_tlb_device(mconfig, HEATH_TLB, tag, owner, clock) +{ +} + +heath_tlb_device::heath_tlb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) : + device_t(mconfig, type, tag, owner, clock), + device_heath_tlb_card_interface(mconfig, *this), + m_maincpu(*this, "maincpu"), + m_screen(*this, "screen"), + m_palette(*this, "palette"), + m_crtc(*this, "crtc"), + m_p_videoram(*this, "videoram"), + m_p_chargen(*this, "chargen"), + m_config(*this, "CONFIG"), + m_ace(*this, "ins8250"), + m_beep(*this, "beeper"), + m_mm5740(*this, "mm5740"), + m_kbdrom(*this, "keyboard"), + m_kbspecial(*this, "MODIFIERS"), + m_repeat_clock(*this, "repeatclock") +{ +} + +void heath_tlb_device::check_beep_state() +{ + if (!m_key_click_active && !m_bell_active) + { + m_beep->set_state(0); + } +} + +TIMER_CALLBACK_MEMBER(heath_tlb_device::key_click_off) +{ + m_key_click_active = false; + + check_beep_state(); +} + +TIMER_CALLBACK_MEMBER(heath_tlb_device::bell_off) +{ + m_bell_active = false; + + check_beep_state(); +} + +void heath_tlb_device::mem_map(address_map &map) +{ + map.unmap_value_high(); + + // H19 ROM + map(0x0000, 0x0fff).mirror(0x3000).rom(); + + // Scratchpad memory + map(0x4000, 0x40ff).mirror(0x3f00).ram(); + + // Video Memory + map(0xc000, 0xc7ff).mirror(0x3800).ram().share(m_p_videoram); +} + +void heath_tlb_device::io_map(address_map &map) +{ + map.unmap_value_high(); + map.global_mask(0xff); + map(0x00, 0x00).mirror(0x1f).portr("SW401"); + map(0x20, 0x20).mirror(0x1f).portr("SW402"); + map(0x40, 0x47).mirror(0x18).rw(m_ace, FUNC(ins8250_device::ins8250_r), FUNC(ins8250_device::ins8250_w)); + map(0x60, 0x60).mirror(0x1a).select(0x04).w(FUNC(heath_tlb_device::crtc_addr_w)); + map(0x61, 0x61).mirror(0x1a).select(0x04).rw(FUNC(heath_tlb_device::crtc_reg_r), FUNC(heath_tlb_device::crtc_reg_w)); + map(0x80, 0x80).mirror(0x1f).r(FUNC(heath_tlb_device::kbd_key_r)); + map(0xa0, 0xa0).mirror(0x1f).r(FUNC(heath_tlb_device::kbd_flags_r)); + map(0xc0, 0xc0).mirror(0x1f).w(FUNC(heath_tlb_device::key_click_w)); + map(0xe0, 0xe0).mirror(0x1f).w(FUNC(heath_tlb_device::bell_w)); +} + +void heath_tlb_device::device_start() +{ + save_item(NAME(m_transchar)); + save_item(NAME(m_strobe)); + save_item(NAME(m_key_click_active)); + save_item(NAME(m_bell_active)); + save_item(NAME(m_reset_pending)); + save_item(NAME(m_right_shift)); + save_item(NAME(m_reset_key)); + save_item(NAME(m_keyboard_irq_raised)); + save_item(NAME(m_serial_irq_raised)); + save_item(NAME(m_break_key_irq_raised)); + save_item(NAME(m_allow_vsync_nmi)); + + m_strobe = false; + m_key_click_active = false; + m_bell_active = false; + m_reset_pending = false; + m_right_shift = false; + m_reset_key = false; + m_keyboard_irq_raised = false; + m_serial_irq_raised = false; + m_break_key_irq_raised = false; + m_allow_vsync_nmi = false; + + m_key_click_timer = timer_alloc(FUNC(heath_tlb_device::key_click_off), this); + m_bell_timer = timer_alloc(FUNC(heath_tlb_device::bell_off), this); + + // Flip bits in font ROM to avoid having to flip them during scan out since some + // boards with graphics has the pixel graphic reversed from the font layout. Doing + // it for all devices for consistency. + for (size_t i = 0; i < m_p_chargen.length(); i++) + { + m_p_chargen[i] = bitswap<8>(m_p_chargen[i], 0, 1, 2, 3, 4, 5, 6, 7); + } +} + +void heath_tlb_device::device_reset() +{ + m_strobe = false; + m_key_click_active = false; + m_bell_active = false; + m_allow_vsync_nmi = false; + + ioport_value const cfg(m_config->read()); + + // CPU clock speed + switch (BIT(cfg, 0, 2)) + { + case 0x01: + m_maincpu->set_clock(H19_3MHZ); + break; + case 0x02: + m_maincpu->set_clock(H19_4MHZ); + break; + case 0x03: + m_maincpu->set_clock(H19_6MHZ); + break; + case 0x00: + default: + // Standard Clock + m_maincpu->set_clock(H19_CLOCK); + break; + } + + // Set screen color + switch (BIT(cfg, 2, 2)) + { + case 0x01: + m_screen->set_color(rgb_t::white()); + break; + case 0x02: + m_screen->set_color(rgb_t::amber()); + break; + case 0x00: + default: + m_screen->set_color(rgb_t::green()); + break; + } +} + +void heath_tlb_device::key_click_w(u8 data) +{ + // Keyclick - 6 mSec + m_beep->set_state(1); + m_key_click_active = true; + m_key_click_timer->adjust(attotime::from_msec(6)); +} + +void heath_tlb_device::bell_w(u8 data) +{ + // Bell (^G) - 200 mSec + m_beep->set_state(1); + m_bell_active = true; + m_bell_timer->adjust(attotime::from_msec(200)); +} + +/** + * MM5740 B Mapping to the ROM address + */ +u16 heath_tlb_device::translate_mm5740_b(u16 b) +{ + return bitswap<9>(b, 7, 6, 8, 5, 4, 3, 2, 1, 0); +} + +u8 heath_tlb_device::kbd_key_r() +{ + m_strobe = false; + m_keyboard_irq_raised = false; + + set_irq_line(); + + // high bit is for control key pressed, this is handled in the ROM, + // no processing needed. + return m_transchar; +} + +u8 heath_tlb_device::kbd_flags_r() +{ + u16 modifiers = m_kbspecial->read(); + u8 rv = modifiers & 0x7e; + + // check both shifts + if ((modifiers & 0x120) != 0x120) + { + rv |= KB_STATUS_SHIFT_KEYS_MASK; + } + + if (!m_strobe) + { + rv |= KB_STATUS_KEYBOARD_STROBE_MASK; + } + + return rv; +} + +int heath_tlb_device::mm5740_shift_r() +{ + return ((m_kbspecial->read() & 0x120) != 0x120) ? 1 : 0; +} + +int heath_tlb_device::mm5740_control_r() +{ + return (m_kbspecial->read() & KB_STATUS_CONTROL_KEY_MASK) ? 0 : 1; +} + +void heath_tlb_device::mm5740_data_ready_w(int state) +{ + if (state) + { + u8 *decode = m_kbdrom->base(); + + m_transchar = decode[translate_mm5740_b(m_mm5740->b_r())]; + m_strobe = true; + m_keyboard_irq_raised = true; + + set_irq_line(); + } +} + +void heath_tlb_device::crtc_addr_w(offs_t reg, u8 val) +{ + m_allow_vsync_nmi = bool(BIT(reg, 2)); + + m_crtc->address_w(val); +} + +u8 heath_tlb_device::crtc_reg_r(offs_t reg) +{ + if (!machine().side_effects_disabled()) + { + m_allow_vsync_nmi = bool(BIT(reg, 2)); + } + + return m_crtc->register_r(); +} + +void heath_tlb_device::crtc_reg_w(offs_t reg, u8 val) +{ + m_allow_vsync_nmi = bool(BIT(reg, 2)); + + m_crtc->register_w(val); +} + +void heath_tlb_device::crtc_vsync_w(int val) +{ + m_maincpu->set_input_line(INPUT_LINE_NMI, m_allow_vsync_nmi ? val : CLEAR_LINE); +} + +void heath_tlb_device::serial_irq_w(int state) +{ + m_serial_irq_raised = bool(state); + + set_irq_line(); +} + +void heath_tlb_device::set_irq_line() +{ + m_maincpu->set_input_line(INPUT_LINE_IRQ0, + (m_keyboard_irq_raised || m_serial_irq_raised || m_break_key_irq_raised) ? + ASSERT_LINE : CLEAR_LINE); +} + +void heath_tlb_device::check_for_reset() +{ + if (m_reset_key && m_right_shift) + { + m_reset_pending = true; + m_slot->reset_out(1); + m_maincpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); + } + else if (m_reset_pending) + { + m_reset_pending = false; + reset(); + m_maincpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE); + m_slot->reset_out(0); + } +} + +void heath_tlb_device::reset_key_w(int state) +{ + m_reset_key = (state == 0); + + check_for_reset(); +} + +void heath_tlb_device::right_shift_w(int state) +{ + m_right_shift = (state == 0); + + check_for_reset(); +} + +void heath_tlb_device::repeat_key_w(int state) +{ + // when repeat key pressed, set duty cycle to 50%, else 0%. + m_repeat_clock->set_duty_cycle(state == 0 ? 0.5 : 0); +} + +void heath_tlb_device::break_key_w(int state) +{ + m_break_key_irq_raised = (state == 0); + + set_irq_line(); +} + +MC6845_UPDATE_ROW(heath_tlb_device::crtc_update_row) +{ + rgb_t const *const palette = m_palette->palette()->entry_list_raw(); + u32 *p = &bitmap.pix(y); + + if (de) + { + for (int x = 0; x < x_count; x++) + { + u8 inv = (x == cursor_x) ? 0xff : 0; + u8 chr = m_p_videoram[(ma + x) & 0x7ff]; + + if (chr & 0x80) + { + inv ^= 0xff; + chr &= 0x7f; + } + + // get pattern of pixels for that character scanline + u8 const gfx = m_p_chargen[(chr << 4) | ra] ^ inv; + + // Display a scanline of a character (8 pixels) + for (int b = 0; 8 > b; ++b) + { + *p++ = palette[BIT(gfx, b)]; + } + } + } + else + { + std::fill_n(p, x_count * 8, palette[0]); + } +} + + +// F4 Character Displayer +static const gfx_layout h19_charlayout = +{ + 8, 10, // 8 x 10 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 }, + 8*16 // every char takes 16 bytes +}; + +static GFXDECODE_START( gfx_h19 ) + GFXDECODE_ENTRY("chargen", 0x0000, h19_charlayout, 0, 1) +GFXDECODE_END + + +// Input ports +static INPUT_PORTS_START( tlb ) + + PORT_START("MODIFIERS") + // bit 0 - 0x001 connects to B8 of MM5740 - low if either shift key is + PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("CapsLock") PORT_CODE(KEYCODE_CAPSLOCK) PORT_TOGGLE + PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Break") PORT_CODE(KEYCODE_PAUSE) PORT_WRITE_LINE_MEMBER(heath_tlb_device, break_key_w) + PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("OffLine") PORT_CODE(KEYCODE_F12) PORT_TOGGLE + PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("CTRL") PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_MAMEKEY(LCONTROL)) + PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("LeftShift") PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1) + PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Repeat") PORT_CODE(KEYCODE_RALT) PORT_WRITE_LINE_MEMBER(heath_tlb_device, repeat_key_w) + // bit 7 - 0x080 is low if any key is pressed + PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("RightShift") PORT_CODE(KEYCODE_RSHIFT) PORT_WRITE_LINE_MEMBER(heath_tlb_device, right_shift_w) + PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Reset") PORT_CODE(KEYCODE_F10) PORT_WRITE_LINE_MEMBER(heath_tlb_device, reset_key_w) + + PORT_START("X1") + PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("/") PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?') + PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("k_X2") + PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-0") PORT_CODE(KEYCODE_0_PAD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD)) + PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-.") PORT_CODE(KEYCODE_DEL_PAD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD)) + PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-Enter") PORT_CODE(KEYCODE_ENTER_PAD) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD)) + PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_UNUSED) + + PORT_START("X2") + PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("; :") PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':') + PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("' \"") PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('"') + PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("{ }") PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('{') PORT_CHAR('}') + PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Return") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) + PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-1 IL") PORT_CODE(KEYCODE_1_PAD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD)) + PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-2 Down") PORT_CODE(KEYCODE_2_PAD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD)) + PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-3 DL") PORT_CODE(KEYCODE_3_PAD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD)) + PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_UNUSED) + + PORT_START("X3") + PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("P") PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') + PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("[ ]") PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR(']') + PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("\\ |") PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') PORT_CHAR('|') + PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Line Feed") PORT_CODE(KEYCODE_RWIN) PORT_CHAR(10) + PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("DEL") PORT_CODE(KEYCODE_DEL) PORT_CHAR(127) + PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-4 LEFT") PORT_CODE(KEYCODE_4_PAD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD)) + PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-5 HOME") PORT_CODE(KEYCODE_5_PAD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD)) + PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-6 RIGHT") PORT_CODE(KEYCODE_6_PAD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD)) + PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_UNUSED) + + PORT_START("X4") + PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("0 )") PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')') + PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("- _") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_') + PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("= +") PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+') + PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("` ~") PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`') PORT_CHAR('~') + PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Back Space") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8) + PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("k_X1") + PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-7 IC") PORT_CODE(KEYCODE_7_PAD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD)) + PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-8 UP") PORT_CODE(KEYCODE_8_PAD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD)) + PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-9 DC") PORT_CODE(KEYCODE_9_PAD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD)) + PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_UNUSED) + + PORT_START("X5") + PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F1") PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1)) + PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F2") PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2)) + PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F3") PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3)) + PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F4") PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4)) + PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F5") PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5)) + PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Erase") PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6)) + PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Blue") PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7)) + PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Red") PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8)) + PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Gray") PORT_CODE(KEYCODE_F9) PORT_CHAR(UCHAR_MAMEKEY(F9)) + PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_UNUSED) + + PORT_START("X6") + PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Z") PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') + PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("X") PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') + PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C") PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') + PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("V") PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') + PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') + PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("N") PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') + PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("M") PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') + PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(", <") PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<') + PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(". >") PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>') + PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Space") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') + + PORT_START("X7") + PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') + PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("S") PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') + PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D") PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') + PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') + PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G") PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') + PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("H") PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') + PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("J") PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') + PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("K") PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') + PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("L") PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') + PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Scroll") PORT_CODE(KEYCODE_F11) + + PORT_START("X8") + PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Q") PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') + PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("W") PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') + PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E") PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') + PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("R") PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') + PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("T") PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') + PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Y") PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') + PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("U") PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') + PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("I") PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') + PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("O") PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') + PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Tab") PORT_CODE(KEYCODE_TAB) PORT_CHAR(9) + + PORT_START("X9") + PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("1 !") PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') + PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("2 @") PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@') + PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("3 #") PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') + PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("4 $") PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') + PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("5 %") PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') + PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("6 ^") PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^') + PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("7 &") PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&') + PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("8 *") PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*') + PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("9 (") PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(') + PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Esc") PORT_CODE(KEYCODE_ESC) PORT_CHAR(27) + + PORT_START("SW401") + PORT_DIPNAME( 0x0f, 0x0c, "Baud Rate") PORT_DIPLOCATION("SW401:1,2,3,4") + PORT_DIPSETTING( 0x01, "110") + PORT_DIPSETTING( 0x02, "150") + PORT_DIPSETTING( 0x03, "300") + PORT_DIPSETTING( 0x04, "600") + PORT_DIPSETTING( 0x05, "1200") + PORT_DIPSETTING( 0x06, "1800") + PORT_DIPSETTING( 0x07, "2000") + PORT_DIPSETTING( 0x08, "2400") + PORT_DIPSETTING( 0x09, "3600") + PORT_DIPSETTING( 0x0a, "4800") + PORT_DIPSETTING( 0x0b, "7200") + PORT_DIPSETTING( 0x0c, "9600") + PORT_DIPSETTING( 0x0d, "19200") + PORT_DIPNAME( 0x30, 0x00, "Parity") PORT_DIPLOCATION("SW401:5,6") + PORT_DIPSETTING( 0x00, DEF_STR( None ) ) + PORT_DIPSETTING( 0x10, "Odd") + PORT_DIPSETTING( 0x20, DEF_STR( None ) ) + PORT_DIPSETTING( 0x30, "Even") + PORT_DIPNAME( 0x40, 0x00, "Parity Type") PORT_DIPLOCATION("SW401:7") + PORT_DIPSETTING( 0x00, DEF_STR( Normal ) ) + PORT_DIPSETTING( 0x40, "Stick") + PORT_DIPNAME( 0x80, 0x80, "Duplex") PORT_DIPLOCATION("SW401:8") + PORT_DIPSETTING( 0x00, "Half") + PORT_DIPSETTING( 0x80, "Full") + + PORT_START("SW402") + PORT_DIPNAME( 0x01, 0x00, "Cursor") PORT_DIPLOCATION("SW402:1") + PORT_DIPSETTING( 0x00, "Underline") + PORT_DIPSETTING( 0x01, "Block") + PORT_DIPNAME( 0x02, 0x00, "Keyclick") PORT_DIPLOCATION("SW402:2") + PORT_DIPSETTING( 0x02, DEF_STR( No ) ) + PORT_DIPSETTING( 0x00, DEF_STR( Yes ) ) + PORT_DIPNAME( 0x04, 0x00, "Wrap at EOL") PORT_DIPLOCATION("SW402:3") + PORT_DIPSETTING( 0x00, DEF_STR( No ) ) + PORT_DIPSETTING( 0x04, DEF_STR( Yes ) ) + PORT_DIPNAME( 0x08, 0x00, "Auto LF on CR") PORT_DIPLOCATION("SW402:4") + PORT_DIPSETTING( 0x00, DEF_STR( No ) ) + PORT_DIPSETTING( 0x08, DEF_STR( Yes ) ) + PORT_DIPNAME( 0x10, 0x00, "Auto CR on LF") PORT_DIPLOCATION("SW402:5") + PORT_DIPSETTING( 0x00, DEF_STR( No ) ) + PORT_DIPSETTING( 0x10, DEF_STR( Yes ) ) + PORT_DIPNAME( 0x20, 0x00, "Mode") PORT_DIPLOCATION("SW402:6") + PORT_DIPSETTING( 0x00, "Heath/VT52") + PORT_DIPSETTING( 0x20, "ANSI") + PORT_DIPNAME( 0x40, 0x00, "Keypad Shifted") PORT_DIPLOCATION("SW402:7") + PORT_DIPSETTING( 0x00, DEF_STR( No ) ) + PORT_DIPSETTING( 0x40, DEF_STR( Yes ) ) + PORT_DIPNAME( 0x80, 0x00, "Refresh") PORT_DIPLOCATION("SW402:8") + PORT_DIPSETTING( 0x00, "60Hz") + PORT_DIPSETTING( 0x80, "50Hz") + + PORT_START("CONFIG") + PORT_CONFNAME(0x03, 0x00, "CPU Clock") + PORT_CONFSETTING( 0x00, "2 MHz") + PORT_CONFSETTING( 0x01, "3 MHz") + PORT_CONFSETTING( 0x02, "4 MHz") + PORT_CONFSETTING( 0x03, "6 MHz") + PORT_CONFNAME(0x0C, 0x00, "CRT Color") + PORT_CONFSETTING( 0x00, "Green") + PORT_CONFSETTING( 0x04, "White") + PORT_CONFSETTING( 0x08, "Amber") +INPUT_PORTS_END + + +static INPUT_PORTS_START( super19 ) + PORT_INCLUDE( tlb ) + + PORT_MODIFY("SW401") + PORT_DIPNAME( 0x0f, 0x0c, "Baud Rate") PORT_DIPLOCATION("SW401:1,2,3,4") + PORT_DIPSETTING( 0x01, "110") + PORT_DIPSETTING( 0x02, "150") + PORT_DIPSETTING( 0x03, "300") + PORT_DIPSETTING( 0x04, "600") + PORT_DIPSETTING( 0x05, "1200") + PORT_DIPSETTING( 0x06, "1800") + PORT_DIPSETTING( 0x07, "2000") + PORT_DIPSETTING( 0x08, "2400") + PORT_DIPSETTING( 0x09, "3600") + PORT_DIPSETTING( 0x0a, "4800") + PORT_DIPSETTING( 0x0b, "7200") + PORT_DIPSETTING( 0x0c, "9600") + PORT_DIPSETTING( 0x0d, "19200") + PORT_DIPSETTING( 0x0e, "38400") + PORT_DIPNAME( 0x70, 0x00, "8 bit mode") PORT_DIPLOCATION("SW401:5,6,7") + PORT_DIPSETTING( 0x00, "Mode A/0 - 8th bit ignored, sent as 0") + PORT_DIPSETTING( 0x10, "Mode B/1 - 8th bit ignored, sent as 1") + PORT_DIPSETTING( 0x20, "Mode C/2 - 8 bit escape mode") + PORT_DIPSETTING( 0x30, "Mode D/3 - 8 bit escape mode, invert 8th bit") + PORT_DIPSETTING( 0x40, "Mode E/4 - 8 bit data mode") + PORT_DIPSETTING( 0x50, "Mode F/5 - 8 bit data mode, invert 8th bit") + PORT_DIPSETTING( 0x60, "7 bit data with odd parity, 8th bit ignored on input") + PORT_DIPSETTING( 0x70, "7 bit data with even parity, 8th bit ignored on input") + PORT_DIPNAME( 0x80, 0x80, "Duplex") PORT_DIPLOCATION("SW401:8") + PORT_DIPSETTING( 0x00, "Half") + PORT_DIPSETTING( 0x80, "Full") + + PORT_MODIFY("SW402") + PORT_DIPNAME( 0x02, 0x00, "Transmit mode") PORT_DIPLOCATION("SW402:2") + PORT_DIPSETTING( 0x00, DEF_STR( Normal ) ) + PORT_DIPSETTING( 0x02, "Slow") + PORT_DIPNAME( 0x80, 0x00, "DEC Keypad Codes") PORT_DIPLOCATION("SW402:8") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x80, DEF_STR( On ) ) +INPUT_PORTS_END + + +static INPUT_PORTS_START( superset ) + PORT_INCLUDE( tlb ) + + PORT_MODIFY("SW401") + PORT_DIPNAME( 0x0f, 0x0c, "Baud Rate") PORT_DIPLOCATION("SW401:1,2,3,4") + PORT_DIPSETTING( 0x00, "75") + PORT_DIPSETTING( 0x01, "110") + PORT_DIPSETTING( 0x02, "150") + PORT_DIPSETTING( 0x03, "300") + PORT_DIPSETTING( 0x04, "600") + PORT_DIPSETTING( 0x05, "1200") + PORT_DIPSETTING( 0x06, "1800") + PORT_DIPSETTING( 0x07, "2000") + PORT_DIPSETTING( 0x08, "2400") + PORT_DIPSETTING( 0x09, "3600") + PORT_DIPSETTING( 0x0a, "4800") + PORT_DIPSETTING( 0x0b, "7200") + PORT_DIPSETTING( 0x0c, "9600") + PORT_DIPSETTING( 0x0d, "19200") + PORT_DIPSETTING( 0x0e, "38400") + PORT_DIPSETTING( 0x0f, "134.5") + PORT_DIPNAME( 0x10, 0x10, "Duplex") PORT_DIPLOCATION("SW401:5") + PORT_DIPSETTING( 0x00, "Half") + PORT_DIPSETTING( 0x80, "Full") + PORT_DIPNAME( 0x20, 0x00, "Word Length") PORT_DIPLOCATION("SW401:6") + PORT_DIPSETTING( 0x00, "8-bit" ) + PORT_DIPSETTING( 0x20, "7-bit" ) + PORT_DIPNAME( 0x40, 0x00, "Parity Type") PORT_DIPLOCATION("SW401:7") + PORT_DIPSETTING( 0x00, DEF_STR( None ) ) + PORT_DIPSETTING( 0x40, "Even") + PORT_DIPNAME( 0x80, 0x80, "Parity") PORT_DIPLOCATION("SW401:8") + PORT_DIPSETTING( 0x00, "Disabled") + PORT_DIPSETTING( 0x80, "Enabled") +INPUT_PORTS_END + + +static INPUT_PORTS_START( ultra19 ) + PORT_INCLUDE( tlb ) + + PORT_MODIFY("SW401") + PORT_DIPNAME( 0x07, 0x05, "Baud Rate") PORT_DIPLOCATION("SW401:1,2,3") + PORT_DIPSETTING( 0x00, "110") + PORT_DIPSETTING( 0x01, "300") + PORT_DIPSETTING( 0x02, "1200") + PORT_DIPSETTING( 0x03, "2400") + PORT_DIPSETTING( 0x04, "4800") + PORT_DIPSETTING( 0x05, "9600") + PORT_DIPSETTING( 0x06, "19200") + PORT_DIPSETTING( 0x07, "38400") + PORT_DIPNAME( 0x08, 0x00, "Parity") PORT_DIPLOCATION("SW401:4") + PORT_DIPSETTING( 0x00, "Disabled") + PORT_DIPSETTING( 0x08, "Enabled") + PORT_DIPNAME( 0x10, 0x00, "Parity Type") PORT_DIPLOCATION("SW401:5") + PORT_DIPSETTING( 0x00, "Odd") + PORT_DIPSETTING( 0x10, "Even") + PORT_DIPNAME( 0x20, 0x00, "Data Size") PORT_DIPLOCATION("SW401:6") + PORT_DIPSETTING( 0x00, "8-bit") + PORT_DIPSETTING( 0x20, "7-bit") + PORT_DIPNAME( 0x40, 0x40, "Duplex") PORT_DIPLOCATION("SW401:7") + PORT_DIPSETTING( 0x00, "Half") + PORT_DIPSETTING( 0x40, "Full") + PORT_DIPNAME( 0x80, 0x80, "Software Handshaking") PORT_DIPLOCATION("SW401:8") + PORT_DIPSETTING( 0x00, "Enabled") + PORT_DIPSETTING( 0x80, "Disabled") + + PORT_MODIFY("SW402") + PORT_DIPNAME( 0x08, 0x00, "Keypad Shifted") PORT_DIPLOCATION("SW402:4") + PORT_DIPSETTING( 0x00, DEF_STR( No ) ) + PORT_DIPSETTING( 0x08, DEF_STR( Yes ) ) + PORT_DIPNAME( 0x10, 0x00, "Default Key Values") PORT_DIPLOCATION("SW402:5") + PORT_DIPSETTING( 0x00, "HDOS Values") + PORT_DIPSETTING( 0x10, "CP/M Values") + PORT_DIPNAME( 0x60, 0x60, "Cursor Blink") PORT_DIPLOCATION("SW402:6,7") + PORT_DIPSETTING( 0x00, "Steady") + PORT_DIPSETTING( 0x20, "Invisible") + PORT_DIPSETTING( 0x40, "Fast Blink") + PORT_DIPSETTING( 0x60, "Slow Blink") + PORT_DIPNAME( 0x80, 0x00, "Interlace Scan Mode") PORT_DIPLOCATION("SW402:8") + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x80, DEF_STR( On ) ) +INPUT_PORTS_END + + +static INPUT_PORTS_START( watz19 ) + PORT_INCLUDE( tlb ) + + PORT_MODIFY("SW401") + PORT_DIPNAME( 0x0f, 0x0c, "Baud Rate") PORT_DIPLOCATION("SW401:1,2,3,4") + PORT_DIPSETTING( 0x00, "75") + PORT_DIPSETTING( 0x01, "110") + PORT_DIPSETTING( 0x02, "150") + PORT_DIPSETTING( 0x03, "300") + PORT_DIPSETTING( 0x04, "600") + PORT_DIPSETTING( 0x05, "1200") + PORT_DIPSETTING( 0x06, "1800") + PORT_DIPSETTING( 0x07, "2000") + PORT_DIPSETTING( 0x08, "2400") + PORT_DIPSETTING( 0x09, "3600") + PORT_DIPSETTING( 0x0a, "4800") + PORT_DIPSETTING( 0x0b, "7200") + PORT_DIPSETTING( 0x0c, "9600") + PORT_DIPSETTING( 0x0d, "19200") + PORT_DIPSETTING( 0x0e, "38400") + PORT_DIPSETTING( 0x0f, "134.5") + PORT_DIPNAME( 0x40, 0x00, "Word Size") PORT_DIPLOCATION("SW401:7") + PORT_DIPSETTING( 0x00, "8-bit Word") + PORT_DIPSETTING( 0x40, "7-bit Word") + PORT_DIPNAME( 0x80, 0x80, "Duplex") PORT_DIPLOCATION("SW401:8") + PORT_DIPSETTING( 0x00, "Half") + PORT_DIPSETTING( 0x80, "Full") +INPUT_PORTS_END + + +static INPUT_PORTS_START( gp19 ) + PORT_INCLUDE( tlb ) + + PORT_MODIFY("SW402") + PORT_DIPNAME( 0x80, 0x00, "Automatic Holdscreen") PORT_DIPLOCATION("SW402:8") + PORT_DIPSETTING( 0x00, "Disabled (VT100 mode)") + PORT_DIPSETTING( 0x80, "Enabled (Z19 mode)") + + PORT_START("SW1") + PORT_DIPNAME( 0x03, 0x01, "Trailing Characters for Tektronix Message") PORT_DIPLOCATION("SW1:1,2") + PORT_DIPSETTING( 0x00, DEF_STR( None ) ) + PORT_DIPSETTING( 0x01, "CR") + PORT_DIPSETTING( 0x02, DEF_STR( None ) ) + PORT_DIPSETTING( 0x03, "CR,EOT") + PORT_DIPNAME( 0x04, 0x01, "Shift Key") PORT_DIPLOCATION("SW1:3") + PORT_DIPSETTING( 0x00, DEF_STR( Normal ) ) + PORT_DIPSETTING( 0x04, "Shift key inverts CAPS LOCK") + PORT_DIPNAME( 0x08, 0x00, "Terminal Transmission Rate") PORT_DIPLOCATION("SW1:4") + PORT_DIPSETTING( 0x00, "Only limited by baud rate") + PORT_DIPSETTING( 0x08, "One character per 16.7 msec") + PORT_DIPNAME( 0x10, 0x10, "Character Set") PORT_DIPLOCATION("SW1:5") + PORT_DIPSETTING( 0x00, "VT100") + PORT_DIPSETTING( 0x10, "Zenith") + PORT_DIPNAME( 0x20, 0x00, "ANSI Mode") PORT_DIPLOCATION("SW1:6") + PORT_DIPSETTING( 0x00, "Zenith ANSI") + PORT_DIPSETTING( 0x20, "EDT compatible") + PORT_DIPNAME( 0x40, 0x00, "Tektronix Character Wrap") PORT_DIPLOCATION("SW1:7") + PORT_DIPSETTING( 0x00, "Column 74") + PORT_DIPSETTING( 0x40, "Column 73") + PORT_DIPNAME( 0x80, 0x00, "Blank Screen") PORT_DIPLOCATION("SW1:8") + PORT_DIPSETTING( 0x00, "After 10 mins") + PORT_DIPSETTING( 0x80, "Never") +INPUT_PORTS_END + + +ROM_START( h19 ) + // Original terminal code + ROM_REGION( 0x1000, "maincpu", ROMREGION_ERASEFF ) + ROM_LOAD( "2732_444-46_h19code.u437", 0x0000, 0x1000, CRC(f4447da0) SHA1(fb4093d5b763be21a9580a0defebed664b1f7a7b)) + + // Original font + ROM_REGION( 0x0800, "chargen", 0 ) + ROM_LOAD( "2716_444-29_h19font.u420", 0x0000, 0x0800, CRC(d595ac1d) SHA1(130fb4ea8754106340c318592eec2d8a0deaf3d0)) + + // Original keyboard + ROM_REGION( 0x0800, "keyboard", 0 ) + ROM_LOAD( "2716_444-37_h19keyb.u445", 0x0000, 0x0800, CRC(5c3e6972) SHA1(df49ce64ae48652346a91648c58178a34fb37d3c)) +ROM_END + +ROM_START( super19 ) + // Super-19 ROM + ROM_REGION( 0x1000, "maincpu", ROMREGION_ERASEFF ) + ROM_LOAD( "2732_super19_h447.u437", 0x0000, 0x1000, CRC(6c51aaa6) SHA1(5e368b39fe2f1af44a905dc474663198ab630117)) + + // Original font + ROM_REGION( 0x0800, "chargen", 0 ) + ROM_LOAD( "2716_444-29_h19font.u420", 0x0000, 0x0800, CRC(d595ac1d) SHA1(130fb4ea8754106340c318592eec2d8a0deaf3d0)) + + // Original keyboard + ROM_REGION( 0x0800, "keyboard", 0 ) + ROM_LOAD( "2716_444-37_h19keyb.u445", 0x0000, 0x0800, CRC(5c3e6972) SHA1(df49ce64ae48652346a91648c58178a34fb37d3c)) +ROM_END + +ROM_START( superset ) + // SuperSet ROM + ROM_REGION( 0x4000, "maincpu", ROMREGION_ERASEFF ) + ROM_LOAD( "27256_101-402_superset_code.u437", 0x0000, 0x2000, CRC(a6896076) SHA1(a4e2d25028dc75a665c3f5a830a4e8cdecbd481c)) + // 1st 8k is unused, so overwrite it, with the next 16k (but only first 8k is valid) + ROM_CONTINUE(0x0000, 0x4000) + // overwrite at 8k starting address with the last 8k of the chip. + ROM_CONTINUE(0x2000, 0x2000) + + // Superset SUPERFONT + ROM_REGION( 0x8000, "chargen", 0 ) + ROM_LOAD( "27256_101-431_superset_font.u420", 0x0000, 0x8000, CRC(4c0688f6) SHA1(be6059913420ad66f5c839d619fdcb164ffae85a)) + + // Superset Keyboard + ROM_REGION( 0x0800, "keyboard", 0 ) + ROM_LOAD( "2716_101-422_superset_kbd.u445", 0x0000, 0x0800, CRC(549d15b3) SHA1(981962e5e05bbdc5a66b0e86870853ce5596e877)) +ROM_END + +ROM_START( watz19 ) + ROM_REGION( 0x1000, "maincpu", ROMREGION_ERASEFF ) + ROM_DEFAULT_BIOS("watzman-a") + + // Watzman ROM + ROM_SYSTEM_BIOS(0, "watzman", "Watzman") + ROMX_LOAD("watzman.u437", 0x0000, 0x1000, CRC(8168b6dc) SHA1(bfaebb9d766edbe545d24bc2b6630be4f3aa0ce9), ROM_BIOS(0)) + + ROM_SYSTEM_BIOS(1, "watzman-a", "Watzman w/clock persists after reset") + ROMX_LOAD("watzman-a.u437", 0x0000, 0x1000, CRC(1f7553e9) SHA1(ac6ddb12b4fb46c1a0ad08ee43978ad3153b51aa), ROM_BIOS(1)) + + // Original font + ROM_REGION( 0x0800, "chargen", 0 ) + ROM_LOAD( "2716_444-29_h19font.u420", 0x0000, 0x0800, CRC(d595ac1d) SHA1(130fb4ea8754106340c318592eec2d8a0deaf3d0)) + + // Watzman keyboard + ROM_REGION( 0x0800, "keyboard", 0 ) + ROM_LOAD( "keybd.u445", 0x0000, 0x0800, CRC(58dc8217) SHA1(1b23705290bdf9fc6342065c6a528c04bff67b13)) +ROM_END + +ROM_START( ultra19 ) + // Ultra ROM + ROM_REGION( 0x1000, "maincpu", ROMREGION_ERASEFF ) + ROM_LOAD( "2532_h19_ultra_firmware.u437", 0x0000, 0x1000, CRC(8ad4cdb4) SHA1(d6e1fc37a1f52abfce5e9adb1819e0030bed1df3)) + + // Original font + ROM_REGION( 0x0800, "chargen", 0 ) + ROM_LOAD( "2716_444-29_h19font.u420", 0x0000, 0x0800, CRC(d595ac1d) SHA1(130fb4ea8754106340c318592eec2d8a0deaf3d0)) + + // Ultra keyboard + ROM_REGION( 0x0800, "keyboard", 0 ) + ROM_LOAD( "2716_h19_ultra_keyboard.u445", 0x0000, 0x0800, CRC(76130c92) SHA1(ca39c602af48505139d2750a084b5f8f0e662ff7)) +ROM_END + +ROM_START( gp19 ) + // GP-19 ROMs + ROM_REGION( 0x3000, "maincpu", ROMREGION_ERASEFF ) + ROM_LOAD( "gp19_rom_1_ver_1_1.u26", 0x0000, 0x1000, CRC(7cbe8e0d) SHA1(977df895b067fa4e4646b4518cffb08d4e6bb6e0)) + ROM_LOAD( "gp19_rom_2_ver_1_1.u25", 0x1000, 0x1000, CRC(a85e3bc4) SHA1(f64e851c5d3ef98a9a48e0fc482baa576773ff43)) + ROM_LOAD( "gp19_rom_3_ver_1_1.u24", 0x2000, 0x1000, CRC(878f577c) SHA1(0756435914dcfb981de4e40d5f81af3e0f5bb1c5)) + + // GP-19 font + ROM_REGION( 0x1000, "chargen", 0 ) + ROM_LOAD( "gp19_char_gen_cg_1.u21", 0x0000, 0x1000, CRC(49ec9242) SHA1(770a8c7b5b15bcfe465fd84326d0ae3dcaa85311)) + + // Original keyboard + ROM_REGION( 0x0800, "keyboard", 0 ) + ROM_LOAD( "2716_444-37_h19keyb.u445", 0x0000, 0x0800, CRC(5c3e6972) SHA1(df49ce64ae48652346a91648c58178a34fb37d3c)) +ROM_END + +ROM_START( imaginator ) + // Program code + ROM_REGION( 0x4000, "maincpu", ROMREGION_ERASEFF ) + // Original terminal code + ROM_LOAD( "2732_444-46_h19code.u437", 0x0000, 0x1000, CRC(f4447da0) SHA1(fb4093d5b763be21a9580a0defebed664b1f7a7b)) + // Imaginator ROMs + ROM_LOAD( "2732_imaginator_gpc_rev_1.2_pn_9000_0002.u9a", 0x2000, 0x1000, CRC(507bb13f) SHA1(5b210f8d77e22fdf063f611eb5c29636cdb01250)) + + // Original font + ROM_REGION( 0x0800, "chargen", 0 ) + ROM_LOAD( "2716_444-29_h19font.u420", 0x0000, 0x0800, CRC(d595ac1d) SHA1(130fb4ea8754106340c318592eec2d8a0deaf3d0)) + + // Original keyboard + ROM_REGION( 0x0800, "keyboard", 0 ) + ROM_LOAD( "2716_444-37_h19keyb.u445", 0x0000, 0x0800, CRC(5c3e6972) SHA1(df49ce64ae48652346a91648c58178a34fb37d3c)) +ROM_END + + +ioport_constructor heath_tlb_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(tlb); +} + +const tiny_rom_entry *heath_tlb_device::device_rom_region() const +{ + return ROM_NAME(h19); +} + +void heath_tlb_device::serial_out_b(int data) +{ + m_slot->serial_out_b(data); +} + +void heath_tlb_device::dtr_out(int data) +{ + m_slot->dtr_out(data); +} + +void heath_tlb_device::rts_out(int data) +{ + m_slot->rts_out(data); +} + +void heath_tlb_device::serial_in_w(int state) +{ + m_ace->rx_w(state); +} + +void heath_tlb_device::rlsd_in_w(int state) +{ + m_ace->dcd_w(state); +} + +void heath_tlb_device::dsr_in_w(int state) +{ + m_ace->dsr_w(state); +} + +void heath_tlb_device::cts_in_w(int state) +{ + m_ace->cts_w(state); +} + +void heath_tlb_device::device_add_mconfig(machine_config &config) +{ + // basic machine hardware + Z80(config, m_maincpu, H19_CLOCK); + m_maincpu->set_addrmap(AS_PROGRAM, &heath_tlb_device::mem_map); + m_maincpu->set_addrmap(AS_IO, &heath_tlb_device::io_map); + + // video hardware + SCREEN(config, m_screen, SCREEN_TYPE_RASTER, rgb_t::green()); + // based on the H19 ROM code for 60 Hz + m_screen->set_raw(BASE_DOT_CLOCK, 768, 32, 672, 270, 0, 250); + m_screen->set_screen_update("crtc", FUNC(mc6845_device::screen_update)); + + GFXDECODE(config, "gfxdecode", m_palette, gfx_h19); + PALETTE(config, "palette", palette_device::MONOCHROME); + + // MC 6845 uses a character clock, divide the DOT clock by 8. + MC6845(config, m_crtc, BASE_DOT_CLOCK / 8); + 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(heath_tlb_device::crtc_update_row)); + // frame pulse + m_crtc->out_vsync_callback().set(FUNC(heath_tlb_device::crtc_vsync_w)); + + // serial port + INS8250(config, m_ace, INS8250_CLOCK); + m_ace->out_int_callback().set(FUNC(heath_tlb_device::serial_irq_w)); + m_ace->out_tx_callback().set(FUNC(heath_tlb_device::serial_out_b)); + m_ace->out_dtr_callback().set(FUNC(heath_tlb_device::dtr_out)); + m_ace->out_rts_callback().set(FUNC(heath_tlb_device::rts_out)); + + // keyboard + MM5740(config, m_mm5740, MM5740_CLOCK); + m_mm5740->x_cb<1>().set_ioport("X1"); + m_mm5740->x_cb<2>().set_ioport("X2"); + m_mm5740->x_cb<3>().set_ioport("X3"); + m_mm5740->x_cb<4>().set_ioport("X4"); + m_mm5740->x_cb<5>().set_ioport("X5"); + m_mm5740->x_cb<6>().set_ioport("X6"); + m_mm5740->x_cb<7>().set_ioport("X7"); + m_mm5740->x_cb<8>().set_ioport("X8"); + m_mm5740->x_cb<9>().set_ioport("X9"); + m_mm5740->shift_cb().set(FUNC(heath_tlb_device::mm5740_shift_r)); + m_mm5740->control_cb().set(FUNC(heath_tlb_device::mm5740_control_r)); + m_mm5740->data_ready_cb().set(FUNC(heath_tlb_device::mm5740_data_ready_w)); + + // sound hardware + SPEAKER(config, "mono").front_center(); + BEEP(config, m_beep, H19_BEEP_FRQ).add_route(ALL_OUTPUTS, "mono", 0.05); + + // clock for repeat key + CLOCK(config, m_repeat_clock, 40); + m_repeat_clock->set_duty_cycle(0); + m_repeat_clock->signal_handler().set(m_mm5740, FUNC(mm5740_device::repeat_line_w)); +} + + +/** + * Super-19 ROM + * + * Developed by ATG Systems + */ +heath_super19_tlb_device::heath_super19_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + heath_tlb_device(mconfig, HEATH_SUPER19, tag, owner, clock) +{ +} + +const tiny_rom_entry *heath_super19_tlb_device::device_rom_region() const +{ + return ROM_NAME(super19); +} + +ioport_constructor heath_super19_tlb_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(super19); +} + + +/** + * Superset ROM + * + * Developed by TMSI + */ +heath_superset_tlb_device::heath_superset_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + heath_tlb_device(mconfig, HEATH_SUPERSET, tag, owner, clock), + m_selected_char_set(0) +{ +} + +void heath_superset_tlb_device::device_add_mconfig(machine_config &config) +{ + heath_tlb_device::device_add_mconfig(config); + + // part of the Superset upgrade was to upgrade the CPU to 3 MHz. + m_maincpu->set_clock(H19_3MHZ); + m_maincpu->set_addrmap(AS_PROGRAM, &heath_superset_tlb_device::mem_map); + m_maincpu->set_addrmap(AS_IO, &heath_superset_tlb_device::io_map); + + // per line updates are needed for onscreen menu to display properly + m_screen->set_video_attributes(VIDEO_UPDATE_SCANLINE); + + m_crtc->set_update_row_callback(FUNC(heath_superset_tlb_device::crtc_update_row)); + + // link up the serial port outputs to font chip. + m_ace->out_dtr_callback().set(FUNC(heath_superset_tlb_device::dtr_internal)); + m_ace->out_out1_callback().set(FUNC(heath_superset_tlb_device::out1_internal)); + m_ace->out_out2_callback().set(FUNC(heath_superset_tlb_device::out2_internal)); +} + +void heath_superset_tlb_device::device_start() +{ + heath_tlb_device::device_start(); + + save_item(NAME(m_selected_char_set)); + + m_selected_char_set = 0; +} + +void heath_superset_tlb_device::mem_map(address_map &map) +{ + heath_tlb_device::mem_map(map); + + // update rom space for the 16k ROM. + map(0x0000, 0x3fff).rom(); + + // page 2 memory + map(0x8000, 0x87ff).ram(); +} + +void heath_superset_tlb_device::io_map(address_map &map) +{ + heath_tlb_device::io_map(map); + + map(0x61, 0x61).mirror(0x12).select(0x0c).rw(FUNC(heath_superset_tlb_device::crtc_reg_r), FUNC(heath_superset_tlb_device::crtc_reg_w)); +} + +const tiny_rom_entry *heath_superset_tlb_device::device_rom_region() const +{ + return ROM_NAME(superset); +} + +ioport_constructor heath_superset_tlb_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(superset); +} + +u8 heath_superset_tlb_device::crtc_reg_r(offs_t reg) +{ + if (!machine().side_effects_disabled()) + { + m_reverse_video_disabled = bool(BIT(reg, 3)); + } + + return heath_tlb_device::crtc_reg_r(reg); +} + +void heath_superset_tlb_device::crtc_reg_w(offs_t reg, u8 val) +{ + m_reverse_video_disabled = bool(BIT(reg, 3)); + + heath_tlb_device::crtc_reg_w(reg, val); +} + +MC6845_UPDATE_ROW(heath_superset_tlb_device::crtc_update_row) +{ + rgb_t const *const palette = m_palette->palette()->entry_list_raw(); + u32 *p = &bitmap.pix(y); + + if (de) + { + for (int x = 0; x < x_count; x++) + { + u8 inv = (x == cursor_x) ? 0xff : 0; + u8 chr = m_p_videoram[(ma + x) & 0x7ff]; + u16 char_set_base_offset = (m_selected_char_set << 11); + + if (chr & 0x80) + { + if (m_reverse_video_disabled) + { + // set A13 + char_set_base_offset |= 0x2000; + } + else + { + inv ^= 0xff; + } + + chr &= 0x7f; + } + + // get pattern of pixels for the character scanline + u8 const gfx = m_p_chargen[char_set_base_offset | (chr << 4) | ra] ^ inv; + + // Display a scanline of a character (8 pixels) + for (int b = 0; 8 > b; ++b) + { + *p++ = palette[BIT(gfx, b)]; + } + } + } + else + { + std::fill_n(p, bitmap.rowpixels(), palette[0]); + } +} + +// DTR (pin 33) to A14 (pin 27) of 27256 ROM +void heath_superset_tlb_device::dtr_internal(int data) +{ + m_selected_char_set = (m_selected_char_set & 0x03) | ((data & 0x01) << 3); +} + +// OUT1 (pin 34) to A12 (pin 2) of 27256 ROM +void heath_superset_tlb_device::out1_internal(int data) +{ + m_selected_char_set = (m_selected_char_set & 0x09) | ((data & 0x01) << 1); +} + +// OUT2 (pin 31) to A11? on board +void heath_superset_tlb_device::out2_internal(int data) +{ + m_selected_char_set = (m_selected_char_set & 0x0a) | (data & 0x01); +} + + +/** + * Watzman ROM + * + * Developed by Barry Watzman, sold by HUG (Heath Users Group) +*/ +heath_watz_tlb_device::heath_watz_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + heath_tlb_device(mconfig, HEATH_WATZ, tag, owner, clock) +{ +} + +const tiny_rom_entry *heath_watz_tlb_device::device_rom_region() const +{ + return ROM_NAME(watz19); +} + +ioport_constructor heath_watz_tlb_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(watz19); +} + + +/** + * UltraROM + * + * Developed by William G. Parrott, III, sold by Software Wizardry, Inc. + */ +heath_ultra_tlb_device::heath_ultra_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + heath_tlb_device(mconfig, HEATH_ULTRA, tag, owner, clock) +{ +} + +void heath_ultra_tlb_device::device_add_mconfig(machine_config &config) +{ + heath_tlb_device::device_add_mconfig(config); + + m_maincpu->set_addrmap(AS_PROGRAM, &heath_ultra_tlb_device::mem_map); +} + +void heath_ultra_tlb_device::mem_map(address_map &map) +{ + heath_tlb_device::mem_map(map); + + // update rom mirror setting to allow page 2 memory + map(0x0000, 0x0fff).mirror(0x2000).rom(); + + // Page 2 memory + map(0x1000, 0x1fff).mirror(0x2000).ram(); +} + +const tiny_rom_entry *heath_ultra_tlb_device::device_rom_region() const +{ + return ROM_NAME(ultra19); +} + +ioport_constructor heath_ultra_tlb_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(ultra19); +} + + +/** + * Northwest Digital Systems GP-19 add-in board + */ +heath_gp19_tlb_device::heath_gp19_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + heath_tlb_device(mconfig, HEATH_GP19, tag, owner, clock) +{ +} + +void heath_gp19_tlb_device::device_add_mconfig(machine_config &config) +{ + heath_tlb_device::device_add_mconfig(config); + + m_maincpu->set_addrmap(AS_PROGRAM, &heath_gp19_tlb_device::mem_map); + m_maincpu->set_addrmap(AS_IO, &heath_gp19_tlb_device::io_map); + + m_crtc->set_update_row_callback(FUNC(heath_gp19_tlb_device::crtc_update_row)); + m_crtc->set_clock(GP19_DOT_CLOCK_2 / 8); + + m_screen->set_raw(GP19_DOT_CLOCK_2, 776, 32, 672, 264, 10, 250); +} + +void heath_gp19_tlb_device::device_start() +{ + heath_tlb_device::device_start(); + + save_item(NAME(m_char_gen_a11)); + save_item(NAME(m_graphic_mode)); + save_item(NAME(m_col_132)); + save_item(NAME(m_reverse_video)); + + m_char_gen_a11 = false; + m_graphic_mode = false; + m_col_132 = false; + m_reverse_video = false; +} + +void heath_gp19_tlb_device::mem_map(address_map &map) +{ + // ROMs 1, 2, 3 + map(0x0000, 0x02fff).rom(); + + // Optional external board - Program ROM 4(not aware if any ever existed), external I/O + // map(0x3000, 0x03fff).rom(); + + map(0x4000, 0x40ff).mirror(0x3f00).ram(); + map(0x6000, 0x67ff).mirror(0x1800).ram(); + map(0x8000, 0xbfff).mirror(0x4000).ram().share(m_p_videoram); +} + +void heath_gp19_tlb_device::io_map(address_map &map) +{ + heath_tlb_device::io_map(map); + + // Latch U5 + map(0x68, 0x68).mirror(0x07).w(FUNC(heath_gp19_tlb_device::latch_u5_w)); + + // Switch on GP-19 board + map(0x70, 0x70).mirror(0x07).portr("SW1"); + + // Optional Auxiliary I/O connector(not aware if any ever existed) + // map(0x78, 0x78).mirror(0x07); +} + +/** + * U5 Latch + * + * Q0 Graph/character H + * Q1 132/80 columns H + * Q2 Reverse Screen H + * Q3 Alt Character L + * Q4-Q7 LED indicators (debug LEDs on circuit board) + */ +void heath_gp19_tlb_device::latch_u5_w(u8 data) +{ + m_graphic_mode = bool(BIT(data, 0)); + m_col_132 = bool(BIT(data, 1)); + m_reverse_video = bool(BIT(data, 2)); + m_char_gen_a11 = bool(BIT(data, 3)); + + // TODO handle LED indicators + + if (m_graphic_mode) + { + m_crtc->set_clock(GP19_DOT_CLOCK_3 / 8); + } + else if (m_col_132) + { + m_crtc->set_clock(GP19_DOT_CLOCK_1 / 8); + } + else + { + m_crtc->set_clock(GP19_DOT_CLOCK_2 / 8); + } +} + +MC6845_UPDATE_ROW(heath_gp19_tlb_device::crtc_update_row) +{ + rgb_t const *const palette = m_palette->palette()->entry_list_raw(); + u32 *p = &bitmap.pix(y); + + if (de) + { + u8 screen_inv = m_reverse_video ? 0xff : 0x00; + + if (m_graphic_mode) + { + for (int x = 0; x < x_count; x++) + { + u8 const gfx = m_p_videoram[((ma << 1) + (ra * x_count) + x) & 0x3fff] ^ screen_inv; + + for (int b = 0; 8 > b; ++b) + { + *p++ = palette[BIT(gfx, b)]; + } + } + } + else + { + u16 const base = m_char_gen_a11 ? 0x800 : 0x0; + + for (int x = 0; x < x_count; x++) + { + u8 inv = (x == cursor_x) ? 0xff : 0; + u8 chr = m_p_videoram[(ma + x) & 0x3fff]; + + if (chr & 0x80) + { + inv ^= 0xff; + chr &= 0x7f; + } + + inv ^= screen_inv; + + // select proper character set + u8 const gfx = m_p_chargen[base | (chr << 4) | ra] ^ inv; + + // Display a scanline of a character (8 pixels) + for (int b = 0; 8 > b; ++b) + { + *p++ = palette[BIT(gfx, b)]; + } + } + } + } + else + { + std::fill_n(p, x_count * 8, palette[0]); + } +} + +const tiny_rom_entry *heath_gp19_tlb_device::device_rom_region() const +{ + return ROM_NAME(gp19); +} + +ioport_constructor heath_gp19_tlb_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(gp19); +} + + +/** + * Cleveland Codonics Imaginator-100 (I-100) add-in board + * + * Memory Range Description + * ----------------------------------------------------------------- + * 0x0000-0x1fff Program ROM (Heath TLB board) + * 0x2000-0x3fff Graphics Command Processor(GCP) ROM (I-100) + * 0x4000-0x5fff Scratchpad RAM (Heath TLB board) + * 0x6000-0x7fff Graphics Scratchpad R/W RAM (I-100) + * 0x8000-0xbfff Graphics Display R/W RAM(I-100) + * 0xc000-0xdfff Optional Graphics Command Processor memory (I-100) + * 0xe000-0xffff Display Memory (Heath TLB board) + * + * New interrupt source + * - horizontal retrace interrupt + * + */ +heath_imaginator_tlb_device::heath_imaginator_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + heath_tlb_device(mconfig, HEATH_IMAGINATOR, tag, owner, clock), + m_mem_bank(*this, "membank"), + m_p_graphic_ram(*this, "graphicram") +{ +} + +void heath_imaginator_tlb_device::device_add_mconfig(machine_config &config) +{ + heath_tlb_device::device_add_mconfig(config); + + m_maincpu->set_addrmap(AS_PROGRAM, &heath_imaginator_tlb_device::mem_map); + m_maincpu->set_addrmap(AS_IO, &heath_imaginator_tlb_device::io_map); + m_maincpu->set_irq_acknowledge_callback(FUNC(heath_imaginator_tlb_device::irq_ack_cb)); + + m_crtc->out_hsync_callback().set(FUNC(heath_imaginator_tlb_device::crtc_hsync_w)); +} + +void heath_imaginator_tlb_device::device_start() +{ + heath_tlb_device::device_start(); + + save_item(NAME(m_im2_val)); + save_item(NAME(m_alphanumeric_mode_active)); + save_item(NAME(m_graphics_mode_active)); + save_item(NAME(m_allow_tlb_interrupts)); + save_item(NAME(m_allow_imaginator_interrupts)); + save_item(NAME(m_hsync_irq_raised)); + + m_mem_bank->configure_entries(0, 2, memregion("maincpu")->base(), 0x2000); + + m_maincpu->space(AS_PROGRAM).install_readwrite_tap(0x8000, 0xbfff, "irq_update", + [this] (offs_t offset, u8 &data, u8 mem_mask) { if (!machine().side_effects_disabled()) { tap_8000h(); } }, + [this] (offs_t offset, u8 &data, u8 mem_mask) { if (!machine().side_effects_disabled()) { tap_8000h(); } }); +} + +void heath_imaginator_tlb_device::device_reset() +{ + heath_tlb_device::device_reset(); + + m_mem_bank->set_entry(1); + m_tap_6000h.remove(); + m_tap_6000h = m_maincpu->space(AS_PROGRAM).install_readwrite_tap(0x6000, 0x7fff, "mem_map_update", + [this] (offs_t offset, u8 &data, u8 mem_mask) { if (!machine().side_effects_disabled()) { tap_6000h(); } }, + [this] (offs_t offset, u8 &data, u8 mem_mask) { if (!machine().side_effects_disabled()) { tap_6000h(); } }); + + m_alphanumeric_mode_active = true; + m_graphics_mode_active = false; + + m_hsync_irq_raised = false; + + allow_tlb_intr(); +} + +void heath_imaginator_tlb_device::mem_map(address_map &map) +{ + map.unmap_value_high(); + + map(0x0000, 0x1fff).bankr(m_mem_bank); + + // Normal spot of the GCP ROM + map(0x2000, 0x3fff).rom(); + + // TLB Scratchpad + map(0x4000, 0x40ff).mirror(0x1f00).ram(); + + // GCP Scratchpad + map(0x6000, 0x607f).mirror(0x1f80).ram(); + + // Graphics RAM + map(0x8000, 0xbfff).ram().share(m_p_graphic_ram); + + // optional Graphics Command Processor (GCP) + // map(0xc000, 0xdfff); + + // Alphanumeric RAM + map(0xe000, 0xe7ff).mirror(0x1800).ram().share(m_p_videoram); +} + +void heath_imaginator_tlb_device::tap_6000h() +{ + m_mem_bank->set_entry(0); + m_tap_6000h.remove(); +} + +void heath_imaginator_tlb_device::tap_8000h() +{ + if (!m_allow_tlb_interrupts) + { + allow_tlb_intr(); + + set_irq_line(); + } +} + +void heath_imaginator_tlb_device::allow_tlb_intr() +{ + m_allow_tlb_interrupts = true; + m_allow_imaginator_interrupts = false; + m_im2_val = 0x02; +} + +void heath_imaginator_tlb_device::allow_hsync_intr() +{ + m_allow_tlb_interrupts = false; + m_allow_imaginator_interrupts = true; + m_im2_val = 0x00; +} + +/** + * An input/output request (IORQ) is sent to the TERMINAL LOGIC board only when + * both IORQ (pin 20 of U7) AND A4 are low. + */ +void heath_imaginator_tlb_device::io_map(address_map &map) +{ + heath_tlb_device::io_map(map); + + // interrupt routing + map(0x10, 0x10).select(0x08).mirror(0x07).w(FUNC(heath_imaginator_tlb_device::config_irq_w)); + + // display enabling (graphics or alphanumeric) + map(0x30, 0x30).select(0xc0).mirror(0x0f).w(FUNC(heath_imaginator_tlb_device::display_enable_w)); + + // Avoids writes to TLB when a4 is high on unused + map(0x50, 0x50).select(0x80).mirror(0x0f).w(FUNC(heath_imaginator_tlb_device::nop_w)); +} + +IRQ_CALLBACK_MEMBER(heath_imaginator_tlb_device::irq_ack_cb) +{ + return m_im2_val; +} + +void heath_imaginator_tlb_device::config_irq_w(offs_t reg, u8 val) +{ + if (BIT(reg, 3)) + { + allow_tlb_intr(); + } + else + { + allow_hsync_intr(); + } + + set_irq_line(); +} + +void heath_imaginator_tlb_device::display_enable_w(offs_t reg, u8 val) +{ + m_alphanumeric_mode_active = bool(BIT(reg, 7)); + m_graphics_mode_active = bool(BIT(reg, 6)); +} + +void heath_imaginator_tlb_device::nop_w(offs_t, u8) +{ +} + +const tiny_rom_entry *heath_imaginator_tlb_device::device_rom_region() const +{ + return ROM_NAME(imaginator); +} + +MC6845_UPDATE_ROW(heath_imaginator_tlb_device::crtc_update_row) +{ + rgb_t const *const palette = m_palette->palette()->entry_list_raw(); + u32 *p = &bitmap.pix(y); + + if (de) + { + for (int x = 0; x < x_count; x++) + { + u8 output = 0x00; + + if (m_alphanumeric_mode_active) + { + u8 inv = (x == cursor_x) ? 0xff : 0; + u8 chr = m_p_videoram[(ma + x) & 0x7ff]; + + if (chr & 0x80) + { + inv ^= 0xff; + chr &= 0x7f; + } + + output |= m_p_chargen[(chr << 4) | ra] ^ inv; + } + + if (m_graphics_mode_active && (x > 7 ) && (x < 73)) + { + output |= m_p_graphic_ram[((y * 64) + (x - 8)) & 0x3fff]; + } + + for (int b = 0; 8 > b; ++b) + { + *p++ = palette[BIT(output, b)]; + } + } + } + else + { + std::fill_n(p, x_count * 8, palette[0]); + } +} + +void heath_imaginator_tlb_device::crtc_hsync_w(int val) +{ + m_hsync_irq_raised = bool(val); + + set_irq_line(); +} + +void heath_imaginator_tlb_device::set_irq_line() +{ + m_maincpu->set_input_line(INPUT_LINE_IRQ0, + (m_allow_imaginator_interrupts && m_hsync_irq_raised) || + (m_allow_tlb_interrupts && (m_keyboard_irq_raised || m_serial_irq_raised || m_break_key_irq_raised)) ? + ASSERT_LINE : CLEAR_LINE); +} + + +/** + * SigmaSoft Interactive Graphics Controller (IGC) + * + * + */ +heath_igc_tlb_device::heath_igc_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + heath_tlb_device(mconfig, HEATH_IGC, tag, owner, clock) +{ +} + +heath_igc_tlb_device::heath_igc_tlb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) : + heath_tlb_device(mconfig, type, tag, owner, clock) +{ +} + +void heath_igc_tlb_device::device_add_mconfig(machine_config &config) +{ + heath_tlb_device::device_add_mconfig(config); + + m_crtc->set_update_row_callback(FUNC(heath_igc_tlb_device::crtc_update_row)); +} + +void heath_igc_tlb_device::device_start() +{ + heath_tlb_device::device_start(); + + m_p_graphic_ram = make_unique_clear(0x3ffff); + save_pointer(NAME(m_p_graphic_ram), 0x3ffff); + + save_item(NAME(m_data_reg)); + save_item(NAME(m_pixel_video_enabled)); + save_item(NAME(m_character_video_disabled)); + save_item(NAME(m_video_invert_enabled)); + save_item(NAME(m_alternate_character_set_enabled)); + save_item(NAME(m_video_fill_enabled)); + save_item(NAME(m_read_address_increment_disabled)); + save_item(NAME(m_memory_bank_select)); + save_item(NAME(m_io_address)); + save_item(NAME(m_window_address)); +} + +void heath_igc_tlb_device::device_reset() +{ + heath_tlb_device::device_reset(); + + sigma_ctrl_w(0); + m_data_reg = 0x00; + m_io_address = 0x0000; + m_window_address = 0x0000; +} + +void heath_igc_tlb_device::sigma_ctrl_w(u8 data) +{ + LOGREG("%s: data: %02x\n", FUNCNAME, data); + + m_pixel_video_enabled = bool(BIT(data, 0)); + m_character_video_disabled = bool(BIT(data, 1)); + m_video_invert_enabled = bool(BIT(data, 2)); + m_alternate_character_set_enabled = bool(BIT(data, 3)); + m_video_fill_enabled = bool(BIT(data, 4)); + m_read_address_increment_disabled = bool(BIT(data, 5)); + + m_memory_bank_select = bitswap<2>(data, 6, 7); + + if (m_video_fill_enabled) + { + std::fill_n(&m_p_graphic_ram[(m_memory_bank_select << 16) & 0x3ffff], 0x10000, m_data_reg); + } +} + +u8 heath_igc_tlb_device::sigma_ctrl_r() +{ + u8 ret_val = 0x00; + + ret_val |= m_pixel_video_enabled ? 0x01 : 0x00; + ret_val |= m_character_video_disabled ? 0x02 : 0x00; + ret_val |= m_video_invert_enabled ? 0x04 : 0x00; + ret_val |= m_alternate_character_set_enabled ? 0x08 : 0x00; + ret_val |= m_video_fill_enabled ? 0x10 : 0x00; + ret_val |= m_read_address_increment_disabled ? 0x20 : 0x00; + + ret_val |= bitswap<2>(m_memory_bank_select, 0, 1) << 6; + + LOGREG("%s: ret_val: %02x\n", FUNCNAME, ret_val); + + return ret_val; +} + +void heath_igc_tlb_device::sigma_video_mem_w(u8 data) +{ + LOGREG("%s: data: %02x\n", FUNCNAME, data); + + m_data_reg = data; + + m_p_graphic_ram[(m_memory_bank_select << 16) + m_io_address++] = data; +} + +u8 heath_igc_tlb_device::sigma_video_mem_r() +{ + // control whether m_io_address is incremented during a read + u32 addr = (m_read_address_increment_disabled || machine().side_effects_disabled()) ? + ((m_memory_bank_select << 16) + m_io_address) : + ((m_memory_bank_select << 16) + m_io_address++); + + return m_p_graphic_ram[addr]; +} + +void heath_igc_tlb_device::sigma_io_lo_addr_w(u8 data) +{ + LOGREG("%s: data: %02x\n", FUNCNAME, data); + + m_io_address = (m_io_address & 0xff00) | data; +} + +void heath_igc_tlb_device::sigma_io_hi_addr_w(u8 data) +{ + LOGREG("%s: data: %02x\n", FUNCNAME, data); + + m_io_address = (data << 8) | (m_io_address & 0x00ff); +} + +void heath_igc_tlb_device::sigma_window_lo_addr_w(u8 data) +{ + LOGREG("%s: data: %02x\n", FUNCNAME, data); + + m_window_address = (m_window_address & 0xff00) | data; +} + +void heath_igc_tlb_device::sigma_window_hi_addr_w(u8 data) +{ + LOGREG("%s: data: %02x\n", FUNCNAME, data); + + m_window_address = (data << 8) | (m_window_address & 0x00ff); +} + +MC6845_UPDATE_ROW(heath_igc_tlb_device::crtc_update_row) +{ + rgb_t const *const palette = m_palette->palette()->entry_list_raw(); + u32 *p = &bitmap.pix(y); + + if (de) + { + u8 video_invert = m_video_invert_enabled ? 0xff : 0; + + for (int x = 0; x < x_count; x++) + { + u8 output = 0x00; + + if (!m_character_video_disabled) + { + u8 inv = (x == cursor_x) ? 0xff : 0; + u8 chr = m_p_videoram[(ma + x) & 0x7ff]; + + if (chr & 0x80) + { + inv ^= 0xff; + chr &= 0x7f; + } + + // TODO handle alt font + output |= m_p_chargen[(chr << 4) | ra] ^ inv; + } + + if (m_pixel_video_enabled) + { + output |= m_p_graphic_ram[(((y * 80) + x) + m_window_address) & 0xffff]; + } + + output ^= video_invert; + + for (int b = 0; 8 > b; ++b) + { + *p++ = palette[BIT(output, b)]; + } + } + } + else + { + std::fill_n(p, x_count * 8, palette[0]); + } +} + + +/** + * SigmaSoft and Systems IGC plus TLB with Super-19 ROM + * + */ +heath_igc_super19_tlb_device::heath_igc_super19_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + heath_igc_tlb_device(mconfig, HEATH_IGC_SUPER19, tag, owner, clock) +{ +} + +const tiny_rom_entry *heath_igc_super19_tlb_device::device_rom_region() const +{ + return ROM_NAME(super19); +} + +ioport_constructor heath_igc_super19_tlb_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(super19); +} + + +/** + * SigmaSoft and Systems IGC plus TLB with UltraROM + * + */ +heath_igc_ultra_tlb_device::heath_igc_ultra_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + heath_igc_tlb_device(mconfig, HEATH_IGC_ULTRA, tag, owner, clock) +{ +} + +void heath_igc_ultra_tlb_device::device_add_mconfig(machine_config &config) +{ + heath_tlb_device::device_add_mconfig(config); + + m_maincpu->set_addrmap(AS_PROGRAM, &heath_igc_ultra_tlb_device::mem_map); +} + +void heath_igc_ultra_tlb_device::mem_map(address_map &map) +{ + heath_tlb_device::mem_map(map); + + // update rom mirror setting to allow page 2 memory + map(0x0000, 0x0fff).mirror(0x2000).rom(); + + // Page 2 memory + map(0x1000, 0x1fff).mirror(0x2000).ram(); +} + +const tiny_rom_entry *heath_igc_ultra_tlb_device::device_rom_region() const +{ + return ROM_NAME(ultra19); +} + +ioport_constructor heath_igc_ultra_tlb_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(ultra19); +} + + +/** + * SigmaSoft and Systems IGC plus TLB with Watzman ROM + * + */ +heath_igc_watz_tlb_device::heath_igc_watz_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + heath_igc_tlb_device(mconfig, HEATH_IGC_WATZ, tag, owner, clock) +{ +} + +const tiny_rom_entry *heath_igc_watz_tlb_device::device_rom_region() const +{ + return ROM_NAME(watz19); +} + +ioport_constructor heath_igc_watz_tlb_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(watz19); +} + + +/** + * Terminal Logic Board Connector + * + */ +heath_tlb_connector::heath_tlb_connector(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + device_t(mconfig, HEATH_TLB_CONNECTOR, tag, owner, clock), + device_single_card_slot_interface(mconfig, *this), + m_write_sd(*this), + m_dtr_cb(*this), + m_rts_cb(*this), + m_reset(*this), + m_tlb(nullptr) +{ +} + +heath_tlb_connector::~heath_tlb_connector() +{ +} + +void heath_tlb_connector::device_start() +{ + m_tlb = get_card_device(); +} diff --git a/src/mame/heathzenith/tlb.h b/src/mame/heathzenith/tlb.h new file mode 100644 index 00000000000..4763f5ffe98 --- /dev/null +++ b/src/mame/heathzenith/tlb.h @@ -0,0 +1,477 @@ +// license:BSD-3-Clause +// copyright-holders:Mark Garlanger +/*************************************************************************** + + Heathkit Terminal Logic Board (TLB) + +****************************************************************************/ + +#ifndef MAME_HEATHKIT_TLB_H +#define MAME_HEATHKIT_TLB_H + +#pragma once + +#include "cpu/z80/z80.h" +#include "machine/clock.h" +#include "machine/ins8250.h" +#include "machine/mm5740.h" +#include "sound/beep.h" +#include "video/mc6845.h" + +#include "emupal.h" +#include "screen.h" +#include "speaker.h" + + +class heath_tlb_connector; + +class device_heath_tlb_card_interface : public device_interface +{ +public: + + // required operation + virtual void serial_in_w(int state) = 0; + + // optional operations + virtual void rlsd_in_w(int state) {} + virtual void dsr_in_w(int state) {} + virtual void cts_in_w(int state) {} + + // optional SigmaSet operations + virtual void sigma_ctrl_w(u8 data) {} + virtual u8 sigma_ctrl_r() { return 0x00; } + virtual u8 sigma_video_mem_r() { return 0x00; } + virtual void sigma_video_mem_w(u8 val) {} + virtual void sigma_io_lo_addr_w(u8 val) {} + virtual void sigma_io_hi_addr_w(u8 val) {} + virtual void sigma_window_lo_addr_w(u8 val) {} + virtual void sigma_window_hi_addr_w(u8 val) {} + +protected: + device_heath_tlb_card_interface(const machine_config &mconfig, device_t &device); + + heath_tlb_connector *const m_slot; +}; + + +/** + * Standard Heath Terminal logic board + */ +class heath_tlb_device : public device_t, + public device_heath_tlb_card_interface +{ +public: + heath_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + + // 8250 UART + virtual void serial_in_w(int state) override; + virtual void rlsd_in_w(int state) override; + virtual void dsr_in_w(int state) override; + virtual void cts_in_w(int state) override; + void serial_irq_w(int state); + + // Keyboard + void reset_key_w(int state); + void right_shift_w(int state); + void repeat_key_w(int state); + void break_key_w(int state); + +protected: + heath_tlb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock = 0); + + virtual ioport_constructor device_input_ports() const override; + virtual const tiny_rom_entry *device_rom_region() const override; + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_add_mconfig(machine_config &config) override; + + void mem_map(address_map &map); + void io_map(address_map &map); + + + // interrupt related + virtual void set_irq_line(); + + // reset + void check_for_reset(); + + // sound/speaker + void check_beep_state(); + void key_click_w(u8 data); + void bell_w(u8 data); + TIMER_CALLBACK_MEMBER(key_click_off); + TIMER_CALLBACK_MEMBER(bell_off); + + // keyboard + u8 kbd_key_r(); + u8 kbd_flags_r(); + u16 translate_mm5740_b(u16 b); + int mm5740_shift_r(); + int mm5740_control_r(); + void mm5740_data_ready_w(int state); + + // serial port + void serial_out_b(int data); + void dtr_out(int data); + void rts_out(int data); + + // crtc + void crtc_addr_w(offs_t reg, u8 val); + virtual u8 crtc_reg_r(offs_t reg); + virtual void crtc_reg_w(offs_t reg, u8 val); + void crtc_vsync_w(int val); + virtual MC6845_UPDATE_ROW(crtc_update_row); + + required_device m_maincpu; + required_device m_screen; + required_device m_palette; + required_device m_crtc; + required_shared_ptr m_p_videoram; + required_region_ptr m_p_chargen; + required_ioport m_config; + required_device m_ace; + required_device m_beep; + required_device m_mm5740; + required_memory_region m_kbdrom; + required_ioport m_kbspecial; + required_device m_repeat_clock; + + emu_timer *m_key_click_timer; + emu_timer *m_bell_timer; + + u8 m_transchar; + bool m_strobe; + bool m_key_click_active; + bool m_bell_active; + bool m_reset_pending; + bool m_right_shift; + bool m_reset_key; + bool m_keyboard_irq_raised; + bool m_serial_irq_raised; + bool m_break_key_irq_raised; + bool m_allow_vsync_nmi; +}; + +/** + * Heath TLB with Super19 ROM + */ +class heath_super19_tlb_device : public heath_tlb_device +{ +public: + heath_super19_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + +protected: + virtual const tiny_rom_entry *device_rom_region() const override; + virtual ioport_constructor device_input_ports() const override; +}; + +/** + * Heath TLB with Superset ROM + */ +class heath_superset_tlb_device : public heath_tlb_device +{ +public: + heath_superset_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + +protected: + virtual const tiny_rom_entry *device_rom_region() const override; + virtual ioport_constructor device_input_ports() const override; + + virtual void device_start() override; + virtual void device_add_mconfig(machine_config &config) override; + + void mem_map(address_map &map); + void io_map(address_map &map); + + virtual MC6845_UPDATE_ROW(crtc_update_row) override; + + void dtr_internal(int data); + void out1_internal(int data); + void out2_internal(int data); + + virtual u8 crtc_reg_r(offs_t reg) override; + virtual void crtc_reg_w(offs_t reg, u8 val) override; + + u8 m_selected_char_set; + bool m_reverse_video_disabled; +}; + +/** + * Heath TLB with Watzman (HUG) ROM + */ +class heath_watz_tlb_device : public heath_tlb_device +{ +public: + heath_watz_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + +protected: + virtual const tiny_rom_entry *device_rom_region() const override; + virtual ioport_constructor device_input_ports() const override; +}; + +/** + * Heath TLB with Ultra ROM + */ +class heath_ultra_tlb_device : public heath_tlb_device +{ +public: + heath_ultra_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + +protected: + virtual const tiny_rom_entry *device_rom_region() const override; + virtual ioport_constructor device_input_ports() const override; + virtual void device_add_mconfig(machine_config &config) override; + + void mem_map(address_map &map); +}; + +/** + * Heath TLB plus Northwest Digital Systems GP-19 + */ +class heath_gp19_tlb_device : public heath_tlb_device +{ +public: + heath_gp19_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + + static constexpr feature_type imperfect_features() { return feature::GRAPHICS; } + +protected: + virtual const tiny_rom_entry *device_rom_region() const override; + virtual ioport_constructor device_input_ports() const override; + + virtual void device_start() override; + virtual void device_add_mconfig(machine_config &config) override; + + void mem_map(address_map &map); + void io_map(address_map &map); + + void latch_u5_w(u8 data); + + virtual MC6845_UPDATE_ROW(crtc_update_row) override; + + bool m_char_gen_a11; + bool m_graphic_mode; + bool m_col_132; + bool m_reverse_video; +}; + +/** + * Heath TLB plus Cleveland Codonics Imaginator-100 + */ +class heath_imaginator_tlb_device : public heath_tlb_device +{ +public: + heath_imaginator_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + +protected: + virtual const tiny_rom_entry *device_rom_region() const override; + + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_add_mconfig(machine_config &config) override; + + void mem_map(address_map &map); + void io_map(address_map &map); + + virtual MC6845_UPDATE_ROW(crtc_update_row) override; + void crtc_hsync_w(int val); + + IRQ_CALLBACK_MEMBER(irq_ack_cb); + + void tap_6000h(); + void tap_8000h(); + + void allow_tlb_intr(); + void allow_hsync_intr(); + + void display_enable_w(offs_t reg, u8 val); + void config_irq_w(offs_t reg, u8 val); + void nop_w(offs_t reg, u8 val); + virtual void set_irq_line() override; + + required_memory_bank m_mem_bank; + required_shared_ptr m_p_graphic_ram; + memory_passthrough_handler m_tap_6000h; + + u8 m_im2_val; + + bool m_alphanumeric_mode_active; + bool m_graphics_mode_active; + + bool m_allow_tlb_interrupts; + bool m_allow_imaginator_interrupts; + + bool m_hsync_irq_raised; +}; + +/** + * Heath TLB plus SigmaSoft Interactive Graphics Controller + */ +class heath_igc_tlb_device : public heath_tlb_device +{ +public: + heath_igc_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + + virtual void sigma_ctrl_w(u8 data) override; + virtual u8 sigma_ctrl_r() override; + + virtual u8 sigma_video_mem_r() override; + virtual void sigma_video_mem_w(u8 val) override; + + virtual void sigma_io_lo_addr_w(u8 val) override; + virtual void sigma_io_hi_addr_w(u8 val) override; + + virtual void sigma_window_lo_addr_w(u8 val) override; + virtual void sigma_window_hi_addr_w(u8 val) override; + +protected: + heath_igc_tlb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock = 0); + + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_add_mconfig(machine_config &config) override; + + virtual MC6845_UPDATE_ROW(crtc_update_row) override; + + std::unique_ptr m_p_graphic_ram; + + // Control Register + bool m_pixel_video_enabled; + bool m_character_video_disabled; + bool m_video_invert_enabled; + bool m_alternate_character_set_enabled; + bool m_video_fill_enabled; + bool m_read_address_increment_disabled; + u8 m_memory_bank_select; + + u8 m_data_reg; + + u16 m_io_address; + u16 m_window_address; +}; + +/** + * Heath TLB with the super19 ROM plus SigmaSoft Interactive Graphics Controller + */ +class heath_igc_super19_tlb_device : public heath_igc_tlb_device +{ +public: + heath_igc_super19_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + +protected: + virtual const tiny_rom_entry *device_rom_region() const override; + virtual ioport_constructor device_input_ports() const override; +}; + +/** + * Heath TLB with the ultrarom plus SigmaSoft Interactive Graphics Controller + */ +class heath_igc_ultra_tlb_device : public heath_igc_tlb_device +{ +public: + heath_igc_ultra_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + +protected: + virtual const tiny_rom_entry *device_rom_region() const override; + virtual ioport_constructor device_input_ports() const override; + virtual void device_add_mconfig(machine_config &config) override; + + void mem_map(address_map &map); +}; + +/** + * Heath TLB with the watzman ROM plus SigmaSoft Interactive Graphics Controller + */ +class heath_igc_watz_tlb_device : public heath_igc_tlb_device +{ +public: + heath_igc_watz_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + +protected: + virtual const tiny_rom_entry *device_rom_region() const override; + virtual ioport_constructor device_input_ports() const override; +}; + +// Options for the standard H89 class of systems +DECLARE_DEVICE_TYPE(HEATH_TLB, heath_tlb_device) +DECLARE_DEVICE_TYPE(HEATH_GP19, heath_gp19_tlb_device) +DECLARE_DEVICE_TYPE(HEATH_IMAGINATOR, heath_imaginator_tlb_device) +DECLARE_DEVICE_TYPE(HEATH_SUPER19, heath_super19_tlb_device) +DECLARE_DEVICE_TYPE(HEATH_SUPERSET, heath_superset_tlb_device) +DECLARE_DEVICE_TYPE(HEATH_WATZ, heath_watz_tlb_device) +DECLARE_DEVICE_TYPE(HEATH_ULTRA, heath_ultra_tlb_device) + +// Options for the H89 with the SigmaSoft IGC graphics installed +DECLARE_DEVICE_TYPE(HEATH_IGC, heath_igc_tlb_device) +DECLARE_DEVICE_TYPE(HEATH_IGC_SUPER19, heath_igc_super19_tlb_device) +DECLARE_DEVICE_TYPE(HEATH_IGC_ULTRA, heath_igc_ultra_tlb_device) +DECLARE_DEVICE_TYPE(HEATH_IGC_WATZ, heath_igc_watz_tlb_device) + +/** + * Connector for the Terminal Logic Board in an H-89 class computer + */ +class heath_tlb_connector : public device_t, + public device_single_card_slot_interface +{ +public: + + template + heath_tlb_connector(const machine_config &mconfig, const char *tag, device_t *owner, T &&opts, const char *dflt, bool fixed = false) : + heath_tlb_connector(mconfig, tag, owner, 0) + { + option_reset(); + opts(*this); + set_default_option(dflt); + set_fixed(fixed); + } + + heath_tlb_connector(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + virtual ~heath_tlb_connector(); + + // computer interface + auto serial_data_callback() { return m_write_sd.bind(); } + auto dtr_callback() { return m_dtr_cb.bind(); } + auto rts_callback() { return m_rts_cb.bind(); } + auto reset_cb() { return m_reset.bind(); } + + // card interface + void serial_in_w(int state) { if (m_tlb) m_tlb->serial_in_w(state); } + void rlsd_in_w(int state) { if (m_tlb) m_tlb->rlsd_in_w(state); } + void dsr_in_w(int state) { if (m_tlb) m_tlb->dsr_in_w(state); } + void cts_in_w(int state) { if (m_tlb) m_tlb->cts_in_w(state); } + + // signals out from the tlb + void serial_out_b(int data) { m_write_sd(data); } + void dtr_out(int data) { m_dtr_cb(data); } + void rts_out(int data) { m_rts_cb(data); } + void reset_out(int data) { m_reset(data); } + + // optional SigmaSet IGC operations + u8 sigma_ctrl_r() { return (m_tlb) ? m_tlb->sigma_ctrl_r() : 0x00; } + void sigma_ctrl_w(u8 data) { if (m_tlb) m_tlb->sigma_ctrl_w(data); } + + u8 sigma_video_mem_r() { return (m_tlb) ? m_tlb->sigma_video_mem_r() : 0x00; } + void sigma_video_mem_w(u8 val) { if (m_tlb) m_tlb->sigma_video_mem_w(val); } + + void sigma_io_lo_addr_w(u8 val) { if (m_tlb) m_tlb->sigma_io_lo_addr_w(val); } + void sigma_io_hi_addr_w(u8 val) { if (m_tlb) m_tlb->sigma_io_hi_addr_w(val); } + + void sigma_window_lo_addr_w(u8 val) { if (m_tlb) m_tlb->sigma_window_lo_addr_w(val); } + void sigma_window_hi_addr_w(u8 val) { if (m_tlb) m_tlb->sigma_window_hi_addr_w(val); } + +protected: + virtual void device_start() override; + + devcb_write_line m_write_sd; + devcb_write_line m_dtr_cb; + devcb_write_line m_rts_cb; + devcb_write_line m_reset; + + device_heath_tlb_card_interface *m_tlb; +}; + + +// device type definition +DECLARE_DEVICE_TYPE(HEATH_TLB_CONNECTOR, heath_tlb_connector) + +#endif // MAME_HEATHKIT_TLB_H diff --git a/src/mame/heathzenith/z100.cpp b/src/mame/heathzenith/z100.cpp new file mode 100644 index 00000000000..15a2e247bdc --- /dev/null +++ b/src/mame/heathzenith/z100.cpp @@ -0,0 +1,910 @@ +// license:BSD-3-Clause +// copyright-holders:Angelo Salese, AJR +/*************************************************************************** + + Zenith Z-100 + + 15/07/2011 Skeleton driver. + + Commands: + Press DELETE to abort boot, then press H to list all the commands. + + TODO: + - implement S-100 bus features; + - memory test hangs on the first pass; + +============================================================================ + +Z207A EQU 0B0H ; Z-207 disk controller base port + ; (See DEFZ207 to program controller) +Z217A EQU 0AEH ; Z-217 disk controller base port + ; (See DEFZ217 to program controller) +ZGRNSEG EQU 0E000H ; Segment of green video plane +ZREDSEG EQU 0D000H ; Segment of red video plane +ZBLUSEG EQU 0C000H ; Segment of blue video plane +ZVIDEO EQU 0D8H ; Video 68A21 port + ; PA0 -> enable red display + ; PA1 -> enable green display + ; PA2 -> enable blue display + ; PA3 -> not flash screen + ; PA4 -> not write multiple red + ; PA5 -> not write multiple green + ; PA6 -> not write multiple blue + ; PA7 -> disable video RAM + ; PB7-PB0 -> LA15-LA8 + ; CA1 - not used + ; CA2 -> clear screen + ; CB1 - not used + ; CB2 -> value to write (0 or 1) on clear screen + ; (see DEF6821 to program the 6821) +ZCRTC EQU 0DCH ; Video 6845 CRT-C port + ; (see DEF6845 to program the 6845) +ZLPEN EQU 0DEH ; Light pen latch + ZLPEN_BIT EQU 00000111B ; Bit hit by pen + ZLPEN_ROW EQU 11110000B ; Row hit by pen +ZPIA EQU 0E0H ; Parallel printer plus light pen and + ; video vertical retrace 68A21 port + ; PA0 -> PDATA1 + ; PA1 -> PDATA2 + ; PA2 -> not STROBE + ; PA3 -> not INIT + ; PA4 <- VSYNC + ; PA5 -> clear VSYNC flip flop + ; PA6 <- light pen switch + ; PA7 -> clear light pen flip flop + ; PB0 <- BUSY + ; PB1 <- not ERROR + ; PB2 -> PDATA3 + ; PB3 -> PDATA4 + ; PB4 -> PDATA5 + ; PB5 -> PDATA6 + ; PB6 -> PDATA7 + ; PB7 -> PDATA8 + ; CA1 <- light pen hit (from flip flop) + ; CA2 <- VSYNC (from flip flop) + ; CB1 <- not ACKNLG + ; CB2 <- BUSY + ; (See DEF6821 to program the PIA) +ZTIMER EQU 0E4H ; Timer 8253 port + ZTIMEVAL EQU 2500 ; 100ms divide by N value + ; (See DEF8253 to program the 8253) +ZTIMERS EQU 0FBH ; Timer interrupt status port + ZTIMERS0 EQU 001H ; Timer 0 interrupt + ZTIMERS2 EQU 002H ; Timer 2 interrupt +ZSERA EQU 0E8H ; First 2661-2 serial port +ZSERB EQU 0ECH ; Second 2661-2 serial port + ; (See DEFEP2 to program 2661-2) +ZM8259A EQU 0F2H ; Master 8259A interrupt controller port + ZINTEI EQU 0 ; Parity error or S-100 pin 98 interrupt + ZINTPS EQU 1 ; Processor swap interrupt + ZINTTIM EQU 2 ; Timer interrupt + ZINTSLV EQU 3 ; Slave 8259A interrupt + ZINTSA EQU 4 ; Serial port A interrupt + ZINTSB EQU 5 ; Serial port B interrupt + ZINTKD EQU 6 ; Keyboard, Display, or Light pen interrupt + ZINTPP EQU 7 ; Parallel port interrupt + ; (See DEF8259A to program the 8259A) + ZM8259AI EQU 64 ; Base interrupt number for master +ZS8259A EQU 0F0H ; Secondary 8259A interrupt controller port + ZS8259AI EQU 72 ; Base interrupt number for slave + BIOSAI EQU ZS8259AI+8 ; Base of BIOS generated interrupts +ZKEYBRD EQU 0F4H ; Keyboard port + ZKEYBRDD EQU ZKEYBRD+0 ; Keyboard data port + ZKEYBRDC EQU ZKEYBRD+1 ; Keyboard command port + ZKEYRES EQU 0 ; Reset command + ZKEYARD EQU 1 ; Autorepeat on command + ZKEYARF EQU 2 ; Autorepeat off command + ZKEYKCO EQU 3 ; Key click on command + ZKEYKCF EQU 4 ; Key click off command + ZKEYCF EQU 5 ; Clear keyboard FIFO command + ZKEYCLK EQU 6 ; Generate a click sound command + ZKEYBEP EQU 7 ; Generate a beep sound command + ZKEYEK EQU 8 ; Enable keyboard command + ZKEYDK EQU 9 ; Disable keyboard command + ZKEYUDM EQU 10 ; Enter UP/DOWN mode command + ZKEYNSM EQU 11 ; Enter normal scan mode command + ZKEYEI EQU 12 ; Enable keyboard interrupts command + ZKEYDI EQU 13 ; Disable keyboard interrupts command + ZKEYBRDS EQU ZKEYBRD+1 ; Keyboard status port + ZKEYOBF EQU 001H ; Output buffer not empty + ZKEYIBF EQU 002H ; Input buffer full +ZMCL EQU 0FCH ; Memory control latch + ZMCLMS EQU 00000011B ; Map select mask + ZSM0 EQU 0 ; Map select 0 + ZSM1 EQU 1 ; Map select 1 + ZSM2 EQU 2 ; Map select 2 + ZSM3 EQU 3 ; Map select 3 + ZMCLRM EQU 00001100B ; Monitor ROM mapping mask + ZRM0 EQU 0*4 ; Power up mode - ROM everywhere on reads + ZRM1 EQU 1*4 ; ROM at top of every 64K page + ZRM2 EQU 2*4 ; ROM at top of 8088's addr space + ZRM3 EQU 3*4 ; Disable ROM + ZMCLPZ EQU 00010000B ; 0=Set Parity to the zero state + ZMCLPK EQU 00100000B ; 0=Disable parity checking circuity + ZMCLPF EQU 01000000B ; 0=Disable parity error flag +Z205BA EQU 098H ; Base address for Z-205 boards + Z205BMC EQU 8 ; Maximum of 8 Z-205 boards installed +ZHAL EQU 0FDH ; Hi-address latch + ZHAL85 EQU 0FFH ; 8085 Mask + ZHAL88 EQU 0F0H ; 8088 Mask +ZPSP EQU 0FEH ; Processor swap port + ZPSPPS EQU 10000000B ; Processor select (0=8085, 1=8088) + ZPSPPS5 EQU 00000000B ; Select 8085 + ZPSPPS8 EQU 10000000B ; Select 8088 + ZPSPSI EQU 00000010B ; Generate interrupt on swapping + ZPSPI8 EQU 00000001B ; 8088 processes all interrupts +ZDIPSW EQU 0FFH ; Configuration dip switches + ZDIPSWBOOT EQU 00000111B ; Boot device field + ZDIPSWAB EQU 00001000B ; 1=Auto boot(0=Manual boot) + ZDIPSWRES EQU 01110000B ; Reserved + ZDIPSWHZ EQU 10000000B ; 1=50Hz(0=60HZ) + +****************************************************************************/ + +#include "emu.h" +#include "cpu/i86/i86.h" +#include "cpu/i8085/i8085.h" +#include "cpu/mcs48/mcs48.h" +#include "bus/centronics/ctronics.h" +//#include "bus/rs232/rs232.h" +//#include "bus/s100/s100.h" +#include "imagedev/floppy.h" +#include "machine/74123.h" +#include "machine/6821pia.h" +#include "machine/input_merger.h" +#include "machine/pit8253.h" +#include "machine/pic8259.h" +#include "machine/rescap.h" +#include "machine/scn_pci.h" +#include "machine/wd_fdc.h" +#include "sound/beep.h" +#include "video/mc6845.h" +#include "emupal.h" +#include "screen.h" +#include "speaker.h" + + +namespace { + +class z100_state : public driver_device +{ +public: + z100_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag), + m_maincpu(*this, "maincpu"), + m_ram(*this, "ram"), + m_pia(*this, "pia%u", 0U), + m_picm(*this, "pic8259_master"), + m_pics(*this, "pic8259_slave"), + m_fdc(*this, "z207_fdc"), + m_floppies(*this, "z207_fdc:%u", 0U), + m_epci(*this, "epci%u", 0U), + m_keyclick(*this, "keyclick"), + m_keybeep(*this, "keybeep"), + m_beeper(*this, "beeper"), + m_crtc(*this, "crtc"), + m_palette(*this, "palette"), + m_vrmm(*this, "vrmm"), + m_vram_config(*this, "VRAM"), + m_keys(*this, "COL%u", 0U), + m_ctrl(*this, "CTRL"), + m_floppy(nullptr) + { } + + void z100(machine_config &config); + + DECLARE_INPUT_CHANGED_MEMBER(kbd_reset); + +private: + virtual void machine_start() override; + virtual void machine_reset() override; + virtual void video_start() override; + + uint8_t ram_r(offs_t offset); + void ram_w(offs_t offset, uint8_t data); + void memory_ctrl_w(uint8_t data); + offs_t vram_map(offs_t offset) const; + uint8_t z100_vram_r(offs_t offset); + void z100_vram_w(offs_t offset, uint8_t data); + void kbd_col_w(uint8_t data); + uint8_t kbd_rows_r(); + int kbd_shift_row_r(); + void beep_update(int state); + void floppy_select_w(uint8_t data); + void floppy_motor_w(uint8_t data); + uint8_t tmr_status_r(); + void tmr_status_w(uint8_t data); + void timer_flipflop0_w(int state); + void timer_flipflop1_w(int state); + void vidint_w(int state); + void vidint_enable_w(int state); + + u8 get_slave_ack(offs_t offset); + void video_pia_A_w(u8 data); + void video_pia_B_w(u8 data); + void video_pia_CA2_w(int state); + void video_pia_CB2_w(int state); + + MC6845_UPDATE_ROW(update_row); + + void z100_io(address_map &map); + void z100_mem(address_map &map); + + required_device m_maincpu; + required_shared_ptr m_ram; + required_device_array m_pia; + required_device m_picm; + required_device m_pics; + required_device m_fdc; + required_device_array m_floppies; + required_device_array m_epci; + required_device m_keyclick; + required_device m_keybeep; + required_device m_beeper; + required_device m_crtc; + required_device m_palette; + required_region_ptr m_vrmm; + required_ioport m_vram_config; + required_ioport_array<16> m_keys; + required_ioport m_ctrl; + + std::unique_ptr m_gvram; + std::unique_ptr m_parity; + uint8_t m_kbd_col; + uint8_t m_vram_enable; + uint8_t m_gbank; + uint8_t m_display_mask; + uint8_t m_flash; + uint8_t m_clr_val; + uint8_t m_tmr_status; + uint8_t m_start_addr; + bool m_vidint_enable; + uint8_t m_memory_ctrl; + + floppy_image_device *m_floppy; +}; + + +void z100_state::machine_start() +{ + m_parity = make_unique_clear(m_ram.bytes() / 32); +} + +void z100_state::video_start() +{ + m_gvram = make_unique_clear(0x30000); + + m_vidint_enable = false; +} + +uint8_t z100_state::ram_r(offs_t offset) +{ + if (!machine().side_effects_disabled() && BIT(m_memory_ctrl, 5)) + { + uint32_t parity = m_parity[offset >> 5]; + if (BIT(parity, offset & 31)) + m_picm->ir0_w(1); + } + + return m_ram[offset]; +} + +void z100_state::ram_w(offs_t offset, uint8_t data) +{ + if (!machine().side_effects_disabled()) + { + uint32_t &parity = m_parity[offset >> 5]; + if (!BIT(m_memory_ctrl, 4) && BIT(population_count_32(data), 0)) + parity |= 1 << (offset & 31); + else if (parity != 0) + parity &= ~(1 << (offset & 31)); + } + + m_ram[offset] = data; +} + +void z100_state::memory_ctrl_w(uint8_t data) +{ + m_memory_ctrl = data & 0x3f; + if (!BIT(data, 5)) + m_picm->ir0_w(0); +} + +MC6845_UPDATE_ROW(z100_state::update_row) +{ + uint32_t *const pix = &bitmap.pix(y); + const uint16_t amask = m_vram_config->read() ? 0xfff : 0x7ff; + + for (int x = 0; x < x_count; x++) + { + for (int xi = 0; xi < 8; xi++) + { + int dot = 0; + if (m_flash) + { + dot = m_display_mask; + } + else + { + for (int i = 0; i < 3; i++) + dot |= ((m_gvram[((x + ma) & amask) << 4 | (ra & 0xf) | (0x10000*i)] >> (7-xi)) & 1) << i; // b, r, g + + if (x == cursor_x) + dot ^= 7; + + dot &= m_display_mask; + } + + pix[x*8+xi] = m_palette->pen(dot); + } + } +} + +offs_t z100_state::vram_map(offs_t offset) const +{ + // Translate logical address to physical address + return (offset & 0x30000) | (offset & 0x000f) << 4 | (offset & 0x0780) >> 7 + | ((m_vrmm[(offset & 0xf800) >> 8 | (offset & 0x0070) >> 4] + m_start_addr) & (m_vram_config->read() ? 0xff : 0x7f)) << 8; +} + +uint8_t z100_state::z100_vram_r(offs_t offset) +{ + return m_gvram[vram_map(offset)]; +} + +void z100_state::z100_vram_w(offs_t offset, uint8_t data) +{ + if(m_vram_enable) + { + offset = vram_map(offset); + m_gvram[offset] = data; + + for (int i = 0; i < 3; i++) + { + if (BIT(m_gbank, i)) + m_gvram[((offset) & 0xffff)+0x10000*i] = data; + } + } +} + +void z100_state::z100_mem(address_map &map) +{ + map.unmap_value_high(); + map(0x00000, 0x3ffff).rw(FUNC(z100_state::ram_r), FUNC(z100_state::ram_w)).share("ram"); // 128*2 KB RAM +// map(0xb0000,0xbffff).rom(); // expansion ROM + map(0xc0000, 0xeffff).rw(FUNC(z100_state::z100_vram_r), FUNC(z100_state::z100_vram_w)); // Blue / Red / Green +// map(0xf0000,0xf0fff) // network card (NET-100) +// map(0xf4000,0xf7fff) // MTRET-100 Firmware I expansion ROM +// map(0xf8000,0xfbfff) // MTRET-100 Firmware II expansion ROM check ID 0x4550 + map(0xfc000, 0xfffff).rom().region("ipl", 0); +} + +void z100_state::kbd_col_w(uint8_t data) +{ + m_kbd_col = data & 0x0f; + + m_keyclick->b_w(BIT(data, 7)); + m_keybeep->a_w((data & 0x82) == 0); +} + +uint8_t z100_state::kbd_rows_r() +{ + if (m_kbd_col < 0x0c) + return m_keys[m_kbd_col]->read(); + + return 0xff; +} + +int z100_state::kbd_shift_row_r() +{ + if ((m_kbd_col & 0x0c) == 0x0c) + return m_keys[m_kbd_col]->read(); + + return 1; +} + +void z100_state::beep_update(int state) +{ + m_beeper->set_state(m_keyclick->q_r() | m_keybeep->q_r()); +} + +// todo: side select? + +void z100_state::floppy_select_w(uint8_t data) +{ + m_floppy = m_floppies[data & 0x03]->get_device(); + m_fdc->set_floppy(m_floppy); +} + +void z100_state::floppy_motor_w(uint8_t data) +{ + if (m_floppy) + m_floppy->mon_w(!BIT(data, 1)); +} + +uint8_t z100_state::tmr_status_r() +{ + return m_tmr_status; +} + +void z100_state::tmr_status_w(uint8_t data) +{ + m_tmr_status &= data & 3; + if (m_tmr_status == 0) + m_picm->ir2_w(0); +} + +void z100_state::timer_flipflop0_w(int state) +{ + if (state) + { + m_tmr_status |= 1; + m_picm->ir2_w(1); + } +} + +void z100_state::timer_flipflop1_w(int state) +{ + if (state) + { + m_tmr_status |= 2; + m_picm->ir2_w(1); + } +} + +void z100_state::vidint_w(int state) +{ + m_pia[1]->pa4_w(state); + + if (state && m_vidint_enable) + m_pia[1]->ca2_w(1); +} + +void z100_state::vidint_enable_w(int state) +{ + m_vidint_enable = state; + if (!m_vidint_enable) + m_pia[1]->ca2_w(0); +} + +void z100_state::z100_io(address_map &map) +{ + map.unmap_value_high(); + map.global_mask(0xff); +// map(0x00, 0x3f) reserved for non-ZDS vendors +// map(0x40, 0x5f) secondary Multiport card (Z-204) +// map(0x60, 0x7f) primary Multiport card (Z-204) +// map(0x80, 0x83) development board +// map(0x98, 0x9f) Z-205 expansion memory boards +// map(0xa0, 0xa3) network card (NET-100) +// map(0xa4, 0xa7) gateway (reserved) +// map(0xac, 0xad) Z-217 secondary disk controller (winchester) +// map(0xae, 0xaf) Z-217 primary disk controller (winchester) + map(0xb0, 0xb3).rw(m_fdc, FUNC(fd1797_device::read), FUNC(fd1797_device::write)); + map(0xb4, 0xb4).w(FUNC(z100_state::floppy_select_w)); + map(0xb5, 0xb5).w(FUNC(z100_state::floppy_motor_w)); +// z-207 secondary disk controller (wd1797) +// map(0xcd, 0xce) ET-100 CRT Controller +// map(0xd4, 0xd7) ET-100 Trainer Parallel I/O + map(0xd8, 0xdb).rw(m_pia[0], FUNC(pia6821_device::read), FUNC(pia6821_device::write)); //video board + map(0xdc, 0xdc).w(m_crtc, FUNC(mc6845_device::address_w)); + map(0xdd, 0xdd).w(m_crtc, FUNC(mc6845_device::register_w)); +// map(0xde, 0xde) light pen + map(0xe0, 0xe3).rw(m_pia[1], FUNC(pia6821_device::read), FUNC(pia6821_device::write)); //main board + map(0xe4, 0xe7).rw("pit", FUNC(pit8253_device::read), FUNC(pit8253_device::write)); + map(0xe8, 0xeb).rw(m_epci[0], FUNC(scn2661b_device::read), FUNC(scn2661b_device::write)); + map(0xec, 0xef).rw(m_epci[1], FUNC(scn2661b_device::read), FUNC(scn2661b_device::write)); + map(0xf0, 0xf1).rw(m_pics, FUNC(pic8259_device::read), FUNC(pic8259_device::write)); + map(0xf2, 0xf3).rw(m_picm, FUNC(pic8259_device::read), FUNC(pic8259_device::write)); + map(0xf4, 0xf5).rw("kbdc", FUNC(i8041a_device::upi41_master_r), FUNC(i8041a_device::upi41_master_w)); +// map(0xf6, 0xf6) expansion ROM is present (bit 0, active low) + map(0xfb, 0xfb).rw(FUNC(z100_state::tmr_status_r), FUNC(z100_state::tmr_status_w)); + map(0xfc, 0xfc).w(FUNC(z100_state::memory_ctrl_w)); +// map(0xfd, 0xfd) Hi-address latch +// map(0xfe, 0xfe) Processor swap port + map(0xff, 0xff).portr("DSW101"); +} + +INPUT_CHANGED_MEMBER(z100_state::kbd_reset) +{ + if (m_ctrl->read() == 0) + reset(); +} + +/* Input ports */ +INPUT_PORTS_START( z100 ) + PORT_START("COL0") // 15 + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('a') PORT_CHAR('A') PORT_CODE(KEYCODE_A) + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('s') PORT_CHAR('S') PORT_CODE(KEYCODE_S) + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('d') PORT_CHAR('D') PORT_CODE(KEYCODE_D) + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('f') PORT_CHAR('F') PORT_CODE(KEYCODE_F) + PORT_BIT(0x08, 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('h') PORT_CHAR('H') PORT_CODE(KEYCODE_H) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('j') PORT_CHAR('J') PORT_CODE(KEYCODE_J) + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('k') PORT_CHAR('K') PORT_CODE(KEYCODE_K) + + PORT_START("COL1") // 11 + PORT_BIT(0x80, 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('w') PORT_CHAR('W') PORT_CODE(KEYCODE_W) + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('e') PORT_CHAR('E') PORT_CODE(KEYCODE_E) + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('r') PORT_CHAR('R') PORT_CODE(KEYCODE_R) + PORT_BIT(0x08, 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('y') PORT_CHAR('Y') PORT_CODE(KEYCODE_Y) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('u') PORT_CHAR('U') PORT_CODE(KEYCODE_U) + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('i') PORT_CHAR('I') PORT_CODE(KEYCODE_I) + + PORT_START("COL2") // 16 + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('z') PORT_CHAR('Z') PORT_CODE(KEYCODE_Z) + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('x') PORT_CHAR('X') PORT_CODE(KEYCODE_X) + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('c') PORT_CHAR('C') PORT_CODE(KEYCODE_C) + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('v') PORT_CHAR('V') PORT_CODE(KEYCODE_V) + PORT_BIT(0x08, 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('n') PORT_CHAR('N') PORT_CODE(KEYCODE_N) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('m') PORT_CHAR('M') PORT_CODE(KEYCODE_M) + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('l') PORT_CHAR('L') PORT_CODE(KEYCODE_L) + + PORT_START("COL3") // 13 + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('p') PORT_CHAR('P') PORT_CODE(KEYCODE_P) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('o') PORT_CHAR('O') PORT_CODE(KEYCODE_O) + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED) + + PORT_START("COL4") // 9 + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F0") + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F1)) PORT_CODE(KEYCODE_F1) + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F2)) PORT_CODE(KEYCODE_F2) + PORT_BIT(0x10, 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(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F5)) PORT_CODE(KEYCODE_F5) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F6)) PORT_CODE(KEYCODE_F6) + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F7)) PORT_CODE(KEYCODE_F7) + + PORT_START("COL5") // 12 + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Del/Ins Char") PORT_CODE(KEYCODE_F14) + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Del/Ins Line") PORT_CODE(KEYCODE_F13) + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F12)) PORT_CODE(KEYCODE_F12) + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F11)) PORT_CODE(KEYCODE_F11) + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F10)) PORT_CODE(KEYCODE_F10) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F9)) PORT_CODE(KEYCODE_F9) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F8)) PORT_CODE(KEYCODE_F8) + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED) + + PORT_START("COL6") // 17 + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(HOME)) PORT_CODE(KEYCODE_HOME) + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD)) PORT_CODE(KEYCODE_7_PAD) + PORT_BIT(0x20, 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(UCHAR_MAMEKEY(1_PAD)) PORT_CODE(KEYCODE_1_PAD) + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) PORT_CODE(KEYCODE_RIGHT) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD)) PORT_CODE(KEYCODE_9_PAD) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD)) PORT_CODE(KEYCODE_6_PAD) + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD)) PORT_CODE(KEYCODE_3_PAD) + + PORT_START("COL7") // 18 + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) PORT_CODE(KEYCODE_LEFT) + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD)) PORT_CODE(KEYCODE_8_PAD) + PORT_BIT(0x20, 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(UCHAR_MAMEKEY(2_PAD)) PORT_CODE(KEYCODE_2_PAD) + PORT_BIT(0x08, 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(DOWN)) PORT_CODE(KEYCODE_DOWN) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD)) PORT_CODE(KEYCODE_MINUS_PAD) + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD)) PORT_CODE(KEYCODE_ENTER_PAD) + + PORT_START("COL8") // 3 + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Break") + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Help") + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(' ') PORT_CODE(KEYCODE_SPACE) + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(0x0a) PORT_CODE(KEYCODE_RALT) PORT_NAME("Line Feed") + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('\\') PORT_CHAR('|') PORT_CODE(KEYCODE_BACKSLASH) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(DEL)) PORT_CODE(KEYCODE_DEL) PORT_NAME("Delete") + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD)) PORT_CODE(KEYCODE_0_PAD) + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD)) PORT_CODE(KEYCODE_DEL_PAD) + + PORT_START("COL9") // 7 + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(0x1b) PORT_CODE(KEYCODE_ESC) + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(0x09) PORT_CODE(KEYCODE_TAB) + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(',') PORT_CHAR('<') PORT_CODE(KEYCODE_COMMA) + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(0x0d) PORT_CODE(KEYCODE_ENTER) PORT_NAME("Return") + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('/') PORT_CHAR('?') PORT_CODE(KEYCODE_SLASH) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('.') PORT_CHAR('>') PORT_CODE(KEYCODE_STOP) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(';') PORT_CHAR(':') PORT_CODE(KEYCODE_COLON) + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('\'') PORT_CHAR('"') PORT_CODE(KEYCODE_QUOTE) + + PORT_START("COL10") // 10 + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('1') PORT_CHAR('!') PORT_CODE(KEYCODE_1) + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('2') PORT_CHAR('@') PORT_CODE(KEYCODE_2) + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('3') PORT_CHAR('#') PORT_CODE(KEYCODE_3) + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('4') PORT_CHAR('$') PORT_CODE(KEYCODE_4) + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('5') PORT_CHAR('%') PORT_CODE(KEYCODE_5) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('6') PORT_CHAR('^') PORT_CODE(KEYCODE_6) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('7') PORT_CHAR('&') PORT_CODE(KEYCODE_7) + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('8') PORT_CHAR('*') PORT_CODE(KEYCODE_8) + + PORT_START("COL11") // 14 + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(0x08) PORT_CODE(KEYCODE_BACKSPACE) PORT_NAME("Back Space") + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('`') PORT_CHAR('~') PORT_CODE(KEYCODE_TILDE) // ~ key is between BS and = + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('=') PORT_CHAR('+') PORT_CODE(KEYCODE_EQUALS) + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('-') PORT_CHAR('_') PORT_CODE(KEYCODE_MINUS) + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('0') PORT_CHAR(')') PORT_CODE(KEYCODE_0) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('9') PORT_CHAR('(') PORT_CODE(KEYCODE_9) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('[') PORT_CHAR('{') PORT_CODE(KEYCODE_OPENBRACE) + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(']') PORT_CHAR('}') PORT_CODE(KEYCODE_CLOSEBRACE) + + PORT_START("COL12") // 5 + PORT_BIT(1, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_SHIFT_1) PORT_CODE(KEYCODE_LSHIFT) PORT_NAME("Shift Left") + + PORT_START("COL13") // 8 + PORT_BIT(1, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RSHIFT) PORT_NAME("Shift Right") + + PORT_START("COL14") // 6 + PORT_BIT(1, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK)) PORT_CODE(KEYCODE_CAPSLOCK) + + PORT_START("COL15") // 1 + PORT_BIT(1, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LALT) PORT_NAME("Fast Repeat") + + PORT_START("CTRL") // 2 & 4 + PORT_BIT(1, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_NAME("Ctrl") PORT_CHANGED_MEMBER(DEVICE_SELF, z100_state, kbd_reset, 0) + PORT_BIT(2, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Reset") PORT_CHANGED_MEMBER(DEVICE_SELF, z100_state, kbd_reset, 0) + + PORT_START("DSW101") + PORT_DIPNAME( 0x07, 0x00, "Default Auto-boot Device" ) + PORT_DIPSETTING( 0x00, "0" ) + PORT_DIPSETTING( 0x01, "1" ) + PORT_DIPSETTING( 0x02, "2" ) + PORT_DIPSETTING( 0x03, "3" ) + PORT_DIPSETTING( 0x04, "4" ) + PORT_DIPSETTING( 0x05, "5" ) + PORT_DIPSETTING( 0x06, "6" ) + PORT_DIPSETTING( 0x07, "7" ) + PORT_DIPNAME( 0x08, 0x08, "Auto-boot" ) + PORT_DIPSETTING( 0x00, DEF_STR( No ) ) + PORT_DIPSETTING( 0x08, DEF_STR( Yes ) ) + PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) ) // Reserved + PORT_DIPSETTING( 0x10, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) ) // Reserved + PORT_DIPSETTING( 0x20, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) ) // Reserved + PORT_DIPSETTING( 0x40, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x80, 0x00, "Monitor" ) + PORT_DIPSETTING( 0x80, "PAL 50 Hz" ) + PORT_DIPSETTING( 0x00, "NTSC 60 Hz" ) + + PORT_START("CONFIG") + PORT_CONFNAME( 0x01, 0x01, "Video Board" ) + PORT_CONFSETTING( 0x00, "Monochrome" ) + PORT_CONFSETTING( 0x01, "Color" ) + + PORT_START("VRAM") + PORT_DIPNAME( 0x01, 0x01, "Video Memory" ) PORT_DIPLOCATION("J307:1") + PORT_DIPSETTING( 0x00, "32K" ) + PORT_DIPSETTING( 0x01, "64K" ) +INPUT_PORTS_END + +u8 z100_state::get_slave_ack(offs_t offset) +{ + if (offset==7) { // IRQ = 7 + return m_pics->acknowledge(); + } + return 0; +} + +void z100_state::video_pia_A_w(u8 data) +{ + /* + all bits are active low + x--- ---- -> disable video RAM + -x-- ---- -> not write multiple blue + --x- ---- -> not write multiple green + ---x ---- -> not write multiple red + ---- x--- -> not flash screen + ---- -x-- -> enable blue display + ---- --x- -> enable green display + ---- ---x -> enable red display + */ + + m_vram_enable = ((data & 0x80) >> 7) ^ 1; + m_gbank = bitswap<8>(((data & 0x70) >> 4) ^ 0x7,7,6,5,4,3,1,0,2); + m_flash = ((data & 8) >> 3) ^ 1; + m_display_mask = bitswap<8>((data & 7) ^ 7,7,6,5,4,3,1,0,2); +} + +void z100_state::video_pia_B_w(u8 data) +{ + m_start_addr = data; +} + +/* clear screen */ +void z100_state::video_pia_CA2_w(int state) +{ + int i; + + for(i=0; i<0x30000; i++) + m_gvram[i] = m_clr_val; +} + +void z100_state::video_pia_CB2_w(int state) +{ + m_clr_val = (state & 1) ? 0x00 : 0xff; +} + +void z100_state::machine_reset() +{ + int i; + + if(ioport("CONFIG")->read() & 1) + { + for(i=0;i<8;i++) + m_palette->set_pen_color(i,pal1bit(i >> 1),pal1bit(i >> 2),pal1bit(i >> 0)); + } + else + { + for(i=0;i<8;i++) + m_palette->set_pen_color(i,pal3bit(0),pal3bit(i),pal3bit(0)); + } + + memory_ctrl_w(0); +} + +static void z100_floppies(device_slot_interface &device) +{ + device.option_add("dd", FLOPPY_525_DD); +} + +void z100_state::z100(machine_config &config) +{ + /* basic machine hardware */ + I8088(config, m_maincpu, 15_MHz_XTAL / 3); // 5 MHz or 8 MHz depending on XTAL + m_maincpu->set_addrmap(AS_PROGRAM, &z100_state::z100_mem); + m_maincpu->set_addrmap(AS_IO, &z100_state::z100_io); + m_maincpu->set_irq_acknowledge_callback("pic8259_master", FUNC(pic8259_device::inta_cb)); + + I8085A(config, "cpu85", 10_MHz_XTAL).set_disable(); + + i8041a_device &kbdc(I8041A(config, "kbdc", 6_MHz_XTAL)); + kbdc.p1_in_cb().set(FUNC(z100_state::kbd_rows_r)); + kbdc.p2_out_cb().set(FUNC(z100_state::kbd_col_w)); + kbdc.p2_out_cb().append("keydspyint", FUNC(input_merger_device::in_w<0>)).bit(4); + kbdc.t0_in_cb().set_ioport("CTRL").bit(0); + kbdc.t1_in_cb().set(FUNC(z100_state::kbd_shift_row_r)); + + TTL74123(config, m_keyclick, RES_K(150), CAP_U(.1)); + m_keyclick->set_connection_type(TTL74123_NOT_GROUNDED_NO_DIODE); + m_keyclick->set_a_pin_value(0); + m_keyclick->set_b_pin_value(1); + m_keyclick->set_clear_pin_value(1); + m_keyclick->out_cb().set(FUNC(z100_state::beep_update)); + + TTL74123(config, m_keybeep, RES_K(220), CAP_U(2.2)); + m_keybeep->set_connection_type(TTL74123_NOT_GROUNDED_NO_DIODE); + m_keybeep->set_b_pin_value(1); + m_keybeep->set_clear_pin_value(1); + m_keybeep->out_cb().set(FUNC(z100_state::beep_update)); + + SPEAKER(config, "mono").front_center(); + BEEP(config, m_beeper, 1'000'000'000 / PERIOD_OF_555_ASTABLE_NSEC(RES_K(470), RES_K(470), CAP_U(.001))); + m_beeper->add_route(ALL_OUTPUTS, "mono", 0.50); + + /* video hardware */ + screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); + screen.set_raw(14.112_MHz_XTAL, 912, 0, 640, 258, 0, 216); + screen.set_screen_update("crtc", FUNC(mc6845_device::screen_update)); + + PALETTE(config, m_palette).set_entries(8); + + /* devices */ + MC6845(config, m_crtc, 14.112_MHz_XTAL / 8); // 68A45 + 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(z100_state::update_row)); + m_crtc->out_vsync_callback().set(FUNC(z100_state::vidint_w)); + + PIC8259(config, m_picm); + m_picm->out_int_callback().set_inputline(m_maincpu, 0); + m_picm->in_sp_callback().set_constant(1); + m_picm->read_slave_ack_callback().set(FUNC(z100_state::get_slave_ack)); + + PIC8259(config, m_pics); + m_pics->out_int_callback().set(m_picm, FUNC(pic8259_device::ir3_w)); + m_pics->in_sp_callback().set_constant(0); + + pit8253_device &pit(PIT8253(config, "pit")); + pit.set_clk<0>(4_MHz_XTAL / 16); + pit.out_handler<0>().set(FUNC(z100_state::timer_flipflop0_w)); + pit.out_handler<0>().append("pit", FUNC(pit8253_device::write_clk1)); + pit.set_clk<2>(4_MHz_XTAL / 16); + pit.out_handler<2>().set(FUNC(z100_state::timer_flipflop1_w)); + + PIA6821(config, m_pia[0]); + m_pia[0]->writepa_handler().set(FUNC(z100_state::video_pia_A_w)); + m_pia[0]->writepb_handler().set(FUNC(z100_state::video_pia_B_w)); + m_pia[0]->ca2_handler().set(FUNC(z100_state::video_pia_CA2_w)); + m_pia[0]->cb2_handler().set(FUNC(z100_state::video_pia_CB2_w)); + + PIA6821(config, m_pia[1]); + m_pia[1]->irqa_handler().set("keydspyint", FUNC(input_merger_device::in_w<1>)); + m_pia[1]->irqb_handler().set(m_picm, FUNC(pic8259_device::ir7_w)); + m_pia[1]->writepa_handler().set("centronics", FUNC(centronics_device::write_strobe)).bit(2); + m_pia[1]->writepa_handler().append("centronics", FUNC(centronics_device::write_data0)).bit(0); + m_pia[1]->writepa_handler().append("centronics", FUNC(centronics_device::write_data1)).bit(1); + m_pia[1]->writepa_handler().append("centronics", FUNC(centronics_device::write_init)).bit(3); + m_pia[1]->writepa_handler().append(FUNC(z100_state::vidint_enable_w)).bit(5); + m_pia[1]->writepb_handler().set("centronics", FUNC(centronics_device::write_data2)).bit(2); + m_pia[1]->writepb_handler().append("centronics", FUNC(centronics_device::write_data3)).bit(3); + m_pia[1]->writepb_handler().append("centronics", FUNC(centronics_device::write_data4)).bit(4); + m_pia[1]->writepb_handler().append("centronics", FUNC(centronics_device::write_data5)).bit(5); + m_pia[1]->writepb_handler().append("centronics", FUNC(centronics_device::write_data6)).bit(6); + m_pia[1]->writepb_handler().append("centronics", FUNC(centronics_device::write_data7)).bit(7); + + centronics_device ¢ronics(CENTRONICS(config, "centronics", centronics_devices, nullptr)); + centronics.ack_handler().set(m_pia[1], FUNC(pia6821_device::cb1_w)).invert(); + centronics.busy_handler().set(m_pia[1], FUNC(pia6821_device::cb2_w)); + centronics.busy_handler().append(m_pia[1], FUNC(pia6821_device::pb0_w)); + centronics.perror_handler().set(m_pia[1], FUNC(pia6821_device::pb1_w)); + + input_merger_device &keydspyint(INPUT_MERGER_ANY_HIGH(config, "keydspyint")); + keydspyint.output_handler().set(m_picm, FUNC(pic8259_device::ir6_w)); + + FD1797(config, m_fdc, 4_MHz_XTAL / 4); + + FLOPPY_CONNECTOR(config, m_floppies[0], z100_floppies, "dd", floppy_image_device::default_mfm_floppy_formats); + FLOPPY_CONNECTOR(config, m_floppies[1], z100_floppies, "dd", floppy_image_device::default_mfm_floppy_formats); + FLOPPY_CONNECTOR(config, m_floppies[2], z100_floppies, nullptr, floppy_image_device::default_mfm_floppy_formats); + FLOPPY_CONNECTOR(config, m_floppies[3], z100_floppies, nullptr, floppy_image_device::default_mfm_floppy_formats); + + SCN2661B(config, m_epci[0], 4.9152_MHz_XTAL); // First 2661-2 serial port (printer) + m_epci[0]->txrdy_handler().set("epci0int", FUNC(input_merger_device::in_w<0>)); + m_epci[0]->rxrdy_handler().set("epci0int", FUNC(input_merger_device::in_w<1>)); + + SCN2661B(config, m_epci[1], 4.9152_MHz_XTAL); // Second 2661-2 serial port (modem) + m_epci[1]->txrdy_handler().set("epci1int", FUNC(input_merger_device::in_w<0>)); + m_epci[1]->rxrdy_handler().set("epci1int", FUNC(input_merger_device::in_w<1>)); + + input_merger_device &epci0int(INPUT_MERGER_ANY_HIGH(config, "epci0int")); + epci0int.output_handler().set(m_picm, FUNC(pic8259_device::ir4_w)); + + input_merger_device &epci1int(INPUT_MERGER_ANY_HIGH(config, "epci1int")); + epci1int.output_handler().set(m_picm, FUNC(pic8259_device::ir5_w)); +} + +/* ROM definition */ +ROM_START( z100 ) + ROM_REGION(0x4000, "ipl", 0) + ROM_LOAD("intel-d27128-1.bin", 0x0000, 0x4000, CRC(b21f0392) SHA1(69e492891cceb143a685315efe0752981a2d8143)) + + ROM_REGION(0x0400, "kbdc", 0) // 8041A keyboard controller + ROM_LOAD("444-109.u204", 0x0000, 0x0400, CRC(45181029) SHA1(0e89649364d25cf2d8669d2a293ee162e274cb64)) + + // All PROMs are typed in from Zenith technical manual listings rather than dumped from real devices, and are accordingly marked BAD_DUMP + ROM_REGION(0x0100, "iodec", 0) // 82S129 I/O Decoder PROM + ROM_LOAD("444-101.u179", 0x0000, 0x0100, CRC(c952be82) SHA1(0edf9265d302f8478a310858eb6a9352f0cda17b) BAD_DUMP) + + ROM_REGION(0x0100, "memdec", 0) // 82S129 Memory Decoder PROM + ROM_LOAD("444-104.u111", 0x0000, 0x0100, CRC(46edd69d) SHA1(5d4bafeaa4593e419bf94dba9e44c8b2be58727b) BAD_DUMP) + + ROM_REGION(0x0020, "status", 0) // 82S123 CPU Status Decode PROM + ROM_LOAD("444-105.u226", 0x0000, 0x0020, CRC(98b084e9) SHA1(d968b9a1b1d2ba3ed40036c2192c9960a6c15e99) BAD_DUMP) + + ROM_REGION(0x0100, "vramsel", 0) // 82S129 Video RAM Select PROM + ROM_LOAD("444-102.u371", 0x0000, 0x0100, CRC(4558f540) SHA1(55c9bad87b111537a6d386a6eb405169fb47304c) BAD_DUMP) + + ROM_REGION(0x0100, "viosel", 0) // 82S129 Video I/O Select PROM + ROM_LOAD("444-103.u369", 0x0000, 0x0100, CRC(854cef15) SHA1(836b244dac0085bcfe8006fde0c5f19982969236) BAD_DUMP) + + ROM_REGION(0x0100, "vrmm", 0) // TBP18S22 Video RAM Mapping Module + ROM_LOAD("444-127.u370", 0x0000, 0x0100, CRC(ac386f6b) SHA1(2b62b939d704d90edf59923a8a1a51ef1902f4d7) BAD_DUMP) +ROM_END + +} // anonymous namespace + + +/* Driver */ + +// YEAR NAME PARENT COMPAT MACHINE INPUT STATE INIT COMPANY FULLNAME FLAGS +COMP( 1982, z100, 0, 0, z100, z100, z100_state, empty_init, "Zenith Data Systems", "Z-100", MACHINE_NOT_WORKING ) diff --git a/src/mame/heathzenith/z22.cpp b/src/mame/heathzenith/z22.cpp new file mode 100644 index 00000000000..a9fcab693f1 --- /dev/null +++ b/src/mame/heathzenith/z22.cpp @@ -0,0 +1,221 @@ +// 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" + + +namespace { + +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); + + void eeprom_clock_w(int state); + + void mem_map(address_map &map); + + required_device m_maincpu; + required_device m_crtc; + optional_device_array m_uart; + required_device m_eeprom; + required_shared_ptr m_dispram; + required_shared_ptr 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.pix(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)); +} + +void z22_state::eeprom_clock_w(int state) +{ + 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 + +} // anonymous namespace + + +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/heathzenith/z29.cpp b/src/mame/heathzenith/z29.cpp new file mode 100644 index 00000000000..d54273430fe --- /dev/null +++ b/src/mame/heathzenith/z29.cpp @@ -0,0 +1,180 @@ +// license:BSD-3-Clause +// copyright-holders:AJR +/*************************************************************************** + + Skeleton driver for Zenith Z-29 (alias Heathkit H-29) video terminal. + +****************************************************************************/ + +#include "emu.h" +//#include "bus/rs232/rs232.h" +#include "bus/z29_kbd/keyboard.h" +#include "cpu/mcs51/mcs51.h" +#include "machine/x2212.h" +#include "video/i8275.h" +#include "screen.h" + + +namespace { + +class z29_state : public driver_device +{ +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) + { + } + + void z29(machine_config &config); + +protected: + virtual void machine_start() override; + +private: + void keyin_w(int state); + u8 p1_r(); + void p3_w(u8 data); + u8 bs_24k_r(offs_t offset); + void crtc_w(offs_t offset, u8 data); + void latch_12k_w(u8 data); + + void prg_map(address_map &map); + void ext_map(address_map &map); + + required_device m_maincpu; + required_device m_keyboard; + required_device_array m_crtc; + required_device m_nvram; + + required_shared_ptr m_charmem; + required_shared_ptr m_attrmem; + required_region_ptr m_chargen; + + bool m_dmatype; + bool m_keyin; +}; + +void z29_state::machine_start() +{ + save_item(NAME(m_dmatype)); + save_item(NAME(m_keyin)); +} + +void z29_state::keyin_w(int state) +{ + m_keyin = state; +} + +u8 z29_state::p1_r() +{ + return m_keyin ? 0xfd : 0xff; +} + +void z29_state::p3_w(u8 data) +{ + m_dmatype = BIT(data, 4); +} + +u8 z29_state::bs_24k_r(offs_t offset) +{ + if (!machine().side_effects_disabled()) + { + if (m_dmatype) + { + u8 chardata = m_charmem[offset]; + u8 attrdata = m_attrmem[offset] & 0xf; + + m_crtc[0]->dack_w(chardata & 0x7f); + m_crtc[1]->dack_w((chardata & 0x60) | (BIT(chardata, 7) ? 0x10 : 0) | attrdata); + } + else + { + m_charmem[offset] = 0x20; + m_attrmem[offset] = 0; + } + } + + return m_dmatype ? 0x24 : 0x20; +} + +void z29_state::crtc_w(offs_t offset, u8 data) +{ + m_crtc[0]->write(offset, data); + m_crtc[1]->write(offset, data); +} + +void z29_state::latch_12k_w(u8 data) +{ + m_nvram->store(!BIT(data, 0)); + m_nvram->recall(!BIT(data, 3)); +} + +void z29_state::prg_map(address_map &map) +{ + map(0x0000, 0x1fff).rom().region("maincpu", 0); + map(0x6000, 0x67ff).mirror(0x800).r(FUNC(z29_state::bs_24k_r)); +} + +void z29_state::ext_map(address_map &map) +{ + map(0x2000, 0x2001).mirror(0xffe).r("crtc1", FUNC(i8276_device::read)).w(FUNC(z29_state::crtc_w)); + map(0x3000, 0x3000).mirror(0xfff).w(FUNC(z29_state::latch_12k_w)); + map(0x4000, 0x47ff).mirror(0x800).ram().share("attrmem"); + map(0x5000, 0x57ff).mirror(0x800).ram().share("charmem"); + map(0x7000, 0x703f).mirror(0xfc0).rw("nvram", FUNC(x2210_device::read), FUNC(x2210_device::write)); +} + + +static INPUT_PORTS_START(z29) +INPUT_PORTS_END + + +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(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"); + 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)); + + I8276(config, m_crtc[0], 14.784_MHz_XTAL / 8).set_character_width(8); + m_crtc[0]->drq_wr_callback().set_inputline(m_maincpu, MCS51_INT0_LINE); + 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); +} + + +ROM_START(z29) // All EPROMs on 85-2835-1 terminal board are HN482732AG-30 + ROM_REGION(0x2000, "maincpu", 0) + ROM_LOAD("u440.bin", 0x0000, 0x1000, CRC(169b9517) SHA1(c18b6a193655a64808e9ae8765d3e54d13e6669e)) // occupies pins 9-32 of 40-pin expansion socket + ROM_LOAD("u407.bin", 0x1000, 0x1000, CRC(b5aae8e6) SHA1(692e521a85d7e07647c66a660faa2041d1bfd785)) + + ROM_REGION(0x1000, "chargen", 0) + ROM_LOAD("u429.bin", 0x0000, 0x1000, CRC(5e3bc5bf) SHA1(18d73e3d74a9768bee8b063ea45891f955558ae7)) +ROM_END + +} // anonymous namespace + +// year name parent compat machine input class init company fullname flags +COMP( 1983, z29, 0, 0, z29, z29, z29_state, empty_init, "Zenith Data Systems", "Z-29 Terminal", MACHINE_IS_SKELETON) diff --git a/src/mame/heathzenith/z37_fdc.cpp b/src/mame/heathzenith/z37_fdc.cpp new file mode 100644 index 00000000000..669bd5b8722 --- /dev/null +++ b/src/mame/heathzenith/z37_fdc.cpp @@ -0,0 +1,235 @@ +// license:BSD-3-Clause +// copyright-holders:Mark Garlanger +/*************************************************************************** + + Heathkit Z-37 Floppy controller + + This was an option for both the Heathkit H8 and H89 computer systems. + +****************************************************************************/ + +#include "emu.h" + +#include "z37_fdc.h" + +#define LOG_REG (1U << 1) // Shows register setup +#define LOG_LINES (1U << 2) // Show control lines +#define LOG_DRIVE (1U << 3) // Show drive select +#define LOG_FUNC (1U << 4) // Function calls + +#define VERBOSE (0) + +#include "logmacro.h" + +#define LOGREG(...) LOGMASKED(LOG_REG, __VA_ARGS__) +#define LOGLINES(...) LOGMASKED(LOG_LINES, __VA_ARGS__) +#define LOGDRIVE(...) LOGMASKED(LOG_DRIVE, __VA_ARGS__) +#define LOGFUNC(...) LOGMASKED(LOG_FUNC, __VA_ARGS__) + +#ifdef _MSC_VER +#define FUNCNAME __func__ +#else +#define FUNCNAME __PRETTY_FUNCTION__ +#endif + +DEFINE_DEVICE_TYPE(HEATH_Z37_FDC, heath_z37_fdc_device, "heath_z37_fdc", "Heath H/Z-37 Soft-sectored Controller"); + +heath_z37_fdc_device::heath_z37_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock): + device_t(mconfig, HEATH_Z37_FDC, tag, owner, 0), + m_irq_cb(*this), + m_drq_cb(*this), + m_block_interrupt_cb(*this), + m_fdc(*this, "z37_fdc"), + m_floppies(*this, "z37_fdc:%u", 0U) +{ +} + + +void heath_z37_fdc_device::ctrl_w(u8 val) +{ + bool motor_on = bool(BIT(val, ctrl_MotorsOn_c)); + + m_irq_allowed = bool(BIT(val, ctrl_EnableIntReq_c)); + m_drq_allowed = bool(BIT(val, ctrl_EnableDrqInt_c)); + m_fdc->dden_w(BIT(~val, ctrl_SetMFMRecording_c)); + + LOGREG("%s: motor on: %d, intrq allowed: %d, drq allowed: %d\n", + FUNCNAME, motor_on, m_irq_allowed, m_drq_allowed); + + if (m_drq_allowed) + { + m_block_interrupt_cb(1); + } + else + { + m_block_interrupt_cb(0); + m_drq_cb(0); + } + + if (BIT(val, ctrl_Drive_0_c)) + { + m_fdc->set_floppy(m_floppies[0]->get_device()); + LOGDRIVE("Drive selected: 0\n"); + } + else if (BIT(val, ctrl_Drive_1_c)) + { + m_fdc->set_floppy(m_floppies[1]->get_device()); + LOGDRIVE("Drive selected: 1\n"); + } + else if (BIT(val, ctrl_Drive_2_c)) + { + m_fdc->set_floppy(m_floppies[2]->get_device()); + LOGDRIVE("Drive selected: 2\n"); + } + else if (BIT(val, ctrl_Drive_3_c)) + { + m_fdc->set_floppy(m_floppies[3]->get_device()); + LOGDRIVE("Drive selected: 3\n"); + } + else + { + m_fdc->set_floppy(nullptr); + LOGDRIVE("Drive selected: none\n"); + } + + for (auto &elem : m_floppies) + { + floppy_image_device *floppy = elem->get_device(); + if (floppy) + { + floppy->mon_w(!motor_on); + } + } +} + +void heath_z37_fdc_device::intf_w(u8 val) +{ + m_access_track_sector = bool(BIT(val, if_SelectSectorTrack_c)); + + LOGREG("access track/sector: %d\n", m_access_track_sector); +} + +void heath_z37_fdc_device::cmd_w(u8 val) +{ + m_access_track_sector ? m_fdc->sector_w(val) : m_fdc->cmd_w(val); +} + +u8 heath_z37_fdc_device::stat_r() +{ + return m_access_track_sector ? m_fdc->sector_r() : m_fdc->status_r(); +} + +void heath_z37_fdc_device::data_w(u8 val) +{ + m_access_track_sector ? m_fdc->track_w(val) : m_fdc->data_w(val); +} + +u8 heath_z37_fdc_device::data_r() +{ + return m_access_track_sector ? m_fdc->track_r() : m_fdc->data_r(); +} + +void heath_z37_fdc_device::write(offs_t reg, u8 val) +{ + LOGFUNC("%s: reg: %d val: %d\n", FUNCNAME, reg, val); + + switch (reg) + { + case 0: + ctrl_w(val); + break; + case 1: + intf_w(val); + break; + case 2: + cmd_w(val); + break; + case 3: + data_w(val); + break; + } +} + +u8 heath_z37_fdc_device::read(offs_t reg) +{ + // default return for the h89 + u8 value = 0xff; + + switch (reg) + { + case 0: + case 1: + // read not supported on these addresses + break; + case 2: + value = stat_r(); + break; + case 3: + value = data_r(); + break; + } + + LOGFUNC("%s: reg: %d val: %d\n", FUNCNAME, reg, value); + + return value; +} + +void heath_z37_fdc_device::device_start() +{ + save_item(NAME(m_irq_allowed)); + save_item(NAME(m_drq_allowed)); + save_item(NAME(m_access_track_sector)); +} + +void heath_z37_fdc_device::device_reset() +{ + m_irq_allowed = false; + m_drq_allowed = false; + m_access_track_sector = false; + + m_irq_cb(0); + m_drq_cb(0); + m_block_interrupt_cb(0); +} + +static void z37_floppies(device_slot_interface &device) +{ + // H-17-1 -- SS 48tpi + device.option_add("ssdd", FLOPPY_525_SSDD); + // SS 96tpi + device.option_add("ssqd", FLOPPY_525_SSQD); + // DS 48tpi + device.option_add("dd", FLOPPY_525_DD); + // H-17-4 / H-17-5 -- DS 96tpi + device.option_add("qd", FLOPPY_525_QD); +} + +void heath_z37_fdc_device::device_add_mconfig(machine_config &config) +{ + FD1797(config, m_fdc, 16_MHz_XTAL / 16); + m_fdc->intrq_wr_callback().set(FUNC(heath_z37_fdc_device::set_irq)); + m_fdc->drq_wr_callback().set(FUNC(heath_z37_fdc_device::set_drq)); + + FLOPPY_CONNECTOR(config, m_floppies[0], z37_floppies, "qd", floppy_image_device::default_mfm_floppy_formats); + m_floppies[0]->enable_sound(true); + FLOPPY_CONNECTOR(config, m_floppies[1], z37_floppies, "qd", floppy_image_device::default_mfm_floppy_formats); + m_floppies[1]->enable_sound(true); + FLOPPY_CONNECTOR(config, m_floppies[2], z37_floppies, "qd", floppy_image_device::default_mfm_floppy_formats); + m_floppies[2]->enable_sound(true); + FLOPPY_CONNECTOR(config, m_floppies[3], z37_floppies, nullptr, floppy_image_device::default_mfm_floppy_formats); + m_floppies[3]->enable_sound(true); +} + +void heath_z37_fdc_device::set_irq(int state) +{ + LOGLINES("set irq, allowed: %d state: %d\n", m_irq_allowed, state); + + m_irq_cb(m_irq_allowed ? state : CLEAR_LINE); +} + +void heath_z37_fdc_device::set_drq(int state) +{ + LOGLINES("set drq, allowed: %d state: %d\n", m_irq_allowed, state); + + m_drq_cb(m_drq_allowed ? state : CLEAR_LINE); +} diff --git a/src/mame/heathzenith/z37_fdc.h b/src/mame/heathzenith/z37_fdc.h new file mode 100644 index 00000000000..1d758882470 --- /dev/null +++ b/src/mame/heathzenith/z37_fdc.h @@ -0,0 +1,78 @@ +// license:BSD-3-Clause +// copyright-holders:Mark Garlanger +/*************************************************************************** + + Heathkit Z-37 Floppy Disk Controller + +****************************************************************************/ + +#ifndef MAME_HEATHKIT_Z37_FDC_H +#define MAME_HEATHKIT_Z37_FDC_H + +#pragma once + +#include "imagedev/floppy.h" +#include "machine/wd_fdc.h" + + +class heath_z37_fdc_device : public device_t +{ +public: + heath_z37_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + + void write(offs_t reg, u8 val); + u8 read(offs_t reg); + auto irq_cb() { return m_irq_cb.bind(); } + auto drq_cb() { return m_drq_cb.bind(); } + + auto block_interrupt_cb() { return m_block_interrupt_cb.bind(); } + +protected: + + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_add_mconfig(machine_config &config) override; + + void ctrl_w(u8 val); + + void intf_w(u8 val); + + void cmd_w(u8 val); + u8 stat_r(); + + void data_w(u8 val); + u8 data_r(); + + void set_irq(int state); + void set_drq(int state); + +private: + devcb_write_line m_irq_cb; + devcb_write_line m_drq_cb; + devcb_write_line m_block_interrupt_cb; + + required_device m_fdc; + required_device_array m_floppies; + + bool m_irq_allowed; + bool m_drq_allowed; + bool m_access_track_sector; + + /// Bits set in cmd_ControlPort_c - DK.CON + static constexpr u8 ctrl_EnableIntReq_c = 0; + static constexpr u8 ctrl_EnableDrqInt_c = 1; + static constexpr u8 ctrl_SetMFMRecording_c = 2; + static constexpr u8 ctrl_MotorsOn_c = 3; + static constexpr u8 ctrl_Drive_0_c = 4; + static constexpr u8 ctrl_Drive_1_c = 5; + static constexpr u8 ctrl_Drive_2_c = 6; + static constexpr u8 ctrl_Drive_3_c = 7; + + /// Bits to set alternate registers on InterfaceControl_c - DK.INT + static constexpr u8 if_SelectSectorTrack_c = 0; +}; + +DECLARE_DEVICE_TYPE(HEATH_Z37_FDC, heath_z37_fdc_device) + + +#endif // MAME_HEATHKIT_Z37_FDC_H diff --git a/src/mame/mame.lst b/src/mame/mame.lst index 3c89ebef9ac..9267c55a8ca 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -19423,19 +19423,32 @@ wildfire // Parker Bros @source:hds/hds200.cpp hds200 // (c) Human Designed Systems -@source:heathkit/et3400.cpp +@source:heathzenith/et3400.cpp et3400 // -@source:heathkit/h8.cpp +@source:heathzenith/h8.cpp h8 // -@source:heathkit/h19.cpp -h19 // Heath H19 (Zenith Z-19) +@source:heathzenith/h19.cpp +h19 // Heath H19 -@source:heathkit/h89.cpp -h89 // Heath H89 (WH89, Zenith Z-89, Z-90) +@source:heathzenith/h89.cpp +h89 // Heath H89 (WH89) h88 // Heath H88 (with cassette tape) h89_sigmasoft // H89 with the SigmaSoft IGC card +z90 // Zenith Z-90 + +@source:heathzenith/mdt60.cpp +mdt60 // + +@source:heathzenith/z22.cpp +z22 // + +@source:heathzenith/z29.cpp +z29 // + +@source:heathzenith/z100.cpp +z100 // @source:hec2hrp/hec2hrp.cpp hec2hr // @@ -46486,18 +46499,6 @@ jackrabts // (c) 1984 monymony // (c) 1983 monymony2 // (c) 1983 -@source:zenith/mdt60.cpp -mdt60 // - -@source:zenith/z22.cpp -z22 // - -@source:zenith/z29.cpp -z29 // - -@source:zenith/z100.cpp -z100 // - @source:zpa/iq151.cpp iq151 // diff --git a/src/mame/zenith/mdt60.cpp b/src/mame/zenith/mdt60.cpp deleted file mode 100644 index 039ee3f02b0..00000000000 --- a/src/mame/zenith/mdt60.cpp +++ /dev/null @@ -1,269 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:AJR -/************************************************************************** - - 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 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/i8251.h" -#include "video/mc6845.h" -#include "screen.h" - - -namespace { - -class mdt60_state : public driver_device -{ -public: - 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") - , m_charrom(*this, "charrom") - , m_attrram(*this, "attrram") - , m_dip0(*this, "DIP0") - , m_baud_timer(nullptr) - , m_keyin(false) - , m_output_reg(0x3f) - , m_timer_output(false) - { - } - - void mdt60(machine_config &mconfig); - -protected: - virtual void machine_start() override; - virtual void machine_reset() override; - -private: - MC6845_UPDATE_ROW(update_row); - MC6845_ON_UPDATE_ADDR_CHANGED(update_cb); - TIMER_CALLBACK_MEMBER(baud_timer); - - void keyin_w(int state); - u8 dip0_r(offs_t offset); - void reg_w(u8 data); - - void mem_map(address_map &map); - - required_device m_maincpu; - required_device m_keyboard; - required_device m_crtc; - optional_device_array m_uart; - required_shared_ptr m_charram; - required_region_ptr m_charrom; - required_shared_ptr m_attrram; - required_ioport m_dip0; - - emu_timer *m_baud_timer; - - bool m_keyin; - u8 m_output_reg; - bool m_timer_output; -}; - -void mdt60_state::machine_start() -{ - m_baud_timer = timer_alloc(FUNC(mdt60_state::baud_timer), this); - m_baud_timer->adjust(attotime::zero); - - save_item(NAME(m_keyin)); - save_item(NAME(m_output_reg)); - save_item(NAME(m_timer_output)); -} - -void mdt60_state::machine_reset() -{ - reg_w(0); -} - - -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.pix(y); - - for (unsigned x = 0; x < x_count; x++) - { - u8 cdata = m_charram[(ma + x) & 0x7ff]; - u8 adata = m_attrram[(ma + x) & 0x3ff] >> (BIT(ma + x, 10) ? 4 : 0); - u16 dots = m_charrom[cdata << 4 | ra] << 1 | BIT(adata, 3); - - if (x == cursor_x) - dots = ~dots; - if (BIT(adata, 2)) - dots = ~dots; - if (BIT(adata, 0) && (ra & 0xb) == 0xa) - dots = ~dots; - - rgb_t fg = BIT(adata, 1) ? rgb_t::white() : rgb_t(0xc0, 0xc0, 0xc0); - rgb_t bg = rgb_t::black(); - if (BIT(m_output_reg, 5)) - std::swap(fg, bg); - - for (int n = 8; n >= 0; n--) - *pix++ = BIT(dots, n) ? fg : bg; - } -} - -MC6845_ON_UPDATE_ADDR_CHANGED(mdt60_state::update_cb) -{ -} - - -void mdt60_state::keyin_w(int state) -{ - m_keyin = state; - m_maincpu->set_input_line(m6502_device::IRQ_LINE, state ? ASSERT_LINE : CLEAR_LINE); -} - -u8 mdt60_state::dip0_r(offs_t offset) -{ - u8 buffer = 0xff; - if (!BIT(offset, 0)) - buffer &= m_dip0->read() >> 1 | 0x80; - if (!BIT(offset, 1)) - buffer &= m_dip0->read() | 0xfe; - if (!m_keyin) - buffer &= 0x7f; - return buffer; -} - -void mdt60_state::reg_w(u8 data) -{ - if (BIT(data, 0) != BIT(m_output_reg, 0)) - m_keyboard->keyout_w(BIT(data, 0)); - - // 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) -{ - map(0x0000, 0x03ff).mirror(0x1800).ram(); - map(0x0400, 0x07ff).mirror(0x1800).ram().share("attrram"); - map(0x2000, 0x27ff).mirror(0x1800).ram().share("charram"); - map(0x4000, 0x4000).mirror(0x1ffe).rw(m_crtc, FUNC(r6545_1_device::status_r), FUNC(r6545_1_device::address_w)); - map(0x4001, 0x4001).mirror(0x1ffe).rw(m_crtc, FUNC(r6545_1_device::register_r), FUNC(r6545_1_device::register_w)); - map(0x6000, 0x6001).mirror(0x1ffe).rw(m_uart[0], FUNC(i8251_device::read), FUNC(i8251_device::write)); - //map(0x8000, 0x8001).mirror(0x1ffe).rw(m_uart[1], FUNC(i8251_device::read), FUNC(i8251_device::write)); - map(0xa000, 0xa003).mirror(0x1ffc).r(FUNC(mdt60_state::dip0_r)); - map(0xa000, 0xa000).mirror(0x1fff).w(FUNC(mdt60_state::reg_w)); - //map(0xc000, 0xc000).mirror(0x1fff).portr("DIP1"); - map(0xe000, 0xefff).mirror(0x1000).rom().region("coderom", 0); -} - - -static INPUT_PORTS_START(mdt60) - PORT_START("DIP0") - PORT_DIPNAME(0x03, 0x01, "Baud Rate") PORT_DIPLOCATION("SW1:1,2") - PORT_DIPSETTING(0x03, "300") - PORT_DIPSETTING(0x02, "1200") - PORT_DIPSETTING(0x01, "9600") - PORT_DIPSETTING(0x00, "19200") - PORT_DIPNAME(0x0c, 0x00, "Parity") PORT_DIPLOCATION("SW1:3,4") - PORT_DIPSETTING(0x04, "Odd") - PORT_DIPSETTING(0x0c, "Even") - PORT_DIPSETTING(0x00, "Mark") - PORT_DIPSETTING(0x08, "Space") - PORT_DIPNAME(0x70, 0x00, "Character Set") PORT_DIPLOCATION("SW1:5,6,7") - PORT_DIPSETTING(0x00, "U.S.") - PORT_DIPSETTING(0x10, "U.K.") - PORT_DIPSETTING(0x20, "French") - PORT_DIPSETTING(0x30, "German") - PORT_DIPSETTING(0x40, "Spanish") - PORT_DIPSETTING(0x50, "Danish/Norwegian") - PORT_DIPSETTING(0x60, "Swedish/Finnish") - PORT_DIPSETTING(0x70, "Italian") - PORT_DIPNAME(0x80, 0x80, "Function Key Sequence Type") PORT_DIPLOCATION("SW1:8") - PORT_DIPSETTING(0x80, "Morrow (FS)") - PORT_DIPSETTING(0x00, "TeleVideo (SOH...CR)") - - PORT_START("DIP1") - PORT_BIT(0xff, 0xff, IPT_UNUSED) // SW2 is unpopulated (as is LS244 at U20) -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. - -void mdt60_state::mdt60(machine_config &config) -{ - M6512(config, m_maincpu, 16.5888_MHz_XTAL / 9); // R6512AP - m_maincpu->set_addrmap(AS_PROGRAM, &mdt60_state::mem_map); - - 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("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)); - - // UART 1 (at U28) is unpopulated and not used by code - - Z29_KEYBOARD(config, m_keyboard, z29_keyboards, "md"); - m_keyboard->keyin_callback().set(FUNC(mdt60_state::keyin_w)).invert(); - // Reset output (pin 2) is not connected - - 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)); - // LPEN is tied to GND (code uses this to determine CRTC type) - - 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)); -} - - -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 - -} // anonymous namespace - - -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/zenith/z100.cpp b/src/mame/zenith/z100.cpp deleted file mode 100644 index 15a2e247bdc..00000000000 --- a/src/mame/zenith/z100.cpp +++ /dev/null @@ -1,910 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Angelo Salese, AJR -/*************************************************************************** - - Zenith Z-100 - - 15/07/2011 Skeleton driver. - - Commands: - Press DELETE to abort boot, then press H to list all the commands. - - TODO: - - implement S-100 bus features; - - memory test hangs on the first pass; - -============================================================================ - -Z207A EQU 0B0H ; Z-207 disk controller base port - ; (See DEFZ207 to program controller) -Z217A EQU 0AEH ; Z-217 disk controller base port - ; (See DEFZ217 to program controller) -ZGRNSEG EQU 0E000H ; Segment of green video plane -ZREDSEG EQU 0D000H ; Segment of red video plane -ZBLUSEG EQU 0C000H ; Segment of blue video plane -ZVIDEO EQU 0D8H ; Video 68A21 port - ; PA0 -> enable red display - ; PA1 -> enable green display - ; PA2 -> enable blue display - ; PA3 -> not flash screen - ; PA4 -> not write multiple red - ; PA5 -> not write multiple green - ; PA6 -> not write multiple blue - ; PA7 -> disable video RAM - ; PB7-PB0 -> LA15-LA8 - ; CA1 - not used - ; CA2 -> clear screen - ; CB1 - not used - ; CB2 -> value to write (0 or 1) on clear screen - ; (see DEF6821 to program the 6821) -ZCRTC EQU 0DCH ; Video 6845 CRT-C port - ; (see DEF6845 to program the 6845) -ZLPEN EQU 0DEH ; Light pen latch - ZLPEN_BIT EQU 00000111B ; Bit hit by pen - ZLPEN_ROW EQU 11110000B ; Row hit by pen -ZPIA EQU 0E0H ; Parallel printer plus light pen and - ; video vertical retrace 68A21 port - ; PA0 -> PDATA1 - ; PA1 -> PDATA2 - ; PA2 -> not STROBE - ; PA3 -> not INIT - ; PA4 <- VSYNC - ; PA5 -> clear VSYNC flip flop - ; PA6 <- light pen switch - ; PA7 -> clear light pen flip flop - ; PB0 <- BUSY - ; PB1 <- not ERROR - ; PB2 -> PDATA3 - ; PB3 -> PDATA4 - ; PB4 -> PDATA5 - ; PB5 -> PDATA6 - ; PB6 -> PDATA7 - ; PB7 -> PDATA8 - ; CA1 <- light pen hit (from flip flop) - ; CA2 <- VSYNC (from flip flop) - ; CB1 <- not ACKNLG - ; CB2 <- BUSY - ; (See DEF6821 to program the PIA) -ZTIMER EQU 0E4H ; Timer 8253 port - ZTIMEVAL EQU 2500 ; 100ms divide by N value - ; (See DEF8253 to program the 8253) -ZTIMERS EQU 0FBH ; Timer interrupt status port - ZTIMERS0 EQU 001H ; Timer 0 interrupt - ZTIMERS2 EQU 002H ; Timer 2 interrupt -ZSERA EQU 0E8H ; First 2661-2 serial port -ZSERB EQU 0ECH ; Second 2661-2 serial port - ; (See DEFEP2 to program 2661-2) -ZM8259A EQU 0F2H ; Master 8259A interrupt controller port - ZINTEI EQU 0 ; Parity error or S-100 pin 98 interrupt - ZINTPS EQU 1 ; Processor swap interrupt - ZINTTIM EQU 2 ; Timer interrupt - ZINTSLV EQU 3 ; Slave 8259A interrupt - ZINTSA EQU 4 ; Serial port A interrupt - ZINTSB EQU 5 ; Serial port B interrupt - ZINTKD EQU 6 ; Keyboard, Display, or Light pen interrupt - ZINTPP EQU 7 ; Parallel port interrupt - ; (See DEF8259A to program the 8259A) - ZM8259AI EQU 64 ; Base interrupt number for master -ZS8259A EQU 0F0H ; Secondary 8259A interrupt controller port - ZS8259AI EQU 72 ; Base interrupt number for slave - BIOSAI EQU ZS8259AI+8 ; Base of BIOS generated interrupts -ZKEYBRD EQU 0F4H ; Keyboard port - ZKEYBRDD EQU ZKEYBRD+0 ; Keyboard data port - ZKEYBRDC EQU ZKEYBRD+1 ; Keyboard command port - ZKEYRES EQU 0 ; Reset command - ZKEYARD EQU 1 ; Autorepeat on command - ZKEYARF EQU 2 ; Autorepeat off command - ZKEYKCO EQU 3 ; Key click on command - ZKEYKCF EQU 4 ; Key click off command - ZKEYCF EQU 5 ; Clear keyboard FIFO command - ZKEYCLK EQU 6 ; Generate a click sound command - ZKEYBEP EQU 7 ; Generate a beep sound command - ZKEYEK EQU 8 ; Enable keyboard command - ZKEYDK EQU 9 ; Disable keyboard command - ZKEYUDM EQU 10 ; Enter UP/DOWN mode command - ZKEYNSM EQU 11 ; Enter normal scan mode command - ZKEYEI EQU 12 ; Enable keyboard interrupts command - ZKEYDI EQU 13 ; Disable keyboard interrupts command - ZKEYBRDS EQU ZKEYBRD+1 ; Keyboard status port - ZKEYOBF EQU 001H ; Output buffer not empty - ZKEYIBF EQU 002H ; Input buffer full -ZMCL EQU 0FCH ; Memory control latch - ZMCLMS EQU 00000011B ; Map select mask - ZSM0 EQU 0 ; Map select 0 - ZSM1 EQU 1 ; Map select 1 - ZSM2 EQU 2 ; Map select 2 - ZSM3 EQU 3 ; Map select 3 - ZMCLRM EQU 00001100B ; Monitor ROM mapping mask - ZRM0 EQU 0*4 ; Power up mode - ROM everywhere on reads - ZRM1 EQU 1*4 ; ROM at top of every 64K page - ZRM2 EQU 2*4 ; ROM at top of 8088's addr space - ZRM3 EQU 3*4 ; Disable ROM - ZMCLPZ EQU 00010000B ; 0=Set Parity to the zero state - ZMCLPK EQU 00100000B ; 0=Disable parity checking circuity - ZMCLPF EQU 01000000B ; 0=Disable parity error flag -Z205BA EQU 098H ; Base address for Z-205 boards - Z205BMC EQU 8 ; Maximum of 8 Z-205 boards installed -ZHAL EQU 0FDH ; Hi-address latch - ZHAL85 EQU 0FFH ; 8085 Mask - ZHAL88 EQU 0F0H ; 8088 Mask -ZPSP EQU 0FEH ; Processor swap port - ZPSPPS EQU 10000000B ; Processor select (0=8085, 1=8088) - ZPSPPS5 EQU 00000000B ; Select 8085 - ZPSPPS8 EQU 10000000B ; Select 8088 - ZPSPSI EQU 00000010B ; Generate interrupt on swapping - ZPSPI8 EQU 00000001B ; 8088 processes all interrupts -ZDIPSW EQU 0FFH ; Configuration dip switches - ZDIPSWBOOT EQU 00000111B ; Boot device field - ZDIPSWAB EQU 00001000B ; 1=Auto boot(0=Manual boot) - ZDIPSWRES EQU 01110000B ; Reserved - ZDIPSWHZ EQU 10000000B ; 1=50Hz(0=60HZ) - -****************************************************************************/ - -#include "emu.h" -#include "cpu/i86/i86.h" -#include "cpu/i8085/i8085.h" -#include "cpu/mcs48/mcs48.h" -#include "bus/centronics/ctronics.h" -//#include "bus/rs232/rs232.h" -//#include "bus/s100/s100.h" -#include "imagedev/floppy.h" -#include "machine/74123.h" -#include "machine/6821pia.h" -#include "machine/input_merger.h" -#include "machine/pit8253.h" -#include "machine/pic8259.h" -#include "machine/rescap.h" -#include "machine/scn_pci.h" -#include "machine/wd_fdc.h" -#include "sound/beep.h" -#include "video/mc6845.h" -#include "emupal.h" -#include "screen.h" -#include "speaker.h" - - -namespace { - -class z100_state : public driver_device -{ -public: - z100_state(const machine_config &mconfig, device_type type, const char *tag) - : driver_device(mconfig, type, tag), - m_maincpu(*this, "maincpu"), - m_ram(*this, "ram"), - m_pia(*this, "pia%u", 0U), - m_picm(*this, "pic8259_master"), - m_pics(*this, "pic8259_slave"), - m_fdc(*this, "z207_fdc"), - m_floppies(*this, "z207_fdc:%u", 0U), - m_epci(*this, "epci%u", 0U), - m_keyclick(*this, "keyclick"), - m_keybeep(*this, "keybeep"), - m_beeper(*this, "beeper"), - m_crtc(*this, "crtc"), - m_palette(*this, "palette"), - m_vrmm(*this, "vrmm"), - m_vram_config(*this, "VRAM"), - m_keys(*this, "COL%u", 0U), - m_ctrl(*this, "CTRL"), - m_floppy(nullptr) - { } - - void z100(machine_config &config); - - DECLARE_INPUT_CHANGED_MEMBER(kbd_reset); - -private: - virtual void machine_start() override; - virtual void machine_reset() override; - virtual void video_start() override; - - uint8_t ram_r(offs_t offset); - void ram_w(offs_t offset, uint8_t data); - void memory_ctrl_w(uint8_t data); - offs_t vram_map(offs_t offset) const; - uint8_t z100_vram_r(offs_t offset); - void z100_vram_w(offs_t offset, uint8_t data); - void kbd_col_w(uint8_t data); - uint8_t kbd_rows_r(); - int kbd_shift_row_r(); - void beep_update(int state); - void floppy_select_w(uint8_t data); - void floppy_motor_w(uint8_t data); - uint8_t tmr_status_r(); - void tmr_status_w(uint8_t data); - void timer_flipflop0_w(int state); - void timer_flipflop1_w(int state); - void vidint_w(int state); - void vidint_enable_w(int state); - - u8 get_slave_ack(offs_t offset); - void video_pia_A_w(u8 data); - void video_pia_B_w(u8 data); - void video_pia_CA2_w(int state); - void video_pia_CB2_w(int state); - - MC6845_UPDATE_ROW(update_row); - - void z100_io(address_map &map); - void z100_mem(address_map &map); - - required_device m_maincpu; - required_shared_ptr m_ram; - required_device_array m_pia; - required_device m_picm; - required_device m_pics; - required_device m_fdc; - required_device_array m_floppies; - required_device_array m_epci; - required_device m_keyclick; - required_device m_keybeep; - required_device m_beeper; - required_device m_crtc; - required_device m_palette; - required_region_ptr m_vrmm; - required_ioport m_vram_config; - required_ioport_array<16> m_keys; - required_ioport m_ctrl; - - std::unique_ptr m_gvram; - std::unique_ptr m_parity; - uint8_t m_kbd_col; - uint8_t m_vram_enable; - uint8_t m_gbank; - uint8_t m_display_mask; - uint8_t m_flash; - uint8_t m_clr_val; - uint8_t m_tmr_status; - uint8_t m_start_addr; - bool m_vidint_enable; - uint8_t m_memory_ctrl; - - floppy_image_device *m_floppy; -}; - - -void z100_state::machine_start() -{ - m_parity = make_unique_clear(m_ram.bytes() / 32); -} - -void z100_state::video_start() -{ - m_gvram = make_unique_clear(0x30000); - - m_vidint_enable = false; -} - -uint8_t z100_state::ram_r(offs_t offset) -{ - if (!machine().side_effects_disabled() && BIT(m_memory_ctrl, 5)) - { - uint32_t parity = m_parity[offset >> 5]; - if (BIT(parity, offset & 31)) - m_picm->ir0_w(1); - } - - return m_ram[offset]; -} - -void z100_state::ram_w(offs_t offset, uint8_t data) -{ - if (!machine().side_effects_disabled()) - { - uint32_t &parity = m_parity[offset >> 5]; - if (!BIT(m_memory_ctrl, 4) && BIT(population_count_32(data), 0)) - parity |= 1 << (offset & 31); - else if (parity != 0) - parity &= ~(1 << (offset & 31)); - } - - m_ram[offset] = data; -} - -void z100_state::memory_ctrl_w(uint8_t data) -{ - m_memory_ctrl = data & 0x3f; - if (!BIT(data, 5)) - m_picm->ir0_w(0); -} - -MC6845_UPDATE_ROW(z100_state::update_row) -{ - uint32_t *const pix = &bitmap.pix(y); - const uint16_t amask = m_vram_config->read() ? 0xfff : 0x7ff; - - for (int x = 0; x < x_count; x++) - { - for (int xi = 0; xi < 8; xi++) - { - int dot = 0; - if (m_flash) - { - dot = m_display_mask; - } - else - { - for (int i = 0; i < 3; i++) - dot |= ((m_gvram[((x + ma) & amask) << 4 | (ra & 0xf) | (0x10000*i)] >> (7-xi)) & 1) << i; // b, r, g - - if (x == cursor_x) - dot ^= 7; - - dot &= m_display_mask; - } - - pix[x*8+xi] = m_palette->pen(dot); - } - } -} - -offs_t z100_state::vram_map(offs_t offset) const -{ - // Translate logical address to physical address - return (offset & 0x30000) | (offset & 0x000f) << 4 | (offset & 0x0780) >> 7 - | ((m_vrmm[(offset & 0xf800) >> 8 | (offset & 0x0070) >> 4] + m_start_addr) & (m_vram_config->read() ? 0xff : 0x7f)) << 8; -} - -uint8_t z100_state::z100_vram_r(offs_t offset) -{ - return m_gvram[vram_map(offset)]; -} - -void z100_state::z100_vram_w(offs_t offset, uint8_t data) -{ - if(m_vram_enable) - { - offset = vram_map(offset); - m_gvram[offset] = data; - - for (int i = 0; i < 3; i++) - { - if (BIT(m_gbank, i)) - m_gvram[((offset) & 0xffff)+0x10000*i] = data; - } - } -} - -void z100_state::z100_mem(address_map &map) -{ - map.unmap_value_high(); - map(0x00000, 0x3ffff).rw(FUNC(z100_state::ram_r), FUNC(z100_state::ram_w)).share("ram"); // 128*2 KB RAM -// map(0xb0000,0xbffff).rom(); // expansion ROM - map(0xc0000, 0xeffff).rw(FUNC(z100_state::z100_vram_r), FUNC(z100_state::z100_vram_w)); // Blue / Red / Green -// map(0xf0000,0xf0fff) // network card (NET-100) -// map(0xf4000,0xf7fff) // MTRET-100 Firmware I expansion ROM -// map(0xf8000,0xfbfff) // MTRET-100 Firmware II expansion ROM check ID 0x4550 - map(0xfc000, 0xfffff).rom().region("ipl", 0); -} - -void z100_state::kbd_col_w(uint8_t data) -{ - m_kbd_col = data & 0x0f; - - m_keyclick->b_w(BIT(data, 7)); - m_keybeep->a_w((data & 0x82) == 0); -} - -uint8_t z100_state::kbd_rows_r() -{ - if (m_kbd_col < 0x0c) - return m_keys[m_kbd_col]->read(); - - return 0xff; -} - -int z100_state::kbd_shift_row_r() -{ - if ((m_kbd_col & 0x0c) == 0x0c) - return m_keys[m_kbd_col]->read(); - - return 1; -} - -void z100_state::beep_update(int state) -{ - m_beeper->set_state(m_keyclick->q_r() | m_keybeep->q_r()); -} - -// todo: side select? - -void z100_state::floppy_select_w(uint8_t data) -{ - m_floppy = m_floppies[data & 0x03]->get_device(); - m_fdc->set_floppy(m_floppy); -} - -void z100_state::floppy_motor_w(uint8_t data) -{ - if (m_floppy) - m_floppy->mon_w(!BIT(data, 1)); -} - -uint8_t z100_state::tmr_status_r() -{ - return m_tmr_status; -} - -void z100_state::tmr_status_w(uint8_t data) -{ - m_tmr_status &= data & 3; - if (m_tmr_status == 0) - m_picm->ir2_w(0); -} - -void z100_state::timer_flipflop0_w(int state) -{ - if (state) - { - m_tmr_status |= 1; - m_picm->ir2_w(1); - } -} - -void z100_state::timer_flipflop1_w(int state) -{ - if (state) - { - m_tmr_status |= 2; - m_picm->ir2_w(1); - } -} - -void z100_state::vidint_w(int state) -{ - m_pia[1]->pa4_w(state); - - if (state && m_vidint_enable) - m_pia[1]->ca2_w(1); -} - -void z100_state::vidint_enable_w(int state) -{ - m_vidint_enable = state; - if (!m_vidint_enable) - m_pia[1]->ca2_w(0); -} - -void z100_state::z100_io(address_map &map) -{ - map.unmap_value_high(); - map.global_mask(0xff); -// map(0x00, 0x3f) reserved for non-ZDS vendors -// map(0x40, 0x5f) secondary Multiport card (Z-204) -// map(0x60, 0x7f) primary Multiport card (Z-204) -// map(0x80, 0x83) development board -// map(0x98, 0x9f) Z-205 expansion memory boards -// map(0xa0, 0xa3) network card (NET-100) -// map(0xa4, 0xa7) gateway (reserved) -// map(0xac, 0xad) Z-217 secondary disk controller (winchester) -// map(0xae, 0xaf) Z-217 primary disk controller (winchester) - map(0xb0, 0xb3).rw(m_fdc, FUNC(fd1797_device::read), FUNC(fd1797_device::write)); - map(0xb4, 0xb4).w(FUNC(z100_state::floppy_select_w)); - map(0xb5, 0xb5).w(FUNC(z100_state::floppy_motor_w)); -// z-207 secondary disk controller (wd1797) -// map(0xcd, 0xce) ET-100 CRT Controller -// map(0xd4, 0xd7) ET-100 Trainer Parallel I/O - map(0xd8, 0xdb).rw(m_pia[0], FUNC(pia6821_device::read), FUNC(pia6821_device::write)); //video board - map(0xdc, 0xdc).w(m_crtc, FUNC(mc6845_device::address_w)); - map(0xdd, 0xdd).w(m_crtc, FUNC(mc6845_device::register_w)); -// map(0xde, 0xde) light pen - map(0xe0, 0xe3).rw(m_pia[1], FUNC(pia6821_device::read), FUNC(pia6821_device::write)); //main board - map(0xe4, 0xe7).rw("pit", FUNC(pit8253_device::read), FUNC(pit8253_device::write)); - map(0xe8, 0xeb).rw(m_epci[0], FUNC(scn2661b_device::read), FUNC(scn2661b_device::write)); - map(0xec, 0xef).rw(m_epci[1], FUNC(scn2661b_device::read), FUNC(scn2661b_device::write)); - map(0xf0, 0xf1).rw(m_pics, FUNC(pic8259_device::read), FUNC(pic8259_device::write)); - map(0xf2, 0xf3).rw(m_picm, FUNC(pic8259_device::read), FUNC(pic8259_device::write)); - map(0xf4, 0xf5).rw("kbdc", FUNC(i8041a_device::upi41_master_r), FUNC(i8041a_device::upi41_master_w)); -// map(0xf6, 0xf6) expansion ROM is present (bit 0, active low) - map(0xfb, 0xfb).rw(FUNC(z100_state::tmr_status_r), FUNC(z100_state::tmr_status_w)); - map(0xfc, 0xfc).w(FUNC(z100_state::memory_ctrl_w)); -// map(0xfd, 0xfd) Hi-address latch -// map(0xfe, 0xfe) Processor swap port - map(0xff, 0xff).portr("DSW101"); -} - -INPUT_CHANGED_MEMBER(z100_state::kbd_reset) -{ - if (m_ctrl->read() == 0) - reset(); -} - -/* Input ports */ -INPUT_PORTS_START( z100 ) - PORT_START("COL0") // 15 - PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('a') PORT_CHAR('A') PORT_CODE(KEYCODE_A) - PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('s') PORT_CHAR('S') PORT_CODE(KEYCODE_S) - PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('d') PORT_CHAR('D') PORT_CODE(KEYCODE_D) - PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('f') PORT_CHAR('F') PORT_CODE(KEYCODE_F) - PORT_BIT(0x08, 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('h') PORT_CHAR('H') PORT_CODE(KEYCODE_H) - PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('j') PORT_CHAR('J') PORT_CODE(KEYCODE_J) - PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('k') PORT_CHAR('K') PORT_CODE(KEYCODE_K) - - PORT_START("COL1") // 11 - PORT_BIT(0x80, 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('w') PORT_CHAR('W') PORT_CODE(KEYCODE_W) - PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('e') PORT_CHAR('E') PORT_CODE(KEYCODE_E) - PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('r') PORT_CHAR('R') PORT_CODE(KEYCODE_R) - PORT_BIT(0x08, 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('y') PORT_CHAR('Y') PORT_CODE(KEYCODE_Y) - PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('u') PORT_CHAR('U') PORT_CODE(KEYCODE_U) - PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('i') PORT_CHAR('I') PORT_CODE(KEYCODE_I) - - PORT_START("COL2") // 16 - PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('z') PORT_CHAR('Z') PORT_CODE(KEYCODE_Z) - PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('x') PORT_CHAR('X') PORT_CODE(KEYCODE_X) - PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('c') PORT_CHAR('C') PORT_CODE(KEYCODE_C) - PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('v') PORT_CHAR('V') PORT_CODE(KEYCODE_V) - PORT_BIT(0x08, 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('n') PORT_CHAR('N') PORT_CODE(KEYCODE_N) - PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('m') PORT_CHAR('M') PORT_CODE(KEYCODE_M) - PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('l') PORT_CHAR('L') PORT_CODE(KEYCODE_L) - - PORT_START("COL3") // 13 - PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED) - PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED) - PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED) - PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED) - PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_UNUSED) - PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('p') PORT_CHAR('P') PORT_CODE(KEYCODE_P) - PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('o') PORT_CHAR('O') PORT_CODE(KEYCODE_O) - PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED) - - PORT_START("COL4") // 9 - PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F0") - PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F1)) PORT_CODE(KEYCODE_F1) - PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F2)) PORT_CODE(KEYCODE_F2) - PORT_BIT(0x10, 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(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F5)) PORT_CODE(KEYCODE_F5) - PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F6)) PORT_CODE(KEYCODE_F6) - PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F7)) PORT_CODE(KEYCODE_F7) - - PORT_START("COL5") // 12 - PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Del/Ins Char") PORT_CODE(KEYCODE_F14) - PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Del/Ins Line") PORT_CODE(KEYCODE_F13) - PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F12)) PORT_CODE(KEYCODE_F12) - PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F11)) PORT_CODE(KEYCODE_F11) - PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F10)) PORT_CODE(KEYCODE_F10) - PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F9)) PORT_CODE(KEYCODE_F9) - PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F8)) PORT_CODE(KEYCODE_F8) - PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED) - - PORT_START("COL6") // 17 - PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(HOME)) PORT_CODE(KEYCODE_HOME) - PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD)) PORT_CODE(KEYCODE_7_PAD) - PORT_BIT(0x20, 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(UCHAR_MAMEKEY(1_PAD)) PORT_CODE(KEYCODE_1_PAD) - PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) PORT_CODE(KEYCODE_RIGHT) - PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD)) PORT_CODE(KEYCODE_9_PAD) - PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD)) PORT_CODE(KEYCODE_6_PAD) - PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD)) PORT_CODE(KEYCODE_3_PAD) - - PORT_START("COL7") // 18 - PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) PORT_CODE(KEYCODE_LEFT) - PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD)) PORT_CODE(KEYCODE_8_PAD) - PORT_BIT(0x20, 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(UCHAR_MAMEKEY(2_PAD)) PORT_CODE(KEYCODE_2_PAD) - PORT_BIT(0x08, 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(DOWN)) PORT_CODE(KEYCODE_DOWN) - PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD)) PORT_CODE(KEYCODE_MINUS_PAD) - PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD)) PORT_CODE(KEYCODE_ENTER_PAD) - - PORT_START("COL8") // 3 - PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Break") - PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Help") - PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(' ') PORT_CODE(KEYCODE_SPACE) - PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(0x0a) PORT_CODE(KEYCODE_RALT) PORT_NAME("Line Feed") - PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('\\') PORT_CHAR('|') PORT_CODE(KEYCODE_BACKSLASH) - PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(DEL)) PORT_CODE(KEYCODE_DEL) PORT_NAME("Delete") - PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD)) PORT_CODE(KEYCODE_0_PAD) - PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD)) PORT_CODE(KEYCODE_DEL_PAD) - - PORT_START("COL9") // 7 - PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(0x1b) PORT_CODE(KEYCODE_ESC) - PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(0x09) PORT_CODE(KEYCODE_TAB) - PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(',') PORT_CHAR('<') PORT_CODE(KEYCODE_COMMA) - PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(0x0d) PORT_CODE(KEYCODE_ENTER) PORT_NAME("Return") - PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('/') PORT_CHAR('?') PORT_CODE(KEYCODE_SLASH) - PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('.') PORT_CHAR('>') PORT_CODE(KEYCODE_STOP) - PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(';') PORT_CHAR(':') PORT_CODE(KEYCODE_COLON) - PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('\'') PORT_CHAR('"') PORT_CODE(KEYCODE_QUOTE) - - PORT_START("COL10") // 10 - PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('1') PORT_CHAR('!') PORT_CODE(KEYCODE_1) - PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('2') PORT_CHAR('@') PORT_CODE(KEYCODE_2) - PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('3') PORT_CHAR('#') PORT_CODE(KEYCODE_3) - PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('4') PORT_CHAR('$') PORT_CODE(KEYCODE_4) - PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('5') PORT_CHAR('%') PORT_CODE(KEYCODE_5) - PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('6') PORT_CHAR('^') PORT_CODE(KEYCODE_6) - PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('7') PORT_CHAR('&') PORT_CODE(KEYCODE_7) - PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('8') PORT_CHAR('*') PORT_CODE(KEYCODE_8) - - PORT_START("COL11") // 14 - PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(0x08) PORT_CODE(KEYCODE_BACKSPACE) PORT_NAME("Back Space") - PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('`') PORT_CHAR('~') PORT_CODE(KEYCODE_TILDE) // ~ key is between BS and = - PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('=') PORT_CHAR('+') PORT_CODE(KEYCODE_EQUALS) - PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('-') PORT_CHAR('_') PORT_CODE(KEYCODE_MINUS) - PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('0') PORT_CHAR(')') PORT_CODE(KEYCODE_0) - PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('9') PORT_CHAR('(') PORT_CODE(KEYCODE_9) - PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('[') PORT_CHAR('{') PORT_CODE(KEYCODE_OPENBRACE) - PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(']') PORT_CHAR('}') PORT_CODE(KEYCODE_CLOSEBRACE) - - PORT_START("COL12") // 5 - PORT_BIT(1, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_SHIFT_1) PORT_CODE(KEYCODE_LSHIFT) PORT_NAME("Shift Left") - - PORT_START("COL13") // 8 - PORT_BIT(1, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RSHIFT) PORT_NAME("Shift Right") - - PORT_START("COL14") // 6 - PORT_BIT(1, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK)) PORT_CODE(KEYCODE_CAPSLOCK) - - PORT_START("COL15") // 1 - PORT_BIT(1, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LALT) PORT_NAME("Fast Repeat") - - PORT_START("CTRL") // 2 & 4 - PORT_BIT(1, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_NAME("Ctrl") PORT_CHANGED_MEMBER(DEVICE_SELF, z100_state, kbd_reset, 0) - PORT_BIT(2, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Reset") PORT_CHANGED_MEMBER(DEVICE_SELF, z100_state, kbd_reset, 0) - - PORT_START("DSW101") - PORT_DIPNAME( 0x07, 0x00, "Default Auto-boot Device" ) - PORT_DIPSETTING( 0x00, "0" ) - PORT_DIPSETTING( 0x01, "1" ) - PORT_DIPSETTING( 0x02, "2" ) - PORT_DIPSETTING( 0x03, "3" ) - PORT_DIPSETTING( 0x04, "4" ) - PORT_DIPSETTING( 0x05, "5" ) - PORT_DIPSETTING( 0x06, "6" ) - PORT_DIPSETTING( 0x07, "7" ) - PORT_DIPNAME( 0x08, 0x08, "Auto-boot" ) - PORT_DIPSETTING( 0x00, DEF_STR( No ) ) - PORT_DIPSETTING( 0x08, DEF_STR( Yes ) ) - PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) ) // Reserved - PORT_DIPSETTING( 0x10, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) ) // Reserved - PORT_DIPSETTING( 0x20, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) ) // Reserved - PORT_DIPSETTING( 0x40, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x80, 0x00, "Monitor" ) - PORT_DIPSETTING( 0x80, "PAL 50 Hz" ) - PORT_DIPSETTING( 0x00, "NTSC 60 Hz" ) - - PORT_START("CONFIG") - PORT_CONFNAME( 0x01, 0x01, "Video Board" ) - PORT_CONFSETTING( 0x00, "Monochrome" ) - PORT_CONFSETTING( 0x01, "Color" ) - - PORT_START("VRAM") - PORT_DIPNAME( 0x01, 0x01, "Video Memory" ) PORT_DIPLOCATION("J307:1") - PORT_DIPSETTING( 0x00, "32K" ) - PORT_DIPSETTING( 0x01, "64K" ) -INPUT_PORTS_END - -u8 z100_state::get_slave_ack(offs_t offset) -{ - if (offset==7) { // IRQ = 7 - return m_pics->acknowledge(); - } - return 0; -} - -void z100_state::video_pia_A_w(u8 data) -{ - /* - all bits are active low - x--- ---- -> disable video RAM - -x-- ---- -> not write multiple blue - --x- ---- -> not write multiple green - ---x ---- -> not write multiple red - ---- x--- -> not flash screen - ---- -x-- -> enable blue display - ---- --x- -> enable green display - ---- ---x -> enable red display - */ - - m_vram_enable = ((data & 0x80) >> 7) ^ 1; - m_gbank = bitswap<8>(((data & 0x70) >> 4) ^ 0x7,7,6,5,4,3,1,0,2); - m_flash = ((data & 8) >> 3) ^ 1; - m_display_mask = bitswap<8>((data & 7) ^ 7,7,6,5,4,3,1,0,2); -} - -void z100_state::video_pia_B_w(u8 data) -{ - m_start_addr = data; -} - -/* clear screen */ -void z100_state::video_pia_CA2_w(int state) -{ - int i; - - for(i=0; i<0x30000; i++) - m_gvram[i] = m_clr_val; -} - -void z100_state::video_pia_CB2_w(int state) -{ - m_clr_val = (state & 1) ? 0x00 : 0xff; -} - -void z100_state::machine_reset() -{ - int i; - - if(ioport("CONFIG")->read() & 1) - { - for(i=0;i<8;i++) - m_palette->set_pen_color(i,pal1bit(i >> 1),pal1bit(i >> 2),pal1bit(i >> 0)); - } - else - { - for(i=0;i<8;i++) - m_palette->set_pen_color(i,pal3bit(0),pal3bit(i),pal3bit(0)); - } - - memory_ctrl_w(0); -} - -static void z100_floppies(device_slot_interface &device) -{ - device.option_add("dd", FLOPPY_525_DD); -} - -void z100_state::z100(machine_config &config) -{ - /* basic machine hardware */ - I8088(config, m_maincpu, 15_MHz_XTAL / 3); // 5 MHz or 8 MHz depending on XTAL - m_maincpu->set_addrmap(AS_PROGRAM, &z100_state::z100_mem); - m_maincpu->set_addrmap(AS_IO, &z100_state::z100_io); - m_maincpu->set_irq_acknowledge_callback("pic8259_master", FUNC(pic8259_device::inta_cb)); - - I8085A(config, "cpu85", 10_MHz_XTAL).set_disable(); - - i8041a_device &kbdc(I8041A(config, "kbdc", 6_MHz_XTAL)); - kbdc.p1_in_cb().set(FUNC(z100_state::kbd_rows_r)); - kbdc.p2_out_cb().set(FUNC(z100_state::kbd_col_w)); - kbdc.p2_out_cb().append("keydspyint", FUNC(input_merger_device::in_w<0>)).bit(4); - kbdc.t0_in_cb().set_ioport("CTRL").bit(0); - kbdc.t1_in_cb().set(FUNC(z100_state::kbd_shift_row_r)); - - TTL74123(config, m_keyclick, RES_K(150), CAP_U(.1)); - m_keyclick->set_connection_type(TTL74123_NOT_GROUNDED_NO_DIODE); - m_keyclick->set_a_pin_value(0); - m_keyclick->set_b_pin_value(1); - m_keyclick->set_clear_pin_value(1); - m_keyclick->out_cb().set(FUNC(z100_state::beep_update)); - - TTL74123(config, m_keybeep, RES_K(220), CAP_U(2.2)); - m_keybeep->set_connection_type(TTL74123_NOT_GROUNDED_NO_DIODE); - m_keybeep->set_b_pin_value(1); - m_keybeep->set_clear_pin_value(1); - m_keybeep->out_cb().set(FUNC(z100_state::beep_update)); - - SPEAKER(config, "mono").front_center(); - BEEP(config, m_beeper, 1'000'000'000 / PERIOD_OF_555_ASTABLE_NSEC(RES_K(470), RES_K(470), CAP_U(.001))); - m_beeper->add_route(ALL_OUTPUTS, "mono", 0.50); - - /* video hardware */ - screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); - screen.set_raw(14.112_MHz_XTAL, 912, 0, 640, 258, 0, 216); - screen.set_screen_update("crtc", FUNC(mc6845_device::screen_update)); - - PALETTE(config, m_palette).set_entries(8); - - /* devices */ - MC6845(config, m_crtc, 14.112_MHz_XTAL / 8); // 68A45 - 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(z100_state::update_row)); - m_crtc->out_vsync_callback().set(FUNC(z100_state::vidint_w)); - - PIC8259(config, m_picm); - m_picm->out_int_callback().set_inputline(m_maincpu, 0); - m_picm->in_sp_callback().set_constant(1); - m_picm->read_slave_ack_callback().set(FUNC(z100_state::get_slave_ack)); - - PIC8259(config, m_pics); - m_pics->out_int_callback().set(m_picm, FUNC(pic8259_device::ir3_w)); - m_pics->in_sp_callback().set_constant(0); - - pit8253_device &pit(PIT8253(config, "pit")); - pit.set_clk<0>(4_MHz_XTAL / 16); - pit.out_handler<0>().set(FUNC(z100_state::timer_flipflop0_w)); - pit.out_handler<0>().append("pit", FUNC(pit8253_device::write_clk1)); - pit.set_clk<2>(4_MHz_XTAL / 16); - pit.out_handler<2>().set(FUNC(z100_state::timer_flipflop1_w)); - - PIA6821(config, m_pia[0]); - m_pia[0]->writepa_handler().set(FUNC(z100_state::video_pia_A_w)); - m_pia[0]->writepb_handler().set(FUNC(z100_state::video_pia_B_w)); - m_pia[0]->ca2_handler().set(FUNC(z100_state::video_pia_CA2_w)); - m_pia[0]->cb2_handler().set(FUNC(z100_state::video_pia_CB2_w)); - - PIA6821(config, m_pia[1]); - m_pia[1]->irqa_handler().set("keydspyint", FUNC(input_merger_device::in_w<1>)); - m_pia[1]->irqb_handler().set(m_picm, FUNC(pic8259_device::ir7_w)); - m_pia[1]->writepa_handler().set("centronics", FUNC(centronics_device::write_strobe)).bit(2); - m_pia[1]->writepa_handler().append("centronics", FUNC(centronics_device::write_data0)).bit(0); - m_pia[1]->writepa_handler().append("centronics", FUNC(centronics_device::write_data1)).bit(1); - m_pia[1]->writepa_handler().append("centronics", FUNC(centronics_device::write_init)).bit(3); - m_pia[1]->writepa_handler().append(FUNC(z100_state::vidint_enable_w)).bit(5); - m_pia[1]->writepb_handler().set("centronics", FUNC(centronics_device::write_data2)).bit(2); - m_pia[1]->writepb_handler().append("centronics", FUNC(centronics_device::write_data3)).bit(3); - m_pia[1]->writepb_handler().append("centronics", FUNC(centronics_device::write_data4)).bit(4); - m_pia[1]->writepb_handler().append("centronics", FUNC(centronics_device::write_data5)).bit(5); - m_pia[1]->writepb_handler().append("centronics", FUNC(centronics_device::write_data6)).bit(6); - m_pia[1]->writepb_handler().append("centronics", FUNC(centronics_device::write_data7)).bit(7); - - centronics_device ¢ronics(CENTRONICS(config, "centronics", centronics_devices, nullptr)); - centronics.ack_handler().set(m_pia[1], FUNC(pia6821_device::cb1_w)).invert(); - centronics.busy_handler().set(m_pia[1], FUNC(pia6821_device::cb2_w)); - centronics.busy_handler().append(m_pia[1], FUNC(pia6821_device::pb0_w)); - centronics.perror_handler().set(m_pia[1], FUNC(pia6821_device::pb1_w)); - - input_merger_device &keydspyint(INPUT_MERGER_ANY_HIGH(config, "keydspyint")); - keydspyint.output_handler().set(m_picm, FUNC(pic8259_device::ir6_w)); - - FD1797(config, m_fdc, 4_MHz_XTAL / 4); - - FLOPPY_CONNECTOR(config, m_floppies[0], z100_floppies, "dd", floppy_image_device::default_mfm_floppy_formats); - FLOPPY_CONNECTOR(config, m_floppies[1], z100_floppies, "dd", floppy_image_device::default_mfm_floppy_formats); - FLOPPY_CONNECTOR(config, m_floppies[2], z100_floppies, nullptr, floppy_image_device::default_mfm_floppy_formats); - FLOPPY_CONNECTOR(config, m_floppies[3], z100_floppies, nullptr, floppy_image_device::default_mfm_floppy_formats); - - SCN2661B(config, m_epci[0], 4.9152_MHz_XTAL); // First 2661-2 serial port (printer) - m_epci[0]->txrdy_handler().set("epci0int", FUNC(input_merger_device::in_w<0>)); - m_epci[0]->rxrdy_handler().set("epci0int", FUNC(input_merger_device::in_w<1>)); - - SCN2661B(config, m_epci[1], 4.9152_MHz_XTAL); // Second 2661-2 serial port (modem) - m_epci[1]->txrdy_handler().set("epci1int", FUNC(input_merger_device::in_w<0>)); - m_epci[1]->rxrdy_handler().set("epci1int", FUNC(input_merger_device::in_w<1>)); - - input_merger_device &epci0int(INPUT_MERGER_ANY_HIGH(config, "epci0int")); - epci0int.output_handler().set(m_picm, FUNC(pic8259_device::ir4_w)); - - input_merger_device &epci1int(INPUT_MERGER_ANY_HIGH(config, "epci1int")); - epci1int.output_handler().set(m_picm, FUNC(pic8259_device::ir5_w)); -} - -/* ROM definition */ -ROM_START( z100 ) - ROM_REGION(0x4000, "ipl", 0) - ROM_LOAD("intel-d27128-1.bin", 0x0000, 0x4000, CRC(b21f0392) SHA1(69e492891cceb143a685315efe0752981a2d8143)) - - ROM_REGION(0x0400, "kbdc", 0) // 8041A keyboard controller - ROM_LOAD("444-109.u204", 0x0000, 0x0400, CRC(45181029) SHA1(0e89649364d25cf2d8669d2a293ee162e274cb64)) - - // All PROMs are typed in from Zenith technical manual listings rather than dumped from real devices, and are accordingly marked BAD_DUMP - ROM_REGION(0x0100, "iodec", 0) // 82S129 I/O Decoder PROM - ROM_LOAD("444-101.u179", 0x0000, 0x0100, CRC(c952be82) SHA1(0edf9265d302f8478a310858eb6a9352f0cda17b) BAD_DUMP) - - ROM_REGION(0x0100, "memdec", 0) // 82S129 Memory Decoder PROM - ROM_LOAD("444-104.u111", 0x0000, 0x0100, CRC(46edd69d) SHA1(5d4bafeaa4593e419bf94dba9e44c8b2be58727b) BAD_DUMP) - - ROM_REGION(0x0020, "status", 0) // 82S123 CPU Status Decode PROM - ROM_LOAD("444-105.u226", 0x0000, 0x0020, CRC(98b084e9) SHA1(d968b9a1b1d2ba3ed40036c2192c9960a6c15e99) BAD_DUMP) - - ROM_REGION(0x0100, "vramsel", 0) // 82S129 Video RAM Select PROM - ROM_LOAD("444-102.u371", 0x0000, 0x0100, CRC(4558f540) SHA1(55c9bad87b111537a6d386a6eb405169fb47304c) BAD_DUMP) - - ROM_REGION(0x0100, "viosel", 0) // 82S129 Video I/O Select PROM - ROM_LOAD("444-103.u369", 0x0000, 0x0100, CRC(854cef15) SHA1(836b244dac0085bcfe8006fde0c5f19982969236) BAD_DUMP) - - ROM_REGION(0x0100, "vrmm", 0) // TBP18S22 Video RAM Mapping Module - ROM_LOAD("444-127.u370", 0x0000, 0x0100, CRC(ac386f6b) SHA1(2b62b939d704d90edf59923a8a1a51ef1902f4d7) BAD_DUMP) -ROM_END - -} // anonymous namespace - - -/* Driver */ - -// YEAR NAME PARENT COMPAT MACHINE INPUT STATE INIT COMPANY FULLNAME FLAGS -COMP( 1982, z100, 0, 0, z100, z100, z100_state, empty_init, "Zenith Data Systems", "Z-100", MACHINE_NOT_WORKING ) diff --git a/src/mame/zenith/z22.cpp b/src/mame/zenith/z22.cpp deleted file mode 100644 index a9fcab693f1..00000000000 --- a/src/mame/zenith/z22.cpp +++ /dev/null @@ -1,221 +0,0 @@ -// 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" - - -namespace { - -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); - - void eeprom_clock_w(int state); - - void mem_map(address_map &map); - - required_device m_maincpu; - required_device m_crtc; - optional_device_array m_uart; - required_device m_eeprom; - required_shared_ptr m_dispram; - required_shared_ptr 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.pix(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)); -} - -void z22_state::eeprom_clock_w(int state) -{ - 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 - -} // anonymous namespace - - -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/zenith/z29.cpp b/src/mame/zenith/z29.cpp deleted file mode 100644 index 5400529100a..00000000000 --- a/src/mame/zenith/z29.cpp +++ /dev/null @@ -1,180 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:AJR -/*************************************************************************** - - Skeleton driver for Zenith Z-29 (alias Heathkit H-29) video terminal. - -****************************************************************************/ - -#include "emu.h" -//#include "bus/rs232/rs232.h" -#include "bus/z29_kbd/keyboard.h" -#include "cpu/mcs51/mcs51.h" -#include "machine/x2212.h" -#include "video/i8275.h" -#include "screen.h" - - -namespace { - -class z29_state : public driver_device -{ -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) - { - } - - void z29(machine_config &config); - -protected: - virtual void machine_start() override; - -private: - void keyin_w(int state); - u8 p1_r(); - void p3_w(u8 data); - u8 bs_24k_r(offs_t offset); - void crtc_w(offs_t offset, u8 data); - void latch_12k_w(u8 data); - - void prg_map(address_map &map); - void ext_map(address_map &map); - - required_device m_maincpu; - required_device m_keyboard; - required_device_array m_crtc; - required_device m_nvram; - - required_shared_ptr m_charmem; - required_shared_ptr m_attrmem; - required_region_ptr m_chargen; - - bool m_dmatype; - bool m_keyin; -}; - -void z29_state::machine_start() -{ - save_item(NAME(m_dmatype)); - save_item(NAME(m_keyin)); -} - -void z29_state::keyin_w(int state) -{ - m_keyin = state; -} - -u8 z29_state::p1_r() -{ - return m_keyin ? 0xfd : 0xff; -} - -void z29_state::p3_w(u8 data) -{ - m_dmatype = BIT(data, 4); -} - -u8 z29_state::bs_24k_r(offs_t offset) -{ - if (!machine().side_effects_disabled()) - { - if (m_dmatype) - { - u8 chardata = m_charmem[offset]; - u8 attrdata = m_attrmem[offset] & 0xf; - - m_crtc[0]->dack_w(chardata & 0x7f); - m_crtc[1]->dack_w((chardata & 0x60) | (BIT(chardata, 7) ? 0x10 : 0) | attrdata); - } - else - { - m_charmem[offset] = 0x20; - m_attrmem[offset] = 0; - } - } - - return m_dmatype ? 0x24 : 0x20; -} - -void z29_state::crtc_w(offs_t offset, u8 data) -{ - m_crtc[0]->write(offset, data); - m_crtc[1]->write(offset, data); -} - -void z29_state::latch_12k_w(u8 data) -{ - m_nvram->store(!BIT(data, 0)); - m_nvram->recall(!BIT(data, 3)); -} - -void z29_state::prg_map(address_map &map) -{ - map(0x0000, 0x1fff).rom().region("maincpu", 0); - map(0x6000, 0x67ff).mirror(0x800).r(FUNC(z29_state::bs_24k_r)); -} - -void z29_state::ext_map(address_map &map) -{ - map(0x2000, 0x2001).mirror(0xffe).r("crtc1", FUNC(i8276_device::read)).w(FUNC(z29_state::crtc_w)); - map(0x3000, 0x3000).mirror(0xfff).w(FUNC(z29_state::latch_12k_w)); - map(0x4000, 0x47ff).mirror(0x800).ram().share("attrmem"); - map(0x5000, 0x57ff).mirror(0x800).ram().share("charmem"); - map(0x7000, 0x703f).mirror(0xfc0).rw("nvram", FUNC(x2210_device::read), FUNC(x2210_device::write)); -} - - -static INPUT_PORTS_START(z29) -INPUT_PORTS_END - - -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(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"); - 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)); - - I8276(config, m_crtc[0], 14.784_MHz_XTAL / 8).set_character_width(8); - m_crtc[0]->drq_wr_callback().set_inputline(m_maincpu, MCS51_INT0_LINE); - 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); -} - - -ROM_START(z29) // All EPROMs on 85-2835-1 terminal board are HN482732AG-30 - ROM_REGION(0x2000, "maincpu", 0) - ROM_LOAD("u440.bin", 0x0000, 0x1000, CRC(169b9517) SHA1(c18b6a193655a64808e9ae8765d3e54d13e6669e)) // occupies pins 9-32 of 40-pin expansion socket - ROM_LOAD("u407.bin", 0x1000, 0x1000, CRC(b5aae8e6) SHA1(692e521a85d7e07647c66a660faa2041d1bfd785)) - - ROM_REGION(0x1000, "chargen", 0) - ROM_LOAD("u429.bin", 0x0000, 0x1000, CRC(5e3bc5bf) SHA1(18d73e3d74a9768bee8b063ea45891f955558ae7)) -ROM_END - -} // anonymous namespace - - -COMP(1983, z29, 0, 0, z29, z29, z29_state, empty_init, "Zenith Data Systems", "Z-29", MACHINE_IS_SKELETON) -- cgit v1.2.3