User:Johnburger/Demo/Dev/Key
Programmers are often surprised to find out that the IBM keyboard doesn't send ASCII characters to the PC.
Key Codes
Instead, it sends byte-wide scan codes in a particular format:
- The high bit is
0
to indicate that the key has been pressed ("make"), and1
to indicate that it was released ("break"); - The remaining seven bits are simply a number that superficially resembles its location on the keyboard, with
01h
being the top left key and (around)50h
being the bottom right key. As keyboard layouts changed, these starting values became muddied: it was more important that a moved key kept its original scan code than that it held a rigorous positional value!
Shift Keys
This encoding has the effect of not caring about the current values of the <Shift> keys - the same letter or number key produces the same code regardless of whether <Shift> or <Caps Lock> is currently down. Indeed, these keys send their individual scan codes just like any other key on the keyboard. It is up to the system to keep track of what Shift/Ctrl/Alt/Lock keys are currently pressed, and to interpret the subsequent keypresses appropriately.
Extended Keys
The original IBM PC keyboard has 84 keys. Each was given its own scan code, so for example the Left and Right <Shift> keys each had their own value (2Ah
and 36h
respectively). When the 104-key Extended keyboard came out, they had duplicated some keys and added new ones - for example they added an extra <Ctrl> and <Alt> key on the right hand side, and provided dedicated arrow keys rather than overlaying the numeric keypad. Even later, completely new keys were added that had no equivalents, such as the <Windows> and <Menu> keys.
New Keys
These latter keys could be assigned brand new scan codes, since they didn't have to be backward compatible - if an old system didn't understand the scan code it could just ignore it. But the repeated keys caused backward compatibility issues that were resolved in an interesting way - but in a way that makes our job harder.
Multi-code Keys
The duplicated keys couldn't be given new scan codes, since existing software wouldn't understand the codes and that would cripple the new keys' functionality. But giving them the same code meant that new software couldn't distinguish between the original and the duplicate. So instead the designers made the new keys send a double scan code when they were pressed or released. The first byte was a special magic value of 0E0h: it looks like a break code (with the high bit set), but for an unknown key, so old software would ignore it. Then the normal scan code for the old key was sent. For example, the Left <Ctrl> key has a scan code of 1Dh
, so the new Right <Ctrl> key would send the double-byte sequence 0E0h 1Dh
(and 0E0h 9Dh
on release). Old code would only recognize the second byte, while new code could take advantage of the prefix byte to distinguish the duplicate keys.
One-key Keys
Some of the added keys were designed to be one-key replacements for functions that previously required two keystrokes to invoke: for example, on the original IBM to get the screen to dump to a printer required the user to press <Shift><PrScn>, and to Pause or Break the current program required <Ctrl><NumLock>. When the one-key replacements were added, they distinguished themselves with the magic value as well, but now they generated extended sequences by double-coding the <Shift> key too - Prt Sc generated 0E0h 2Ah 0E0h 37h
on press and 0E0h 0B7h 0E0h 0AAh
on release, which corresponded to the original key sequence.
Pause/Break
For some reason though, <Pause/Break> has its own magic value: 0E1h
. This value means that there will be two extended scan codes sent - 0E1h 1Dh 45h
and 0E1h 09Dh 0C5h
for make and break respectively. This magic value also seems to indicate that the codes won't be auto-repeated, unlike every other key on the keyboard.
Definitions
The following definitions are for the keyboard controller, but they also give scan codes for many of the special keys - not all of which are used by this Demonstrator. The system does display all keypresses though, so it should be easy to add new definitions for values as required.
Demo/Dev/Key.inc
;
; Dev/Key.inc
;
; These are the definitions for the Keyboard
Dev.Key.Data EQU 060h
Dev.Key.Ctrl EQU 064h
Dev.Key.Make EQU 000h ; "Make" codes have high bit off
Dev.Key.Break EQU 080h ; "Break" codes have high bit on
Dev.Key.Ext1 EQU 0E0h ; This is the Extended Key prefix
Dev.Key.Ext2 EQU 0E1h ; This one means TWO following
; Scan codes for various keys
Dev.Key.Esc EQU 01h
Dev.Key.Enter EQU 1Ch
Dev.Key.Space EQU 39h
Dev.Key.Pause EQU 45h
Dev.Key.Home EQU 47h
Dev.Key.Up EQU 48h
Dev.Key.PgUp EQU 49h
Dev.Key.Left EQU 4Bh
Dev.Key.Right EQU 4Dh
Dev.Key.End EQU 4Fh
Dev.Key.Down EQU 50h
Dev.Key.PgDn EQU 51h
Dev.Key.Ins EQU 52h
Dev.Key.Del EQU 53h
Dev.Key.F1 EQU 3Bh
Dev.Key.F2 EQU 3Ch
Dev.Key.F3 EQU 3Dh
Dev.Key.F4 EQU 3Eh
Dev.Key.F5 EQU 3Fh
Dev.Key.F6 EQU 40h
Dev.Key.F7 EQU 41h
Dev.Key.F8 EQU 42h
Dev.Key.F9 EQU 43h
Dev.Key.F10 EQU 44h
Dev.Key.F11 EQU 57h
Dev.Key.F12 EQU 58h
Dev.Key.Window EQU 5Bh
Dev.Key.Menu EQU 5Dh