-kbdc8042: Added rudimentary PS/2 mouse support. [Ryan Holtz]

-indy_indigo2: Added mouse cursor support to Newport graphics emulation. [Ryan Holtz]
This commit is contained in:
mooglyguy 2018-06-19 04:41:22 +02:00
parent 0c1bd73d82
commit 771b9d0cd6
4 changed files with 253 additions and 244 deletions

View File

@ -2,175 +2,9 @@
// copyright-holders:Peter Trauner
/*********************************************************************
8042kbdc.c
8042kbdc.cpp
Code specific to fun IBM AT stuff
PeT's notes about various Power On Self Tests (POSTs)
at post
-------
f81d2 01
f82e6 05
f8356 07
f83e5 0a
f847e 0e
f8e7c 10
f8f3a 13
f9058 1a
f913a 1e
fa8ba 30
fa96c 36
fa9d3 3c
fa9f4 3e
ff122 50
ff226 5b
ff29f 5f
f9228 70
f92b2 74 ide?
ibm at bios
-----------
f0101 after switch to real mode jump back!!!!!!!!!!
jumping table
f0123
f098e memory tests
f10b4 ???
not reached
f1050
f1617
f0119
f10d8
f10b7 system board error
f019f
f025b
f02e6
f0323
f03b3 0e
f03d7 0f
f058d
at8042 signal timing test
sets errorcode!
f0655
f06a3 postcode 15
f06ba 16
f0747 18
f0763 enter pm! (0x81, 0x85)
f0766 1a
f07b3 first 640kb memory test
f084c 1c
f086e extended memory test
f0928 1f
f097d 20
???
f0ff4 34
???
f1675 f0
f16cb f2
illegal access trap test!!!!
f16fe f3
task descriptor test!!!!
f174a f4
f17af f5
f1800 f6 writing to non write segment
f1852 f7 arpl
f1880 f8 lar, lsl
f18ca fa
f10d8
f10ec 35
f1106 36
f1137 !!!!!!!keyboard test fails
f11aa 3a
f1240 3c harddisk controller test!!!
f13f3 3b
f1a6d xthdd bios init
f1429
f1462
f1493 40
f1532
keyboard lock
f1 to unlock
f155c
jumps to f0050 (reset) without enabling of the a20 gate --> hangs
0412 bit 5 must be set to reach f1579
f1579
f15c3 41
f1621 43
routines
f1945 read cmos ram
f195f write to cmos al value ah
f1a3a poll 0x61 bit 4
f1a49 sets something in cmos ram
f1d30 switch to protected mode
neat
----
f80b9
at386
-----
fd28c fd
fd2c3 fc
f40dc
fd949
fd8e3
fd982
f4219 01
f4296 03
f42f3 04
f4377 05
f43ec 06
f4430 08
f6017 switches to PM
f4456 09
f55a2
f44ec 0d
f4557 20
f462d 27 my special friend, the keyboard controller once more
ed0a1
f4679 28
fa16a
f46d6
f4768 2c
f47f0 2e
f5081
fa16a
f9a83
Message: "Checksum Error on Extended CMOS"
f4840 34
f488c 35
reset
f48ee
f493e 3a
f49cd
f4fc7
fe842
f4a5a
f4b01 38
(Memory Test)
f4b41 3b
f4c0f
Message: "Invalid configuration information - please run SETUP program"
f4c5c
f86fc
f8838
f4c80
f4ca2
f4d4c
f4e15 (int 19h)
[f9a83 output text at return address!, return after text]
at486
-----
f81a5 03
f1096 0f 09 wbinvd i486 instruction
8042-based keyboard/mouse controller simulation
*********************************************************************/
@ -191,7 +25,7 @@
#define LOG_KEYBOARD 0
#define LOG_ACCESSES 0
DEFINE_DEVICE_TYPE(KBDC8042, kbdc8042_device, "kbdc8042", "8042 Keyboard Controller")
DEFINE_DEVICE_TYPE(KBDC8042, kbdc8042_device, "kbdc8042", "8042 Keyboard/Mouse Controller")
//-------------------------------------------------
// kbdc8042_device - constructor
@ -200,6 +34,9 @@ DEFINE_DEVICE_TYPE(KBDC8042, kbdc8042_device, "kbdc8042", "8042 Keyboard Control
kbdc8042_device::kbdc8042_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, KBDC8042, tag, owner, clock)
, m_keyboard_dev(*this, "at_keyboard")
, m_mousex_port(*this, "MOUSEX")
, m_mousey_port(*this, "MOUSEY")
, m_mousebtn_port(*this, "MOUSEBTN")
, m_system_reset_cb(*this)
, m_gate_a20_cb(*this)
, m_input_buffer_full_cb(*this)
@ -228,6 +65,7 @@ void kbdc8042_device::device_start()
m_operation_write_state = 0; /* first write to 0x60 might occur before anything can set this */
memset(&m_keyboard, 0x00, sizeof(m_keyboard));
memset(&m_mouse, 0x00, sizeof(m_mouse));
m_mouse.sample_rate = 100;
m_sending = 0;
m_last_write_to_control = 0;
m_status_read_mode = 0;
@ -244,12 +82,15 @@ void kbdc8042_device::device_reset()
/* ibmat bios wants 0x20 set! (keyboard locked when not set) 0x80 */
m_inport = 0xa0;
at_8042_set_outport(0xfe, 1);
m_mouse_x = 0;
m_mouse_y = 0;
m_mouse_btn = 0;
}
void kbdc8042_device::at_8042_set_outport(uint8_t data, int initial)
{
uint8_t change;
change = initial ? 0xFF : (m_outport ^ data);
uint8_t change = initial ? 0xFF : (m_outport ^ data);
m_outport = data;
if (change & 0x02)
{
@ -264,15 +105,18 @@ WRITE_LINE_MEMBER( kbdc8042_device::keyboard_w )
at_8042_check_keyboard();
}
void kbdc8042_device::at_8042_receive(uint8_t data)
void kbdc8042_device::at_8042_receive(uint8_t data, bool mouse)
{
if (LOG_KEYBOARD)
logerror("at_8042_receive Received 0x%02x\n", data);
m_data = data;
if(!(m_speaker & 0x80))
if(!(m_speaker & 0x80) || mouse)
{
m_keyboard.received = 1;
if (mouse)
m_mouse.received = 1;
else
m_keyboard.received = 1;
if (!m_input_buffer_full_cb.isnull())
m_input_buffer_full_cb(1);
@ -281,15 +125,62 @@ void kbdc8042_device::at_8042_receive(uint8_t data)
void kbdc8042_device::at_8042_check_keyboard()
{
int data;
if (!m_keyboard.received && !m_mouse.received)
{
if((data = m_keyboard_dev->read(machine().dummy_space(), 0)))
int data = m_keyboard_dev->read(machine().dummy_space(), 0);
if (data)
at_8042_receive(data);
}
}
void kbdc8042_device::at_8042_check_mouse()
{
if (!m_keyboard.received && !m_mouse.received)
{
if (m_mouse.to_transmit == 0)
{
uint16_t x = m_mousex_port->read();
uint16_t y = m_mousey_port->read();
uint8_t buttons = m_mousebtn_port->read();
uint16_t old_mouse_x = m_mouse_x;
uint16_t old_mouse_y = m_mouse_y;
uint16_t old_mouse_btn = m_mouse_btn;
if(m_mouse_x == 0xffff)
{
old_mouse_x = x & 0x3ff;
old_mouse_y = y & 0x3ff;
old_mouse_btn = buttons;
}
m_mouse_x = x & 0x3ff;
m_mouse_y = y & 0x3ff;
m_mouse_btn = buttons;
uint16_t dx = m_mouse_x - old_mouse_x;
uint16_t dy = old_mouse_y - m_mouse_y;
if (dx != 0 || dy != 0 || buttons != old_mouse_btn)
{
m_mouse.to_transmit = 3;
m_mouse.transmit_buf[0] = buttons | 0x08 | (BIT(dx, 8) << 4) | (BIT(dy, 8) << 5);
m_mouse.transmit_buf[1] = dx & 0xff;
m_mouse.transmit_buf[2] = dy & 0xff;
}
}
if (m_mouse.to_transmit)
{
at_8042_receive(m_mouse.transmit_buf[0], true);
m_mouse.to_transmit--;
for (int i = 0; i < m_mouse.to_transmit; i++)
{
m_mouse.transmit_buf[i] = m_mouse.transmit_buf[i + 1];
}
}
}
}
void kbdc8042_device::at_8042_clear_keyboard_received()
{
@ -370,6 +261,7 @@ READ8_MEMBER(kbdc8042_device::data_r)
case 4:
at_8042_check_keyboard();
at_8042_check_mouse();
if (m_keyboard.received || m_mouse.received)
data |= 1;
@ -444,6 +336,29 @@ WRITE8_MEMBER(kbdc8042_device::data_w)
case 4:
/* preceded by writing 0xD4 to port 60h */
m_data = data;
if (m_mouse.receiving_sample_rate)
{
m_mouse.received = 1;
m_mouse.sample_rate = data;
m_data = 0xfa;
break;
}
switch (m_data)
{
case 0xf6:
m_mouse.received = 1;
m_data = 0xfa;
break;
case 0xf3:
m_mouse.received = 1;
m_data = 0xfa;
m_mouse.receiving_sample_rate = true;
break;
default:
logerror("%s: Unknown mouse command: %02x\n", machine().describe_context(), m_data);
break;
}
break;
case 5:
@ -463,7 +378,7 @@ WRITE8_MEMBER(kbdc8042_device::data_w)
}
m_speaker &= ~0x80;
if (!m_speaker_cb.isnull())
m_speaker_cb((offs_t)0, m_speaker);
m_speaker_cb((offs_t)0, m_speaker);
break;
@ -473,7 +388,7 @@ WRITE8_MEMBER(kbdc8042_device::data_w)
/* switch based on the command */
switch(data) {
case 0x20: /* current 8042 command byte is placed on port 60h */
m_data = m_command;
at_8042_receive(m_command);
break;
case 0x60: /* next data byte is placed in 8042 command byte */
m_operation_write_state = 5;
@ -548,12 +463,16 @@ WRITE8_MEMBER(kbdc8042_device::data_w)
* written to input register a port at 60h is sent to the
* auxiliary device */
m_operation_write_state = 4;
m_send_to_mouse = 1;
break;
case 0xe0:
/* read test inputs; read T1/T0 test inputs into bit 1/0 */
at_8042_receive(0x00);
break;
case 0xed:
/* set/unset keyboard LEDs */
at_8042_receive(0xfa);
break;
case 0xf0:
case 0xf2:
case 0xf4:
@ -581,3 +500,21 @@ WRITE_LINE_MEMBER(kbdc8042_device::write_out2)
{
m_out2 = state;
}
INPUT_PORTS_START( kbdc8042_mouse )
PORT_START("MOUSEX")
PORT_BIT(0x3ff, 0x000, IPT_MOUSE_X) PORT_SENSITIVITY(100) PORT_MINMAX(0x000, 0x3ff) PORT_KEYDELTA(2)
PORT_START("MOUSEY")
PORT_BIT(0x3ff, 0x000, IPT_MOUSE_Y) PORT_SENSITIVITY(100) PORT_MINMAX(0x000, 0x3ff) PORT_KEYDELTA(2)
PORT_START("MOUSEBTN")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_CODE(MOUSECODE_BUTTON1) PORT_NAME("Mouse Button 1")
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_CODE(MOUSECODE_BUTTON2) PORT_NAME("Mouse Button 2")
PORT_BIT(0xfc, IP_ACTIVE_HIGH, IPT_UNUSED)
INPUT_PORTS_END
ioport_constructor kbdc8042_device::device_input_ports() const
{
return INPUT_PORTS_NAME(kbdc8042_mouse);
}

View File

@ -70,8 +70,9 @@ public:
DECLARE_WRITE_LINE_MEMBER( write_out2 );
void at_8042_set_outport(uint8_t data, int initial);
void at_8042_receive(uint8_t data);
void at_8042_receive(uint8_t data, bool mouse = false);
void at_8042_check_keyboard();
void at_8042_check_mouse();
void at_8042_clear_keyboard_received();
protected:
@ -79,9 +80,13 @@ protected:
virtual void device_start() override;
virtual void device_reset() override;
virtual void device_add_mconfig(machine_config &config) override;
virtual ioport_constructor device_input_ports() const override;
private:
uint8_t m_inport, m_outport, m_data, m_command;
uint8_t m_inport;
uint8_t m_outport;
uint8_t m_data;
uint8_t m_command;
struct {
int received;
@ -90,6 +95,10 @@ private:
struct {
int received;
int on;
uint8_t sample_rate;
bool receiving_sample_rate;
uint8_t transmit_buf[8];
uint8_t to_transmit;
} m_mouse;
int m_last_write_to_control;
@ -108,6 +117,9 @@ private:
int m_poll_delay;
required_device<at_keyboard_device> m_keyboard_dev;
required_ioport m_mousex_port;
required_ioport m_mousey_port;
required_ioport m_mousebtn_port;
kbdc8042_type_t m_keybtype;
@ -118,6 +130,10 @@ private:
devcb_write8 m_speaker_cb;
uint16_t m_mouse_x;
uint16_t m_mouse_y;
uint8_t m_mouse_btn;
DECLARE_WRITE_LINE_MEMBER( keyboard_w );
};

View File

@ -200,9 +200,42 @@ void newport_video_device::device_reset()
m_REX3.nKludge_SkipLine = 0;
}
uint32_t newport_video_device::get_cursor_pixel(int x, int y)
{
if (x < 0 || y < 0)
return 0;
bool monochrome_cursor = BIT(VC2_DISPLAYCTRL, DCR_CURSOR_SIZE_BIT) == DCR_CURSOR_SIZE_64;
int size = monochrome_cursor ? 64 : 32;
if (x >= size || y >= size)
return 0;
const int shift = 15 - (x % 16);
if (monochrome_cursor)
{
const int address = y * 4 + (x / 16);
const uint16_t word = m_VC2.nRAM[VC2_CURENTRY + address];
const uint16_t entry = BIT(word, shift);
return m_CMAP0.nPalette[entry];
}
else
{
const int address = y * 2 + (x / 16);
const uint16_t word0 = m_VC2.nRAM[VC2_CURENTRY + address];
const uint16_t word1 = m_VC2.nRAM[VC2_CURENTRY + address + 64];
const uint16_t entry = BIT(word0, shift) | (BIT(word1, shift) << 1);
return m_CMAP0.nPalette[entry];
}
}
uint32_t newport_video_device::screen_update(screen_device &device, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
bool enable_cursor = BIT(VC2_DISPLAYCTRL, DCR_CURSOR_FUNC_ENABLE_BIT) != 0
&& BIT(VC2_DISPLAYCTRL, DCR_CURSOR_ENABLE_BIT) != 0
&& BIT(VC2_DISPLAYCTRL, DCR_CURSOR_MODE_BIT) == DCR_CURSOR_MODE_GLYPH;
/* loop over rows and copy to the destination */
for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
{
@ -212,7 +245,14 @@ uint32_t newport_video_device::screen_update(screen_device &device, bitmap_rgb32
/* loop over columns */
for (int x = cliprect.min_x; x < cliprect.max_x; x++)
{
*dest++ = (*src++) & 0x00f8f8f8;
uint32_t ram_pixel = (*src) & 0x00f8f8f8;
uint32_t cursor_pixel = 0;
if (x >= (VC2_CURSORX - 31) && x <= VC2_CURSORX && y >= (VC2_CURSORY - 31) && y <= VC2_CURSORY && enable_cursor)
{
cursor_pixel = get_cursor_pixel(x - ((int)VC2_CURSORX - 31), y - ((int)VC2_CURSORY - 31));
}
*dest++ = cursor_pixel ? cursor_pixel : ram_pixel;
src++;
}
}
return 0;
@ -505,67 +545,68 @@ WRITE32_MEMBER( newport_video_device::vc2_w )
//verboselog(machine(), 2, "VC2 Register Setup:\n" );
m_VC2.nRegIdx = ( data & 0xff000000 ) >> 24;
m_VC2.nRegData = ( data & 0x00ffff00 ) >> 8;
switch( m_VC2.nRegIdx )
{
case 0x00:
//verboselog(machine(), 2, " Video Entry Pointer: %04x\n", m_VC2.nRegData );
break;
case 0x01:
//verboselog(machine(), 2, " Cursor Entry Pointer: %04x\n", m_VC2.nRegData );
break;
case 0x02:
//verboselog(machine(), 2, " Cursor X Location: %04x\n", m_VC2.nRegData );
break;
case 0x03:
//verboselog(machine(), 2, " Cursor Y Location: %04x\n", m_VC2.nRegData );
break;
case 0x04:
//verboselog(machine(), 2, " Current Cursor X: %04x\n", m_VC2.nRegData );
break;
case 0x05:
//verboselog(machine(), 2, " DID Entry Pointer: %04x\n", m_VC2.nRegData );
break;
case 0x06:
//verboselog(machine(), 2, " Scanline Length: %04x\n", m_VC2.nRegData );
break;
case 0x07:
//verboselog(machine(), 2, " RAM Address: %04x\n", m_VC2.nRegData );
break;
case 0x08:
//verboselog(machine(), 2, " VT Frame Table Ptr: %04x\n", m_VC2.nRegData );
break;
case 0x09:
//verboselog(machine(), 2, " VT Line Sequence Ptr: %04x\n", m_VC2.nRegData );
break;
case 0x0a:
//verboselog(machine(), 2, " VT Lines in Run: %04x\n", m_VC2.nRegData );
break;
case 0x0b:
//verboselog(machine(), 2, " Vertical Line Count: %04x\n", m_VC2.nRegData );
break;
case 0x0c:
//verboselog(machine(), 2, " Cursor Table Ptr: %04x\n", m_VC2.nRegData );
break;
case 0x0d:
//verboselog(machine(), 2, " Working Cursor Y: %04x\n", m_VC2.nRegData );
break;
case 0x0e:
//verboselog(machine(), 2, " DID Frame Table Ptr: %04x\n", m_VC2.nRegData );
break;
case 0x0f:
//verboselog(machine(), 2, " DID Line Table Ptr: %04x\n", m_VC2.nRegData );
break;
case 0x10:
//verboselog(machine(), 2, " Display Control: %04x\n", m_VC2.nRegData );
break;
case 0x1f:
//verboselog(machine(), 2, " Configuration: %04x\n", m_VC2.nRegData );
m_VC2.nRegister[0x20] = m_VC2.nRegData;
break;
default:
//verboselog(machine(), 2, " Unknown VC2 Register: %04x\n", m_VC2.nRegData );
break;
}
switch( m_VC2.nRegIdx )
{
case 0x00:
//verboselog(machine(), 2, " Video Entry Pointer: %04x\n", m_VC2.nRegData );
break;
case 0x01:
//verboselog(machine(), 2, " Cursor Entry Pointer: %04x\n", m_VC2.nRegData );
break;
case 0x02:
//verboselog(machine(), 2, " Cursor X Location: %04x\n", m_VC2.nRegData );
break;
case 0x03:
//verboselog(machine(), 2, " Cursor Y Location: %04x\n", m_VC2.nRegData );
VC2_CURCURSORX = VC2_CURSORX;
break;
case 0x04:
//verboselog(machine(), 2, " Current Cursor X: %04x\n", m_VC2.nRegData );
break;
case 0x05:
//verboselog(machine(), 2, " DID Entry Pointer: %04x\n", m_VC2.nRegData );
break;
case 0x06:
//verboselog(machine(), 2, " Scanline Length: %04x\n", m_VC2.nRegData );
break;
case 0x07:
//verboselog(machine(), 2, " RAM Address: %04x\n", m_VC2.nRegData );
break;
case 0x08:
//verboselog(machine(), 2, " VT Frame Table Ptr: %04x\n", m_VC2.nRegData );
break;
case 0x09:
//verboselog(machine(), 2, " VT Line Sequence Ptr: %04x\n", m_VC2.nRegData );
break;
case 0x0a:
//verboselog(machine(), 2, " VT Lines in Run: %04x\n", m_VC2.nRegData );
break;
case 0x0b:
//verboselog(machine(), 2, " Vertical Line Count: %04x\n", m_VC2.nRegData );
break;
case 0x0c:
//verboselog(machine(), 2, " Cursor Table Ptr: %04x\n", m_VC2.nRegData );
break;
case 0x0d:
//verboselog(machine(), 2, " Working Cursor Y: %04x\n", m_VC2.nRegData );
break;
case 0x0e:
//verboselog(machine(), 2, " DID Frame Table Ptr: %04x\n", m_VC2.nRegData );
break;
case 0x0f:
//verboselog(machine(), 2, " DID Line Table Ptr: %04x\n", m_VC2.nRegData );
break;
case 0x10:
//verboselog(machine(), 2, " Display Control: %04x\n", m_VC2.nRegData );
break;
case 0x1f:
//verboselog(machine(), 2, " Configuration: %04x\n", m_VC2.nRegData );
m_VC2.nRegister[0x20] = m_VC2.nRegData;
break;
default:
//verboselog(machine(), 2, " Unknown VC2 Register: %04x\n", m_VC2.nRegData );
break;
}
m_VC2.nRegister[m_VC2.nRegIdx] = m_VC2.nRegData;
break;
default:

View File

@ -27,6 +27,20 @@ protected:
virtual void device_reset() override;
private:
enum
{
DCR_CURSOR_FUNC_ENABLE_BIT = 4,
DCR_CURSOR_ENABLE_BIT = 7,
DCR_CURSOR_MODE_BIT = 8,
DCR_CURSOR_MODE_GLYPH = 0,
DCR_CURSOR_MODE_CROSSHAIR = 1,
DCR_CURSOR_SIZE_BIT = 9,
DCR_CURSOR_SIZE_32 = 0,
DCR_CURSOR_SIZE_64 = 1
};
struct VC2_t
{
uint16_t nRegister[0x21];
@ -128,6 +142,7 @@ private:
uint32_t nPalette[0x10000];
};
uint32_t get_cursor_pixel(int x, int y);
// internal state