[comp.sys.ibm.pc] Quickey.com - increase keyboard auto-repeat rate

vgreenberg@watnot.UUCP (03/12/87)

Following is the binary and source for Quickey. This is a very handy 
little utility (from PC Magazine V5N5) that overcomes the sluggishness 
of the IBM PC keyboard. The program increases the auto-repeat rate to 
about 18 characters / second, by patching itself into the keyboard and 
timer interrupts, and stuffing the last key pressed into the input 
buffer with every clock tick (until the key is released). 

The program can be run more than once, each time increasing the auto-
repeat rate (each copy contributes a character with every clock tick).
I fixed a small bug in the original listing -- it was not working 
correctly with Alt numeric-keypad entries. 

Quickey also provides a way to flush the input buffer with Alt-Shift. Enjoy!

begin 644 quickey.com
MZ<D                 !P$>4[M  ([;+L8&#0$ BQX< )PN_QX' 3L>' !U
M%2['!@L!___V!A< "G0XB1X: .LRD(L?"O]T)"X['@L!+HD>"P$NBAX/ 74%
M+HH>$ $NB!X. 2[&!@T! >L(D"['!@L!__];'\\N@#X- 0%U2"[^#@X!=4$>
M5U-0NT  CMN+'AP B_N#PP*#^SYU [L> #L>&@!U"2[&!@T! .L5D/HNH0L!
MB06)'AP ^RZ@$ $NH@X!6%M?'R[_+@,!,\".P":A(  FBQXB ":+#B0 )HL6
M)@"C P&)'@4!B0X' 8D6"0'ZC09W 2:C(  FC XB (T&$0$FHR0 )HP.)@#[
&C1;, <TG
 
end
--- cut here ---
; Quickey.asm: speed up the IBM PC keyboard auto-repeat 
; This program was obtained from a PC Magazine listing (V5N5)
; Bug fixed: now responds correctly to ALT numeric-keypad entries
;
; To create quickey.com:
;    masm quickey;
;    link quickey;
;    exe2bin quickey quickey.com
;    del quickey.exe

BIOS_SEG segment at 40h
BIOS_SEG ends
CSEG segment
		assume	cs:CSEG
		org	100h
begin:		jmp	initialize
rom_int8	dw	?,?			; save original timer vector
rom_int9	dw	?,?			; and keyboard vector
dup_char	dw	?			; char to be repeated next
dup_switch	db	0			; 1 if char to be repeated
dup_count	db	0			; tics left before repeat
dup_delay1	db	7			; tics before first repeat
dup_delay2	db	1			; tics between repeats
ALT_SHIFT	equ	0Ah			; KBFLAGS mask
BIOS_KBFLAGS	equ	17h
BIOS_HEAD	equ	1Ah
BIOS_TAIL	equ	1Ch
BIOS_END	equ	3Eh
BIOS_START	equ	1Eh

;keystroke interrupt
int9:
		push	ds
		push	bx

		mov	bx,BIOS_SEG
		mov	ds,bx
		assume	DS:BIOS_SEG
		mov	dup_switch,0		; turn off auto key repeat
		mov	bx,ds:[BIOS_TAIL]	; get current tail

		pushf
		call	dword ptr rom_int9	; call bios
		cmp	bx,ds:[BIOS_TAIL]	; see if tail moved
		jne	was_new_key		; yes
		mov	dup_char,-1		; match any key next time
		test	byte ptr ds:[BIOS_KBFLAGS],ALT_SHIFT
		jz	key_return		; no.

		mov	ds:[BIOS_HEAD],bx	; empty kb buffer
		jmp	key_return
was_new_key:
		mov	bx,[bx]			; get char
		or	bh,bh			; if scan code == 0: ALT-keypad
		jz	false_key

		cmp	bx,dup_char		; see if same as before
		mov	dup_char,bx		; - and store
		mov	bl,dup_delay1		; if different key - start slow
		jne	switch_on
		mov	bl,dup_delay2		; if not different - autorepeat
switch_on:
		mov	dup_count,bl		; set repeat rate
		mov	dup_switch,1		; turn tick ctr back on
		jmp	key_return
false_key:
		mov	dup_char,-1		; match any key next time
key_return:
		pop	bx
		pop	ds
		iret

;timer interrupt
int8:
		cmp	dup_switch,1		; see if should repeat
		jne	move_on
		dec	dup_count
		jnz	move_on
		push	ds
		push	di
		push	bx
		push	ax
		mov	bx,BIOS_SEG
		mov	ds,bx
		mov	bx,ds:[bios_tail]
		mov	di,bx
		add	bx,2			; move ptr to next word
		cmp	bx,bios_end
		jne	full_check
		mov	bx,bios_start		; wrap around
full_check:
		cmp	bx,ds:[bios_head]
		jne	have_room
		mov	dup_switch,0		; no more room
		jmp	reg_restore
have_room:
		cli
		mov	ax,dup_char
		mov	[di],ax
		mov	ds:[bios_tail],bx	; stuff dup_char into kb buffer
		sti

		mov	al,dup_delay2
		mov	dup_count,al		; set dup_count for high rate
reg_restore:
		pop	ax
		pop	bx
		pop	di
		pop	ds
move_on:
		jmp	dword ptr rom_int8	; call timer interrupt

initialize:
		assume	ds:CSEG
		xor	ax,ax
		mov	es,ax
		mov	ax,es:[8*4]		; timer code offset
		mov	bx,es:[8*4+2]		; timer code segment
		mov	cx,es:[9*4]		; keyboard code offset
		mov	dx,es:[9*4+2]		; keyboard code segment
		mov	rom_int8,ax
		mov	rom_int8[2],bx
		mov	rom_int9,cx
		mov	rom_int9[2],dx

		cli
		lea	ax,int8
		mov	es:[8*4],ax
		mov	es:[8*4+2],cs
		lea	ax,int9
		mov	es:[9*4],ax
		mov	es:[9*4+2],cs
		sti

		lea	dx,initialize
		int	27h
CSEG ends
end begin

------
Victor Greenberg
{allegra,decvax,ihnp4,tektronix,utai}!watmath!watnot!vgreenberg