Fix extended key processing on XT 101/102-key and AT 84-key keyboards.

This commit is contained in:
OBattler
2025-12-31 18:54:28 +01:00
parent 2b53f5595e
commit 2c670bf42d
4 changed files with 161 additions and 7 deletions

View File

@@ -85,6 +85,7 @@ typedef struct xtkbd_t {
uint8_t type;
uint8_t pravetz_flags;
uint8_t cpu_speed;
uint8_t ignore;
pc_timer_t send_delay_timer;
} xtkbd_t;
@@ -96,6 +97,8 @@ static int is_tandy = 0;
static int is_t1x00 = 0;
static int is_amstrad = 0;
#define kbd_adddata kbd_adddata_xt_common
#ifdef ENABLE_KEYBOARD_XT_LOG
int keyboard_xt_do_log = ENABLE_KEYBOARD_XT_LOG;
@@ -117,7 +120,6 @@ kbd_log(const char *fmt, ...)
static uint8_t
get_fdd_switch_settings(void)
{
uint8_t fdd_count = 0;
for (uint8_t i = 0; i < FDD_NUM; i++) {
@@ -134,7 +136,6 @@ get_fdd_switch_settings(void)
static uint8_t
get_videomode_switch_settings(void)
{
if (video_is_mda())
return 0x30;
else if (video_is_cga())
@@ -172,8 +173,8 @@ kbd_poll(void *priv)
}
}
static void
kbd_adddata(uint16_t val)
void
kbd_adddata_xt_common(uint16_t val)
{
/* Test for T1000 'Fn' key (Right Alt / Right Ctrl) */
if (is_t1x00) {
@@ -257,6 +258,98 @@ kbd_adddata_process(uint16_t val, void (*adddata)(uint16_t val))
}
}
void
kbd_adddata_process_10x(uint16_t val, void (*adddata)(uint16_t val))
{
uint8_t fake_shift[4] = { 0 };
uint8_t num_lock = 0;
uint8_t shift_states = 0;
if (!adddata)
return;
keyboard_get_states(NULL, &num_lock, NULL, NULL);
shift_states = keyboard_get_shift() & STATE_SHIFT_MASK;
switch (val) {
case FAKE_LSHIFT_ON:
kbd_log("%s: Fake left shift on, scan code: ", dev->name);
if (num_lock) {
if (shift_states) {
kbd_log("N/A (one or both shifts on)\n");
break;
} else {
/* Num lock on and no shifts are pressed, send non-inverted fake shift. */
kbd_log("E0 2A\n");
fake_shift[0] = 0xe0;
fake_shift[1] = 0x2a;
for (int i = 0; i < 2; i++)
adddata(fake_shift[0]);
}
} else {
if (shift_states & STATE_LSHIFT) {
/* Num lock off and left shift pressed. */
kbd_log("E0 AA\n");
fake_shift[0] = 0xe0;
fake_shift[1] = 0xaa;
for (int i = 0; i < 2; i++)
adddata(fake_shift[0]);
}
if (shift_states & STATE_RSHIFT) {
/* Num lock off and right shift pressed. */
kbd_log("E0 B6\n");
fake_shift[0] = 0xe0;
fake_shift[1] = 0xb6;
for (int i = 0; i < 2; i++)
adddata(fake_shift[0]);
}
kbd_log(shift_states ? "" : "N/A (both shifts off)\n");
}
break;
case FAKE_LSHIFT_OFF:
kbd_log("%s: Fake left shift on, scan code: ", dev->name);
if (num_lock) {
if (shift_states) {
kbd_log("N/A (one or both shifts on)\n");
break;
} else {
/* Num lock on and no shifts are pressed, send non-inverted fake shift. */
kbd_log("E0 AA\n");
fake_shift[0] = 0xe0;
fake_shift[1] = 0xaa;
for (int i = 0; i < 2; i++)
adddata(fake_shift[0]);
}
} else {
if (shift_states & STATE_LSHIFT) {
/* Num lock off and left shift pressed. */
kbd_log("E0 2A\n");
fake_shift[0] = 0xe0;
fake_shift[1] = 0x2a;
for (int i = 0; i < 2; i++)
adddata(fake_shift[0]);
break;
}
if (shift_states & STATE_RSHIFT) {
/* Num lock off and right shift pressed. */
kbd_log("E0 36\n");
fake_shift[0] = 0xe0;
fake_shift[1] = 0x36;
for (int i = 0; i < 2; i++)
adddata(fake_shift[0]);
break;
}
kbd_log(shift_states ? "" : "N/A (both shifts off)\n");
}
break;
default:
adddata(val);
break;
}
}
static void
kbd_adddata_ex(uint16_t val)
{

View File

@@ -5342,6 +5342,46 @@ add_data_vals(atkbc_dev_t *dev, uint8_t *val, uint8_t len)
kbc_at_dev_queue_add(dev, val[i], 1);
}
static void
add_data_kbd_84(uint16_t val)
{
atkbc_dev_t *dev = SavedKbd;
uint8_t fake_shift = 0;
uint8_t num_lock = 0;
uint8_t shift_states = 0;
keyboard_get_states(NULL, &num_lock, NULL, NULL);
shift_states = keyboard_get_shift() & STATE_LSHIFT;
/* If NumLock is on, invert the left shift state so we can always check for
the the same way flag being set (and with NumLock on that then means it
is actually *NOT* set). */
if (num_lock)
shift_states ^= STATE_LSHIFT;
switch (val) {
case FAKE_LSHIFT_ON:
/* If NumLock is on, fake shifts are sent when shift is *NOT* presed,
if NumLock is off, fake shifts are sent when shift is pressed. */
if (shift_states) {
/* Send fake shift. */
fake_shift = num_lock ? 0x2a : 0xaa;
add_data_vals(dev, &fake_shift, 1);
}
break;
case FAKE_LSHIFT_OFF:
if (shift_states) {
/* Send fake shift. */
fake_shift = num_lock ? 0xaa : 0x2a;
add_data_vals(dev, &fake_shift, 1);
}
break;
default:
kbc_at_dev_queue_add(dev, val, 1);
break;
}
}
static void
add_data_kbd(uint16_t val)
{
@@ -5975,7 +6015,10 @@ keyboard_at_init(const device_t *info)
bat_counter = 0x0000;
}
keyboard_send = add_data_kbd;
if ((dev->type & FLAG_TYPE_MASK) > KBD_84_KEY)
keyboard_send = add_data_kbd;
else
keyboard_send = add_data_kbd_84;
SavedKbd = dev;
keyboard_update_states(0, 0, 0, 0);

View File

@@ -557,6 +557,18 @@ typedef struct {
int type;
} kbd_t;
static void
kbd_adddata_xt(uint16_t val)
{
kbd_adddata_process(val, kbd_adddata_xt_common);
}
static void
kbd_adddata_xt_10x(uint16_t val)
{
kbd_adddata_process_10x(val, kbd_adddata_xt_common);
}
static void *
kbd_init(const device_t *info)
{
@@ -564,10 +576,13 @@ kbd_init(const device_t *info)
dev->type = device_get_config_int("keys");
if (dev->type == KBD_83_KEY)
if (dev->type == KBD_83_KEY) {
keyboard_set_table(scancode_xt);
else
keyboard_send = kbd_adddata_xt;
} else {
keyboard_set_table(scancode_set1);
keyboard_send = kbd_adddata_xt_10x;
}
return dev;
}

View File

@@ -165,7 +165,9 @@ extern uint16_t scancode_map[768];
extern uint16_t scancode_config_map[768];
extern void (*keyboard_send)(uint16_t val);
extern void kbd_adddata_xt_common(uint16_t val);
extern void kbd_adddata_process(uint16_t val, void (*adddata)(uint16_t val));
extern void kbd_adddata_process_10x(uint16_t val, void (*adddata)(uint16_t val));
extern const scancode scancode_xt[512];
@@ -211,6 +213,7 @@ extern void keyboard_close(void);
extern void keyboard_set_table(const scancode *ptr);
extern void keyboard_poll_host(void);
extern void keyboard_process(void);
extern void keyboard_process_10x(void);
extern uint16_t keyboard_convert(int ch);
extern void keyboard_input(int down, uint16_t scan);
extern void keyboard_all_up(void);