New skeleton: GRiD Compass series

This commit is contained in:
Sergey Svishchev 2017-05-18 03:01:53 +03:00
parent 7044a6b5fc
commit 24d016f62c
10 changed files with 1977 additions and 0 deletions

View File

@ -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

View File

@ -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",

View File

@ -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;
}

240
src/devices/machine/i7220.h Normal file
View File

@ -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 <class Object> static devcb_base &set_intrq_wr_callback(device_t &device, Object &&cb) { return downcast<i7220_device &>(device).intrq_cb.set_callback(std::forward<Object>(cb)); }
template <class Object> static devcb_base &set_drq_wr_callback(device_t &device, Object &&cb) { return downcast<i7220_device &>(device).drq_cb.set_callback(std::forward<Object>(cb)); }
static void set_data_size(device_t &device, int data_size) { downcast<i7220_device &>(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<uint8_t, 40> m_fifo;
};
// device type definition
DECLARE_DEVICE_TYPE(I7220, i7220_device)
#endif // MAME_MACHINE_I7220_H

View File

@ -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 */

View File

@ -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<cpu_device> m_maincpu;
required_device<i80130_device> m_osp;
required_device<i8255_device> m_modem;
optional_device<i8274_new_device> m_uart8274;
required_device<speaker_sound_device> m_speaker;
required_device<ram_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 )

View File

@ -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);
}

View File

@ -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<void (u16 character)> output_delegate;
grid_keyboard_device(
const machine_config &mconfig,
const char *tag,
device_t *owner,
u32 clock);
template <class Object> static void set_keyboard_callback(device_t &device, Object &&cb) { downcast<grid_keyboard_device &>(device).m_keyboard_cb = std::forward<Object>(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

View File

@ -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

View File

@ -226,6 +226,7 @@ goupil.cpp
gp2x.cpp
gp32.cpp
grfd2301.cpp
gridcomp.cpp
h19.cpp
h8.cpp
h89.cpp