Specification of the Windows 95 KBD-file by Joakim Ek. (Rev 0.02)

This information is what i have figured out by debugging the file and
changing things to see what happends. It might be wrong in every way since
i have not seen any original specification, and a do not guarantee thet any
information here is correct. Though it was at least correct enough for me
to create/modify the cyrillic keyboard-drivers i supplied in this package.

All numbers are decimal, all strings/characters are placed between ""

*** HEADER (28 byte) ***
2 characters "DS"       Indicates that this is a .KBD file
1 byte ???              ?? Diffrent values, might be some country-ID (2/9/29)
1 byte 4                ?? (Theese two could also be a word)
1 word 0                ??
1 word ??               ?? US and RU has 1, BUL and SW has 0
1 word 28               Probably a pointer to start of DATA-block
1 word 0                ?? (Above DWORD ?)
1 word ??               Size of DATA-block (equals filesize-28)
1 word 0                ?? (Above DWORD ?)
13 byte 0               ?? Reserved

*** DATA-block ***
* Fixed part *
word A ??               ? RU,SW=10, US,BUL=2
                  (00001010/00000010 bit3=1=if compose- or AltGr-keys ???)
word B 3                Might be entrys at pointer F
word C ??               Entrys at pointer G (and possibly others)
word D ??               Number of deadkeys (at pointer P)
word E 0                ??
(Pointers are 1 word wide and 0 means start of DATA-block=29th byte in file)
ptr F                   'Unknown table'
ptr G                   2nd byte in 'Type-table'
ptr H                   1st word in 'Pointer-table'
ptr I                   Nth word in 'Pointer-table'
ptr J                   'Keytablesize-table'
ptr K                   Nth byte in 'Type-table' (Thats 'C' bytes after 'G')
ptr L                   'Scancode-table'
ptr M                   'CAPS-table'
word N 48               ?? (Is 48 even for files with 49 keys in xxx-key-tables)
ptr O                   'ALT?-table'
ptr P                   'Deadkey-table' or 0 if no dead/compose-keys
ptr Q                   'Compose-data' or 0 if no dead/compose-keys
ptr R                   ?? always 0
ptr S                   'CAPS-bitmap'

* Placment of theese things may differ depending on pointers *
'CAPS-bitmap' is a 32 byte=256 bit table where each bit corresponds to a
              key and a 1 means that that key is to be shifted when the
              CAPS-lock key is active. In the 'CAPS-table' each scancode
              that is redefined gets a value, witch for the normal latin
              letter-keys is QWERT etc, and for the other is a number usually
              in the range 184-223. This value is then used as the index to
              this bitmap. The bitmap is arranged in 8 DWORDS, and within
              each DWORD the lowest indexnumber is on bit 0. that means that
              byte 1 is for indexvalue 24-31, byte 2 for 16-23, byte 3 for
              8-15, byte 4 for 0-7, byte 5 for 56-63 etc. A normal table
              where only the letters A-Z should be CAPS:ed, and the 'CAPS-
              table' uses the normal "QWERT" layout the value, in bytes, of
              this table is:
              0,0,0,0,0,0,0,0,254,255,255,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
'Unknown-table' is mabe up of 3 words, with bit 15 set, or maby 6 bytes.
              it seems to always be (bytes): 18,128,16,128,17,128
'Type-table' probably defines the types of tabels at the pointers in the
              'Pointer-table' but i am not sure. It always begins with a 0
              wich is not pointed to by anything (but it seems to be a part
              of the table anyway), the following (2nd) byte is pointed to
              by ptr G and there are 'C' entrys. It begins with 1,2,3,4,6
              and sometimes is extended with 5,7 (though i think theese numbers
              might vary). The following byte should be pointed to by ptr K
              and there seems to be 'C' number of bytes here too. Usually
              it is 0,0,1,2,3 optionally followed by 6,7 but i have also seen
              it as 0,0,1,2,4.
'Pointer-table' is a set of pointers whos type might be difined by the 'Type-
              table' or they might be pre-defined depending on order. There
              might be a diffrent number of pointers though, but not the same
              as word 'C', apparantly there are 1 more in each half.
              ptr H points to the start and each entry is a 2-byte pointer
              to the key-definition-tables. Many pointers seems to have the
              same value and the usual definition is like this:
              ptr a,b 'BASE-key-table'
              ptr c,d 'SHIFT-key-table'
              ptr e   '12byte ptr 1'
              ptr f   '12byte ptr 2' (Always to the byte with value 30)
              ptr g   optional, points into 'AltGr-table'
              ptr h   optional, points into 'AltGr-table'
              ptr i,j,k,l 'CAPS-table'
              ptr m   '12byte ptr 3'
              ptr n   '12byte ptr 4' (Always to the byte with value 54)
              ptr o   optional, points into 'AltGr-table'
              ptr p   optional, points into 'AltGr-table'
              See below for more info on '12byte-table' and 'AltGr-table'
'Keytablesize-table' begins with a byte defining the number of keys that is
              redifined, and therefore is the size of the 'BASE-key-table',
              'SHIFT-key-table', 'CAPS-table', "ALT?-table' and 'Scancode-
              table'. The following 3 bytes sometimes are the same but it
              might be 1 less (48,48,48,48 / 49,49,49,49 / 49,48,48,48) and
              i do not know if there is any meaning with that 3 bytes.
              Next comes 2 bytes (or 1 word) that what i have seen is
              either 5,1 (SW,BUL) or 4,2 (US,RU). Sometimes (SW,RU) there
              are 2 more bytes (or 1 word) thats either 11,1 or 14,14. The
              tho additional bytes defines the sizes of the 'AltGr-table'
              tables (There are actually two tables, but they are placed
              after eachother in the files i've seen, and described together
              futher down). The 'C' word probably defines how many entries
              you have in this table too, even though its 1 entry more than C.

* The following, whos internal order varies, seems to come after the above *
'Scancode-table' pointed to by L is a list of the scancodes that is to be
              redefined by this driver. They normally are placed in the same
              order as the keys are placed on the keyboard, begining with 41
              for the ~' key and then 2,3,4 etc for the number keys, ofcourse
              it does not include the scancodes for Backspace, tab etc, just
              the letter-keys and [] etc that is to be redefined. It seems to
              always include A-Z even if they are the same. Usually this table
              is 48 bytes (all normal keys plus the 102nd key on a 102-key
              keyboard found in some countries) but sometimes is 49 when the
              [.] on the num-keypad is included, to be redefined as [,]. The
              1st byte in 'Keytablesize-table' defines the size of this table.
              In the other tables, like 'BASE-key-table' the position in the
              table that corresponds to the position of the pressed scancode
              in the scancode-table is used. (that is, if the scancode-table
              is: 16,17,18 witch corresponds to Q,W,E then the BASE-table
              should include the ASCII for q,w,e on an us-keyboard)
'BASE-key-table' contains the ASCII sent by the keys when not shifted/CAPS:ed
              and is placed in the same order as the corresponding scancodes
              in the 'Scancode-table'. The size of this table is defined by
              the first byte in the 'Keytablesize-table'.
'SHIFT-key-table' contains the ASCII sent by the keys when shifted or CAPS-
              locked (for CAPS-sensitive keys). Size is as 'BASE-key-table'.
'ALT?-table' might be the keys sent when used with ALT, for pull-down menus
              etc. but i am not at all sure on this one. The letters seems to
              be the same as in either the BASE or the SHIFT table, while all
              the other keys, like 123[],.- always seems to be the same as in
              the BASE-table.
'CAPS-table' is, as far as i figured out, just an index to the 'CAPS-bitmap'
              where the CAPS-sensitivness is defined. The A-Z,0-9 seems to
              have the corresponding entrys in this table (also for a BUL or
              RU keyboard that does not have A-Z) but the other keys are
              defined with values somewhere between 184-223. Most files
              seems to map the keys the same, but SW places them a little
              diffrent, even though its the same numbers altogether. It seems
              a littel exagerated to have this table, you could use the 
              scancode directly to index the 'CAPS-bitmap' so i guess its for
              something else too. One guess is that it defines the CTRL-keys
              that are made, but you have to AND the byte in the table with
              1F first. The usual values in this table is like this:
              192,"1234567890",189,187
              "QWERTYUIOP",219,221,220
              "ASDFGHJKL",186,222
              "ZXCVBNM",188,190,191,226 and if 49 keys are defined: 110
'12byte-table' is a strange 12-byte table that always has the same bytes, but
              in diffrent order. There seems to be no rules to the order as
              i can find, like some numbers always comes after another or
              that the n:th nr at one ptr is replaces the same n:th at another
              ptr. Though the 10th byte always seems to be 30, and '12byte-
              pointer 2' always points to this byte. The '12byte-pointer 4'
              always points to the byte with value 54, but that byte can be
              on diffrent positions in the table. Here are some versions:
              SW: *29,31,28,27,28,~186,189,220,221,226,30,54
              US: ~219,220,221,226,*27,28,29,28,54,189,30,31
              BUL:*31,27,29,28,28,~189,221,186,220,226,30,54
              * is pointed to by pointer 1 and ~ by pointer 3.
              It might be that the large numbers is the same as the values
              in the 'CAPS-table' and the lower the CTRL-value for that key,
              but i do not know how they make the connection between them.
'AltGr-table' is optional and pointed to by ptr 9,h,o and p and in the
              swedish file they are arranged like this:
              g-> @${[]}\~|
              o-> 2347890M
              h-> ~
              p-> 
              The characters at g is the ones you get when pressing the
              keys at o while holding AltGr (RightAlt) down, the o-key for
              \~ and | seems to be the value in 'CAPS-table' on the key that
              is to be pressed. The p and h containes one of the keys, that
              are also present in the g,o part, i don't know why.
              The size is defined by the two last bytes in the 'Keytablesize-
              table'.
'Deadkey-table' is optional and lists the ASCII values of the dead keys, that
              is the keys that do not directly produce a character when pressed
              but instead waits for an additional key to be pressed and then
              composes the two if possible. Normally a space after the dead-key
              will enter the dead-key itself, but you have to define even this
              in the composetable. Pointer P points here and its 'D' bytes long.
'Compose-data' first containes a word with the number of compose-combinations
              thats available. After that wollowes the compose-pairs, first the 
              dead-key and then the other key (ASCII) and after all the pairs
              follows a table with the ASCII-character that is produced by the
              compose-pair in the corresponding position. Example:
              0003 "`a`e` `"
              Deadkey and Compose-keytable probably always are used together
              or none of them. SW and RU uses them, not BUL and US.
It might be that each entry in 'Keytablesize' corresponds to one of the 'BASE
key-table', 'SHIFTkey-table' etc, but then there are one byte extra in some of
the files i looked at since they might be 49,48,48,48 in the size-table byt 49
entries in all of the other. The 5,1 or 4,2 is probably the number of entrys
in the '12byte-table' and the 'Type-table' and then 'Pointer-table' is probably
connected in some way, even if there sometimes is a 1 difference between the
'C' and the entries in theese tables. If the 'AltGr' table and the '12byte-
table' (that might be CTRL-table) uses the 'CAPS-table' as pointer, in addition
to the 'CAPS-bitmap', (and they sure seems to) thats probably the reason that
the 'CAPS-table' deos exist, and the scancodes aren't used directly in the
'CAPS-bitmap'. This is probable but not tested and confirmed.
*** EOF ***

Happy hacking from jek (jek@swipnet.se | jocke@ecedata.se) 1997-02-11

