diff --git a/src/devices/machine/8042kbdc.cpp b/src/devices/machine/8042kbdc.cpp index 44927c1433c..649be5f2529 100644 --- a/src/devices/machine/8042kbdc.cpp +++ b/src/devices/machine/8042kbdc.cpp @@ -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); +} diff --git a/src/devices/machine/8042kbdc.h b/src/devices/machine/8042kbdc.h index 2166b2141b8..398cd1127e4 100644 --- a/src/devices/machine/8042kbdc.h +++ b/src/devices/machine/8042kbdc.h @@ -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 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 ); }; diff --git a/src/mame/video/newport.cpp b/src/mame/video/newport.cpp index d1ae70816a2..778049a721a 100644 --- a/src/mame/video/newport.cpp +++ b/src/mame/video/newport.cpp @@ -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: diff --git a/src/mame/video/newport.h b/src/mame/video/newport.h index 6ab8c2308dd..0b64803b623 100644 --- a/src/mame/video/newport.h +++ b/src/mame/video/newport.h @@ -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