Merge pull request #2154 from shattered/_b85368c

hp_ipc: de-skeletonize.
This commit is contained in:
ajrhacker 2017-03-16 23:35:15 -04:00 committed by GitHub
commit 1265aae040
16 changed files with 2438 additions and 30 deletions

View File

@ -715,6 +715,23 @@ if (BUSES["EP64"]~=null) then
end
---------------------------------------------------
--
--@src/devices/bus/hp_hil/hp_hil.h,BUSES["HPHIL"] = true
---------------------------------------------------
if (BUSES["HPHIL"]~=null) then
files {
MAME_DIR .. "src/devices/bus/hp_hil/hp_hil.cpp",
MAME_DIR .. "src/devices/bus/hp_hil/hp_hil.h",
MAME_DIR .. "src/devices/bus/hp_hil/hil_devices.cpp",
MAME_DIR .. "src/devices/bus/hp_hil/hil_devices.h",
MAME_DIR .. "src/devices/bus/hp_hil/hlekbd.cpp",
MAME_DIR .. "src/devices/bus/hp_hil/hlekbd.h",
}
end
---------------------------------------------------
--
--@src/devices/bus/generic/slot.h,BUSES["GENERIC"] = true

View File

@ -893,6 +893,18 @@ if (FORMATS["HECT_TAP"]~=null or _OPTIONS["with-tools"]) then
}
end
--------------------------------------------------
--
--@src/lib/formats/hp_ipc_dsk.h,FORMATS["HP_IPC_DSK"] = true
--------------------------------------------------
if (FORMATS["HP_IPC_DSK"]~=null or _OPTIONS["with-tools"]) then
files {
MAME_DIR.. "src/lib/formats/hp_ipc_dsk.cpp",
MAME_DIR.. "src/lib/formats/hp_ipc_dsk.h",
}
end
--------------------------------------------------
--
--@src/lib/formats/iq151_dsk.h,FORMATS["IQ151_DSK"] = true

View File

@ -364,6 +364,18 @@ if (VIDEOS["HLCD0538"]~=null) then
}
end
--------------------------------------------------
--
--@src/devices/video/hp1ll3.h,VIDEOS["HP1LL3"] = true
--------------------------------------------------
if (VIDEOS["HP1LL3"]~=null) then
files {
MAME_DIR .. "src/devices/video/hp1ll3.cpp",
MAME_DIR .. "src/devices/video/hp1ll3.h",
}
end
--------------------------------------------------
--
--@src/devices/video/huc6202.h,VIDEOS["HUC6202"] = true

View File

@ -301,6 +301,7 @@ VIDEOS["HD61830"] = true
VIDEOS["HD66421"] = true
VIDEOS["HLCD0515"] = true
VIDEOS["HLCD0538"] = true
VIDEOS["HP1LL3"] = true
VIDEOS["HUC6202"] = true
VIDEOS["HUC6260"] = true
VIDEOS["HUC6261"] = true
@ -652,6 +653,7 @@ BUSES["GAMEBOY"] = true
BUSES["GAMEGEAR"] = true
BUSES["GBA"] = true
BUSES["GENERIC"] = true
BUSES["HPHIL"] = true
BUSES["IEEE488"] = true
BUSES["IMI7000"] = true
BUSES["INTV"] = true
@ -797,6 +799,7 @@ FORMATS["GTP_CAS"] = true
FORMATS["HECTOR_MINIDISC"] = true
FORMATS["HECT_DSK"] = true
FORMATS["HECT_TAP"] = true
FORMATS["HP_IPC_DSK"] = true
FORMATS["IQ151_DSK"] = true
FORMATS["ITT3030_DSK"] = true
FORMATS["JVC_DSK"] = true

View File

@ -0,0 +1,11 @@
// license:BSD-3-Clause
// copyright-holders:Sergey Svishchev
#include "emu.h"
#include "hil_devices.h"
#include "hlekbd.h"
SLOT_INTERFACE_START(hp_hil_devices)
SLOT_INTERFACE(STR_KBD_HP_INTEGRAL, HP_IPC_HLE_KEYBOARD)
SLOT_INTERFACE_END

View File

@ -0,0 +1,25 @@
// license:BSD-3-Clause
// copyright-holders:Sergey Svishchev
/***************************************************************************
HP-HIL devices
***************************************************************************/
#ifndef __HP_HIL_DEVICES_H__
#define __HP_HIL_DEVICES_H__
#define STR_KBD_HP_46020A "hp_46020a" // ITF Keyboard
#define STR_KBD_HP_46021A "hp_46021a" // ITF Keyboard
#define STR_KBD_HP_46030A "hp_46030a" // Vectra Keyboard
#define STR_KBD_HP_INTEGRAL "hp_ipc_kbd" // Integral Keyboard
#define STR_MOUSE_HP_46060A "hp_46060a" // 2-button mouse
#define STR_MOUSE_HP_46060B "hp_46060b" // 3-button mouse
SLOT_INTERFACE_EXTERN(hp_hil_devices);
#endif /* __HP_HIL_DEVICES_H__ */

View File

@ -0,0 +1,412 @@
// license:BSD-3-Clause
// copyright-holders:Sergey Svishchev
#include "hlekbd.h"
#include "machine/keyboard.ipp"
/***************************************************************************
DEVICE TYPE GLOBALS
***************************************************************************/
device_type const HP_IPC_HLE_KEYBOARD = device_creator<bus::hp_hil::hle_hp_ipc_device>;
namespace bus { namespace hp_hil {
namespace {
/***************************************************************************
INPUT PORT DEFINITIONS
***************************************************************************/
// ID codes: A0h..BFh (HP-HIL reference, p. B-4) + (IPC Service Manual, p. 10-2)
INPUT_PORTS_START( id )
PORT_START("COL0")
PORT_DIPNAME( 0xff, 0xb7, "Layout" )
PORT_DIPSETTING( 0xBF, "US" )
PORT_DIPSETTING( 0xAF, "German" )
PORT_DIPSETTING( 0xB7, "UK" )
PORT_DIPSETTING( 0xBB, "French" )
PORT_DIPSETTING( 0xBD, "Katakana" )
PORT_DIPSETTING( 0xBE, "Latin Spanish" )
PORT_DIPSETTING( 0xA7, "Canadian English" )
PORT_DIPSETTING( 0xAB, "Italian" )
PORT_DIPSETTING( 0xAD, "Dutch" )
PORT_DIPSETTING( 0xAE, "Swedish" )
PORT_DIPSETTING( 0xB3, "European Spanish" )
PORT_DIPSETTING( 0xB5, "Belgian (Flemish)" )
PORT_DIPSETTING( 0xB6, "Finnish" )
PORT_DIPSETTING( 0xB4, "Swiss German" )
PORT_DIPSETTING( 0xBA, "Norwegian" )
PORT_DIPSETTING( 0xBC, "Danish" )
PORT_DIPSETTING( 0xB2, "Swiss French" )
INPUT_PORTS_END
INPUT_PORTS_START( basic )
// keycodes 90..9f
PORT_START("COL1")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Menu") PORT_CODE(KEYCODE_F9) PORT_CHAR(UCHAR_MAMEKEY(F9))
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("F4") PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4))
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("F3") PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3))
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("F2") PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2))
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("F1") PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1))
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("KP 8") PORT_CODE(KEYCODE_8_PAD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD))
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Stop")
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Print/Enter")
// keycodes a0..af
PORT_START("COL2")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("User/System") PORT_CODE(KEYCODE_F10) PORT_CHAR(UCHAR_MAMEKEY(F10))
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("F5") PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5))
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("F6") PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6))
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("F7") PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7))
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("F8") PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8))
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("KP 9") PORT_CODE(KEYCODE_9_PAD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD))
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Clear Line")
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Clear Display")
// keycodes b0..bf
PORT_START("COL3")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*')
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(')
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')')
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+')
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?')
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Backspace") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8)
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNUSED )
// keycodes c0..cf
PORT_START("COL4")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') PORT_CHAR(0x09) PORT_CHAR(0x09)
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') PORT_CHAR(0x0f) PORT_CHAR(0x0f)
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') PORT_CHAR(0x10) PORT_CHAR(0x10)
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{')
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}')
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("< >")
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNUSED )
// keycodes d0..df
PORT_START("COL5")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') PORT_CHAR(0x0a) PORT_CHAR(0x0a)
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') PORT_CHAR(0x0b) PORT_CHAR(0x0b)
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') PORT_CHAR(0x0c) PORT_CHAR(0x0c)
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('"')
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') PORT_CHAR('|')
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Return") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13)
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Home") PORT_CODE(KEYCODE_HOME) PORT_CHAR(UCHAR_MAMEKEY(HOME))
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNUSED )
// keycodes e0..ef
PORT_START("COL6")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') PORT_CHAR(0x0d) PORT_CHAR(0x0d)
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<')
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>')
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_')
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Select") PORT_CODE(KEYCODE_PLUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(PLUS_PAD))
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNUSED )
// keycodes f0..ff
PORT_START("COL7")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') PORT_CHAR(0x0e) PORT_CHAR(0x0e)
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Space") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("KP .") PORT_CODE(KEYCODE_DEL_PAD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD))
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Left") PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT))
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Down") PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN))
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Up") PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP))
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Right") PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
// keycodes 00..0f
PORT_START("COL8")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("KP 5") PORT_CODE(KEYCODE_5_PAD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD))
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Extend Char R")PORT_CODE(KEYCODE_RALT) PORT_CHAR(UCHAR_SHIFT_2)
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Extend Char L")PORT_CODE(KEYCODE_LALT) PORT_CHAR(UCHAR_SHIFT_2)
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("R Shift") PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_MAMEKEY(RSHIFT))
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("L Shift") PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Control") PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_MAMEKEY(LCONTROL))
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Break/Reset")
// keycodes 10..1f
PORT_START("COL9")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("KP 4") PORT_CODE(KEYCODE_4_PAD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD))
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("KP 7") PORT_CODE(KEYCODE_7_PAD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD))
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNUSED )
// keycodes 20..2f
PORT_START("COL10")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("KP 1") PORT_CODE(KEYCODE_1_PAD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD))
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("KP 2") PORT_CODE(KEYCODE_2_PAD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD))
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("KP 0") PORT_CODE(KEYCODE_0_PAD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD))
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNUSED )
// keycodes 30..3f
PORT_START("COL11")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') PORT_CHAR(0x02) PORT_CHAR(0x02)
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') PORT_CHAR(0x16) PORT_CHAR(0x16)
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') PORT_CHAR(0x03) PORT_CHAR(0x03)
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') PORT_CHAR(0x18) PORT_CHAR(0x18)
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') PORT_CHAR(0x1a) PORT_CHAR(0x1a)
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("DEL/Esc") PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC))
// keycodes 40..4f
PORT_START("COL12")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("KP 6") PORT_CODE(KEYCODE_6_PAD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD))
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("KP 3") PORT_CODE(KEYCODE_3_PAD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD))
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNUSED )
// keycodes 50..5f
PORT_START("COL13")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') PORT_CHAR(0x08) PORT_CHAR(0x08)
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') PORT_CHAR(0x07) PORT_CHAR(0x07)
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') PORT_CHAR(0x06) PORT_CHAR(0x06)
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') PORT_CHAR(0x04) PORT_CHAR(0x04)
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') PORT_CHAR(0x13) PORT_CHAR(0x13)
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') PORT_CHAR(0x01) PORT_CHAR(0x01)
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Caps Lock") PORT_CODE(KEYCODE_CAPSLOCK) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK))
// keycodes 60..6f
PORT_START("COL14")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') PORT_CHAR(0x15) PORT_CHAR(0x15)
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') PORT_CHAR(0x19) PORT_CHAR(0x19)
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') PORT_CHAR(0x14) PORT_CHAR(0x14)
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') PORT_CHAR(0x12) PORT_CHAR(0x12)
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') PORT_CHAR(0x05) PORT_CHAR(0x05)
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') PORT_CHAR(0x17) PORT_CHAR(0x17)
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') PORT_CHAR(0x11) PORT_CHAR(0x11)
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Tab") PORT_CODE(KEYCODE_TAB) PORT_CHAR(9)
// keycodes 70..7f
PORT_START("COL15")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&')
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^')
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$')
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#')
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@')
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!')
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`') PORT_CHAR('~')
INPUT_PORTS_END
INPUT_PORTS_START( hle_hp_ipc_device )
PORT_INCLUDE( basic )
PORT_INCLUDE( id )
INPUT_PORTS_END
} // anonymous namespace
/***************************************************************************
BASE HLE KEYBOARD DEVICE
***************************************************************************/
/*--------------------------------------------------
hle_device_base::hle_device_base
designated device constructor
--------------------------------------------------*/
hle_device_base::hle_device_base(machine_config const &mconfig, device_type type, char const *name, char const *tag, device_t *owner, uint32_t clock, char const *shortname, char const *source)
: device_t(mconfig, type, name, tag, owner, clock, shortname, source)
, device_hp_hil_interface(mconfig, *this)
, device_matrix_keyboard_interface(mconfig, *this, "COL1", "COL2", "COL3", "COL4", "COL5", "COL6", "COL7", "COL8", "COL9", "COL10", "COL11", "COL12", "COL13", "COL14", "COL15")
{ }
/*--------------------------------------------------
hle_device_base::~hle_device_base
destructor
--------------------------------------------------*/
hle_device_base::~hle_device_base()
{ }
/*--------------------------------------------------
hle_device_base::device_start
perform expensive initialisations, allocate
resources, register for save state
--------------------------------------------------*/
void hle_device_base::device_start()
{
set_hp_hil_mlc_device();
m_powerup = true;
m_passthru = false;
}
/*--------------------------------------------------
hle_device_base::device_reset
perform startup tasks, also used for host
requested reset
--------------------------------------------------*/
void hle_device_base::device_reset()
{
m_fifo.clear();
// kick the base
reset_key_state();
start_processing(attotime::from_hz(1'200));
}
/*--------------------------------------------------
hle_device_base::device_timer
handle timed events
--------------------------------------------------*/
void hle_device_base::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
device_matrix_keyboard_interface::device_timer(timer, id, param, ptr);
}
void hle_device_base::hil_write(uint16_t data)
{
int frames = 0;
// printf("rx from mlc %04X (%s %02X)\n", data, BIT(data, 11) ? "command" : "data", data & 255);
if (BIT(data, 11)) switch (data & 255)
{
case HPHIL_IFC:
m_powerup = false;
break;
case HPHIL_EPT:
m_passthru = true;
break;
case HPHIL_ELB:
m_passthru = false;
break;
case HPHIL_ACF+1:
m_device_id = data & 7;
m_device_id16 = m_device_id << 8;
m_hp_hil_mlc->hil_write((data & ~7) | ((data + 1) & 7));
return;
break;
case HPHIL_POL:
if (!m_fifo.empty())
{
m_hp_hil_mlc->hil_write(m_device_id16 | 0x40); // Keycode Set 1, no coordinate data
frames = 1;
while (!m_fifo.empty())
{
m_hp_hil_mlc->hil_write(m_device_id16 | m_fifo.dequeue());
frames++;
}
}
m_hp_hil_mlc->hil_write(HPMLC_W1_C | m_device_id16 | HPHIL_POL | ((data + frames) & 7));
return;
break;
case HPHIL_DSR:
m_device_id = m_device_id16 = 0;
m_powerup = true;
break;
case HPHIL_IDD:
m_hp_hil_mlc->hil_write(m_device_id16 | ioport("COL0")->read());
m_hp_hil_mlc->hil_write(m_device_id16 | 0);
break;
case HPHIL_DHR:
device_reset();
return;
break;
default:
logerror("command %02X unknown\n", data & 255);
break;
}
if (!m_passthru)
m_hp_hil_mlc->hil_write(data);
// else
// m_next->hil_write(data);
}
void hle_device_base::transmit_byte(uint8_t byte)
{
if (!m_fifo.full()) {
// printf("queuing %02X\n", byte);
m_fifo.enqueue(byte);
}
// else
// printf("queuing fail (fifo full)\n");
}
/*--------------------------------------------------
hle_device_base::key_make
handle a key being pressed
--------------------------------------------------*/
void hle_device_base::key_make(uint8_t row, uint8_t column)
{
transmit_byte((((row + 1) ^ 8) << 4) + (column << 1));
}
/*--------------------------------------------------
hle_device_base::key_break
handle a key being released
--------------------------------------------------*/
void hle_device_base::key_break(uint8_t row, uint8_t column)
{
transmit_byte((((row + 1) ^ 8) << 4) + (column << 1) + 1);
}
/***************************************************************************
HP INTEGRAL HLE KEYBOARD DEVICE
***************************************************************************/
/*--------------------------------------------------
hle_hp_ipc_device::hle_hp_ipc_device
abbreviated constructor
--------------------------------------------------*/
hle_hp_ipc_device::hle_hp_ipc_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock)
: hle_device_base(mconfig, HP_IPC_HLE_KEYBOARD, "HP Integral Keyboard (HLE)", tag, owner, clock, "hp_ipc_hle_kbd", __FILE__)
{ }
/*--------------------------------------------------
hle_hp_ipc_device::device_input_ports
get input ports for this device
--------------------------------------------------*/
ioport_constructor hle_hp_ipc_device::device_input_ports() const
{
return INPUT_PORTS_NAME(hle_hp_ipc_device);
}
} } // namespace bus::hp_hil

View File

@ -0,0 +1,60 @@
// license:BSD-3-Clause
// copyright-holders:Sergey Svishchev
#ifndef MAME_DEVICES_HP_HIL_HLEKBD_H
#define MAME_DEVICES_HP_HIL_HLEKBD_H
#pragma once
#include "hp_hil.h"
#include "machine/keyboard.h"
extern device_type const HP_IPC_HLE_KEYBOARD;
namespace bus { namespace hp_hil {
class hle_device_base
: public device_t
, public device_hp_hil_interface
, protected device_matrix_keyboard_interface<15U>
{
public:
protected:
// constructor/destructor
hle_device_base(machine_config const &mconfig, device_type type, char const *name, char const *tag, device_t *owner, uint32_t clock, char const *shortname, char const *source);
virtual ~hle_device_base() override;
// device overrides
virtual void device_start() override;
virtual void device_reset() override;
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
// device_matrix_keyboard_interface overrides
virtual void key_make(uint8_t row, uint8_t column) override;
virtual void key_break(uint8_t row, uint8_t column) override;
// device_hp_hil_interface overrides
virtual void hil_write(uint16_t data) override;
private:
// device_serial_interface uses 10'000 range
// device_matrix_keyboard_interface uses 20'000 range
void transmit_byte(uint8_t byte);
util::fifo<uint8_t, 8> m_fifo;
};
class hle_hp_ipc_device : public hle_device_base
{
public:
hle_hp_ipc_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock);
virtual ioport_constructor device_input_ports() const override;
};
} } // namespace bus::hp_hil
#endif // MAME_DEVICES_HP_HIL_HLEKBD_H

View File

@ -0,0 +1,282 @@
// license:BSD-3-Clause
// copyright-holders:Sergey Svishchev
/***************************************************************************
HP-HIL Keyboard connector interface
***************************************************************************/
#include "emu.h"
#include "hp_hil.h"
#define VERBOSE_DBG 0
#define DBG_LOG(N,M,A) \
do { \
if(VERBOSE_DBG>=N) \
{ \
if( M ) \
logerror("%11.6f at %s: %-10s",machine().time().as_double(),machine().describe_context(),(char*)M ); \
logerror A; \
} \
} while (0)
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
const device_type HP_HIL_SLOT = device_creator<hp_hil_slot_device>;
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// hp_hil_slot_device - constructor
//-------------------------------------------------
hp_hil_slot_device::hp_hil_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, HP_HIL_SLOT, "HP_HIL_SLOT", tag, owner, clock, "hp_hil_slot", __FILE__)
, device_slot_interface(mconfig, *this)
{
}
void hp_hil_slot_device::static_set_hp_hil_slot(device_t &device, device_t *owner, const char *mlc_tag)
{
hp_hil_slot_device &hp_hil = dynamic_cast<hp_hil_slot_device &>(device);
hp_hil.m_owner = owner;
hp_hil.m_mlc_tag = mlc_tag;
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void hp_hil_slot_device::device_start()
{
device_hp_hil_interface *dev = dynamic_cast<device_hp_hil_interface *>(get_card_device());
if (dev) device_hp_hil_interface::static_set_hp_hil_mlc(*dev,m_owner->subdevice(m_mlc_tag));
}
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
const device_type HP_HIL_MLC = device_creator<hp_hil_mlc_device>;
//-------------------------------------------------
// hp_hil_mlc_device - constructor
//-------------------------------------------------
hp_hil_mlc_device::hp_hil_mlc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, HP_HIL_MLC, "HP-HIL Master Link Controller", tag, owner, clock, "hp_hil", __FILE__)
, int_cb(*this)
, nmi_cb(*this)
{
}
void hp_hil_mlc_device::add_hp_hil_device( device_hp_hil_interface *device )
{
m_device_list.append(*device);
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void hp_hil_mlc_device::device_start()
{
// resolve callbacks
int_cb.resolve_safe();
nmi_cb.resolve_safe();
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void hp_hil_mlc_device::device_reset()
{
// FIFO contents are not initialized at powerup or reset
m_r2 = 0;
m_r3 = 0; // HPMLC_R3_NMI;
}
WRITE8_MEMBER(hp_hil_mlc_device::write)
{
device_hp_hil_interface *entry = m_device_list.first();
DBG_LOG(2,"Write", ("%d <- %02x\n", offset, data));
switch (offset)
{
case 0:
DBG_LOG(1,"Transmit", ("%scommand 0x%02x to device %d\n", !m_loop?"loopback ":"", data, m_w1 & 7));
if (m_loop & 2) // no devices on 2nd link loop
return;
if (m_loop == 0)
{
if (!m_fifo.full()) {
m_fifo.enqueue(data | (m_w1 << 8));
m_r3 |= HPMLC_R3_INT;
int_cb(ASSERT_LINE);
}
return;
}
if ((m_w1 & 7) == 0) // broadcast
{
while (entry)
{
entry->hil_write(data | (m_w1 << 8));
entry = entry->next();
}
} else
{
while (entry)
{
if (entry->device_id() == (m_w1 & 7))
entry->hil_write(data | (m_w1 << 8));
entry = entry->next();
}
}
break;
case 1:
m_w1 = data & 0xf;
break;
case 2:
m_w2 = data;
break;
case 3:
m_w3 = data;
break;
case 32: // loopback switch: bit 0 = loop0, bit 1 = loop1
m_loop = data;
break;
}
}
READ8_MEMBER(hp_hil_mlc_device::read)
{
uint8_t data = 0;
switch (offset)
{
case 0:
if (!m_fifo.empty())
data = m_fifo.dequeue() & 255;
break;
case 1:
if (!m_fifo.empty())
data = m_fifo.peek() >> 8;
break;
case 2:
data = m_r2;
m_r2 &= ~(HPMLC_R2_PERR|HPMLC_R2_FERR|HPMLC_R2_FOF);
break;
case 3:
data = m_r3;
m_r3 &= ~(HPMLC_R3_INT|HPMLC_R3_NMI|HPMLC_R3_LERR);
int_cb(CLEAR_LINE);
break;
}
DBG_LOG(2,"Read", ("%d == %02x\n", offset, data));
return data;
}
void hp_hil_mlc_device::hil_write(uint16_t data)
{
DBG_LOG(1,"Receive", ("%s %04X fifo %s\n",
BIT(data, 11)?"command":"data", data, m_fifo.full()?"full":(m_fifo.empty()?"empty":"ok")));
if (!m_fifo.full())
{
if (!BIT(data, 11))
{
m_fifo.enqueue(data);
}
else if (!m_fifo.empty() || !(m_w2 & HPMLC_W2_IPF))
{
m_fifo.enqueue(data);
m_r3 |= HPMLC_R3_INT;
m_w3 &= ~HPMLC_W3_APE;
int_cb(ASSERT_LINE);
}
}
else
{
m_r2 |= HPMLC_R2_FOF;
m_r3 |= HPMLC_R3_INT;
int_cb(ASSERT_LINE);
}
}
WRITE_LINE_MEMBER(hp_hil_mlc_device::ap_w)
{
if (state && (m_w3 & HPMLC_W3_APE))
{
device_hp_hil_interface *entry = m_device_list.first();
while (entry)
{
entry->hil_write(HPMLC_W1_C | HPHIL_POL);
entry = entry->next();
}
}
}
//**************************************************************************
// DEVICE PC KBD INTERFACE
//**************************************************************************
//-------------------------------------------------
// device_hp_hil_interface - constructor
//-------------------------------------------------
device_hp_hil_interface::device_hp_hil_interface(const machine_config &mconfig, device_t &device)
: device_slot_card_interface(mconfig, device)
, m_hp_hil_mlc(nullptr)
, m_hp_hil_mlc_dev(nullptr)
, m_next(nullptr)
{
}
//-------------------------------------------------
// ~device_hp_hil_interface - destructor
//-------------------------------------------------
device_hp_hil_interface::~device_hp_hil_interface()
{
}
void device_hp_hil_interface::static_set_hp_hil_mlc(device_t &device, device_t *mlc_device)
{
device_hp_hil_interface &hp_hil = dynamic_cast<device_hp_hil_interface &>(device);
hp_hil.m_hp_hil_mlc_dev = mlc_device;
}
void device_hp_hil_interface::set_hp_hil_mlc_device()
{
m_hp_hil_mlc = dynamic_cast<hp_hil_mlc_device *>(m_hp_hil_mlc_dev);
m_hp_hil_mlc->add_hp_hil_device(this);
}

View File

@ -0,0 +1,200 @@
// license:BSD-3-Clause
// copyright-holders:Sergey Svishchev
/***************************************************************************
HP-HIL Keyboard connector interface
***************************************************************************/
#pragma once
#ifndef __HP_HIL_H__
#define __HP_HIL_H__
#include "emu.h"
#define HPMLC_R1_OB 0x10
#define HPMLC_W1_C 0x0800
#define HPMLC_R2_PERR 0x01
#define HPMLC_R2_FERR 0x02
#define HPMLC_R2_FOF 0x04
#define HPMLC_W2_TEST 0x01
#define HPMLC_W2_IPF 0x04
#define HPMLC_R3_INT 0x01
#define HPMLC_R3_NMI 0x02
#define HPMLC_R3_LERR 0x04
#define HPMLC_W3_APE 0x02
// commands
#define HPHIL_IFC 0x00 // Interface Clear
#define HPHIL_EPT 0x01 // Enter Pass-Thru Mode
#define HPHIL_ELB 0x02 // Enter Loop-Back Mode
#define HPHIL_IDD 0x03 // Identify and Describe
#define HPHIL_DSR 0x04 // Device Soft Reset
#define HPHIL_PST 0x05 // Perform Self Test
#define HPHIL_RRG 0x06 // Read Register
#define HPHIL_WRG 0x07 // Write Register
#define HPHIL_ACF 0x08 // Auto Configure [08..0f]
#define HPHIL_POL 0x10 // Poll [10..1f]
#define HPHIL_RPL 0x20 // RePoll [20..2f]
#define HPHIL_RNM 0x30 // Report Name
#define HPHIL_RST 0x31 // Report Status
#define HPHIL_EXD 0x32 // Extended Describe
#define HPHIL_RSC 0x33 // Report Security Code
#define HPHIL_DKA 0x3D // Disable Keyswitch AutoRepeat
#define HPHIL_EK1 0x3E // Enable Keyswitch AutoRepeat 30cps
#define HPHIL_EK2 0x3F // Enable Keyswitch AutoRepeat 60cps
#define HPHIL_PR1 0x40 // Prompt 1..7 [40..46]
#define HPHIL_PRM 0x47 // Prompt (General Purpose)
#define HPHIL_AK1 0x48 // Acknowledge 1..7 [40..46]
#define HPHIL_ACK 0x4F // Acknowledge (General Purpose)
#define HPHIL_RIO 0xFA // Register I/O Error
#define HPHIL_SHR 0xFB // System Hard Reset
#define HPHIL_TER 0xFC // Transmission Error
#define HPHIL_CAE 0xFD // Configuration Address Error
#define HPHIL_DHR 0xFE // Device Hard Reset
/*
* init sequnce (p. 4-13)
*
* DHR
* IFC
* ACF
* IDD
* EXD
* EPT
* ELB
* RPL
* POL
* EPT
* ELB
*
*/
//**************************************************************************
// INTERFACE CONFIGURATION MACROS
//**************************************************************************
#define MCFG_HP_HIL_INT_CALLBACK(_devcb) \
devcb = &hp_hil_mlc_device::set_int_callback(*device, DEVCB_##_devcb);
#define MCFG_HP_HIL_NMI_CALLBACK(_devcb) \
devcb = &hp_hil_mlc_device::set_nmi_callback(*device, DEVCB_##_devcb);
#define MCFG_HP_HIL_SLOT_ADD(_mlc_tag, _tag, _slot_intf, _def_slot) \
MCFG_DEVICE_ADD(_tag, HP_HIL_SLOT, 0) \
MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, false) \
hp_hil_slot_device::static_set_hp_hil_slot(*device, owner, _mlc_tag);
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
class hp_hil_slot_device : public device_t,
public device_slot_interface
{
public:
// construction/destruction
hp_hil_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// device-level overrides
virtual void device_start() override;
// inline configuration
static void static_set_hp_hil_slot(device_t &device, device_t *owner, const char *mlc_tag);
protected:
// configuration
device_t *m_owner;
const char *m_mlc_tag;
};
// device type definition
extern const device_type HP_HIL_SLOT;
class device_hp_hil_interface;
class hp_hil_mlc_device : public device_t
{
public:
// construction/destruction
hp_hil_mlc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
~hp_hil_mlc_device() { m_device_list.detach_all(); }
template<class _Object> static devcb_base &set_int_callback(device_t &device, _Object object) { return downcast<hp_hil_mlc_device &>(device).int_cb.set_callback(object); }
template<class _Object> static devcb_base &set_nmi_callback(device_t &device, _Object object) { return downcast<hp_hil_mlc_device &>(device).nmi_cb.set_callback(object); }
void add_hp_hil_device(device_hp_hil_interface *device);
DECLARE_READ8_MEMBER(read);
DECLARE_WRITE8_MEMBER(write);
DECLARE_WRITE_LINE_MEMBER(ap_w);
void hil_write(uint16_t data);
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
simple_list<device_hp_hil_interface> m_device_list;
util::fifo<uint16_t, 16> m_fifo;
uint8_t m_r2, m_r3, m_w1, m_w2, m_w3, m_loop;
private:
devcb_write_line int_cb, nmi_cb;
};
// device type definition
extern const device_type HP_HIL_MLC;
// ======================> device_hp_hil_interface
class device_hp_hil_interface : public device_slot_card_interface
{
friend class hp_hil_mlc_device;
public:
// construction/destruction
device_hp_hil_interface(const machine_config &mconfig, device_t &device);
virtual ~device_hp_hil_interface();
device_hp_hil_interface *next() const { return m_next; }
void set_hp_hil_mlc_device();
// inline configuration
static void static_set_hp_hil_mlc(device_t &device, device_t *mlc_device);
virtual void hil_write(uint16_t data) { };
int device_id() { return m_device_id; };
hp_hil_mlc_device *m_hp_hil_mlc;
device_t *m_hp_hil_mlc_dev;
device_hp_hil_interface *m_next;
protected:
virtual void device_reset() { }
hp_hil_slot_device *m_slot;
int m_device_id;
uint16_t m_device_id16;
bool m_powerup;
bool m_passthru;
};
#endif /* __HP_HIL_H__ */

View File

@ -0,0 +1,713 @@
// license:BSD-3-Clause
// copyright-holders:Sergey Svishchev
/*
HP 1LL3-0005 GPU emulation.
Used by HP Integral PC, possibly other HP products.
On IPC, memory is 4 16Kx4bit DRAM chips = 32KB total (16K words),
but firmware probes memory size and can work with 128KB memory.
Undocumented "_desktop" mode requires this.
Capabilities:
- up to 1024x1024 px on screen
- lines
- rectangles
- area fill with user-defined pattern
- 16x16 user-defined proportional font, with automatic cursor
- 16x16 user-defined sprite for mouse cursor (not a sprite layer)
- windows with blitter (copy, fill and scroll) and clipping
To do:
. proper cursor and mouse pointers [cursor can be offset from the pen location]
+ variable width fonts [?? placed relative to current window]
+ basic lines
- patterned lines
. bit blits & scroll
. meaning of WRRR bits
. meaning of CONF data [+ autoconfiguration]
- interrupt generation
- realistic timing?
- &c.
*/
#include "emu.h"
#include "hp1ll3.h"
#include "screen.h"
//**************************************************************************
// MACROS / CONSTANTS
//**************************************************************************
#define VERBOSE_DBG 2 /* general debug messages */
#define DBG_LOG(N,M,A) \
do { \
if(VERBOSE_DBG>=N) \
{ \
if( M ) \
logerror("%11.6f at %s: %-16s",machine().time().as_double(),machine().describe_context(),(char*)M ); \
logerror A; \
} \
} while (0)
#define HPGPU_VRAM_SIZE 16384 // *4 // experiment
#define HPGPU_HORZ_TOTAL 512
#define HPGPU_VERT_TOTAL 256
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
// devices
const device_type HP1LL3 = device_creator<hp1ll3_device>;
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// hp1ll3_device - constructor
//-------------------------------------------------
hp1ll3_device::hp1ll3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, HP1LL3, "Hewlett-Package 1LL3-0005 GPU", tag, owner, clock, "hp1ll3", __FILE__)
, device_video_interface(mconfig, *this)
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void hp1ll3_device::device_start()
{
// register for state saving
save_item(NAME(m_conf));
machine().first_screen()->register_screen_bitmap(m_bitmap);
m_cursor.allocate(16, 16);
m_sprite.allocate(16, 16);
m_videoram = std::make_unique<uint16_t[]>(HPGPU_VRAM_SIZE*2); // x2 size to make WRWIN/RDWIN easier
}
void hp1ll3_device::device_reset()
{
m_input_ptr = m_command = 0;
m_sad = m_fad = m_dad = m_org = m_rr = m_udl = 0;
m_enable_video = m_enable_cursor = m_enable_sprite = m_busy = false;
}
inline void hp1ll3_device::point(int x, int y, int px)
{
uint16_t offset = m_sad;
offset += y*(HPGPU_HORZ_TOTAL/16) + (x >> 4);
if (px)
m_videoram[offset] |= (1 << (15-(x%16)));
else
m_videoram[offset] &= ~(1 << (15-(x%16)));
}
// Bresenham algorithm -- from ef9365.cpp
void hp1ll3_device::line(int x1, int y1, int x2, int y2)
{
int dx;
int dy,t;
int e;
int x,y;
int incy;
int diago,horiz;
unsigned char c1;
c1=0;
incy=1;
if(x2>x1)
dx = x2 - x1;
else
dx = x1 - x2;
if(y2>y1)
dy = y2 - y1;
else
dy = y1 - y2;
if( dy > dx )
{
t = y2;
y2 = x2;
x2 = t;
t = y1;
y1 = x1;
x1 = t;
t = dx;
dx = dy;
dy = t;
c1 = 1;
}
if( x1 > x2 )
{
t = y2;
y2 = y1;
y1 = t;
t = x1;
x1 = x2;
x2 = t;
}
horiz = dy<<1;
diago = ( dy - dx )<<1;
e = ( dy<<1 ) - dx;
if( y1 <= y2 )
incy = 1;
else
incy = -1;
x = x1;
y = y1;
if(c1)
{
do
{
point(y,x,m_udl);
if( e > 0 )
{
y = y + incy;
e = e + diago;
}
else
{
e = e + horiz;
}
x++;
} while( x <= x2 );
}
else
{
do
{
point(x,y,m_udl);
if( e > 0 )
{
y = y + incy;
e = e + diago;
}
else
{
e = e + horiz;
}
x++;
} while( x <= x2 );
}
return;
}
void hp1ll3_device::fill(int org_x, int org_y, int w, int h, int arg)
{
uint16_t gfx, offset, mask, max_x = org_x + w;
if (m_enable_cursor) bitblt(m_cursor_x, m_cursor_y, m_dad, 16, 16, RR_XOR);
if (m_enable_sprite) bitblt(m_sprite_x, m_sprite_y, m_dad + 16, 16, 16, RR_XOR);
for (int y = org_y; y < org_y + h; y++) {
gfx = m_videoram[m_dad + (0x10 * arg) + y%16];
if (m_rr == RR_COPYINVERTED) gfx ^= 0xffff;
for (int x = org_x; x < max_x;) {
mask = 0xffff;
offset = m_sad + m_org + y * (HPGPU_HORZ_TOTAL/16) + (x >> 4);
if (offset >= m_sad + (HPGPU_VERT_TOTAL * HPGPU_HORZ_TOTAL/WS))
DBG_LOG(0,"HPGPU",("buffer overflow in FILL: %04x (%d, %d)\n", offset, 16*x, y));
// clipping
if (x == org_x) {
mask >>= (org_x % WS);
x += (WS - (org_x % WS));
} else {
if ((max_x - x) < WS) {
mask &= ~((1 << (WS - (max_x % WS))) - 1);
}
x += WS;
}
m_videoram[offset] &= ~mask;
m_videoram[offset] |= gfx & mask;
}
}
if (m_enable_cursor) bitblt(m_cursor_x, m_cursor_y, m_dad, 16, 16, RR_XOR);
if (m_enable_sprite) bitblt(m_sprite_x, m_sprite_y, m_dad + 16, 16, 16, RR_XOR);
}
// sprite drawing -- source is 16x16 px max, no window clipping
void hp1ll3_device::bitblt(int dstx, int dsty, uint16_t srcaddr, int width, int height, int op)
{
uint16_t gfx, offset, mask;
int max_x, max_y;
max_x = dstx + width;
if (max_x >= HPGPU_HORZ_TOTAL)
max_x = HPGPU_HORZ_TOTAL;
max_y = dsty + height;
if (max_y >= HPGPU_VERT_TOTAL)
max_y = HPGPU_VERT_TOTAL;
for (int y = dsty; y < max_y; y++) {
mask = 0xffff;
gfx = m_videoram[srcaddr + y - dsty] & mask;
offset = m_sad + y * (HPGPU_HORZ_TOTAL/16) + (dstx >> 4);
if (offset >= m_sad + (HPGPU_VERT_TOTAL * HPGPU_HORZ_TOTAL/16))
DBG_LOG(0,"HPGPU",("buffer overflow in bitblt: %04x (%d, %d)\n", offset, 16*dstx, y));
// are we crossing word boundary?
if (dstx % 16) {
if (op == RR_XOR)
{
m_videoram[offset ] ^= gfx >> (dstx % 16);
m_videoram[offset + 1] ^= gfx << (16 - (dstx % 16));
}
} else {
if (op == RR_XOR)
{
m_videoram[offset] ^= (gfx & mask);
}
}
}
}
void hp1ll3_device::label(uint8_t chr, int width)
{
uint16_t x, gfx, bg = 0x3f, offset, font = m_fontdata + chr * 16;
int max_y = m_cursor_y + m_fontheight;
if (max_y >= m_window.org_y + m_window.height)
max_y = m_window.org_y + m_window.height - 1 - m_cursor_y;
else
max_y -= m_cursor_y;
if (m_enable_cursor) bitblt(m_cursor_x, m_cursor_y, m_dad, 16, 16, RR_XOR);
if (m_enable_sprite) bitblt(m_sprite_x, m_sprite_y, m_dad + 16, 16, 16, RR_XOR);
for (int y = 0; y < max_y; y++) {
x = m_cursor_x;
offset = m_sad + (m_cursor_y + y) * (HPGPU_HORZ_TOTAL/16) + (x >> 4);
gfx = m_videoram[font + y] >> (16 - width);
if (offset >= m_sad + (HPGPU_VERT_TOTAL * HPGPU_HORZ_TOTAL/16))
DBG_LOG(0,"HPGPU",("buffer overflow in LABEL: %04x (%d, %d)\n", offset, 16*x, y));
// are we crossing word boundary?
if ((x % 16) > (16 - width)) {
if (m_rr == RR_COPYINVERTED) {
m_videoram[offset ] |= bg >> ((x % 16) - (16 - width));
m_videoram[offset + 1] |= bg << (16 - ((x + width) % 16));
} else {
m_videoram[offset ] &= ~(bg>> ((x % 16) - (16 - width)));
m_videoram[offset + 1] &= ~(bg<< (16 - ((x + width) % 16)));
}
m_videoram[offset ] ^= gfx >> ((x % 16) - (16 - width));
m_videoram[offset + 1] ^= gfx << (16 - ((x + width) % 16));
} else {
if (m_rr == RR_COPYINVERTED) {
m_videoram[offset ] |= bg << ((16 - width) - (x % 16));
} else {
m_videoram[offset ] &= ~(bg<< ((16 - width) - (x % 16)));
}
m_videoram[offset ] ^= gfx << ((16 - width) - (x % 16));
}
}
m_cursor_x += width;
if (m_enable_cursor) bitblt(m_cursor_x, m_cursor_y, m_dad, 16, 16, RR_XOR);
if (m_enable_sprite) bitblt(m_sprite_x, m_sprite_y, m_dad + 16, 16, 16, RR_XOR);
}
uint32_t hp1ll3_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
int x, y, offset;
uint16_t gfx, *p;
if (!m_enable_video) {
bitmap.fill(rgb_t::black());
return 0;
}
// XXX last line is not actually drawn on real hw
for (y = 0; y < HPGPU_VERT_TOTAL-1; y++) {
offset = m_sad + y*(HPGPU_HORZ_TOTAL/16);
p = &m_bitmap.pix16(y);
for (x = offset; x < offset + HPGPU_HORZ_TOTAL/16; x++)
{
gfx = m_videoram[x];
*p++ = BIT(gfx, 15);
*p++ = BIT(gfx, 14);
*p++ = BIT(gfx, 13);
*p++ = BIT(gfx, 12);
*p++ = BIT(gfx, 11);
*p++ = BIT(gfx, 10);
*p++ = BIT(gfx, 9);
*p++ = BIT(gfx, 8);
*p++ = BIT(gfx, 7);
*p++ = BIT(gfx, 6);
*p++ = BIT(gfx, 5);
*p++ = BIT(gfx, 4);
*p++ = BIT(gfx, 3);
*p++ = BIT(gfx, 2);
*p++ = BIT(gfx, 1);
*p++ = BIT(gfx, 0);
}
}
copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect);
return 0;
}
//-------------------------------------------------
// read - register read
//-------------------------------------------------
/*
* offset 0: CSR
*
* bit 0 gpu is busy
* bit 1 data is ready
* bit 3 vert blank time
* bit 7 out of window
*
* offset 2: data
*/
READ8_MEMBER( hp1ll3_device::read )
{
uint8_t data = 0;
switch (offset)
{
case 0:
data = m_busy ? 1 : 0;
data |= 2;
data |= (m_screen->vblank() ? 8 : 0);
break;
case 2:
switch (m_command)
{
case RDMEM:
if (m_memory_ptr < HPGPU_VRAM_SIZE*2) {
if (m_memory_ptr & 1) {
data = m_videoram[m_memory_ptr >> 1] & 0xff;
} else {
data = m_videoram[m_memory_ptr >> 1] >> 8;
}
m_memory_ptr++;
}
break;
}
}
DBG_LOG(1,"HPGPU", ("R @ %d == %02x\n", offset, data));
return data;
}
//-------------------------------------------------
// write - register write
//-------------------------------------------------
WRITE8_MEMBER( hp1ll3_device::write )
{
DBG_LOG(1,"HPGPU", ("W @ %d <- %02x\n", offset, data));
switch (offset)
{
case 0:
command(data);
break;
case 2:
switch (m_command)
{
case CONF:
if (m_conf_ptr & 1) {
m_conf[m_conf_ptr >> 1] |= data;
} else {
m_conf[m_conf_ptr >> 1] = data << 8;
}
if (m_conf_ptr++ == 22) {
DBG_LOG(2,"HPGPU",("CONF data received: %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X\n",
m_conf[0], m_conf[1], m_conf[2], m_conf[3],
m_conf[4], m_conf[5], m_conf[6], m_conf[7],
m_conf[8], m_conf[9], m_conf[10]));
}
break;
case WRMEM:
if (m_memory_ptr < HPGPU_VRAM_SIZE*2) {
if (m_memory_ptr & 1) {
m_videoram[m_memory_ptr >> 1] |= data;
} else {
m_videoram[m_memory_ptr >> 1] = data << 8;
}
m_memory_ptr++;
}
break;
default:
switch (m_input_ptr)
{
case 0:
m_input[0] = data << 8;
break;
case 1:
m_input[0] |= data;
break;
case 2:
m_input[1] = data << 8;
break;
case 3:
m_input[1] |= data;
break;
}
DBG_LOG(2,"HPGPU",("wrote %02x at %d, input buffer is %04X %04X\n", data, m_input_ptr, m_input[0], m_input[1]));
m_input_ptr++;
}
}
}
void hp1ll3_device::command(int command)
{
int c, w;
switch (command)
{
// type 0 commands -- no data
case NOP:
DBG_LOG(2,"HPGPU",("command: NOP [%d, 0x%x]\n", command, command));
switch (m_command)
{
case RDMEM:
DBG_LOG(1,"HPGPU",("RDMEM of %d words at %04X complete\n", (m_memory_ptr >> 1) - m_input[0], m_input[0]));
break;
case WRMEM:
DBG_LOG(1,"HPGPU",("WRMEM of %d words to %04X complete\n", (m_memory_ptr >> 1) - m_input[0], m_input[0]));
break;
}
break;
case DISVID:
DBG_LOG(2,"HPGPU",("command: DISVID [%d, 0x%x]\n", command, command));
m_enable_video = false;
break;
case ENVID:
DBG_LOG(2,"HPGPU",("command: ENVID [%d, 0x%x]\n", command, command));
DBG_LOG(1,"HPGPU",("enable video; SAD %04x FAD %04x DAD %04x ORG %04x UDL %04x RR %04x\n",
m_sad, m_fad, m_dad, m_org, m_udl, m_rr));
m_enable_video = true;
break;
case DISSP:
DBG_LOG(2,"HPGPU",("command: DISSP [%d, 0x%x]\n", command, command));
if (m_enable_sprite) {
bitblt(m_sprite_x, m_sprite_y, m_dad + 16, 16, 16, RR_XOR);
m_enable_sprite = false;
}
break;
case ENSP:
DBG_LOG(2,"HPGPU",("command: ENSP [%d, 0x%x]\n", command, command));
if (m_enable_sprite) {
bitblt(m_sprite_x, m_sprite_y, m_dad + 16, 16, 16, RR_XOR);
}
bitblt(m_sprite_x, m_sprite_y, m_dad + 16, 16, 16, RR_XOR);
m_enable_sprite = true;
DBG_LOG(1,"HPGPU",("enable sprite; cursor %d,%d sprite %d,%d\n", m_cursor_x, m_cursor_y, m_sprite_x, m_sprite_y));
break;
case DISCURS:
DBG_LOG(2,"HPGPU",("command: DISCURS [%d, 0x%x]\n", command, command));
if (m_enable_cursor) {
bitblt(m_cursor_x, m_cursor_y, m_dad, 16, 16, RR_XOR);
m_enable_cursor = false;
}
break;
case ENCURS:
DBG_LOG(2,"HPGPU",("command: ENCURS [%d, 0x%x]\n", command, command));
if (m_enable_cursor) {
bitblt(m_cursor_x, m_cursor_y, m_dad, 16, 16, RR_XOR);
}
bitblt(m_cursor_x, m_cursor_y, m_dad, 16, 16, RR_XOR);
m_enable_cursor = true;
DBG_LOG(1,"HPGPU",("enable cursor; cursor %d,%d sprite %d,%d\n", m_cursor_x, m_cursor_y, m_sprite_x, m_sprite_y));
break;
// type 1 commands -- 1 word of data expected in the buffer
// start of screen memory
case WRSAD:
DBG_LOG(2,"HPGPU",("command: WRSAD [%d, 0x%x] (0x%04x)\n", command, command, m_input[0]));
m_sad = m_input[0];
break;
// start of font memory
case WRFAD:
DBG_LOG(2,"HPGPU",("command: WRFAD [%d, 0x%x] (0x%04x)\n", command, command, m_input[0]));
m_fad = m_input[0];
m_fontheight = m_videoram[m_fad];
m_fontdata = m_fad + m_videoram[m_fad + 1] + 2;
DBG_LOG(1,"HPGPU",("font data set: FAD %04X header %d bitmaps %04X height %d\n",
m_fad, m_videoram[m_fad + 1], m_fontdata, m_fontheight));
break;
// start of data area
case WRDAD:
DBG_LOG(2,"HPGPU",("command: WRDAD [%d, 0x%x] (0x%04x)\n", command, command, m_input[0]));
m_dad = m_input[0];
break;
// ??
case WRORG:
DBG_LOG(2,"HPGPU",("command: WRORG [%d, 0x%x] (0x%04x)\n", command, command, m_input[0]));
m_org = m_input[0];
break;
// set replacement rule (raster op)
case WRRR:
DBG_LOG(2,"HPGPU",("command: WRRR [%d, 0x%x] (0x%04x)\n", command, command, m_input[0]));
m_rr = m_input[0];
break;
// set user-defined line pattern
case WRUDL:
DBG_LOG(2,"HPGPU",("command: WRUDL [%d, 0x%x] (0x%04x)\n", command, command, m_input[0]));
m_udl = m_input[0];
break;
// area fill
case FILL:
DBG_LOG(2,"HPGPU",("command: FILL [%d, 0x%x] (0x%04x) from (%d,%d) size (%d,%d) rop 0x%x\n",
command, command, m_input[0],
m_window.org_x, m_window.org_y, m_window.width, m_window.height, m_rr));
fill(m_window.org_x, m_window.org_y, m_window.width, m_window.height, m_input[0]);
break;
case LABEL:
DBG_LOG(2,"HPGPU",("command: LABEL [%d, 0x%x] (0x%04x, '%c') at %d,%d\n", command, command, m_input[0],
(m_input[0]<32||m_input[0]>127) ? ' ' : m_input[0], m_cursor_x, m_cursor_y));
c = m_input[0] & 255;
w = (c & 1) ?
(m_videoram[m_fad + 2 + (c>>1)] & 255) :
(m_videoram[m_fad + 2 + (c>>1)] >> 8);
label(c, w);
break;
// type 2 commands -- 2 words of data expected in the buffer
case DRAWPX:
DBG_LOG(2,"HPGPU",("command: DRAWPX [%d, 0x%x] (%d, %d)\n", command, command, m_input[0], m_input[1]));
point(m_input[0], m_input[1],(m_rr != RR_COPYINVERTED));
break;
// set window size
case WRWINSIZ:
DBG_LOG(2,"HPGPU",("command: WRWINSIZ [%d, 0x%x] (%d, %d)\n", command, command, m_input[0], m_input[1]));
m_window.width = m_input[0];
m_window.height = m_input[1];
break;
// set window origin
case WRWINORG:
DBG_LOG(2,"HPGPU",("command: WRWINORG [%d, 0x%x] (%d, %d)\n", command, command, m_input[0], m_input[1]));
m_window.org_x = m_input[0];
m_window.org_y = m_input[1];
break;
// move pointer absolute
case MOVEP:
DBG_LOG(2,"HPGPU",("command: MOVEP [%d, 0x%x] (%d, %d)\n", command, command, m_input[0], m_input[1]));
if (m_enable_cursor) bitblt(m_cursor_x, m_cursor_y, m_dad, 16, 16, RR_XOR);
if (m_enable_sprite) bitblt(m_sprite_x, m_sprite_y, m_dad + 16, 16, 16, RR_XOR);
m_cursor_x = m_input[0];
m_cursor_y = m_input[1];
if (m_enable_cursor) bitblt(m_cursor_x, m_cursor_y, m_dad, 16, 16, RR_XOR);
if (m_enable_sprite) bitblt(m_sprite_x, m_sprite_y, m_dad + 16, 16, 16, RR_XOR);
break;
// move sprite absolute
case MOVESP:
DBG_LOG(2,"HPGPU",("command: MOVESP [%d, 0x%x] (%d, %d)\n", command, command, m_input[0], m_input[1]));
m_sprite_x = m_input[0];
m_sprite_y = m_input[1];
break;
// draw to ...
case DRAWP:
DBG_LOG(2,"HPGPU",("command: DRAWP [%d, 0x%x] (%d, %d) to (%d, %d)\n",
command, command, m_cursor_x, m_cursor_y, m_input[0], m_input[1]));
line(m_cursor_x, m_cursor_y, m_input[0], m_input[1]);
m_cursor_x = m_input[0];
m_cursor_y = m_input[1];
break;
// type 3 command -- CONF -- accept configuration parameters (11 words)
case CONF:
m_conf_ptr = 0;
break;
// type 4 commands -- like type 1 plus data is read or written after command, terminated by NOP
case RDMEM:
case WRMEM:
DBG_LOG(2,"HPGPU",("command: %s [%d, 0x%x] (0x%04x)\n",
command == RDMEM?"RDMEM":"WRMEM", command, command, m_input[0]));
m_memory_ptr = m_input[0] << 1; // memory is word-addressable
break;
default:
DBG_LOG(1,"HPGPU",("command: UNKNOWN [%d, 0x%x]\n", command, command));
break;
}
m_input_ptr = 0;
m_command = command;
}

176
src/devices/video/hp1ll3.h Normal file
View File

@ -0,0 +1,176 @@
// license:BSD-3-Clause
// copyright-holders:Sergey Svishchev
/***************************************************************************
HP 1LL3-0005 GPU emulation.
***************************************************************************/
#pragma once
#ifndef __HP1LL3_H__
#define __HP1LL3_H__
///*************************************************************************
// MACROS / CONSTANTS
///*************************************************************************
/*
* command types (send)
*
* 0 -- no data
* 1 -- write 1 word of data, then command
* 2 -- write 2 words of data, then command
* 3 -- write command, then 11 words of data (= CONF only?)
* 4 -- write 1 word of data, then command, then write X words of data, then write NOP
*
* (read)
*
* 3 -- ???
* 4 -- write 1 word of data, then command, then read X words of data, then write NOP
*/
#define NOP 0 // type 0
#define CONF 2 // type 3, configure GPU (screen size, timings...). 11 words of data.
#define DISVID 3 // type 0, disable video
#define ENVID 4 // type 0, enable video
#define WRMEM 7 // type 4, write GPU memory at offset, terminate by NOP
#define RDMEM 8 // type 4, read GPU memory from offset, terminate by NOP
#define WRSAD 9 // type 1, set screen area start address
#define WRORG 10 // type 1, set ???
#define WRDAD 11 // type 1, set data area start address (16x16 area fill, sprite and cursor)
#define WRRR 12 // type 1, set replacement rule (rasterop)
#define MOVEP 13 // type 2, move pointer
#define IMOVEP 14
#define DRAWP 15 // type 2, draw line
#define IDRAWP 16
#define RDP 17
#define WRUDL 18 // type 1, set user-defined line pattern (16-bit)
#define WRWINSIZ 19 // type 2, set ???
#define WRWINORG 20 // type 2, set ???
#define COPY 21 // type 2
#define FILL 22 // type 1, fill area
#define FRAME 23 // type _, draw rectangle
#define SCROLUP 24 // type 2
#define SCROLDN 25 // type 2
#define SCROLLF 26 // type 2
#define SCROLRT 27 // type 2
#define RDWIN 28 // type 1
#define WRWIN 29 // type 1
#define RDWINPARM 30
#define CR 31
#define CRLFx 32
#define LABEL 36 // type 1, draw text
#define ENSP 38 // type 0, enable sprite
#define DISSP 39 // type 0, disable sprite
#define MOVESP 40 // type 2, move sprite
#define IMOVESP 41
#define RDSP 42
#define DRAWPX 43 // type _, draw single pixel
#define WRFAD 44 // type 1, set font area start address
#define ENCURS 45 // type 0
#define DISCURS 46 // type 0
#define ID 63
/*
* Replacement Rules (rops). sources:
*
* - NetBSD's diofbvar.h (definitions for Topcat chip)
* - pdf/hp/9000_300/specs/A-5958-4362-9_Series_300_Display_Color_Card_Theory_of_Operation_Oct85.pdf
* refers to TOPCAT documentation p/n A-1FH2-2001-7 (not online)
*/
#define RR_FORCE_ZERO 0x0
#define RR_CLEAR RR_FORCE_ZERO
#define RR_AND 0x1
#define RR_AND_NOT_OLD 0x2
#define RR_NEW 0x3
#define RR_COPY RR_NEW
#define RR_AND_NOT_NEW 0x4
#define RR_OLD 0x5
#define RR_XOR 0x6
#define RR_OR 0x7
#define RR_NOR 0x8
#define RR_XNOR 0x9
#define RR_NOT_OLD 0xa
#define RR_INVERT RR_NOT_OLD
#define RR_OR_NOT_OLD 0xb
#define RR_NOT_NEW 0xc
#define RR_COPYINVERTED RR_NOT_NEW
#define RR_OR_NOT_NEW 0xd
#define RR_NAND 0xe
#define RR_FORCE_ONE 0xf
#define WS 16 // bits in a word
///*************************************************************************
// INTERFACE CONFIGURATION MACROS
///*************************************************************************
#define MCFG_HP1LL3_ADD(_tag) \
MCFG_DEVICE_ADD(_tag, HP1LL3, 0)
///*************************************************************************
// TYPE DEFINITIONS
///*************************************************************************
// ======================> hp1ll3_device
class hp1ll3_device : public device_t,
public device_video_interface
{
public:
// construction/destruction
hp1ll3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
DECLARE_READ8_MEMBER(read);
DECLARE_WRITE8_MEMBER(write);
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
private:
void command(int command);
inline void point(int x, int y, int px);
void label(uint8_t chr, int width);
void fill(int x, int y, int w, int h, int arg);
void line(int x_from, int y_from, int x_to, int y_to);
void bitblt(int dstx, int dsty, uint16_t srcaddr, int width, int height, int op);
uint16_t m_conf[11], m_input[2];
int m_input_ptr, m_memory_ptr, m_conf_ptr;
int m_command;
uint16_t m_sad;
uint16_t m_org;
uint16_t m_dad;
uint16_t m_rr;
uint16_t m_fad, m_fontdata, m_fontheight;
uint16_t m_udl;
bool m_enable_video, m_enable_cursor, m_enable_sprite;
uint16_t m_cursor_x, m_cursor_y;
uint16_t m_sprite_x, m_sprite_y;
struct {
uint16_t width, height, org_x, org_y, width_w;
} m_window;
std::unique_ptr<uint16_t[]> m_videoram;
bool m_busy;
bitmap_ind16 m_bitmap, m_cursor, m_sprite;
};
// device type definition
extern const device_type HP1LL3;
#endif

View File

@ -152,6 +152,7 @@ enum
XTAL_15_4MHz = 15400000, /* DVK KSM */
XTAL_15_468MHz = 15468480, /* Bank Panic h/w, Sega G80 */
XTAL_15_8976MHz = 15897600, /* IAI Swyft */
XTAL_15_92MHz = 15920000, /* HP Integral PC */
XTAL_16MHz = 16000000, /* Extremely common, used on 100's of PCBs */
XTAL_16_384MHz = 16384000,
XTAL_16_5888MHz = 16588800, /* SM 7238 */

View File

@ -0,0 +1,42 @@
// license:BSD-3-Clause
// copyright-holders:Sergey Svishchev
/*********************************************************************
formats/hp_ipc_dsk.c
HP Integral PC format
*********************************************************************/
#include <assert.h>
#include "formats/hp_ipc_dsk.h"
hp_ipc_format::hp_ipc_format() : wd177x_format(formats)
{
}
const char *hp_ipc_format::name() const
{
return "hp_ipc";
}
const char *hp_ipc_format::description() const
{
return "HP Integral PC disk image";
}
const char *hp_ipc_format::extensions() const
{
return "img";
}
const hp_ipc_format::format hp_ipc_format::formats[] = {
// images from coho.org. gaps unverified.
{ floppy_image::FF_35, floppy_image::DSDD, floppy_image::MFM,
2000, 9, 77, 2, 512, {}, 1, {}, 60, 22, 43 },
{}
};
const floppy_format_type FLOPPY_HP_IPC_FORMAT = &floppy_image_format_creator<hp_ipc_format>;

View File

@ -0,0 +1,30 @@
// license:BSD-3-Clause
// copyright-holders:Sergey Svishchev
/*********************************************************************
formats/hp_ipc_dsk.h
hp_ipc format
*********************************************************************/
#ifndef HP_IPC_DSK_H_
#define HP_IPC_DSK_H_
#include "wd177x_dsk.h"
class hp_ipc_format : public wd177x_format {
public:
hp_ipc_format();
virtual const char *name() const override;
virtual const char *description() const override;
virtual const char *extensions() const override;
private:
static const format formats[];
};
extern const floppy_format_type FLOPPY_HP_IPC_FORMAT;
#endif

View File

@ -2,10 +2,51 @@
// copyright-holders:
/******************************************************************************
Integral Personal Computer (HP9807A)
Hewlett-Packard, 1985
Driver to-do list
=================
- softlist: merge dumps from coho.org and classiccmp.org
- keyboard: NMI generation, autorepeat
- HP-HIL mouse
- RTC chip: proper month, day
- switchable graphics resolution ("_desktop" mode uses 640x400)
- HP-IB chip
- CS/80, SS/80 storage protocol(s) and drives
- HP-IL printer
- sound (needs dump of COP452)
QA
- diagnstc.td0: display test [cannot execute]
- diagnstc.td0: complete keyboard test [keyboard stops responding]
- diagnstc.td0: speaker test
- diagnstc.td0: printer test
+ diagnstc.td0: auto: floppy disc test
+ diagnstc.td0: auto: ram test
- diagnstc.td0: auto: rtc test [cannot execute]
- diagnstc.td0: auto: short keyboard test [cannot execute + keyboard stops responding]
maybe
- drive AP line of MLC from a timer
- RTC standby interrupt?
- what does _desktop do except setting 640x400 mode?
- non-HLE keyboard and mouse? (need dumps of COP4xx)
slot devices
- 82915A -- 300/1200 bps modem; http://www.hpmuseum.net/display_item.php?hw=920
- 82919A -- serial; http://www.hpmuseum.net/display_item.php?hw=445
- 82920A -- current loop; http://www.hpmuseum.net/display_item.php?hw=975
- 82922A -- BCD interface; http://www.hpmuseum.net/display_item.php?hw=921
- 82923A -- GPIO; http://www.hpmuseum.net/display_item.php?hw=976
- 82924A -- HP-IL; http://www.hpmuseum.net/display_item.php?hw=922
- 82968A -- up to 256 KB of ROM on top of operating system PCA
- 82971A -- up to 1 MB of EPROM or 2 MB or masked ROM
- 82998A -- HP-IB; http://www.hpmuseum.net/display_item.php?hw=933
- 98071A -- 640x400 composite Video + Serial; http://www.hpmuseum.net/display_item.php?hw=935
This is a portable mains-powered UNIX workstation computer system produced by Hewlett-Packard and launched in 1985
Basic hardware specs are....
- 68000 CPU at 7.96MHz
@ -74,7 +115,7 @@ Notes:
LS74 - 74LS74 at U2 provides system clock dividers /4 /2
MB81256 - Fujitsu MB81256 256Kx1 DRAM. Total RAM 512Kx8/256Kx16. HP part# 1818-3308. U20-U35 (DIP16)
TMS4500 - Texas Instruments TMS4500A DRAM Controller at U4. Clock input 3.98MHz [15.92/4] (DIP40)
U58 - HP-HIL Keyboard Interface 'Cerberus'. Clock input on pin 24 is unknown (DIP24)
U58 - 1RD2-6001, HP-HIL Master Link Controller 'Cerberus'. Clock input on pin 24 is unknown (DIP24)
U60 - Unknown IC used as an interrupt encoder. Possibly a logic chip? (DIP20)
555 - 555 Timer
J1/J2 - Connectors joining to LOGIC B PCA (logic A to logic B bus)
@ -121,13 +162,13 @@ HP Part# 00095-60952
| J14 J6 J5 J4 J3 J7 J1 J8 J9 J12 |
|------------------------------------------------------------------------------------------------------|
Notes:
GPU - GPU (Graphics Processor) at U1. Clock input 3MHz [24/8]. VSync on pin 45, HSync on pin 46 (DIP48)
GPU - 1LL3-0005 GPU (Graphics Processor) at U1. Clock input 3MHz [24/8]. VSync on pin 45, HSync on pin 46 (DIP48)
16Kx4 - 16Kx4 DRAM, organised as 32Kx8bit/16Kx16bit at U3, U4, U5 & U6. Chip type unknown, likely Fujitsu MB81416 (DIP18)
WD2797 - Western Digital WD2797 Floppy Disk Controller at U18. Clock input 2MHz [24/2/3/2] (DIP40)
HP-IL(1) - HP-IL 1LJ7-0015 'Saturn' Thinkjet Printer Controller IC at U28. Clock input 3MHz on pin 9 [24/8] (DIP48)
HP-IL(2) - HP-IL Interface IC at U31. Clock input 2MHz on pin 22 [24/2/3/2] (DIP28)
HP-IL(2) - HP-IL 1LB3 Interface IC at U31. Clock input 2MHz on pin 22 [24/2/3/2] (DIP28)
1Kb - 1Kb RAM at U27 for printer buffer (DIP28, type unknown, very old, with only DATA0,1,2,3, C/D and DIN,DOUT)
ROM - 16Kb (2Kx8?) Some kind of very early DIP28 PROM/ROM? Same pinout as 1Kb RAM above. Holds the character font table for the printer
ROM - 16Kb (32Kx4) Some kind of very early DIP28 PROM/ROM? Same pinout as 1Kb RAM above. Holds the character font table for the printer
Four versions of this ROM exist, one each for Japan/Arabic/Hebrew and one for all other regions
NS58167A - National Semiconductor NS58167A Clock Controller RTC at U44. Clock input 32.768kHz (DIP24)
LM358 - National Semiconductor LM358 Operational Amplifier at U40 (DIP8)
@ -246,7 +287,7 @@ F80000-FFFFFF - Reserved 512Kb
Access to 800000-FFFFFF can be remapped by the MMU registers.
Interrupts
Interrupts (all autovectored)
----------
High Priority 7 - Soft reset from keyboard (NMI)
/\ 6 - RTC or NBIR3 (external I/O)
@ -259,10 +300,81 @@ Low Priority 1 - RTC
Note external interrupt lines NBIR0 to NBIR3 can be asserted by an interface connected to the external I/O port
Useful links etc.
-----------------
bitsavers://pdf/hp/integral/00095-90126_Integral_Personal_Computer_Service_Jan86.pdf
bitsavers://pdf/hp/hp-hil/45918A-90001_HP-HIL_Technical_Reference_Manual_Jan86.pdf
HP-HIL MLC, SLC datasheets
bitsavers://pdf/sony/floppy/Sony_OA-D32_Microfloppy_Service_Nov83.pdf
OA-D32W
http://www.hpl.hp.com/hpjournal/pdfs/IssuePDFs/1983-01.pdf
HP-IL issue
http://www.hpl.hp.com/hpjournal/pdfs/IssuePDFs/1985-10.pdf
IPC issue
http://www.hpl.hp.com/hpjournal/pdfs/IssuePDFs/1987-06.pdf
HP-HIL article
http://www.hpmuseum.net/pdf/ComputerNews_1985_Jan15_37pages_OCR.pdf
introducing the IPC
http://www.hpmuseum.net/pdf/ComputerFocus_1985_Nov_25pages_OCR.pdf
SysV upgrade
http://www.hpmuseum.net/pdf/InformationSystemsAndManufacturingNews_81pages_Jun1-86_OCR.pdf
EPROM/ROM modules
http://www.hpmuseum.net/pdf/HPChannels_1986_11_37pages_Nov86_OCR.pdf
SW Eng ROM and serial option for it
http://www.coho.org/~pete/downloads/IPC/burst/Freeware/IPC_Driver_Writers_Disc/hp-ux.5.0.0
kernel namelist
http://www.hpmuseum.net/display_item.php?hw=122
overview, manuals, software
http://www.ambry.com/hp-computer-model/9807A.html
replacement parts
http://www.brouhaha.com/~eric/hpcalc/chips/
chip part numbers
Software to look for
--------------------
00095-60978 "Service ROM - Used in trobleshooting the integral PC" via ambry
00095-60925 "Service ROM" via service manual
00095-60969 "Service Diagnostic Disc" via service manual
00095-60950 "I/O Component-Level Diagnostic Disc" via serial interface service manual
00095-60006 (original System III-based HP-UX 1.0 ROM)
82995A (same bits as 82991A; the latter is an upgrade kit, former was pre-installed)
82989J Technical Basic ROM (Jan'1986)
82987A Software Engineering ROM (Nov'1986) (possibly can be rebuilt from floppy images on coho?)
******************************************************************************/
#include "emu.h"
#include "bus/hp_hil/hp_hil.h"
#include "bus/hp_hil/hil_devices.h"
#include "cpu/m68000/m68000.h"
#include "formats/hp_ipc_dsk.h"
#include "machine/bankdev.h"
#include "machine/mm58167.h"
#include "machine/ram.h"
#include "machine/wd_fdc.h"
#include "video/hp1ll3.h"
#include "rendlay.h"
#include "screen.h"
class hp_ipc_state : public driver_device
@ -271,81 +383,381 @@ public:
hp_ipc_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_maincpu(*this, "maincpu")
, m_bankdev(*this, "bankdev")
, m_fdc(*this, "fdc")
, m_ram(*this, RAM_TAG)
, m_screen(*this, "screen")
{ }
virtual void machine_start() override;
virtual void machine_reset() override;
DECLARE_READ16_MEMBER(mem_r);
DECLARE_WRITE16_MEMBER(mem_w);
DECLARE_READ16_MEMBER(mmu_r);
DECLARE_WRITE16_MEMBER(mmu_w);
DECLARE_READ16_MEMBER(ram_r);
DECLARE_WRITE16_MEMBER(ram_w);
DECLARE_READ16_MEMBER(trap_r);
DECLARE_WRITE16_MEMBER(trap_w);
DECLARE_READ8_MEMBER(floppy_id_r);
DECLARE_WRITE8_MEMBER(floppy_id_w);
DECLARE_FLOPPY_FORMATS(floppy_formats);
DECLARE_WRITE_LINE_MEMBER(irq_1);
DECLARE_WRITE_LINE_MEMBER(irq_2);
DECLARE_WRITE_LINE_MEMBER(irq_3);
DECLARE_WRITE_LINE_MEMBER(irq_4);
DECLARE_WRITE_LINE_MEMBER(irq_5);
DECLARE_WRITE_LINE_MEMBER(irq_6);
DECLARE_WRITE_LINE_MEMBER(irq_7);
emu_timer *m_bus_error_timer;
private:
required_device<m68000_device> m_maincpu;
required_device<address_map_bank_device> m_bankdev;
required_device<wd2797_t> m_fdc;
required_device<ram_device> m_ram;
required_device<screen_device> m_screen;
uint32_t m_mmu[4];
uint16_t m_internal_ram[0x40000];
uint32_t m_mmu[4], m_lowest_ram_addr;
uint16_t *m_internal_ram;
int m_fc;
inline uint32_t get_ram_address(offs_t offset) { return (m_mmu[(m_maincpu->get_fc() >> 1) & 3] + offset) & 0x3FFFFF; }
floppy_image_device *m_floppy;
inline uint32_t get_ram_address(offs_t offset)
{
return (m_mmu[(m_maincpu->get_fc() >> 1) & 3] + offset) & 0x3FFFFF;
}
protected:
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
void set_bus_error(uint32_t address, bool write, uint16_t mem_mask);
bool m_bus_error;
};
static ADDRESS_MAP_START(hp_ipc_mem, AS_PROGRAM, 16, hp_ipc_state)
AM_RANGE(0x000000, 0x07FFFF) AM_ROM
AM_RANGE(0x600000, 0x60FFFF) AM_WRITE(mmu_w)
AM_RANGE(0x800000, 0xFFFFFF) AM_READWRITE(ram_r, ram_w)
void hp_ipc_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
m_bus_error = false;
}
void hp_ipc_state::set_bus_error(uint32_t address, bool write, uint16_t mem_mask)
{
if (m_bus_error)
{
return;
}
if (!ACCESSING_BITS_8_15)
{
address++;
}
m_bus_error = true;
m_maincpu->set_buserror_details(address, write, m_maincpu->get_fc());
m_maincpu->set_input_line(M68K_LINE_BUSERROR, ASSERT_LINE);
m_bus_error_timer->adjust(m_maincpu->cycles_to_attotime(16)); // let rmw cycles complete
}
static ADDRESS_MAP_START(hp_ipc_mem_outer, AS_PROGRAM, 16, hp_ipc_state)
AM_RANGE(0x000000, 0xFFFFFF) AM_READWRITE(mem_r, mem_w)
ADDRESS_MAP_END
static ADDRESS_MAP_START(hp_ipc_mem_inner, AS_PROGRAM, 16, hp_ipc_state)
// user mode
AM_RANGE(0x1000000, 0x17FFFFF) AM_READWRITE(ram_r, ram_w)
AM_RANGE(0x1800000, 0x187FFFF) AM_ROM AM_REGION("maincpu", 0)
AM_RANGE(0x1E20000, 0x1E2000F) AM_DEVREADWRITE8("gpu", hp1ll3_device, read, write, 0x00ff)
AM_RANGE(0x1E40000, 0x1E4002F) AM_DEVREADWRITE8("rtc", mm58167_device, read, write, 0x00ff)
// supervisor mode
AM_RANGE(0x0000000, 0x007FFFF) AM_ROM AM_REGION("maincpu", 0) // Internal ROM (operating system PCA)
AM_RANGE(0x0080000, 0x00FFFFF) AM_UNMAP // Internal ROM (option ROM PCA)
AM_RANGE(0x0100000, 0x04FFFFF) AM_UNMAP // External ROM modules
AM_RANGE(0x0600000, 0x060FFFF) AM_READWRITE(mmu_r, mmu_w)
AM_RANGE(0x0610000, 0x0610007) AM_READWRITE8(floppy_id_r, floppy_id_w, 0x00ff)
AM_RANGE(0x0610008, 0x061000F) AM_DEVREADWRITE8("fdc", wd2797_t, read, write, 0x00ff)
AM_RANGE(0x0620000, 0x062000F) AM_DEVREADWRITE8("gpu", hp1ll3_device, read, write, 0x00ff)
AM_RANGE(0x0630000, 0x063FFFF) AM_NOP // AM_DEVREADWRITE8(TMS9914_TAG, tms9914_device, read, write, 0x00ff)
AM_RANGE(0x0640000, 0x064002F) AM_DEVREADWRITE8("rtc", mm58167_device, read, write, 0x00ff)
AM_RANGE(0x0650000, 0x065FFFF) AM_NOP // HP-IL Printer (optional; ROM sets _desktop to 0 if not mapped) -- sys/lpint.h
AM_RANGE(0x0660000, 0x06600FF) AM_DEVREADWRITE8("mlc", hp_hil_mlc_device, read, write, 0x00ff) // 'caravan', scrn/caravan.h
AM_RANGE(0x0670000, 0x067FFFF) AM_NOP // Speaker (NatSemi COP 452)
AM_RANGE(0x0680000, 0x068FFFF) AM_NOP // 'SIMON (98628) fast HP-IB card' -- sys/simon.h
AM_RANGE(0x0700000, 0x07FFFFF) AM_UNMAP // External I/O
AM_RANGE(0x0800000, 0x0FFFFFF) AM_READWRITE(ram_r, ram_w)
// bus error handler
AM_RANGE(0x0000000, 0x1FFFFFF) AM_READWRITE(trap_r, trap_w)
ADDRESS_MAP_END
static INPUT_PORTS_START(hp_ipc)
INPUT_PORTS_END
READ16_MEMBER(hp_ipc_state::mmu_r)
{
uint16_t data = (m_mmu[offset & 3] >> 10);
return data;
}
WRITE16_MEMBER(hp_ipc_state::mmu_w)
{
logerror("mmu_w: offset = %08x, data = %04x, register = %d, data_to_add = %08x\n", offset, data, offset & 3, (data & 0xFFF) << 10);
m_mmu[offset & 3] = (data & 0xFFF) << 10;
}
READ16_MEMBER(hp_ipc_state::mem_r)
{
int fc = m_maincpu->get_fc() & 4;
if (fc != m_fc)
{
m_fc = fc;
m_bankdev->set_bank(m_fc ? 0 : 1);
}
return m_bankdev->read16(space, offset, mem_mask);
}
WRITE16_MEMBER(hp_ipc_state::mem_w)
{
int fc = m_maincpu->get_fc() & 4;
if (fc != m_fc)
{
m_fc = fc;
m_bankdev->set_bank(m_fc ? 0 : 1);
}
m_bankdev->write16(space, offset, data, mem_mask);
}
READ16_MEMBER(hp_ipc_state::trap_r)
{
if (!machine().side_effect_disabled()) set_bus_error((offset << 1) & 0xFFFFFF, 0, mem_mask);
return 0xffff;
}
WRITE16_MEMBER(hp_ipc_state::trap_w)
{
if (!machine().side_effect_disabled()) set_bus_error((offset << 1) & 0xFFFFFF, 1, mem_mask);
}
READ16_MEMBER(hp_ipc_state::ram_r)
{
uint32_t ram_address = get_ram_address(offset);
uint16_t data = 0xffff;
//logerror("RAM read, offset = %08x, ram address = %08X\n", offset, ram_address);
if (ram_address < 0x380000)
if (ram_address < m_lowest_ram_addr)
{
// External RAM modules
if (!machine().side_effect_disabled()) set_bus_error((offset << 1) + 0x800000, 0, mem_mask);
}
else if (ram_address < 0x3c0000)
{
// Internal RAM
return m_internal_ram[offset & 0x3ffff];
data = m_internal_ram[ram_address - m_lowest_ram_addr];
}
return 0xffff;
}
return data;
}
WRITE16_MEMBER(hp_ipc_state::ram_w)
{
uint32_t ram_address = get_ram_address(offset);
//logerror("RAM write, offset = %08x, ram address = %08X, data = %04x\n", offset, ram_address, data);
if (ram_address < 0x380000)
if (ram_address < m_lowest_ram_addr)
{
// External RAM modules
if (!machine().side_effect_disabled()) set_bus_error((offset << 1) + 0x800000, 1, mem_mask);
}
else if (ram_address < 0x3c0000)
{
// Internal RAM
m_internal_ram[offset & 0x3ffff] = data;
COMBINE_DATA(&m_internal_ram[ram_address - m_lowest_ram_addr]);
}
}
/*
* bit 6 -- INTRQ
* bit 1 -- disk changed (from drive)
* bit 0 -- write protect (from drive)
*/
READ8_MEMBER(hp_ipc_state::floppy_id_r)
{
uint8_t data = 0;
data = (m_fdc->intrq_r() << 6);
if (m_floppy)
{
data |= (m_fdc->intrq_r() << 6) | (m_floppy->dskchg_r() << 1) | m_floppy->wpt_r();
}
return data;
}
/*
* bit 7 -- 1: motor on (via inverter to drive's /MTorOn)
* bit 3 -- 1: head 0, 0: head 1 (via inverter to drive's /SSO)
* bit 1 -- 1: drive select (via inverter to drive's /DRIVE SEL 1)
* bit 0 -- 1: reset disc_changed (via inverter to drive's /DSKRST)
*/
WRITE8_MEMBER(hp_ipc_state::floppy_id_w)
{
floppy_image_device *floppy0 = m_fdc->subdevice<floppy_connector>("0")->get_device();
if (!BIT(data, 1))
{
if (m_floppy == nullptr)
{
m_floppy = floppy0;
m_fdc->set_floppy(m_floppy);
}
}
else
{
m_floppy = nullptr;
}
if (m_floppy)
{
m_floppy->ss_w(BIT(data, 3));
m_floppy->mon_w(!BIT(data, 7));
if (BIT(data, 0))
m_floppy->dskchg_w(0);
}
else
{
floppy0->mon_w(1);
}
}
WRITE_LINE_MEMBER(hp_ipc_state::irq_1)
{
m_maincpu->set_input_line_and_vector(M68K_IRQ_1, state, M68K_INT_ACK_AUTOVECTOR);
}
WRITE_LINE_MEMBER(hp_ipc_state::irq_2)
{
m_maincpu->set_input_line_and_vector(M68K_IRQ_2, state, M68K_INT_ACK_AUTOVECTOR);
}
WRITE_LINE_MEMBER(hp_ipc_state::irq_3)
{
m_maincpu->set_input_line_and_vector(M68K_IRQ_3, state, M68K_INT_ACK_AUTOVECTOR);
}
WRITE_LINE_MEMBER(hp_ipc_state::irq_4)
{
m_maincpu->set_input_line_and_vector(M68K_IRQ_4, state, M68K_INT_ACK_AUTOVECTOR);
}
WRITE_LINE_MEMBER(hp_ipc_state::irq_5)
{
m_maincpu->set_input_line_and_vector(M68K_IRQ_5, state, M68K_INT_ACK_AUTOVECTOR);
}
WRITE_LINE_MEMBER(hp_ipc_state::irq_6)
{
m_maincpu->set_input_line_and_vector(M68K_IRQ_6, state, M68K_INT_ACK_AUTOVECTOR);
}
WRITE_LINE_MEMBER(hp_ipc_state::irq_7)
{
m_maincpu->set_input_line_and_vector(M68K_IRQ_7, state, M68K_INT_ACK_AUTOVECTOR);
}
void hp_ipc_state::machine_start()
{
m_bus_error_timer = timer_alloc(0);
m_bankdev->set_bank(1);
m_lowest_ram_addr = 0x3c0000 - (m_ram->size() >> 1);
m_internal_ram = (uint16_t *) m_ram->pointer();
}
void hp_ipc_state::machine_reset()
{
m_floppy = nullptr;
}
FLOPPY_FORMATS_MEMBER( hp_ipc_state::floppy_formats )
FLOPPY_HP_IPC_FORMAT
FLOPPY_FORMATS_END
static SLOT_INTERFACE_START( hp_ipc_floppies )
SLOT_INTERFACE( "35dd", SONY_OA_D32W )
SLOT_INTERFACE_END
/*
* IRQ levels (page 5-4)
*
* 7 Soft reset from keyboard, non-maskable
* 6 Real-time clock or NBIR3 (ext. I/O)
* 5 Disc Drive or NBIR2
* 4 GPU or NBIR1
* 3 HP-IB, printer, or NBIR0
* 2 HP-HIL devices (keyboard, mouse)
* 1 Real-time clock
*/
static MACHINE_CONFIG_START(hp_ipc, hp_ipc_state)
/* basic machine hardware */
MCFG_CPU_ADD("maincpu", M68000, 15920000 / 2)
MCFG_CPU_PROGRAM_MAP(hp_ipc_mem)
MCFG_CPU_ADD("maincpu", M68000, XTAL_15_92MHz / 2)
MCFG_CPU_PROGRAM_MAP(hp_ipc_mem_outer)
MCFG_DEVICE_ADD("bankdev", ADDRESS_MAP_BANK, 0)
MCFG_DEVICE_PROGRAM_MAP(hp_ipc_mem_inner)
MCFG_ADDRESS_MAP_BANK_ENDIANNESS(ENDIANNESS_BIG)
MCFG_ADDRESS_MAP_BANK_ADDRBUS_WIDTH(25)
MCFG_ADDRESS_MAP_BANK_DATABUS_WIDTH(16)
MCFG_ADDRESS_MAP_BANK_STRIDE(0x1000000)
// horizontal time = 60 us (min)
// ver.refresh period = ~300 us
// ver.period = 16.7ms (~60 hz)
MCFG_SCREEN_ADD_MONOCHROME("screen", RASTER, rgb_t::amber())
MCFG_SCREEN_UPDATE_DEVICE("gpu", hp1ll3_device, screen_update)
MCFG_SCREEN_RAW_PARAMS(XTAL_6MHz * 2, 720, 0, 512, 278, 0, 256)
// when _desktop == 0:
// MCFG_SCREEN_RAW_PARAMS(XTAL_6MHz * 2, 720, 0, 640, 480, 0, 400)
MCFG_SCREEN_VBLANK_CALLBACK(DEVWRITELINE("mlc", hp_hil_mlc_device, ap_w)) // XXX actually it's driven by 555 (U59)
MCFG_DEFAULT_LAYOUT(layout_lcd)
MCFG_SCREEN_PALETTE("palette")
MCFG_PALETTE_ADD_MONOCHROME("palette")
MCFG_HP1LL3_ADD("gpu")
// MCFG_HP1LL3_IRQ_CALLBACK(WRITELINE(hp_ipc_state, irq_4))
MCFG_VIDEO_SET_SCREEN("screen")
// XXX actual clock is 1MHz; remove this workaround (and change 2000 to 100 in hp_ipc_dsk.cpp)
// XXX when floppy code correctly handles 600 rpm drives.
MCFG_WD2797_ADD("fdc", XTAL_2MHz)
MCFG_WD_FDC_INTRQ_CALLBACK(WRITELINE(hp_ipc_state, irq_5))
MCFG_FLOPPY_DRIVE_ADD("fdc:0", hp_ipc_floppies, "35dd", hp_ipc_state::floppy_formats)
MCFG_SOFTWARE_LIST_ADD("flop_list","hp_ipc")
MCFG_DEVICE_ADD("rtc", MM58167, XTAL_32_768kHz)
MCFG_MM58167_IRQ_CALLBACK(WRITELINE(hp_ipc_state, irq_1))
// MCFG_MM58167_STANDBY_IRQ_CALLBACK(WRITELINE(hp_ipc_state, irq_6))
MCFG_DEVICE_ADD("mlc", HP_HIL_MLC, XTAL_15_92MHz/2)
MCFG_HP_HIL_INT_CALLBACK(WRITELINE(hp_ipc_state, irq_2))
MCFG_HP_HIL_NMI_CALLBACK(WRITELINE(hp_ipc_state, irq_7))
MCFG_HP_HIL_SLOT_ADD("mlc", "hil1", hp_hil_devices, "hp_ipc_kbd")
MCFG_RAM_ADD(RAM_TAG)
MCFG_RAM_DEFAULT_SIZE("512K")
MCFG_RAM_EXTRA_OPTIONS("768K,1M,1576K,2M,3M,4M,5M,6M,7M,7680K")
MACHINE_CONFIG_END
@ -355,4 +767,4 @@ ROM_START(hp_ipc)
ROM_END
COMP(1985, hp_ipc, 0, 0, hp_ipc, hp_ipc, driver_device, 0, "HP", "Integral Personal Computer", MACHINE_IS_SKELETON)
COMP(1985, hp_ipc, 0, 0, hp_ipc, hp_ipc, driver_device, 0, "HP", "Integral Personal Computer", MACHINE_NO_SOUND|MACHINE_IMPERFECT_GRAPHICS|MACHINE_IMPERFECT_KEYBOARD)