Skip to content

Commit c7462dd

Browse files
committed
Handle OEM102 and ABNT1 keyboard scancodes (#2199)
1 parent d49a201 commit c7462dd

File tree

6 files changed

+300
-162
lines changed

6 files changed

+300
-162
lines changed

contrib/sdl_key_logger/README.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,60 @@ meson compile -C build
2121
``` shell
2222
./build/logger
2323
```
24+
25+
## Add handling for a new key
26+
27+
Pre-requisite: the physical keyboard with the (currently)
28+
unhandled key
29+
30+
1. Compile and run the logger. Press the unhandled key and get
31+
the SDL scancode number for the key (get the decimal value, not
32+
the hex value).
33+
34+
2. Using the key's SDL scancode number, open SDL's
35+
`SDL_scancode.h` header and find the corresponding enum key
36+
name.
37+
38+
3. In `sdl_mapper.cpp`:
39+
40+
- Confirm the SDL enum name doesn't exist (yet) in this
41+
file.
42+
43+
- Add the SDL enum and a corresponding new shorthand string
44+
to the DefaultKeys[] array.
45+
46+
- add the key's default symbol and your new shorthand name
47+
to the best KeyBlock array, along with a new KBD_<name> for
48+
the key
49+
50+
- if the logger didn't report a text scancode name for the
51+
key, then add your new shorthand name for it in
52+
GetBindName(), similar to 'oem102' and 'abnt1', for which
53+
SDL also doesn't have SDL scancode names.
54+
55+
3. In keyboard.h and .cpp:
56+
57+
- Using http://kbdlayout.info using the correct arrangement,
58+
look up the key's (non-SDL) scancode hex value.
59+
60+
- Convert that (non-SDL) hex scancode to decimal value.
61+
62+
- Add your new KBD_shortname enum name KEYBOARD_AddKey()
63+
switch statement, with the ret=<value> being the (non-SDL)
64+
scancode decimal value.
65+
66+
4. In bios_keyboard.cpp's get_key_codes_for() function:
67+
68+
- Find (or add) the decimal index entry matching the ret=
69+
(non-SDL) scancode decimal value.
70+
71+
- Add four codes for the key, matching the same pattern (or
72+
use existing code). For example, the codes usually start
73+
with the high-byte being the hex value of the (non-SDL)
74+
scancode number.
75+
76+
77+
For a graphical layout of this process, see the image attached
78+
in PR:
79+
80+
https://github.com/dosbox-staging/dosbox-staging/pull/2209

include/bios.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,11 @@
112112
#define BIOS_DEFAULT_IRQ2_LOCATION (RealMake(0xf000,0xff55))
113113
#define BIOS_DEFAULT_RESET_LOCATION (RealMake(0xf000,(machine==MCH_PCJR)?0x0043:0xe05b))
114114

115-
/* maximum of scancodes handled by keyboard bios routines */
116-
#define MAX_SCAN_CODE 0x59
115+
// The maximum "normal key" scancode value handled by keyboard bios routines.
116+
// This should match the maximum return value set in KEYBOARD_AddKey()'s switch
117+
// statement. The scan code is read from an 8-bit register (reg_al) and
118+
// therefore limited to handling 255 keys.
119+
constexpr uint8_t MAX_SCAN_CODE = 115;
117120

118121
/* The Section handling Bios Disk Access */
119122
//#define BIOS_MAX_DISK 10

include/keyboard.h

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,22 +32,19 @@ enum KBD_KEYS {
3232
KBD_f1, KBD_f2, KBD_f3, KBD_f4, KBD_f5, KBD_f6,
3333
KBD_f7, KBD_f8, KBD_f9, KBD_f10, KBD_f11, KBD_f12,
3434

35-
// Now the weirder keys
36-
3735
KBD_esc, KBD_tab, KBD_backspace, KBD_enter, KBD_space,
3836

3937
KBD_leftalt, KBD_rightalt,
4038
KBD_leftctrl, KBD_rightctrl,
4139
KBD_leftgui, KBD_rightgui, // 'windows' keys
4240
KBD_leftshift, KBD_rightshift,
43-
41+
4442
KBD_capslock, KBD_scrolllock, KBD_numlock,
4543

4644
KBD_grave, KBD_minus, KBD_equals, KBD_backslash,
4745
KBD_leftbracket, KBD_rightbracket,
4846
KBD_semicolon, KBD_quote,
49-
KBD_period, KBD_comma, KBD_slash,
50-
KBD_extra_lt_gt,
47+
KBD_oem102, KBD_period, KBD_comma, KBD_slash, KBD_abnt1,
5148

5249
KBD_printscreen, KBD_pause,
5350

@@ -60,8 +57,6 @@ enum KBD_KEYS {
6057
KBD_kpdivide, KBD_kpmultiply, KBD_kpminus, KBD_kpplus,
6158
KBD_kpenter, KBD_kpperiod,
6259

63-
KBD_intl1,
64-
6560
KBD_LAST,
6661
// clang-format on
6762
};

src/gui/sdl_mapper.cpp

Lines changed: 55 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -361,12 +361,30 @@ class CKeyBind final : public CBind {
361361

362362
std::string GetBindName() const override
363363
{
364-
if (key == SDL_SCANCODE_RETURN)
365-
return "Enter"; // instead of "Return"
366-
else if (key == SDL_SCANCODE_INTERNATIONAL1)
367-
return "International 1"; // instead of empty string
368-
else
369-
return SDL_GetScancodeName(key);
364+
// Always map Return to Enter
365+
if (key == SDL_SCANCODE_RETURN) {
366+
return "Enter";
367+
}
368+
369+
const std::string sdl_scancode_name = SDL_GetScancodeName(key);
370+
if (!sdl_scancode_name.empty()) {
371+
return sdl_scancode_name;
372+
}
373+
374+
// SDL Doesn't have a name for this key, so use our own
375+
assert(sdl_scancode_name.empty());
376+
377+
// Key between Left Shift and Z is "oem102"
378+
if (key == SDL_SCANCODE_NONUSBACKSLASH) {
379+
return "oem102"; // called 'OEM_102" at kbdlayout.info
380+
}
381+
// Key to the left of Right Shift on ABNT layouts
382+
if (key == SDL_SCANCODE_INTERNATIONAL1) {
383+
return "abnt1"; // called "ABNT_C1" at kbdlayout.info
384+
}
385+
386+
DEBUG_LOG_MSG("MAPPER: Please report unnamed SDL scancode %d (%xh)", key, key);
387+
return sdl_scancode_name;
370388
}
371389

372390
void ConfigName(char *buf) override
@@ -2080,13 +2098,18 @@ static KeyBlock combo_3[12]={
20802098
{"\\|","backslash",KBD_backslash},
20812099
};
20822100

2083-
static KeyBlock combo_4[11]={
2084-
{"<>","lessthan",KBD_extra_lt_gt},
2085-
{"Z","z",KBD_z}, {"X","x",KBD_x}, {"C","c",KBD_c},
2086-
{"V","v",KBD_v}, {"B","b",KBD_b}, {"N","n",KBD_n},
2087-
{"M","m",KBD_m}, {",<","comma",KBD_comma},
2088-
{".>","period",KBD_period}, {"/?","slash",KBD_slash},
2089-
};
2101+
static KeyBlock combo_4[12] = {{"\\|", "oem102", KBD_oem102},
2102+
{"Z", "z", KBD_z},
2103+
{"X", "x", KBD_x},
2104+
{"C", "c", KBD_c},
2105+
{"V", "v", KBD_v},
2106+
{"B", "b", KBD_b},
2107+
{"N", "n", KBD_n},
2108+
{"M", "m", KBD_m},
2109+
{",<", "comma", KBD_comma},
2110+
{".>", "period", KBD_period},
2111+
{"/?", "slash", KBD_slash},
2112+
{"/?", "abnt1", KBD_abnt1}};
20902113

20912114
static CKeyEvent * caps_lock_event=NULL;
20922115
static CKeyEvent * num_lock_event=NULL;
@@ -2112,8 +2135,16 @@ static void CreateLayout() {
21122135
for (i=0;i<12;i++) AddKeyButtonEvent(PX(2+i),PY(3),BW,BH,combo_3[i].title,combo_3[i].entry,combo_3[i].key);
21132136

21142137
AddKeyButtonEvent(PX(0),PY(4),BW*2,BH,"SHIFT","lshift",KBD_leftshift);
2115-
for (i=0;i<11;i++) AddKeyButtonEvent(PX(2+i),PY(4),BW,BH,combo_4[i].title,combo_4[i].entry,combo_4[i].key);
2116-
AddKeyButtonEvent(PX(13),PY(4),BW*3,BH,"SHIFT","rshift",KBD_rightshift);
2138+
for (i = 0; i < 12; i++) {
2139+
AddKeyButtonEvent(PX(2 + i),
2140+
PY(4),
2141+
BW,
2142+
BH,
2143+
combo_4[i].title,
2144+
combo_4[i].entry,
2145+
combo_4[i].key);
2146+
}
2147+
AddKeyButtonEvent(PX(14), PY(4), BW * 3, BH, "SHIFT", "rshift", KBD_rightshift);
21172148

21182149
/* Bottom Row */
21192150
AddKeyButtonEvent(PX(0), PY(5), BW * 2, BH, MMOD1_NAME, "lctrl", KBD_leftctrl);
@@ -2177,8 +2208,6 @@ static void CreateLayout() {
21772208
AddKeyButtonEvent(PX(XO),PY(YO+4),BW*2,BH,"0","kp_0",KBD_kp0);
21782209
AddKeyButtonEvent(PX(XO+2),PY(YO+4),BW,BH,".","kp_period",KBD_kpperiod);
21792210

2180-
/* International Keys */
2181-
AddKeyButtonEvent(PX(XO + 5), PY(YO), BW * 2, BH, "Intl1", "intl1", KBD_intl1);
21822211
#undef XO
21832212
#undef YO
21842213

@@ -2478,11 +2507,15 @@ static struct {
24782507
{"kp_period", SDL_SCANCODE_KP_PERIOD},
24792508
{"kp_enter", SDL_SCANCODE_KP_ENTER},
24802509

2481-
/* Is that the extra backslash key ("less than" key) */
2482-
/* on some keyboards with the 102-keys layout?? */
2483-
{"lessthan", SDL_SCANCODE_NONUSBACKSLASH},
2484-
2485-
{"intl1", SDL_SCANCODE_INTERNATIONAL1},
2510+
// ABNT-arrangement, key between Left-Shift and Z: SDL
2511+
// scancode 100 (0x64) maps to OEM102 key with scancode 86
2512+
// (0x56)
2513+
{"oem102", SDL_SCANCODE_NONUSBACKSLASH},
2514+
2515+
// ABNT-arrangement, key between Left-Shift and Z: SDL
2516+
// scancode 135 (0x87) maps to first ABNT key with scancode
2517+
// 115 (0x73)
2518+
{"abnt1", SDL_SCANCODE_INTERNATIONAL1},
24862519

24872520
{0, SDL_SCANCODE_UNKNOWN}};
24882521

src/hardware/keyboard.cpp

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,14 @@
1919
#include "dosbox.h"
2020
#include "keyboard.h"
2121

22+
#include "bios.h"
2223
#include "bitops.h"
2324
#include "inout.h"
24-
#include "pic.h"
2525
#include "mem.h"
2626
#include "mixer.h"
27-
#include "timer.h"
27+
#include "pic.h"
2828
#include "support.h"
29+
#include "timer.h"
2930

3031
#define KEYBUFSIZE 32
3132
#define KEYDELAY 0.300 // Considering 20-30 khz serial clock and 11 bits/char
@@ -365,6 +366,7 @@ void KEYBOARD_AddKey(KBD_KEYS keytype,bool pressed) {
365366
case KBD_grave:ret=41;break;
366367
case KBD_leftshift:ret=42;break;
367368
case KBD_backslash:ret=43;break;
369+
case KBD_oem102: ret = 86; break;
368370
case KBD_z:ret=44;break;
369371
case KBD_x:ret=45;break;
370372
case KBD_c:ret=46;break;
@@ -376,6 +378,7 @@ void KEYBOARD_AddKey(KBD_KEYS keytype,bool pressed) {
376378
case KBD_comma:ret=51;break;
377379
case KBD_period:ret=52;break;
378380
case KBD_slash:ret=53;break;
381+
case KBD_abnt1: ret = 115; break;
379382
case KBD_rightshift:ret=54;break;
380383
case KBD_kpmultiply:ret=55;break;
381384
case KBD_leftalt:ret=56;break;
@@ -410,16 +413,10 @@ void KEYBOARD_AddKey(KBD_KEYS keytype,bool pressed) {
410413
case KBD_kp0:ret=82;break;
411414
case KBD_kpperiod:ret=83;break;
412415

413-
case KBD_extra_lt_gt:ret=86;break;
414416
case KBD_f11:ret=87;break;
415417
case KBD_f12:ret=88;break;
416418

417-
// International keys
418-
419-
case KBD_intl1:ret=89;break;
420-
421419
//The Extended keys
422-
423420
case KBD_kpenter:extend=true;ret=28;break;
424421
case KBD_rightctrl:extend=true;ret=29;break;
425422
case KBD_kpdivide:extend=true;ret=53;break;
@@ -434,8 +431,8 @@ void KEYBOARD_AddKey(KBD_KEYS keytype,bool pressed) {
434431
case KBD_pagedown:extend=true;ret=81;break;
435432
case KBD_insert:extend=true;ret=82;break;
436433
case KBD_delete:extend=true;ret=83;break;
437-
case KBD_leftgui:extend=true;ret=90;break;
438-
case KBD_rightgui:extend=true;ret=89;break;
434+
case KBD_leftgui:extend=true;ret=91;break;
435+
case KBD_rightgui:extend=true;ret=92;break;
439436

440437
case KBD_pause:
441438
KEYBOARD_AddBuffer(0xe1);
@@ -452,6 +449,8 @@ void KEYBOARD_AddKey(KBD_KEYS keytype,bool pressed) {
452449
E_Exit("Unsupported key press");
453450
break;
454451
}
452+
assert(ret <= MAX_SCAN_CODE);
453+
455454
/* Add the actual key in the keyboard queue */
456455
if (pressed) {
457456
if (keyb.repeat.key == keytype) keyb.repeat.wait = keyb.repeat.rate;

0 commit comments

Comments
 (0)