RISC-V Input controller
What the Input controller is
The Input controller reports key presses and releases, held keys, mouse buttons, pointer position and wheel turns. Unlike the keyboard registers, which provide typed characters, it also reports keys such as the arrows, Shift and the function keys.
This editor adds the device to RARS, alongside the Synth. Its memory registers start at 0xffff0300, after the Synth's. In RARS these addresses read 0 and provide no input. Check the ID register before using the controller, as the first program below does.
Click the Screen panel to send keyboard and mouse input to the program. While the Screen has focus, keys go to the program, including Escape. Press Shift+Tab, or click outside the Screen, to return keyboard control to the editor. Losing focus releases all held keys and mouse buttons: their state bits clear and release events enter the queue. This also happens when the browser window loses focus.
A first program
This program prints a letter for each arrow key you press, R, L, D or U, and ends when you press Escape. Build it and press Run, then click the Screen and press the arrows.
.text
main: li s0, 0xffff0300 # the Input controller
lw t0, 0(s0) # ID: 0x494E5001 when it is there
srli t0, t0, 8
li t1, 0x494E50 # "INP"
bne t0, t1, absent
poll: lw t0, 8(s0) # Status: how many events wait
beqz t0, idle
lw t2, 12(s0) # Event: take the oldest one
srli t3, t2, 8
andi t3, t3, 7 # its kind
andi t4, t2, 0xff # its code
li t5, 1 # kind 1: a key went down
bne t3, t5, poll
li t5, 0x29 # Escape
beq t4, t5, done
addi t5, t4, -0x4F # the arrows are 0x4F to 0x52
sltiu t6, t5, 4
beqz t6, poll # another key
la t6, arrows
add t6, t6, t5
lb a0, 0(t6) # R, L, D or U
li a7, 11
ecall
j poll
idle: li a0, 16 # nothing waits: sleep a frame
li a7, 32
ecall
j poll
absent: la a0, missing
li a7, 4
ecall
done: li a7, 10
ecall
.data
arrows: .ascii "RLDU"
missing:.asciz "This simulator has no Input controller.\n"1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
The program uses three registers:
- It reads the ID register once, to make sure the Input controller is there.
- It reads Status, which says how many events are waiting. If there are none, it sleeps for 16 milliseconds and looks again.
- Each read of Event takes the oldest waiting event, one word. The program takes it apart: the kind in bits 10–8, and the code in bits 7–0.
The registers
Offsets below are from 0xffff0300. Each register is one 32-bit word, except Keys, which occupies 32 bytes. Read registers with lw. Read individual bytes of Keys with lbu.
| Offset | Register | In C | Access | What it holds |
|---|---|---|---|---|
0x00 | Id | SIM_INPUT_ID | read | Reads 0x494E5001 ("INP", version 1) when the Input controller is available. Reads 0 in MARS and RARS, which do not provide this device |
0x04 | Control | SIM_INPUT_CONTROL | write | Reads 0. Bit 1 is reserved: setting it stops the program because the Input controller does not support interrupts. Leave it clear and poll Status for events. Other bits are ignored |
0x08 | Status | SIM_INPUT_STATUS | read | Bits 6–0 hold the number of queued events, 0 to 127. Reading Status does not remove events |
0x0C | Event | SIM_INPUT_EVENT | read, takes an event | Reading removes and returns the oldest queued event, or 0 if the queue is empty. Read once with lw and keep the result |
0x10 | Pointer | SIM_INPUT_POINTER | read | Pointer position and held mouse buttons: y in bits 30–21, x in bits 20–11, buttons in bits 2–0 |
0x14–0x1F | Reserved | Reads 0 | ||
0x20 | Keys | SIM_INPUT_KEYS | read | 256 bits indicating held keys, one per HID usage code. For code u, test bit u & 7 of the byte at KEYS + (u >> 3) |
Status normally ranges from 0 to 64, the queue's capacity. Undo can restore additional events, so Status can exceed 64. It reports at most 127, even if more events are waiting.
Reading Event removes an event. Even a byte read with lbu removes it. Read it once with lw and keep the result. Reads of the other registers remove nothing.
Writes do not change the controller's state or the values later reads return. One write causes an error: setting bit 1 of Control stops the program, because this controller does not support interrupts. Leave that bit clear and poll Status.
Events
Key presses, repeats and releases, mouse button presses and releases, and wheel turns produce events, one word each. Events wait in a queue, oldest first. Two key presses between reads are both kept in order, unless the queue is full.
| Bits | Field | What it holds |
|---|---|---|
| 31 | always 0 | |
| 30–21 | y | the pointer’s row when the event happened, 0 to 1023 |
| 20–11 | x | the pointer’s column, 0 to 1023 |
| 10–8 | kind | what happened, from the table below |
| 7–0 | code | which key or button, or how far the wheel turned |
Bit 31 of an Event word is always 0. Logical and arithmetic right shifts therefore give the same result when extracting its fields.
| Kind | In C | Meaning |
|---|---|---|
| 0 | No event: the queue was empty | |
| 1 | SIM_INPUT_KEY_DOWN | A key went down; the code is its HID usage |
| 2 | SIM_INPUT_KEY_UP | A key came up; the code is its HID usage |
| 3 | SIM_INPUT_KEY_REPEAT | A held key repeats, as it does when typing; the code is its HID usage |
| 4 | SIM_INPUT_BUTTON_DOWN | A mouse button went down; the code is 1 left, 2 right or 3 middle |
| 5 | SIM_INPUT_BUTTON_UP | A mouse button came up; the code is 1 left, 2 right or 3 middle |
| 6 | SIM_INPUT_WHEEL | The wheel turned; the code is a signed count of notches, positive away from the user |
| 7 | SIM_INPUT_DROPPED | The queue was full and events were lost here: read the state registers again |
- A key's code is its USB HID number. It identifies a physical key position rather than its printed character. For example, the position labelled S on a US keyboard is
KeyS(0x16), regardless of the active layout. The table at the end lists the supported keys. - Holding a key sends one key-down event, then repeats at the keyboard's typing repeat rate, then one key-up event on release. To move something while a key is held, read the keys held now instead of counting repeats.
- A button's code is 1 for the left button, 2 for the right and 3 for the middle one.
- The wheel's code is a signed number of notches: positive away from you, negative towards you. Consecutive unread wheel turns in the same direction merge into one event while their sum fits from −127 to 127. The merged event uses the latest pointer position.
- Every event carries the pointer's position at the moment it happened, so a click event says where the click was.
Taking an event apart:
lw t0, 12(s0) # one event
srli t1, t0, 8
andi t1, t1, 7 # kind, bits 10-8
andi t2, t0, 0xff # code, bits 7-0
srli t3, t0, 11
andi t3, t3, 0x3ff # x, bits 20-11
srli t4, t0, 21 # y, bits 30-21: bit 31 is 0
slli t5, t0, 24
srai t5, t5, 24 # a wheel's code as a signed number of notches1
2
3
4
5
6
7
8
9
The last two instructions sign-extend the wheel code on RV32. On RV64, use slli t5, t0, 56 followed by srai t5, t5, 56, as explained below.
Keys held now
From offset 0x20, 32 bytes hold one bit per key code. A bit is 1 while its key is held. For code k, read byte 0x20 + k / 8, bit k % 8, using integer division. Reads with lbu or lw leave the state unchanged.
This checks whether the left arrow, code 0x50, is held. 0x50 / 8 is 10 and 0x50 % 8 is 0, so the bit is bit 0 of the byte at offset 0x20 + 10:
lbu t0, 0x2a(s0) # keys 0x50 to 0x57
andi t0, t0, 1 # bit 0: the left arrow, 0x50
bnez t0, left # held: move left this frame1
2
3
A game can read held keys once per frame and use events for single presses such as Escape. The two views answer different questions: a key pressed and released between frames is no longer held, but both events remain queued.
The pointer
The Pointer word holds y in bits 30–21, x in bits 20–11, and held buttons in bits 2–0: bit 0 left, bit 1 right and bit 2 middle.
x and y count words of the bitmap display, from 0 at the top left. The word under the pointer is y × columns + x, where columns is the display's width in words. Dragging past an edge keeps the coordinates at the last word. Pointer movement updates this register without queuing an event.
Waiting for input
To wait for input, sleep for a few milliseconds with service 32, then read Status again, as the first program does. Sleeping costs no instructions. Polling continuously uses instructions, fills the Undo history and can reach the instruction limit.
When the queue is full
The normal queue holds 64 events, including any dropped markers. When it is full, new events are lost. Once space becomes available, a later arriving event first adds a dropped marker, kind 7. If only one slot is free, the marker fills it and that arriving event is lost too. Reading events alone does not add a marker.
On receiving a dropped marker, read Keys and Pointer to recover the current state. Held-key and button state still updates when events are lost. Undo can temporarily restore more than 64 events, as explained below.
Typed characters and keys
A press that produces a character feeds both the keyboard registers at 0xffff0000 and the Input controller. Non-character keys, such as arrows and Shift, and key releases feed only the Input controller.
- Use the keyboard registers for text. They provide characters in the user's keyboard layout, including Shift and AltGr combinations, pasted text and Testcase input.
- Use the Input controller for keys. It provides physical key codes. A program using it for text must convert those codes into characters itself.
The two queues are separate. Reading the Input controller leaves typed characters waiting in the keyboard receiver. A later character read, including a read through a service, gets those old characters first. To discard them, read receiver data until the receiver's Ready bit is clear.
Escape types character 27 at the keyboard registers.
When the Input controller hears nothing
- Before the program starts and after it ends. Input is accepted from the program's first instruction until it ends. A click that focuses the Screen before Run is not queued. A key already held when the program starts appears at its next repeat as a key-down event.
- In a Testcase. A Testcase has no keyboard and no mouse: no events, no keys held, and the pointer at 0, 0. A Testcase's input still reaches the keyboard registers as typed lines.
- Under the bitmap display. A display whose base address is
0xffff0000, RARS's "memory map" base, can cover the Input controller's addresses. Its words are then pixels, and the Input controller writes none of them. Move the display, or make it smaller, to use both.
Undo
Undo restores events removed by the instruction being undone, at the front of the queue and in their original order. Running forward can read them again. Restored events are kept even if the queue grows past 64. Status reports at most 127.
Undo does not rewind held keys, held buttons or pointer position. Those registers show current input, so the restored queue may contain a key-down event for a key that is now released.
From C
<sim.h> names the Input controller's registers, the parts of an event and every key:
- Registers:
SIM_INPUT_ID,SIM_INPUT_CONTROL,SIM_INPUT_STATUS,SIM_INPUT_EVENTandSIM_INPUT_POINTERread a register, andSIM_INPUT_KEYSis the 32 bytes of keys held. - Helpers:
sim_input_present()says whether the Input controller is there,sim_input_pending()how many events wait,sim_input_event()takes the oldest event,sim_input_key_down(key)says whether a key is held, andsim_input_pointer()reads the Pointer register. - Parts of a word:
SIM_INPUT_KIND(event),SIM_INPUT_CODE(event)andSIM_INPUT_WHEEL_NOTCHES(event), which gives the wheel's notches as a signed number;SIM_INPUT_X(word)andSIM_INPUT_Y(word)for an event or the pointer, andSIM_INPUT_BUTTONS(pointer). - Kinds:
SIM_INPUT_KEY_DOWN,SIM_INPUT_KEY_UP,SIM_INPUT_KEY_REPEAT,SIM_INPUT_BUTTON_DOWN,SIM_INPUT_BUTTON_UP,SIM_INPUT_WHEELandSIM_INPUT_DROPPED. - Buttons, in two forms:
SIM_INPUT_BUTTON_LEFT,SIM_INPUT_BUTTON_RIGHTandSIM_INPUT_BUTTON_MIDDLE(1, 2 and 3) are a button event's code, whileSIM_INPUT_HELD_LEFT,SIM_INPUT_HELD_RIGHTandSIM_INPUT_HELD_MIDDLE(1, 2 and 4) are the Pointer register's bits. - Keys:
SIM_KEY_and the key's name from the table below, such asSIM_KEY_A,SIM_KEY_ARROW_LEFTandSIM_KEY_SPACE.
See Using C and C++ for compiling. This program moves a dot with the arrow keys, draws where you click, and ends on Escape:
#include <sim.h>
SIM_SCREEN(screen, 64, 64, 1);
int main(void) {
if (!sim_input_present()) {
sim_print_string("This simulator has no Input controller.\n");
return 1;
}
unsigned x = 32, y = 32;
for (;;) {
while (sim_input_pending()) {
unsigned event = sim_input_event();
unsigned kind = SIM_INPUT_KIND(event);
if (kind == SIM_INPUT_KEY_DOWN && SIM_INPUT_CODE(event) == SIM_KEY_ESCAPE)
return 0;
/* a left click paints the word under the pointer */
if (kind == SIM_INPUT_BUTTON_DOWN && SIM_INPUT_CODE(event) == SIM_INPUT_BUTTON_LEFT)
screen[SIM_INPUT_Y(event) * 64 + SIM_INPUT_X(event)] = sim_rgb(255, 255, 0);
}
screen[y * 64 + x] = 0;
if (sim_input_key_down(SIM_KEY_ARROW_LEFT) && x > 0) x--;
if (sim_input_key_down(SIM_KEY_ARROW_RIGHT) && x < 63) x++;
if (sim_input_key_down(SIM_KEY_ARROW_UP) && y > 0) y--;
if (sim_input_key_down(SIM_KEY_ARROW_DOWN) && y < 63) y++;
screen[y * 64 + x] = sim_rgb(0, 200, 255);
sim_sleep(16);
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29On RISC-V 64
The register addresses and layouts are the same on RV32 and RV64: li s0, 0xffff0300 reaches the controller on either target. The first program and the held-key example work on both.
lw sign-extends a word on RV64. Bit 31 is clear in Id, Control, Status, Event and Pointer, so those reads have the same value on both targets. Words in the Keys bitmap can have bit 31 set. Use lbu for a key byte, or mask the bit you need after a word read.
The wheel decoder above uses 32-bit shifts. On RV64, replace its last two instructions with slli t5, t0, 56 followed by srai t5, t5, 56. This moves the wheel code's sign bit, bit 7, into bit 63 before shifting it back. The shifts by 24 shown above are for RV32.
Read Event with lw. An ld spanning Status and Event also removes an event, and its Status half already counts one fewer. In C, unsigned is 32 bits on both targets, so the SIM_INPUT_ macros, including SIM_INPUT_WHEEL_NOTCHES, work on both.
Key codes
Each key is named after the browser's name for it, written in capitals with underscores: ArrowLeft is SIM_KEY_ARROW_LEFT in C. Left and right Shift, Control, Alt and Meta (the Windows or Command key) are different keys. The keypad's keys are their own and do not depend on Num Lock. Keys that a USB keyboard has no code for, such as volume and media keys and Fn, send nothing.
Letters and digits
| Key | Code | In C |
|---|---|---|
KeyA | 0x04 | SIM_KEY_A |
KeyB | 0x05 | SIM_KEY_B |
KeyC | 0x06 | SIM_KEY_C |
KeyD | 0x07 | SIM_KEY_D |
KeyE | 0x08 | SIM_KEY_E |
KeyF | 0x09 | SIM_KEY_F |
KeyG | 0x0A | SIM_KEY_G |
KeyH | 0x0B | SIM_KEY_H |
KeyI | 0x0C | SIM_KEY_I |
KeyJ | 0x0D | SIM_KEY_J |
KeyK | 0x0E | SIM_KEY_K |
KeyL | 0x0F | SIM_KEY_L |
KeyM | 0x10 | SIM_KEY_M |
KeyN | 0x11 | SIM_KEY_N |
KeyO | 0x12 | SIM_KEY_O |
KeyP | 0x13 | SIM_KEY_P |
KeyQ | 0x14 | SIM_KEY_Q |
KeyR | 0x15 | SIM_KEY_R |
KeyS | 0x16 | SIM_KEY_S |
KeyT | 0x17 | SIM_KEY_T |
KeyU | 0x18 | SIM_KEY_U |
KeyV | 0x19 | SIM_KEY_V |
KeyW | 0x1A | SIM_KEY_W |
KeyX | 0x1B | SIM_KEY_X |
KeyY | 0x1C | SIM_KEY_Y |
KeyZ | 0x1D | SIM_KEY_Z |
Digit1 | 0x1E | SIM_KEY_DIGIT_1 |
Digit2 | 0x1F | SIM_KEY_DIGIT_2 |
Digit3 | 0x20 | SIM_KEY_DIGIT_3 |
Digit4 | 0x21 | SIM_KEY_DIGIT_4 |
Digit5 | 0x22 | SIM_KEY_DIGIT_5 |
Digit6 | 0x23 | SIM_KEY_DIGIT_6 |
Digit7 | 0x24 | SIM_KEY_DIGIT_7 |
Digit8 | 0x25 | SIM_KEY_DIGIT_8 |
Digit9 | 0x26 | SIM_KEY_DIGIT_9 |
Digit0 | 0x27 | SIM_KEY_DIGIT_0 |
Typing keys
| Key | Code | In C |
|---|---|---|
Enter | 0x28 | SIM_KEY_ENTER |
Escape | 0x29 | SIM_KEY_ESCAPE |
Backspace | 0x2A | SIM_KEY_BACKSPACE |
Tab | 0x2B | SIM_KEY_TAB |
Space | 0x2C | SIM_KEY_SPACE |
Minus | 0x2D | SIM_KEY_MINUS |
Equal | 0x2E | SIM_KEY_EQUAL |
BracketLeft | 0x2F | SIM_KEY_BRACKET_LEFT |
BracketRight | 0x30 | SIM_KEY_BRACKET_RIGHT |
Backslash | 0x31 | SIM_KEY_BACKSLASH |
Semicolon | 0x33 | SIM_KEY_SEMICOLON |
Quote | 0x34 | SIM_KEY_QUOTE |
Backquote | 0x35 | SIM_KEY_BACKQUOTE |
Comma | 0x36 | SIM_KEY_COMMA |
Period | 0x37 | SIM_KEY_PERIOD |
Slash | 0x38 | SIM_KEY_SLASH |
CapsLock | 0x39 | SIM_KEY_CAPS_LOCK |
Function keys
| Key | Code | In C |
|---|---|---|
F1 | 0x3A | SIM_KEY_F1 |
F2 | 0x3B | SIM_KEY_F2 |
F3 | 0x3C | SIM_KEY_F3 |
F4 | 0x3D | SIM_KEY_F4 |
F5 | 0x3E | SIM_KEY_F5 |
F6 | 0x3F | SIM_KEY_F6 |
F7 | 0x40 | SIM_KEY_F7 |
F8 | 0x41 | SIM_KEY_F8 |
F9 | 0x42 | SIM_KEY_F9 |
F10 | 0x43 | SIM_KEY_F10 |
F11 | 0x44 | SIM_KEY_F11 |
F12 | 0x45 | SIM_KEY_F12 |
F13 | 0x68 | SIM_KEY_F13 |
F14 | 0x69 | SIM_KEY_F14 |
F15 | 0x6A | SIM_KEY_F15 |
F16 | 0x6B | SIM_KEY_F16 |
F17 | 0x6C | SIM_KEY_F17 |
F18 | 0x6D | SIM_KEY_F18 |
F19 | 0x6E | SIM_KEY_F19 |
F20 | 0x6F | SIM_KEY_F20 |
F21 | 0x70 | SIM_KEY_F21 |
F22 | 0x71 | SIM_KEY_F22 |
F23 | 0x72 | SIM_KEY_F23 |
F24 | 0x73 | SIM_KEY_F24 |
Navigation
| Key | Code | In C |
|---|---|---|
PrintScreen | 0x46 | SIM_KEY_PRINT_SCREEN |
ScrollLock | 0x47 | SIM_KEY_SCROLL_LOCK |
Pause | 0x48 | SIM_KEY_PAUSE |
Insert | 0x49 | SIM_KEY_INSERT |
Home | 0x4A | SIM_KEY_HOME |
PageUp | 0x4B | SIM_KEY_PAGE_UP |
Delete | 0x4C | SIM_KEY_DELETE |
End | 0x4D | SIM_KEY_END |
PageDown | 0x4E | SIM_KEY_PAGE_DOWN |
ArrowRight | 0x4F | SIM_KEY_ARROW_RIGHT |
ArrowLeft | 0x50 | SIM_KEY_ARROW_LEFT |
ArrowDown | 0x51 | SIM_KEY_ARROW_DOWN |
ArrowUp | 0x52 | SIM_KEY_ARROW_UP |
ContextMenu | 0x65 | SIM_KEY_CONTEXT_MENU |
Help | 0x75 | SIM_KEY_HELP |
Keypad
| Key | Code | In C |
|---|---|---|
NumLock | 0x53 | SIM_KEY_NUM_LOCK |
NumpadDivide | 0x54 | SIM_KEY_NUMPAD_DIVIDE |
NumpadMultiply | 0x55 | SIM_KEY_NUMPAD_MULTIPLY |
NumpadSubtract | 0x56 | SIM_KEY_NUMPAD_SUBTRACT |
NumpadAdd | 0x57 | SIM_KEY_NUMPAD_ADD |
NumpadEnter | 0x58 | SIM_KEY_NUMPAD_ENTER |
Numpad1 | 0x59 | SIM_KEY_NUMPAD_1 |
Numpad2 | 0x5A | SIM_KEY_NUMPAD_2 |
Numpad3 | 0x5B | SIM_KEY_NUMPAD_3 |
Numpad4 | 0x5C | SIM_KEY_NUMPAD_4 |
Numpad5 | 0x5D | SIM_KEY_NUMPAD_5 |
Numpad6 | 0x5E | SIM_KEY_NUMPAD_6 |
Numpad7 | 0x5F | SIM_KEY_NUMPAD_7 |
Numpad8 | 0x60 | SIM_KEY_NUMPAD_8 |
Numpad9 | 0x61 | SIM_KEY_NUMPAD_9 |
Numpad0 | 0x62 | SIM_KEY_NUMPAD_0 |
NumpadDecimal | 0x63 | SIM_KEY_NUMPAD_DECIMAL |
NumpadEqual | 0x67 | SIM_KEY_NUMPAD_EQUAL |
NumpadComma | 0x85 | SIM_KEY_NUMPAD_COMMA |
NumpadParenLeft | 0xB6 | SIM_KEY_NUMPAD_PAREN_LEFT |
NumpadParenRight | 0xB7 | SIM_KEY_NUMPAD_PAREN_RIGHT |
NumpadBackspace | 0xBB | SIM_KEY_NUMPAD_BACKSPACE |
Modifiers
| Key | Code | In C |
|---|---|---|
ControlLeft | 0xE0 | SIM_KEY_CONTROL_LEFT |
ShiftLeft | 0xE1 | SIM_KEY_SHIFT_LEFT |
AltLeft | 0xE2 | SIM_KEY_ALT_LEFT |
MetaLeft | 0xE3 | SIM_KEY_META_LEFT |
ControlRight | 0xE4 | SIM_KEY_CONTROL_RIGHT |
ShiftRight | 0xE5 | SIM_KEY_SHIFT_RIGHT |
AltRight | 0xE6 | SIM_KEY_ALT_RIGHT |
MetaRight | 0xE7 | SIM_KEY_META_RIGHT |
International
| Key | Code | In C |
|---|---|---|
IntlBackslash | 0x64 | SIM_KEY_INTL_BACKSLASH |
IntlRo | 0x87 | SIM_KEY_INTL_RO |
KanaMode | 0x88 | SIM_KEY_KANA_MODE |
IntlYen | 0x89 | SIM_KEY_INTL_YEN |
Convert | 0x8A | SIM_KEY_CONVERT |
NonConvert | 0x8B | SIM_KEY_NON_CONVERT |
Lang1 | 0x90 | SIM_KEY_LANG_1 |
Lang2 | 0x91 | SIM_KEY_LANG_2 |
Lang3 | 0x92 | SIM_KEY_LANG_3 |
Lang4 | 0x93 | SIM_KEY_LANG_4 |
Lang5 | 0x94 | SIM_KEY_LANG_5 |
On Windows, AltGr arrives as two keys at once: Control Left and Alt Right.
For assembly, these lines give the common keys names, ready to paste at the top of a program:
.eqv KEY_A, 0x04
.eqv KEY_B, 0x05
.eqv KEY_C, 0x06
.eqv KEY_D, 0x07
.eqv KEY_E, 0x08
.eqv KEY_F, 0x09
.eqv KEY_G, 0x0A
.eqv KEY_H, 0x0B
.eqv KEY_I, 0x0C
.eqv KEY_J, 0x0D
.eqv KEY_K, 0x0E
.eqv KEY_L, 0x0F
.eqv KEY_M, 0x10
.eqv KEY_N, 0x11
.eqv KEY_O, 0x12
.eqv KEY_P, 0x13
.eqv KEY_Q, 0x14
.eqv KEY_R, 0x15
.eqv KEY_S, 0x16
.eqv KEY_T, 0x17
.eqv KEY_U, 0x18
.eqv KEY_V, 0x19
.eqv KEY_W, 0x1A
.eqv KEY_X, 0x1B
.eqv KEY_Y, 0x1C
.eqv KEY_Z, 0x1D
.eqv KEY_DIGIT_1, 0x1E
.eqv KEY_DIGIT_2, 0x1F
.eqv KEY_DIGIT_3, 0x20
.eqv KEY_DIGIT_4, 0x21
.eqv KEY_DIGIT_5, 0x22
.eqv KEY_DIGIT_6, 0x23
.eqv KEY_DIGIT_7, 0x24
.eqv KEY_DIGIT_8, 0x25
.eqv KEY_DIGIT_9, 0x26
.eqv KEY_DIGIT_0, 0x27
.eqv KEY_ENTER, 0x28
.eqv KEY_ESCAPE, 0x29
.eqv KEY_BACKSPACE, 0x2A
.eqv KEY_TAB, 0x2B
.eqv KEY_SPACE, 0x2C
.eqv KEY_MINUS, 0x2D
.eqv KEY_EQUAL, 0x2E
.eqv KEY_BRACKET_LEFT, 0x2F
.eqv KEY_BRACKET_RIGHT, 0x30
.eqv KEY_BACKSLASH, 0x31
.eqv KEY_SEMICOLON, 0x33
.eqv KEY_QUOTE, 0x34
.eqv KEY_BACKQUOTE, 0x35
.eqv KEY_COMMA, 0x36
.eqv KEY_PERIOD, 0x37
.eqv KEY_SLASH, 0x38
.eqv KEY_CAPS_LOCK, 0x39
.eqv KEY_F1, 0x3A
.eqv KEY_F2, 0x3B
.eqv KEY_F3, 0x3C
.eqv KEY_F4, 0x3D
.eqv KEY_F5, 0x3E
.eqv KEY_F6, 0x3F
.eqv KEY_F7, 0x40
.eqv KEY_F8, 0x41
.eqv KEY_F9, 0x42
.eqv KEY_F10, 0x43
.eqv KEY_F11, 0x44
.eqv KEY_F12, 0x45
.eqv KEY_PRINT_SCREEN, 0x46
.eqv KEY_SCROLL_LOCK, 0x47
.eqv KEY_PAUSE, 0x48
.eqv KEY_INSERT, 0x49
.eqv KEY_HOME, 0x4A
.eqv KEY_PAGE_UP, 0x4B
.eqv KEY_DELETE, 0x4C
.eqv KEY_END, 0x4D
.eqv KEY_PAGE_DOWN, 0x4E
.eqv KEY_ARROW_RIGHT, 0x4F
.eqv KEY_ARROW_LEFT, 0x50
.eqv KEY_ARROW_DOWN, 0x51
.eqv KEY_ARROW_UP, 0x52
.eqv KEY_NUM_LOCK, 0x53
.eqv KEY_NUMPAD_DIVIDE, 0x54
.eqv KEY_NUMPAD_MULTIPLY, 0x55
.eqv KEY_NUMPAD_SUBTRACT, 0x56
.eqv KEY_NUMPAD_ADD, 0x57
.eqv KEY_NUMPAD_ENTER, 0x58
.eqv KEY_NUMPAD_1, 0x59
.eqv KEY_NUMPAD_2, 0x5A
.eqv KEY_NUMPAD_3, 0x5B
.eqv KEY_NUMPAD_4, 0x5C
.eqv KEY_NUMPAD_5, 0x5D
.eqv KEY_NUMPAD_6, 0x5E
.eqv KEY_NUMPAD_7, 0x5F
.eqv KEY_NUMPAD_8, 0x60
.eqv KEY_NUMPAD_9, 0x61
.eqv KEY_NUMPAD_0, 0x62
.eqv KEY_NUMPAD_DECIMAL, 0x63
.eqv KEY_INTL_BACKSLASH, 0x64
.eqv KEY_CONTEXT_MENU, 0x65
.eqv KEY_NUMPAD_EQUAL, 0x67
.eqv KEY_F13, 0x68
.eqv KEY_F14, 0x69
.eqv KEY_F15, 0x6A
.eqv KEY_F16, 0x6B
.eqv KEY_F17, 0x6C
.eqv KEY_F18, 0x6D
.eqv KEY_F19, 0x6E
.eqv KEY_F20, 0x6F
.eqv KEY_F21, 0x70
.eqv KEY_F22, 0x71
.eqv KEY_F23, 0x72
.eqv KEY_F24, 0x73
.eqv KEY_HELP, 0x75
.eqv KEY_NUMPAD_COMMA, 0x85
.eqv KEY_INTL_RO, 0x87
.eqv KEY_KANA_MODE, 0x88
.eqv KEY_INTL_YEN, 0x89
.eqv KEY_CONVERT, 0x8A
.eqv KEY_NON_CONVERT, 0x8B
.eqv KEY_LANG_1, 0x90
.eqv KEY_LANG_2, 0x91
.eqv KEY_LANG_3, 0x92
.eqv KEY_LANG_4, 0x93
.eqv KEY_LANG_5, 0x94
.eqv KEY_NUMPAD_PAREN_LEFT, 0xB6
.eqv KEY_NUMPAD_PAREN_RIGHT, 0xB7
.eqv KEY_NUMPAD_BACKSPACE, 0xBB
.eqv KEY_CONTROL_LEFT, 0xE0
.eqv KEY_SHIFT_LEFT, 0xE1
.eqv KEY_ALT_LEFT, 0xE2
.eqv KEY_META_LEFT, 0xE3
.eqv KEY_CONTROL_RIGHT, 0xE4
.eqv KEY_SHIFT_RIGHT, 0xE5
.eqv KEY_ALT_RIGHT, 0xE6
.eqv KEY_META_RIGHT, 0xE71
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133