; ; keyboard.asm - Test different key combinations. ; ; Jason Hood, 2 to 4 December, 2000. ; Public Domain. ; ; Currently it does not handle Pause correctly - it generates E1 1D 45 on make ; and E1 9D C5 immediately after. I simply ignore the E1 1D and so the Numlock ; key is flashed. ; ; 031013, v1.00: ; display scancodes using a hexadecimal matrix. ; .model tiny .code org 100h LEFTSHIFT equ 2ah RIGHTSHIFT equ 36h ESCAPE equ 01h RELEASED equ esc_on equ 01b shift_on equ 10b esc_off equ shift_off equ exit_state equ esc_on or shift_on COL_UNPRESSED equ 112 ; Black on grey COL_PRESSED equ 123 ; Bright cyan on grey COL_PREFIX equ 122 ; Bright green on grey KEY_DISP equ 0602h ; Adjustment for keyboard position HEX_DISP equ 1516h ; Adjustment for hex matrix position begin: jmp start db 8, 8, 8 helpmsg db 'Keyboard by Jason Hood .',13,10 db 'Version 1.00 (14 October, 2003). Public Domain.',13,10 db 'http://misc.adoxa.cjb.net/',13,10 db 13,10 db 'Display a keyboard layout and highlight each key as it',13,10 db 'is pressed and released. It is particularly useful for',13,10 db 'determining which keys can be pressed together without',13,10 db 'interfering with each other (for games).',13,10 db 13,10 db 'It also shows the key''s hexadecimal scancode. Prefixed',13,10 db 'keys show up in green.',13,10 db 26, 8, ' $' help: mov dx, offset helpmsg mov ah, 9 int 21h ret start: cmp word ptr [ds:81h],'?/' je help cmp word ptr [ds:82h],'?/' ; Assume a space before it je help mov ax,3 ; 80 x 25 colour int 10h mov ah,1 ; Hide the cursor mov cx,2000h int 10h mov ah,9 ; Clear the screen mov al,' ' mov bh,0 mov bl,COL_UNPRESSED mov cx,80*25 int 10h mov bx,offset title_msg call print mov bx,offset exit_msg call print mov bx,offset hex_msg push bx call print pop bx mov byte ptr [bx],42 ; Adjust for second half add byte ptr [bx+38],4 add byte ptr [bx+41],4 add byte ptr [bx+44],4 add byte ptr [bx+47],4 call print call key_lens call display_keys mov ax,3515h ; Get the original Int15 int 21h mov word ptr int15,bx ; Preserve it mov word ptr int15+2,es mov dx,offset scancode ; Point to my new one mov ax,2515h ; Set it int 21h continue: ; Wait for termination cmp done,exit_state jne continue lds dx,int15 ; Point to the original Int15 mov ax,2515h ; Restore it int 21h mov ax,3 ; Clear screen and restore cursor int 10h ret ; Finished ; Print a string using BIOS. ; BX - pointer to x, y, length and string. print proc mov dx,[bx] mov ch,0 mov cl,[bx+2] lea bp,[bx+3] mov bx,COL_UNPRESSED mov ax,1300h int 10h ret print endp title_msg db 36, 1, 8, 'KEYBOARD' exit_msg db 28, 3, 24, 'Press Shift+Esc to exit.' hex_msg db 21, 20, 45, ' 0123456789abcdef', 17 dup (8) db 10, '0', 8 db 10, '1', 8 db 10, '2', 8 db 10, '3' int15 dd 0 ; Original Int15 vector done db 0 ; Termination flag prefix db 0 ; For the E0 and E1 prefixed codes old_code dw 0 ; Prevent repeat scancode proc far pushf sti ; Okay to interrupt cmp ah,4fh ; Intercept function? je okay popf jmp cs:[int15] okay: push ax dx ds push cs pop ds xor ah,ah xchg prefix,ah or ah,ah ; Have we seen a prefix? jne prefixed_code ; Yes cmp al,0e0h ; Test for prefix je prefix_found cmp al,0e1h ; Second prefix (Pause only) jne no_prefix prefix_found: mov prefix,al ; Remember the prefix jmp short exit ; and get out no_prefix: prefixed_code: cmp ax,old_code ; Same as the previous key? je exit ; Yep, get out mov old_code,ax test_escape: ; Test for certain keys cmp ax,ESCAPE jne test_shift or done,esc_on jmp short print_key test_shift: cmp ax,LEFTSHIFT je shift_pressed cmp ax,RIGHTSHIFT jne test_esc_release shift_pressed: or done,shift_on jmp short print_key test_esc_release: cmp ax,ESCAPE RELEASED jne test_shift_release and done,esc_off jmp short print_key test_shift_release: cmp ax,LEFTSHIFT RELEASED je shift_released cmp ax,RIGHTSHIFT RELEASED jne print_key shift_released: and done,shift_off print_key: call display_key exit: pop ds dx ax popf clc ; Ignore the key ret 2 ; and the interrupted flags scancode endp ; Display a key ; In: AX - key code (AH = prefix, AL = scan code) display_key proc push ax bx cx dx bp si push es push cs pop es mov si,offset normal_keys or ah,ah jz is_normal cmp ah,0e0h jne display_exit mov si,offset prefix_keys is_normal: mov bx,COL_PRESSED ; BH = 0 for page cmp al,128 jb is_pressed mov bl,COL_UNPRESSED sub al,128 is_pressed: push ax mov dh,size _key mul dh add si,ax mov ch,0 cmp byte ptr [si],ch ; Unknown key - ignore it je display_hex mov ax,1300h mov dx,word ptr [si.x] add dx,KEY_DISP mov bp,si mov cl,es:[bp+nlen] int 10h display_hex: pop ax or ah,ah ; Display prefixed keys jz d_no_p ; using a different colour cmp bl,COL_UNPRESSED je d_no_p mov bl,COL_PREFIX d_no_p: mov dh,al ; Split AL into DH and DL mov cl,4 shr dh,cl mov dl,al and dl,0fh cmp dh,4 ; If it's the second half jb d_h add dl,21 ; move across to the right and dh,3 d_h: add dx,HEX_DISP mov ax,1300h mov bp,offset asterisk mov cl,1 int 10h display_exit: pop es pop si bp dx cx bx ax ret display_key endp ; Calculate the length of the key names. key_lens proc mov cx,256 ; 128 normal, 128 prefix mov bx,offset normal_keys key_len: mov si,-1 len: inc si cmp byte ptr [bx+si],0 jne len mov ax,si mov [bx+nlen],al add bx,size _key loop key_len ret key_lens endp ; Display all keys. display_keys proc mov ax,128 ; Unpressed keys call disp mov ax,0e080h ; Unpressed prefixed keys disp: mov cx,128 another_key: call display_key inc ax loop another_key ret display_keys endp _key struc n db 7 dup (0) x db 0 y db 0 _key ends nlen equ 6 ; Don't want another field normal_keys label _key _key<> ; 0 _key< "Esc", 0, 0 > ; 1 _key< "1", 4, 3 > ; 2 _key< "2", 7, 3 > ; 3 _key< "3", 10, 3 > ; 4 _key< "4", 13, 3 > ; 5 _key< "5", 16, 3 > ; 6 _key< "6", 19, 3 > ; 7 _key< "7", 22, 3 > ; 8 _key< "8", 25, 3 > ; 9 _key< "9", 28, 3 > ; 10 _key< "0", 31, 3 > ; 11 _key< "-", 34, 3 > ; 12 _key< "=", 37, 3 > ; 13 _key< 27, 43, 3 > ; 14 _key< "Tab", 0, 5 > ; 15 _key< "Q", 5, 5 > ; 16 _key< "W", 8, 5 > ; 17 _key< "E", 11, 5 > ; 18 _key< "R", 14, 5 > ; 19 _key< "T", 17, 5 > ; 20 _key< "Y", 20, 5 > ; 21 _key< "U", 23, 5 > ; 22 _key< "I", 26, 5 > ; 23 _key< "O", 29, 5 > ; 24 _key< "P", 32, 5 > ; 25 _key< "[", 35, 5 > ; 26 _key< "]", 38, 5 > ; 27 db 17, "ÄÙ" org $ - 3 _key< ?, 41, 7 > ; 28 _key< "Ctrl", 0, 11 > ; 29 _key< "A", 6, 7 > ; 30 _key< "S", 9, 7 > ; 31 _key< "D", 12, 7 > ; 32 _key< "F", 15, 7 > ; 33 _key< "G", 18, 7 > ; 34 _key< "H", 21, 7 > ; 35 _key< "J", 24, 7 > ; 36 _key< "K", 27, 7 > ; 37 _key< "L", 30, 7 > ; 38 _key< ";", 33, 7 > ; 39 _key< "'", 36, 7 > ; 40 _key< "`", 1, 3 > ; 41 _key< "Shift", 0, 9 > ; 42 _key< "\", 40, 3 > ; 43 _key< "Z", 7, 9 > ; 44 _key< "X", 10, 9 > ; 45 _key< "C", 13, 9 > ; 46 _key< "V", 16, 9 > ; 47 _key< "B", 19, 9 > ; 48 _key< "N", 22, 9 > ; 49 _key< "M", 25, 9 > ; 50 _key< ",", 28, 9 > ; 51 _key< ".", 31, 9 > ; 52 _key< "/", 34, 9 > ; 53 _key< "Shift", 39, 9 > ; 54 asterisk label byte ; For the matrix _key< "*", 72, 3 > ; 55 _key< "Alt", 11, 11 > ; 56 _key< "Space", 17, 11 > ; 57 _key< "Caps", 0, 7 > ; 58 _key< "F1", 5, 0 > ; 59 _key< "F2", 8, 0 > ; 60 _key< "F3", 11, 0 > ; 61 _key< "F4", 14, 0 > ; 62 _key< "F5", 18, 0 > ; 63 _key< "F6", 21, 0 > ; 64 _key< "F7", 24, 0 > ; 65 _key< "F8", 27, 0 > ; 66 _key< "F9", 31, 0 > ; 67 _key< "F10", 34, 0 > ; 68 _key< "Num", 64, 3 > ; 69 _key< "Scroll",53, 0 > ; 70 _key< "7", 66, 5 > ; 71 _key< "8", 69, 5 > ; 72 _key< "9", 72, 5 > ; 73 _key< "-", 75, 3 > ; 74 _key< "4", 66, 7 > ; 75 _key< "5", 69, 7 > ; 76 _key< "6", 72, 7 > ; 77 _key< "+", 75, 5 > ; 78 _key< "1", 66, 9 > ; 79 _key< "2", 69, 9 > ; 80 _key< "3", 72, 9 > ; 81 _key< "0", 66, 11 > ; 82 _key< ".", 72, 11 > ; 83 _key< "PrSc", 48, 0 > ; 84 (Actually SysRq - Alt+PrSc) _key<> ; 85 _key<> ; 86 _key< "F11", 38, 0 > ; 87 _key< "F12", 42, 0 > ; 88 _key<> ; 89 _key<> ; 90 _key<> ; 91 _key<> ; 92 _key<> ; 93 _key<> ; 94 _key<> ; 95 _key<> ; 96 _key<> ; 97 _key<> ; 98 _key<> ; 99 _key<> ; 100 _key<> ; 101 _key<> ; 102 _key<> ; 103 _key<> ; 104 _key<> ; 105 _key<> ; 106 _key<> ; 107 _key<> ; 108 _key<> ; 109 _key<> ; 110 _key<> ; 111 _key<> ; 112 _key<> ; 113 _key<> ; 114 _key<> ; 115 _key<> ; 116 _key<> ; 117 _key<> ; 118 _key<> ; 119 _key<> ; 120 _key<> ; 121 _key<> ; 122 _key<> ; 123 _key<> ; 124 _key<> ; 125 _key<> ; 126 _key<> ; 127 prefix_keys label _key _key<> ; 0 _key<> ; 1 _key<> ; 2 _key<> ; 3 _key<> ; 4 _key<> ; 5 _key<> ; 6 _key<> ; 7 _key<> ; 8 _key<> ; 9 _key<> ; 10 _key<> ; 11 _key<> ; 12 _key<> ; 13 _key<> ; 14 _key<> ; 15 _key<> ; 16 _key<> ; 17 _key<> ; 18 _key<> ; 19 _key<> ; 20 _key<> ; 21 _key<> ; 22 _key<> ; 23 _key<> ; 24 _key<> ; 25 _key<> ; 26 _key<> ; 27 _key< "Ù", 75, 11 > ; 28 _key< "Ctrl", 40, 11 > ; 29 _key<> ; 30 _key<> ; 31 _key<> ; 32 _key<> ; 33 _key<> ; 34 _key<> ; 35 _key<> ; 36 _key<> ; 37 _key<> ; 38 _key<> ; 39 _key<> ; 40 _key<> ; 41 _key<> ; 42 _key<> ; 43 _key<> ; 44 _key<> ; 45 _key<> ; 46 _key<> ; 47 _key<> ; 48 _key<> ; 49 _key<> ; 50 _key<> ; 51 _key<> ; 52 _key< "/", 69, 3 > ; 53 _key<> ; 54 _key< "PrSc", 48, 0 > ; 55 _key< "Alt", 25, 11 > ; 56 _key<> ; 57 _key<> ; 58 _key<> ; 59 _key<> ; 60 _key<> ; 61 _key<> ; 62 _key<> ; 63 _key<> ; 64 _key<> ; 65 _key<> ; 66 _key<> ; 67 _key<> ; 68 _key<> ; 69 _key< "Pause", 60, 0 > ; 70 _key< "Home", 52, 3 > ; 71 _key< 24, 54, 9 > ; 72 _key< "PgUp", 57, 3 > ; 73 _key<> ; 74 db 27, "Ä" org $ - 2 _key< ?, 50, 11 > ; 75 _key<> ; 76 db "Ä", 26 org $ - 2 _key< ?, 57, 11 > ; 77 _key<> ; 78 _key< "End", 52, 5 > ; 79 _key< 25, 54, 11 > ; 80 _key< "PgDn", 57, 5 > ; 81 _key< "Ins", 48, 3 > ; 82 _key< "Del", 48, 5 > ; 83 _key<> ; 84 _key<> ; 85 _key<> ; 86 _key<> ; 87 _key<> ; 88 _key<> ; 89 _key<> ; 90 _key< "Win", 6, 11 > ; 91 _key< "Win", 30, 11 > ; 92 _key< "Mnu", 35, 11 > ; 93 _key< "Slp", 48, 7 > ; 94 _key< "Sus", 52, 7 > ; 95 _key<> ; 96 _key<> ; 97 _key<> ; 98 _key< "Wake", 57, 7 > ; 99 _key<> ; 100 _key<> ; 101 _key<> ; 102 _key<> ; 103 _key<> ; 104 _key<> ; 105 _key<> ; 106 _key<> ; 107 _key<> ; 108 _key<> ; 109 _key<> ; 110 _key<> ; 111 _key<> ; 112 _key<> ; 113 _key<> ; 114 _key<> ; 115 _key<> ; 116 _key<> ; 117 _key<> ; 118 _key<> ; 119 _key<> ; 120 _key<> ; 121 _key<> ; 122 _key<> ; 123 _key<> ; 124 _key<> ; 125 _key<> ; 126 _key<> ; 127 end begin