home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Black Box 4
/
BlackBox.cdr
/
editors
/
tde150.arj
/
SIMUL101.ASM
< prev
next >
Wrap
Assembly Source File
|
1992-04-01
|
14KB
|
319 lines
; 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.
;
;
; ****************************************************************************
; ****** for tde 1.3, i added support for alt+<, alt+>, and alt+? ******
; ****** for tde 1.4, i added support for alt+;:, alt+'", and alt+`~ ******
; alt+[{ and alt+]}
; Since users can now reassign regular text keys to unused function keys,
; I decided to support a few more 101 key combinations, so other punctuation
; characters maybe assigned to those keys. This should be especially useful
; for languages that use characters in 128-255 extended ASCII set.
; ****************************************************************************
;
;
; 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.
;
; *************************************************************************
; **** The above paragraph is abso-damn-lutely wrong. I have demon- ****
; **** strated once again that I have trouble reading manuals. After ****
; **** reading the MASM 6.0 manual numerous times over the past six ****
; **** months, I have finally realized that only the cursor movement ****
; **** keys in the cursor/control cluster on 101 keyboards return ****
; **** 0xe0 in al. The other keypad keys are just extensions, which ****
; **** is what I am simulating. ****
; *************************************************************************
;
; 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, so you can scroll really fast thru files.
;
; 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. See the last section in tdefunc.h for more info.
;
_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.
;
; These tables are patterned after the ones in the IBM AT Technical Reference
; Manual, page 5-170 (the system bios listing), labels k8 thru k15.
;
; 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, 1ah ; is it less than "[{"?
jb pop_out_9 ; yes, let regular int handle it
cmp al, 1bh ; is it less than "]}"?
jbe special ; yes, let's check for alt
cmp al, 27h ; is it less than ";:"?
jb pop_out_9 ; yes, let regular int handle it
cmp al, 29h ; is it less than "`~"?
jbe special ; yes, let's check for alt
cmp al, 33h ; is it less than '<'?
jb pop_out_9 ; yes, let regular int handle it
cmp al, 35h ; is it less than '?'?
jbe special ; yes, let's check for alt
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
jmp SHORT k7
ALIGN 2
special:
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, 08h ; & it with 0x08 to see if the alt key is down
jnz k6 ; alt key is down, let's do the special case
jmp SHORT regular_int_9 ; otherwise goto regular interrupt 9
ALIGN 2
k6:
mov ah, al ; put the scan code in ah
xor al, al ; zero out al
;
; We now have a key we want to emulate. Put it in the keyboard buffer and
; end our interrupt.
;
k7:
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
sti ; enable interrupts - see IBM tech. ref. man.
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
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