home *** CD-ROM | disk | FTP | other *** search
- ; This function simulates the scan codes of the 101 keyboard on older 83/84 key
- ; keyboard systems that lack bios support for some often used 101 keyboard
- ; control key combinations. I miss being able to use the Control+Up, which is
- ; one of the key combinations that the old BIOS does not support on my old
- ; machine at home. Not all of the 101 keys are simulated. I decided to return
- ; simulated scan codes for the 83/84 keypad keys only. It would be trivial to
- ; expand this utility to include almost all of the 101 extended codes, but
- ; I sorta doubt users will miss keys like Alt + ; or Alt + ~ on 83/84 keyboards
- ; (especially if they couldn't use them in the first place).
- ;
- ; If this routine were to mimic the enhanced BIOS exactly, it would return
- ; 0xE0 in register al and the extended code in ah for the simulated scan codes.
- ; I have decided to stay with the original BIOS convention and return 0x00 in
- ; register al and the extended code in register ah.
- ;
- ; To see if control+up is pressed, we have to look at the keyboard status flags
- ; in the bios data area. The flags at byte 0040:0017 are as follows:
- ;
- ; Bit
- ; 7 Insert state 1 = active, 0 = inactive
- ; 6 Caps Lock 1 = active, 0 = inactive
- ; 5 Num Lock 1 = active, 0 = inactive
- ; 4 Scroll Lock 1 = active, 0 = inactive
- ; 3 Alt Shift 1 = active, 0 = inactive
- ; 2 Ctrl Shift 1 = active, 0 = inactive
- ; 1 Left Shift 1 = active, 0 = inactive
- ; 0 Right Shift 1 = active, 0 = inactive
- ;
- ; We are only concerned with bits 0-3, the shift status bits. At label "k1"
- ; in this routine, the status byte is tested with 0x0f. With simple tests,
- ; the status of the shift keys can be determined. Then, it easy to use the
- ; tables to translate (XLAT) the raw key codes to extended scan codes.
- ;
- ; This function was designed to be linked with C object code. The prototype
- ; for this function is far so it may be easily used with any memory model.
- ;
- ; For those of you (like me) who use keyboard speed up or other keyboard TSRs
- ; on XT's, you will find that those TSRs do not work with simulated scan codes
- ; generated by this utility. This function grabs the raw keys before the TSR
- ; gets them and they don't get passed to the TSR. This is the reason I mapped
- ; the "Keypad -" and "Keypad +" to the scroll up and scroll down functions -
- ; they aren't filtered by this function and get through to the typefast (TSR)
- ; utilities.
- ;
- ; Editor name: tde, the Thomson-Davis Editor.
- ; Author: Frank Davis
- ; Date: September 9, 1991
- ;
- ; This code is released into the public domain, Frank Davis. You may
- ; distribute it freely.
-
- kb_data_port EQU 60h
- kb_cntl_port EQU 61h
-
- bios_data SEGMENT AT 40h
- ORG 17h
- kb_status DB ?
- ORG 1ah
- buffer_head DW ?
- buffer_tail DW ?
- ORG 80h
- buffer_start DW ?
- buffer_end DW ?
- bios_data ENDS
-
-
- _TEXT SEGMENT WORD PUBLIC 'CODE'
- ASSUME cs:_TEXT, ds:NOTHING, es:bios_data
- public _simulate_enh_kbd
-
-
- ;
- ; Prototype this function as far in the C header file so it may be used easily
- ; with any memory model.
- ;
- _simulate_enh_kbd PROC FAR
- jmp initialize
-
-
- ; Map the keys starting at scan code 47h, which is the Home key. This routine
- ; DOES NOT return most of these values from systems with a 101 enhanced keyboard
- ; connected, but the codes are included here for reference. One should use the
- ; extended BIOS keyboard services with the 101 keyboard and not this function.
- ; Indeed, tde uses the extended BIOS if a 101 keyboard is detected.
- ;
- ; Home = 47h Left = 4bh End = 4fh Del = 53h F11 = 57h
- ; Up = 48h Center = 4ch Down = 50h SysReq = 54h F12 = 58h
- ; PgUp = 49h Right = 4dh PgDn = 51h --- = 55h
- ; Grey - = 4ah Grey + = 4eh Ins = 52h --- = 56h
- ;
- ; 47, 48, 49, 4a, 4b, 4c, 4d, 4e, 4f, 50, 51, 52,
- ; 53 54, 55, 56, 57, 58
- table:
- DB -1, -1, -1, -1, -1, 76, -1, -1, -1, -1, -1, -1
- DB -1, -1, -1, -1, 133, 134
- shift_table:
- DB -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
- DB -1, -1, -1, -1, 135, 136
- ctrl_table:
- DB -1, 141, -1, 142, -1, 143, -1, 144, -1, 145, -1, 146
- DB 147, -1, -1, -1, 137, 138
- alt_table:
- DB -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
- DB -1, -1, -1, -1, 139, 140
-
- old_int_9 DW ?,? ; space for old interrupt
-
- start:
- sti
- push ax ; push the registers we use
- push bx
- push dx
- push ds
- push es
-
- in al, kb_data_port ; let's look at the waiting key
-
- cmp al, 47h ; is it less than home?
- jb pop_out_9 ; yes, let regular int handle it
- cmp al, 80h ; is it less than a break code?
- jb k1 ; yes, let's look at this key - a keypad key
- ALIGN 2
- pop_out_9:
- jmp regular_int_9 ; default - let regular int 9 handle break codes
- ; and other stuff
-
- k1:
- mov dx, 0040h ; segment of bios data area
- mov es, dx ; put it in es
- mov dl, BYTE PTR es:kb_status ; get shift status of alt & ctrl keys
- test dl, 0fh ; & it with 0x0f to see if any shift keys down
- jnz k2 ; one of the shift keys is pressed - find it
- mov bx, OFFSET table ; get offset of table
- jmp SHORT k5 ; no shift keys were down, translate normal keys
- k2:
- test dl, 03h ; are the left or right shift keys down?
- jz k3 ; not pressed, must be a ctrl or an alt
- mov bx, OFFSET shift_table ; get offset of shift table
- jmp SHORT k5
- k3:
- test dl, 04h ; is the control shift key down?
- jz k4 ; not pressed, must be an alt
- mov bx, OFFSET ctrl_table ; get offset of control table
- jmp SHORT k5
- k4:
- ; the only shift key left is alt
- mov bx, OFFSET alt_table ; get offset of alt table
- ALIGN 2
- k5:
- sub al, 47h ; normalize key to zero
-
- mov dx, cs ; put code segment in dx
- mov ds, dx ; now transfer code segment to ds
-
- xlat ; table look up
- cmp al, -1 ; is it -1?
- je regular_int_9 ; yes, let regular interrupt 9 handle it
-
- mov ah, al ; put copy of character in ah
- xor al, al ; zero out scan code - simulate extended key
-
- ;
- ; We now have a key we want to emulate. Put it in the keyboard buffer and
- ; end our interrupt.
- ;
-
- mov bx, WORD PTR es:buffer_tail ; get the end pointer to buffer
- mov dx, bx ; save in dx
- inc dx ; move to next word in list
- inc dx
- cmp dx, WORD PTR es:buffer_end ; at end of buffer?
- jnz ck_full_kbd ; if no, continue
- mov dx, WORD PTR es:buffer_start ; yes, reset to buffer start
- ALIGN 2
-
- ck_full_kbd:
- cmp dx, WORD PTR es:buffer_head ; has the buffer wrapped?
- jz end_int_9 ; yes, kbd full - enable keyboard for next key
- mov WORD PTR es:[bx], ax ; store simulated key into kbd buffer
- mov WORD PTR es:buffer_tail, dx ; move the tail up for next key
- ALIGN 2
-
- end_int_9:
- cli ; no interrupts now
- mov al, 20h ; end of interrupt command
- out 20h, al ; send command to interrupt control port
- in al, kb_cntl_port ; get char from control port
- mov ah, al ; save it in ah
- or al, 80h ; set bit 7
- out kb_cntl_port, al ; output reset value
- mov al, ah ; send original value
- jmp SHORT $+2 ; take your time
- out kb_cntl_port, al ; send it to enable keyboard
- sti
- pop es ; restore registers
- pop ds
- pop dx
- pop bx
- pop ax
- iret ; return from interrupt
- regular_int_9:
- pop es ; restore registers
- pop ds
- pop dx
- pop bx
- pop ax
- jmp DWORD PTR old_int_9 ; no interrupt return - old one does it
-
- ; ***********************************************************************
- ; prototype for _simulate_enh_kbd is
- ;
- ; void far simulate_enh_kbd( int )
- ;
- ; The formal parameter is available on the stack. Use the bp register to
- ; access it.
- ;
- ; Passing any non-zero value will make this function grab interrupt 9.
- ; Pass a zero to this function to restore the old interrupt 9.
- ;
- ; If this function were really clever, it would have a "unique" signature.
- ; Before "installing", it would check to see if it was already installed.
- ; Similarly, before "uninstalling", this function would check to make sure
- ; it was installed so it wouldn't uninstall the regular interrupt 9
- ; handler by accident. What the hell, live dangerously.
- ;
- ; ***********************************************************************
-
- initialize:
- push bp
- mov bp, sp
-
- mov dx, [bp+6] ; put the parameter in dx
-
- push ds
- ASSUME es:_TEXT,ds:_TEXT
- mov ax, cs ; put cs in ds
- mov es, ax
- mov ds, ax
-
- cmp dx, 0 ; 'NULL' character unhooks interrupt 9
- je restore_9 ; any non NULL character grabs interrupt 9
- grab_9:
- mov ax, 3509h ; get old interrupt 9 location
- int 21h ; call MSDOS to get it
- mov WORD PTR old_int_9, bx ; save old int 9 offset
- mov WORD PTR old_int_9+2, es ; save old int 9 segment
-
- mov dx, OFFSET start ; get new offset of int 9
- mov ax, 2509h ; use function 25 so int 9 points
- int 21h ; to my routine
- jmp SHORT get_out ; continue with editor
-
- restore_9:
- mov dx, WORD PTR old_int_9 ; get offset of old int 9
- mov ax, WORD PTR old_int_9+2 ; get segment of old int 9
- mov ds, ax ; put segment in ds
- mov ax, 2509h ; restore old int 9
- int 21h
-
- get_out:
- pop ds ; clean up
- pop bp
- retf
- _simulate_enh_kbd endp
- _TEXT ends
- end