;--------------------- KEYBOARD BUFFER EXTENDER -------- EN#1.0SRW02R ---[]
; By - Titas Raha (27/11/93) System Research Work # 2 (Resident program) :
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :
; Extends the keyboard buffer length by passing the additional keys through :
; a generated que. Must be converted into a .COM file :
;--------------------------------------------------------------------------[]
MAXKEYS EQU 128 ; Added Keyboard buffer length
BIOSSEG EQU 40h ; Dada segment of the BIOS
GETKBD EQU 3509h ; Get INT Vector Keyboard 9
SETKBD EQU 2509h ; Set INT Vector Keyboard 9
GETTIM EQU 351Ch ; Get INT Vector Timer 1C
SETTIM EQU 251Ch ; Set INT Vector Timer 1C
GETBRK EQU 351Bh ; Get INT Vector Break 1B
SETBRK EQU 251Bh ; Set INT Vector Break 1B
KBD_CTL EQU 61h ; Keyboard control port address
EOI EQU 20h ; End of int No.
SPKCYOFF EQU 28h ; Iterations at off position
SPKCYON EQU 68h ; Iterations at on position
SPKCYCLES EQU 80h ; No. of speaker cycles
code SEGMENT
ASSUME cs:code,ds:code
ORG 1Ah
buffhead LABEL WORD ; Keyboard buffer head
ORG 1Ch
bufftail LABEL WORD ; Keyboard buffer tail
ORG 80h
buffstart LABEL WORD ; Location of the Keyboard buffer
ORG 82h
buffend LABEL WORD ; Pointer to the end of buffer
ORG 100h ; In anticipation of .COM file
RESIDENT_LEN EQU ((OFFSET RB - OFFSET RT+100h) SHR 4)+1
; Length of the resident program
RT LABEL WORD ; Top of the resident program
start: jmp newloc ; Jump away from
; the resident data area
org_kbd dw 0,0 ; Original Keyboard handler INT 9
org_tim dw 0,0 ; Original Timer INT 1C handler
org_brk dw 0,0 ; Original Break INT 1B handler
que_head dw QUE_START ; Initial Head pointer of the que
que_tail dw QUE_START ; Initial Tail pointer of the que
QUE_START EQU OFFSET qs ; Start of the que
QUE_END EQU OFFSET qe ; End of the que
qs LABEL WORD ; Que's physical start address
que dw MAXKEYS DUP('U'*256+'Q')
; Que for storing additional keys
qe LABEL WORD ; Que's physical end address
newbrk PROC FAR ; New break procedure
;Clears the que with every invocation of the break interrupt
mov cs:que_head,QUE_START ; Make que head equal to
mov cs:que_tail,QUE_START ; que tail.
jmp dword ptr cs:[org_brk] ; Original Break interrupt
newbrk ENDP
newkbd PROC FAR ; The new rerouted keyboard INT 9
; Gets the extra keys from the keyboard buffer and saves it in a que.
push ax ; Save registers to use
push ds
pushf ; Will be restored by the handler
mov ax,BIOSSEG
mov ds,ax ; Set to BIOS's data segment
mov ax,bufftail ; Save the old tail pointer value
call dword ptr cs:[org_kbd] ; Call the original handler
push bx ; Save registers to use
push si
mov bx,ax ; Save tail pointer value to bx
mov ax,bufftail ; Get the new buffer position
mov si,ax ; Save in SI
inc ax ; Go to next buffer position
inc ax ; Inc 2 since it is of word length
cmp ax,buffend ; Is it end of the buffer ?
jne bptrok ; No, jump
mov ax,buffstart ; Yes, set to start of buffer
bptrok: cmp ax,buffhead ; Tail touched the head ?
je branch ; If yes, jump
cmp si,bx ; Is the buffer changed by handler
je kbdone ; No, nothing to do, leave
mov ax,cs:que_tail ; Get tail ptr of the extra buffer
cmp ax,cs:que_head ; Is it equal to the head ?
je kbdone ; Yes, X buffer empty no probs
attach: mov si,[bx] ; Get the char that just came in
mov bufftail,bx ; as if no change in the buffer
mov ax,cs ; set DS to the programs DATA
mov ds,ax ; segment.
mov ax,que_tail ; Get the X buffer tail ptr
mov bx,ax ; Save it
inc ax ; Goto next X buffer position
inc ax
cmp ax,QUE_END ; Is it at the end of the que ?
jne qptrok ; No, jump
mov ax,QUE_START ; Yes, set it to start of the que
qptrok: cmp ax,que_head ; Que head touched the tail ?
je beep ; Yes, buffer full beep
mov que_tail,ax ; No, advance the X buffer tail
mov [bx],si ; Save the char in X buffer.
kbdone: pop si ; Restore the stack and registers
pop bx
pop ds
pop ax
iret ; Interrupt return
beep: push cx ; Save CX
mov al,EOI ; End of interrupt command
out 20h,al ; Send command to INT control port
mov bx,SPKCYCLES ; No of cycle
in al,KBD_CTL ; Get control information
push ax ; Save information
atoffstate: and al,0FCh ; Turn off timer gate and speaker
out KBD_CTL,al ; Output to control
mov cx,SPKCYOFF ; No. of empty iterations
itr1: loop itr1 ; Speaker off
or al,2 ; Turn on speaker bit
out KBD_CTL,al ; Output to control
mov cx,SPKCYON ; Again set up count
itr2: loop itr2 ; With speaker at on position
dec bx ; Total time count
jnz atoffstate ; Do another cycle
pop ax ; Recover control
out KBD_CTL,al ; output the control
pop cx ; Recover CX
jmp kbdone
branch: cmp si,buffstart ; Current tail ptr = buffer start?
jne posfound ; No jump
mov si,buffend ; Yes, make it at end
posfound: dec si ; Get the previous position
dec si
mov bx,si ; save it in bx
jmp attach ; jump to the mainstreem
newkbd ENDP
newtim PROC FAR ; New rerouted INT 1C
; Tryies to restore the keys from the que to the keyboard buffer.
push ax ; Save registers to use
push si
push dx
push ds
mov ax,cs ; Make DATA segment as CODE
mov ds,ax
mov si,que_head ; Get the que head ptr
cmp si,que_tail ; Is it equal to the tail
je timdone ; Yes, no keys present, jump
mov ax,[si] ; Get the character from the que
mov dx,BIOSSEG ; Set DS to BIOS data
mov ds,dx
mov si,bufftail ; Get the kyb buffer tail
mov [si],ax ; Store the char to the kyb buffer
mov ax,buffend ; get the end of the buffer
inc si ; Get the next of the tail ptr
inc si
cmp si,ax ; Is it equal to the end of buffer
jne atbend1 ; Jump if not
mov si,buffstart ; Yes, Set to the start
atbend1: mov dx,si ; save next of the tail ptr
cmp si,buffhead ; Is it equal to the head ?
je timdone ; Yes, Buffer full quit
inc si ; No, get next to next of tail
inc si ; pointer
cmp si,ax ; Is it equal to the end of buffer
jne atbend2 ; Jump if not
mov si,buffstart ; Yes, Set to the start
atbend2: cmp si,buffhead ; Is it equal to the head ?
je timdone ; Yes, space left for 1 char, quit
mov bufftail,dx ; Increment the tail pointer
; ( character already saved )
mov ax,cs ; Again set DS as CS
mov ds,ax
mov ax,que_head ; Get the que head pointer
inc ax ; get the next position
inc ax
cmp ax,QUE_END ; Is it equal to the end ?
jne atbend3 ; No, jump
mov ax,QUE_START ; Yes, Set to start of the que
atbend3: mov que_head,ax ; Set the new que head position
timdone: pop ds ; restore the registers
pop dx
pop si
pop ax
jmp dword ptr cs:[org_tim] ; Call the old timer INT 1C
newtim ENDP
RB LABEL WORD ; End of the resident program
newloc: mov ah,9 ; Display line
mov dx,OFFSET heading ; Get Heading position
int 21h ; Dos function does it
mov ax,GETKBD ; Get the Keyboard interrupt
int 21h ; Dos function 21h does it
mov ax,es ; Get the segment of Kyb handler
cmp ax,0D000h ; Is it above 0D000h ?
ja kybnotset ; Yes, Keyboard not re-routed
mov ah,9 ; Dos function no. to print a line
mov dx,OFFSET msgfail ; Get the failure message to print
int 21h ; Call Dos
int 20h ; Terminate as normal program
kybnotset: mov org_kbd,bx ; Save the value OFFSET
mov org_kbd+2,es ; Save the value SEGMENT
mov ax,GETTIM ; Get the Timer interrupt in ES:BX
int 21h ; Function to get it
mov org_tim,bx ; Save the OFFSET
mov org_tim+2,es ; Save the SEGMENT
mov ax,GETBRK ; Get the Break interrupt
int 21h
mov org_brk,bx ; Save offset
mov org_brk+2,es ; Save segment
mov ax,SETKBD ; Set the new keyboard interrupt
mov dx,OFFSET newkbd ; OFFSET of the keyboard routine
int 21h ; Dos function 21h does it
mov ax,SETTIM ; Set the new timer interrupt
mov dx,OFFSET newtim ; OFFSET of it
int 21h ; Function to set it
mov ax,SETBRK ; Set new break interrupt handler
mov dx,OFFSET newbrk ; Address of it
int 21h
mov ah,9 ; Dos. function No. to print
mov dx,OFFSET msgsucc ; Get the success message
int 21h
mov ax,3100h ; Get ready to be resident
mov dx,RESIDENT_LEN ; No. of para to be resident
int 21h ; Initiate residency
msgfail db 'Keyboard interrupt vector re-routed',13,10
db 'Cannot load the resident part',13,10
db 'Terminating as a normal program.',13,10
db 10,'$'
heading db 13,10
db 10
db '<<<<<<-- KEYBOARD BUFFER EXTENDER -->>>>>>',9,9,9,'EN#1.0SRW02R',13,10
db 10
db 'A self taught product from :',13,10
db 'Titas Raha,',13,10
db '17, Uttar Palli, Sodepur',13,10
db 'Dist. 24 Parganas (N)',13,10
db 'WEST BENGAL - 743178',13,10
db '--------------------',13,10
db 10
db 'This is a resident program which handles the keys typed in when the',13,10
db 'keyboard buffer gets filled by storing those keys in another place,',13,10
db 'and transfering it back as soon as the keyboard buffer is in a',13,10
db 'position to accept it. It extends the buffer from normally 15 Keys',13,10
db 'to 15+127=142 Keys. Reroutes the 1C,1B and 9 interrupt vectors.',13,10
db 10,'$'
msgsucc db 'Resident portion loaded.',13,10
db 10,'$'
code ends
end start