;
; 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

    Source: geocities.com/jadoxa/misc

               ( geocities.com/jadoxa)