home *** CD-ROM | disk | FTP | other *** search
- title KBUF -- extend keyboard buffer
-
- comment #
-
- KBUF version 1.1 Copyright (C) 1988 Mark Adler
- All rights reserved.
-
- Version history -
-
- 1.0 26 May 1988 First public version
- 1.1 18 Nov 1988 Added queue stuff call (AH=0FFh)
-
- kbuf.com -
-
- kbuf maintains a 127 entry (vs. 15 entry) typeahead buffer. Also the
- original 15 character buffer is retained so a maximum of 142 characters
- are buffered.
-
- The following assumptions are made about the behavior of the keyboard
- scan and support interrupts:
-
- 1. The shift status is a byte stored at location 0:417h.
-
- 2. The support routine is not re-entrant.
-
- kbuf also adds a new function to interrupt 16h---if AH is 0FFh, then
- the scan code in DX is put into the queue, behind what is already
- there (i.e., as if it were just typed). This is different from
- stacking, which puts the keystroke at the front of the queue. On
- return, AL=0 indicates success, AL=1 indicates failure (no room in
- queue).
-
- #
-
-
-
- ;
- ; Interrupt vector segment definitions.
- ;
-
- ints segment at 0
- org 4*8h ;Timer interrupt.
- int8 label word
- org 4*9h ;Scan interrupt.
- int9 label word
- org 4*16h ;Keyboard BIOS interrupt.
- int16 label word
- org 417h
- KB_FLAG db ? ;Keyboard shift status.
- ints ends
-
-
-
- ;
- ; Program segment.
- ;
-
- kbuf segment
- assume CS:kbuf,DS:kbuf,ES:kbuf,SS:kbuf
-
-
-
- ;
- ; Put data as low as DOS will allow.
- org 5Ch
-
- oldtv label dword
- oldt dw ?,? ;Old timer routine address.
- oldsv label dword
- olds dw ?,? ;Old keyboard scan routine address.
- oldkv label dword
- oldk dw ?,? ;Old keyboard service routine address.
-
- ink db ?,? ;In kcopy--don't call it again.
-
- kqs dw ? ;Queue size in bytes.
- kqf dw ? ;Queue front.
- kqr dw ? ;Queue rear.
- kq label word ;Queue.
- kqsz equ 128 ;Queue size in entries plus one.
-
-
-
- ;
- ; Start of .COM code - jump to installation.
- org 100h
- start:
- jmp install
-
- db 13,'KBUF version 1.1 Copyright (C) 1988 Mark Adler',13,10
- db 'All rights reserved.',13,10,'Z'-64
-
- org kq+kqsz*2 ;Start at end of queue.
-
-
-
- ;
- ; Traps and their subroutines -
-
- assume CS:kbuf,SS:nothing ;For all traps and subroutines.
-
-
-
- timer proc near
-
- assume DS:nothing,ES:nothing
-
- ; save registers.
- push AX
- push BX
- push DI
- push DS
- push ES
-
- ; enqueue keyboard data.
- call kcopy
- assume DS:kbuf,ES:kbuf
-
- ; restore registers and drop to next guy in chain.
- pop ES
- pop DS
- assume DS:nothing,ES:nothing
- pop DI
- pop BX
- pop AX
- jmp oldtv
-
- timer endp
-
-
-
- kscan proc near
-
- assume DS:nothing,ES:nothing
-
- ; save registers.
- push AX
- push BX
- push DI
- push DS
- push ES
-
- ; call normal service routine.
- pushf ;(simulate interrupt)
- call oldsv ;Call original service routine.
-
- ; enqueue keyboard data.
- call kcopy
- assume DS:kbuf,ES:kbuf
-
- ; restore registers and return from interrupt.
- pop ES
- pop DS
- assume DS:nothing,ES:nothing
- pop DI
- pop BX
- pop AX
- iret
-
- kscan endp
-
-
-
- ksupp proc near
-
- assume DS:nothing,ES:nothing
-
- ; save registers, set data segment.
- sti ;Allow interrupts.
- push BX
- push SI
- push DS
- mov BX,CS ;Set data segment.
- mov DS,BX
- assume DS:kbuf
-
- ; do function in AH.
- cmp AH,0FFh ;See if key stuff.
- je kstuff ;If so, stuff one.
- test AH,AH ;See if read.
- jz kread ;If so, wait for key data.
- dec AH ;See if status.
- jz kstat ;If so, get status.
- dec AH ;See if shift status.
- jnz kdone ;If not, just return.
-
- ; get shift status from original routine.
- sub BX,BX ;Get shift status in AL.
- mov DS,BX
- assume DS:ints
- mov AL,KB_FLAG
- jmp short kdone ;Return AX.
- assume DS:kbuf
-
- ; peek at queue for status.
- kstat:
- mov BX,offset kq ;Point to queue.
- cli ;Freeze queue.
- call pkq ;Get entry if any, set Z.
- sti ;Set interrupts back.
-
- ; return, restore registers except AX, F.
- pop DS
- assume DS:nothing
- pop SI
- pop BX
- retf 2 ;Discard flags on stack.
- assume DS:kbuf
-
- ; stuff - try to stuff the scan code in DX.
- kstuff:
- push ES
- push DI
- mov ES,BX ;Point ES to data area also.
- assume ES:kbuf
- mov BX,offset kq ;Point to queue.
- mov AX,DX ;Get code to stuff.
- cli ;Freeze queue.
- call enq ;Enqueue code.
- sti ;Unfreeze.
- mov AX,0FF00h ;Restore AH, zero AL -> ok.
- jnz ksok
- inc AX ;AL = 1 -> failure (no room to stuff).
- ksok:
- pop DI
- pop ES
- assume ES:nothing
- jmp short kdone
-
- ; read - try to dequeue until successful.
- kread:
- mov BX,offset kq ;Point to queue.
- cli ;Freeze queue.
- call deq ;Try to get entry.
- sti ;Allow scan interrupt.
- jz kread ;Wait until something there.
-
- ; return, restore registers except AX.
- kdone:
- pop DS
- assume DS:nothing
- pop SI
- pop BX
- iret
-
- ksupp endp
-
-
-
- kcopy proc near
-
- assume DS:nothing,ES:nothing
-
- ; kcopy - copy data from old queue to new queue.
- ; Hits DS, ES, DI, BX, AX, and F.
-
- ; set up segments.
- mov AX,CS
- mov DS,AX
- mov ES,AX
- assume DS:kbuf,ES:kbuf
-
- ; lock out use of this routine.
- mov AL,1 ;Try to lock out this routine.
- xchg AL,ink ;(Indivisible operation.)
- test AL,AL ;See if already locked out.
- jnz nogo ;If so, do nothing.
-
- ; check for data in old queue.
- kloop:
- mov AH,1 ;See if any data there.
- pushf ;(Simulate interrupt.)
- call oldkv ;Call original support routine.
- jz kfin ;If queue is empty, then done.
- mov BX,offset kq ;Point to keyboard queue.
- test AX,AX ;See if Ctrl Break.
- jnz knbrk ;If not, go on.
-
- ; empty queue on break (before enqueueing 0).
- mov AX,kqsz ;Queue size.
- call mtq ;Empty queue.
- sub AX,AX ;Restore AX.
- knbrk:
-
- ; try to enqueue data.
- cli ;Freeze queue.
- call enq ;Enqueue code.
- sti ;Unfreeze.
- jz kfin ;If failure, leave the code in the old queue.
- mov AH,0 ;Delete the code from the old queue.
- pushf ;(Simulate interrupt.)
- call oldkv ;Call original support routine.
- jmp short kloop ;See if there is more.
-
- ; finished---unlock this routine.
- kfin:
- mov ink,0
-
- ; return.
- nogo:
- ret
-
- kcopy endp
-
-
-
- mtq proc near
-
- assume DS:kbuf,ES:kbuf
-
- ; Initialize and empty queue.
- ; ES:BX points to queue, AX is ring size in words.
- ; F, AX, DI hit.
- cld
- lea DI,[BX-6] ;Point to queue size.
- shl AX,1 ;Convert size to bytes.
- stosw ;Set size.
- mov AX,BX ;Set pointers equal.
- stosw ;Set front.
- stosw ;Set rear.
- ret
-
- mtq endp
-
-
-
- enq proc near
-
- assume DS:kbuf,ES:kbuf
-
- ; Put entry in queue if possible.
- ; DS/ES:BX points to queue, AX is value to enqueue.
- ; On return Z reset indicates success, Z set failure.
- ; F, DI hit.
- std ;Set reverse direction.
- mov DI,[BX-2] ;Get rear pointer.
- cmp DI,BX ;See if pointer will underflow.
- stosw ;Store word in queue.
- ja enq1 ;If pointer not underflowed go on.
- add DI,[BX-6] ;Else, add size of queue in bytes.
- enq1:
- cmp DI,[BX-4] ;See if queue full.
- je enq2 ;If so, return zero set.
- mov [BX-2],DI ;Else, update rear pointer.
- enq2: ;Zero reset indicates success.
- ret
-
- enq endp
-
-
-
- deq proc near
-
- assume DS:kbuf,ES:nothing
-
- ; Remove entry from queue if possible.
- ; DS:BX points to queue.
- ; On return Z reset indicates success and AX contains
- ; the queue entry, else Z is set and AX is unchanged.
- ; F, SI hit.
- std ;Set reverse direction.
- mov SI,[BX-4] ;Get front pointer.
- cmp SI,[BX-2] ;See if queue empty.
- je deq2 ;If so, return zero set.
- cmp SI,BX ;See if pointer will underflow.
- lodsw ;Get word from queue.
- ja deq1 ;If pointer not underflowed, go on.
- add SI,[BX-6] ;Else, add size of queue.
- deq1:
- mov [BX-4],SI ;Update front pointer.
- deq2: ;Zero reset indicates success.
- ret
-
- deq endp
-
-
-
- pkq proc near
-
- assume DS:kbuf,ES:nothing
-
- ; Peek at entry in queue, if any.
- ; DS:BX points to queue.
- ; On return Z set if queue empty. Else, AX contains next entry
- ; to be dequeued. SI, F hit.
- mov SI,[BX-4] ;Get front pointer.
- cmp SI,[BX-2] ;See if queue empty.
- lodsw ;Get entry (if any).
- ret
-
- pkq endp
-
-
-
- ;
- ; Installation code - all segment registers set.
-
- install:
-
- assume CS:kbuf,DS:kbuf,ES:kbuf,SS:kbuf
-
- ; initialize new keyboard queue.
- mov BX,offset kq ;Point to queue.
- mov AX,kqsz ;Queue size.
- call mtq ;Empty queue.
-
- ; initialize flag.
- mov ink,0 ;Not currently in support routine.
-
- ; insert trap in timer interrupt vector.
- sub AX,AX
- mov ES,AX ;Point to interrupt area.
- assume ES:ints
- cli ;Disable interrupts during change.
- mov AX,int8 ;Save old pointer.
- mov oldt,AX
- mov AX,int8+2
- mov oldt+2,AX
- mov int8,offset timer ;Set new interrupt.
- mov int8+2,CS
-
- ; insert trap in scan interrupt vector.
- mov AX,int9 ;Save old pointer.
- mov olds,AX
- mov AX,int9+2
- mov olds+2,AX
- mov int9,offset kscan ;Set new interrupt.
- mov int9+2,CS
-
- ; insert trap in keyboard BIOS interrupt vector.
- mov AX,int16 ;Save old pointer.
- mov oldk,AX
- mov AX,int16+2
- mov oldk+2,AX
- mov int16,offset ksupp ;Set new interrupt.
- mov int16+2,CS
- sti ;Interrupts OK now.
-
- ; copy data from old queue to new queue.
- call kcopy
- assume DS:kbuf,ES:kbuf
-
- ; tell DOS to keep the traps in memory and exit.
- mov DX,offset install ;Amount to keep.
- int 27h ;Exit and remain resident.
-
-
-
- kbuf ends
-
-
- end start
-