diff options
Diffstat (limited to 'src/mame/drivers/hp9825.cpp')
-rw-r--r-- | src/mame/drivers/hp9825.cpp | 1183 |
1 files changed, 0 insertions, 1183 deletions
diff --git a/src/mame/drivers/hp9825.cpp b/src/mame/drivers/hp9825.cpp deleted file mode 100644 index dfcc7c5d007..00000000000 --- a/src/mame/drivers/hp9825.cpp +++ /dev/null @@ -1,1183 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:F. Ulivi - -// ************************** -// Driver for HP 9825 systems -// ************************** -// -// **** Temporary header, will hopefully evolve into proper doc **** -// -// What's in: -// - Emulation of 9825B and 9825T systems -// - 12 kw (9825B) or 31kw (9825T) of RAM -// - 12 kw of system ROM -// - Keyboard (SHIFT LOCK & RESET not implemented) -// - Display & run light -// - DC100 tape drive -// - Printer -// - Beeper -// - Internal expansion ROMs -// - I/O expansion slots: 98032, 98034 & 98035 modules can be connected -// - For 9825T: the so-called SKOAL mechanism that transparently overlays RAM & ROM -// in the same address space -// - External expansion ROMs -// What's not yet in: -// - Configurable RAM size -// -// Thanks to Dyke Shaffer for publishing (on https://groups.io/g/VintHPcom) -// the source code of 98217 mass memory ROM. The 98217.bin image was reconstructed -// by re-assembling the source code (this is the reason why it's marked as -// a BAD_DUMP). And thanks to Ansgar Kueckes for adapting his assembler to -// handle HP9825 source files. -// For what regards the 9825T, I'd like to thank again Dyke Shaffer for -// publishing a lot of internal HP docs about the SKOAL card. I recovered the -// content of SKOAL ROM from its printed & scanned dump. -// I'd also like to thank Paul Berger for providing the images of the optional -// mass storage ROMs (see http://www.hpmuseum.net). -// -// 9825A can also be emulated. At the moment I haven't all the necessary -// ROM dumps, though. - -#include "emu.h" -#include "cpu/hphybrid/hphybrid.h" -#include "machine/timer.h" -#include "machine/hp9825_tape.h" -#include "machine/hp98x5_io_sys.h" -#include "machine/hp9825_optrom.h" -#include "bus/hp9845_io/hp9845_io.h" -#include "imagedev/bitbngr.h" -#include "speaker.h" -#include "sound/beep.h" -#include "hp9825.lh" -#include "softlist.h" - -// Debugging -#define VERBOSE 0 -#include "logmacro.h" - -// CPU clock (generated by a trimmered RC oscillator) -constexpr unsigned MAIN_CLOCK = 6000000; - -// KDP chip clock -constexpr unsigned KDP_CLOCK = MAIN_CLOCK / 4; - -// Peripheral Addresses (PA) -constexpr uint8_t KDP_PA = 0; -constexpr uint8_t TAPE_PA = 1; -constexpr uint8_t IO_SLOT_FIRST_PA = 2; -constexpr uint8_t IO_SLOT_LAST_PA = 15; - -// KDP clocks to print 1 line of dots (~33 ms) -// This value is semi-guessed. -constexpr unsigned KDP_CLOCKS_PER_LINE = 50000; - -// Beeper constants -// Values come from R/C values on schematics -constexpr unsigned BEEPER_FREQ = 900; -constexpr unsigned BEEPER_MS = 40; - -// Bit manipulation -namespace { - template<typename T> constexpr T BIT_MASK(unsigned n) - { - return (T)1U << n; - } - - template<typename T> void BIT_CLR(T& w , unsigned n) - { - w &= ~BIT_MASK<T>(n); - } - - template<typename T> void BIT_SET(T& w , unsigned n) - { - w |= BIT_MASK<T>(n); - } -} - -// +--------------+ -// | hp9825_state | -// +--------------+ -class hp9825_state : public driver_device -{ -public: - hp9825_state(const machine_config &mconfig, device_type type, const char *tag) - : driver_device(mconfig, type, tag) - , m_cpu(*this , "cpu") - , m_rom_drawers(*this , "drawer%u" , 0U) - , m_io_sys(*this , "io_sys") - , m_cursor_timer(*this , "cursor_timer") - , m_tape(*this , "tape") - , m_io_key(*this , "KEY%u" , 0) - , m_shift_key(*this , "KEY_SHIFT") - , m_prt_alpha_out(*this , "prt_alpha") - , m_prt_graph_out(*this , "prt_graph") - , m_prt_timer(*this , "prt_timer") - , m_beeper(*this , "beeper") - , m_beep_timer(*this , "beep_timer") - , m_io_slot(*this, "slot%u", 0U) - , m_display(*this , "char_%u_%u" , 0U , 0U) - , m_run_light(*this , "run_light") - { - } - - void hp9825_base(machine_config &config); - -protected: - virtual void machine_start() override; - virtual void device_reset() override; - virtual void machine_reset() override; - - required_device<hp_09825_67907_cpu_device> m_cpu; - required_device_array<hp9825_optrom_device , 4> m_rom_drawers; - -private: - required_device<hp98x5_io_sys_device> m_io_sys; - required_device<timer_device> m_cursor_timer; - required_device<hp9825_tape_device> m_tape; - required_ioport_array<4> m_io_key; - required_ioport m_shift_key; - required_device<bitbanger_device> m_prt_alpha_out; - required_device<bitbanger_device> m_prt_graph_out; - required_device<timer_device> m_prt_timer; - required_device<beep_device> m_beeper; - required_device<timer_device> m_beep_timer; - required_device_array<hp9845_io_slot_device , 3> m_io_slot; - output_finder<32 , 7> m_display; - output_finder<> m_run_light; - - bool m_display_on; - uint8_t m_display_mem[ 32 ]; - uint8_t m_display_idx; - bool m_rpl_cursor; - bool m_cursor_blink; - bool m_any_cursor; - uint8_t m_scancode; - bool m_key_pressed; - bool m_autorepeating; - unsigned m_autorepeat_cnt; - // Printer - uint8_t m_printer_mem[ 16 ]; - uint8_t m_printer_idx; - unsigned m_printer_line; // 0: printer idle, 1..10: line being printed - // SC of slots - int m_slot_sc[ 3 ]; - - void cpu_io_map(address_map &map); - - uint16_t kb_scancode_r(); - void disp_w(uint16_t data); - uint16_t kdp_status_r(); - void kdp_control_w(uint16_t data); - void printer_w(uint16_t data); - - void update_display(); - TIMER_DEVICE_CALLBACK_MEMBER(cursor_blink); - void kb_scan_ioport(ioport_value pressed , ioport_port &port , unsigned idx_base , int& max_seq_len , unsigned& max_seq_idx); - TIMER_DEVICE_CALLBACK_MEMBER(kb_scan); - - TIMER_DEVICE_CALLBACK_MEMBER(prt_timer); - - TIMER_DEVICE_CALLBACK_MEMBER(beep_timer); - - // Slot handling - void set_irq_slot(unsigned slot , int state); - void set_sts_slot(unsigned slot , int state); - void set_flg_slot(unsigned slot , int state); - void set_dmar_slot(unsigned slot , int state); -}; - -void hp9825_state::machine_start() -{ - m_display.resolve(); - m_run_light.resolve(); - - save_item(NAME(m_display_on)); - save_item(NAME(m_display_mem)); - save_item(NAME(m_display_idx)); - save_item(NAME(m_scancode)); -} - -void hp9825_state::device_reset() -{ - // First, unmap every r/w handler in 1..12 select codes - for (unsigned sc = IO_SLOT_FIRST_PA; sc < (IO_SLOT_LAST_PA + 1); sc++) { - m_cpu->space(AS_IO).unmap_readwrite(sc * 4 , sc * 4 + 3); - } - - // Then, set r/w handlers of all installed I/O cards - int sc; - read16m_delegate rhandler(*this); - write16m_delegate whandler(*this); - for (unsigned i = 0; i < 3; i++) { - if ((sc = m_io_slot[ i ]->get_rw_handlers(rhandler , whandler)) >= 0) { - logerror("Install R/W handlers for slot %u @ SC = %d\n", i, sc); - m_cpu->space(AS_IO).install_readwrite_handler(sc * 4 , sc * 4 + 3 , rhandler , whandler); - } - m_slot_sc[ i ] = sc; - } -} - -void hp9825_state::machine_reset() -{ - m_display_on = false; - m_display_idx = 0; - m_rpl_cursor = false; - m_cursor_timer->reset(); - m_cursor_blink = true; - update_display(); - m_scancode = 0; - m_key_pressed = false; - m_autorepeating = false; - m_autorepeat_cnt = 0; - m_printer_idx = 0; - m_printer_line = 0; - m_prt_timer->reset(); - m_beeper->set_state(0); - m_beep_timer->reset(); -} - -void hp9825_state::cpu_io_map(address_map &map) -{ - map.unmap_value_low(); - map(HP_MAKE_IOADDR(KDP_PA , 0) , HP_MAKE_IOADDR(KDP_PA , 0)).rw(FUNC(hp9825_state::kb_scancode_r) , FUNC(hp9825_state::disp_w)); - map(HP_MAKE_IOADDR(KDP_PA , 1) , HP_MAKE_IOADDR(KDP_PA , 1)).rw(FUNC(hp9825_state::kdp_status_r) , FUNC(hp9825_state::kdp_control_w)); - map(HP_MAKE_IOADDR(KDP_PA , 2) , HP_MAKE_IOADDR(KDP_PA , 2)).w(FUNC(hp9825_state::printer_w)); - map(HP_MAKE_IOADDR(TAPE_PA , 0) , HP_MAKE_IOADDR(TAPE_PA , 3)).rw(m_tape , FUNC(hp9825_tape_device::tape_r) , FUNC(hp9825_tape_device::tape_w)); - // TODO: -} - -uint16_t hp9825_state::kb_scancode_r() -{ - uint8_t res = m_scancode; - if (m_shift_key->read()) { - BIT_SET(res , 7); - } - m_io_sys->set_irq(KDP_PA , false); - return res; -} - -void hp9825_state::disp_w(uint16_t data) -{ - if (m_display_on) { - m_display_on = false; - m_cursor_timer->reset(); - m_cursor_blink = true; - m_display_idx = 0; - update_display(); - } - m_display_mem[ m_display_idx++ ] = uint8_t(data); -} - -uint16_t hp9825_state::kdp_status_r() -{ - uint16_t res = 8; - if (m_io_sys->is_irq_pending(KDP_PA)) { - BIT_SET(res , 4); - } - if (m_printer_line) { - BIT_SET(res , 2); - } - - return res; -} - -void hp9825_state::kdp_control_w(uint16_t data) -{ - bool regen_display = false; - if (BIT(data , 1) && !m_display_on) { - m_display_on = true; - // Cursor should blink at 2^-19 the KDP clock - attotime cursor_half_period{ attotime::from_ticks(262144 , KDP_CLOCK) }; - m_cursor_timer->adjust(cursor_half_period , 0 , cursor_half_period); - regen_display = true; - } - if (BIT(data , 6) && !m_rpl_cursor) { - m_rpl_cursor = true; - regen_display = true; - } - if (BIT(data , 5) && m_rpl_cursor) { - m_rpl_cursor = false; - regen_display = true; - } - if (BIT(data , 4)) { - if (BIT(data , 3)) { - m_run_light = !m_run_light; - } else { - m_run_light = false; - } - } else if (BIT(data , 3)) { - m_run_light = true; - } - if (BIT(data , 0) && m_printer_line == 0) { - // Start printing - // Dump text line to alpha bitbanger - for (auto c : m_printer_mem) { - m_prt_alpha_out->output(c); - } - m_prt_alpha_out->output('\n'); - m_printer_idx = 0; - m_printer_line++; - m_prt_timer->adjust(attotime::from_ticks(KDP_CLOCKS_PER_LINE , KDP_CLOCK)); - } - if (BIT(data , 2)) { - // Start beeper - m_beeper->set_state(1); - m_beep_timer->adjust(attotime::from_msec(BEEPER_MS)); - } - if (regen_display) { - update_display(); - } -} - -void hp9825_state::printer_w(uint16_t data) -{ - m_printer_mem[ m_printer_idx ] = uint8_t(data); - m_printer_idx = (m_printer_idx + 1) & 0xf; -} - -// The character generator was reverse engineered from images of printer & display test patterns. -// It is not guaranteed to be pixel-accurate though it looks quite close to the original. -static const uint8_t chargen[ 128 ][ 5 ] = { - { 0x08,0x1c,0x3e,0x7f,0x00 }, // 00 - { 0x30,0x48,0x45,0x40,0x30 }, // 01 - { 0x45,0x29,0x11,0x29,0x45 }, // 02 - { 0x7d,0x09,0x11,0x21,0x7d }, // 03 - { 0x38,0x44,0x44,0x38,0x44 }, // 04 - { 0x7c,0x2a,0x4a,0x4a,0x34 }, // 05 - { 0x7f,0x01,0x01,0x01,0x03 }, // 06 - { 0x7d,0x09,0x05,0x05,0x79 }, // 07 - { 0x60,0x58,0x46,0x58,0x60 }, // 08 - { 0x38,0x44,0x44,0x3c,0x04 }, // 09 - { 0x10,0x20,0x7f,0x20,0x10 }, // 0a - { 0x62,0x14,0x08,0x10,0x60 }, // 0b - { 0x40,0x3c,0x20,0x20,0x1c }, // 0c - { 0x08,0x1c,0x2a,0x08,0x08 }, // 0d - { 0x10,0x08,0x78,0x08,0x04 }, // 0e - { 0x08,0x55,0x7f,0x55,0x08 }, // 0f - { 0x3e,0x49,0x49,0x49,0x3e }, // 10 - { 0x5e,0x61,0x01,0x61,0x5e }, // 11 - { 0x30,0x4a,0x4d,0x49,0x30 }, // 12 - { 0x78,0x14,0x15,0x14,0x78 }, // 13 - { 0x38,0x44,0x45,0x3c,0x40 }, // 14 - { 0x78,0x15,0x14,0x15,0x78 }, // 15 - { 0x38,0x45,0x44,0x3d,0x40 }, // 16 - { 0x3c,0x43,0x42,0x43,0x3c }, // 17 - { 0x38,0x45,0x44,0x45,0x38 }, // 18 - { 0x3e,0x41,0x40,0x41,0x3e }, // 19 - { 0x3c,0x41,0x40,0x41,0x3c }, // 1a - { 0x7e,0x09,0x7f,0x49,0x49 }, // 1b - { 0x38,0x44,0x38,0x54,0x58 }, // 1c - { 0x12,0x19,0x15,0x12,0x00 }, // 1d - { 0x48,0x7e,0x49,0x41,0x42 }, // 1e - { 0x55,0x2a,0x55,0x2a,0x55 }, // 1f - { 0x00,0x00,0x00,0x00,0x00 }, // 20 - { 0x00,0x5f,0x00,0x00,0x00 }, // 21 - { 0x00,0x03,0x00,0x03,0x00 }, // 22 - { 0x14,0x7f,0x14,0x7f,0x14 }, // 23 - { 0x24,0x2a,0x7f,0x2a,0x12 }, // 24 - { 0x23,0x13,0x08,0x64,0x62 }, // 25 - { 0x36,0x49,0x56,0x20,0x50 }, // 26 - { 0x00,0x0b,0x07,0x00,0x00 }, // 27 - { 0x00,0x00,0x3e,0x41,0x00 }, // 28 - { 0x00,0x41,0x3e,0x00,0x00 }, // 29 - { 0x08,0x2a,0x1c,0x2a,0x08 }, // 2a - { 0x08,0x08,0x3e,0x08,0x08 }, // 2b - { 0x00,0x58,0x38,0x00,0x00 }, // 2c - { 0x08,0x08,0x08,0x08,0x08 }, // 2d - { 0x00,0x60,0x60,0x00,0x00 }, // 2e - { 0x20,0x10,0x08,0x04,0x02 }, // 2f - { 0x3e,0x51,0x49,0x45,0x3e }, // 30 - { 0x00,0x42,0x7f,0x40,0x00 }, // 31 - { 0x62,0x51,0x49,0x49,0x46 }, // 32 - { 0x22,0x41,0x49,0x49,0x36 }, // 33 - { 0x18,0x14,0x12,0x7f,0x10 }, // 34 - { 0x27,0x45,0x45,0x45,0x39 }, // 35 - { 0x3c,0x4a,0x49,0x49,0x30 }, // 36 - { 0x01,0x71,0x09,0x05,0x03 }, // 37 - { 0x36,0x49,0x49,0x49,0x36 }, // 38 - { 0x06,0x49,0x49,0x29,0x1e }, // 39 - { 0x00,0x36,0x36,0x00,0x00 }, // 3a - { 0x00,0x5b,0x3b,0x00,0x00 }, // 3b - { 0x00,0x08,0x14,0x22,0x41 }, // 3c - { 0x14,0x14,0x14,0x14,0x14 }, // 3d - { 0x41,0x22,0x14,0x08,0x00 }, // 3e - { 0x06,0x01,0x51,0x09,0x06 }, // 3f - { 0x3e,0x41,0x5d,0x55,0x1e }, // 40 - { 0x7e,0x09,0x09,0x09,0x7e }, // 41 - { 0x7f,0x49,0x49,0x49,0x36 }, // 42 - { 0x3e,0x41,0x41,0x41,0x22 }, // 43 - { 0x7f,0x41,0x41,0x41,0x3e }, // 44 - { 0x7f,0x49,0x49,0x49,0x41 }, // 45 - { 0x7f,0x09,0x09,0x09,0x01 }, // 46 - { 0x3e,0x41,0x41,0x51,0x72 }, // 47 - { 0x7f,0x08,0x08,0x08,0x7f }, // 48 - { 0x00,0x41,0x7f,0x41,0x00 }, // 49 - { 0x20,0x40,0x40,0x40,0x3f }, // 4a - { 0x7f,0x08,0x14,0x22,0x41 }, // 4b - { 0x7f,0x40,0x40,0x40,0x40 }, // 4c - { 0x7f,0x02,0x0c,0x02,0x7f }, // 4d - { 0x7f,0x04,0x08,0x10,0x7f }, // 4e - { 0x3e,0x41,0x41,0x41,0x3e }, // 4f - { 0x7f,0x09,0x09,0x09,0x06 }, // 50 - { 0x3e,0x41,0x51,0x21,0x5e }, // 51 - { 0x7f,0x09,0x19,0x29,0x46 }, // 52 - { 0x26,0x49,0x49,0x49,0x32 }, // 53 - { 0x01,0x01,0x7f,0x01,0x01 }, // 54 - { 0x3f,0x40,0x40,0x40,0x3f }, // 55 - { 0x07,0x18,0x60,0x18,0x07 }, // 56 - { 0x7f,0x20,0x10,0x20,0x7f }, // 57 - { 0x63,0x14,0x08,0x14,0x63 }, // 58 - { 0x03,0x04,0x78,0x04,0x03 }, // 59 - { 0x61,0x51,0x49,0x45,0x43 }, // 5a - { 0x00,0x00,0x7f,0x41,0x41 }, // 5b - { 0x20,0x7f,0x01,0x01,0x01 }, // 5c - { 0x41,0x41,0x7f,0x00,0x00 }, // 5d - { 0x04,0x02,0x7f,0x02,0x04 }, // 5e - { 0x40,0x40,0x40,0x40,0x40 }, // 5f - { 0x00,0x07,0x0b,0x00,0x00 }, // 60 - { 0x38,0x44,0x44,0x3c,0x40 }, // 61 - { 0x7f,0x48,0x44,0x44,0x38 }, // 62 - { 0x38,0x44,0x44,0x44,0x20 }, // 63 - { 0x38,0x44,0x44,0x48,0x7f }, // 64 - { 0x38,0x54,0x54,0x54,0x08 }, // 65 - { 0x08,0x7e,0x09,0x02,0x00 }, // 66 - { 0x08,0x14,0x54,0x54,0x3c }, // 67 - { 0x7f,0x08,0x04,0x04,0x78 }, // 68 - { 0x00,0x44,0x7d,0x40,0x00 }, // 69 - { 0x20,0x40,0x44,0x3d,0x00 }, // 6a - { 0x7f,0x10,0x28,0x44,0x00 }, // 6b - { 0x00,0x41,0x7f,0x40,0x00 }, // 6c - { 0x78,0x04,0x18,0x04,0x78 }, // 6d - { 0x7c,0x08,0x04,0x04,0x78 }, // 6e - { 0x38,0x44,0x44,0x44,0x38 }, // 6f - { 0x7c,0x14,0x24,0x24,0x18 }, // 70 - { 0x18,0x24,0x14,0x7c,0x40 }, // 71 - { 0x7c,0x08,0x04,0x04,0x00 }, // 72 - { 0x48,0x54,0x54,0x54,0x20 }, // 73 - { 0x04,0x3e,0x44,0x20,0x00 }, // 74 - { 0x3c,0x40,0x40,0x20,0x7c }, // 75 - { 0x1c,0x20,0x40,0x20,0x1c }, // 76 - { 0x3c,0x40,0x30,0x40,0x3c }, // 77 - { 0x44,0x28,0x10,0x28,0x44 }, // 78 - { 0x04,0x48,0x30,0x08,0x04 }, // 79 - { 0x44,0x64,0x54,0x4c,0x44 }, // 7a - { 0x08,0x7c,0x04,0x7c,0x02 }, // 7b - { 0x00,0x00,0x7f,0x00,0x00 }, // 7c - { 0x08,0x08,0x2a,0x1c,0x08 }, // 7d - { 0x41,0x63,0x55,0x49,0x63 }, // 7e - { 0x7f,0x08,0x08,0x08,0x08 } // 7f -}; - -void hp9825_state::update_display() -{ - m_any_cursor = false; - for (unsigned i = 0; i < 32; ++i) { - bool cursor_here = BIT(m_display_mem[ i ] , 7); - if (cursor_here) { - m_any_cursor = true; - } - bool show_cursor = m_cursor_blink && cursor_here; - uint8_t char_code = m_display_mem[ i ] & 0x7f; - for (unsigned j = 0; j < 7; ++j) { - uint8_t five_dots = 0; - if (m_display_on) { - for (unsigned col = 0; col < 5; col++) { - uint8_t char_col; - if (show_cursor) { - if (m_rpl_cursor) { - // Replace cursor: all pixels lit - char_col = ~0; - } else { - // Insert cursor: character code 0 - char_col = chargen[ 0 ][ col ]; - } - } else { - char_col = chargen[ char_code ][ col ]; - } - if (BIT(char_col , j)) { - BIT_SET(five_dots , col); - } - } - } - m_display[ i ][ j ] = five_dots; - } - } -} - -TIMER_DEVICE_CALLBACK_MEMBER(hp9825_state::cursor_blink) -{ - m_cursor_blink = !m_cursor_blink; - if (m_any_cursor) { - update_display(); - } -} - -TIMER_DEVICE_CALLBACK_MEMBER(hp9825_state::kb_scan) -{ - ioport_value input[ 4 ] - { m_io_key[ 0 ]->read(), - m_io_key[ 1 ]->read(), - m_io_key[ 2 ]->read(), - m_io_key[ 3 ]->read() - }; - - if (m_key_pressed) { - // Still pressed ? - m_key_pressed = BIT(input[ m_scancode / 32 ] , m_scancode % 32); - } else { - int max_seq_len = 0; - unsigned max_seq_idx = 0; - for (unsigned i = 0; i < 4; i++) { - kb_scan_ioport(input[ i ] , *m_io_key[ i ] , i << 5 , max_seq_len , max_seq_idx); - } - if (max_seq_len) { - m_scancode = max_seq_idx; - m_key_pressed = true; - m_io_sys->set_irq(KDP_PA , true); - } - } - - if (m_key_pressed) { - auto prev_cnt = m_autorepeat_cnt; - m_autorepeat_cnt++; - // Auto-repeat initial delay & frequency are entirely guessed.. - if (BIT(m_autorepeat_cnt , 5)) { - // Initial delay passed - m_autorepeating = true; - } - if (m_autorepeating && BIT(~prev_cnt & m_autorepeat_cnt , 3)) { - // Repeat key every time bit 3 of autorepeat counter goes 0->1 - m_io_sys->set_irq(KDP_PA , true); - } - } else { - m_autorepeating = false; - m_autorepeat_cnt = 0; - } -} - -void hp9825_state::kb_scan_ioport(ioport_value pressed , ioport_port &port , unsigned idx_base , int& max_seq_len , unsigned& max_seq_idx) -{ - while (pressed) { - unsigned bit_no = 31 - count_leading_zeros_32(pressed); - ioport_value mask = BIT_MASK<ioport_value>(bit_no); - int seq_len = port.field(mask)->seq().length(); - if (seq_len > max_seq_len) { - max_seq_len = seq_len; - max_seq_idx = bit_no + idx_base; - } - pressed &= ~mask; - } -} - -TIMER_DEVICE_CALLBACK_MEMBER(hp9825_state::prt_timer) -{ - if (m_printer_line == 1 || m_printer_line == 9 || m_printer_line == 10) { - // Empty lines - for (unsigned i = 0; i < 110; i++) { - m_prt_graph_out->output(' '); - } - } else { - for (unsigned i = 0; i < 16; i++) { - for (unsigned col = 0; col < 5; col++) { - uint8_t pixels = chargen[ m_printer_mem[ i ] & 0x7f ][ col ]; - m_prt_graph_out->output(BIT(pixels , m_printer_line - 2) ? '*' : ' '); - } - m_prt_graph_out->output(' '); - m_prt_graph_out->output(' '); - } - } - m_prt_graph_out->output('\n'); - m_printer_line++; - if (m_printer_line <= 10) { - m_prt_timer->adjust(attotime::from_ticks(KDP_CLOCKS_PER_LINE , KDP_CLOCK)); - } else { - m_printer_line = 0; - } -} - -TIMER_DEVICE_CALLBACK_MEMBER(hp9825_state::beep_timer) -{ - m_beeper->set_state(0); -} - -void hp9825_state::set_irq_slot(unsigned slot , int state) -{ - int sc = m_slot_sc[ slot ]; - assert(sc >= 0); - m_io_sys->set_irq(uint8_t(sc) , state); -} - -void hp9825_state::set_sts_slot(unsigned slot , int state) -{ - int sc = m_slot_sc[ slot ]; - assert(sc >= 0); - m_io_sys->set_sts(uint8_t(sc) , state); -} - -void hp9825_state::set_flg_slot(unsigned slot , int state) -{ - int sc = m_slot_sc[ slot ]; - assert(sc >= 0); - m_io_sys->set_flg(uint8_t(sc) , state); -} - -void hp9825_state::set_dmar_slot(unsigned slot , int state) -{ - int sc = m_slot_sc[ slot ]; - assert(sc >= 0); - m_io_sys->set_dmar(uint8_t(sc) , state); -} - -void hp9825_state::hp9825_base(machine_config &config) -{ - HP_09825_67907(config , m_cpu , MAIN_CLOCK); - // Just guessing... settings borrowed from hp9845 - m_cpu->set_rw_cycles(6 , 6); - m_cpu->set_relative_mode(false); - m_cpu->set_addrmap(AS_IO , &hp9825_state::cpu_io_map); - m_cpu->int_cb().set(m_io_sys , FUNC(hp98x5_io_sys_device::int_r)); - m_cpu->pa_changed_cb().set(m_io_sys , FUNC(hp98x5_io_sys_device::pa_w)); - - // Needed when 98035 RTC module is connected or time advances at about 1/4 the correct speed (NP misses a lot of 1kHz interrupts) - config.set_maximum_quantum(attotime::from_hz(5000)); - - HP98X5_IO_SYS(config , m_io_sys , 0); - m_io_sys->irl().set_inputline(m_cpu, HPHYBRID_IRL); - m_io_sys->irh().set_inputline(m_cpu, HPHYBRID_IRH); - m_io_sys->sts().set(m_cpu , FUNC(hp_09825_67907_cpu_device::status_w)); - m_io_sys->flg().set(m_cpu , FUNC(hp_09825_67907_cpu_device::flag_w)); - m_io_sys->dmar().set(m_cpu , FUNC(hp_09825_67907_cpu_device::dmar_w)); - - TIMER(config , m_cursor_timer , 0).configure_generic(FUNC(hp9825_state::cursor_blink)); - - // Keyboard scan timer. A scan of the whole keyboard should take 2^14 KDP clocks. - TIMER(config , "kb_timer" , 0).configure_periodic(FUNC(hp9825_state::kb_scan), attotime::from_ticks(16384 , KDP_CLOCK)); - - // Tape drive - HP9825_TAPE(config , m_tape , 0); - m_tape->flg().set([this](int state) { m_io_sys->set_flg(TAPE_PA , state); }); - m_tape->sts().set([this](int state) { m_io_sys->set_sts(TAPE_PA , state); }); - m_tape->dmar().set([this](int state) { m_io_sys->set_dmar(TAPE_PA , state); }); - - // Printer - BITBANGER(config , m_prt_alpha_out , 0); - BITBANGER(config , m_prt_graph_out , 0); - TIMER(config , m_prt_timer , 0).configure_generic(FUNC(hp9825_state::prt_timer)); - - // Beeper - SPEAKER(config, "mono").front_center(); - BEEP(config, m_beeper, BEEPER_FREQ).add_route(ALL_OUTPUTS, "mono", 1.00); - TIMER(config , m_beep_timer , 0).configure_generic(FUNC(hp9825_state::beep_timer)); - - // I/O slots - for (unsigned slot = 0; slot < 3; slot++) { - auto& finder = m_io_slot[ slot ]; - hp9845_io_slot_device& tmp( HP9845_IO_SLOT(config , finder , 0) ); - tmp.irq().set([this , slot](int state) { set_irq_slot(slot , state); }); - tmp.sts().set([this , slot](int state) { set_sts_slot(slot , state); }); - tmp.flg().set([this , slot](int state) { set_flg_slot(slot , state); }); - tmp.dmar().set([this , slot](int state) { set_dmar_slot(slot , state); }); - } - - // Optional ROM slots - for (auto& finder : m_rom_drawers) { - HP9825_OPTROM(config , finder); - } - - config.set_default_layout(layout_hp9825); -} - -#define IOP_MASK(x) BIT_MASK<ioport_value>((x)) - -static INPUT_PORTS_START(hp9825) - // Keyboard is arranged in a 8 x 16 matrix. Of the 128 possible positions, 102 are used. - // Keys are mapped on bit b of KEYn - // where b = (row & 1) << 4 + column, n = row >> 1 - // column = [0..15] - // row = [0..7] - // 4 more keys are not in the matrix: 2 SHIFTs, 1 SHIFT LOCK and RESET key. - // Fun fact: alphanumeric keys are arranged in the matrix so that their scancode (row/column number) - // equals the lower case ASCII code. The person in charge of routing the keyboard PCB - // must have loved this arrangement... - PORT_START("KEY0") - PORT_BIT(IOP_MASK(0) , IP_ACTIVE_HIGH , IPT_UNUSED) // 0,0: N/U - PORT_BIT(IOP_MASK(1) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC)) PORT_NAME("Stop") // 0,1: Stop - PORT_BIT(IOP_MASK(2) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Rewind") // 0,2: Rewind - PORT_BIT(IOP_MASK(3) , IP_ACTIVE_HIGH , IPT_UNUSED) // 0,3: N/U - PORT_BIT(IOP_MASK(4) , IP_ACTIVE_HIGH , IPT_UNUSED) // 0,4: N/U - PORT_BIT(IOP_MASK(5) , IP_ACTIVE_HIGH , IPT_UNUSED) // 0,5: N/U - PORT_BIT(IOP_MASK(6) , IP_ACTIVE_HIGH , IPT_UNUSED) // 0,6: N/U - PORT_BIT(IOP_MASK(7) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Result") // 0,7: Result - PORT_BIT(IOP_MASK(8) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Line insert") // 0,8: Line insert - PORT_BIT(IOP_MASK(9) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Line delete") // 0,9: Line delete - PORT_BIT(IOP_MASK(10) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER_PAD) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD)) PORT_NAME("Execute") // 0,10: Execute - PORT_BIT(IOP_MASK(11) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Line recall") // 0,11: Line recall - PORT_BIT(IOP_MASK(12) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Run") // 0,12: Run - PORT_BIT(IOP_MASK(13) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Store") // 0,13: Store - PORT_BIT(IOP_MASK(14) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Display left") // 0,14: Display left - PORT_BIT(IOP_MASK(15) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Display right") // 0,15: Display right - PORT_BIT(IOP_MASK(16) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) PORT_NAME("Display down") // 1,0: Display down - PORT_BIT(IOP_MASK(17) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP)) PORT_NAME("Display up") // 1,1: Display up - PORT_BIT(IOP_MASK(18) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_HOME) PORT_NAME("Clear") // 1,2: Clear - PORT_BIT(IOP_MASK(19) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Print all") // 1,3: Print all - PORT_BIT(IOP_MASK(20) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_LEFT) PORT_NAME("Char back") // 1,4: Char back - PORT_BIT(IOP_MASK(21) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_RIGHT) PORT_NAME("Char forward") // 1,5: Char forward - PORT_BIT(IOP_MASK(22) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_INSERT) PORT_NAME("Char ins/rpl") // 1,6: Char ins/rpl - PORT_BIT(IOP_MASK(23) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_DEL) PORT_NAME("Char delete") // 1,7: Char delete - PORT_BIT(IOP_MASK(24) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Step") // 1,8: Step - PORT_BIT(IOP_MASK(25) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER) PORT_NAME("Continue") PORT_CHAR(13) // 1,9: Continue - PORT_BIT(IOP_MASK(26) , IP_ACTIVE_HIGH , IPT_UNUSED) // 1,10: N/U - PORT_BIT(IOP_MASK(27) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("List") // 1,11: List - PORT_BIT(IOP_MASK(28) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Line fetch") // 1,12: Line fetch - PORT_BIT(IOP_MASK(29) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Erase") // 1,13: Erase - PORT_BIT(IOP_MASK(30) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Record") // 1,14: Record - PORT_BIT(IOP_MASK(31) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Load") // 1,15: Load - - PORT_START("KEY1") - PORT_BIT(IOP_MASK(0) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') // 2,0: Space - PORT_BIT(IOP_MASK(1) , IP_ACTIVE_HIGH , IPT_UNUSED) // 2,1: N/U - PORT_BIT(IOP_MASK(2) , IP_ACTIVE_HIGH , IPT_UNUSED) // 2,2: N/U - PORT_BIT(IOP_MASK(3) , IP_ACTIVE_HIGH , IPT_UNUSED) // 2,3: N/U - PORT_BIT(IOP_MASK(4) , IP_ACTIVE_HIGH , IPT_UNUSED) // 2,4: N/U - PORT_BIT(IOP_MASK(5) , IP_ACTIVE_HIGH , IPT_UNUSED) // 2,5: N/U - PORT_BIT(IOP_MASK(6) , IP_ACTIVE_HIGH , IPT_UNUSED) // 2,6: N/U - PORT_BIT(IOP_MASK(7) , IP_ACTIVE_HIGH , IPT_UNUSED) // 2,7: N/U - PORT_BIT(IOP_MASK(8) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('(') PORT_NAME("Keypad (") // 2,8: KP ( - PORT_BIT(IOP_MASK(9) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(')') PORT_NAME("Keypad )") // 2,9: KP ) - PORT_BIT(IOP_MASK(10) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_ASTERISK) PORT_CHAR(UCHAR_MAMEKEY(ASTERISK)) // 2,10: KP * - PORT_BIT(IOP_MASK(11) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_PLUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(PLUS_PAD)) // 2,11: KP + - PORT_BIT(IOP_MASK(12) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<') // 2,12: , - PORT_BIT(IOP_MASK(13) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD)) // 2,13: KP - - PORT_BIT(IOP_MASK(14) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>') // 2,14: . - PORT_BIT(IOP_MASK(15) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH_PAD) PORT_CHAR(UCHAR_MAMEKEY(SLASH_PAD)) // 2,15: KP / - PORT_BIT(IOP_MASK(16) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR('\'') // 3,0: 0 - PORT_BIT(IOP_MASK(17) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') // 3,1: 1 - PORT_BIT(IOP_MASK(18) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"') // 3,2: 2 - PORT_BIT(IOP_MASK(19) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') // 3,3: 3 - PORT_BIT(IOP_MASK(20) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') // 3,4: 4 - PORT_BIT(IOP_MASK(21) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') // 3,5: 5 - PORT_BIT(IOP_MASK(22) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&') // 3,6: 6 - PORT_BIT(IOP_MASK(23) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('@') // 3,7: 7 - PORT_BIT(IOP_MASK(24) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('[') // 3,8: 8 - PORT_BIT(IOP_MASK(25) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(']') // 3,9: 9 - PORT_BIT(IOP_MASK(26) , IP_ACTIVE_HIGH , IPT_UNUSED) // 3,10: N/U - PORT_BIT(IOP_MASK(27) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') // 3,11: ; - PORT_BIT(IOP_MASK(28) , IP_ACTIVE_HIGH , IPT_UNUSED) // 3,12: N/U - PORT_BIT(IOP_MASK(29) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS_PAD) PORT_CHAR(UCHAR_MAMEKEY(EQUALS_PAD)) // 3,13: = - PORT_BIT(IOP_MASK(30) , IP_ACTIVE_HIGH , IPT_UNUSED) // 3,14: N/U - PORT_BIT(IOP_MASK(31) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('?') PORT_CHAR(':') // 3,15: ? - - PORT_START("KEY2") - PORT_BIT(IOP_MASK(0) , IP_ACTIVE_HIGH , IPT_UNUSED) // 4,0: N/U - PORT_BIT(IOP_MASK(1) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("f0") // 4,1: f0 - PORT_BIT(IOP_MASK(2) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1)) PORT_NAME("f1") // 4,2: f1 - PORT_BIT(IOP_MASK(3) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2)) PORT_NAME("f2") // 4,3: f2 - PORT_BIT(IOP_MASK(4) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3)) PORT_NAME("f3") // 4,4: f3 - PORT_BIT(IOP_MASK(5) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4)) PORT_NAME("f4") // 4,5: f4 - PORT_BIT(IOP_MASK(6) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5)) PORT_NAME("f5") // 4,6: f5 - PORT_BIT(IOP_MASK(7) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6)) PORT_NAME("f6") // 4,7: f6 - PORT_BIT(IOP_MASK(8) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7)) PORT_NAME("f7") // 4,8: f7 - PORT_BIT(IOP_MASK(9) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8)) PORT_NAME("f8") // 4,9: f8 - PORT_BIT(IOP_MASK(10) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_F9) PORT_CHAR(UCHAR_MAMEKEY(F9)) PORT_NAME("f9") // 4,10: f9 - PORT_BIT(IOP_MASK(11) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_F10) PORT_CHAR(UCHAR_MAMEKEY(F10)) PORT_NAME("f10") // 4,11: f10 - PORT_BIT(IOP_MASK(12) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_F11) PORT_CHAR(UCHAR_MAMEKEY(F11)) PORT_NAME("f11") // 4,12: f11 - PORT_BIT(IOP_MASK(13) , IP_ACTIVE_HIGH , IPT_UNUSED) // 4,13: N/U - PORT_BIT(IOP_MASK(14) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_0_PAD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD)) // 4,14: KP 0 - PORT_BIT(IOP_MASK(15) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_1_PAD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD)) // 4,15: KP 1 - PORT_BIT(IOP_MASK(16) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_2_PAD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD)) // 5,0: KP 2 - PORT_BIT(IOP_MASK(17) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_3_PAD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD)) // 5,1: KP 3 - PORT_BIT(IOP_MASK(18) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_4_PAD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD)) // 5,2: KP 4 - PORT_BIT(IOP_MASK(19) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_5_PAD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD)) // 5,3: KP 5 - PORT_BIT(IOP_MASK(20) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_6_PAD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD)) // 5,4: KP 6 - PORT_BIT(IOP_MASK(21) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_7_PAD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD)) // 5,5: KP 7 - PORT_BIT(IOP_MASK(22) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_8_PAD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD)) // 5,6: KP 8 - PORT_BIT(IOP_MASK(23) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_9_PAD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD)) // 5,7: KP 9 - PORT_BIT(IOP_MASK(24) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_DEL_PAD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD)) // 5,8: KP . - PORT_BIT(IOP_MASK(25) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA_PAD) PORT_CHAR(UCHAR_MAMEKEY(COMMA_PAD)) // 5,9: KP , - PORT_BIT(IOP_MASK(26) , IP_ACTIVE_HIGH , IPT_UNUSED) // 5,10: N/U - PORT_BIT(IOP_MASK(27) , IP_ACTIVE_HIGH , IPT_UNUSED) // 5,11: N/U - PORT_BIT(IOP_MASK(28) , IP_ACTIVE_HIGH , IPT_UNUSED) // 5,12: N/U - PORT_BIT(IOP_MASK(29) , IP_ACTIVE_HIGH , IPT_UNUSED) // 5,13: N/U - PORT_BIT(IOP_MASK(30) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_NAME(u8"\u2191 \u221A") // 5,14: ^ (↑ √) - PORT_BIT(IOP_MASK(31) , IP_ACTIVE_HIGH , IPT_UNUSED) // 5,15: N/U - - PORT_START("KEY3") - PORT_BIT(IOP_MASK(0) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Enter exp _") // 6,0: Enter exp - PORT_BIT(IOP_MASK(1) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') // 6,1: A - PORT_BIT(IOP_MASK(2) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') // 6,2: B - PORT_BIT(IOP_MASK(3) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') // 6,3: C - PORT_BIT(IOP_MASK(4) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') // 6,4: D - PORT_BIT(IOP_MASK(5) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') // 6,5: E - PORT_BIT(IOP_MASK(6) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') // 6,6: F - PORT_BIT(IOP_MASK(7) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') // 6,7: G - PORT_BIT(IOP_MASK(8) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') // 6,8: H - PORT_BIT(IOP_MASK(9) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') // 6,9: I - PORT_BIT(IOP_MASK(10) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') // 6,10: J - PORT_BIT(IOP_MASK(11) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') // 6,11: K - PORT_BIT(IOP_MASK(12) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') // 6,12: L - PORT_BIT(IOP_MASK(13) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') // 6,13: M - PORT_BIT(IOP_MASK(14) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') // 6,14: N - PORT_BIT(IOP_MASK(15) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') // 6,15: O - PORT_BIT(IOP_MASK(16) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') // 7,0: P - PORT_BIT(IOP_MASK(17) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') // 7,1: Q - PORT_BIT(IOP_MASK(18) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') // 7,2: R - PORT_BIT(IOP_MASK(19) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') // 7,3: S - PORT_BIT(IOP_MASK(20) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') // 7,4: T - PORT_BIT(IOP_MASK(21) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') // 7,5: U - PORT_BIT(IOP_MASK(22) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') // 7,6: V - PORT_BIT(IOP_MASK(23) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') // 7,7: W - PORT_BIT(IOP_MASK(24) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') // 7,8: X - PORT_BIT(IOP_MASK(25) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') // 7,9: Y - PORT_BIT(IOP_MASK(26) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') // 7,10: Z - PORT_BIT(IOP_MASK(27) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME(u8"π |") // 7,11: Pi - PORT_BIT(IOP_MASK(28) , IP_ACTIVE_HIGH , IPT_UNUSED) // 7,12: N/U - PORT_BIT(IOP_MASK(29) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_END) PORT_NAME(u8"\u2192") // 7,13: Gazinta (→) - PORT_BIT(IOP_MASK(30) , IP_ACTIVE_HIGH , IPT_UNUSED) // 7,14: N/U - PORT_BIT(IOP_MASK(31) , IP_ACTIVE_HIGH , IPT_UNUSED) // 7,15: N/U - - PORT_START("KEY_SHIFT") - PORT_BIT(IOP_MASK(0) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1) // Shift -INPUT_PORTS_END - -// +---------------+ -// | hp9825b_state | -// +---------------+ -class hp9825b_state : public hp9825_state -{ -public: - hp9825b_state(const machine_config &mconfig, device_type type, const char *tag) - : hp9825_state(mconfig , type , tag) - { - } - - void hp9825b(machine_config &config); - -protected: - virtual void device_reset() override; - -private: - void cpu_mem_map(address_map &map); -}; - -void hp9825b_state::hp9825b(machine_config &config) -{ - hp9825_base(config); - m_cpu->set_addrmap(AS_PROGRAM , &hp9825b_state::cpu_mem_map); - - for (auto& finder : m_rom_drawers) { - finder->set_rom_limit(0x5000); - } - - SOFTWARE_LIST(config, "optrom_list").set_original("hp9825b_rom"); -} - -void hp9825b_state::device_reset() -{ - hp9825_state::device_reset(); - - auto space = &m_cpu->space(AS_PROGRAM); - - for (auto& finder : m_rom_drawers) { - finder->install_rw_handlers(space , nullptr); - } -} - -void hp9825b_state::cpu_mem_map(address_map &map) -{ - map.unmap_value_low(); - map(0x0000 , 0x2fff).rom(); - map(0x3400 , 0x3bff).rom(); - map(0x4000 , 0x4fff).rom(); - map(0x5000 , 0x7fff).ram(); -} - -// +---------------+ -// | hp9825t_state | -// +---------------+ -class hp9825t_state : public hp9825_state, - public device_memory_interface -{ -public: - hp9825t_state(const machine_config &mconfig, device_type type, const char *tag) - : hp9825_state(mconfig , type , tag) - , device_memory_interface(mconfig , *this) - , m_skoalrom(*this , "skoalrom") - , m_ram_space_config("ram" , ENDIANNESS_BIG , 16 , 15 , -1) - , m_rom_space_config("rom" , ENDIANNESS_BIG , 16 , 15 , -1) - { - } - - void hp9825t(machine_config &config); - -protected: - virtual void machine_start() override; - virtual void device_reset() override; - - // device_memory_interface overrides - virtual space_config_vector memory_space_config() const override; - -private: - required_memory_region m_skoalrom; - address_space_config m_ram_space_config; - address_space *m_ram_space; - address_space_config m_rom_space_config; - address_space *m_rom_space; - - uint8_t m_cycle_type; - - // SKOAL state - bool m_skoalbit; // U53 - bool m_second_access; // U57-3 - bool m_mref; // U57-4 - bool m_ifetch_4400; // U57-5 - uint8_t m_special_opt; // U42 - uint16_t m_fetch_addr; - - void cpu_mem_map(address_map &map); - void ram_mem_map(address_map &map); - void rom_mem_map(address_map &map); - uint16_t cpu_mem_r(offs_t offset, uint16_t mem_mask = ~0); - void cpu_mem_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - void stm(uint8_t cycle_type); - void on_cycle_end(); - void opcode_fetch(uint16_t opcode); - uint8_t get_skoalrom(uint16_t addr); - bool is_rom(uint16_t addr , uint8_t cycle_type) const; -}; - -void hp9825t_state::hp9825t(machine_config &config) -{ - hp9825_base(config); - m_cpu->set_addrmap(AS_PROGRAM , &hp9825t_state::cpu_mem_map); - m_cpu->stm_cb().set(FUNC(hp9825t_state::stm)); - m_cpu->opcode_cb().set(FUNC(hp9825t_state::opcode_fetch)); - set_addrmap(0 , &hp9825t_state::ram_mem_map); - set_addrmap(1 , &hp9825t_state::rom_mem_map); - - for (auto& finder : m_rom_drawers) { - finder->set_rom_limit(0x6000); - } - - SOFTWARE_LIST(config, "optrom_list").set_original("hp9825b_rom"); -} - -void hp9825t_state::machine_start() -{ - hp9825_state::machine_start(); - - m_ram_space = &space(0); - m_rom_space = &space(1); -} - -void hp9825t_state::device_reset() -{ - hp9825_state::device_reset(); - - for (auto& finder : m_rom_drawers) { - finder->install_rw_handlers(m_rom_space , m_ram_space); - } - - // This has to be done before CPU reset or first instruction won't be fetched correctly - m_cycle_type = 0; - m_special_opt = 0xf; -} - -device_memory_interface::space_config_vector hp9825t_state::memory_space_config() const -{ - return space_config_vector { - std::make_pair(0 , &m_ram_space_config), - std::make_pair(1 , &m_rom_space_config) - }; -} - -void hp9825t_state::cpu_mem_map(address_map &map) -{ - map.unmap_value_low(); - map(0x0000 , 0x7fff).rw(FUNC(hp9825t_state::cpu_mem_r) , FUNC(hp9825t_state::cpu_mem_w)); -} - -void hp9825t_state::ram_mem_map(address_map &map) -{ - // 32 kw of RAM covering the whole address space (1st kw not accessible) - map(0x0000 , 0x7fff).ram(); -} - -void hp9825t_state::rom_mem_map(address_map &map) -{ - map.unmap_value_low(); - map(0x0000 , 0x2fff).rom().region(":rom" , 0); - map(0x3400 , 0x3bff).rom().region(":rom" , 0x6800); - map(0x4000 , 0x53ff).rom().region(":rom" , 0x8000); -} - -uint16_t hp9825t_state::cpu_mem_r(offs_t offset, uint16_t mem_mask) -{ - bool from_rom; - - if (m_cycle_type & hp_hybrid_cpu_device::CYCLE_RD_MASK) { - if (m_cycle_type & hp_hybrid_cpu_device::CYCLE_IFETCH_MASK) { - m_fetch_addr = offset; - } - from_rom = is_rom(offset , m_cycle_type); - LOG("rd @%04x CYC=%x %d%d%d%d ROM=%d\n" , offset , m_cycle_type , m_skoalbit , m_second_access , m_mref , m_ifetch_4400 , from_rom); - if (!(m_cycle_type & (hp_hybrid_cpu_device::CYCLE_IFETCH_MASK | hp_hybrid_cpu_device::CYCLE_DMA_MASK))) { - on_cycle_end(); - } - m_cycle_type = 0; - // TODO: diagnostic read - } else { - // Read coming from debugger and not from CPU: fake an ifetch - from_rom = is_rom(offset , hp_hybrid_cpu_device::CYCLE_IFETCH_MASK); - } - - return from_rom ? m_rom_space->read_word(offset , mem_mask) : m_ram_space->read_word(offset , mem_mask); -} - -void hp9825t_state::cpu_mem_w(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - if (m_cycle_type & hp_hybrid_cpu_device::CYCLE_WR_MASK) { - if (!(m_cycle_type & hp_hybrid_cpu_device::CYCLE_DMA_MASK)) { - on_cycle_end(); - } - m_cycle_type = 0; - } - // All write cycles go to RAM - m_ram_space->write_word(offset , data , mem_mask); -} - -void hp9825t_state::stm(uint8_t cycle_type) -{ - LOG("stm %x\n" , cycle_type); - m_cycle_type = cycle_type; - if (m_cycle_type & hp_hybrid_cpu_device::CYCLE_IFETCH_MASK) { - m_second_access = false; - m_mref = false; - m_ifetch_4400 = false; - // In case of ifetch from register area this is kept at 0 (because cpu_mem_r is not called) - // In case of ifetch from RAM/ROM this is set by cpu_mem_r to the fetch address - m_fetch_addr = 0; - } else if (m_cycle_type & hp_hybrid_cpu_device::CYCLE_RAL_MASK) { - if (!(m_cycle_type & hp_hybrid_cpu_device::CYCLE_DMA_MASK)) { - on_cycle_end(); - } - m_cycle_type = 0; - } -} - -void hp9825t_state::on_cycle_end() -{ - m_second_access = false; -} - -void hp9825t_state::opcode_fetch(uint16_t opcode) -{ - LOG("oc %04x\n" , opcode); - m_cycle_type = 0; - // memory referencing instructions - m_mref = (opcode & 0x7000) != 0x7000; - m_second_access = true; - m_ifetch_4400 = (m_fetch_addr & 0x7f00) == 0x0900; - if (BIT(m_special_opt , 3) && BIT(m_special_opt , 2)) { - // Set SKOAL bit - if (m_fetch_addr < 0x20) { - // Fetch from registers -> SKOAL bit = 0 - m_skoalbit = false; - } else if ((m_fetch_addr & 0x6000) == 0x6000) { - // Fetch in [6000..7fff] range -> SKOAL bit = 0 - m_skoalbit = false; - } else { - uint8_t tmp = get_skoalrom(m_fetch_addr); - m_skoalbit = (tmp >> ((~m_fetch_addr >> 12) & 7)) & 1; - } - } - // Decode SKOAL instructions. They are ignored by the hybrid processor - // as they are not recognized. - if ((opcode & 0xffc0) == 0x7040) { - m_special_opt = opcode & 0xf; - if (!BIT(m_special_opt , 3)) { - // RAM/ == 0 - m_skoalbit = false; - } else if (!BIT(m_special_opt , 2)) { - // ROM/ == 0 - m_skoalbit = true; - } - } -} - -uint8_t hp9825t_state::get_skoalrom(uint16_t addr) -{ - return m_skoalrom->as_u8(~addr & 0x0fff); -} - -bool hp9825t_state::is_rom(uint16_t addr , uint8_t cycle_type) const -{ - if ((addr & 0x6000) == 0x6000) { - // [6000..7fff] -> always RAM - return false; - } else if ((cycle_type & hp_hybrid_cpu_device::CYCLE_DMA_MASK) != 0 || - !BIT(m_special_opt , 1)) { - // DMA cycle or BIT/ == 0 -> RAM - return false; - } else if (addr >= 0x400 && !BIT(m_special_opt , 0)) { - // [0400..5fff] and BIN/ == 0 -> RAM - return false; - } else { - bool addr_0800_7fff = (addr & 0x7800) != 0; - bool addr_0400_07ff = !addr_0800_7fff && BIT(addr , 10); - bool addr_0000_03ff = !addr_0800_7fff && !BIT(addr , 10); - - // U58-6 - bool force_rom; - - // ROM when one or more of these is true: - // - addr in [0000..03ff] - // - Ifetch cycle and addr in [0800..5fff] - // - 2nd access of a memory-referencing instruction not in [0400..07ff] range - // - skoalbit = 1 and instruction fetched in [0900..09ff] range - force_rom = - addr_0000_03ff || - ((cycle_type & hp_hybrid_cpu_device::CYCLE_IFETCH_MASK) != 0 && addr_0800_7fff) || - (m_second_access && m_mref && (!BIT(m_special_opt , 2) || !addr_0400_07ff)) || - (m_skoalbit && m_ifetch_4400); - - if (force_rom) { - return true; - } else if (addr_0400_07ff && BIT(m_special_opt , 2)) { - return false; - } else { - return m_skoalbit; - } - } -} - -ROM_START(hp9825b) - ROM_REGION(0xa000 , "cpu" , ROMREGION_16BIT | ROMREGION_BE) - ROM_LOAD("sysrom1.bin" , 0x0000 , 0x2000 , CRC(fe429268) SHA1(f2fe7c5abca92bd13f81b4385fc4fce0cafb0da0)) - ROM_LOAD("sysrom2.bin" , 0x2000 , 0x2000 , CRC(96093b5d) SHA1(c6ec4cafd019887df0fa849b3c7070bb74faee54)) - ROM_LOAD("sysrom3.bin" , 0x4000 , 0x2000 , CRC(f9470f67) SHA1(b80cb4a366d93bd7acc3508ce987bb11c5986b2a)) - ROM_LOAD("genio_t.bin" , 0x6800 , 0x0800 , CRC(ade1d1ed) SHA1(9af74a65b29ef1885f74164238ecf8d16ac995d6)) - ROM_LOAD("plot72.bin" , 0x7000 , 0x0800 , CRC(0a9cb8db) SHA1(d0d126fca108f2715e1e408cb31b09ba69385ac4)) - ROM_LOAD("advpgm_t.bin", 0x8000 , 0x0800 , CRC(965b5e5a) SHA1(ff44dd15f8fa4ca03dfd970ed8b200e8a071ec13)) - ROM_LOAD("extio_t.bin" , 0x8800 , 0x1000 , CRC(a708b978) SHA1(baf53c8a2b24d059f95252baf1452188eaf6e4be)) - ROM_LOAD("strings_t.bin",0x9800 , 0x0800 , CRC(b5ca5da5) SHA1(af13abb3c15836c566863c656e1659f7e6f96d04)) -ROM_END - -ROM_START(hp9825t) - ROM_REGION(0xa800 , ":rom" , ROMREGION_16BIT | ROMREGION_BE | ROMREGION_ERASE | ROMREGION_ERASE00) - ROM_LOAD("sysrom1.bin" , 0x0000 , 0x2000 , CRC(fe429268) SHA1(f2fe7c5abca92bd13f81b4385fc4fce0cafb0da0)) - ROM_LOAD("sysrom2.bin" , 0x2000 , 0x2000 , CRC(96093b5d) SHA1(c6ec4cafd019887df0fa849b3c7070bb74faee54)) - ROM_LOAD("sysrom3.bin" , 0x4000 , 0x2000 , CRC(f9470f67) SHA1(b80cb4a366d93bd7acc3508ce987bb11c5986b2a)) - ROM_LOAD("genio_t.bin" , 0x6800 , 0x0800 , CRC(ade1d1ed) SHA1(9af74a65b29ef1885f74164238ecf8d16ac995d6)) - ROM_LOAD("plot72.bin" , 0x7000 , 0x0800 , CRC(0a9cb8db) SHA1(d0d126fca108f2715e1e408cb31b09ba69385ac4)) - ROM_LOAD("advpgm_t.bin", 0x8000 , 0x0800 , CRC(965b5e5a) SHA1(ff44dd15f8fa4ca03dfd970ed8b200e8a071ec13)) - ROM_LOAD("extio_t.bin" , 0x8800 , 0x1000 , CRC(a708b978) SHA1(baf53c8a2b24d059f95252baf1452188eaf6e4be)) - ROM_LOAD("strings_t.bin",0x9800 , 0x0800 , CRC(b5ca5da5) SHA1(af13abb3c15836c566863c656e1659f7e6f96d04)) - ROM_LOAD("syspgm.bin" , 0xa000 , 0x0800 , CRC(8915588f) SHA1(037f497b5ecc3216fb6b8356767cc361fb0b2945)) - - ROM_REGION(0x1000 , "skoalrom" , 0) - ROM_LOAD("skoalrom.bin" , 0 , 0x1000 , CRC(5e8124d5) SHA1(dedf7f8a10c62b444f04213956083089e97bf219)) -ROM_END - -// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS -COMP(1980, hp9825b, 0, 0, hp9825b, hp9825, hp9825b_state,empty_init, "Hewlett-Packard", "HP 9825B", 0) -COMP(1980, hp9825t, 0, 0, hp9825t, hp9825, hp9825t_state,empty_init, "Hewlett-Packard", "HP 9825T", 0) |