interpro: expansion bus/slots and keyboard

* added basic support for the system bus variously referred to as SR, SR bus, SRX and CBUS
* added an initial GT graphics card implementation, only supports the video ram and ramdac for now, but sufficient to boot the diagnostic monitor in graphics mode
* added a high-level emulation of the InterPro keyboard
This commit is contained in:
Patrick Mackinlay 2017-10-23 18:17:19 +07:00
parent d47254d287
commit fa45a71bce
12 changed files with 1607 additions and 0 deletions

View File

@ -3238,3 +3238,33 @@ if (BUSES["PSI_KEYBOARD"]~=null) then
MAME_DIR .. "src/devices/bus/psi_kbd/hle.h",
}
end
---------------------------------------------------
--
--@src/devices/bus/interpro/sr/sr.h,BUSES["INTERPRO_SR"] = true
---------------------------------------------------
if (BUSES["INTERPRO_SR"]~=null) then
files {
MAME_DIR .. "src/devices/bus/interpro/sr/sr.cpp",
MAME_DIR .. "src/devices/bus/interpro/sr/sr.h",
MAME_DIR .. "src/devices/bus/interpro/sr/sr_cards.cpp",
MAME_DIR .. "src/devices/bus/interpro/sr/sr_cards.h",
MAME_DIR .. "src/devices/bus/interpro/sr/gt.cpp",
MAME_DIR .. "src/devices/bus/interpro/sr/gt.h",
}
end
---------------------------------------------------
--
--@src/devices/bus/interpro/keyboard/keyboard.h,BUSES["INTERPRO_KEYBOARD"] = true
---------------------------------------------------
if (BUSES["INTERPRO_KEYBOARD"]~=null) then
files {
MAME_DIR .. "src/devices/bus/interpro/keyboard/keyboard.cpp",
MAME_DIR .. "src/devices/bus/interpro/keyboard/keyboard.h",
MAME_DIR .. "src/devices/bus/interpro/keyboard/hle.cpp",
MAME_DIR .. "src/devices/bus/interpro/keyboard/hle.h"
}
end

View File

@ -675,6 +675,8 @@ BUSES["HPDIO"] = true
BUSES["IEEE488"] = true
BUSES["IMI7000"] = true
BUSES["INTELLEC4"] = true
BUSES["INTERPRO_SR"] = true
BUSES["INTERPRO_KEYBOARD"] = true
BUSES["INTV"] = true
BUSES["INTV_CTRL"] = true
BUSES["IQ151"] = true

View File

@ -0,0 +1,461 @@
// license:BSD-3-Clause
// copyright-holders:Patrick Mackinlay
/*
* A high level emulation implementation of the Intergraph InterPro keyboard,
* largely copied from the sunkbd and psi hle implementations.
*
* These keyboards have two primary banks of keys. The lower bank consists of
* a total of 67 regular keyboard keyswitches plus a numeric keypad with a
* further 18 keys. The upper bank consists of 57 membrane-style programmable
* function keys in groups of 9, 36 and 12 from left to right.
*
* The following describes the key labels and positions according to the
* standard US English keyboard layout. It's unknown what other variations
* existed at this point.
*
* Upper bank keys indicated here with asterisks are printed in white, as are
* all the A*, B* and C* keys; all the others are printed in brown.
*
* Setup* Home* 2nd A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 A15 2nd
* Help Clear F* F*
* Screen
*
* Find Insert Print B1 B2 B3 B4 B5 B6 B7 B8 B9 B10 B11 B12 B13 B14 B15 B16
* Here Screen*
* Remove
*
* Select Prev Next C1 C2 C3 C4 C5 C6 C7 C8 C9 C10 C11 C12 C13 C14 C15 C16
* Screen Screen
*
*
* In between the banks on the right hand side, there is a row of LEDs, the
* first three are pictures, rather than the descriptions given here).
*
* Disk Lock ----- L1 L2 L3 L4
*
* Lower bank keys have up to 3 labels, in shifted and unshifted positions, and
* in red on the front face of the key-cap.
*
* Esc ~ ! @ # $ % ^ & * ( ) _ + Back Delete PF1 PF2 PF3 PF4
* ` 1 2 3 4 5 6 7 8 9 0 - = Space ± ÷ × +
* Esc Num Lk ScrlLk Sys
*
* Alt Tab Q W E R T Y U I O P { } 7 8 9 _
* Mode [ ]
* Home Pg Up Prt Sc
*
* Ctrl Caps A S D F G H J K L : " | Return 4 5 6 ,
* Lock
*
*
* Shift > Z X C V B N M , . ? Shift 1 2 3 =
* <
* End Pg Dn
*
* Hold Super- Line Repeat 0
* Screen impose Feed . Enter
* Ins Del +
*
* Alt Mode and Caps Lock keys have locking switches, capturing the key in the
* depressed position, as well as physical leds visible on the keycaps
* themselves. The keyboard also has two physical buttons on the back face of
* the keyboard, circular button labelled Boot, and a square one labelled Reset.
*
* The keyboard uses a 1200bps serial protocol to communicate with the host,
* with 1 start bit, 8 data bits, 1 stop bit, and even parity. The protocol
* as far as is known consists of the following sequences:
*
* From Host Purpose Expected Response
* --------- ------- -----------------
* <esc> D Diagnostic 0xff <status>, where status bits are set to
* indicate diagnostic failure source: 0x8=EPROM
* checksum, 0x10=RAM error, 0x20=ROM checksum
*
* <esc> B ( Bell On None
*
* <esc> B ) Bell Off None
*
* <esc> B <byte> Unknown None
*
* The keyboard has a keyboard click function, and the LED indicators described
* earlier, meaning that there are additional commands to enable and disable
* these functions.
*
* The keyboard transmits ASCII codes corresponding to the keycap labels for
* keys which map to the ASCII character set. Modifiers are applied by the
* keyboard itself, and do not generate make/break codes of their own.
*
* The following non-ASCII sequences are recognised in the system software,
* and likely correspond to specific keyboard keys or buttons:
*
* Sequence Function
* -------- --------
* <esc> ^L Reboot, possibly maps to Reboot button
* <esc> ^M Unknown
* <esc> ^N Unknown, but operates as a toggle
* <esc> ^U Unknown
*
* TODO
* - unmapped keys
* - auto-repeat
* - key click and LED commands
* - alternative layouts
*
*/
#include "emu.h"
#include "hle.h"
#include "machine/keyboard.ipp"
#include "speaker.h"
#define VERBOSE 0
#include "logmacro.h"
DEFINE_DEVICE_TYPE_NS(INTERPRO_HLE_EN_US_KEYBOARD, bus::interpro::keyboard, hle_en_us_device, "kbd_hle_en_us", "InterPro Keyboard (HLE, US English)")
namespace bus { namespace interpro { namespace keyboard {
namespace {
u8 const TRANSLATION_TABLE[4][5][16] =
{
// unshifted
{
{ 0x1b, 0x60, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x2d, 0x3d, 0x08, 0x7f }, // 0
{ 0x00, 0x09, 0x71, 0x77, 0x65, 0x72, 0x74, 0x79, 0x75, 0x69, 0x6f, 0x70, 0x5b, 0x5d, 0x00, 0x00 }, // 1
{ 0x00, 0x00, 0x61, 0x73, 0x64, 0x66, 0x67, 0x68, 0x6a, 0x6b, 0x6c, 0x3b, 0x27, 0x5c, 0x0d, 0x00 }, // 2
{ 0x00, 0x3c, 0x7a, 0x78, 0x63, 0x76, 0x62, 0x6e, 0x6d, 0x2c, 0x2e, 0x2f, 0x00, 0x00, 0x00, 0x00 }, // 3
{ 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 4
},
// shifted
{
{ 0x1b, 0x7e, 0x21, 0x40, 0x23, 0x24, 0x25, 0x5e, 0x26, 0x2a, 0x28, 0x29, 0x5f, 0x2b, 0x08, 0x7f }, // 0
{ 0x00, 0x09, 0x51, 0x57, 0x45, 0x52, 0x54, 0x59, 0x55, 0x49, 0x4f, 0x50, 0x7b, 0x7d, 0x00, 0x00 }, // 1
{ 0x00, 0x00, 0x41, 0x53, 0x44, 0x46, 0x47, 0x48, 0x4a, 0x4b, 0x4c, 0x3a, 0x22, 0x7c, 0x0d, 0x00 }, // 2
{ 0x00, 0x3e, 0x5a, 0x58, 0x43, 0x56, 0x42, 0x4e, 0x4d, 0x2c, 0x2e, 0x3f, 0x00, 0x00, 0x00, 0x00 }, // 3
{ 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 4
},
// unshifted-control
{
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0
{ 0x00, 0x00, 0x11, 0x17, 0x05, 0x12, 0x14, 0x19, 0x15, 0x09, 0x0f, 0x10, 0x1b, 0x1d, 0x00, 0x00 }, // 1
{ 0x00, 0x00, 0x01, 0x13, 0x04, 0x06, 0x07, 0x08, 0x0a, 0x0b, 0x0c, 0x00, 0x00, 0x1c, 0x00, 0x00 }, // 2
{ 0x00, 0x00, 0x1a, 0x18, 0x03, 0x16, 0x02, 0x0e, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 3
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 4
},
// shifted-control
{
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0
{ 0x00, 0x00, 0x11, 0x17, 0x05, 0x12, 0x14, 0x19, 0x15, 0x09, 0x0f, 0x10, 0x1b, 0x1d, 0x00, 0x00 }, // 1
{ 0x00, 0x00, 0x01, 0x13, 0x04, 0x06, 0x07, 0x08, 0x0a, 0x0b, 0x0c, 0x00, 0x00, 0x1c, 0x00, 0x00 }, // 2
{ 0x00, 0x00, 0x1a, 0x18, 0x03, 0x16, 0x02, 0x0e, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 3
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 4
}
};
INPUT_PORTS_START(interpro_en_us)
PORT_START("modifiers")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_CODE(KEYCODE_RCONTROL) PORT_NAME("Control") PORT_CHAR(UCHAR_MAMEKEY(LCONTROL))
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) PORT_NAME("Shift") PORT_CHAR(UCHAR_SHIFT_1)
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_CAPSLOCK) PORT_NAME("Caps Lock") PORT_TOGGLE PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK))
PORT_START("row_0")
PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_ESC) PORT_NAME("Esc") PORT_CHAR(UCHAR_MAMEKEY(ESC))
PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`') PORT_CHAR('~')
PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!')
PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@')
PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#')
PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$')
PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')
PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^')
PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&')
PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*')
PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(')
PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')')
PORT_BIT(0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_')
PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+')
PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSPACE) PORT_NAME("Backspace") PORT_CHAR(8)
PORT_BIT(0x8000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_DEL) PORT_NAME("Delete") PORT_CHAR(UCHAR_MAMEKEY(DEL))
PORT_START("row_1")
PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_UNUSED) // "Alt Mode"
PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_TAB) PORT_NAME("Tab") PORT_CHAR(9)
PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q')
PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W')
PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E')
PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R')
PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T')
PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y')
PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U')
PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I')
PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O')
PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P')
PORT_BIT(0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{')
PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}')
PORT_START("row_2")
PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_UNUSED) // CTRL
PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_UNUSED) // LOCK
PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A')
PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S')
PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D')
PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F')
PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G')
PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H')
PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J')
PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K')
PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L')
PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':')
PORT_BIT(0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('"')
PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') PORT_CHAR('|')
PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER) PORT_NAME("Return") PORT_CHAR(13)
PORT_START("row_3")
PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_UNUSED) // LSHIFT
PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('<') PORT_CHAR('>')
PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z')
PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X')
PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C')
PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V')
PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B')
PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N')
PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M')
PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',')
PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.')
PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?')
PORT_BIT(0x1000, IP_ACTIVE_HIGH, IPT_UNUSED) // RSHIFT
PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_UP) PORT_NAME("Up") PORT_CHAR(UCHAR_MAMEKEY(UP))
PORT_START("row_4")
PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_UNUSED) // "Hold Screen"
PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_UNUSED) // "Superimpose"
PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_UNUSED) // "Line Feed"
PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_NAME("Space") PORT_CHAR(UCHAR_MAMEKEY(SPACE))
PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_UNUSED) // "Repeat"
PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_LEFT) PORT_NAME("Left") PORT_CHAR(UCHAR_MAMEKEY(LEFT))
PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_DOWN) PORT_NAME("Down") PORT_CHAR(UCHAR_MAMEKEY(DOWN))
PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_RIGHT) PORT_NAME("Right") PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
INPUT_PORTS_END
INPUT_PORTS_START(hle_en_us_device)
PORT_INCLUDE(interpro_en_us)
INPUT_PORTS_END
} // anonymous namespace
hle_device_base::hle_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock)
: device_t(mconfig, type, tag, owner, clock)
, device_buffered_serial_interface(mconfig, *this)
, device_interpro_keyboard_port_interface(mconfig, *this)
, device_matrix_keyboard_interface(mconfig, *this, "row_0", "row_1", "row_2", "row_3", "row_4")
, m_click_timer(nullptr)
, m_beeper(*this, "beeper")
, m_make_count(0U)
, m_rx_state(RX_IDLE)
, m_keyclick(0U)
, m_beeper_state(0U)
{
}
hle_device_base::~hle_device_base()
{
}
WRITE_LINE_MEMBER(hle_device_base::input_txd)
{
device_buffered_serial_interface::rx_w(state);
}
MACHINE_CONFIG_MEMBER(hle_device_base::device_add_mconfig)
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
void hle_device_base::device_start()
{
m_click_timer = timer_alloc(CLICK_TIMER_ID);
save_item(NAME(m_make_count));
save_item(NAME(m_rx_state));
save_item(NAME(m_keyclick));
save_item(NAME(m_beeper_state));
}
void hle_device_base::device_reset()
{
// initialise state
clear_fifo();
m_make_count = 0U;
m_rx_state = RX_IDLE;
m_keyclick = 0U;
m_beeper_state = 0x00U;
// configure device_buffered_serial_interface
set_data_frame(START_BIT_COUNT, DATA_BIT_COUNT, PARITY, STOP_BITS);
set_rate(BAUD);
receive_register_reset();
transmit_register_reset();
// start with keyboard LEDs off
machine().output().set_led_value(LED_DISK, 0);
machine().output().set_led_value(LED_LOCK, 0);
machine().output().set_led_value(LED_UNKNOWN, 0);
machine().output().set_led_value(LED_L1, 0);
machine().output().set_led_value(LED_L2, 0);
machine().output().set_led_value(LED_L3, 0);
machine().output().set_led_value(LED_L4, 0);
// no beep
m_click_timer->reset();
// kick the base
reset_key_state();
start_processing(attotime::from_hz(1'200));
}
void hle_device_base::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
switch (id)
{
case CLICK_TIMER_ID:
m_beeper_state &= ~u8(BEEPER_CLICK);
m_beeper->set_state(m_beeper_state ? 1 : 0);
break;
default:
break;
}
}
void hle_device_base::tra_callback()
{
output_rxd(transmit_register_get_data_bit());
}
void hle_device_base::tra_complete()
{
if (fifo_full())
start_processing(attotime::from_hz(1'200));
device_buffered_serial_interface::tra_complete();
}
void hle_device_base::key_make(u8 row, u8 column)
{
// we should have stopped processing if we filled the FIFO
assert(!fifo_full());
// send the make code, click if desired
transmit_byte(translate(row, column));
if (m_keyclick)
{
m_beeper_state |= u8(BEEPER_CLICK);
m_beeper->set_state(m_beeper_state ? 1 : 0);
m_click_timer->reset(attotime::from_msec(5));
}
// count keys
++m_make_count;
assert(m_make_count);
}
void hle_device_base::key_break(u8 row, u8 column)
{
// we should have stopped processing if we filled the FIFO
assert(!fifo_full());
assert(m_make_count);
--m_make_count;
// check our counting
assert(are_all_keys_up() == !bool(m_make_count));
}
void hle_device_base::transmit_byte(u8 byte)
{
LOG("transmit_byte 0x%02x\n", byte);
device_buffered_serial_interface::transmit_byte(byte);
if (fifo_full())
stop_processing();
}
void hle_device_base::received_byte(u8 byte)
{
LOG("received_byte 0x%02x\n", byte);
switch (m_rx_state)
{
case RX_ESC:
switch (byte)
{
case 'B': // bell
m_rx_state = RX_BELL;
break;
case 'D': // diagnostic
transmit_byte(0xff);
transmit_byte(0x00);
m_rx_state = RX_IDLE;
break;
}
break;
case RX_BELL:
switch (byte)
{
case '(':
LOG("bell on\n");
m_beeper_state |= u8(BEEPER_BELL);
m_beeper->set_state(m_beeper_state ? 1 : 0);
break;
case ')':
LOG("bell off\n");
m_beeper_state &= ~u8(BEEPER_BELL);
m_beeper->set_state(m_beeper_state ? 1 : 0);
break;
default:
// FIXME: boot code sends 0x8, unknown meaning
break;
}
m_rx_state = RX_IDLE;
break;
case RX_IDLE:
if (byte == 0x1b)
m_rx_state = RX_ESC;
break;
}
}
hle_en_us_device::hle_en_us_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
: hle_device_base(mconfig, INTERPRO_HLE_EN_US_KEYBOARD, tag, owner, clock),
m_modifiers(*this, "modifiers")
{
}
ioport_constructor hle_en_us_device::device_input_ports() const
{
return INPUT_PORTS_NAME(hle_en_us_device);
}
u8 hle_en_us_device::translate(u8 row, u8 column)
{
u8 const modifiers(m_modifiers->read());
bool const ctrl(modifiers & 0x01);
bool const shift(bool(modifiers & 0x02) || (bool(modifiers & 0x04)));
bool const ctrl_shift(ctrl && shift);
unsigned const map(ctrl_shift ? 3 : ctrl ? 2 : shift ? 1 : 0);
return TRANSLATION_TABLE[map][row][column];
}
} } } // namespace bus::interpro::keyboard

View File

@ -0,0 +1,113 @@
// license:BSD-3-Clause
// copyright-holders:Patrick Mackinlay
#ifndef MAME_DEVICES_INTERPRO_KEYBOARD_HLE_H
#define MAME_DEVICES_INTERPRO_KEYBOARD_HLE_H
#pragma once
#include "keyboard.h"
#include "machine/keyboard.h"
#include "sound/beep.h"
namespace bus { namespace interpro { namespace keyboard {
class hle_device_base
: public device_t
, public device_buffered_serial_interface<16U>
, public device_interpro_keyboard_port_interface
, protected device_matrix_keyboard_interface<5U>
{
public:
virtual ~hle_device_base() override;
virtual DECLARE_WRITE_LINE_MEMBER(input_txd) override;
protected:
// constructor/destructor
hle_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock);
// device overrides
virtual void device_add_mconfig(machine_config &config) override;
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;
// device_buffered_serial_interface overrides
virtual void tra_callback() override;
virtual void tra_complete() override;
// device_matrix_keyboard_interface overrides
virtual void key_make(u8 row, u8 column) override;
virtual void key_break(u8 row, u8 column) override;
// customised transmit_byte method
void transmit_byte(u8 byte);
virtual u8 translate(u8 row, u8 column) = 0;
private:
enum {
CLICK_TIMER_ID = 30'000
};
enum : int {
LED_DISK = 0,
LED_LOCK,
LED_UNKNOWN,
LED_L1,
LED_L2,
LED_L3,
LED_L4
};
enum : u8 {
BEEPER_BELL = 0x01U,
BEEPER_CLICK = 0x02U
};
enum : u8 {
RX_IDLE,
RX_ESC,
RX_BELL
};
enum : u8 {
COMMAND_RESET = 0x01U,
COMMAND_BELL_ON = 0x02U,
COMMAND_BELL_OFF = 0x03U,
COMMAND_CLICK_ON = 0x0aU,
COMMAND_CLICK_OFF = 0x0bU,
COMMAND_LED = 0x0eU,
COMMAND_LAYOUT = 0x0fU
};
// device_buffered_serial_interface overrides
virtual void received_byte(u8 byte) override;
emu_timer *m_click_timer;
required_device<beep_device> m_beeper;
u8 m_make_count;
u8 m_rx_state;
u8 m_keyclick;
u8 m_beeper_state;
};
class hle_en_us_device : public hle_device_base
{
public:
hle_en_us_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
virtual ioport_constructor device_input_ports() const override;
virtual u8 translate(u8 row, u8 column) override;
required_ioport m_modifiers;
};
} } } // namespace bus::interpro::keyboard
DECLARE_DEVICE_TYPE_NS(INTERPRO_HLE_EN_US_KEYBOARD, bus::interpro::keyboard, hle_en_us_device)
#endif // MAME_DEVICES_INTERPRO_KEYBOARD_HLE_H

View File

@ -0,0 +1,67 @@
// license:BSD-3-Clause
// copyright-holders:Patrick Mackinlay
#include "emu.h"
#include "keyboard.h"
#define VERBOSE 0
#include "logmacro.h"
DEFINE_DEVICE_TYPE(INTERPRO_KEYBOARD_PORT, interpro_keyboard_port_device, "interpro_keyboard_port", "InterPro Keyboard Port")
int const device_interpro_keyboard_port_interface::START_BIT_COUNT;
int const device_interpro_keyboard_port_interface::DATA_BIT_COUNT;
device_serial_interface::parity_t const device_interpro_keyboard_port_interface::PARITY;
device_serial_interface::stop_bits_t const device_interpro_keyboard_port_interface::STOP_BITS;
int const device_interpro_keyboard_port_interface::BAUD;
interpro_keyboard_port_device::interpro_keyboard_port_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock)
: interpro_keyboard_port_device(mconfig, INTERPRO_KEYBOARD_PORT, tag, owner, clock)
{
}
interpro_keyboard_port_device::interpro_keyboard_port_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, type, tag, owner, clock)
, device_slot_interface(mconfig, *this)
, m_rxd_handler(*this)
, m_dev(nullptr)
{
}
interpro_keyboard_port_device::~interpro_keyboard_port_device()
{
}
void interpro_keyboard_port_device::device_config_complete()
{
m_dev = dynamic_cast<device_interpro_keyboard_port_interface *>(get_card_device());
}
void interpro_keyboard_port_device::device_start()
{
m_rxd_handler.resolve_safe();
save_item(NAME(m_rxd));
}
WRITE_LINE_MEMBER(interpro_keyboard_port_device::write_txd)
{
if (m_dev)
m_dev->input_txd(state);
}
device_interpro_keyboard_port_interface::device_interpro_keyboard_port_interface(machine_config const &mconfig, device_t &device)
: device_slot_card_interface(mconfig, device)
, m_port(dynamic_cast<interpro_keyboard_port_device *>(device.owner()))
{
}
device_interpro_keyboard_port_interface::~device_interpro_keyboard_port_interface()
{
}
#include "hle.h"
SLOT_INTERFACE_START(interpro_keyboard_devices)
SLOT_INTERFACE("hle_en_us", INTERPRO_HLE_EN_US_KEYBOARD)
SLOT_INTERFACE_END

View File

@ -0,0 +1,71 @@
// license:BSD-3-Clause
// copyright-holders:Patrick Mackinlay
#ifndef MAME_BUS_INTERPRO_KEYBOARD_KEYBOARD_H
#define MAME_BUS_INTERPRO_KEYBOARD_KEYBOARD_H
#pragma once
#define MCFG_INTERPRO_KEYBOARD_PORT_ADD(tag, slot_intf, def_slot) \
MCFG_DEVICE_ADD(tag, INTERPRO_KEYBOARD_PORT, 0) \
MCFG_DEVICE_SLOT_INTERFACE(slot_intf, def_slot, false)
#define MCFG_INTERPRO_KEYBOARD_RXD_HANDLER(cb) \
devcb = &interpro_keyboard_port_device::set_rxd_handler(*device, DEVCB_##cb);
class device_interpro_keyboard_port_interface;
class interpro_keyboard_port_device : public device_t, public device_slot_interface
{
friend class device_interpro_keyboard_port_interface;
public:
interpro_keyboard_port_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock);
virtual ~interpro_keyboard_port_device();
// static configuration helpers
template <class Object> static devcb_base &set_rxd_handler(device_t &device, Object &&cb) { return downcast<interpro_keyboard_port_device &>(device).m_rxd_handler.set_callback(std::forward<Object>(cb)); }
DECLARE_WRITE_LINE_MEMBER(write_txd);
protected:
interpro_keyboard_port_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, uint32_t clock);
virtual void device_start() override;
virtual void device_config_complete() override;
int m_rxd;
devcb_write_line m_rxd_handler;
private:
device_interpro_keyboard_port_interface *m_dev;
};
class device_interpro_keyboard_port_interface : public device_slot_card_interface
{
friend class interpro_keyboard_port_device;
public:
virtual ~device_interpro_keyboard_port_interface() override;
virtual DECLARE_WRITE_LINE_MEMBER(input_txd) { }
DECLARE_WRITE_LINE_MEMBER(output_rxd) { m_port->m_rxd = state; m_port->m_rxd_handler(state); }
protected:
device_interpro_keyboard_port_interface(machine_config const &mconfig, device_t &device);
interpro_keyboard_port_device *m_port;
static constexpr int START_BIT_COUNT = 1;
static constexpr int DATA_BIT_COUNT = 8;
static constexpr device_serial_interface::parity_t PARITY = device_serial_interface::PARITY_EVEN;
static constexpr device_serial_interface::stop_bits_t STOP_BITS = device_serial_interface::STOP_BITS_1;
static constexpr int BAUD = 1'200;
};
DECLARE_DEVICE_TYPE(INTERPRO_KEYBOARD_PORT, interpro_keyboard_port_device)
SLOT_INTERFACE_EXTERN(interpro_keyboard_devices);
#endif // MAME_BUS_INTERPRO_KEYBOARD_KEYBOARD_H

View File

@ -0,0 +1,199 @@
// license:BSD-3-Clause
// copyright-holders:Patrick Mackinlay
/*
* An emulation of GT graphics for Intergraph InterPro.
*
* TODO
* - control register (including primary/secondary buffer selection)
* - DP8510V BITBLT unit
* - custom Bresenham line drawing ASIC
* - support GT+, GTII, GTII+
*
*/
#include "emu.h"
#include "screen.h"
#include "gt.h"
#define VERBOSE 0
#include "logmacro.h"
DEVICE_ADDRESS_MAP_START(map, 32, mpcb963_device)
AM_RANGE(0x00000000, 0x0000007f) AM_READ(idprom_r)
AM_RANGE(0x00000080, 0x0000008f) AM_DEVICE8("ramdac0", bt459_device, map, 0xff)
AM_RANGE(0x000000b0, 0x000000b3) AM_READWRITE16(control_r, control_w, 0xffff)
//AM_RANGE(0x000000d4, 0x000000d7) AM_READWRITE8(, 0xff) // currently unknown
//AM_RANGE(0x000000a0, 0x000000a0) AM_READWRITE8(, 0xff) // currently unknown
AM_RANGE(0x00400000, 0x005fffff) AM_READWRITE(vram_r, vram_w)
ADDRESS_MAP_END
DEVICE_ADDRESS_MAP_START(map, 32, mpcba79_device)
AM_RANGE(0x00000000, 0x0000007f) AM_READ(idprom_r)
AM_RANGE(0x00000080, 0x0000008f) AM_DEVICE8("ramdac0", bt459_device, map, 0xff)
AM_RANGE(0x00000090, 0x0000009f) AM_DEVICE8("ramdac1", bt459_device, map, 0xff)
AM_RANGE(0x000000b0, 0x000000b3) AM_READWRITE16(control_r, control_w, 0xffff)
//AM_RANGE(0x000000d4, 0x000000d7) AM_READWRITE8(, 0xff) // currently unknown
//AM_RANGE(0x000000a0, 0x000000a0) AM_READWRITE8(, 0xff) // currently unknown
AM_RANGE(0x00400000, 0x007fffff) AM_READWRITE(vram_r, vram_w)
ADDRESS_MAP_END
ROM_START(mpcb963)
ROM_REGION(0x80, "idprom", 0)
ROM_LOAD32_BYTE("mpcb963a.bin", 0x0, 0x20, CRC(4cf4562d) SHA1(58bcc2afb66168f1d44a0366b6a5ccc4c22e0f32))
ROM_END
ROM_START(mpcba79)
ROM_REGION(0x80, "idprom", 0)
ROM_LOAD32_BYTE("mpcba79a.bin", 0x0, 0x20, CRC(b3b98324) SHA1(77b4ed0bbc6ed19646c4536d9976563f78961408))
ROM_END
DEFINE_DEVICE_TYPE(MPCB963, mpcb963_device, "mpcb963", "2000 Graphics f/1 1Mp Monitor")
DEFINE_DEVICE_TYPE(MPCBA79, mpcba79_device, "mpcba79", "2000 Graphics f/2 1Mp Monitors")
/*
* The screen data here is just a guess for now. Real values will need to be
* determined to ensure the cursor positions generated by the Bt459 are
* aligned properly on the screen.
*/
MACHINE_CONFIG_MEMBER(mpcb963_device::device_add_mconfig)
MCFG_SCREEN_ADD("screen0", RASTER)
MCFG_SCREEN_RAW_PARAMS(80'000'000, XRES, 0, XRES, YRES, 0, YRES)
MCFG_SCREEN_UPDATE_DEVICE("", mpcb963_device, screen_update0)
MCFG_DEVICE_ADD("ramdac0", BT459, 0)
MACHINE_CONFIG_END
MACHINE_CONFIG_MEMBER(mpcba79_device::device_add_mconfig)
MCFG_SCREEN_ADD("screen0", RASTER)
MCFG_SCREEN_RAW_PARAMS(80'000'000, XRES, 0, XRES, YRES, 0, YRES)
MCFG_SCREEN_UPDATE_DEVICE("", mpcba79_device, screen_update0)
MCFG_DEVICE_ADD("ramdac0", BT459, 0)
MCFG_SCREEN_ADD("screen1", RASTER)
MCFG_SCREEN_RAW_PARAMS(80'000'000, XRES, 0, XRES, YRES, 0, YRES)
MCFG_SCREEN_UPDATE_DEVICE("", mpcba79_device, screen_update1)
MCFG_DEVICE_ADD("ramdac1", BT459, 0)
MACHINE_CONFIG_END
gt_device_base::gt_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
sr_card_device_base(mconfig, type, tag, owner, clock)
{
}
mpcb963_device::mpcb963_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
gt_device_base(mconfig, MPCB963, tag, owner, clock),
m_screen
{
{ { *this, "ramdac0" }, {}, true }
}
{
}
const tiny_rom_entry *mpcb963_device::device_rom_region() const
{
return ROM_NAME(mpcb963);
}
void mpcb963_device::device_start()
{
gt_device_base::device_start();
m_screen[0].vram.reset(new u8[VRAM_SIZE]);
save_item(NAME(m_control));
save_pointer(NAME(m_screen[0].vram.get()), VRAM_SIZE);
}
WRITE16_MEMBER(mpcb963_device::control_w)
{
LOG("control_w 0x%04x\n", data);
m_control = data;
}
READ32_MEMBER(mpcb963_device::vram_r) const
{
return ((u32 *)m_screen[(offset >> 19) & 1].vram.get())[offset & 0x7ffff];
}
WRITE32_MEMBER(mpcb963_device::vram_w)
{
gt_screen_t &gt_screen = m_screen[(offset >> 19) & 1];
((u32 *)gt_screen.vram.get())[offset & 0x7ffff] = (((u32 *)gt_screen.vram.get())[offset & 0x7ffff] & ~mem_mask) | (data & mem_mask);
}
u32 mpcb963_device::screen_update0(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
gt_screen_t &gt_screen = m_screen[0];
gt_screen.ramdac->screen_update(screen, bitmap, cliprect, &gt_screen.vram[gt_screen.primary ? 0x000000 : 0x100000]);
return 0;
}
mpcba79_device::mpcba79_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
gt_device_base(mconfig, MPCBA79, tag, owner, clock),
m_screen
{
{ { *this, "ramdac0" },{}, true },
{ { *this, "ramdac1" },{}, true }
}
{
}
const tiny_rom_entry *mpcba79_device::device_rom_region() const
{
return ROM_NAME(mpcba79);
}
void mpcba79_device::device_start()
{
gt_device_base::device_start();
m_screen[0].vram.reset(new u8[VRAM_SIZE]);
m_screen[1].vram.reset(new u8[VRAM_SIZE]);
save_item(NAME(m_control));
save_pointer(NAME(m_screen[0].vram.get()), VRAM_SIZE);
save_pointer(NAME(m_screen[1].vram.get()), VRAM_SIZE);
}
WRITE16_MEMBER(mpcba79_device::control_w)
{
LOG("control_w 0x%04x\n", data);
m_control = data;
}
READ32_MEMBER(mpcba79_device::vram_r) const
{
return ((u32 *)m_screen[(offset >> 19) & 1].vram.get())[offset & 0x7ffff];
}
WRITE32_MEMBER(mpcba79_device::vram_w)
{
gt_screen_t &gt_screen = m_screen[(offset >> 19) & 1];
((u32 *)gt_screen.vram.get())[offset & 0x7ffff] = (((u32 *)gt_screen.vram.get())[offset & 0x7ffff] & ~mem_mask) | (data & mem_mask);
}
u32 mpcba79_device::screen_update0(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
gt_screen_t &gt_screen = m_screen[0];
gt_screen.ramdac->screen_update(screen, bitmap, cliprect, &gt_screen.vram[gt_screen.primary ? 0x000000 : 0x100000]);
return 0;
}
u32 mpcba79_device::screen_update1(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
gt_screen_t &gt_screen = m_screen[1];
gt_screen.ramdac->screen_update(screen, bitmap, cliprect, &gt_screen.vram[gt_screen.primary ? 0x000000 : 0x100000]);
return 0;
}

View File

@ -0,0 +1,110 @@
// license:BSD-3-Clause
// copyright-holders:Patrick Mackinlay
#ifndef MAME_BUS_INTERPRO_SR_GT_H
#define MAME_BUS_INTERPRO_SR_GT_H
#pragma once
#include "sr.h"
#include "video/bt459.h"
class gt_device_base : public sr_card_device_base
{
protected:
gt_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
public:
const int XRES = 1184;
const int YRES = 884;
const int VRAM_SIZE = 0x200000; // 1 megabyte double buffered
enum control_mask
{
CONTROL_SCREEN = 0x1000, // possibly selects screen 0 or 1?
CONTROL_BUSY = 0x8000
};
typedef struct
{
required_device<bt459_device> ramdac;
std::unique_ptr<u8[]> vram;
bool primary;
} gt_screen_t;
virtual DECLARE_READ16_MEMBER(control_r) const = 0;
virtual DECLARE_WRITE16_MEMBER(control_w) = 0;
//virtual DECLARE_READ8_MEMBER(dac_r) const = 0;
//virtual DECLARE_WRITE8_MEMBER(dac_w) = 0;
virtual DECLARE_READ32_MEMBER(vram_r) const = 0;
virtual DECLARE_WRITE32_MEMBER(vram_w) = 0;
// BSGA XLeft 0x104 (write)
// BSGA XLeft 0x10c (read)
};
class mpcb963_device : public gt_device_base
{
public:
mpcb963_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual DECLARE_ADDRESS_MAP(map, 32) override;
virtual DECLARE_READ16_MEMBER(control_r) const override { return m_control; }
virtual DECLARE_WRITE16_MEMBER(control_w) override;
//virtual DECLARE_READ8_MEMBER(dac_r) const override { return m_screen[0].ramdac->read(space, offset, mem_mask); }
//virtual DECLARE_WRITE8_MEMBER(dac_w) override { m_screen[0].ramdac->write(space, offset, data, mem_mask); }
virtual DECLARE_READ32_MEMBER(vram_r) const override;
virtual DECLARE_WRITE32_MEMBER(vram_w) override;
u32 screen_update0(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
protected:
virtual const tiny_rom_entry *device_rom_region() const override;
virtual void device_add_mconfig(machine_config &config) override;
virtual void device_start() override;
private:
u16 m_control;
gt_screen_t m_screen[1];
};
class mpcba79_device : public gt_device_base
{
public:
mpcba79_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual DECLARE_ADDRESS_MAP(map, 32) override;
virtual DECLARE_READ16_MEMBER(control_r) const override { return m_control; }
virtual DECLARE_WRITE16_MEMBER(control_w) override;
//virtual DECLARE_READ8_MEMBER(dac_r) const override { return m_screen[offset >> 2].ramdac->read(space, offset & 0x3, mem_mask); }
//virtual DECLARE_WRITE8_MEMBER(dac_w) override { m_screen[offset >> 2].ramdac->write(space, offset & 0x3, data, mem_mask); }
virtual DECLARE_READ32_MEMBER(vram_r) const override;
virtual DECLARE_WRITE32_MEMBER(vram_w) override;
u32 screen_update0(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
u32 screen_update1(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
protected:
virtual const tiny_rom_entry *device_rom_region() const override;
virtual void device_add_mconfig(machine_config &config) override;
virtual void device_start() override;
private:
u16 m_control;
gt_screen_t m_screen[2];
};
// device type definition
DECLARE_DEVICE_TYPE(MPCB963, mpcb963_device)
DECLARE_DEVICE_TYPE(MPCBA79, mpcba79_device)
#endif // MAME_BUS_INTERPRO_SR_GT_H

View File

@ -0,0 +1,379 @@
// license:BSD-3-Clause
// copyright-holders:Patrick Mackinlay
/*
* An initial very primitive emulation of the SR bus for the Intergraph
* InterPro.
*
* The bus is referred to by several different names at different places
* in the system code, such as SR, SR bus, SRX, SRX/C bus, CBUS and some
* variations on those. It's likely that SRX is an enhanced version of the
* original SR bus implementation, and that CBUS is an alternate name.
*
* SR bus devices are mapped into the host memory map at a fixed address
* range per slot, starting at 0x87000000 and incrementing by 0x08000000.
* Within this address range, the first 32 double words provide access to
* a 32 byte board signature area, with a format as follows.
*
* u8 board[8] first four bytes typically zero, next three bytes
* contain a board number (in ASCII) from the list
* below, last byte contains a revision character
* u8 eco[8] engineering change order bits; these are initially
* all set, and are cleared starting from the least
* significant bit of the first byte onward to indicate
* board level changes
* u8 feature[8] used for different purposes by different boards
* u8 reserved[2] always set to 0xff
* u16 family indicate the board type from the list below
* u8 footprint[4] the first three bytes contain the magic number 0x55
* 0xaa 0x55, the last byte contains the ones-complement
* of the sum of the other bytes as a checksum
*
* The following are the board families taken from the system boot ROM.
*
* Family Description
* ------ -----------
* 0x0000 I/O processor
* 0x0001 CLIX engine
* 0x0002 expansion memory
* 0x0003 floating-point engine
* 0x0004 pipe-starter
* 0x0005 integrated frame buffer
* 0x0006 32/CGX
* 0x0007 GRE integrated frame buffer
* 0x0008 hardcopy/digitizer
* 0x0009 plotter DMA I/F
* 0x000a A/V mux
* 0x000b image subsystem I/F
* 0x000c VME adapter
* 0x000d I/O processor
* 0x000e CLIX engine
* 0x000f frame grabber
* 0x0010 screen generator subsystem
* 0x0011 scanner I/F
* 0x0012 convolution filter
* 0x0013 non-linear filter
* 0x0014 run-length encoder
* 0x0015 color setter data board
* 0x0016 EDGE I
* 0x0017 6000-series system board
* 0x0018 32-channel async I/F
* 0x0019 SR QUAD SCSI I/F
* 0x001a FDDI I/F
* 0x001b EDGE II processor
* 0x001c EDGE II frame buffer
* 0x001d IOI
* 0x001e IOI Clix Engine
* 0x001f MAYA bus I/F unit
* 0x0020 comp/decomp group 4
* 0x0021 QWIC/SRX I/F
* 0x0022 SRX test board
* 0x0023 QWIC bus CPU
* 0x0024 2000-series system board
* 0x0025 2000-series graphics board
* 0x0026 E100/SRX device I/F
* 0x0027 IKOS H/W simulator I/F
* 0x0028 enhanced VME adapter
* 0x0029 QWIC expansion memory
* 0x002a image comp/decomp
* 0x002b teleconferencing controller
* 0x002c Sky 8115-I interface
* 0x002d C-bus token ring
* 0x002e Screen IV PressFax Subsystem
* 0x002f C400E CPU
* 0x0030 C-bus exp Ethernet
* 0x0031 2400-series CPU
* 0x0032 6400-series CPU
* 0x0033 6000-series GT Graphics
* 0x0034 C4K QWIC bus processor
* 0x0038 Visualization Processor
* 0x0039 2700-series CPU
* 0x0040 6700-series CPU
* 0x0041 2800-series CPU
* 0x0042 6700-series CPU
*
* The following are the board names taken from the showconfig.dat file
* shipped with the operating system.
*
* # Description
* --- -----------
* 004 EDGE-2 Processor f/2 2Mp-FB's
* 008 Image Memory VRAM Board
* 009 EDGE II Frame Buffer for ImageStation
* 010 VI50 Image Processor
* 014 SRX Quad-SCSI Controller
* 019 C4E CPU Assembly
* 030 EDGE-2 Processor f/1 or 2 1Mp-FB's
* 031 EDGE-2 Processor f/1 2Mp-FB
* 032 CBUS Token Ring
* 034 256MB QWIC Bus Expansion Memory
* 046 6400 36-MHz Series System Board
* 047 2400 Series System Board
* 068 2400 Graphics f/1 1Mp Monitor (V-60)
* 069 2400 Graphics f/2 1Mp Monitors (V-60)
* 070 2400 Graphics f/1 1Mp Monitor (V-76)
* 071 2400 Graphics f/2 1Mp Monitors (V-76)
* 081 2400 Graphics f/1 2Mp Monitor (V-60/76)
* 083 SRX Hard PC Option / 8 Mb
* 093 EDGE-2 Plus Processor f/1 or 2 1Mp-FB's
* 094 EDGE-2 Plus Processor f/1 2Mp-FB
* 095 EDGE-2 Plus Processor f/2 2Mp-FB's
* 096 EDGE-2 Plus Frame Buffer f/1Mp Monitor
* 098 6400 32-MHz Sapphire System Board
* 101 2400 Graphics f/1 1Mp Monitor (V-76)
* 100 2500 Series System Board
* 102 2400 Graphics f/2 1Mp Monitors (V-76)
* 106 C-Bus Series Hard PC Option / 8 Mb
* 112 SRX Fast Quad-SCSI Controller
* 115 Edge III Processor
* 116 Edge III-C Single Ramdac
* 126 SRX Enhanced VME Adapter
* 127 6700 Series System Board
* 128 2700 Series System Board
* 129 6800 Series System Board
* 135 GT II Graphics f/1 2Mp Monitor (V-60/76)
* 136 GT II Graphics f/2 2Mp Monitor (V-60/76)
* 144 6800 Series System Board
* 145 2800 Series System Board
* 217 C-Bus Hard PC Option / 16 Mb
* 218 SRX Hard PC Option / 16 Mb
* 512 32C Clix Engine w/6MB
* 543 Floating Point Engine
* 548 80386 I/O Processor
* 577 Analog Video Mux/Summer
* 588 80186 I/O Processor
* 595 Pipe Starter
* 604 Digitizer/HardCopy Controller
* 605 300 Series Clix Engine w/16MB
* 617 300 Series SR VME-Adapter
* 633 32MB Expansion Memory
* 636 80186 I/O Processor w/CoProcessor
* 641 Image Subsystem Interface
* 643 8Mb Integrated Frame Buffer f/1Mp
* 650 2Mb Integrated Frame Buffer f/1Mp
* 652 2Mb Integrated Frame Buffer f/1Mp
* 657 32C Clix Engine w/8MB
* 663 200 Series SR VME-Adapter
* 664 32C Clix Engine w/16MB
* 675 SR Plotter-DMA-Interface
* 677 32C Clix Engine w/6MB
* 686 8Mb Integrated Frame Buffer f/2Mp
* 693 Clix Engine w/8MB
* 694 Clix Engine w/16MB
* 722 SR Frame Grabber NTSC
* 730 300/400 Series Clix Engine w/8MB
* 732 Clix Engine w/16MB
* 739 16MB Expansion Memory
* 765 6000 System Board w/16MB
* 776 Runlength Encoder
* 777 Scanner Interface
* 778 Nonlinear Filter
* 779 SIP Convolution Filter
* 789 32C Clix Engine w/6MB
* 792 Digitizer/HardCopy Controller Plus
* 796 2Mb Integrated Frame Buffer f/1Mp -T
* 799 80386 I/O Processor -T
* 801 Clix Engine w/8MB
* 819 QWIC Bus Clix Engine w/256K CB CACHE
* 820 QWIC System Interface w/64MB ECC
* 821 SRX 32 Channel RS232 Controller
* 822 300 Series Clix Engine w/16MB ECC
* 823 300/400 Series Clix Engine w/8MB ECC
* 825 32C Clix Engine w/12MB
* 826 FDDI Communications Processor
* 828 EDGE-1 Graphics f/1 1Mp Monitor (55K/60)
* 837 Analog Video Mux/Summer -T
* 838 Floating Point Engine -T
* 844 32MB Expansion Memory -T
* 849 EDGE-1 Graphics f/1 2Mp Monitor (55K/60)
* 851 Clix Engine w/16MB ECC -T
* 852 Digitizer/HardCopy Controller Plus -T
* 853 Clix Engine w/16MB ECC -T
* 883 6000 System Board w/8MB
* 887 SR Frame Grabber PAL
* 894 Clix Engine w/16MB ECC
* 896 EDGE-2/Plus Frame Buffer f/2Mp Monitor (V-60)
* 897 EDGE-2 Processor f/1 2Mp-FB
* 904 EDGE-1 Graphics f/2 1Mp Monitors (55K/60)
* 905 SRX Frame Grabber NTSC
* 906 SRX Frame Grabber PAL
* 915 64MB QWIC Bus Expansion Memory
* 917 Input Output Interface
* 932 IOI Clix Engine w/16MB ECC
* 956 SRX Enhanced VME-Adapter
* 958 VME-Controller f/SRX Interface
* 962 2000 System Board
* 963 2000 Graphics f/1 1Mp Monitor
* 965 EDGE-1 Graphics f/1 1Mp Monitor (66K/72)
* 966 EDGE-1 Graphics f/2 1Mp Monitors (66K/72)
* 977 6000 System Board w/32MB parity
* 978 6000 System Board w/48MB parity
* 979 6000 System Board w/64MB parity
* 980 6200 System Board w/8MB parity
* 981 6200 System Board w/16MB parity
* 982 6200 System Board w/32MB parity
* 983 6200 System Board w/48MB parity
* 984 6200 System Board w/64MB parity
* 31275 Raster Data Board
* 31277 Screener III A Board
* 31277/8 Screener III A+B Board
* A59 200 Series Clix Engine w/16MB parity
* A61 200 Series Clix Engine w/8MB parity
* A63 EDGE-2 Frame Buffer f/1Mp Monitor (55K/60)
* A77 200 Series Clix Engine w/16MB
* A79 2000 Graphics f/2 1Mp Monitors
* A80 QWIC System Interface w/16MB ECC
* A81 300 Series Clix Engine w/16MB ECC
* A86 SRX Teleconferencing Controller
* A95 IOI Clix Engine w/32MB ECC
* A96 IOI Clix Engine w/64MB ECC
* B13 System Board w/16MB parity -T
* B14 System Board w/48MB parity -T
* B15 EDGE-1 Graphics f/1 1Mp Monitor (55K/60) -T
* B16 EDGE-1 Graphics f/2 1Mp Monitors (55K/60) -T
* B17 IOI Clix Engine w/16MB ECC -T
* B18 Input Output Interface -T
* B20 SRX 32 Channel RS232 Controller -T
* B21 FDDI Communications Processor -T
* B22 SRX Quad-SCSI Controller -T
* b23 JPEG Compression/Decompression I/F
* B50 Application-Specific Acceleration Proc. II
* B63 IOI Clix Engine w/64MB ECC -T
* B67 GT Plus Graphics f/1 1Mp Monitor (V-76)
* B68 GT II Graphics f/1 1Mp Monitor (V-76)
* B70 GT II Graphics f/2 1Mp Monitors (V-76)
* B92 GT II Graphics f/1 2Mp Monitor (V-60/76)
* B93 GT II Graphics f/2 2Mp Monitors (V-60/76)
* B99 NTSC Frame Grabber for 3000 Series
* C01 PAL Frame Grabber for 3000 series
* C02 NTSC Frame Grabber for 6000 series
* C03 PAL Frame Grabber for 6000 series
* c05 25Mhz GTII Graphics f/1 1Mp Monitor
* c06 25Mhz GTII Graphics f/2 1Mp Monitors
* C41 GTII 60/76Hz Graphics f/1 2Mp Monitor
* C42 GTII 60/76Hz Graphics f/2 2Mp Monitor
*
* TODO
* - general refactoring and rework to improve implementation
*/
#include "emu.h"
#include "sr.h"
#define VERBOSE 1
#include "logmacro.h"
DEFINE_DEVICE_TYPE(SR_SLOT, sr_slot_device, "sr_slot", "InterPro SR bus slot")
sr_slot_device::sr_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, SR_SLOT, tag, owner, clock)
, device_slot_interface(mconfig, *this)
, m_sr_tag(nullptr)
, m_sr_slottag(nullptr)
{
}
void sr_slot_device::static_set_sr_slot(device_t &device, const char *tag, const char *slottag)
{
sr_slot_device &sr_card = dynamic_cast<sr_slot_device &>(device);
sr_card.m_sr_tag = tag;
sr_card.m_sr_slottag = slottag;
}
void sr_slot_device::device_start()
{
device_sr_card_interface *dev = dynamic_cast<device_sr_card_interface *>(get_card_device());
if (dev)
device_sr_card_interface::static_set_sr_tag(*dev, m_sr_tag, m_sr_slottag);
}
DEFINE_DEVICE_TYPE(SR, sr_device, "sr", "InterPro SR bus")
sr_device::sr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, SR, tag, owner, clock),
m_data_space(nullptr),
m_io_space(nullptr),
m_out_irq0_cb(*this),
m_out_irq1_cb(*this),
m_out_irq2_cb(*this)
{
}
void sr_device::device_start()
{
// grab the main memory space from the mmu
device_memory_interface *mmu;
siblingdevice("mmu")->interface(mmu);
m_data_space = &mmu->space(0);
m_io_space = &mmu->space(1);
// resolve callbacks
m_out_irq0_cb.resolve_safe();
m_out_irq1_cb.resolve_safe();
m_out_irq2_cb.resolve_safe();
// empty the slots
m_slot_count = 0;
for (auto &slot : m_slot)
slot = nullptr;
}
void sr_device::device_reset()
{
}
void sr_device::install_idprom(device_t *dev, const char *tag, const char *region)
{
// compute slot base address
offs_t base = 0x87000000;
// map the idprom
m_data_space->install_read_bank(base, base + 0x7f, 0, tag);
m_data_space->unmap_write(base, base + 0x7f);
// assign the region
machine().root_device().membank(m_data_space->device().siblingtag(tag).c_str())->set_base(machine().root_device().memregion(dev->subtag(region).c_str())->base());
}
device_sr_card_interface::device_sr_card_interface(const machine_config &mconfig, device_t &device)
: device_slot_card_interface(mconfig, device)
, m_sr(nullptr)
, m_sr_tag(nullptr)
, m_sr_slottag(nullptr)
{
}
device_sr_card_interface::~device_sr_card_interface()
{
}
void device_sr_card_interface::static_set_sr_tag(device_t &device, const char *tag, const char *slottag)
{
device_sr_card_interface &sr_card = dynamic_cast<device_sr_card_interface &>(device);
sr_card.m_sr_tag = tag;
sr_card.m_sr_slottag = slottag;
}
void device_sr_card_interface::set_sr_device()
{
// get a reference to the bus
m_sr = dynamic_cast<sr_device *>(device().machine().device(m_sr_tag));
// install the card in the next available slot
m_sr->install_card(*this, &device_sr_card_interface::map);
}
sr_card_device_base::sr_card_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, const char *idprom_region)
: device_t(mconfig, type, tag, owner, clock)
, device_sr_card_interface(mconfig, *this)
, m_idprom_region(idprom_region)
{
}
void sr_card_device_base::device_start()
{
set_sr_device();
}

View File

@ -0,0 +1,139 @@
// license:BSD-3-Clause
// copyright-holders:Patrick Mackinlay
#ifndef MAME_BUS_INTERPRO_SR_SR_H
#define MAME_BUS_INTERPRO_SR_SR_H
#pragma once
#define MCFG_SR_OUT_IRQ0_CB(_devcb) \
devcb = &sr_device::set_out_irq0_callback(*device, DEVCB_##_devcb);
#define MCFG_SR_OUT_IRQ1_CB(_devcb) \
devcb = &sr_device::set_out_irq1_callback(*device, DEVCB_##_devcb);
#define MCFG_SR_OUT_IRQ2_CB(_devcb) \
devcb = &sr_device::set_out_irq2_callback(*device, DEVCB_##_devcb);
#define MCFG_SR_SLOT_ADD(_srtag, _tag, _slot_intf, _def_slot, _fixed) \
MCFG_DEVICE_ADD(_tag, SR_SLOT, 0) \
MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, _fixed) \
sr_slot_device::static_set_sr_slot(*device, _srtag, _tag);
#define MCFG_SR_SLOT_REMOVE(_tag) \
MCFG_DEVICE_REMOVE(_tag)
class sr_slot_device : public device_t, public device_slot_interface
{
public:
// construction/destruction
sr_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// inline configuration
static void static_set_sr_slot(device_t &device, const char *tag, const char *slottag);
protected:
sr_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
// device-level overrides
virtual void device_start() override;
// configuration
const char *m_sr_tag, *m_sr_slottag;
};
class device_sr_card_interface;
class sr_device : public device_t
{
public:
// construction/destruction
sr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// inline configuration
template <class Object> static devcb_base &set_out_irq0_callback(device_t &device, Object &&cb) { return downcast<sr_device &>(device).m_out_irq0_cb.set_callback(std::forward<Object>(cb)); }
template <class Object> static devcb_base &set_out_irq1_callback(device_t &device, Object &&cb) { return downcast<sr_device &>(device).m_out_irq1_cb.set_callback(std::forward<Object>(cb)); }
template <class Object> static devcb_base &set_out_irq2_callback(device_t &device, Object &&cb) { return downcast<sr_device &>(device).m_out_irq2_cb.set_callback(std::forward<Object>(cb)); }
DECLARE_WRITE_LINE_MEMBER(irq0_w) { m_out_irq0_cb(state); }
DECLARE_WRITE_LINE_MEMBER(irq1_w) { m_out_irq1_cb(state); }
DECLARE_WRITE_LINE_MEMBER(irq2_w) { m_out_irq2_cb(state); }
// helper functions for card devices
template <typename T> void install_card(T &device, void (T::*map)(address_map &map))
{
// record the device in the next free slot
m_slot[m_slot_count] = &device;
// compute slot base address
offs_t start = 0x87000000 + m_slot_count * 0x8000000;
offs_t end = start + 0x7ffffff;
// install the device address map
m_data_space->install_device(start, end, device, map, 32);
m_io_space->install_device(start, end, device, map, 32);
m_slot_count++;
}
void install_idprom(device_t *dev, const char *tag, const char *region);
protected:
sr_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
// internal state
address_space *m_data_space;
address_space *m_io_space;
devcb_write_line m_out_irq0_cb;
devcb_write_line m_out_irq1_cb;
devcb_write_line m_out_irq2_cb;
private:
device_sr_card_interface *m_slot[16];
int m_slot_count;
};
class device_sr_card_interface : public device_slot_card_interface
{
public:
// construction/destruction
virtual ~device_sr_card_interface();
virtual DECLARE_ADDRESS_MAP(map, 32) = 0;
void set_sr_device();
// inline configuration
static void static_set_sr_tag(device_t &device, const char *tag, const char *slottag);
protected:
device_sr_card_interface(const machine_config &mconfig, device_t &device);
sr_device *m_sr;
const char *m_sr_tag, *m_sr_slottag;
};
class sr_card_device_base : public device_t, public device_sr_card_interface
{
protected:
sr_card_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, const char *idprom_region = "idprom");
public:
READ32_MEMBER(idprom_r) { return device().memregion(m_idprom_region)->as_u32(offset); }
protected:
// device-level overrides
virtual void device_start() override;
private:
const char *const m_idprom_region;
};
DECLARE_DEVICE_TYPE(SR, sr_device)
DECLARE_DEVICE_TYPE(SR_SLOT, sr_slot_device)
#endif // MAME_BUS_INTERPRO_SR_SR_H

View File

@ -0,0 +1,24 @@
// license:BSD-3-Clause
// copyright-holders:Patrick Mackinlay
#include "emu.h"
#include "sr_cards.h"
// video
#include "gt.h"
// storage
// sound
// network
// communication ports
// other
SLOT_INTERFACE_START(sr_cards)
SLOT_INTERFACE("mpcb963", MPCB963)
SLOT_INTERFACE("mpcba79", MPCBA79)
SLOT_INTERFACE_END

View File

@ -0,0 +1,12 @@
// license:BSD-3-Clause
// copyright-holders:Patrick Mackinlay
#ifndef MAME_BUS_INTERPRO_SR_SR_CARDS_H
#define MAME_BUS_INTERPRO_SR_SR_CARDS_H
#pragma once
// supported devices
SLOT_INTERFACE_EXTERN(sr_cards);
#endif // MAME_BUS_INTERPRO_SR_SR_CARDS_H