Improved passing of scan codes to the emulated keyboards;

Fixed Sound Blaster 16 and earlier CD-ROM volume registers (and made them no longer default to 0);
Serial mouse now resets the FIFO before sending the ID, fixes mouse detection after clipping and moving the mouse;
Rewritten CD-ROM and SCSI disk Mode Select handling and changed things regarding Mode Sense as well, also fixes emulator segmentation faults when anything attempts to do a Mode Select;
Fixed the Microsoft InPort mouse emulation (used the Bochs code as reference for the polling/state update code), now it actually moves;
The PCjr initialization now sets the XT scan code table, makes the keyboard actually work on the PCjr again;
Several bugfixes regarding the Read CD commands, fixes CD Audio in digital mode on Windows ME;
Finally properly fixed the regular CD Audio MSF/LBA conversion mess;
Applied all applicable PCem commits.
This commit is contained in:
OBattler
2018-01-13 22:56:13 +01:00
parent b4aff71a6b
commit 845c8ed4bd
29 changed files with 2127 additions and 2358 deletions

View File

@@ -8,15 +8,15 @@
*
* General keyboard driver interface.
*
* Version: @(#)keyboard.c 1.0.10 2017/12/31
* Version: @(#)keyboard.c 1.0.11 2018/01/09
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
*
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016,2017 Miran Grca.
* Copyright 2017 Fred N. van Kempen.
* Copyright 2008-2018 Sarah Walker.
* Copyright 2016,2018 Miran Grca.
* Copyright 2018 Fred N. van Kempen.
*/
#include <stdio.h>
#include <stdint.h>
@@ -29,54 +29,57 @@
int64_t keyboard_delay;
int keyboard_scan;
void (*keyboard_send)(uint8_t val);
void (*keyboard_send)(uint16_t val);
static int recv_key[272]; /* keyboard input buffer */
static int oldkey[272];
static int keydelay[272];
static int recv_key[512]; /* keyboard input buffer */
static int oldkey[512];
static int keydelay[512];
static scancode *scan_table; /* scancode table for keyboard */
static uint8_t caps_lock = 0;
static uint8_t num_lock = 0;
static uint8_t scroll_lock = 0;
static uint8_t shift = 0;
/*
* This array acts an intermediary so scan codes are processed in
* the correct order (ALT-CTRL-SHIFT-RSHIFT first, then all others).
*/
static int scorder[272] = {
0x38, 0xB8, 0x1D, 0x9D, 0xFF, 0x2A, 0x36, 0x103,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1E, 0x1F, 0x20,
0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
0x29, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31,
0x32, 0x33, 0x34, 0x35, 0x37, 0x39, 0x3A, 0x3B,
0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43,
0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B,
0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53,
0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B,
0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63,
0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B,
0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73,
0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B,
0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83,
0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B,
0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93,
0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B,
0x9C, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4,
0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC,
0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4,
0xB5, 0xB6, 0xB7, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD,
0xBE, 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5,
0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD,
0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5,
0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD,
0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5,
0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED,
0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5,
0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD,
0xFE, 0x100, 0x101, 0x102, 0x104, 0x105, 0x106, 0x107,
0x108, 0x109, 0x10A, 0x10B, 0x10C, 0x10D, 0x10E, 0x10F
static int scorder[512] = {
0x38, 0xB8, 0x1D, 0x9D, 0xFF, 0x2A, 0x36, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
0x19, 0x1A, 0x1B, 0x1C, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x28,
0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x37, 0x39, 0x3A, 0x3B, 0x3C,
0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C,
0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C,
0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C,
0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C,
0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C,
0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C,
0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD,
0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE,
0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE,
0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE,
0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE,
0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE,
0x100,0x101,0x102,0x103,0x104,0x105,0x106,0x107,0x108,0x109,0x10A,0x10B,0x10C,0x10D,0x10E,0x10F,
0x110,0x111,0x112,0x113,0x114,0x115,0x116,0x117,0x118,0x119,0x11A,0x11B,0x11C,0x11D,0x11E,0x11F,
0x120,0x121,0x122,0x123,0x124,0x125,0x126,0x127,0x128,0x129,0x12A,0x12B,0x12C,0x12D,0x12E,0x12F,
0x130,0x131,0x132,0x133,0x134,0x135,0x136,0x137,0x138,0x139,0x13A,0x13B,0x13C,0x13D,0x13E,0x13F,
0x140,0x141,0x142,0x143,0x144,0x145,0x146,0x147,0x148,0x149,0x14A,0x14B,0x14C,0x14D,0x14E,0x14F,
0x150,0x151,0x152,0x153,0x154,0x155,0x156,0x157,0x158,0x159,0x15A,0x15B,0x15C,0x15D,0x15E,0x15F,
0x160,0x161,0x162,0x163,0x164,0x165,0x166,0x167,0x168,0x169,0x16A,0x16B,0x16C,0x16D,0x16E,0x16F,
0x170,0x171,0x172,0x173,0x174,0x175,0x176,0x177,0x178,0x179,0x17A,0x17B,0x17C,0x17D,0x17E,0x17F,
0x180,0x181,0x182,0x183,0x184,0x185,0x186,0x187,0x188,0x189,0x18A,0x18B,0x18C,0x18D,0x18E,0x18F,
0x190,0x191,0x192,0x193,0x194,0x195,0x196,0x197,0x198,0x199,0x19A,0x19B,0x19C,0x19D,0x19E,0x19F,
0x1A0,0x1A1,0x1A2,0x1A3,0x1A4,0x1A5,0x1A6,0x1A7,0x1A8,0x1A9,0x1AA,0x1AB,0x1AC,0x1AD,0x1AE,0x1AF,
0x1B0,0x1B1,0x1B2,0x1B3,0x1B4,0x1B5,0x1B6,0x1B7,0x1B8,0x1B9,0x1BA,0x1BB,0x1BC,0x1BD,0xBAE,0x1BF,
0x1C0,0x1C1,0x1C2,0x1C3,0x1C4,0x1C5,0x1C6,0x1C7,0x1C8,0x1C9,0x1CA,0x1CB,0x1CC,0x1CD,0x1CE,0x1CF,
0x1D0,0x1D1,0x1D2,0x1D3,0x1D4,0x1D5,0x1D6,0x1D7,0x1D8,0x1D9,0x1DA,0x1DB,0x1DC,0x1DD,0x1DE,0x1DF,
0x1E0,0x1E1,0x1E2,0x1E3,0x1E4,0x1E5,0x1E6,0x1E7,0x1E8,0x1E9,0x1EA,0x1EB,0x1EC,0x1ED,0x1EE,0x1EF,
0x1F0,0x1F1,0x1F2,0x1F3,0x1F4,0x1F5,0x1F6,0x1F7,0x1F8,0x1F9,0x1FA,0x1FB,0x1FC,0x1FD,0x1FE,0x1FF
};
@@ -102,6 +105,27 @@ keyboard_set_table(scancode *ptr)
}
static uint8_t
fake_shift_needed(uint16_t scan)
{
switch(scan) {
case 0x147:
case 0x148:
case 0x149:
case 0x14a:
case 0x14d:
case 0x14f:
case 0x150:
case 0x151:
case 0x152:
case 0x153:
return 1;
default:
return 0;
}
}
void
keyboard_process(void)
{
@@ -110,14 +134,14 @@ keyboard_process(void)
if (! keyboard_scan) return;
for (c = 0; c < 272; c++) {
for (c = 0; c < 512; c++) {
if (recv_key[scorder[c]])
keydelay[scorder[c]]++;
else
keydelay[scorder[c]] = 0;
}
for (c = 0; c < 272; c++) {
for (c = 0; c < 512; c++) {
if (recv_key[scorder[c]] != oldkey[scorder[c]]) {
oldkey[scorder[c]] = recv_key[scorder[c]];
if (recv_key[scorder[c]] &&
@@ -134,16 +158,22 @@ keyboard_process(void)
d = 0;
if (recv_key[scorder[c]]) {
/* Send the special code indicating an opening fake shift might be needed. */
if (fake_shift_needed(scorder[c]))
keyboard_send(0x100);
while (codes[scorder[c]].mk[d] != -1)
keyboard_send(codes[scorder[c]].mk[d++]);
} else {
while (codes[scorder[c]].brk[d] != -1)
keyboard_send(codes[scorder[c]].brk[d++]);
/* Send the special code indicating a closing fake shift might be needed. */
if (fake_shift_needed(scorder[c]))
keyboard_send(0x101);
}
}
}
for (c = 0; c < 272; c++) {
for (c = 0; c < 512; c++) {
if (AT && ((keyboard_mode & 3) == 3)) {
if (codes[scorder[c]].mk[0] == -1) continue;
@@ -168,12 +198,15 @@ keyboard_process(void)
void
keyboard_input(int down, uint16_t scan)
{
#if 0
int key;
#endif
#if 0
pclog("KBD: kbinput %d %04x\n", down, scan);
#endif
#if 0
if ((scan >> 8) == 0xf0) {
scan &= 0x00ff;
scan |= 0x0100; /* ext key code in disambiguated format */
@@ -191,6 +224,174 @@ keyboard_input(int down, uint16_t scan)
key = scan & 0xff;
if (key > 0)
recv_key[key] = down;
#endif
/* Translate E0 xx scan codes to 01xx because we use 512-byte arrays for states
and scan code sets. */
if ((scan >> 8) == 0xe0) {
scan &= 0x00ff;
scan |= 0x0100; /* extended key code */
} else if ((scan >> 8) != 0x01)
scan &= 0x00ff; /* we can receive a scan code whose upper byte is 0x01,
this means we're the Win32 version running on windows
that already sends us preprocessed scan codes, which
means we then use the scan code as is, and need to
make sure we do not accidentally strip that upper byte */
if (recv_key[scan & 0x1ff] ^ down) {
if (down) {
switch(scan & 0x1ff) {
case 0x01c: /* Left Ctrl */
shift |= 0x01;
break;
case 0x11c: /* Right Ctrl */
shift |= 0x10;
break;
case 0x02a: /* Left Shift */
shift |= 0x02;
break;
case 0x036: /* Right Shift */
shift |= 0x20;
break;
case 0x038: /* Left Alt */
shift |= 0x03;
break;
case 0x138: /* Right Alt */
shift |= 0x30;
break;
}
} else {
switch(scan & 0x1ff) {
case 0x01c: /* Left Ctrl */
shift &= ~0x01;
break;
case 0x11c: /* Right Ctrl */
shift &= ~0x10;
break;
case 0x02a: /* Left Shift */
shift &= ~0x02;
break;
case 0x036: /* Right Shift */
shift &= ~0x20;
break;
case 0x038: /* Left Alt */
shift &= ~0x03;
break;
case 0x138: /* Right Alt */
shift &= ~0x30;
break;
case 0x03a: /* Caps Lock */
caps_lock ^= 1;
break;
case 0x045:
num_lock ^= 1;
break;
case 0x046:
scroll_lock ^= 1;
break;
}
}
}
/* NOTE: Shouldn't this be some sort of bit shift? An array of 8 unsigned 64-bit integers
should be enough. */
/* recv_key[scan >> 6] |= ((uint64_t) down << ((uint64_t) scan & 0x3fLL)); */
/* pclog("Received scan code: %03X (%s)\n", scan & 0x1ff, down ? "down" : "up"); */
recv_key[scan & 0x1ff] = down;
}
static uint8_t
keyboard_do_break(uint16_t scan)
{
scancode *codes = scan_table;
if (AT && ((keyboard_mode & 3) == 3)) {
if (!keyboard_set3_all_break &&
!recv_key[scorder[scan]] &&
!(keyboard_set3_flags[codes[scorder[scan]].mk[0]] & 2))
return 0;
else
return 1;
} else
return 1;
}
/* Also called by the emulated keyboard controller to update the states of
Caps Lock, Num Lock, and Scroll Lock when receving the "Set keyboard LEDs"
command. */
void
keyboard_update_states(uint8_t cl, uint8_t nl, uint8_t sl)
{
caps_lock = cl;
num_lock = nl;
scroll_lock = sl;
}
uint8_t
keyboard_get_shift(void)
{
return shift;
}
void
keyboard_get_states(uint8_t *cl, uint8_t *nl, uint8_t *sl)
{
if (cl)
*cl = caps_lock;
if (nl)
*nl = num_lock;
if (sl)
*sl = scroll_lock;
}
/* Called by the UI to update the states of Caps Lock, Num Lock, and Scroll Lock. */
void
keyboard_set_states(uint8_t cl, uint8_t nl, uint8_t sl)
{
scancode *codes = scan_table;
int i;
if (caps_lock != cl) {
i = 0;
while (codes[0x03a].mk[i] != -1)
keyboard_send(codes[0x03a].mk[i++]);
if (keyboard_do_break(0x03a)) {
i = 0;
while (codes[0x03a].brk[i] != -1)
keyboard_send(codes[0x03a].brk[i++]);
}
}
if (num_lock != nl) {
i = 0;
while (codes[0x045].mk[i] != -1)
keyboard_send(codes[0x045].mk[i++]);
if (keyboard_do_break(0x045)) {
i = 0;
while (codes[0x045].brk[i] != -1)
keyboard_send(codes[0x045].brk[i++]);
}
}
if (scroll_lock != sl) {
i = 0;
while (codes[0x046].mk[i] != -1)
keyboard_send(codes[0x046].mk[i++]);
if (keyboard_do_break(0x046)) {
i = 0;
while (codes[0x046].brk[i] != -1)
keyboard_send(codes[0x046].brk[i++]);
}
}
keyboard_update_states(cl, nl, sl);
}
@@ -220,6 +421,6 @@ keyboard_ismsexit(void)
return( recv_key[0x42] && recv_key[0x58] );
#else
/* WxWidgets cannot do two regular keys.. CTRL+END */
return( (recv_key[0x1D] || recv_key[0x9D]) && recv_key[0xCF] );
return( (recv_key[0x1D] || recv_key[0x9D]) && (recv_key[0x14F] || recv_key[0x1CF]) );
#endif
}