Category : Utilities for DOS and Windows Machines
Archive   : KWIKKEYS.ZIP
Filename : KWIKKEY.ASM

Output of file : KWIKKEY.ASM contained in archive : KWIKKEYS.ZIP
; KWIKKEY.ASM Version 1.4 5-28-86
; Copyright (c) 1985 by Dan Rollins
; This program speeds up the repeat action of the IBM PC and XT
; keyboard. After installation, a keystroke begins repeating about
; 1/4 second after the initial keystroke and the repeats occur at
; about twice the normal speed. These delay and rate parameters may
; be modified. The program uses the 55ms timer interrupt to augment
; the speed of the keyboard. The basic idea is to have the timer
; interrupt check to see if the key has been released. If not, then
; it stuffs a keystroke into the BIOS keyboard buffer. Notes: This
; program must be used with DOS 2.x or later. It is a COM format
; program, so it must be processed by EXE2BIN.
;=== program equates ===

REPT_DELAY equ 5 ;number of 55ms intervals to skip before
; the first repeat. 5 = 275ms = about
; 1/4 second. Use at least 2 to avoid
; "key bounce"

REPT_RATE equ 1 ;Select from: 0 = 29 repeats per second
; 1 = 20 repeats per second
; 2 = 16 repeats per second
; 3 = 13 repeats per second
; 4 or more = standard repeat rate

BIOS_DATA_SEG equ 40h ;These addresses are listed
BUF_START equ 1eh ; in the Technical Reference manual
BUF_END equ 3eh
ALT_NUM_BUF equ 19h

FALSE equ 0
TRUE equ 1


com_seg segment
assume cs:com_seg, ds:com_seg
org 100h ;must set up for COM file
kwikkey proc far
jmp set_up ;get past the data and install the
;interrupt handlers

;============= program data area ========
delay db REPT_DELAY ;max ticks BEFORE STARTING to repeat
rate db REPT_RATE ;maximum ticks BETWEEN repeats

inst_flag dw 1234h ;KWIKKEY signature when already installed

rep_ok db FALSE ;flag turns off repeat while processing
last_key dw 0 ;stores most recent keyboard scan code

init_delay db REPT_DELAY ;remaining ticks before
;starting to repeat
rate_delay db REPT_RATE ;remaining tick between repeats

bios_kbd_int label dword ;DWORD so it can be used in a FAR call
bki_offset dw 0 ; This is set to the addr of BIOS KB_INT
bki_segment dw 0 ; at the time of installation of KWIKKEY

user_timer_int label dword ;used to preserve "forward chain" of user
uti_offset dw 0 ;timer interrupt handlers. Set in SET_UP
uti_segment dw 0 ;procedure, this addr will normally point
;to an IRET.

; This procedure intercepts keystrokes and sends control to normal
; BIOS KB_INT. Its primary function is to set up for the repeat action
; that occurs in the TIMER_INT. It checks each key that comes in, and
; resets a delay counter if it is a new keystroke.

kbd_int proc far
mov cs:rep_ok,FALSE ;turn off repeats while
push ax ;save the registers
push si
push ds
mov ax,BIOS_DATA_SEG ; set up to address
mov ds,ax ; BIOS data area
mov si,ds:[BUF_TAIL_ADDR] ;get addr of current
;buffer tail

;check special case: don't repeat ALT-numpad keystrokes

cmp byte ptr ds:[ALT_NUM_BUF],0 ;is one in progress?
je ki_10 ; no, continue
pushf ; yes, process
call cs:bios_kbd_int ; the keystroke
jmp ki_exit ; exit with repeats off
pushf ;simulate a normal interrupt
call cs:bios_kbd_int ; and process the keystroke

cmp si,ds:[BUF_TAIL_ADDR] ;did the tail move?
jne ki_20 ; no, either a shift-key
; or a release
mov cs:last_key,0 ; insure no spurious repeats
jmp ki_exit ; exit with repeats turned off
ki_20: ; yes, process the keystroke
mov ax,[si] ; get new scan code
cmp ax,cs:[last_key] ; same as last time?
mov cs:last_key,ax ; (save the key for next time)
je ki_30 ; yes, hardware repeat
; just reset the rate
; no, reset both timer delays
mov al,cs:delay ; get maximum tick count
mov cs:init_delay,al ; set delay before repeat
mov al,cs:rate ; get maximum tick value
mov cs:rate_delay,al ; set delay between repeats
mov cs:rep_ok,TRUE ; OK to continue repeating

pop ds
pop si
pop ax
iret ;also restores Flags of interruptee
kbd_int endp

; This procedure is executed 18.2 times per second
; It checks to see if a repeat is needed. If so, it stuffs the scan
; code into the keyboard buffer, ready for the next keystroke request
timer_int proc far
cmp cs:[rep_ok],TRUE ;are repeats blocked?
jne ti_exit ; yes, resume without repeat

cmp cs:init_delay,0 ;finished delaying before
;first repeat?
je ti_10 ; yes, check rate delay
dec cs:init_delay ; no, decrement timer
jmp ti_exit ; and resume without repeat

cmp cs:rate_delay,0 ;finished delaying between repeats?
je ti_20 ; yes, do the repeat
dec cs:rate_delay ; no, decrement rate timer
jmp ti_exit ; and resume without repeat

;------- repeat the previous keystroke -----------

push ax ;save all registers used
push si
push ds

mov ax,BIOS_DATA_SEG ;prepare to address BIOS data area
mov ds,ax
mov ax,ds:[BUF_TAIL_ADDR] ;get current position
;in kbd buffer
mov si,ax ;we'll need this address later
add ax,2 ;point to next position in buffer
cmp ax,BUF_END ;past end of buffer?
jne ti_30 ; no, continue
mov ax,BUF_START ; yes, next position is the
cmp ax,ds:[BUF_HEAD_ADDR] ;if tail=head, buffer is full
je ti_40 ;full, continue without repeat
cli ;not full, dont allow break-in
mov ds:[BUF_TAIL_ADDR],ax ; update buffer position
mov ax,cs:[last_key] ; fetch key to repeat
mov [si],ax ; store key in buffer
sti ; interrupts ok now
mov al,cs:rate ;get the max rate delay value
mov cs:rate_delay,al ;don't repeat for a while
pop ds ;restore registers
pop si ; and exit
pop ax
jmp cs:[user_timer_int] ;continue with previously
;installed interrupt handler
timer_int endp

LAST_BYTE equ offset $+1 ;this is the address passed to INT 27H
; Notice that the code of the SET_UP
; procedure does not need to be preserved

; This routine is executed only once -- when the program is installed.
; It resets the vectors of the KBD_INT and the USER_TIMER_INT,
; pointing them to code within this program. Note that the original
; vectors are saved and executed so all previously-installed interrupt
; handlers remain operational.

logo_msg db 201, 25 dup(205),187,0dh,0ah
db 186,' KWIKKEY Ver. 1.4 ',186,0dh,0ah
db 186,' (c) 1986 by Dan Rollins ',186,0dh,0ah
db 200, 25 dup(205),188,0dh,0ah,'$'

err_msg db 'Error: ',07,'KWIKKEY already installed',0dh,0ah,'$'

set_up proc near
;------ first, make sure KWIKKEY hasn't been installed ---
mov al,9
mov ah,35h ;DOS GET_VECTOR service
int 21h ; for interrupt 9

cmp es:inst_flag,1234h ;has KWIKKEY been installed?
jne su_10 ; no, continue
mov dx,offset err_msg ; yes, display
mov ah,9 ; error
int 21h ; message
int 20h ;and exit to DOS
mov al,9 ;get original vector of keyboard int 9
mov ah,35h ;DOS GET_VECTOR service
int 21h
mov bki_segment,es ;save original address
mov bki_offset,bx ; so we can resume normally
; after intercept
mov dx,offset kbd_int
mov al,9 ;set vector for INT 9
mov ah,25h ;DOS SET_VECTOR service
int 21h

mov al,1ch ;the user timer interrupt
mov ah,35h ;DOS GET_VECTOR service
int 21h
mov uti_segment,es ;save old address
mov uti_offset,bx ; so we don't hog the timer interrupt

mov dx,offset timer_int
mov al,1ch ;set vector to point to new TIMER_INT
mov ah,25h ;DOS SET_VECTOR service
int 21h

;------ display logo to indicate installation complete
mov dx,offset logo_msg
mov ah,9
int 21h

mov cs:rep_ok,TRUE ; it's OK to start repeat action

;------ exit to DOS, leaving the interrupt handlers resident
mov dx,LAST_BYTE
int 27h
set_up endp
kwikkey endp
com_seg ends
end kwikkey ;must specify for COM-format file

  3 Responses to “Category : Utilities for DOS and Windows Machines
Archive   : KWIKKEYS.ZIP
Filename : KWIKKEY.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: