home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 1995 November
/
PCWK1195.iso
/
inne
/
podstawy
/
dos
/
4dos
/
4uzytki
/
gl-keys.exe
/
KEYS.ASM
next >
Wrap
Assembly Source File
|
1994-01-21
|
24KB
|
692 lines
TITLE STACKKEY
;INITIAL VALUES : CS:IP 0000:0100
; SS:SP 0000:FFFE
com_segment SEGMENT
ASSUME cs:com_segment, es:com_segment
assume ss:com_segment, ds:com_segment
org $+80h
keybuffer equ $
parmbuffer equ $
ORG $+80h
bufptr equ $
maxkeys equ 255
keybuflen equ (2*maxkeys)
; WARNING: the code and data below is EXACTLY the right length to
; be consumed by the keybuffer starting at 080h
epoint:
MOV SI, parmbuffer
LODSB
CBW
MOV BX, AX
MOV BYTE PTR [BX+SI], 0 ; null terminate cmd line
look_for_slash:
LODSB
OR AL, AL
JZ no_more_parms
CMP AL, '/'
jz found_slash
cmp al, ' '
JZ look_for_slash
jmp do_parms
found_slash:
LODSB
CMP AL, 'I'
JZ do_install
CMP AL, 'i'
JZ do_install
cmp al, 'f'
jz do_file_parms
cmp al, 'F'
jz do_file_parms
JMP look_for_slash
; if no parms, print installation check results
no_more_parms:
MOV AX, 0D44Fh
XOR BX, BX
INT 2Fh ; install check
CMP AX, 44DDh
JNZ not_installed
MOV DX, offset fdosalready
jz print_and_exit
not_installed:
mov dx, offset fdosnoload
print_and_exit:
MOV AH, 9
INT 21h
MOV AX, 4C01h
INT 21h ; exit normally, exit code 1
fdosinstalled db 'KEYS installed.', 0dh, 0ah, '$'
fdosnoload db 'KEYS not installed.', 0dh, 0ah, '$'
; WARNING: the above code and data is EXACTLY the right length to
; be consumed by the keybuffer starting at 080h
terminator dw -1
; betcha $ is at 0100h right here !!!
skeycnt dw 0
curkeyp dw 0
delaydur dw 0
startticks dw 0
oldint16 dw 0
dw 0
oldint2f dw 0
dw 0
resident proc near
assume cs:com_segment
assume ds:nothing, es:nothing, ss:nothing
fwdint16:
JMP dword ptr [oldint16]
newint16:
sti
CMP [skeycnt], 0
jz fwdint16 ; if no stacked keys, get out quick
test ah, 0eeh ; this weirdness is a quick check for
; 0h, 1h, 10h, and 11h.
; All other calls are always forwarded.
jnz fwdint16
int16around:
PUSH SI
PUSH DS
push ax
PUSH CS
POP DS
assume ds:com_segment
mov si, [curkeyp]
CLD
test ah, 1 ; check vs. get
jnz just_checking
must_get_key:
cmp [delaydur], 0
jz get_key_now
call delay_check
jmp short must_get_key
just_checking:
cmp [delaydur], 0
jz check_now
call delay_check
check_now:
xor ax, ax
cmp [delaydur], ax
jnz check_exit
lodsw
cmp ax, -1
jnz is_key
call delay_setup
xor ax, ax
jmp short check_exit
is_key:
or ax, ax
jnz check_exit
dec [skeycnt] ; zero means fake out the check
mov [curkeyp], si ; but consume the fake out indicator
check_exit:
or ax, ax
pop si ; old ax value
pop ds
pop si
retf 2
get_key_now:
lodsw
cmp ax, -1
jnz not_a_delay
call delay_setup
jmp must_get_key
not_a_delay:
dec [skeycnt]
or ax, ax
jz get_key_now
mov [curkeyp], si
pop si ; old ax value
pop ds
assume ds:nothing
pop si
iret
assume ds:com_segment
; set up new delay if appropriate
delay_setup:
DEC [skeycnt] ; adjust for the -1 flag
LODSW ; fetch the delay parameter
MOV [delaydur], AX
CALL getticks
MOV [startticks], AX
DEC [skeycnt] ; adjust for the delay parameter
mov [curkeyp], si
cmp [skeycnt], 0
jl found_terminator ; negative count remaining
ret
found_terminator:
pop ax ; throw away return IP from call to delay_setup
mov [skeycnt], 0
pop ax
pop ds
assume ds:nothing
pop si
jmp fwdint16
assume ds:com_segment
getticks:
PUSH ES
MOV AX, 40h
MOV ES, AX
MOV AX, es:[6Ch] ; low word of ticks since midnight
POP ES
RET
delay_check:
CALL getticks
SUB AX, [startticks]
CMP AX, [delaydur]
JB moredelay
MOV [delaydur], 0
moredelay:
RET
assume ds:nothing, es:nothing, ss:nothing
fwdint2f: JMP dword ptr [oldint2f]
newint2f: CMP AX, 0D44Fh
JNZ fwdint2f ; we only recognize 1 op-code
MOV AX, 44DDh ; we always do this for grins
OR BX, BX ; here's the real op-code
JZ done2f
; here's the code to load in the new keystrokes
STI
PUSH DI
PUSH SI
CLD
PUSH CS
POP ES
assume es:com_segment
MOV DI, keybuffer
MOV [curkeyp], DI
xor ch, ch ; bounds check cx
MOV [skeycnt], cx
MOV [delaydur], 0
MOV SI, DX
REPZ MOVSW
dec cx
mov word ptr es:[di], cx ; end with -1
POP SI
POP DI
XOR AX, AX
done2f: IRET
assume es:nothing
endres equ $
resident endp
nonres proc near
ASSUME cs:com_segment, es:com_segment
assume ss:com_segment, ds:com_segment
do_install: MOV AX, cs:[2Ch] ; get environment segment
OR AX, AX
JZ noenvironment
assume es:nothing
MOV ES, AX
MOV AH, 49h
INT 21h ; return environment block
noenvironment:
MOV AX, 3516h
INT 21h ; get vector for INT 16h
MOV [oldint16], BX
MOV [oldint16+2], ES
MOV AX, 2516h
MOV DX, newint16
INT 21h
MOV AX, 352Fh
INT 21h ; get vector for INT 2fh
MOV [oldint2f], BX
MOV [oldint2f+2], ES
MOV AX, 252Fh
MOV DX, newint2f
INT 21h
MOV AH, 9
MOV DX, offset fdosinstalled
INT 21h
MOV DX, offset endres + 15
MOV CX, 4
SHR DX, CL
MOV AX, 3100h
INT 21h
ASSUME cs:com_segment, es:com_segment
assume ss:com_segment, ds:com_segment
do_parms:
MOV SI, offset parmbuffer
LODSB
CBW
jmp do_common
do_file_parms:
mov ah, 3fh
mov bx, 1
mov cx, 32767
mov dx, offset filebuf
int 21h
mov si, dx
do_common:
; at this point, si points to buffer, ax is count
MOV BP, AX ; save count
mov bx, ax
mov ax, 0d44fh
add bx, si
CLD
mov byte ptr [bx], 0 ; null terminate the input
mov bx, 0h
int 2fh ; check if KEYS is installed
cmp ax, 044ddh
je installed
exitpoint:
ret ; not installed, exit quietly
installed:
MOV DI, OFFSET bufptr
xor cx, cx
dec cl ; initialize initial scan code value
or bp, bp ; any buffer to process ?
jz exitpoint
call parsemain
mov ax, 0d44fh
mov bx, 1h
mov cx, [numentries]
mov dx, offset bufptr
int 2fh
ret
nonres endp
align 2
numentries dw 0
SOFAR dw 0
BASEVAL dw 0AH
parse proc near
; in remainder of code, the following register assignments are generally used
; BP count of command line bytes remaining (yes, this usage is unusual)
; BX is used as a temporary scratch register; often to a lookup table
; DH is quoted string delimiter during quoted string operations
; DL is a temporary save register during scan code lookup, and putchar ops
; AH generally contains the scan code of interest
; AL generally contains the ASCII code of interest, or the current input byte
; DS:SI points to the input stream
; ES:DI points to the output stream
; CL contains the global scan code (initially 255)
parsemain:
XOR AX, AX
call obtchar
call chkspace
OR BP, BP
JnZ parsemain ; loop until all characters used
ret
chkspace: ; ' ' and all control characters are ignored
cmp al, ' '
jg chkpound
ret
CHKPOUND: ; '#' introduces a scancode value. Once set, it is
; used for all subsequent keystrokes. Initially 255.
; The value of 255 causes a lookup of the "real" scancode.
CMP AL, '#'
JNZ CHKAT
CALL GETNUM
MOV CL, AL
ret
CHKAT: ; '@' introduces a number used as an Extended ASCII code.
; Hence, the ASCII value is set to zero, and the number
; specified is used as the scancode. This is independent
; of the scancode used for subsequent ASCII codes, however.
CMP AL, '@'
JNZ CHKPCT
CALL GETNUM
MOV AH, AL
MOV AL, 0
CALL PUTCHAR
ret
CHKPCT: ; '%' introduces a number used as an Enhanced keyboard
; Extended ASCII code. Hence, the ASCII value is set to
; E0, and the number specified is used as the scancode.
; This is independent of the scancode used for subsequent
; ASCII codes, however.
cmp al, '%'
jnz chkhat
call getnum
mov ah, al
mov al, 0e0h
call putchar
ret
chkhat: ; '^' introduces a letter used for a control code.
; It must be an uppercase letter, or one of '@[\]^_'.
; Also acceptable, are lowercase letters, or one of '`{|}~'.
; Actually, any character is acceptable, and only the low
; 5 bits of the character code are used.
cmp al, '^'
jnz chkbang
call obtchar
and al, 1fh
call xlatchar
call putchar
ret
chkbang: cmp al, '!'
jnz chkamp
mov ax, 0d44fh
mov bx, 1h
xor cx, cx
mov dx, offset bufptr
int 2fh
jmp short startflush
flushloop:
mov ah, 0
int 16h ; eat a character
startflush:
mov ah, 01h
int 16h ; is there a character
jnz flushloop
ret
chkamp: ; '&' introduces a letter used for an ALT code.
; It must be a letter.
; Actually, any character is acceptable, that letter's
; scan code is determined from the table, and used as
; and extended code.
cmp al, '&'
jnz chkstr
call obtchar
call xlatspec
mov al, 0
call putchar
doret:
ret
CHKSTR:
CMP AL, '"'
JZ ISSTR
CMP AL, "'"
JZ ISSTR
CMP AL, '~'
JNZ CHKDASH
ISSTR:
MOV DH, AL
MORESTR:
xor ax, ax
CALL OBTCHAR
CMP AL, DH
JZ doret
CALL xlatchar
CALL PUTCHAR
JMP SHORT MORESTR
CHKDASH:
CMP AL, '-'
JNZ CHKR
MOV AX, 0
CALL PUTCHAR
ret
CHKR:
CMP AL, 'r'
JZ DOENTER
CMP AL, 'R'
JZ DOENTER
CMP AL, 'e'
JZ DOENTER
CMP AL, 'E'
JNZ CHKF
DOENTER:
MOV AL, 0DH
CALL XLATCHAR
CALL PUTCHAR
ret
nochkw:
call unobtchar
ret
CHKSLASH:
CMP AL, '/'
JNZ CHKDIGIT
CHKW:
CALL OBTCHAR
CMP AL, 'w'
JZ DOWAIT
CMP AL, 'W'
JNZ nochkw
DOWAIT:
CALL GETNUM
push ax
mov ax, -1
call putchar
pop ax
shl ax, 1
call putchar
ret
CHKF:
CMP AL, 'f'
JZ DOFUNC
CMP AL, 'F'
JNZ CHKSLASH
DOFUNC:
CALL OBTCHAR
mov bx, offset afunckey
CMP AL, 'A'
JZ DOFUNCNUM
CMP AL, 'a'
JZ DOFUNCNUM
mov bx, offset cfunckey
CMP AL, 'C'
JZ DOFUNCNUM
CMP AL, 'c'
JZ DOFUNCNUM
mov bx, offset sfunckey
CMP AL, 'S'
JZ DOFUNCNUM
CMP AL, 's'
JZ DOFUNCNUM
mov bx, offset rfunckey
CALL UNOBTCHAR
DOFUNCNUM:
CALL GETNUM ; should be in range of 1-12
sub ax, 1 ; put in range of 1-11
cmp ax, 11 ; compare to the max
JA nofunc ; bad number
xlat
mov ah, al
MOV AL, 0
CALL PUTCHAR
nofunc:
ret
CHKDIGIT:
CMP AL, '0'
JB nochkdigit
CMP AL, '9'
JA nochkdigit
CALL UNOBTCHAR
CALL GETNUM
CALL XLATCHAR
CALL PUTCHAR
nochkdigit:
ret
fdosalready db 'KEYS already installed.', 0dh, 0ah, '$'
parse endp
xlatchar PROC NEAR
cmp ah, 0
jnz regnoxlat ; fastest way out, if scan code pre-set
MOV AH, CL
cmp ah, 255
jnz regnoxlat ; 2nd fastest way out, if scan code pre-spec
cmp dh, '~' ; what kind of scan code do you want
jnz xlatspec
mov bx, offset numscan
jmp short xlatact
xlatspec:
mov bx, offset regscan
xlatact:
MOV DL, AL
XLAT
MOV AH, AL
MOV AL, DL
regnoxlat:
RET
xlatchar ENDP
OBTCHAR PROC NEAR
LODSB
DEC BP
RET
OBTCHAR ENDP
UNOBTCHAR PROC
INC BP
DEC SI
RET
UNOBTCHAR ENDP
GETNUM PROC NEAR
PUSH AX
MOV BYTE PTR SOFAR, 0
CHKCHAR:
CALL OBTCHAR
CMP AL, '0'
JB BADCHAR
CMP AL, '9'
JA BADCHAR
SUB AL, '0'
xor ah, ah
XCHG ax, SOFAR
MUL BYTE PTR BASEVAL
ADD SOFAR, ax
JMP SHORT CHKCHAR
BADCHAR:
CALL UNOBTCHAR
POP AX
MOV AX, SOFAR
RET
GETNUM ENDP
PUTCHAR PROC NEAR
mov bx, [numentries]
cmp bx, maxkeys
ja noputchar
STOSW
INC bx
mov [numentries], bx
noputchar:
RET
PUTCHAR ENDP
DB 'Function Key Lookup Table'
; F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12
RFUNCKEY DB 3bh, 3ch, 3dh, 3eh, 3fh, 40h, 41h, 42h, 43h, 44h, 91h, 92h
SFUNCKEY DB 54h, 55h, 56h, 57h, 58h, 59h, 5ah, 5bh, 5ch, 5dh, 93h, 94h
CFUNCKEY DB 5eh, 5fh, 60h, 61h, 62h, 63h, 64h, 65h, 66h, 67h, 95h, 96h
AFUNCKEY DB 68h, 69h, 6ah, 6bh, 6ch, 6dh, 6eh, 6fh, 70h, 71h, 97h, 98h
DB 'Scancode Lookup Table'
regscan DB 03H ; zero (control @)
; control A-Z
DB 1EH, 30H, 2EH, 20H, 12H, 21H, 22H, 0EH, 0FH
DB 24H, 25H, 26H, 1CH, 31H, 18H, 19H, 10H, 13H
DB 1FH, 14H, 16H, 2FH, 11H, 2DH, 15H, 2CH
; control [ | ] ^ _
DB 01H, 2BH, 1BH, 07H, 0CH, 39H
; special characters ! " # $ % & ' ( ) * +, - . /
DB 02H, 28H, 04H, 05H, 06H, 08H, 28H, 0AH, 0BH, 09H, 0DH
DB 33H, 0CH, 34H, 35H
; digits 0-9
DB 0BH, 02H, 03H, 04H, 05H, 06H, 07H, 08H, 09H, 0AH
; special characters : ; < = > ? @
DB 27H, 27H, 33H, 0DH, 34H, 35H, 03H
; A-Z
DB 1EH, 30H, 2EH, 20H, 12H, 21H, 22H, 23H, 17H
DB 24H, 25H, 26H, 32H, 31H, 18H, 19H, 10H, 13H
DB 1FH, 14H, 16H, 2FH, 11H, 2DH, 15H, 2CH
; special characters [ \ ] ^ _ `
DB 1AH, 2BH, 1BH, 07H, 0CH, 39H, 29H
; a-z
DB 1EH, 30H, 2EH, 20H, 12H, 21H, 22H, 23H, 17H
DB 24H, 25H, 26H, 32H, 31H, 18H, 19H, 10H, 13H
DB 1FH, 14H, 16H, 2FH, 11H, 2DH, 15H, 2CH
; special characters { | } ~
DB 1AH, 2BH, 1BH, 29H
; Alt numeric key entry only
DB 129 DUP(0)
numscan DB 03H ; zero
; control A-Z
DB 1EH, 30H, 2EH, 20H, 12H, 21H, 22H, 0EH, 0FH
DB 24H, 25H, 26H, 1CH, 31H, 18H, 19H, 10H, 13H
DB 1FH, 14H, 16H, 2FH, 11H, 2DH, 15H, 2CH
; control [ | ] ^ _
DB 01H, 2BH, 1BH, 07H, 0CH, 39H
; special characters ! " # $ % & ' ( ) * +, - . /
DB 02H, 28H, 04H, 05H, 06H, 08H, 28H, 0AH, 0BH, 37H, 4EH
DB 33H, 4AH, 53H, 35H
; digits 0-9
DB 52H, 4FH, 50H, 51H, 4BH, 4CH, 4DH, 47H, 48H, 49H
; special characters : ; < = > ? @
DB 27H, 27H, 33H, 0DH, 34H, 35H, 03H
; A-Z
DB 1EH, 30H, 2EH, 20H, 12H, 21H, 22H, 23H, 17H
DB 24H, 25H, 26H, 32H, 31H, 18H, 19H, 10H, 13H
DB 1FH, 14H, 16H, 2FH, 11H, 2DH, 15H, 2CH
; special characters [ \ ] ^ _ `
DB 1AH, 2BH, 1BH, 07H, 0CH, 39H, 29H
; a-z
DB 1EH, 30H, 2EH, 20H, 12H, 21H, 22H, 23H, 17H
DB 24H, 25H, 26H, 32H, 31H, 18H, 19H, 10H, 13H
DB 1FH, 14H, 16H, 2FH, 11H, 2DH, 15H, 2CH
; special characters { | } ~
DB 1AH, 2BH, 1BH, 29H
; Alt numeric key entry only
DB 129 DUP(0)
align 2
filebuf equ $
com_segment ends
end epoint