From 24d016f62c5dd9583e2238c0227027b5aebbc27a Mon Sep 17 00:00:00 2001 From: Sergey Svishchev Date: Thu, 18 May 2017 03:01:53 +0300 Subject: [PATCH] New skeleton: GRiD Compass series --- scripts/src/machine.lua | 12 + scripts/target/mame/mess.lua | 9 + src/devices/machine/i7220.cpp | 710 ++++++++++++++++++++++++++++++++++ src/devices/machine/i7220.h | 240 ++++++++++++ src/emu/drivers/xtal.h | 1 + src/mame/drivers/gridcomp.cpp | 586 ++++++++++++++++++++++++++++ src/mame/machine/gridkeyb.cpp | 321 +++++++++++++++ src/mame/machine/gridkeyb.h | 89 +++++ src/mame/mame.lst | 8 + src/mame/mess.flt | 1 + 10 files changed, 1977 insertions(+) create mode 100644 src/devices/machine/i7220.cpp create mode 100644 src/devices/machine/i7220.h create mode 100644 src/mame/drivers/gridcomp.cpp create mode 100644 src/mame/machine/gridkeyb.cpp create mode 100644 src/mame/machine/gridkeyb.h diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua index 93a51243c1b..d24828492e2 100644 --- a/scripts/src/machine.lua +++ b/scripts/src/machine.lua @@ -1024,6 +1024,18 @@ if (MACHINES["I2CMEM"]~=null) then } end +--------------------------------------------------- +-- +--@src/devices/machine/i7220.h,MACHINES["I7220"] = true +--------------------------------------------------- + +if (MACHINES["I7220"]~=null) then + files { + MAME_DIR .. "src/devices/machine/i7220.cpp", + MAME_DIR .. "src/devices/machine/i7220.h", + } +end + --------------------------------------------------- -- --@src/devices/machine/i8155.h,MACHINES["I8155"] = true diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index 423e8927be5..8524bd9c5ca 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -415,6 +415,7 @@ MACHINES["HD63450"] = true MACHINES["HD64610"] = true MACHINES["HP_TACO"] = true MACHINES["I2CMEM"] = true +MACHINES["I7220"] = true MACHINES["I80130"] = true MACHINES["I8089"] = true MACHINES["I8155"] = true @@ -955,6 +956,7 @@ function linkProjects_mame_mess(_target, _subtarget) "galaxy", "gamepark", "gi", + "gridcomp", "grundy", "hartung", "heathkit", @@ -1998,6 +2000,13 @@ files { MAME_DIR .. "src/mame/drivers/hh_pic16.cpp", } +createMESSProjects(_target, _subtarget, "gridcomp") +files { + MAME_DIR .. "src/mame/drivers/gridcomp.cpp", + MAME_DIR .. "src/mame/machine/gridkeyb.cpp", + MAME_DIR .. "src/mame/machine/gridkeyb.h", +} + createMESSProjects(_target, _subtarget, "grundy") files { MAME_DIR .. "src/mame/drivers/newbrain.cpp", diff --git a/src/devices/machine/i7220.cpp b/src/devices/machine/i7220.cpp new file mode 100644 index 00000000000..eaf88b96e32 --- /dev/null +++ b/src/devices/machine/i7220.cpp @@ -0,0 +1,710 @@ +// license:BSD-3-Clause +// copyright-holders:Sergey Svishchev +/********************************************************************** + + Intel 7220 Bubble Memory Controller emulation + + References: + - http://www.decadecounter.com/vta/pdf/BPK72UM.pdf + - http://www.decadecounter.com/vta/pdf/7220-1.pdf + - http://www.decadecounter.com/vta/pdf/7242.pdf + - http://www.decadecounter.com/vta/articleview.php?item=359 + + Implemented at least partially + - commands + Read Bubble Data, Write Bubble Data + Initialize, Reset FIFO, Abort, Software Reset + Read FSA Status, MBM Purge + + Not implemented + - interrupts + - DMA + - commands + Read Seek, Write Seek, Read Corrected Data, all Bootloop-related + - access to other than 2 FSA channels at once + +**********************************************************************/ + +#include "emu.h" +#include "i7220.h" + + +#define VERBOSE_DBG 2 /* general debug messages */ + +#define DBG_LOG(N,M,A) \ + do { \ + if(VERBOSE_DBG>=N) \ + { \ + if( M ) \ + logerror("%11.6f at %s: %-10s",machine().time().as_double(),machine().describe_context(),(char*)M ); \ + logerror A; \ + } \ + } while (0) + + +// device type definition +DEFINE_DEVICE_TYPE(I7220, i7220_device, "i7220", "Intel 7220 BMC") + + + +//************************************************************************** +// HELPERS +//************************************************************************** + + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// i7220_device - constructor +//------------------------------------------------- + +i7220_device::i7220_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, I7220, tag, owner, clock) + , device_image_interface(mconfig, *this) + , intrq_cb(*this) + , drq_cb(*this) +{ +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void i7220_device::device_start() +{ + // resolve callbacks + intrq_cb.resolve_safe(); + drq_cb.resolve_safe(); + + bi.tm = timer_alloc(0); + + // register for state saving + save_item(NAME(m_regs)); + save_item(NAME(m_rac)); + save_item(NAME(m_cmdr)); + save_item(NAME(m_str)); + save_item(NAME(m_blr)); + save_item(NAME(m_ar)); +} + +//------------------------------------------------- +// device_reset - device-specific startup +//------------------------------------------------- + +void i7220_device::device_reset() +{ + main_phase = PHASE_IDLE; + bi.main_state = IDLE; + bi.sub_state = IDLE; + + set_drq(false); + set_irq(false); + fifo_clear(); + + m_rac = m_cmdr = m_str = m_blr = m_ar = 0; + memset(&m_regs, 0, sizeof(m_regs)); +} + +void i7220_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + general_continue(bi); +} + +image_init_result i7220_device::call_load() +{ + if (length() != (m_data_size * I7110_MBM_SIZE)) + { + return image_init_result::FAIL; + } + return image_init_result::PASS; +} + + +void i7220_device::set_drq(bool state) +{ + if (state != drq) + { + drq = state; + drq_cb(drq); + } +} + +void i7220_device::set_irq(bool state) +{ + if (state != irq) + { + irq = state; + intrq_cb(irq); + } +} + +void i7220_device::update_drq() +{ + switch (bi.main_state) + { + case READ_DATA: + set_drq(m_fifo_size < 22 ? false : true); + break; + + case WRITE_DATA: + set_drq(m_fifo_size < (40 - 22) ? true : false); + break; + } +} + + +void i7220_device::fifo_clear() +{ + m_fifo.clear(); + m_fifo_size = 0; + set_drq(false); +} + +uint8_t i7220_device::fifo_pop() +{ + uint8_t val; + + if (m_fifo.empty()) + { + return m_fifo.dequeue(); + } + else + { + val = m_fifo.dequeue(); + m_fifo_size--; + if (main_phase == PHASE_EXEC) + { + update_drq(); + } + return val; + } +} + +void i7220_device::fifo_push(uint8_t val) +{ + if (m_fifo.full()) + { + return; + } + else + { + m_fifo.enqueue(val); + m_fifo_size++; + if (main_phase == PHASE_EXEC) + { + update_drq(); + } + } +} + +void i7220_device::update_regs() +{ + m_blr = (m_regs[R_BLR_M] << 8) + m_regs[R_BLR_L]; + m_ar = (m_regs[R_AR_M] << 8) + m_regs[R_AR_L]; + blr_count = m_blr & 0x7ff; + blr_nfc = (m_blr >> 12) ? ((m_blr >> 12) << 1) : 1; + ar_addr = m_ar & 0x7ff; + ar_mbm = (m_ar >> 11) & 15; +} + + +void i7220_device::start_command(int cmd) +{ + main_phase = PHASE_EXEC; + m_str &= ~SR_CLEAR; + + switch (cmd) + { + // determines how many FSAs are present, reads and decodes bootloop from each MBM and stores result in FSA bootloop regs. + // all parametric registers must be properly set up before issuing Initialize command. + // NFC bits in BLR MSB must be set to 0001 before issuing this command. + // MBM GROUP SELECT bits in the AR must select the last MBM in the system. + case C_INIT: + DBG_LOG(1, "BMC", ("INIT: BLR %04x (NFC %d pages %d) AR %04x (MBM %d addr %03x) ER %02d\n", + m_blr, blr_nfc, blr_count, m_ar, ar_mbm, ar_addr, m_regs[R_ER])); + if (blr_nfc != 2) + { + command_fail_start(bi); + } + else + { + init_start(bi); + } + break; + + case C_READ_FSA_STATUS: + read_fsa_start(bi); + break; + + // all parametric registers must be properly set up before issuing Read Bubble Data command + case C_READ: + DBG_LOG(1, "BMC", ("RBD: BLR %04x (NFC %d pages %d) AR %04x (MBM %d addr %03x) ER %02d\n", + m_blr, blr_nfc, blr_count, m_ar, ar_mbm, ar_addr, m_regs[R_ER])); + if (ar_mbm >= m_data_size || blr_nfc != 2) + { + command_fail_start(bi); + } + else + { + read_data_start(bi); + } + break; + + case C_WRITE: + DBG_LOG(1, "BMC", ("WBD: BLR %04x (NFC %d pages %d) AR %04x (MBM %d addr %03x) ER %02d\n", + m_blr, blr_nfc, blr_count, m_ar, ar_mbm, ar_addr, m_regs[R_ER])); + if (ar_mbm >= m_data_size || blr_nfc != 2) + { + command_fail_start(bi); + } + else + { + write_data_start(bi); + } + break; + + // XXX clears all BMC registers (except BLR &c), counters and the MBM address RAM. used by Initialize as subroutine. + case C_MBM_PURGE: + m_regs[R_AR_L] = 0; + m_regs[R_AR_M] &= ~7; + update_regs(); + main_phase = PHASE_RESULT; + m_str |= SR_DONE; + break; + + // controlled termination of currently executing command. command accepted in BUSY state. + // if not BUSY, clears FIFO. + case C_ABORT: + if (main_phase == PHASE_IDLE) + { + fifo_clear(); + } + else + { + main_phase = PHASE_RESULT; + bi.main_state = bi.sub_state = IDLE; + } + m_str |= SR_DONE; + break; + + case C_RESET_FIFO: + fifo_clear(); + main_phase = PHASE_RESULT; + m_str |= SR_DONE; + break; + + // clears BMC FIFO and all registers except those containing init parameters. sends Reset to every FSA. + case C_RESET: + m_regs[R_UR] = 0; + fifo_clear(); + main_phase = PHASE_RESULT; + m_str |= SR_DONE; + break; + + default: + command_fail_start(bi); + break; + } +} + +void i7220_device::general_continue(bubble_info &bi) +{ + switch (bi.main_state) + { + case IDLE: + break; + + case INIT: + init_continue(bi); + break; + + case FAIL: + command_fail_continue(bi); + break; + + case READ_FSA: + read_fsa_continue(bi); + break; + + case READ_DATA: + read_data_continue(bi); + break; + + case WRITE_DATA: + write_data_continue(bi); + break; + + default: + DBG_LOG(1,"BMC",("general_continue on unknown main-state %d\n", bi.main_state)); + break; + } +} + +void i7220_device::delay_cycles(emu_timer *tm, int cycles) +{ + tm->adjust(attotime::from_double(double(cycles) / clock())); +} + +void i7220_device::command_end(bubble_info &bi, bool success) +{ + logerror("command done (%s) - %02x\n", success ? "success" : "fail", m_str); + main_phase = PHASE_RESULT; + bi.main_state = bi.sub_state = IDLE; + if (success) + { + m_str |= SR_DONE; + } + else + { + m_str |= SR_FAIL | SR_TE; + } +} + + +void i7220_device::command_fail_start(bubble_info &bi) +{ + bi.main_state = FAIL; + bi.sub_state = INITIALIZE; + + command_fail_continue(bi); +} + +void i7220_device::command_fail_continue(bubble_info &bi) +{ + for (;;) + { + switch (bi.sub_state) + { + case INITIALIZE: + bi.sub_state = COMMAND_DONE; + delay_cycles(bi.tm, 1200); // XXX + return; + + case COMMAND_DONE: + command_end(bi, false); + return; + + default: + DBG_LOG(1,"BMC",("fail unknown sub-state %d\n", bi.sub_state)); + return; + } + } +} + +void i7220_device::init_start(bubble_info &bi) +{ + bi.main_state = INIT; + bi.sub_state = INITIALIZE; + + init_continue(bi); +} + +void i7220_device::init_continue(bubble_info &bi) +{ + for (;;) + { + switch (bi.sub_state) + { + case INITIALIZE: + bi.sub_state = WAIT_FSA_REPLY; + delay_cycles(bi.tm, m_data_size * 60); // p. 4-16 of BPK72UM + return; + + case WAIT_FSA_REPLY: + bi.sub_state = COMMAND_DONE; + break; + + case COMMAND_DONE: + command_end(bi, true); + return; + + default: + DBG_LOG(1,"BMC",("init unknown sub-state %d\n", bi.sub_state)); + return; + } + } +} + +void i7220_device::read_fsa_start(bubble_info &bi) +{ + bi.main_state = READ_FSA; + bi.sub_state = INITIALIZE; + + read_fsa_continue(bi); +} + +void i7220_device::read_fsa_continue(bubble_info &bi) +{ + for (;;) + { + switch (bi.sub_state) + { + case INITIALIZE: + bi.sub_state = WAIT_FSA_REPLY; + delay_cycles(bi.tm, m_data_size * 60); // p. 4-16 of BPK72UM + return; + + case WAIT_FSA_REPLY: + bi.sub_state = COMMAND_DONE; + break; + + case COMMAND_DONE: + // each bubble memory module has two FSA channels + for (int a = 0; a < m_data_size; a++) + { + fifo_push(0x28); // FIFOMT | ECF/F + fifo_push(0x28); + } + command_end(bi, true); + return; + + default: + DBG_LOG(1,"BMC",("read fsa unknown sub-state %d\n", bi.sub_state)); + return; + } + } +} + +void i7220_device::read_data_start(bubble_info &bi) +{ + bi.main_state = READ_DATA; + bi.sub_state = INITIALIZE; + + read_data_continue(bi); +} + +void i7220_device::read_data_continue(bubble_info &bi) +{ + for (;;) + { + switch (bi.sub_state) + { + case INITIALIZE: + bi.sub_state = SECTOR_READ; + bi.counter = 0; // 256-bit pages + bi.limit = blr_count * blr_nfc; + fseek((ar_addr * 32 * blr_nfc) + (ar_mbm * I7110_MBM_SIZE) + (bi.counter * 32), SEEK_SET); + break; + + case SECTOR_READ: + fread(buf, 32); + bi.sub_state = WAIT_FSA_REPLY; + delay_cycles(bi.tm, 270 * 20); // p. 4-14 of BPK72UM + break; + + case WAIT_FSA_REPLY: + DBG_LOG(3,"BMC",("read data: ct %02d limit %02d\n", bi.counter, bi.limit)); + if (bi.counter < bi.limit) + { + for (int a = 0; a < 32; a++) + fifo_push(buf[a]); + bi.sub_state = SECTOR_READ; + bi.counter++; + delay_cycles(bi.tm, 270 * 20); // p. 4-14 of BPK72UM + return; + } + bi.sub_state = COMMAND_DONE; + break; + + case COMMAND_DONE: + command_end(bi, true); + return; + + default: + DBG_LOG(1,"BMC",("read data unknown sub-state %d\n", bi.sub_state)); + return; + } + } +} + +void i7220_device::write_data_start(bubble_info &bi) +{ + bi.main_state = WRITE_DATA; + bi.sub_state = INITIALIZE; + + write_data_continue(bi); +} + +void i7220_device::write_data_continue(bubble_info &bi) +{ + for (;;) + { + switch (bi.sub_state) + { + case INITIALIZE: + bi.sub_state = WAIT_FIFO; + bi.counter = 0; + bi.limit = blr_count * blr_nfc * 32; + delay_cycles(bi.tm, 270 * 20); // p. 4-14 of BPK72UM + return; + + case WAIT_FIFO: + DBG_LOG(3,"BMC",("write data: fifo %02d ct %02d limit %02d\n", m_fifo_size, bi.counter, bi.limit)); + if (m_fifo_size >= 32) + { + for (int a = 0; a < 32; a++) + buf[a] = fifo_pop(); + fseek((ar_addr * 32 * blr_nfc) + (ar_mbm * I7110_MBM_SIZE) + bi.counter, SEEK_SET); + fwrite(buf, 32); + bi.counter += 32; + } + if (bi.counter < bi.limit) + { + delay_cycles(bi.tm, 270 * 20); // p. 4-14 of BPK72UM + return; + } + bi.sub_state = COMMAND_DONE; + break; + + case COMMAND_DONE: + command_end(bi, true); + return; + + default: + DBG_LOG(1,"BMC",("write data unknown sub-state %d\n", bi.sub_state)); + return; + } + } +} + + +//------------------------------------------------- +// read - +//------------------------------------------------- + +READ8_MEMBER(i7220_device::read) +{ + uint8_t data = 0; + + switch (offset & 1) + { + case 0: + if (m_rac) + { + data = m_regs[m_rac]; + DBG_LOG(2, "BMC", ("R reg @ %02x == %02x\n", m_rac, data)); + m_rac++; + m_rac &= 15; + } + else + { + data = fifo_pop(); + DBG_LOG(2, "BMC", ("R fifo == %02x\n", data)); + } + break; + + case 1: + data = m_str; + if (main_phase == PHASE_EXEC) + { + data |= SR_BUSY; + switch (bi.main_state) + { + case READ_DATA: + if (!m_fifo.empty()) // XXX + { + data |= SR_FIFO; + } + break; + + case WRITE_DATA: + if (!m_fifo.full()) // XXX + { + data |= SR_FIFO; + } + break; + } + } + else + { + if (!m_fifo.empty()) + { + data |= SR_FIFO; + } + } + DBG_LOG(2, "BMC", ("R status == %02x (phase %d state %d:%d fifo %d drq %d)\n", + data, main_phase, bi.main_state, bi.sub_state, m_fifo_size, drq)); + if (main_phase == PHASE_RESULT) + { + main_phase = PHASE_IDLE; + } + break; + } + + DBG_LOG(3, "BMC", ("R @ %d == %02x\n", offset, data)); + + return data; +} + +//------------------------------------------------- +// write - +//------------------------------------------------- + +WRITE8_MEMBER( i7220_device::write ) +{ + static const char *commands[] = { + "Write Bootloop Register Masked", + "Initialize", + "Read Bubble Data", + "Write Bubble Data", + "Read Seek", + "Read Bootloop Register", + "Write Bootloop Register", + "Write Bootloop", + "Read FSA Status", + "Abort", + "Write Seek", + "Read Bootloop", + "Read Corrected Data", + "Reset FIFO", + "MBM Purge", + "Software Reset" + }; + + DBG_LOG(3, "BMC", ("W @ %d <- %02x\n", offset, data)); + + switch (offset & 1) + { + case 0: + if (m_rac) + { + DBG_LOG(2, "BMC", ("W reg @ %02x <- %02x\n", m_rac, data)); + m_regs[m_rac] = data; + update_regs(); + m_rac++; + m_rac &= 15; + } + else + { + DBG_LOG(2, "BMC", ("W fifo <- %02x\n", data)); + fifo_push(data); + } + break; + + case 1: + if (BIT(data, 5)) + { + intrq_cb(CLEAR_LINE); + } + else if (BIT(data, 4)) + { + m_cmdr = data & 15; + if (main_phase == PHASE_IDLE) + { + DBG_LOG(1, "BMC", ("command %02x '%s'\n", data, commands[m_cmdr])); + main_phase = PHASE_CMD; + start_command(m_cmdr); + } + } + else + { + m_rac = data & 15; + } + break; + } + return; +} diff --git a/src/devices/machine/i7220.h b/src/devices/machine/i7220.h new file mode 100644 index 00000000000..d681695a455 --- /dev/null +++ b/src/devices/machine/i7220.h @@ -0,0 +1,240 @@ +// license:BSD-3-Clause +// copyright-holders:Sergey Svishchev +/********************************************************************** + + Intel 7220 Bubble Memory Controller emulation + +********************************************************************** + _____ _____ + /PWR.FAIL 1 |* \_/ | 40 Vcc + /RESET.OUT 2 | | 39 /X+ + CLK 3 | | 38 /X- + /RESET 4 | | 37 /Y+ + /RD 5 | | 36 /Y- + /WR 6 | | 35 /TM.A + /DACK 7 | | 34 /TM.B + DRQ 8 | | 33 /REP.EN + INT 9 | | 32 /BOOT.EN + A0 10 | 7220 | 31 /SWAP.EN + D0 11 | | 30 /BOOT.S.EN + D1 12 | | 29 C/D + D2 13 | | 28 /DET.ON + D3 14 | | 27 /ERR.FLG + D4 15 | | 26 /WAIT + D5 16 | | 25 /BUS.RD + D6 17 | | 24 /SHIFT.CLK + D7 18 | | 23 /SYNC + D8 19 | | 22 DIO + GND 20 |_____________| 21 /CS + +**********************************************************************/ + +#ifndef MAME_MACHINE_I7220_H +#define MAME_MACHINE_I7220_H + +#pragma once + +#define I7110_MBM_SIZE (128 * 1024) // 1 megabit +#define I7115_MBM_SIZE (512 * 1024) // 4 megabit + + +///************************************************************************* +// INTERFACE CONFIGURATION MACROS +///************************************************************************* + +#define MCFG_I7220_IRQ_CALLBACK(_write) \ + devcb = &i7220_device::set_intrq_wr_callback(*device, DEVCB_##_write); + +#define MCFG_I7220_DRQ_CALLBACK(_write) \ + devcb = &i7220_device::set_drq_wr_callback(*device, DEVCB_##_write); + +#define MCFG_I7220_DATA_SIZE(data_size) \ + i7220_device::set_data_size(*device, data_size); + + + +///************************************************************************* +// TYPE DEFINITIONS +///************************************************************************* + +// ======================> i7220_device + +class i7220_device : public device_t, + public device_image_interface +{ +public: + // construction/destruction + i7220_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + template static devcb_base &set_intrq_wr_callback(device_t &device, Object &&cb) { return downcast(device).intrq_cb.set_callback(std::forward(cb)); } + template static devcb_base &set_drq_wr_callback(device_t &device, Object &&cb) { return downcast(device).drq_cb.set_callback(std::forward(cb)); } + + static void set_data_size(device_t &device, int data_size) { downcast(device).m_data_size = data_size; } + + // image-level overrides + virtual image_init_result call_load() override; + + virtual iodevice_t image_type() const override { return IO_MEMCARD; } + + virtual bool is_readable() const override { return 1; } + virtual bool is_writeable() const override { return 1; } + virtual bool is_creatable() const override { return 0; } + virtual bool must_be_loaded() const override { return 1; } + virtual bool is_reset_on_load() const override { return 0; } + virtual const char *file_extensions() const override { return "bubble"; } + + DECLARE_READ8_MEMBER(read); + DECLARE_WRITE8_MEMBER(write); + +protected: + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; + + int m_data_size; + +private: + enum { + PHASE_IDLE, PHASE_CMD, PHASE_EXEC, PHASE_RESULT + }; + + enum { + // General "doing nothing" state + IDLE, + + // Main states + INIT, + READ_FSA, + READ_DATA, + WRITE_DATA, + FAIL, + + // Sub-states + INITIALIZE, + + WAIT_FSA_REPLY, + WAIT_FSA_REPLY_DONE, + + WAIT_FIFO, + WAIT_FIFO_DONE, + + COMMAND_DONE, + + SECTOR_READ, + SECTOR_WRITTEN + }; + + enum { + C_WRITE_BOOTLOOP_REG_MASKED, + C_INIT, + C_READ, + C_WRITE, + C_READ_SEEK, + C_READ_BOOTLOOP_REG, + C_WRITE_BOOTLOOP_REG, + C_WRITE_BOOTLOOP, + C_READ_FSA_STATUS, + C_ABORT, + C_WRITE_SEEK, + C_READ_BOOTLOOP, + C_READ_CORRECTED, + C_RESET_FIFO, + C_MBM_PURGE, + C_RESET + }; + + enum { + R_UR = 0x0a, + R_BLR_L = 0x0b, + R_BLR_M = 0x0c, + R_ER = 0x0d, + R_AR_L = 0x0e, + R_AR_M = 0x0f, + }; + + enum { + ER_IEN = 0x01, + ER_IEE = 0x02, + ER_DMAEN = 0x04, + ER_MFBTR = 0x08, + ER_WBE = 0x10, + ER_ERCD = 0x20, + ER_EICD = 0x40, + ER_EPI = 0x80 + }; + + enum { + SR_FIFO = 0x01, + SR_PE = 0x02, + SR_UE = 0x04, + SR_CE = 0x08, + SR_TE = 0x10, + SR_FAIL = 0x20, + SR_DONE = 0x40, + SR_BUSY = 0x80, + + SR_CLEAR = 0x7E + }; + + struct bubble_info { + emu_timer *tm; + int main_state, sub_state; + int limit, counter; + }; + + void delay_cycles(emu_timer *tm, int cycles); + void set_drq(bool state); + void set_irq(bool state); + + void update_regs(); + void update_drq(); + + void start_command(int cmd); + void general_continue(bubble_info &bi); + void command_end(bubble_info &bi, bool success); + + void command_fail_start(bubble_info &bi); + void command_fail_continue(bubble_info &bi); + + void init_start(bubble_info &bi); + void init_continue(bubble_info &bi); + + void read_fsa_start(bubble_info &bi); + void read_fsa_continue(bubble_info &bi); + + void read_data_start(bubble_info &bi); + void read_data_continue(bubble_info &bi); + + void write_data_start(bubble_info &bi); + void write_data_continue(bubble_info &bi); + + void fifo_clear(); + void fifo_push(uint8_t val); + uint8_t fifo_pop(); + + int main_phase; + bool drq, irq; + bubble_info bi; + + uint8_t buf[32]; + int blr_count, blr_nfc, ar_addr, ar_mbm; + + devcb_write_line intrq_cb; + devcb_write_line drq_cb; + + uint8_t m_regs[16]; + uint8_t m_rac; + uint8_t m_cmdr; + uint8_t m_str; + uint16_t m_blr; + uint16_t m_ar; + int m_fifo_size; + util::fifo m_fifo; +}; + + +// device type definition +DECLARE_DEVICE_TYPE(I7220, i7220_device) + +#endif // MAME_MACHINE_I7220_H diff --git a/src/emu/drivers/xtal.h b/src/emu/drivers/xtal.h index fc524b5c2b7..4dbd21164a0 100644 --- a/src/emu/drivers/xtal.h +++ b/src/emu/drivers/xtal.h @@ -71,6 +71,7 @@ enum XTAL_3_6864MHz = 3686400, /* Baud rate clock for MC68681 and similar UARTs */ XTAL_4MHz = 4000000, XTAL_4_028MHz = 4028000, /* Sony SMC-777 */ + XTAL_4_032MHz = 4032000, /* GRiD Compass modem board */ XTAL_4_096MHz = 4096000, /* Used to drive OKI M9810 chips */ XTAL_4_194304Mhz = 4194304, /* Used to drive MC146818 / Nintendo Game Boy */ XTAL_4_224MHz = 4224000, /* Used to drive OKI M6295 chips, usually with /4 divider */ diff --git a/src/mame/drivers/gridcomp.cpp b/src/mame/drivers/gridcomp.cpp new file mode 100644 index 00000000000..f767bc9a3d8 --- /dev/null +++ b/src/mame/drivers/gridcomp.cpp @@ -0,0 +1,586 @@ +// license:BSD-3-Clause +// copyright-holders:Sergey Svishchev +/*************************************************************************** + + drivers/gridcomp.cpp + + Driver file for GRiD Compass series + + US patent 4,571,456 describes model 1101: + + - 15 MHz XTAL, produces + - 5 MHz system clock for CPU, FPU, OSP + - 7.5 MHz pixel clock + - Intel 8086 - CPU + - Intel 8087 - FPU + - Intel 80130 - Operating System Processor, equivalent of: + - 8259 PIC + - 8254 PIT + - Texas Instruments TMS9914 GPIB controller + - Intel 7220 Bubble Memory Controller + - 7110 Magnetic Bubble Memory modules and support chips + - (unknown) - EAROM for machine ID + - (unknown) - Real-Time Clock + - (custom DMA logic) + - Intel 8741 - keyboard MCU + - Intel 8274 - UART + - Intel 8255 - modem interface + - 2x DAC0832LCN - DAC + - MK5089N - DTMF generator + - ... + + to do: + + - confirm differences between models except screen size + - Compass 110x do not have GRiDROM slots. + - Compass II (112x, 113x) have 4 of them. + - keyboard: decode and add the rest of keycodes + - EAROM, RTC + - serial port, modem (incl. DTMF generator) + - TMS9914 chip driver (incl. DMA) + - GPIB storage devices (floppy, hard disk) + + missing dumps: + + - BIOS from models other than 1139 (CCOS and MS-DOS variants) + - GRiDROM's + - keyboard MCU + - external floppy and hard disk (2101, 2102) + + to boot CCOS 3.0.1: + - pad binary image (not .imd) to 384K + - attach it as -memcard + - use grid1129 with 'patched' ROM + - start with -debug and add breakpoints: + + # bubble memory driver + bp ff27a,1,{ax=ax*2;go} + # boot loader + bp 20618,1,{temp0=214A8;do w@(temp0+7)=120;do w@(temp0+9)=121;go} + # CCOS kernel + bp 0661a,1,{temp0=0f964;do w@(temp0+7)=120;do w@(temp0+9)=121;go} + +***************************************************************************/ + +#include "emu.h" + +#include "bus/rs232/rs232.h" +#include "cpu/i86/i86.h" +#include "machine/gridkeyb.h" +#include "machine/i7220.h" +#include "machine/i80130.h" +#include "machine/i8255.h" +#include "machine/ram.h" +#include "machine/z80sio.h" +#include "sound/spkrdev.h" + +#include "rendlay.h" +#include "screen.h" +#include "softlist.h" +#include "speaker.h" + + +#define VERBOSE_DBG 1 + +#define DBG_LOG(N,M,A) \ + do { \ + if(VERBOSE_DBG>=N) \ + { \ + if( M ) \ + logerror("%11.6f at %s: %-10s",machine().time().as_double(),machine().describe_context(),(char*)M ); \ + logerror A; \ + } \ + } while (0) + + +#define I80130_TAG "osp" + +class gridcomp_state : public driver_device +{ +public: + gridcomp_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag) + , m_maincpu(*this, "maincpu") + , m_osp(*this, I80130_TAG) + , m_modem(*this, "modem") + , m_uart8274(*this, "uart8274") + , m_speaker(*this, "speaker") + , m_ram(*this, RAM_TAG) + { } + + required_device m_maincpu; + required_device m_osp; + required_device m_modem; + optional_device m_uart8274; + required_device m_speaker; + required_device m_ram; + + DECLARE_DRIVER_INIT(gridcomp); + DECLARE_MACHINE_START(gridcomp); + DECLARE_MACHINE_RESET(gridcomp); + + IRQ_CALLBACK_MEMBER(irq_callback); + + DECLARE_READ16_MEMBER(grid_9ff0_r); + DECLARE_READ16_MEMBER(grid_keyb_r); + DECLARE_READ16_MEMBER(grid_gpib_r); + DECLARE_WRITE16_MEMBER(grid_keyb_w); + DECLARE_WRITE16_MEMBER(grid_gpib_w); + + uint32_t screen_update_110x(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + uint32_t screen_update_113x(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + uint32_t screen_update_generic(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int px); + + void kbd_put(u16 data); + +private: + bool m_kbd_ready; + uint16_t m_kbd_data; + + uint16_t *m_videoram; +}; + + +READ16_MEMBER(gridcomp_state::grid_9ff0_r) +{ + uint16_t data = 0; + + switch (offset) + { + case 0: + data = 0xbb66; + break; + } + + DBG_LOG(1, "9FF0", ("%02x == %02x\n", 0x9ff00 + (offset << 1), data)); + + return data; +} + +READ16_MEMBER(gridcomp_state::grid_keyb_r) +{ + uint16_t data = 0; + + switch (offset) + { + case 0: + data = m_kbd_data; + m_kbd_data = 0xff; + m_kbd_ready = false; + m_osp->ir4_w(CLEAR_LINE); + break; + + case 1: + data = m_kbd_ready ? 2 : 0; + break; + } + + DBG_LOG(1, "Keyb", ("%02x == %02x\n", 0xdffc0 + (offset << 1), data)); + + return data; +} + +WRITE16_MEMBER(gridcomp_state::grid_keyb_w) +{ + DBG_LOG(1, "Keyb", ("%02x <- %02x\n", 0xdffc0 + (offset << 1), data)); +} + +void gridcomp_state::kbd_put(u16 data) +{ + m_kbd_data = data; + m_kbd_ready = true; + m_osp->ir4_w(ASSERT_LINE); +} + + +// reject all commands +READ16_MEMBER(gridcomp_state::grid_gpib_r) +{ + uint16_t data = 0; + + switch (offset) + { + case 0: + data = 0x10; // BO + break; + + case 1: + data = 0x40; // ERR + m_osp->ir5_w(CLEAR_LINE); + break; + } + + DBG_LOG(1, "GPIB", ("%02x == %02x\n", 0xdff80 + (offset << 1), data)); + + return data; +} + +WRITE16_MEMBER(gridcomp_state::grid_gpib_w) +{ + switch (offset) + { + case 7: + m_osp->ir5_w(ASSERT_LINE); + break; + } + + DBG_LOG(1, "GPIB", ("%02x <- %02x\n", 0xdff80 + (offset << 1), data)); +} + + +uint32_t gridcomp_state::screen_update_generic(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int px) +{ + int x, y, offset; + uint16_t gfx, *p; + + for (y = 0; y < 240; y++) + { + p = &bitmap.pix16(y); + + offset = y * (px / 16); + + for (x = offset; x < offset + px / 16; x++) + { + gfx = m_videoram[x]; + + *p++ = BIT(gfx, 15); + *p++ = BIT(gfx, 14); + *p++ = BIT(gfx, 13); + *p++ = BIT(gfx, 12); + *p++ = BIT(gfx, 11); + *p++ = BIT(gfx, 10); + *p++ = BIT(gfx, 9); + *p++ = BIT(gfx, 8); + *p++ = BIT(gfx, 7); + *p++ = BIT(gfx, 6); + *p++ = BIT(gfx, 5); + *p++ = BIT(gfx, 4); + *p++ = BIT(gfx, 3); + *p++ = BIT(gfx, 2); + *p++ = BIT(gfx, 1); + *p++ = BIT(gfx, 0); + } + } + + return 0; +} + +uint32_t gridcomp_state::screen_update_110x(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + return screen_update_generic(screen, bitmap, cliprect, 320); +} + +uint32_t gridcomp_state::screen_update_113x(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + return screen_update_generic(screen, bitmap, cliprect, 512); +} + + +DRIVER_INIT_MEMBER(gridcomp_state, gridcomp) +{ + DBG_LOG(0, "init", ("driver_init()\n")); +} + +MACHINE_START_MEMBER(gridcomp_state, gridcomp) +{ + address_space &program = m_maincpu->space(AS_PROGRAM); + + DBG_LOG(0, "init", ("machine_start()\n")); + + program.install_readwrite_bank(0, m_ram->size() - 1, "bank10"); + membank("bank10")->set_base(m_ram->pointer()); + + m_videoram = (uint16_t *)m_maincpu->space(AS_PROGRAM).get_write_ptr(0x400); +} + +MACHINE_RESET_MEMBER(gridcomp_state, gridcomp) +{ + DBG_LOG(0, "init", ("machine_reset()\n")); + + m_kbd_ready = false; +} + +IRQ_CALLBACK_MEMBER(gridcomp_state::irq_callback) +{ + return m_osp->inta_r(); +} + + +static ADDRESS_MAP_START( grid1101_map, AS_PROGRAM, 16, gridcomp_state ) + ADDRESS_MAP_UNMAP_HIGH + AM_RANGE(0xdfe80, 0xdfe83) AM_DEVREADWRITE8("i7220", i7220_device, read, write, 0x00ff) + AM_RANGE(0xdfea0, 0xdfeaf) AM_UNMAP // ?? + AM_RANGE(0xdfec0, 0xdfecf) AM_DEVREADWRITE8("modem", i8255_device, read, write, 0x00ff) // incl. DTMF generator + AM_RANGE(0xdff40, 0xdff5f) AM_NOP // ?? machine ID EAROM, RTC + AM_RANGE(0xdff80, 0xdff8f) AM_READWRITE(grid_gpib_r, grid_gpib_w) // TMS9914 + AM_RANGE(0xdffc0, 0xdffcf) AM_READWRITE(grid_keyb_r, grid_keyb_w) // Intel 8741 MCU + AM_RANGE(0xfc000, 0xfffff) AM_ROM AM_REGION("user1", 0) +ADDRESS_MAP_END + +static ADDRESS_MAP_START( grid1121_map, AS_PROGRAM, 16, gridcomp_state ) + ADDRESS_MAP_UNMAP_HIGH + AM_RANGE(0x90000, 0x97fff) AM_UNMAP // ?? ROM slot + AM_RANGE(0x9ff00, 0x9ff0f) AM_UNMAP // AM_READ(grid_9ff0_r) // ?? ROM? + AM_RANGE(0xc0000, 0xcffff) AM_UNMAP // ?? ROM slot -- signature expected: 0x4554, 0x5048 + AM_RANGE(0xdfe00, 0xdfe1f) AM_UNMAP // AM_DEVREADWRITE8("uart8274", i8274_new_device, ba_cd_r, ba_cd_w, 0x00ff) + AM_RANGE(0xdfe40, 0xdfe4f) AM_UNMAP // ?? diagnostic 8274 + AM_RANGE(0xdfe80, 0xdfe83) AM_DEVREADWRITE8("i7220", i7220_device, read, write, 0x00ff) + AM_RANGE(0xdfea0, 0xdfeaf) AM_UNMAP // ?? + AM_RANGE(0xdfec0, 0xdfecf) AM_DEVREADWRITE8("modem", i8255_device, read, write, 0x00ff) // incl. DTMF generator + AM_RANGE(0xdff40, 0xdff5f) AM_NOP // ?? machine ID EAROM, RTC + AM_RANGE(0xdff80, 0xdff8f) AM_READWRITE(grid_gpib_r, grid_gpib_w) // TMS9914 + AM_RANGE(0xdffc0, 0xdffcf) AM_READWRITE(grid_keyb_r, grid_keyb_w) // Intel 8741 MCU + AM_RANGE(0xfc000, 0xfffff) AM_ROM AM_REGION("user1", 0) +ADDRESS_MAP_END + +static ADDRESS_MAP_START( grid1101_io, AS_IO, 16, gridcomp_state ) + AM_RANGE(0x0000, 0x000f) AM_DEVICE(I80130_TAG, i80130_device, io_map) +ADDRESS_MAP_END + +static INPUT_PORTS_START( gridcomp ) +INPUT_PORTS_END + +/* + * IRQ0 serial + * IRQ1 bubble + * IRQ2 modem + * IRQ3 system tick || vert sync + * IRQ4 keyboard + * IRQ5 gpib + * IRQ6 8087 + * IRQ7 ring + */ +static MACHINE_CONFIG_START( grid1101 ) + MCFG_CPU_ADD("maincpu", I8086, XTAL_15MHz / 3) + MCFG_CPU_PROGRAM_MAP(grid1101_map) + MCFG_CPU_IO_MAP(grid1101_io) + MCFG_CPU_IRQ_ACKNOWLEDGE_DRIVER(gridcomp_state, irq_callback) + + MCFG_MACHINE_START_OVERRIDE(gridcomp_state, gridcomp) + MCFG_MACHINE_RESET_OVERRIDE(gridcomp_state, gridcomp) + + MCFG_DEVICE_ADD(I80130_TAG, I80130, XTAL_15MHz/3) + MCFG_I80130_IRQ_CALLBACK(INPUTLINE("maincpu", 0)) + + MCFG_SPEAKER_STANDARD_MONO("mono") + MCFG_SOUND_ADD("speaker", SPEAKER_SOUND, 0) + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00) + + MCFG_SCREEN_ADD_MONOCHROME("screen", RASTER, rgb_t::amber()) + MCFG_SCREEN_UPDATE_DRIVER(gridcomp_state, screen_update_110x) + MCFG_SCREEN_RAW_PARAMS(XTAL_15MHz/2, 424, 0, 320, 262, 0, 240) // XXX 66 Hz refresh + MCFG_SCREEN_VBLANK_CALLBACK(DEVWRITELINE(I80130_TAG, i80130_device, ir3_w)) + MCFG_DEFAULT_LAYOUT(layout_lcd) + + MCFG_SCREEN_PALETTE("palette") + MCFG_PALETTE_ADD_MONOCHROME("palette") + + MCFG_DEVICE_ADD("keyboard", GRID_KEYBOARD, 0) + MCFG_GRID_KEYBOARD_CB(PUT(gridcomp_state, kbd_put)) + + MCFG_DEVICE_ADD("i7220", I7220, XTAL_4MHz) + MCFG_I7220_DATA_SIZE(3) // 3 1-Mbit MBM's + MCFG_I7220_IRQ_CALLBACK(DEVWRITELINE(I80130_TAG, i80130_device, ir1_w)) + MCFG_I7220_DRQ_CALLBACK(DEVWRITELINE(I80130_TAG, i80130_device, ir1_w)) + + MCFG_I8274_ADD("uart8274", XTAL_4_032MHz, 0, 0, 0, 0) + + MCFG_DEVICE_ADD("modem", I8255, 0) + + MCFG_RAM_ADD(RAM_TAG) + MCFG_RAM_DEFAULT_SIZE("256K") + MCFG_RAM_DEFAULT_VALUE(0) +MACHINE_CONFIG_END + +static MACHINE_CONFIG_DERIVED( grid1109, grid1101 ) + MCFG_DEVICE_MODIFY(RAM_TAG) + MCFG_RAM_DEFAULT_SIZE("512K") +MACHINE_CONFIG_END + +static MACHINE_CONFIG_DERIVED( grid1121, grid1101 ) + MCFG_CPU_MODIFY("maincpu") + MCFG_CPU_CLOCK(XTAL_24MHz / 3) // XXX + MCFG_CPU_PROGRAM_MAP(grid1121_map) +MACHINE_CONFIG_END + +static MACHINE_CONFIG_DERIVED( grid1129, grid1121 ) + MCFG_DEVICE_MODIFY(RAM_TAG) + MCFG_RAM_DEFAULT_SIZE("512K") +MACHINE_CONFIG_END + +static MACHINE_CONFIG_DERIVED( grid1131, grid1121 ) + MCFG_SCREEN_MODIFY("screen") + MCFG_SCREEN_UPDATE_DRIVER(gridcomp_state, screen_update_113x) + MCFG_SCREEN_RAW_PARAMS(XTAL_15MHz/2, 720, 0, 512, 262, 0, 240) // XXX +MACHINE_CONFIG_END + +static MACHINE_CONFIG_DERIVED( grid1139, grid1131 ) + MCFG_DEVICE_MODIFY(RAM_TAG) + MCFG_RAM_DEFAULT_SIZE("512K") +MACHINE_CONFIG_END + + +ROM_START( grid1101 ) + ROM_REGION16_LE(0x10000, "user1", 0) + + ROM_SYSTEM_BIOS(0, "ccos", "ccos bios") + ROMX_LOAD("1101EVEN.BIN", 0x0000, 0x2000, NO_DUMP, ROM_SKIP(1)|ROM_BIOS(1)) + ROMX_LOAD("1101ODD.BIN", 0x0001, 0x2000, NO_DUMP, ROM_SKIP(1)|ROM_BIOS(1)) +ROM_END + +ROM_START( grid1109 ) + ROM_REGION16_LE(0x10000, "user1", 0) + + ROM_SYSTEM_BIOS(0, "ccos", "ccos bios") + ROMX_LOAD("1109EVEN.BIN", 0x0000, 0x2000, NO_DUMP, ROM_SKIP(1)|ROM_BIOS(1)) + ROMX_LOAD("1109ODD.BIN", 0x0001, 0x2000, NO_DUMP, ROM_SKIP(1)|ROM_BIOS(1)) +ROM_END + +ROM_START( grid1121 ) + ROM_REGION16_LE(0x10000, "user1", 0) + + ROM_SYSTEM_BIOS(0, "ccos", "ccos bios") + ROMX_LOAD("1121EVEN.BIN", 0x0000, 0x2000, NO_DUMP, ROM_SKIP(1)|ROM_BIOS(1)) + ROMX_LOAD("1121ODD.BIN", 0x0001, 0x2000, NO_DUMP, ROM_SKIP(1)|ROM_BIOS(1)) +ROM_END + +ROM_START( grid1129 ) + ROM_REGION16_LE(0x10000, "user1", 0) + ROM_DEFAULT_BIOS("patched") + + ROM_SYSTEM_BIOS(0, "ccos", "ccos bios") + ROMX_LOAD("1129EVEN.BIN", 0x0000, 0x2000, NO_DUMP, ROM_SKIP(1)|ROM_BIOS(1)) + ROMX_LOAD("1129ODD.BIN", 0x0001, 0x2000, NO_DUMP, ROM_SKIP(1)|ROM_BIOS(1)) + + ROM_SYSTEM_BIOS(1, "patched", "patched 1139 bios") + ROMX_LOAD("1139EVEN.BIN", 0x0000, 0x2000, CRC(67071849) SHA1(782239c155fa5821f8dbd2607cee9152d175e90e),ROM_SKIP(1)|ROM_BIOS(2)) + ROMX_LOAD("1139ODD.BIN", 0x0001, 0x2000, CRC(13ed4bf0) SHA1(f7087f86dbbc911bee985125bccd2417e0374e8e),ROM_SKIP(1)|ROM_BIOS(2)) + + // change bubble driver setup to read floppy images with 512-byte sectors + ROM_FILL(0x3114,1,0x00) + ROM_FILL(0x3115,1,0x02) + ROM_FILL(0x3116,1,0xf8) + ROM_FILL(0x3117,1,0x01) + + // move work area from 0440h:XXXX to 0298h:XXXX + ROM_FILL(0x23,1,0x98) + ROM_FILL(0x24,1,0x2) + ROM_FILL(0xbc,1,0x98) + ROM_FILL(0xbd,1,0x2) + ROM_FILL(0x14e,1,0xc1) // + ROM_FILL(0x14f,1,0x2) // + ROM_FILL(0x15a,1,0xc2) // + ROM_FILL(0x15b,1,0x2) // + ROM_FILL(0x17b,1,0x45) // + ROM_FILL(0x17c,1,0x3) // + ROM_FILL(0x28c,1,0x98) + ROM_FILL(0x28d,1,0x2) + ROM_FILL(0x28f,1,0x98) + ROM_FILL(0x290,1,0x2) + ROM_FILL(0x2b9,1,0x98) + ROM_FILL(0x2ba,1,0x2) + ROM_FILL(0x2d0,1,0x98) + ROM_FILL(0x2d1,1,0x2) + ROM_FILL(0x31a,1,0x98) + ROM_FILL(0x31b,1,0x2) + ROM_FILL(0x3a0,1,0x98) + ROM_FILL(0x3a1,1,0x2) + ROM_FILL(0x3a3,1,0x98) + ROM_FILL(0x3a4,1,0x2) + ROM_FILL(0x3e2,1,0x98) + ROM_FILL(0x3e3,1,0x2) + ROM_FILL(0x43e,1,0x98) + ROM_FILL(0x43f,1,0x2) + ROM_FILL(0x46d,1,0x98) + ROM_FILL(0x46e,1,0x2) + ROM_FILL(0x4fe,1,0x98) + ROM_FILL(0x4ff,1,0x2) + ROM_FILL(0x512,1,0x98) + ROM_FILL(0x513,1,0x2) + ROM_FILL(0x768,1,0x98) + ROM_FILL(0x769,1,0x2) + ROM_FILL(0x79e,1,0x98) + ROM_FILL(0x79f,1,0x2) + ROM_FILL(0x7f5,1,0x98) + ROM_FILL(0x7f6,1,0x2) + ROM_FILL(0x92a,1,0x98) + ROM_FILL(0x92b,1,0x2) + ROM_FILL(0xe50,1,0x98) + ROM_FILL(0xe51,1,0x2) + ROM_FILL(0xfa6,1,0x98) + ROM_FILL(0xfa7,1,0x2) + ROM_FILL(0x15fe,1,0xce) // + ROM_FILL(0x15ff,1,0x2) // + ROM_FILL(0x1628,1,0xd0) // + ROM_FILL(0x1629,1,0x2) // + ROM_FILL(0x1700,1,0x98) + ROM_FILL(0x1701,1,0x2) + ROM_FILL(0x1833,1,0xd6) // + ROM_FILL(0x1834,1,0x2) // + ROM_FILL(0x184a,1,0xd6) // + ROM_FILL(0x184b,1,0x2) // + ROM_FILL(0x1a2e,1,0xd6) // + ROM_FILL(0x1a2f,1,0x2) // + ROM_FILL(0x19c2,1,0x98) + ROM_FILL(0x19c3,1,0x2) + ROM_FILL(0x1ee0,1,0x98) + ROM_FILL(0x1ee1,1,0x2) + ROM_FILL(0x1f1d,1,0x98) + ROM_FILL(0x1f1e,1,0x2) + ROM_FILL(0x1f40,1,0x98) + ROM_FILL(0x1f41,1,0x2) + ROM_FILL(0x2253,1,0x98) + ROM_FILL(0x2254,1,0x2) + ROM_FILL(0x2437,1,0x98) + ROM_FILL(0x2438,1,0x2) + ROM_FILL(0x283a,1,0x98) + ROM_FILL(0x283b,1,0x2) + ROM_FILL(0x2868,1,0x98) + ROM_FILL(0x2869,1,0x2) + ROM_FILL(0x288f,1,0x98) + ROM_FILL(0x2890,1,0x2) + ROM_FILL(0x2942,1,0x98) + ROM_FILL(0x2943,1,0x2) + ROM_FILL(0x295c,1,0x98) + ROM_FILL(0x295d,1,0x2) + ROM_FILL(0x2a5e,1,0x98) + ROM_FILL(0x2a5f,1,0x2) + ROM_FILL(0x315c,1,0xc9) // + ROM_FILL(0x315d,1,0x2) // + ROM_FILL(0x3160,1,0xce) // + ROM_FILL(0x3161,1,0x2) // + ROM_FILL(0x3164,1,0xcf) // + ROM_FILL(0x3165,1,0x2) // +ROM_END + +ROM_START( grid1131 ) + ROM_REGION16_LE(0x10000, "user1", 0) + + ROM_SYSTEM_BIOS(0, "ccos", "ccos bios") + ROMX_LOAD("1131EVEN.BIN", 0x0000, 0x2000, NO_DUMP, ROM_SKIP(1)|ROM_BIOS(1)) + ROMX_LOAD("1131ODD.BIN", 0x0001, 0x2000, NO_DUMP, ROM_SKIP(1)|ROM_BIOS(1)) +ROM_END + +ROM_START( grid1139 ) + ROM_REGION16_LE(0x10000, "user1", 0) + + ROM_SYSTEM_BIOS(0, "normal", "normal bios") + ROMX_LOAD("1139EVEN.BIN", 0x0000, 0x2000, CRC(67071849) SHA1(782239c155fa5821f8dbd2607cee9152d175e90e),ROM_SKIP(1)|ROM_BIOS(1)) + ROMX_LOAD("1139ODD.BIN", 0x0001, 0x2000, CRC(13ed4bf0) SHA1(f7087f86dbbc911bee985125bccd2417e0374e8e),ROM_SKIP(1)|ROM_BIOS(1)) +ROM_END + + +/*************************************************************************** + + Game driver(s) + +***************************************************************************/ + +// YEAR NAME PARENT COMPAT MACHINE INPUT STATE INIT COMPANY FULLNAME FLAGS +COMP( 1982, grid1101, 0, 0, grid1101, gridcomp, gridcomp_state, 0, "GRiD Computers", "Compass 1101", MACHINE_IS_SKELETON ) +COMP( 1982, grid1109, grid1101, 0, grid1109, gridcomp, gridcomp_state, 0, "GRiD Computers", "Compass 1109", MACHINE_IS_SKELETON ) +COMP( 1984, grid1121, 0, 0, grid1121, gridcomp, gridcomp_state, 0, "GRiD Computers", "Compass II 1121", MACHINE_IS_SKELETON ) +COMP( 1984, grid1129, grid1121, 0, grid1129, gridcomp, gridcomp_state, 0, "GRiD Computers", "Compass II 1129", MACHINE_IS_SKELETON ) +COMP( 1984, grid1131, grid1121, 0, grid1131, gridcomp, gridcomp_state, 0, "GRiD Computers", "Compass II 1131", MACHINE_IS_SKELETON ) +COMP( 1984, grid1139, grid1121, 0, grid1139, gridcomp, gridcomp_state, 0, "GRiD Computers", "Compass II 1139", MACHINE_IS_SKELETON ) + diff --git a/src/mame/machine/gridkeyb.cpp b/src/mame/machine/gridkeyb.cpp new file mode 100644 index 00000000000..77bbef85bb8 --- /dev/null +++ b/src/mame/machine/gridkeyb.cpp @@ -0,0 +1,321 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb, Sergey Svishchev +/*************************************************************************** + + GRiD Compass keyboard HLE, derived from generic_keyboard + + Keycodes from "6 - Interceptor, CCProm, Utils, OS - Sysgen/UTILS/DVLEXEC.PLM" + + Multiple shift key combos not simulated yet. + +***************************************************************************/ + +#include "emu.h" + +#include "machine/gridkeyb.h" +#include "machine/keyboard.ipp" + + + +namespace { +u16 const TRANSLATION_TABLE[][4][16] = { + { // plain + { '`', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 0x08U, 0x7fU, 0x1bU }, + { 0x09U, 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\\', 0xffU, 0xffU }, + { 0xffU, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', 0x0dU, 0xc5U, 0xc4U, 0x0aU }, + { 0xffU, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0xffU, 0xc6U, 0xc7U, ' ' } + }, + { // SHIFT + { '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', 0x08U, 0x7fU, 0x1bU }, + { 0x09U, 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '|', 0xffU, 0xffU }, + { 0xffU, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', 0x0dU, 0xffU, 0xffU, 0x0aU }, + { 0xffU, '_', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', 0xffU, 0xffU, 0xffU, ' ' } + }, + { // CODE -- partial + { 0xffU, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 0xffU, 0xffU, 0x88U, 0xffU, 0x9bU }, + { 0x89U, 0xf1U, 0xf7U, 0xe5U, 0xf2U, 0xf4U, 0xf9U, 0xf5U, 0xe9U, 0xefU, 0xf0U, 0x9bU, 0xffU, 0xffU, 0xffU, 0xffU }, + { 0xffU, 0xe1U, 0xf3U, 0xe4U, 0xe6U, 0xe7U, 0xe8U, 0xeaU, 0xebU, 0xecU, ';', '\'', 0x8dU, 0xffU, 0xffU, 0xffU }, + { 0xffU, 0x1cU, 0xfaU, 0xf8U, 0xe3U, 0xf6U, 0xe2U, 0xeeU, 0xedU, ',', '.', 0xbfU, 0xffU, 0xd4U, 0xd5U, 0xffU } + }, + { // CTRL + { 0x00U, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 0x1fU, 0x1eU, 0x88U, 0x7fU, 0x1bU }, + { 0x89U, 0x11U, 0x17U, 0x05U, 0x12U, 0x14U, 0x19U, 0x15U, 0x09U, 0x0fU, 0x10U, 0x9bU, 0x1dU, 0x1cU, 0xffU, 0xffU }, + { 0xffU, 0x01U, 0x13U, 0x04U, 0x06U, 0x07U, 0x08U, 0x0aU, 0x0bU, 0x0cU, ';', '\'', 0x8dU, 0xffU, 0xffU, 0x0aU }, + { 0xffU, 0x1cU, 0x1aU, 0x18U, 0x03U, 0x16U, 0x02U, 0x0eU, 0x0dU, ',', '.', 0xbfU, 0xffU, 0xffU, 0xffU, 0x00U } + }, +}; + + +bool const CAPS_TABLE[4][16] = { + { false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false }, + { false, true, true, true, true, true, true, true, true, true, true, false, false, false, false, false }, + { false, true, true, true, true, true, true, true, true, true, false, false, false, false, false, false }, + { false, false, true, true, true, true, true, true, true, false, false, false, false, false, false, false } +}; + +} // anonymous namespace + + + +/*************************************************************************** + REUSABLE I/O PORTS +***************************************************************************/ + +INPUT_PORTS_START( grid_keyboard ) + PORT_START("GRIDKBD_CFG") + PORT_CONFNAME( 0x0006U, 0x0004U, "Typematic Delay" ) + PORT_CONFSETTING( 0x0000U, "0.25s" ) + PORT_CONFSETTING( 0x0002U, "0.5s" ) + PORT_CONFSETTING( 0x0004U, "0.75s" ) + PORT_CONFSETTING( 0x0006U, "1.0s" ) + PORT_CONFNAME( 0x00f8U, 0x0098U, "Typematic Rate" ) + PORT_CONFSETTING( 0x0000U, "2.0cps" ) + PORT_CONFSETTING( 0x0008U, "2.1cps" ) + PORT_CONFSETTING( 0x0010U, "2.5cps" ) + PORT_CONFSETTING( 0x0018U, "2.7cps" ) + PORT_CONFSETTING( 0x0020U, "2.0cps" ) + PORT_CONFSETTING( 0x0028U, "2.1cps" ) + PORT_CONFSETTING( 0x0030U, "2.5cps" ) + PORT_CONFSETTING( 0x0038U, "2.7cps" ) + PORT_CONFSETTING( 0x0040U, "3.3cps" ) + PORT_CONFSETTING( 0x0048U, "3.8cps" ) + PORT_CONFSETTING( 0x0050U, "4.0cps" ) + PORT_CONFSETTING( 0x0058U, "4.3cps" ) + PORT_CONFSETTING( 0x0060U, "4.6cps" ) + PORT_CONFSETTING( 0x0068U, "5.0cps" ) + PORT_CONFSETTING( 0x0070U, "5.5cps" ) + PORT_CONFSETTING( 0x0078U, "6.0cps" ) + PORT_CONFSETTING( 0x0080U, "8.0cps" ) + PORT_CONFSETTING( 0x0088U, "8.6cps" ) + PORT_CONFSETTING( 0x0090U, "9.2cps" ) + PORT_CONFSETTING( 0x0098U, "10.0cps" ) + PORT_CONFSETTING( 0x00a0U, "10.9cps" ) + PORT_CONFSETTING( 0x00a8U, "12.0cps" ) + PORT_CONFSETTING( 0x00b0U, "13.3cps" ) + PORT_CONFSETTING( 0x00b8U, "15.0cps" ) + PORT_CONFSETTING( 0x00c0U, "16.0cps" ) + PORT_CONFSETTING( 0x00c8U, "17.1cps" ) + PORT_CONFSETTING( 0x00d0U, "18.5cps" ) + PORT_CONFSETTING( 0x00d8U, "20.0cps" ) + PORT_CONFSETTING( 0x00e0U, "21.8cps" ) + PORT_CONFSETTING( 0x00e8U, "24.0cps" ) + PORT_CONFSETTING( 0x00f0U, "26.7cps" ) + PORT_CONFSETTING( 0x00f8U, "30.0cps" ) + + PORT_START("GRIDKBD_MOD") + PORT_BIT( 0x01U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Ctrl") PORT_CODE(KEYCODE_LCONTROL) PORT_CODE(KEYCODE_RCONTROL) PORT_CHAR(UCHAR_MAMEKEY(LCONTROL)) + PORT_BIT( 0x02U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Shift") PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1) + PORT_BIT( 0x04U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Caps Lock") PORT_CODE(KEYCODE_CAPSLOCK) PORT_TOGGLE PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK)) + PORT_BIT( 0x08U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Code") PORT_CODE(KEYCODE_LALT) PORT_CODE(KEYCODE_RALT) PORT_CHAR(UCHAR_MAMEKEY(LALT)) + + PORT_START("GRIDKBD_ROW0") + PORT_BIT( 0x0001U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`') PORT_CHAR('~') + PORT_BIT( 0x0002U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') + PORT_BIT( 0x0004U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@') + PORT_BIT( 0x0008U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') + PORT_BIT( 0x0010U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') + PORT_BIT( 0x0020U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') + PORT_BIT( 0x0040U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^') + PORT_BIT( 0x0080U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&') + PORT_BIT( 0x0100U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*') + PORT_BIT( 0x0200U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(') + PORT_BIT( 0x0400U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR('(') + PORT_BIT( 0x0800U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_') + PORT_BIT( 0x1000U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+') + PORT_BIT( 0x2000U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSPACE) PORT_NAME("Backspace") PORT_CHAR(0x08U) + PORT_BIT( 0x4000U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_DEL) PORT_NAME("Del") PORT_CHAR(UCHAR_MAMEKEY(DEL)) + PORT_BIT( 0x8000U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_ESC) PORT_NAME("Escape") PORT_CHAR(UCHAR_MAMEKEY(ESC)) + + PORT_START("GRIDKBD_ROW1") + PORT_BIT( 0x0001U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_TAB) PORT_CHAR('\t') + PORT_BIT( 0x0002U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') + PORT_BIT( 0x0004U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') + PORT_BIT( 0x0008U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') + PORT_BIT( 0x0010U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') + PORT_BIT( 0x0020U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') + PORT_BIT( 0x0040U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') + PORT_BIT( 0x0080U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') + PORT_BIT( 0x0100U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') + PORT_BIT( 0x0200U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') + PORT_BIT( 0x0400U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') + PORT_BIT( 0x0800U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{') + PORT_BIT( 0x1000U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}') + PORT_BIT( 0x2000U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') PORT_CHAR('|') + PORT_BIT( 0x4000U, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x8000U, IP_ACTIVE_HIGH, IPT_UNUSED ) + + PORT_START("GRIDKBD_ROW2") + PORT_BIT( 0x0001U, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x0002U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') + PORT_BIT( 0x0004U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') + PORT_BIT( 0x0008U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') + PORT_BIT( 0x0010U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') + PORT_BIT( 0x0020U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') + PORT_BIT( 0x0040U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') + PORT_BIT( 0x0080U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') + PORT_BIT( 0x0100U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') + PORT_BIT( 0x0200U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') + PORT_BIT( 0x0400U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':') + PORT_BIT( 0x0800U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('"') + PORT_BIT( 0x1000U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_ENTER) PORT_NAME("Return") PORT_CHAR(0x0dU) + PORT_BIT( 0x2000U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_UP) PORT_NAME("UpArrow") + PORT_BIT( 0x4000U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_DOWN) PORT_NAME("DownArrow") + PORT_BIT( 0x8000U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_INSERT) PORT_NAME("Linefeed") PORT_CHAR(UCHAR_MAMEKEY(INSERT)) + + PORT_START("GRIDKBD_ROW3") + PORT_BIT( 0x0001U, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x0002U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('\\') PORT_CHAR('_') + PORT_BIT( 0x0004U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') + PORT_BIT( 0x0008U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') + PORT_BIT( 0x0010U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') + PORT_BIT( 0x0020U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') + PORT_BIT( 0x0040U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') + PORT_BIT( 0x0080U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') + PORT_BIT( 0x0100U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') + PORT_BIT( 0x0200U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<') + PORT_BIT( 0x0400U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>') + PORT_BIT( 0x0800U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?') + PORT_BIT( 0x1000U, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x2000U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_LEFT) PORT_NAME("LeftArrow") + PORT_BIT( 0x4000U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_RIGHT) PORT_NAME("RightArrow") + PORT_BIT( 0x8000U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') +INPUT_PORTS_END + + + +/*************************************************************************** + DEVICE TYPE GLOBALS +***************************************************************************/ + +DEFINE_DEVICE_TYPE(GRID_KEYBOARD, grid_keyboard_device, "grid_keyboard", "GRiD Compass Keyboard") + + + +/*************************************************************************** + IMPLEMENTATION +***************************************************************************/ + +grid_keyboard_device::grid_keyboard_device( + machine_config const &mconfig, + device_type type, + char const *tag, + device_t *owner, + u32 clock) + : device_t(mconfig, type, tag, owner, clock) + , device_matrix_keyboard_interface(mconfig, *this, "GRIDKBD_ROW0", "GRIDKBD_ROW1", "GRIDKBD_ROW2", "GRIDKBD_ROW3") + , m_config(*this, "GRIDKBD_CFG") + , m_modifiers(*this, "GRIDKBD_MOD") + , m_last_modifiers(0U) + , m_keyboard_cb() +{ +} + + +grid_keyboard_device::grid_keyboard_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) + : grid_keyboard_device(mconfig, GRID_KEYBOARD, tag, owner, clock) +{ +} + + +ioport_constructor grid_keyboard_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(grid_keyboard); +} + + +void grid_keyboard_device::device_start() +{ + m_keyboard_cb.bind_relative_to(*owner()); + + save_item(NAME(m_last_modifiers)); +} + + +void grid_keyboard_device::device_reset() +{ + reset_key_state(); + m_last_modifiers = 0; + + start_processing(attotime::from_hz(2'400)); + typematic_stop(); +} + + +void grid_keyboard_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + device_matrix_keyboard_interface::device_timer(timer, id, param, ptr); +} + + +void grid_keyboard_device::key_make(u8 row, u8 column) +{ + send_translated((row << 4) | column); + typematic_start(row, column, typematic_delay(), typematic_period()); +} + + +void grid_keyboard_device::key_repeat(u8 row, u8 column) +{ + send_translated((row << 4) | column); +} + + +void grid_keyboard_device::send_key(u16 code) +{ + m_keyboard_cb(code); +} + + +bool grid_keyboard_device::translate(u8 code, u16 &translated) const +{ + unsigned const row((code >> 4) & 0x03U); + unsigned const col((code >> 0) & 0x0fU); + + u16 const modifiers(m_modifiers->read()); + bool const shift(bool(modifiers & 0x02U) != (bool(modifiers & 0x04U) && CAPS_TABLE[row][col])); + bool const ctrl(modifiers & 0x01U); + bool const meta(modifiers & 0x08U); + + unsigned const map(ctrl ? 3U : meta ? 2U : shift ? 1U : 0U); + u16 const result(TRANSLATION_TABLE[map][row][col]); + if (result == u8(~0U)) + { + return false; + } + else + { + translated = result; + return true; + } +} + + +void grid_keyboard_device::will_scan_row(u8 row) +{ + u16 const modifiers(m_modifiers->read()); + if (modifiers != m_last_modifiers) + typematic_restart(typematic_delay(), typematic_period()); + + m_last_modifiers = modifiers; +} + + +void grid_keyboard_device::send_translated(u8 code) +{ + u16 translated; + if (translate(code, translated)) + send_key(translated); +} + + +attotime grid_keyboard_device::typematic_delay() const +{ + return attotime::from_msec(250 * (1 + ((m_config->read() >> 1) & 0x03U))); +} + + +attotime grid_keyboard_device::typematic_period() const +{ + unsigned const rate(~(m_config->read() >> 3) & 0x1fU); + return attotime::from_ticks((8U + (rate & 0x07U)) * (1 << ((rate >> 3) & 0x03)), 240U); +} diff --git a/src/mame/machine/gridkeyb.h b/src/mame/machine/gridkeyb.h new file mode 100644 index 00000000000..fabf82c0ae2 --- /dev/null +++ b/src/mame/machine/gridkeyb.h @@ -0,0 +1,89 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb, Sergey Svishchev +#ifndef MAME_MACHINE_GRIDKEYB_H +#define MAME_MACHINE_GRIDKEYB_H + +#pragma once + +#include "machine/keyboard.h" + + +/*************************************************************************** + DEVICE CONFIGURATION MACROS +***************************************************************************/ + +#define GRIDKEYBCB_PUT(cls, fnc) grid_keyboard_device::output_delegate((&cls::fnc), (#cls "::" #fnc), DEVICE_SELF, ((cls *)nullptr)) +#define GRIDKEYBCB_DEVPUT(tag, cls, fnc) grid_keyboard_device::output_delegate((&cls::fnc), (#cls "::" #fnc), (tag), ((cls *)nullptr)) + +#define MCFG_GRID_KEYBOARD_CB(cb) \ + grid_keyboard_device::set_keyboard_callback(*device, (GRIDKEYBCB_##cb)); + + + +/*************************************************************************** + DEVICE TYPE GLOBALS +***************************************************************************/ + +DECLARE_DEVICE_TYPE(GRID_KEYBOARD, grid_keyboard_device) + + + +/*************************************************************************** + REUSABLE I/O PORTS +***************************************************************************/ + +INPUT_PORTS_EXTERN( grid_keyboard ); + + + +/*************************************************************************** + TYPE DECLARATIONS +***************************************************************************/ + + +class grid_keyboard_device : public device_t, protected device_matrix_keyboard_interface<4U> +{ +public: + typedef device_delegate output_delegate; + + grid_keyboard_device( + const machine_config &mconfig, + const char *tag, + device_t *owner, + u32 clock); + + template static void set_keyboard_callback(device_t &device, Object &&cb) { downcast(device).m_keyboard_cb = std::forward(cb); } + + virtual ioport_constructor device_input_ports() const override; + +protected: + grid_keyboard_device( + const machine_config &mconfig, + device_type type, + char const *tag, + device_t *owner, + u32 clock); + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; + virtual void key_make(u8 row, u8 column) override; + virtual void key_repeat(u8 row, u8 column) override; + virtual void send_key(u16 code); + virtual bool translate(u8 code, u16 &translated) const; + + required_ioport m_config; + required_ioport m_modifiers; + +private: + virtual void will_scan_row(u8 row) override; + + void typematic(); + void send_translated(u8 code); + attotime typematic_delay() const; + attotime typematic_period() const; + + u16 m_last_modifiers; + output_delegate m_keyboard_cb; +}; + +#endif // MAME_MACHINE_GRIDKEYB_H diff --git a/src/mame/mame.lst b/src/mame/mame.lst index 0c54b5d2992..71f31e439b4 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -14024,6 +14024,14 @@ grchamp // GM (c) 1981 Taito Corporation @source:grfd2301.cpp grfd2301 // +@source:gridcomp.cpp +grid1101 // +grid1109 // +grid1121 // +grid1129 // +grid1131 // +grid1139 // + @source:gridlee.cpp gridlee // [1983 Videa] prototype - no copyright notice diff --git a/src/mame/mess.flt b/src/mame/mess.flt index 193a6f93e5d..3178a52fd59 100644 --- a/src/mame/mess.flt +++ b/src/mame/mess.flt @@ -226,6 +226,7 @@ goupil.cpp gp2x.cpp gp32.cpp grfd2301.cpp +gridcomp.cpp h19.cpp h8.cpp h89.cpp