summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--scripts/target/mame/mess.lua3
-rw-r--r--src/devices/cpu/m6805/m68705.cpp68
-rw-r--r--src/devices/cpu/m6805/m68705.h33
-rw-r--r--src/devices/machine/i8251.cpp221
-rw-r--r--src/devices/machine/i8251.h28
-rw-r--r--src/mame/drivers/gladiatr.cpp55
-rw-r--r--src/mame/drivers/osborne1.cpp2
-rw-r--r--src/mame/drivers/pitnrun.cpp28
-rw-r--r--src/mame/drivers/zorba.cpp608
-rw-r--r--src/mame/includes/gladiatr.h8
-rw-r--r--src/mame/includes/osborne1.h2
-rw-r--r--src/mame/includes/zorba.h113
-rw-r--r--src/mame/machine/osborne1.cpp12
-rw-r--r--src/mame/machine/taito68705interface.cpp1
-rw-r--r--src/mame/machine/zorbakbd.cpp314
-rw-r--r--src/mame/machine/zorbakbd.h43
16 files changed, 1112 insertions, 427 deletions
diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua
index 7487f4435e5..96cfc02d53c 100644
--- a/scripts/target/mame/mess.lua
+++ b/scripts/target/mame/mess.lua
@@ -3422,6 +3422,9 @@ files {
MAME_DIR .. "src/mame/includes/xor100.h",
MAME_DIR .. "src/mame/drivers/xavix.cpp",
MAME_DIR .. "src/mame/drivers/zorba.cpp",
+ MAME_DIR .. "src/mame/includes/zorba.h",
+ MAME_DIR .. "src/mame/machine/zorbakbd.cpp",
+ MAME_DIR .. "src/mame/machine/zorbakbd.h",
}
end
diff --git a/src/devices/cpu/m6805/m68705.cpp b/src/devices/cpu/m6805/m68705.cpp
index b678954e386..fd7ff5be29c 100644
--- a/src/devices/cpu/m6805/m68705.cpp
+++ b/src/devices/cpu/m6805/m68705.cpp
@@ -569,6 +569,30 @@ void m68705_new_device::burn_cycles(unsigned count)
}
}
+template <std::size_t N> void m68705_new_device::add_port_latch_state()
+{
+ state_add(M68705_LATCHA + N, util::string_format("LATCH%c", 'A' + N).c_str(), m_port_latch[N]).mask(~m_port_mask[N] & 0xff);
+}
+
+template <std::size_t N> void m68705_new_device::add_port_ddr_state()
+{
+ state_add(M68705_DDRA + N, util::string_format("DDR%c", 'A' + N).c_str(), m_port_ddr[N]).mask(~m_port_mask[N] & 0xff);
+}
+
+void m68705_new_device::add_timer_state()
+{
+ state_add(M68705_PS, "PS", m_prescaler).mask(0x7f);
+ state_add(M68705_TDR, "TDR", m_tdr).mask(0xff);
+ state_add(M68705_TCR, "TCR", m_tcr).mask(0xff);
+}
+
+void m68705_new_device::add_eprom_state()
+{
+ state_add(M68705_PCR, "PCR", m_pcr).mask(0xff);
+ state_add(M68705_PLA, "PLA", m_pl_addr).mask(0xffff);
+ state_add(M68705_PLD, "PLD", m_pl_data).mask(0xff);
+}
+
/****************************************************************************
* M68705Px family
@@ -613,6 +637,21 @@ m68705p_device::m68705p_device(
set_port_mask<3>(0xff); // Port D isn't present
}
+void m68705p_device::device_start()
+{
+ m68705_new_device::device_start();
+
+ add_port_latch_state<0>();
+ add_port_latch_state<1>();
+ add_port_latch_state<2>();
+ add_port_ddr_state<0>();
+ add_port_ddr_state<1>();
+ add_port_ddr_state<2>();
+ add_timer_state();
+ add_eprom_state();
+ state_add(M68705_MOR, "MOR", get_user_rom()[0x0784]).mask(0xff);
+}
+
offs_t m68705p_device::disasm_disassemble(
std::ostream &stream,
offs_t pc,
@@ -680,6 +719,24 @@ m68705u_device::m68705u_device(
{
}
+void m68705u_device::device_start()
+{
+ m68705_new_device::device_start();
+
+ add_port_latch_state<0>();
+ add_port_latch_state<1>();
+ add_port_latch_state<2>();
+ add_port_latch_state<3>();
+ add_port_ddr_state<0>();
+ add_port_ddr_state<1>();
+ add_port_ddr_state<2>();
+ add_timer_state();
+ add_eprom_state();
+ state_add(M68705_MOR, "MOR", get_user_rom()[0x0f38]).mask(0xff);
+
+ // TODO: MISC register
+}
+
offs_t m68705u_device::disasm_disassemble(
std::ostream &stream,
offs_t pc,
@@ -734,6 +791,13 @@ m68705r_device::m68705r_device(
{
}
+void m68705r_device::device_start()
+{
+ m68705u_device::device_start();
+
+ // TODO: ADC
+}
+
offs_t m68705r_device::disasm_disassemble(
std::ostream &stream,
offs_t pc,
@@ -801,7 +865,7 @@ tiny_rom_entry const *m68705r3_device::device_rom_region() const
u8 m68705r3_device::get_mask_options() const
{
- return get_user_rom()[0x0784] & 0xf7; // no SNM bit
+ return get_user_rom()[0x0f38] & 0xf7; // no SNM bit
}
@@ -821,5 +885,5 @@ tiny_rom_entry const *m68705u3_device::device_rom_region() const
u8 m68705u3_device::get_mask_options() const
{
- return get_user_rom()[0x0784] & 0xf7; // no SNM bit
+ return get_user_rom()[0x0f38] & 0xf7; // no SNM bit
}
diff --git a/src/devices/cpu/m6805/m68705.h b/src/devices/cpu/m6805/m68705.h
index e89517e5735..cd839a6cc54 100644
--- a/src/devices/cpu/m6805/m68705.h
+++ b/src/devices/cpu/m6805/m68705.h
@@ -94,6 +94,28 @@ public:
protected:
enum
{
+ M68705_LATCHA = 0x10,
+ M68705_LATCHB,
+ M68705_LATCHC,
+ M68705_LATCHD,
+ M68705_DDRA,
+ M68705_DDRB,
+ M68705_DDRC,
+ M68705_DDRD,
+
+ M68705_PS,
+ M68705_TDR,
+ M68705_TCR,
+
+ M68705_PCR,
+ M68705_PLD,
+ M68705_PLA,
+
+ M68705_MOR
+ };
+
+ enum
+ {
PORT_COUNT = 4
};
@@ -148,6 +170,11 @@ protected:
u8 *const get_user_rom() const { return &m_user_rom[0]; }
virtual u8 get_mask_options() const = 0;
+ template <std::size_t N> void add_port_latch_state();
+ template <std::size_t N> void add_port_ddr_state();
+ void add_timer_state();
+ void add_eprom_state();
+
private:
bool tcr_tir() const { return BIT(m_tcr, 7); }
bool tcr_tim() const { return BIT(m_tcr, 6); }
@@ -206,6 +233,8 @@ protected:
char const *shortname,
char const *source);
+ virtual void device_start() override;
+
virtual offs_t disasm_disassemble(
std::ostream &stream,
offs_t pc,
@@ -248,6 +277,8 @@ protected:
char const *shortname,
char const *source);
+ virtual void device_start() override;
+
virtual offs_t disasm_disassemble(
std::ostream &stream,
offs_t pc,
@@ -277,6 +308,8 @@ protected:
char const *shortname,
char const *source);
+ virtual void device_start() override;
+
virtual offs_t disasm_disassemble(
std::ostream &stream,
offs_t pc,
diff --git a/src/devices/machine/i8251.cpp b/src/devices/machine/i8251.cpp
index 2fc9ef798b6..6eac8fd3c52 100644
--- a/src/devices/machine/i8251.cpp
+++ b/src/devices/machine/i8251.cpp
@@ -24,7 +24,7 @@
#define VERBOSE 0
-#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+#define LOG(...) do { if (VERBOSE) logerror(__VA_ARGS__); } while (0)
//**************************************************************************
// DEVICE DEFINITIONS
@@ -33,12 +33,26 @@
const device_type I8251 = &device_creator<i8251_device>;
const device_type V53_SCU = &device_creator<v53_scu_device>;
+template class device_finder<i8251_device, false>;
+template class device_finder<i8251_device, true>;
+template class device_finder<v53_scu_device, false>;
+template class device_finder<v53_scu_device, true>;
+
+
//-------------------------------------------------
// i8251_device - constructor
//-------------------------------------------------
-i8251_device::i8251_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, uint32_t clock, const char *shortname)
- : device_t(mconfig, type, name, tag, owner, clock, shortname, __FILE__),
+i8251_device::i8251_device(
+ const machine_config &mconfig,
+ device_type type,
+ const char *name,
+ const char *tag,
+ device_t *owner,
+ uint32_t clock,
+ const char *shortname,
+ const char *source)
+ : device_t(mconfig, type, name, tag, owner, clock, shortname, source),
device_serial_interface(mconfig, *this),
m_txd_handler(*this),
m_dtr_handler(*this),
@@ -56,25 +70,12 @@ i8251_device::i8251_device(const machine_config &mconfig, device_type type, cons
}
i8251_device::i8251_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, I8251, "8251 USART", tag, owner, clock, "i8251", __FILE__),
- device_serial_interface(mconfig, *this),
- m_txd_handler(*this),
- m_dtr_handler(*this),
- m_rts_handler(*this),
- m_rxrdy_handler(*this),
- m_txrdy_handler(*this),
- m_txempty_handler(*this),
- m_syndet_handler(*this),
- m_cts(1),
- m_dsr(1),
- m_rxd(0),
- m_rxc(0),
- m_txc(0)
+ : i8251_device(mconfig, I8251, "8251 USART", tag, owner, clock, "i8251", __FILE__)
{
}
v53_scu_device::v53_scu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : i8251_device(mconfig, V53_SCU, "V53 SCU", tag, owner, clock, "v53_scu")
+ : i8251_device(mconfig, V53_SCU, "V53 SCU", tag, owner, clock, "v53_scu", __FILE__)
{
}
@@ -121,15 +122,11 @@ void i8251_device::device_start()
void i8251_device::update_rx_ready()
{
- int state;
-
- state = m_status & I8251_STATUS_RX_READY;
+ int state = m_status & I8251_STATUS_RX_READY;
- /* masked? */
- if ((m_command & (1<<2))==0)
- {
+ // masked?
+ if (!BIT(m_command, 2))
state = 0;
- }
m_rxrdy_handler(state != 0);
}
@@ -142,19 +139,22 @@ void i8251_device::update_rx_ready()
void i8251_device::receive_clock()
{
- m_rxc_count++;
-
- if (m_rxc_count == m_br_factor)
- m_rxc_count = 0;
- else
- return;
-
/* receive enable? */
- if (m_command & (1<<2))
+ if (BIT(m_command, 2))
{
+ const bool sync = is_receive_register_synchronized();
+ if (sync)
+ {
+ --m_rxc_count;
+ if (m_rxc_count)
+ return;
+ }
+
//logerror("I8251\n");
/* get bit received from other side and update receive register */
receive_register_update_bit(m_rxd);
+ if (is_receive_register_synchronized())
+ m_rxc_count = sync ? m_br_factor : (3 * m_br_factor / 2);
if (is_receive_register_full())
{
@@ -167,25 +167,24 @@ void i8251_device::receive_clock()
/*-------------------------------------------------
is_tx_enabled
-------------------------------------------------*/
-bool i8251_device::is_tx_enabled(void) const
+bool i8251_device::is_tx_enabled() const
{
- return BIT(m_command , 0) != 0 && m_cts == 0;
+ return BIT(m_command , 0) && !m_cts;
}
/*-------------------------------------------------
check_for_tx_start
-------------------------------------------------*/
-void i8251_device::check_for_tx_start(void)
+void i8251_device::check_for_tx_start()
{
- if (is_tx_enabled() && (m_status & (I8251_STATUS_TX_EMPTY | I8251_STATUS_TX_READY)) == I8251_STATUS_TX_EMPTY) {
- start_tx();
- }
+ if (is_tx_enabled() && (m_status & (I8251_STATUS_TX_EMPTY | I8251_STATUS_TX_READY)) == I8251_STATUS_TX_EMPTY)
+ start_tx();
}
/*-------------------------------------------------
start_tx
-------------------------------------------------*/
-void i8251_device::start_tx(void)
+void i8251_device::start_tx()
{
transmit_register_setup(m_tx_data);
m_status &= ~I8251_STATUS_TX_EMPTY;
@@ -199,23 +198,25 @@ void i8251_device::start_tx(void)
void i8251_device::transmit_clock()
{
m_txc_count++;
-
- if (m_txc_count == m_br_factor)
- m_txc_count = 0;
- else
+ if (m_txc_count != m_br_factor)
return;
- if (is_transmit_register_empty()) {
- if ((m_status & I8251_STATUS_TX_READY) == 0 && (is_tx_enabled() || (m_flags & I8251_DELAYED_TX_EN) != 0)) {
+ m_txc_count = 0;
+
+ if (is_transmit_register_empty())
+ {
+ if ((m_status & I8251_STATUS_TX_READY) == 0 && (is_tx_enabled() || (m_flags & I8251_DELAYED_TX_EN) != 0))
start_tx();
- } else {
+ else
m_status |= I8251_STATUS_TX_EMPTY;
- }
+
update_tx_ready();
update_tx_empty();
}
+
/* if diserial has bits to send, make them so */
- if (!is_transmit_register_empty()) {
+ if (!is_transmit_register_empty())
+ {
uint8_t data = transmit_register_get_data_bit();
m_txd_handler(data);
}
@@ -223,7 +224,7 @@ void i8251_device::transmit_clock()
#if 0
/* hunt mode? */
/* after each bit has been shifted in, it is compared against the current sync byte */
- if (m_command & (1<<7))
+ if (BIT(m_command, 7))
{
/* data matches sync byte? */
if (m_data == m_sync_bytes[m_sync_byte_offset])
@@ -236,7 +237,7 @@ void i8251_device::transmit_clock()
if (m_sync_byte_offset == m_sync_byte_count)
{
/* ent hunt mode */
- m_command &=~(1<<7);
+ m_command &= ~(1<<7);
}
}
else
@@ -295,7 +296,7 @@ void i8251_device::update_tx_empty()
void i8251_device::device_reset()
{
- LOG(("I8251: Reset\n"));
+ LOG("I8251: Reset\n");
/* what is the default setup when the 8251 has been reset??? */
@@ -342,52 +343,34 @@ void i8251_device::device_reset()
WRITE8_MEMBER(i8251_device::command_w)
{
/* command */
- LOG(("I8251: Command byte\n"));
+ LOG("I8251: Command byte\n");
m_command = data;
- LOG(("Command byte: %02x\n", data));
+ LOG("Command byte: %02x\n", data);
- if (data & (1<<7))
- {
- LOG(("hunt mode\n"));
- }
+ if (BIT(data, 7))
+ LOG("hunt mode\n");
- if (data & (1<<5))
- {
- LOG(("/rts set to 0\n"));
- }
+ if (BIT(data, 5))
+ LOG("/rts set to 0\n");
else
- {
- LOG(("/rts set to 1\n"));
- }
+ LOG("/rts set to 1\n");
- if (data & (1<<2))
- {
- LOG(("receive enable\n"));
- }
+ if (BIT(data, 2))
+ LOG("receive enable\n");
else
- {
- LOG(("receive disable\n"));
- }
+ LOG("receive disable\n");
- if (data & (1<<1))
- {
- LOG(("/dtr set to 0\n"));
- }
+ if (BIT(data, 1))
+ LOG("/dtr set to 0\n");
else
- {
- LOG(("/dtr set to 1\n"));
- }
+ LOG("/dtr set to 1\n");
- if (data & (1<<0))
- {
- LOG(("transmit enable\n"));
- }
+ if (BIT(data, 0))
+ LOG("transmit enable\n");
else
- {
- LOG(("transmit disable\n"));
- }
+ LOG("transmit disable\n");
/* bit 7:
@@ -419,12 +402,10 @@ WRITE8_MEMBER(i8251_device::command_w)
m_rts_handler(!BIT(data, 5));
m_dtr_handler(!BIT(data, 1));
- if (data & (1<<4))
- {
+ if (BIT(data, 4))
m_status &= ~(I8251_STATUS_PARITY_ERROR | I8251_STATUS_OVERRUN_ERROR | I8251_STATUS_FRAMING_ERROR);
- }
- if (data & (1<<6))
+ if (BIT(data, 6))
{
// datasheet says "returns to mode format", not
// completely resets the chip. behavior of DEC Rainbow
@@ -432,15 +413,15 @@ WRITE8_MEMBER(i8251_device::command_w)
m_flags |= I8251_EXPECTING_MODE;
}
- check_for_tx_start();
+ check_for_tx_start();
update_rx_ready();
update_tx_ready();
- update_tx_empty();
+ update_tx_empty();
}
WRITE8_MEMBER(i8251_device::mode_w)
{
- LOG(("I8251: Mode byte\n"));
+ LOG("I8251: Mode byte = %X\n", data);
m_mode_byte = data;
@@ -472,60 +453,55 @@ WRITE8_MEMBER(i8251_device::mode_w)
3 = x64
*/
- LOG(("I8251: Asynchronous operation\n"));
+ LOG("I8251: Asynchronous operation\n");
- LOG(("Character length: %d\n", (((data >> 2) & 0x03) + 5)));
+ const int data_bits_count = ((data >> 2) & 0x03) + 5;
+ LOG("Character length: %d\n", data_bits_count);
parity_t parity;
-
- if (data & (1 << 4))
+ if (BIT(data, 4))
{
- LOG(("enable parity checking\n"));
-
- if (data & (1 << 5))
+ if (BIT(data, 5))
{
- LOG(("even parity\n"));
+ LOG("enable parity checking (even parity)\n");
parity = PARITY_EVEN;
}
else
{
- LOG(("odd parity\n"));
+ LOG("enable parity checking (odd parity)\n");
parity = PARITY_ODD;
}
}
else
{
- LOG(("parity check disabled\n"));
+ LOG("parity check disabled\n");
parity = PARITY_NONE;
}
stop_bits_t stop_bits;
-
switch ((data >> 6) & 0x03)
{
case 0:
- default:
stop_bits = STOP_BITS_0;
- LOG(("stop bit: inhibit\n"));
+ LOG("stop bit: inhibit\n");
break;
case 1:
stop_bits = STOP_BITS_1;
- LOG(("stop bit: 1 bit\n"));
+ LOG("stop bit: 1 bit\n");
break;
case 2:
stop_bits = STOP_BITS_1_5;
- LOG(("stop bit: 1.5 bits\n"));
+ LOG("stop bit: 1.5 bits\n");
break;
case 3:
stop_bits = STOP_BITS_2;
- LOG(("stop bit: 2 bits\n"));
+ LOG("stop bit: 2 bits\n");
break;
}
- int data_bits_count = ((data >> 2) & 0x03) + 5;
set_data_frame(1, data_bits_count, parity, stop_bits);
receive_register_reset();
@@ -537,13 +513,13 @@ WRITE8_MEMBER(i8251_device::mode_w)
case 3: m_br_factor = 64; break;
}
- m_rxc_count = m_txc_count = 0;
+ m_txc_count = 0;
#if 0
/* data bits */
m_receive_char_length = (((data >> 2) & 0x03) + 5);
- if (data & (1 << 4))
+ if (BIT(data, 4))
{
/* parity */
m_receive_char_length++;
@@ -580,7 +556,7 @@ WRITE8_MEMBER(i8251_device::mode_w)
3 = 8 bits
bit 1,0 = 0
*/
- LOG(("I8251: Synchronous operation\n"));
+ LOG("I8251: Synchronous operation\n");
/* setup for sync byte(s) */
m_flags |= I8251_EXPECTING_SYNC_BYTE;
@@ -603,9 +579,9 @@ WRITE8_MEMBER(i8251_device::control_w)
{
if (m_flags & I8251_EXPECTING_SYNC_BYTE)
{
- LOG(("I8251: Sync byte\n"));
+ LOG("I8251: Sync byte\n");
- LOG(("Sync byte: %02x\n", data));
+ LOG("Sync byte: %02x\n", data);
/* store sync byte written */
m_sync_bytes[m_sync_byte_offset] = data;
m_sync_byte_offset++;
@@ -639,7 +615,7 @@ READ8_MEMBER(i8251_device::status_r)
{
uint8_t status = (m_dsr << 7) | m_status;
- LOG(("status: %02x\n", status));
+ LOG("status: %02x\n", status);
return status;
}
@@ -653,7 +629,7 @@ WRITE8_MEMBER(i8251_device::data_w)
{
m_tx_data = data;
- LOG(("data_w %02x\n" , data));
+ LOG("data_w %02x\n" , data);
/* writing clears */
m_status &=~I8251_STATUS_TX_READY;
@@ -687,9 +663,8 @@ void i8251_device::receive_character(uint8_t ch)
/* char has not been read and another has arrived! */
if (m_status & I8251_STATUS_RX_READY)
- {
m_status |= I8251_STATUS_OVERRUN_ERROR;
- }
+
m_status |= I8251_STATUS_RX_READY;
update_rx_ready();
@@ -703,7 +678,7 @@ void i8251_device::receive_character(uint8_t ch)
READ8_MEMBER(i8251_device::data_r)
{
- LOG(("read data: %02x, STATUS=%02x\n",m_rx_data,m_status));
+ LOG("read data: %02x, STATUS=%02x\n",m_rx_data,m_status);
/* reading clears */
m_status &= ~I8251_STATUS_RX_READY;
@@ -728,9 +703,9 @@ WRITE_LINE_MEMBER(i8251_device::write_cts)
{
m_cts = state;
- check_for_tx_start();
- update_tx_ready();
- update_tx_empty();
+ check_for_tx_start();
+ update_tx_ready();
+ update_tx_empty();
}
WRITE_LINE_MEMBER(i8251_device::write_dsr)
diff --git a/src/devices/machine/i8251.h b/src/devices/machine/i8251.h
index a556851beb7..82659caed11 100644
--- a/src/devices/machine/i8251.h
+++ b/src/devices/machine/i8251.h
@@ -8,8 +8,8 @@
*********************************************************************/
-#ifndef __I8251_H__
-#define __I8251_H__
+#ifndef MAME_DEVICES_MACHINE_I8251_H
+#define MAME_DEVICES_MACHINE_I8251_H
//**************************************************************************
@@ -42,7 +42,6 @@ class i8251_device : public device_t,
{
public:
// construction/destruction
- i8251_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, uint32_t clock, const char *shortname);
i8251_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// static configuration helpers
@@ -82,6 +81,16 @@ public:
};
protected:
+ i8251_device(
+ const machine_config &mconfig,
+ device_type type,
+ const char *name,
+ const char *tag,
+ device_t *owner,
+ uint32_t clock,
+ const char *shortname,
+ const char *source);
+
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
@@ -92,9 +101,9 @@ protected:
void update_tx_empty();
void transmit_clock();
void receive_clock();
- bool is_tx_enabled(void) const;
- void check_for_tx_start(void);
- void start_tx(void);
+ bool is_tx_enabled() const;
+ void check_for_tx_start();
+ void start_tx();
enum
@@ -155,5 +164,10 @@ public:
extern const device_type I8251;
extern const device_type V53_SCU;
+extern template class device_finder<i8251_device, false>;
+extern template class device_finder<i8251_device, true>;
+extern template class device_finder<v53_scu_device, false>;
+extern template class device_finder<v53_scu_device, true>;
+
-#endif /* __I8251_H__ */
+#endif // MAME_DEVICES_MACHINE_I8251_H
diff --git a/src/mame/drivers/gladiatr.cpp b/src/mame/drivers/gladiatr.cpp
index 828fa447413..7b915a13739 100644
--- a/src/mame/drivers/gladiatr.cpp
+++ b/src/mame/drivers/gladiatr.cpp
@@ -270,22 +270,6 @@ WRITE8_MEMBER(gladiatr_state::gladiatr_irq_patch_w)
WRITE_LINE_MEMBER(gladiatr_state::tclk_w)
{
m_tclk_val = state != 0;
-
- // these are actually edge-triggered, but MAME only supports polled inputs
-
- u8 const new_in0_val(m_in0->read());
- if (BIT(~new_in0_val & (new_in0_val ^ m_in0_val), 5))
- m_cctl_p1 = (m_cctl_p1 & 0xfc) | BIT(~new_in0_val, 5) | (BIT(~new_in0_val, 5) << 1);
- else
- m_cctl_p1 = (m_cctl_p1 & 0xfe) | BIT(~new_in0_val, 5);
- m_in0_val = new_in0_val;
-
- u8 const new_in1_val(m_in0->read());
- if (BIT(~new_in1_val & (new_in1_val ^ m_in1_val), 5))
- m_cctl_p2 = (m_cctl_p2 & 0xfc) | BIT(~new_in1_val, 5) | (BIT(~new_in1_val, 5) << 1);
- else
- m_cctl_p2 = (m_cctl_p2 & 0xfe) | BIT(~new_in1_val, 5);
- m_in1_val = new_in1_val;
}
READ8_MEMBER(gladiatr_state::cctl_p1_r)
@@ -370,6 +354,33 @@ READ8_MEMBER(gladiatr_state::csnd_p2_r)
}
+INPUT_CHANGED_MEMBER(gladiatr_state::p1_s1)
+{
+ // P11 gets the value of 1P-S2 at the moment 1P-S1 was pressed
+ if (oldval && !newval)
+ m_cctl_p1 = (m_cctl_p1 & 0xfd) | (BIT(m_cctl_p1, 0) << 1);
+}
+
+INPUT_CHANGED_MEMBER(gladiatr_state::p1_s2)
+{
+ // P10 is high when 1P-S2 is pressed
+ m_cctl_p1 = (m_cctl_p1 & 0xfe) | (newval ? 0x00 : 0x01);
+}
+
+INPUT_CHANGED_MEMBER(gladiatr_state::p2_s1)
+{
+ // P21 gets the value of 2P-S2 at the moment 2P-S1 was pressed
+ if (oldval && !newval)
+ m_cctl_p2 = (m_cctl_p2 & 0xfd) | (BIT(m_cctl_p2, 0) << 1);
+}
+
+INPUT_CHANGED_MEMBER(gladiatr_state::p2_s2)
+{
+ // P20 is high when 2P-S2 is pressed
+ m_cctl_p2 = (m_cctl_p2 & 0xfe) | (newval ? 0x00 : 0x01);
+}
+
+
READ8_MEMBER(ppking_state::ppking_f1_r)
{
@@ -622,8 +633,8 @@ static INPUT_PORTS_START( gladiatr )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_8WAY
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_8WAY
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_CHANGED_MEMBER(DEVICE_SELF, gladiatr_state, p1_s1, 0)
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_CHANGED_MEMBER(DEVICE_SELF, gladiatr_state, p2_s2, 0)
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_START1 )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START2 )
@@ -632,8 +643,8 @@ static INPUT_PORTS_START( gladiatr )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_COCKTAIL
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_COCKTAIL
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_COCKTAIL
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_COCKTAIL
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_COCKTAIL
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_COCKTAIL PORT_CHANGED_MEMBER(DEVICE_SELF, gladiatr_state, p2_s1, 0)
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_COCKTAIL PORT_CHANGED_MEMBER(DEVICE_SELF, gladiatr_state, p2_s2, 0)
PORT_BIT( 0xc0, IP_ACTIVE_LOW, IPT_UNUSED ) // coin counter outputs
PORT_START("IN2") // cctl p1
@@ -1143,16 +1154,12 @@ DRIVER_INIT_MEMBER(gladiatr_state,gladiatr)
membank("bank2")->set_entry(0);
m_tclk_val = false;
- m_in0_val = 0xff;
- m_in1_val = 0xff;
m_cctl_p1 = 0xff;
m_cctl_p2 = 0xff;
m_ucpu_p1 = 0xff;
m_csnd_p1 = 0xff;
save_item(NAME(m_tclk_val));
- save_item(NAME(m_in0_val));
- save_item(NAME(m_in1_val));
save_item(NAME(m_cctl_p1));
save_item(NAME(m_cctl_p2));
save_item(NAME(m_ucpu_p1));
diff --git a/src/mame/drivers/osborne1.cpp b/src/mame/drivers/osborne1.cpp
index f94df70c8b5..99b68229b14 100644
--- a/src/mame/drivers/osborne1.cpp
+++ b/src/mame/drivers/osborne1.cpp
@@ -180,7 +180,7 @@ static INPUT_PORTS_START( osborne1 )
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_START("RESET")
- PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("RESET") PORT_CODE(KEYCODE_F12)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("RESET") PORT_CODE(KEYCODE_F12) PORT_CHANGED_MEMBER(DEVICE_SELF, osborne1_state, reset_key, 0)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED)
diff --git a/src/mame/drivers/pitnrun.cpp b/src/mame/drivers/pitnrun.cpp
index 0147a3716a2..80d20ddf5b9 100644
--- a/src/mame/drivers/pitnrun.cpp
+++ b/src/mame/drivers/pitnrun.cpp
@@ -66,22 +66,25 @@ K1000233A
*/
#include "emu.h"
-#include "cpu/z80/z80.h"
+#include "includes/pitnrun.h"
+
#include "cpu/m6805/m68705.h"
+#include "cpu/z80/z80.h"
+
#include "machine/gen_latch.h"
#include "machine/watchdog.h"
+
#include "sound/ay8910.h"
-#include "includes/pitnrun.h"
INTERRUPT_GEN_MEMBER(pitnrun_state::nmi_source)
{
- if(m_nmi) device.execute().set_input_line(INPUT_LINE_NMI, PULSE_LINE);
+ if (m_nmi) device.execute().set_input_line(INPUT_LINE_NMI, PULSE_LINE);
}
WRITE8_MEMBER(pitnrun_state::nmi_enable_w)
{
- m_nmi = data & 1;
+ m_nmi = data & 1;
}
WRITE8_MEMBER(pitnrun_state::hflip_w)
@@ -136,15 +139,6 @@ static ADDRESS_MAP_START( pitnrun_sound_io_map, AS_IO, 8, pitnrun_state )
AM_RANGE(0x98, 0x98) AM_WRITENOP
ADDRESS_MAP_END
-static ADDRESS_MAP_START( pitnrun_mcu_map, AS_PROGRAM, 8, pitnrun_state )
- ADDRESS_MAP_GLOBAL_MASK(0x7ff)
- AM_RANGE(0x0000, 0x0000) AM_READWRITE(m68705_portA_r,m68705_portA_w)
- AM_RANGE(0x0001, 0x0001) AM_READWRITE(m68705_portB_r,m68705_portB_w)
- AM_RANGE(0x0002, 0x0002) AM_READ(m68705_portC_r)
- AM_RANGE(0x0003, 0x007f) AM_RAM
- AM_RANGE(0x0080, 0x07ff) AM_ROM
-ADDRESS_MAP_END
-
static INPUT_PORTS_START( pitnrun )
PORT_START("SYSTEM")
@@ -231,8 +225,12 @@ static MACHINE_CONFIG_START( pitnrun, pitnrun_state )
MCFG_CPU_IO_MAP(pitnrun_sound_io_map)
MCFG_CPU_VBLANK_INT_DRIVER("screen", pitnrun_state, irq0_line_hold)
- MCFG_CPU_ADD("mcu", M68705,XTAL_18_432MHz/6) /* verified on pcb */
- MCFG_CPU_PROGRAM_MAP(pitnrun_mcu_map)
+ MCFG_CPU_ADD("mcu", M68705P5, XTAL_18_432MHz/6) /* verified on pcb */
+ MCFG_M68705_PORTA_R_CB(READ8(pitnrun_state, m68705_portA_r))
+ MCFG_M68705_PORTB_R_CB(READ8(pitnrun_state, m68705_portB_r))
+ MCFG_M68705_PORTC_R_CB(READ8(pitnrun_state, m68705_portC_r))
+ MCFG_M68705_PORTA_W_CB(WRITE8(pitnrun_state, m68705_portA_w))
+ MCFG_M68705_PORTB_W_CB(WRITE8(pitnrun_state, m68705_portB_w))
MCFG_WATCHDOG_ADD("watchdog")
diff --git a/src/mame/drivers/zorba.cpp b/src/mame/drivers/zorba.cpp
index cc1faf0c449..2efeeed1112 100644
--- a/src/mame/drivers/zorba.cpp
+++ b/src/mame/drivers/zorba.cpp
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:Robbbert
+// copyright-holders:Robbbert, Vas Crabb
/************************************************************************************************************
Telcon Industries/Modular Micros/Gemini Electronics Zorba
@@ -36,6 +36,10 @@ The startup screen varies across each company:
- Modular Micros: "ZORBA" graphical logo with "MODULAR MICROS, INC." below in normal text
- Gemini: "GEMINI ZORBA" graphical logo
+Strangely, the Zorba configures its keyboard UART for 8N2 but the keyboard we're emulating sends 8N1.
+If you type too fast or hold down a key until it repeats, characters will be dropped/corrupted. It's
+possible we have a dump of a different CP/M-compatible keyboard, not the one supplied with the Zorba.
+
Status:
- Boots up, and the keyboard works
@@ -44,8 +48,6 @@ ToDo:
- Add masking feature (only used for the UARTs)
- Connect devices to the above hardware
- Fix the display
-- Connect the PIT to the UARTs
-- Replace the ascii keyboard with the real one, if possible
- Dump Telcon and Gemini BIOSes
- Emulate the Co-Power-88 expansion (allows PC-DOS, CP/M-86, etc. to be used)
- Probably lots of other things
@@ -53,105 +55,44 @@ ToDo:
*************************************************************************************************************/
-
#include "emu.h"
+#include "includes/zorba.h"
+
+#include "machine/zorbakbd.h"
+
+#include "bus/centronics/ctronics.h"
+#include "bus/rs232/rs232.h"
+
#include "cpu/z80/z80.h"
#include "cpu/m6805/m68705.h"
-#include "machine/i8251.h"
-#include "machine/6821pia.h"
-#include "machine/z80dma.h"
+
+#include "machine/input_merger.h"
+#include "machine/latch.h"
#include "machine/pit8253.h"
-#include "video/i8275.h"
-#include "sound/beep.h"
-#include "machine/keyboard.h"
-#include "machine/wd_fdc.h"
+
#include "softlist.h"
-class zorba_state : public driver_device
-{
-public:
- zorba_state(const machine_config &mconfig, device_type type, const char *tag)
- : driver_device(mconfig, type, tag)
- , m_palette(*this, "palette")
- , m_maincpu(*this, "maincpu")
- , m_beep(*this, "beeper")
- , m_dma(*this, "dma")
- , m_u0(*this, "uart0")
- , m_u1(*this, "uart1")
- , m_u2(*this, "uart2")
- , m_pia0(*this, "pia0")
- , m_pia1(*this, "pia1")
- , m_crtc(*this, "crtc")
- , m_fdc (*this, "fdc")
- , m_floppy0(*this, "fdc:0")
- , m_floppy1(*this, "fdc:1")
- {}
-
-public:
- const uint8_t *m_p_chargen;
- DECLARE_DRIVER_INIT(zorba);
- DECLARE_MACHINE_RESET(zorba);
- DECLARE_READ8_MEMBER(ram_r);
- DECLARE_WRITE8_MEMBER(ram_w);
- DECLARE_READ8_MEMBER(rom_r);
- DECLARE_WRITE8_MEMBER(rom_w);
- DECLARE_WRITE8_MEMBER(intmask_w);
- DECLARE_WRITE_LINE_MEMBER(busreq_w);
- DECLARE_READ8_MEMBER(memory_read_byte);
- DECLARE_WRITE8_MEMBER(memory_write_byte);
- DECLARE_READ8_MEMBER(io_read_byte);
- DECLARE_WRITE8_MEMBER(io_write_byte);
- DECLARE_WRITE8_MEMBER(pia0_porta_w);
- DECLARE_WRITE8_MEMBER(kbd_put);
- DECLARE_READ8_MEMBER(keyboard_r);
- DECLARE_WRITE_LINE_MEMBER(irq0_w);
- DECLARE_WRITE_LINE_MEMBER(fdc_drq_w);
- DECLARE_WRITE_LINE_MEMBER(fdc_intrq_w);
- I8275_DRAW_CHARACTER_MEMBER(zorba_update_chr);
- required_device<palette_device> m_palette;
-
-private:
- uint8_t m_term_data;
- uint8_t m_fdc_rq;
- required_device<cpu_device> m_maincpu;
- required_device<beep_device> m_beep;
- required_device<z80dma_device> m_dma;
- required_device<i8251_device> m_u0;
- required_device<i8251_device> m_u1;
- required_device<i8251_device> m_u2;
- required_device<pia6821_device> m_pia0;
- required_device<pia6821_device> m_pia1;
- required_device<i8275_device> m_crtc;
- required_device<fd1793_t> m_fdc;
- required_device<floppy_connector> m_floppy0;
- required_device<floppy_connector> m_floppy1;
-};
+namespace {
-static ADDRESS_MAP_START( zorba_mem, AS_PROGRAM, 8, zorba_state )
+ADDRESS_MAP_START( zorba_mem, AS_PROGRAM, 8, zorba_state )
AM_RANGE( 0x0000, 0x3fff ) AM_READ_BANK("bankr0") AM_WRITE_BANK("bankw0")
AM_RANGE( 0x4000, 0xffff ) AM_RAM
ADDRESS_MAP_END
-static ADDRESS_MAP_START( zorba_kbdmem, AS_PROGRAM, 8, zorba_state )
- ADDRESS_MAP_GLOBAL_MASK(0x7ff)
- AM_RANGE( 0x000, 0x07f ) AM_RAM // internal RAM
- AM_RANGE( 0x080, 0x7ff ) AM_ROM // internal EPROM
-ADDRESS_MAP_END
-static ADDRESS_MAP_START( zorba_io, AS_IO, 8, zorba_state )
+ADDRESS_MAP_START( zorba_io, AS_IO, 8, zorba_state )
ADDRESS_MAP_GLOBAL_MASK(0xff)
AM_RANGE(0x00, 0x03) AM_DEVREADWRITE("pit", pit8254_device, read, write)
- AM_RANGE(0x04, 0x04) AM_READWRITE(rom_r,rom_w)
- AM_RANGE(0x05, 0x05) AM_READWRITE(ram_r,ram_w)
+ AM_RANGE(0x04, 0x04) AM_READWRITE(rom_r, rom_w)
+ AM_RANGE(0x05, 0x05) AM_READWRITE(ram_r, ram_w)
AM_RANGE(0x10, 0x11) AM_DEVREADWRITE("crtc", i8275_device, read, write)
AM_RANGE(0x20, 0x20) AM_DEVREADWRITE("uart0", i8251_device, data_r, data_w)
AM_RANGE(0x21, 0x21) AM_DEVREADWRITE("uart0", i8251_device, status_r, control_w)
AM_RANGE(0x22, 0x22) AM_DEVREADWRITE("uart1", i8251_device, data_r, data_w)
AM_RANGE(0x23, 0x23) AM_DEVREADWRITE("uart1", i8251_device, status_r, control_w)
- //AM_RANGE(0x24, 0x24) AM_DEVREADWRITE("uart2", i8251_device, data_r, data_w)
- //AM_RANGE(0x25, 0x25) AM_DEVREADWRITE("uart2", i8251_device, status_r, control_w)
- AM_RANGE(0x24, 0x25) AM_READ(keyboard_r) AM_WRITENOP
+ AM_RANGE(0x24, 0x24) AM_DEVREADWRITE("uart2", i8251_device, data_r, data_w)
+ AM_RANGE(0x25, 0x25) AM_DEVREADWRITE("uart2", i8251_device, status_r, control_w)
AM_RANGE(0x26, 0x26) AM_WRITE(intmask_w)
AM_RANGE(0x30, 0x30) AM_DEVREADWRITE("dma", z80dma_device, read, write)
AM_RANGE(0x40, 0x43) AM_DEVREADWRITE("fdc", fd1793_t, read, write)
@@ -159,83 +100,294 @@ static ADDRESS_MAP_START( zorba_io, AS_IO, 8, zorba_state )
AM_RANGE(0x60, 0x63) AM_DEVREADWRITE("pia1", pia6821_device, read, write)
ADDRESS_MAP_END
+
+INPUT_PORTS_START( zorba )
+ PORT_START("CNF")
+ PORT_CONFNAME(0x01, 0x00, "Parallel Printer") PORT_CHANGED_MEMBER(DEVICE_SELF, zorba_state, printer_type, 0)
+ PORT_CONFSETTING(0x00, "Centronics")
+ PORT_CONFSETTING(0x01, "Prowriter")
+INPUT_PORTS_END
+
+
+SLOT_INTERFACE_START( zorba_floppies )
+ SLOT_INTERFACE( "525dd", FLOPPY_525_DD )
+SLOT_INTERFACE_END
+
+
+// F4 Character Displayer
+const gfx_layout u5_charlayout =
+{
+ 8, 11, // 8 x 11 characters
+ 256, // 256 characters
+ 1, // 1 bits per pixel
+ { 0 }, // no bitplanes
+ /* x offsets */
+ { 0, 1, 2, 3, 4, 5, 6, 7 },
+ /* y offsets */
+ { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, 8*8, 9*8, 10*8 },
+ 8*16 // every char takes 16 bytes
+};
+
+GFXDECODE_START( zorba )
+ GFXDECODE_ENTRY( "chargen", 0x0000, u5_charlayout, 0, 1 )
+GFXDECODE_END
+
+
+MACHINE_CONFIG_START( zorba, zorba_state )
+ // basic machine hardware
+ MCFG_CPU_ADD("maincpu", Z80, XTAL_24MHz / 6)
+ MCFG_CPU_PROGRAM_MAP(zorba_mem)
+ MCFG_CPU_IO_MAP(zorba_io)
+ MCFG_MACHINE_RESET_OVERRIDE(zorba_state, zorba)
+
+ /* video hardware */
+ MCFG_SCREEN_ADD_MONOCHROME("screen", RASTER, rgb_t::green())
+ MCFG_SCREEN_REFRESH_RATE(50)
+ MCFG_SCREEN_UPDATE_DEVICE("crtc", i8275_device, screen_update)
+ MCFG_GFXDECODE_ADD("gfxdecode", "palette", zorba)
+ MCFG_PALETTE_ADD_MONOCHROME_HIGHLIGHT("palette")
+
+ /* sound hardware */
+ MCFG_SPEAKER_STANDARD_MONO("mono")
+ MCFG_SOUND_ADD("beeper", BEEP, 800) // should be horizontal frequency / 16, so depends on CRTC parameters
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
+
+ MCFG_INPUT_MERGER_ACTIVE_HIGH("irq0")
+ MCFG_INPUT_MERGER_OUTPUT_HANDLER(WRITELINE(zorba_state, irq_w<0>))
+ MCFG_INPUT_MERGER_ACTIVE_HIGH("irq1")
+ MCFG_INPUT_MERGER_OUTPUT_HANDLER(WRITELINE(zorba_state, irq_w<1>))
+ MCFG_INPUT_MERGER_ACTIVE_HIGH("irq2")
+ MCFG_INPUT_MERGER_OUTPUT_HANDLER(WRITELINE(zorba_state, irq_w<2>))
+
+ /* devices */
+ MCFG_DEVICE_ADD("dma", Z80DMA, XTAL_24MHz/6)
+ // busack on cpu connects to bai pin
+ MCFG_Z80DMA_OUT_BUSREQ_CB(WRITELINE(zorba_state, busreq_w)) //connects to busreq on cpu
+ MCFG_Z80DMA_OUT_INT_CB(DEVWRITELINE("irq0", input_merger_active_high_device, in0_w))
+ //ba0 - not connected
+ MCFG_Z80DMA_IN_MREQ_CB(READ8(zorba_state, memory_read_byte))
+ MCFG_Z80DMA_OUT_MREQ_CB(WRITE8(zorba_state, memory_write_byte))
+ MCFG_Z80DMA_IN_IORQ_CB(READ8(zorba_state, io_read_byte))
+ MCFG_Z80DMA_OUT_IORQ_CB(WRITE8(zorba_state, io_write_byte))
+
+ MCFG_DEVICE_ADD("uart0", I8251, 0) // U32 COM port J2
+ MCFG_I8251_TXD_HANDLER(DEVWRITELINE("rs232", rs232_port_device, write_txd)) // TODO: this line has a LED attached
+ MCFG_I8251_DTR_HANDLER(DEVWRITELINE("rs232", rs232_port_device, write_dtr))
+ MCFG_I8251_RTS_HANDLER(DEVWRITELINE("rs232", rs232_port_device, write_rts))
+ MCFG_I8251_RXRDY_HANDLER(WRITELINE(zorba_state, tx_rx_rdy_w<1>))
+ MCFG_I8251_TXRDY_HANDLER(WRITELINE(zorba_state, tx_rx_rdy_w<0>))
+
+ MCFG_DEVICE_ADD("uart1", I8251, 0) // U31 printer port J3
+ MCFG_I8251_TXD_HANDLER(DEVWRITELINE("serprn", rs232_port_device, write_txd))
+ MCFG_I8251_RTS_HANDLER(DEVWRITELINE("serprn", rs232_port_device, write_rts))
+ MCFG_I8251_RXRDY_HANDLER(WRITELINE(zorba_state, tx_rx_rdy_w<3>))
+ MCFG_I8251_TXRDY_HANDLER(WRITELINE(zorba_state, tx_rx_rdy_w<2>))
+
+ MCFG_DEVICE_ADD("uart2", I8251, 0) // U30 serial keyboard J6
+ MCFG_I8251_TXD_HANDLER(DEVWRITELINE("keyboard", zorba_keyboard_device, txd_w))
+ MCFG_I8251_RXRDY_HANDLER(WRITELINE(zorba_state, tx_rx_rdy_w<5>))
+ MCFG_I8251_TXRDY_HANDLER(WRITELINE(zorba_state, tx_rx_rdy_w<4>))
+
+ // port A - disk select etc, beeper
+ // port B - parallel interface
+ MCFG_DEVICE_ADD("pia0", PIA6821, 0)
+ MCFG_PIA_WRITEPA_HANDLER(WRITE8(zorba_state, pia0_porta_w))
+ MCFG_PIA_WRITEPB_HANDLER(DEVWRITE8("parprndata", output_latch_device, write))
+ MCFG_PIA_CB2_HANDLER(DEVWRITELINE("parprn", centronics_device, write_strobe))
+
+ // IEEE488 interface
+ MCFG_DEVICE_ADD("pia1", PIA6821, 0)
+ MCFG_PIA_READPA_HANDLER(DEVREAD8(IEEE488_TAG, ieee488_device, dio_r)) // TODO: gated with PB1
+ MCFG_PIA_WRITEPA_HANDLER(DEVWRITE8(IEEE488_TAG, ieee488_device, dio_w)) // TODO: gated with PB1
+ MCFG_PIA_READPB_HANDLER(READ8(zorba_state, pia1_portb_r))
+ MCFG_PIA_WRITEPB_HANDLER(WRITE8(zorba_state, pia1_portb_w))
+ MCFG_PIA_CA2_HANDLER(DEVWRITELINE(IEEE488_TAG, ieee488_device, ifc_w))
+ MCFG_PIA_CB2_HANDLER(DEVWRITELINE(IEEE488_TAG, ieee488_device, ren_w))
+ MCFG_PIA_IRQA_HANDLER(DEVWRITELINE("irq1", input_merger_active_high_device, in0_w))
+ MCFG_PIA_IRQB_HANDLER(DEVWRITELINE("irq1", input_merger_active_high_device, in1_w))
+
+ // PIT
+ MCFG_DEVICE_ADD("pit", PIT8254, 0)
+ MCFG_PIT8253_CLK0(XTAL_24MHz / 3)
+ MCFG_PIT8253_CLK1(XTAL_24MHz / 3)
+ MCFG_PIT8253_CLK2(XTAL_24MHz / 3)
+ MCFG_PIT8253_OUT0_HANDLER(WRITELINE(zorba_state, br1_w))
+ MCFG_PIT8253_OUT1_HANDLER(DEVWRITELINE("uart1", i8251_device, write_txc))
+ MCFG_DEVCB_CHAIN_OUTPUT(DEVWRITELINE("uart1", i8251_device, write_rxc))
+ MCFG_PIT8253_OUT2_HANDLER(DEVWRITELINE("uart2", i8251_device, write_txc))
+ MCFG_DEVCB_CHAIN_OUTPUT(DEVWRITELINE("uart2", i8251_device, write_rxc))
+
+ // CRTC
+ MCFG_DEVICE_ADD("crtc", I8275, XTAL_14_31818MHz/7)
+ MCFG_I8275_CHARACTER_WIDTH(8)
+ MCFG_I8275_DRAW_CHARACTER_CALLBACK_OWNER(zorba_state, zorba_update_chr)
+ MCFG_I8275_DRQ_CALLBACK(DEVWRITELINE("dma", z80dma_device, rdy_w))
+ MCFG_I8275_IRQ_CALLBACK(DEVWRITELINE("irq0", input_merger_active_high_device, in1_w))
+
+ // Floppies
+ MCFG_FD1793_ADD("fdc", XTAL_24MHz / 24)
+ MCFG_WD_FDC_INTRQ_CALLBACK(DEVWRITELINE("irq2", input_merger_active_high_device, in0_w))
+ MCFG_WD_FDC_DRQ_CALLBACK(DEVWRITELINE("irq2", input_merger_active_high_device, in1_w))
+ MCFG_FLOPPY_DRIVE_ADD("fdc:0", zorba_floppies, "525dd", floppy_image_device::default_floppy_formats)
+ MCFG_FLOPPY_DRIVE_SOUND(true)
+ MCFG_FLOPPY_DRIVE_ADD("fdc:1", zorba_floppies, "525dd", floppy_image_device::default_floppy_formats)
+ MCFG_FLOPPY_DRIVE_SOUND(true)
+
+ // J1 IEEE-488
+ MCFG_IEEE488_BUS_ADD()
+ MCFG_IEEE488_SRQ_CALLBACK(DEVWRITELINE("pia1", pia6821_device, ca2_w)) // TODO: gated with PB1 from PIA
+
+ // J2 EIA RS232/internal modem
+ // TODO: this has additional lines compared to a regular RS232 port (TxC in, RxC in, RxC out, speaker in, power)
+ MCFG_RS232_PORT_ADD("rs232", default_rs232_devices, nullptr)
+ MCFG_RS232_RXD_HANDLER(DEVWRITELINE("uart0", i8251_device, write_rxd)) // TODO: this line has a LED attached
+ MCFG_RS232_CTS_HANDLER(DEVWRITELINE("uart0", i8251_device, write_cts)) // TODO: this line has a LED attached
+ MCFG_RS232_DSR_HANDLER(DEVWRITELINE("uart0", i8251_device, write_dsr))
+
+ // J3 Parallel printer
+ MCFG_CENTRONICS_OUTPUT_LATCH_ADD("parprndata", "parprn")
+ MCFG_CENTRONICS_ADD("parprn", centronics_devices, "printer")
+ MCFG_CENTRONICS_BUSY_HANDLER(DEVWRITELINE("uart1", i8251_device, write_cts))
+ MCFG_DEVCB_CHAIN_OUTPUT(DEVWRITELINE("uart1", i8251_device, write_dsr)) // TODO: shared with serial CTS
+ MCFG_CENTRONICS_FAULT_HANDLER(WRITELINE(zorba_state, printer_fault_w))
+ MCFG_CENTRONICS_SELECT_HANDLER(WRITELINE(zorba_state, printer_select_w))
+
+ // J3 Serial printer
+ MCFG_RS232_PORT_ADD("serprn", default_rs232_devices, nullptr)
+ MCFG_RS232_RXD_HANDLER(DEVWRITELINE("uart1", i8251_device, write_rxd)) // TODO: this line has a LED attached
+
+ // J6 TTL-level serial keyboard
+ MCFG_DEVICE_ADD("keyboard", ZORBA_KEYBOARD, 0)
+ MCFG_ZORBA_KEYBOARD_RXD_CB(DEVWRITELINE("uart2", i8251_device, write_rxd))
+ //MCFG_QUANTUM_PERFECT_CPU("keyboard:mcu")
+
+ MCFG_SOFTWARE_LIST_ADD("flop_list", "zorba")
+MACHINE_CONFIG_END
+
+} // anonymous namespace
+
+
+//-------------------------------------------------
+// Initialise/reset
+//-------------------------------------------------
+
+DRIVER_INIT_MEMBER( zorba_state, zorba )
+{
+ uint8_t *main = memregion("maincpu")->base();
+
+ membank("bankr0")->configure_entry(0, &main[0x0000]);
+ membank("bankr0")->configure_entry(1, &main[0x10000]);
+ membank("bankw0")->configure_entry(0, &main[0x0000]);
+
+ save_item(NAME(m_intmask));
+ save_item(NAME(m_tx_rx_rdy));
+ save_item(NAME(m_irq));
+
+ save_item(NAME(m_printer_prowriter));
+ save_item(NAME(m_printer_fault));
+ save_item(NAME(m_printer_select));
+
+ save_item(NAME(m_term_data));
+
+ m_printer_prowriter = false;
+ m_printer_fault = 0;
+ m_printer_select = 0;
+}
+
+MACHINE_RESET_MEMBER( zorba_state, zorba )
+{
+ m_uart2->write_cts(0); // always asserted
+
+ m_intmask = 0x00;
+ m_tx_rx_rdy = 0x00;
+ m_irq = 0x00;
+
+ m_printer_prowriter = BIT(m_config_port->read(), 0);
+ m_pia0->cb1_w(m_printer_prowriter ? m_printer_select : m_printer_fault);
+
+ m_read_bank->set_entry(1); // point at rom
+ membank("bankw0")->set_entry(0); // always write to ram
+
+ m_maincpu->reset();
+}
+
+
+//-------------------------------------------------
+// Memory banking control
+//-------------------------------------------------
+
READ8_MEMBER( zorba_state::ram_r )
{
- membank("bankr0")->set_entry(0);
+ if (!space.debugger_access())
+ m_read_bank->set_entry(0);
return 0;
}
WRITE8_MEMBER( zorba_state::ram_w )
{
- membank("bankr0")->set_entry(0);
+ m_read_bank->set_entry(0);
}
READ8_MEMBER( zorba_state::rom_r )
{
- membank("bankr0")->set_entry(1);
+ if (!space.debugger_access())
+ m_read_bank->set_entry(1);
return 0;
}
WRITE8_MEMBER( zorba_state::rom_w )
{
- membank("bankr0")->set_entry(1);
+ m_read_bank->set_entry(1);
}
-WRITE_LINE_MEMBER( zorba_state::irq0_w )
-{
- if (state)
- {
- m_maincpu->set_input_line_vector(0, 0x88);
- m_maincpu->set_input_line(0, ASSERT_LINE);
- }
- else
- m_maincpu->set_input_line(0, CLEAR_LINE);
-}
-WRITE_LINE_MEMBER( zorba_state::fdc_intrq_w )
-{
- m_fdc_rq = (m_fdc_rq & 2) | state;
- if (m_fdc_rq == 1)
- {
- m_maincpu->set_input_line_vector(0, 0x80);
- m_maincpu->set_input_line(0, ASSERT_LINE);
- }
- else
- if (m_fdc_rq == 0)
- m_maincpu->set_input_line(0, CLEAR_LINE);
-}
+//-------------------------------------------------
+// Interrupt vectoring glue
+//-------------------------------------------------
-WRITE_LINE_MEMBER( zorba_state::fdc_drq_w )
+WRITE8_MEMBER( zorba_state::intmask_w )
{
- m_fdc_rq = (m_fdc_rq & 1) | (state << 1);
- if (m_fdc_rq == 2)
- {
- m_maincpu->set_input_line_vector(0, 0x80);
- m_maincpu->set_input_line(0, ASSERT_LINE);
- }
- else
- if (m_fdc_rq == 0)
- m_maincpu->set_input_line(0, CLEAR_LINE);
+ m_intmask = data & 0x3f; // only six lines physically present
+ irq_w<3>(BIT(m_intmask & m_tx_rx_rdy, 0) | BIT(m_intmask & m_tx_rx_rdy, 1));
+ irq_w<4>(BIT(m_intmask & m_tx_rx_rdy, 2) | BIT(m_intmask & m_tx_rx_rdy, 3));
+ irq_w<5>(BIT(m_intmask & m_tx_rx_rdy, 4) | BIT(m_intmask & m_tx_rx_rdy, 5));
}
-WRITE8_MEMBER( zorba_state::intmask_w )
+template <unsigned N> WRITE_LINE_MEMBER( zorba_state::tx_rx_rdy_w )
{
+ m_tx_rx_rdy = (m_tx_rx_rdy & ~(1 << N)) | ((state ? 1 : 0) << N);
+ irq_w<(N >> 1) + 3>(BIT(m_intmask & m_tx_rx_rdy, N & ~1) | BIT(m_intmask & m_tx_rx_rdy, N | 1));
}
-static INPUT_PORTS_START( zorba )
-INPUT_PORTS_END
-
-DRIVER_INIT_MEMBER( zorba_state, zorba )
+template <unsigned N> WRITE_LINE_MEMBER( zorba_state::irq_w )
{
- uint8_t *main = memregion("maincpu")->base();
-
- membank("bankr0")->configure_entry(0, &main[0x0000]);
- membank("bankr0")->configure_entry(1, &main[0x10000]);
- membank("bankw0")->configure_entry(0, &main[0x0000]);
+ m_irq = (m_irq & ~(1 << N)) | ((state ? 1 : 0) << N);
+
+ // TODO: get a good dump of the interrupt vector PROM and get rid of this hack
+ // There are six interrupt sources:
+ // * IRQ0: DMAC/CRTC shared
+ // * IRQ1: IEEE488 (PIA IRQA/IRQB shared)
+ // * IRQ2: FDC INTRQ/DRQ shared
+ // * IRQ3: RS232 TXRDY/RXRDY selectable
+ // * IRQ4: Serial printer TXRDY/RXRDY selectable
+ // * IRQ5: Keyboard TXRDY/RXRDY selectable
+ // Valid vectors are 0x80, 0x84, 0x88, 0x8c, 0x90 and 0x94
+ // Floppy needs to be on 0x80, and RS232 is apparently on 0x88
+ // Everything else, including priority, is a complete guess
+ u8 vector;
+ if (BIT(m_irq, 2)) vector = 0x80;
+ else if (BIT(m_irq, 3)) vector = 0x88;
+ else vector = 0x84; // very wrong, need test cases for other things
+
+ m_maincpu->set_input_line_and_vector(
+ INPUT_LINE_IRQ0,
+ m_irq ? ASSERT_LINE : CLEAR_LINE,
+ vector);
}
+
//-------------------------------------------------
-// Z80DMA
+// DMA controller handlers
//-------------------------------------------------
WRITE_LINE_MEMBER( zorba_state::busreq_w )
@@ -268,19 +420,28 @@ WRITE8_MEMBER(zorba_state::io_write_byte)
address_space& prog_space = m_maincpu->space(AS_IO);
if (offset == 0x10)
- {
m_crtc->dack_w(space, 0, data);
- }
else
- {
prog_space.write_byte(offset, data);
- }
}
-static SLOT_INTERFACE_START( zorba_floppies )
- SLOT_INTERFACE( "525dd", FLOPPY_525_DD )
-SLOT_INTERFACE_END
+//-------------------------------------------------
+// PIT handlers
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( zorba_state::br1_w )
+{
+ // TODO: these can be jumpered to inputs from J2 so a modem can generate Baud rates
+ // TODO: receive clock is exposed on J2 for external devices without Baud rate generators
+ m_uart0->write_txc(state);
+ m_uart0->write_rxc(state);
+}
+
+
+//-------------------------------------------------
+// PIA handlers
+//-------------------------------------------------
WRITE8_MEMBER( zorba_state::pia0_porta_w )
{
@@ -300,6 +461,50 @@ WRITE8_MEMBER( zorba_state::pia0_porta_w )
m_floppy1->get_device()->mon_w(BIT(data, 4));
}
+READ8_MEMBER( zorba_state::pia1_portb_r )
+{
+ // 0 (output only)
+ // 1 (output only)
+ // 2 (output only)
+ // 3 EOI gated with PB2 (active high)
+ // 4 (output only)
+ // 5 DAV gated with PB2 (active high)
+ // 6 NDAC gated with PB1 (active high)
+ // 7 NRFD gated with PB1 (active high)
+
+ const uint8_t outputs(m_pia0->b_output());
+ return
+ (m_ieee->eoi_r() << 3) |
+ (m_ieee->dav_r() << 5) |
+ (m_ieee->ndac_r() << 6) |
+ (m_ieee->nrfd_r() << 7) |
+ (BIT(outputs, 1) ? 0x00 : 0xc0) |
+ (BIT(outputs, 2) ? 0x00 : 0x28);
+}
+
+WRITE8_MEMBER( zorba_state::pia1_portb_w )
+{
+ // 0 DIO direction
+ // 1 NDAC/NRFD data direction, SRQ gate
+ // 2 EOI/DAV data direction
+ // 3 EOI gated with PB2 (active low)
+ // 4 ATN
+ // 5 DAV gated with PB2 (active low)
+ // 6 NDAC gated with PB1 (active low)
+ // 7 NRFD gated with PB1 (active low)
+
+ m_ieee->eoi_w(BIT(data, 3) & BIT(~data, 2));
+ m_ieee->atn_w(BIT(data, 4));
+ m_ieee->dav_w(BIT(data, 5) & BIT(~data, 2));
+ m_ieee->ndac_w(BIT(data, 6) & BIT(~data, 1));
+ m_ieee->nrfd_w(BIT(data, 7) & BIT(~data, 1));
+}
+
+
+//-------------------------------------------------
+// Video
+//-------------------------------------------------
+
I8275_DRAW_CHARACTER_MEMBER( zorba_state::zorba_update_chr )
{
int i;
@@ -321,138 +526,47 @@ I8275_DRAW_CHARACTER_MEMBER( zorba_state::zorba_update_chr )
}
-/* F4 Character Displayer */
-static const gfx_layout u5_charlayout =
-{
- 8, 11, /* 8 x 11 characters */
- 256, /* 256 characters */
- 1, /* 1 bits per pixel */
- { 0 }, /* no bitplanes */
- /* x offsets */
- { 0, 1, 2, 3, 4, 5, 6, 7 },
- /* y offsets */
- { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, 8*8, 9*8, 10*8 },
- 8*16 /* every char takes 16 bytes */
-};
-
-static GFXDECODE_START( zorba )
- GFXDECODE_ENTRY( "chargen", 0x0000, u5_charlayout, 0, 1 )
-GFXDECODE_END
+//-------------------------------------------------
+// Printer port glue
+//-------------------------------------------------
-MACHINE_RESET_MEMBER( zorba_state, zorba )
+WRITE_LINE_MEMBER( zorba_state::printer_fault_w )
{
- m_fdc_rq = 0;
- m_p_chargen = memregion("chargen")->base();
- membank("bankr0")->set_entry(1); // point at rom
- membank("bankw0")->set_entry(0); // always write to ram
- m_maincpu->reset();
+ // connects to CB1 for Centronics
+ m_printer_fault = state;
+ if (!m_printer_prowriter)
+ m_pia0->cb1_w(state);
}
-READ8_MEMBER( zorba_state::keyboard_r )
+WRITE_LINE_MEMBER( zorba_state::printer_select_w )
{
- if (offset)
- return (m_term_data) ? 0x87 : 0x85;
-
- uint8_t data = m_term_data;
- m_term_data = 0;
- return data;
+ // connects to CB1 for Prowriter
+ m_printer_select = state;
+ if (m_printer_prowriter)
+ m_pia0->cb1_w(state);
}
-WRITE8_MEMBER( zorba_state::kbd_put )
+INPUT_CHANGED_MEMBER( zorba_state::printer_type )
{
- m_term_data = data;
+ m_printer_prowriter = newval;
+ m_pia0->cb1_w(m_printer_prowriter ? m_printer_select : m_printer_fault);
}
-static MACHINE_CONFIG_START( zorba, zorba_state )
- // basic machine hardware
- MCFG_CPU_ADD("maincpu", Z80, XTAL_24MHz / 6)
- MCFG_CPU_PROGRAM_MAP(zorba_mem)
- MCFG_CPU_IO_MAP(zorba_io)
- MCFG_MACHINE_RESET_OVERRIDE(zorba_state, zorba)
-
- /* keyboard */
- MCFG_CPU_ADD("kbdcpu", M68705, XTAL_3_579545MHz) // MC68705P3S (0x80 bytes ram, 0x780 bytes of rom)
- MCFG_CPU_PROGRAM_MAP(zorba_kbdmem)
-
- /* video hardware */
- MCFG_SCREEN_ADD_MONOCHROME("screen", RASTER, rgb_t::green())
- MCFG_SCREEN_REFRESH_RATE(50)
- MCFG_SCREEN_UPDATE_DEVICE("crtc", i8275_device, screen_update)
- MCFG_GFXDECODE_ADD("gfxdecode", "palette", zorba)
- MCFG_PALETTE_ADD_MONOCHROME_HIGHLIGHT("palette")
-
- /* sound hardware */
- MCFG_SPEAKER_STANDARD_MONO("mono")
- MCFG_SOUND_ADD("beeper", BEEP, 800)
- MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
-
- /* devices */
- MCFG_DEVICE_ADD("dma", Z80DMA, XTAL_24MHz/6)
- // busack on cpu connects to bai pin
- MCFG_Z80DMA_OUT_BUSREQ_CB(WRITELINE(zorba_state, busreq_w)) //connects to busreq on cpu
- MCFG_Z80DMA_OUT_INT_CB(WRITELINE(zorba_state, irq0_w)) // connects to IRQ0 on IM2 controller
- //ba0 - not connected
- MCFG_Z80DMA_IN_MREQ_CB(READ8(zorba_state, memory_read_byte))
- MCFG_Z80DMA_OUT_MREQ_CB(WRITE8(zorba_state, memory_write_byte))
- MCFG_Z80DMA_IN_IORQ_CB(READ8(zorba_state, io_read_byte))
- MCFG_Z80DMA_OUT_IORQ_CB(WRITE8(zorba_state, io_write_byte))
-
- MCFG_DEVICE_ADD("uart0", I8251, 0) // U32 COM port J2
-
- MCFG_DEVICE_ADD("uart1", I8251, 0) // U31 printer port J3
-
- MCFG_DEVICE_ADD("uart2", I8251, 0) // U30 serial keyboard J6
-
- // port A - disk select etc, beeper
- // port B - parallel interface
- MCFG_DEVICE_ADD("pia0", PIA6821, 0)
- MCFG_PIA_WRITEPA_HANDLER(WRITE8(zorba_state, pia0_porta_w))
-
- // IEEE488 interface
- MCFG_DEVICE_ADD("pia1", PIA6821, 0)
-
- MCFG_DEVICE_ADD("pit", PIT8254, 0)
- MCFG_PIT8253_CLK0(XTAL_24MHz / 3) /* Timer 0: clock to J2 comm port */
- MCFG_PIT8253_CLK1(XTAL_24MHz / 3) /* Timer 1: clock to U31 */
- MCFG_PIT8253_CLK2(XTAL_24MHz / 3) /* Timer 2: clock to U30 */
-
- MCFG_DEVICE_ADD("crtc", I8275, XTAL_14_31818MHz/7)
- MCFG_I8275_CHARACTER_WIDTH(8)
- MCFG_I8275_DRAW_CHARACTER_CALLBACK_OWNER(zorba_state, zorba_update_chr)
- MCFG_I8275_DRQ_CALLBACK(DEVWRITELINE("dma", z80dma_device, rdy_w))
- MCFG_I8275_IRQ_CALLBACK(WRITELINE(zorba_state, irq0_w))
- MCFG_FD1793_ADD("fdc", XTAL_24MHz / 24)
- MCFG_WD_FDC_INTRQ_CALLBACK(WRITELINE(zorba_state, fdc_intrq_w))
- MCFG_WD_FDC_DRQ_CALLBACK(WRITELINE(zorba_state, fdc_drq_w))
- MCFG_FLOPPY_DRIVE_ADD("fdc:0", zorba_floppies, "525dd", floppy_image_device::default_floppy_formats)
- MCFG_FLOPPY_DRIVE_SOUND(true)
- MCFG_FLOPPY_DRIVE_ADD("fdc:1", zorba_floppies, "525dd", floppy_image_device::default_floppy_formats)
- MCFG_FLOPPY_DRIVE_SOUND(true)
-
- /* Keyboard */
- MCFG_DEVICE_ADD("keyboard", GENERIC_KEYBOARD, 0)
- MCFG_GENERIC_KEYBOARD_CB(WRITE8(zorba_state, kbd_put))
-
- MCFG_SOFTWARE_LIST_ADD("flop_list", "zorba")
-MACHINE_CONFIG_END
ROM_START( zorba )
ROM_REGION( 0x14000, "maincpu", ROMREGION_ERASEFF )
ROM_LOAD( "780000.u47", 0x10000, 0x1000, CRC(6d58f2c5) SHA1(7763f08c801cd36e5a761c6dc9f30a50b3bc482d) )
- ROM_REGION( 0x800, "kbdcpu", 0 )
- ROM_LOAD( "8999-1 3-28-83", 0x080, 0x780, CRC(79fe6c0d) SHA1(4b6fca9379d5199d1347ad1187cbfdebfc4c73e7) )
-
ROM_REGION( 0x1000, "chargen", 0 )
ROM_LOAD( "773000.u5", 0x0000, 0x1000, CRC(d0a2f8fc) SHA1(29aee7ee657778c46e9800abd4955e6d4b33ef68) )
ROM_REGION( 0x60, "proms", 0 )
- ROM_LOAD( "74ls288.u37", 0x0000, 0x0020, CRC(0a67edd6) SHA1(c1ece8978a3a061e0130d43907fa63a71e75e75d) )
- ROM_LOAD( "74ls288.u38", 0x0020, 0x0020, CRC(5ec93ea7) SHA1(3a84c098474b05d5cbe1939a3e15f66d06470581) )
- ROM_LOAD( "74ls288.u77", 0x0040, 0x0020, CRC(946e03b0) SHA1(24240bdd7bdf507a5b51628fb36ad1266fc53a28) ) // suspected bad dump
+ ROM_LOAD( "74ls288.u37", 0x0000, 0x0020, CRC(0a67edd6) SHA1(c1ece8978a3a061e0130d43907fa63a71e75e75d) BAD_DUMP ) // looks like interrupt vector PROM dumped with scrambled lines
+ ROM_LOAD( "74ls288.u38", 0x0020, 0x0020, CRC(5ec93ea7) SHA1(3a84c098474b05d5cbe1939a3e15f66d06470581) BAD_DUMP ) // looks like bad dump of address decode PROM
+ ROM_LOAD( "74ls288.u77", 0x0040, 0x0020, CRC(946e03b0) SHA1(24240bdd7bdf507a5b51628fb36ad1266fc53a28) BAD_DUMP ) // looks like bad dump of address decode PROM
ROM_END
-COMP( 1984?, zorba, 0, 0, zorba, zorba, zorba_state, zorba, "Modular Micros", "Zorba (Modular Micros)", MACHINE_NOT_WORKING )
+COMP( 1984?, zorba, 0, 0, zorba, zorba, zorba_state, zorba, "Modular Micros", "Zorba (Modular Micros)", MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE )
// Undumped versions (see startup screen notes at top of file)
// COMP( 1983, zorbat, zorba, 0, zorba, zorba, zorba_state, zorba, "Telcon Industries", "Zorba (Telcon Industries)", MACHINE_NOT_WORKING )
diff --git a/src/mame/includes/gladiatr.h b/src/mame/includes/gladiatr.h
index 60166ed4b99..39c99eb8391 100644
--- a/src/mame/includes/gladiatr.h
+++ b/src/mame/includes/gladiatr.h
@@ -83,8 +83,6 @@ public:
, m_in2(*this, "IN2")
, m_coins(*this, "COINS")
, m_tclk_val(false)
- , m_in0_val(0xff)
- , m_in1_val(0xff)
, m_cctl_p1(0xff)
, m_cctl_p2(0xff)
, m_ucpu_p1(0xff)
@@ -123,6 +121,11 @@ public:
DECLARE_WRITE8_MEMBER(csnd_p1_w);
DECLARE_READ8_MEMBER(csnd_p2_r);
+ DECLARE_INPUT_CHANGED_MEMBER(p1_s1);
+ DECLARE_INPUT_CHANGED_MEMBER(p1_s2);
+ DECLARE_INPUT_CHANGED_MEMBER(p2_s1);
+ DECLARE_INPUT_CHANGED_MEMBER(p2_s2);
+
DECLARE_DRIVER_INIT(gladiatr);
DECLARE_MACHINE_RESET(gladiator);
@@ -137,7 +140,6 @@ private:
required_ioport m_coins;
bool m_tclk_val;
- u8 m_in0_val, m_in1_val;
u8 m_cctl_p1, m_cctl_p2;
u8 m_ucpu_p1, m_csnd_p1;
diff --git a/src/mame/includes/osborne1.h b/src/mame/includes/osborne1.h
index bbe12f9efcb..56754a43e82 100644
--- a/src/mame/includes/osborne1.h
+++ b/src/mame/includes/osborne1.h
@@ -81,6 +81,8 @@ public:
DECLARE_WRITE_LINE_MEMBER(serial_acia_irq_func);
+ DECLARE_INPUT_CHANGED_MEMBER(reset_key);
+
DECLARE_DRIVER_INIT(osborne1);
virtual void machine_reset() override;
virtual void video_start() override;
diff --git a/src/mame/includes/zorba.h b/src/mame/includes/zorba.h
new file mode 100644
index 00000000000..9eae677473f
--- /dev/null
+++ b/src/mame/includes/zorba.h
@@ -0,0 +1,113 @@
+// license:BSD-3-Clause
+// copyright-holders:Robbbert, Vas Crabb
+
+#include "sound/beep.h"
+
+#include "bus/ieee488/ieee488.h"
+
+#include "machine/6821pia.h"
+#include "machine/i8251.h"
+#include "machine/wd_fdc.h"
+#include "machine/z80dma.h"
+
+#include "video/i8275.h"
+
+
+class zorba_state : public driver_device
+{
+public:
+ zorba_state(const machine_config &mconfig, device_type type, const char *tag)
+ : driver_device(mconfig, type, tag)
+ , m_config_port(*this, "CNF")
+ , m_read_bank(*this, "bankr0")
+ , m_p_chargen(*this, "chargen")
+ , m_maincpu(*this, "maincpu")
+ , m_dma(*this, "dma")
+ , m_uart0(*this, "uart0")
+ , m_uart1(*this, "uart1")
+ , m_uart2(*this, "uart2")
+ , m_pia0(*this, "pia0")
+ , m_pia1(*this, "pia1")
+ , m_palette(*this, "palette")
+ , m_crtc(*this, "crtc")
+ , m_beep(*this, "beeper")
+ , m_fdc (*this, "fdc")
+ , m_floppy0(*this, "fdc:0")
+ , m_floppy1(*this, "fdc:1")
+ , m_ieee(*this, IEEE488_TAG)
+ {
+ }
+
+public:
+ DECLARE_DRIVER_INIT(zorba);
+ DECLARE_MACHINE_RESET(zorba);
+
+ // Memory banking control
+ DECLARE_READ8_MEMBER(ram_r);
+ DECLARE_WRITE8_MEMBER(ram_w);
+ DECLARE_READ8_MEMBER(rom_r);
+ DECLARE_WRITE8_MEMBER(rom_w);
+
+ // Interrupt vectoring glue
+ DECLARE_WRITE8_MEMBER(intmask_w);
+ template <unsigned N> DECLARE_WRITE_LINE_MEMBER(tx_rx_rdy_w);
+ template <unsigned N> DECLARE_WRITE_LINE_MEMBER(irq_w);
+
+ // DMA controller handlers
+ DECLARE_WRITE_LINE_MEMBER(busreq_w);
+ DECLARE_READ8_MEMBER(memory_read_byte);
+ DECLARE_WRITE8_MEMBER(memory_write_byte);
+ DECLARE_READ8_MEMBER(io_read_byte);
+ DECLARE_WRITE8_MEMBER(io_write_byte);
+
+ // PIT handlers
+ DECLARE_WRITE_LINE_MEMBER(br1_w);
+
+ // PIA handlers
+ DECLARE_WRITE8_MEMBER(pia0_porta_w);
+ DECLARE_READ8_MEMBER(pia1_portb_r);
+ DECLARE_WRITE8_MEMBER(pia1_portb_w);
+
+ // Video
+ I8275_DRAW_CHARACTER_MEMBER(zorba_update_chr);
+
+ // Printer port glue
+ DECLARE_WRITE_LINE_MEMBER(printer_fault_w);
+ DECLARE_WRITE_LINE_MEMBER(printer_select_w);
+ DECLARE_INPUT_CHANGED_MEMBER(printer_type);
+
+private:
+ required_ioport m_config_port;
+
+ required_memory_bank m_read_bank;
+ required_region_ptr<uint8_t> m_p_chargen;
+
+ required_device<cpu_device> m_maincpu;
+ required_device<z80dma_device> m_dma;
+ required_device<i8251_device> m_uart0;
+ required_device<i8251_device> m_uart1;
+ required_device<i8251_device> m_uart2;
+ required_device<pia6821_device> m_pia0;
+ required_device<pia6821_device> m_pia1;
+
+ required_device<palette_device> m_palette;
+ required_device<i8275_device> m_crtc;
+
+ required_device<beep_device> m_beep;
+
+ required_device<fd1793_t> m_fdc;
+ required_device<floppy_connector> m_floppy0;
+ required_device<floppy_connector> m_floppy1;
+
+ required_device<ieee488_device> m_ieee;
+
+ uint8_t m_intmask;
+ uint8_t m_tx_rx_rdy;
+ uint8_t m_irq;
+
+ bool m_printer_prowriter;
+ int m_printer_fault;
+ int m_printer_select;
+
+ uint8_t m_term_data;
+};
diff --git a/src/mame/machine/osborne1.cpp b/src/mame/machine/osborne1.cpp
index cd649cef91a..cb9f84f5bf3 100644
--- a/src/mame/machine/osborne1.cpp
+++ b/src/mame/machine/osborne1.cpp
@@ -252,6 +252,14 @@ WRITE_LINE_MEMBER( osborne1_state::serial_acia_irq_func )
}
+INPUT_CHANGED_MEMBER( osborne1_state::reset_key )
+{
+ // This key affects NMI
+ if (!m_ub6a_q)
+ m_maincpu->set_input_line(INPUT_LINE_NMI, newval ? CLEAR_LINE : ASSERT_LINE);
+}
+
+
DRIVER_INIT_MEMBER( osborne1_state, osborne1 )
{
m_bank_0xxx->configure_entries(0, 1, m_ram->pointer(), 0);
@@ -443,10 +451,6 @@ TIMER_CALLBACK_MEMBER(osborne1_state::video_callback)
m_beep_state = (ra & 0x04) ? 1 : 0;
m_speaker->level_w((BIT(port_b, 5) && m_beep_state) ? 1 : 0);
- // Check reset key if necessary - it affects NMI
- if (!m_ub6a_q)
- m_maincpu->set_input_line(INPUT_LINE_NMI, (m_btn_reset->read() & 0x80) ? CLEAR_LINE : ASSERT_LINE);
-
m_video_timer->adjust(machine().first_screen()->time_until_pos(y + 1, 0));
}
diff --git a/src/mame/machine/taito68705interface.cpp b/src/mame/machine/taito68705interface.cpp
index 3af9611ef43..3cb18183b9a 100644
--- a/src/mame/machine/taito68705interface.cpp
+++ b/src/mame/machine/taito68705interface.cpp
@@ -38,7 +38,6 @@
bublbobl.cpp - bub68705 - this is a bootleg, not an official Taito hookup
changela.cpp - changela - looks like an ancestor of arkanoid without automatic semaphores
mexico86.cpp - knightb, mexico86 - bootleg 68705s
- retofinv.cpp - the current MCU dump is a bootleg at least
sqix.cpp - hotsmash - kaneko hookup, different from Taito ones.
there are other drivers (and games in existing drivers) that could hookup here, but currently lack MCU dumps.
diff --git a/src/mame/machine/zorbakbd.cpp b/src/mame/machine/zorbakbd.cpp
new file mode 100644
index 00000000000..379a021a56b
--- /dev/null
+++ b/src/mame/machine/zorbakbd.cpp
@@ -0,0 +1,314 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/*
+ * TTL-level serial matrix keyboard
+ *
+ * The keyboard MCU handles scanning the matrix and converting key down/
+ * up events to high-level characters for the host computer. The DIP
+ * switches are only read on startup.
+ *
+ * TODO: the eight "holes" generate control codes, six of them are break, home and the arrows
+ *
+ * Strangely, the Zorba configures its keyboard UART for 8N2 but this
+ * keyboard sends 8N1. If you type too fast or hold down a key until it
+ * repeats, characters will be dropped/corrupted. It's possible this is
+ * a dump of a different CP/M-compatible keyboard, not the one supplied
+ * with the Zorba.
+ *
+ * The Zorba manual describes a keyboard PROM with enough space to map
+ * all eight modifier combinations independently, however this keyboard
+ * contains no PROMs (just the MCU and demultiplexer), and the internal
+ * MCU EPROM only contains three tables for normal, shift, and control
+ * (caps lock is computed off the normal table by checking for letter
+ * characters).
+ *
+ * 0 1 2 3 4 5 6 7
+ * 0 F1 F13 3 # KP8 i I s S KP2 , <
+ * 1 F2 F14 4 $ KP9 o O d D KP3 . >
+ * 2 F3 F15 5 % p P f F / ?
+ * 3 F4 F16 6 ^ [ { g G KP0
+ * 4 F5 F17 7 & tab ] } h H shift KP.
+ * 5 F6 F18 8 * q Q KP4 j J z Z
+ * 6 F7 F19 9 ( w W KP5 k K x X
+ * 7 F8 ~ 0 ) e E KP6 l L c C space
+ * 8 F9 \ | - _ r R s-lock ; : v V newline
+ * 9 F10 ESC = + t T ctrl ' " b B KP-
+ * 10 F11 1 ! del y Y c-lock return n N
+ * 11 F12 2 @ KP7 u U a A KP1 m M
+ */
+#include "emu.h"
+#include "zorbakbd.h"
+
+#include "cpu/m6805/m68705.h"
+
+
+namespace {
+
+INPUT_PORTS_START(zorba_keyboard)
+ PORT_START("ROW0")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F1") PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1))
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F13") PORT_CODE(KEYCODE_F13) PORT_CHAR(UCHAR_MAMEKEY(F13))
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("KP 8") PORT_CODE(KEYCODE_8_PAD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD))
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I')
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S')
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("KP 2") PORT_CODE(KEYCODE_2_PAD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD))
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<')
+
+ PORT_START("ROW1")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F2") PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2))
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F14") PORT_CODE(KEYCODE_F14) PORT_CHAR(UCHAR_MAMEKEY(F14))
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("KP 9") PORT_CODE(KEYCODE_9_PAD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD))
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O')
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D')
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("KP 3") PORT_CODE(KEYCODE_3_PAD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD))
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>')
+
+ PORT_START("ROW2")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F3") PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3))
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F15") PORT_CODE(KEYCODE_F15) PORT_CHAR(UCHAR_MAMEKEY(F15))
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN ) // b9
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P')
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F')
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN ) // b3
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?')
+
+ PORT_START("ROW3")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F4") PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F3))
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F16") PORT_CODE(KEYCODE_F16) PORT_CHAR(UCHAR_MAMEKEY(F16))
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN ) // b7
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{')
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G')
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN ) // b4
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("KP 0") PORT_CODE(KEYCODE_0_PAD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD))
+
+ PORT_START("ROW4")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F5") PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5))
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F17") PORT_CODE(KEYCODE_F17) PORT_CHAR(UCHAR_MAMEKEY(F17))
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("TAB") PORT_CODE(KEYCODE_TAB) PORT_CHAR(9)
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}')
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H')
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("SHIFT") PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("KP .") PORT_CODE(KEYCODE_DEL_PAD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD))
+
+ PORT_START("ROW5")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F6") PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6))
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F18") PORT_CODE(KEYCODE_F18) PORT_CHAR(UCHAR_MAMEKEY(F18))
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("KP 4") PORT_CODE(KEYCODE_4_PAD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD))
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J')
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z')
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) // b5
+
+ PORT_START("ROW6")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F7") PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7))
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F19") PORT_CODE(KEYCODE_F19) PORT_CHAR(UCHAR_MAMEKEY(F19))
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("KP 5") PORT_CODE(KEYCODE_5_PAD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD))
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K')
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X')
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) // b6
+
+ PORT_START("ROW7")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F8") PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8))
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("~ PRINT") PORT_CODE(KEYCODE_TILDE) PORT_CHAR('~') PORT_CHAR(UCHAR_MAMEKEY(PRTSCR))
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("KP 6") PORT_CODE(KEYCODE_6_PAD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD))
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L')
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C')
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
+
+ PORT_START("ROW8")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F9") PORT_CODE(KEYCODE_F9) PORT_CHAR(UCHAR_MAMEKEY(F9))
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') PORT_CHAR('|')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("SHIFT LOCK") PORT_CODE(KEYCODE_LALT)
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':')
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V')
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("NEW LINE") PORT_CODE(KEYCODE_ENTER_PAD) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD))
+
+ PORT_START("ROW9")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F10") PORT_CODE(KEYCODE_F10) PORT_CHAR(UCHAR_MAMEKEY(F10))
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("ESC") PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC))
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("CTRL") PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_MAMEKEY(LCONTROL))
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('"')
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B')
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("KP -") PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD))
+
+ PORT_START("ROW10")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F11") PORT_CODE(KEYCODE_F11) PORT_CHAR(UCHAR_MAMEKEY(F11))
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("BS DEL") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8) PORT_CHAR(UCHAR_MAMEKEY(DEL))
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("CAPS LOCK") PORT_CODE(KEYCODE_CAPSLOCK) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK))
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("RETURN") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13)
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N')
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) // e0
+
+ PORT_START("ROW11")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F12") PORT_CODE(KEYCODE_F12) PORT_CHAR(UCHAR_MAMEKEY(F12))
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("KP 7") PORT_CODE(KEYCODE_7_PAD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD))
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A')
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("KP 1") PORT_CODE(KEYCODE_1_PAD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD))
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M')
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) // e1
+
+ PORT_START("ROW12")
+ PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED ) // scanned but the tables are too small so it would post garbage
+
+ PORT_START("ROW13")
+ PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED ) // scanned but the tables are too small so it would post garbage
+
+ PORT_START("ROW14")
+ PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED ) // scanned but the tables are too small so it would post garbage
+
+ PORT_START("ROW15")
+ PORT_DIPNAME( 0x07, 0x07, "Diagnostic Mode" )
+ PORT_DIPSETTING( 0x07, "0 (Normal)" )
+ PORT_DIPSETTING( 0x06, "1 (Dump Tables)" )
+ PORT_DIPSETTING( 0x05, "2 (Report Revision)" )
+ PORT_DIPSETTING( 0x04, "3 (Serial Test)" )
+ PORT_DIPSETTING( 0x03, "4 (Serial Echo)" )
+ PORT_DIPSETTING( 0x02, "5 (Output Test)" )
+ PORT_DIPSETTING( 0x01, "6 (Normal)" )
+ PORT_DIPSETTING( 0x00, "7 (Dump Tables)" )
+ PORT_DIPNAME( 0x08, 0x08, "Key Repeat" )
+ PORT_DIPSETTING( 0x08, DEF_STR(On) )
+ PORT_DIPSETTING( 0x00, DEF_STR(Off) )
+ PORT_DIPNAME( 0x10, 0x10, "Baud Rate" )
+ PORT_DIPSETTING( 0x10, "1200" )
+ PORT_DIPSETTING( 0x00, "300" )
+ PORT_DIPNAME( 0x20, 0x20, "Key Click" )
+ PORT_DIPSETTING( 0x20, DEF_STR(On) )
+ PORT_DIPSETTING( 0x00, DEF_STR(Off) )
+ PORT_DIPNAME( 0x40, 0x20, DEF_STR(Unknown) )
+ PORT_DIPSETTING( 0x20, DEF_STR(Off) )
+ PORT_DIPSETTING( 0x00, DEF_STR(On) )
+ PORT_DIPNAME( 0x80, 0x20, DEF_STR(Unknown) )
+ PORT_DIPSETTING( 0x20, DEF_STR(Off) )
+ PORT_DIPSETTING( 0x00, DEF_STR(On) )
+INPUT_PORTS_END
+
+
+MACHINE_CONFIG_FRAGMENT(zorba_keyboard)
+ MCFG_CPU_ADD("mcu", M68705P3, XTAL_3_579545MHz) // MC68705P3S
+ MCFG_M68705_PORTA_R_CB(READ8(zorba_keyboard_device, mcu_pa_r));
+ MCFG_M68705_PORTB_R_CB(READ8(zorba_keyboard_device, mcu_pb_r));
+ MCFG_M68705_PORTB_W_CB(WRITE8(zorba_keyboard_device, mcu_pb_w));
+ MCFG_M68705_PORTC_W_CB(WRITE8(zorba_keyboard_device, mcu_pc_w));
+
+ // TODO: beeper frequency is unknown, using value from Sun keyboard for now
+ MCFG_SPEAKER_STANDARD_MONO("bell")
+ MCFG_SOUND_ADD("beeper", BEEP, ATTOSECONDS_TO_HZ(480 * ATTOSECONDS_PER_MICROSECOND))
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "bell", 1.0)
+MACHINE_CONFIG_END
+
+
+ROM_START(zorba_keyboard)
+ ROM_REGION(0x0800, "mcu", 0)
+ ROM_LOAD( "8999-1 3-28-83", 0x080, 0x780, CRC(79fe6c0d) SHA1(4b6fca9379d5199d1347ad1187cbfdebfc4c73e7) )
+ROM_END
+
+} // anonymous namespace
+
+
+device_type const ZORBA_KEYBOARD = &device_creator<zorba_keyboard_device>;
+
+
+zorba_keyboard_device::zorba_keyboard_device(
+ machine_config const &mconfig,
+ char const *tag,
+ device_t *owner,
+ uint32_t clock)
+ : device_t(
+ mconfig,
+ ZORBA_KEYBOARD,
+ "Zorba Keyboard",
+ tag,
+ owner,
+ clock,
+ "zorba_kbd",
+ __FILE__)
+ , m_rows(*this, "ROW%u", 0)
+ , m_beeper(*this, "beeper")
+ , m_rxd_cb(*this)
+ , m_txd_high(true)
+ , m_row_select(0)
+{
+}
+
+
+WRITE_LINE_MEMBER(zorba_keyboard_device::txd_w)
+{
+ m_txd_high = CLEAR_LINE != state;
+}
+
+
+READ8_MEMBER(zorba_keyboard_device::mcu_pa_r)
+{
+ return m_rows[m_row_select]->read();
+}
+
+
+READ8_MEMBER(zorba_keyboard_device::mcu_pb_r)
+{
+ return m_txd_high ? 0x7f : 0xff;
+}
+
+
+WRITE8_MEMBER(zorba_keyboard_device::mcu_pb_w)
+{
+ // TODO: bits 2/3/4 do something; some photos show F17/F18/F19 with LED windows
+ m_rxd_cb(BIT(data, 6) ? 0 : 1);
+ m_beeper->set_state(BIT(data, 5) ? 0 : 1);
+ machine().output().set_value("led_key_caps_lock", BIT(data, 1) ? 0 : 1);
+ machine().output().set_value("led_key_shift_lock", BIT(data, 0) ? 0 : 1);
+}
+
+
+WRITE8_MEMBER(zorba_keyboard_device::mcu_pc_w)
+{
+ m_row_select = data & 0x0f;
+}
+
+
+void zorba_keyboard_device::device_start()
+{
+ m_rxd_cb.resolve_safe();
+
+ save_item(NAME(m_txd_high));
+ save_item(NAME(m_row_select));
+
+ m_txd_high = true;
+ m_row_select = 0;
+}
+
+
+machine_config_constructor zorba_keyboard_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME(zorba_keyboard);
+}
+
+
+ioport_constructor zorba_keyboard_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(zorba_keyboard);
+}
+
+
+tiny_rom_entry const *zorba_keyboard_device::device_rom_region() const
+{
+ return ROM_NAME(zorba_keyboard);
+}
diff --git a/src/mame/machine/zorbakbd.h b/src/mame/machine/zorbakbd.h
new file mode 100644
index 00000000000..196a4831c41
--- /dev/null
+++ b/src/mame/machine/zorbakbd.h
@@ -0,0 +1,43 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+#ifndef MAME_MACHINE_ZORBAKBD_H
+#define MAME_MACHINE_ZORBAKBD_H
+
+#include "sound/beep.h"
+
+
+extern device_type const ZORBA_KEYBOARD;
+
+#define MCFG_ZORBA_KEYBOARD_RXD_CB(cb) \
+ zorba_keyboard_device::set_rxd_cb(*device, DEVCB_##cb);
+
+class zorba_keyboard_device : public device_t
+{
+public:
+ template <typename Obj> static devcb_base &set_rxd_cb(device_t &device, Obj &&object)
+ { return downcast<zorba_keyboard_device &>(device).m_rxd_cb.set_callback(std::forward<Obj>(object)); }
+
+ zorba_keyboard_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock);
+
+ DECLARE_WRITE_LINE_MEMBER(txd_w);
+
+ DECLARE_READ8_MEMBER(mcu_pa_r);
+ DECLARE_READ8_MEMBER(mcu_pb_r);
+ DECLARE_WRITE8_MEMBER(mcu_pb_w);
+ DECLARE_WRITE8_MEMBER(mcu_pc_w);
+
+protected:
+ virtual void device_start() override;
+ virtual machine_config_constructor device_mconfig_additions() const override;
+ virtual ioport_constructor device_input_ports() const override;
+ virtual tiny_rom_entry const *device_rom_region() const override;
+
+ required_ioport_array<16> m_rows;
+ required_device<beep_device> m_beeper;
+ devcb_write_line m_rxd_cb;
+
+ bool m_txd_high;
+ u8 m_row_select;
+};
+
+#endif // MAME_MACHINE_ZORBAKBD_H \ No newline at end of file