home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Media Share 9
/
MEDIASHARE_09.ISO
/
comm
/
ykh121.zip
/
YKHSRC.ZIP
/
GOLD.ASM
< prev
next >
Wrap
Assembly Source File
|
1992-10-10
|
22KB
|
567 lines
PAGE 64,132
TITLE GOLD key from NUMLOCK
NAME GOLD
;
; This program maps the NUM LOCK key (scan code 45H) to F1 (scan code 3BH)
; for use with Kermit emulating a DEC VT100.
;
; Version 2.0 - March 1991
; Additions:
; SHIFT and NUM LOCK acts as normal NUM LOCK
; ALT and NUM LOCK inverts current GOLD status
; Fix for problem with some clone BIOSes
; Fix non-detection of BIOS intercept support
; Use INT 09H if interrupt intercept not available
;
; Bob Eager
; rde@ukc.ac.uk USENET
; 100016,2770 CompuServe
; +44 227 367270 Telephone
;
; You may distribute this program freely as long as all of the files that
; make up the package (see the documentation file) are kept with it (including
; this source file) and you don't try to make money from it either by selling
; it directly or incorporating it into a product you sell.
;
; Values for exit status:
;
; 0 - success
; 1 - could not install program
; 2 - no BIOS support present
; 3 - unsupported DOS version (< 3.0)
; 4 - invalid parameter
;
; Constants
; ---------
;
CR = 0DH ; Carriage return
LF = 0AH ; Linefeed
TAB = 09H ; Tab
;
ID = 0DCH ; Multiplex ID
;
CSEG SEGMENT BYTE PUBLIC 'CODE'
;
$BEGIN EQU $
;
ORG 0100H
;
ASSUME CS:CSEG,DS:CSEG,ES:CSEG,SS:CSEG
;
SUBTTL Data areas
PAGE+
;
; The following jump to the initialisation code also provides three bytes
; of storage, two of which are used later by the resident part of the code.
;
BEGIN: JMP INIT ; jump to initialisation code
;
; Redefine storage for the above jump
;
ORG BEGIN
MBIT EQU THIS BYTE ; Make/Break bit
ORG BEGIN+1
ONOFF EQU THIS BYTE ; On/Off flag (0=off, initially on)
;
; Back to normal storage allocation
;
ORG BEGIN+3
;
; The following three values may be changed if required. MPID is the multiplex
; ID, and will only need alteration if some other TSR is using the same value.
; Choose another at random until it works! NEWKEY is the scan code value for
; the key to replace NUM LOCK. MODE is used to force a particular operation
; mode; it is particularly useful when a BIOS says that it supports the
; keyboard intercept function, but doesn't.
;
XXX DW 0
MPID DB 0DCH ; 102H Multiplex ID ** DO NOT MOVE **
NEWKEY DB 03BH ; 103H Replacement key ** DO NOT MOVE **
MODE DB 0 ; 104H Mode selector ** DO NOT MOVE **
; 00H = auto
; 01H = use INT 15H
; 02H = use INT 09H
;
INTOFF DW ? ; Old interrupt vector offset
INTSEG DW ? ; Old interrupt vector segment
I2FOFF DW ? ; Old INT 2FH offset
I2FSEG DW ? ; Old INT 2FH segment
;
SUBTTL INT 2FH (multiplex) handler
PAGE+
;
; This INT 2FH handler is hooked into the MS-DOS multiplex interrupt.
;
; Input parameters:
;
; AH = handler ID (MPID for this program)
; Calls with unrecognised handler IDs are passed on
; AL = function code
; 00 - get installation status
; 01 - get GOLD status
; 02 - set GOLD status
;
; Output parameters:
;
; AL = result
; Get installation status:
; FFH - Already installed
; Get GOLD status:
; 00H - OFF
; 01H - ON
; Set GOLD status:
; 00H - OK
;
I2FHAN PROC FAR
;
ASSUME CS:CSEG,DS:NOTHING,ES:NOTHING,SS:NOTHING
;
CMP AH,MPID ; for this program?
JE I2FH10 ; j if so
JMP DWORD PTR I2FOFF ; else use old handler
;
I2FH10: OR AL,AL ; AL=0, get installation status?
JNE I2FH20 ; j if not
MOV AL,0FFH ; indicate already installed
IRET ; and return
;
I2FH20: DEC AL ; AL=1, get GOLD status?
JNE I2FH30 ; j if not
MOV AL,ONOFF ; get value
IRET ; and return
;
I2FH30: DEC AL ; AL=2, set GOLD status?
JNE I2FH40 ; j if not
MOV ONOFF,DL ; set new value, drop through
;
I2FH40: IRET ; and return
;
I2FHAN ENDP
;
SUBTTL INT 15H (system services) handler
PAGE+
;
; This INT 15H handler is hooked into the BIOS system services interrupt.
; It is used only if the keyboard interrupt intercept capability is available
; in the BIOS.
;
; Input parameters:
; AH - function. Only 4FH (keyboard intercept) is handled;
; other values cause the action to be passed to the
; previous handler.
; AL - scan code for key just pressed
;
; Output parameters:
; AL - input scan code, or mapped version of it.
; CY - set to indicate that keystroke is to be processed.
; All other register contents are preserved.
;
ASSUME CS:CSEG,DS:NOTHING,ES:NOTHING,SS:NOTHING
;
I15HAN PROC FAR
;
CMP AH,4FH ; keyboard intercept function?
JE I15H10 ; j if so
JMP DWORD PTR INTOFF ; else call old handler
;
I15H10: PUSH ES
PUSH DI
PUSH AX
MOV AH,AL
SHR AL,1
SHR AL,1
SHR AL,1
SHR AL,1
AND AH,0FH
ADD AL,'0'
ADD AH,'0'
CMP AL,'9'
JBE FOO1
ADD AL,7
FOO1:
CMP AH,'9'
JBE FOO2
ADD AH,7
FOO2:
MOV DI,0B800H
MOV ES,DI
XOR DI,DI
ADD DI,CS:XXX
ADD CS:XXX,4
AND CS:XXX,127
MOV BYTE PTR ES:[DI ],AL
MOV BYTE PTR ES:[DI+1],15
MOV BYTE PTR ES:[DI+2],AH
MOV BYTE PTR ES:[DI+3],15
POP AX
POP DI
POP ES
;
I15H60: STC ; make sure keystroke processed
RETF 2 ; return, preserving flags
;
I15HAN ENDP
;
I15LEN = $ - I15HAN ; length of INT 15H handler
;
SUBTTL INT 09H (keyboard interrupt) handler
PAGE+
;
; This INT 09H handler is hooked into the keyboard interrupt vector.
; It is used only if the keyboard interrupt intercept facility is not
; available in the BIOS, and is moved in memory so that the space occupied
; by the INT 15H handler is not wasted.
;
; Input parameters:
; No explicit inputs. Implicit input from the keyboard
; hardware.
;
; Output parameters:
; No explicit outputs. Control is passed to the normal keyboard
; interrupt handler unless the keystroke is to be modified or
; absorbed. Modified keystrokes are placed into the BIOS input
; buffer.
; All registers are preserved.
;
I09HAN PROC FAR
;
PUSH AX ; save register
IN AL,60H ; get next character from hardware
MOV AH,AL ; copy scan code
AND AH,80H ; isolate make/break bit
MOV MBIT,AH ; save it
AND AL,7FH ; mask out make/break bit
CMP AL,45H ; NUM LOCK?
JE I09H10 ; j if so
JMP I09H80 ; else just pass on to original handler
;
; NUM LOCK has been pressed. Check for SHIFT (retain normal action).
;
I09H10: PUSH DS ; save segment
MOV AX,40H ; BIOS data segment
MOV DS,AX ; address BIOS data segment
MOV AL,DS:[17H] ; get keyboard flags
POP DS ; recover segment
AND AL,0FH ; mask out lock status
MOV AH,AL ; take copy for later comparison
CMP ONOFF,0 ; is GOLD on?
JE I09H20 ; j if not - do nothing here
AND AL,03H ; mask out ALT and CTRL status
JE I09H20 ; j if not shifted
CMP AH,AL ; see if just SHIFT
JE I09H80 ; if so, treat as normal NUM LOCK call
;
; Check for ALT (invert GOLD status). This needs to work whether GOLD is
; ON or OFF.
;
I09H20: MOV AL,AH ; recover shift status bits
AND AL,08H ; mask out CTRL and SHIFT status
JE I09H30 ; j if not ALT - pass through
CMP AH,AL ; see if just ALT
JNE I09H30 ; j if not - pass through
TEST MBIT,80H ; make operation?
JNE I09H70 ; j if not - ignore
XOR ONOFF,1 ; flip GOLD ON/OFF flag
JMP SHORT I09H70 ; absorb keystroke and exit
;
I09H30: CMP ONOFF,0 ; is GOLD on?
JE I09H80 ; j if not - pass through
;
I09H40: TEST MBIT,80H ; break code?
JNZ I09H70 ; j if so - ignore
PUSH DS ; save segment
PUSH SI ; save register
PUSH BX ; save register
MOV AX,40H ; BIOS data segment
MOV DS,AX ; address it
MOV BX,DS:[1CH] ; get offset of next slot in buffer
MOV SI,BX ; save for later
ADD BX,2 ; advance pointer
CMP BX,DS:[82H] ; time to wrap?
JNZ I09H50 ; j if not
MOV BX,DS:[80H] ; else do it
;
I09H50: CMP BX,DS:[1AH] ; buffer is full?
JZ I09H60 ; j if so - discard character
MOV AH,NEWKEY ; set replacement scan code
XOR AL,AL ; extended code
MOV WORD PTR [SI],AX ; set into buffer
MOV DS:[1CH],BX ; save updated buffer pointer
;
I09H60: POP BX ; recover register
POP SI ; recover register
POP DS ; recover segment
;
; Clear the keyboard port, acknowledging the character.
;
I09H70: IN AL,61H ; get control port
MOV AH,AL ; copy for later reset
OR AL,80H ; set bit to acknowledge
JMP SHORT $+2 ; wait for settle
OUT 61H,AL ; do the acknowledge
JMP SHORT $+2 ; wait for settle
MOV AL,AH ; get original setting
OUT 61H,AL ; put it back
JMP SHORT $+2 ; wait for settle
MOV AL,20H ; End-Of-Interrupt
OUT 20H,AL ; send to interrupt controller
POP AX ; recover register
IRET ; return without calling original
;
I09H80: POP AX ; recover register
JMP DWORD PTR INTOFF ; jump to original interrupt handler
;
I09HAN ENDP
;
I09LEN = $ - I09HAN ; length of INT 09H handler
;
SUBTTL Initialisation code
PAGE+
;
; This is the program initialisation code. It is not present in the resident
; copy of the program.
;
ASSUME CS:CSEG,DS:CSEG,ES:CSEG,SS:CSEG
;
INIT: MOV ONOFF,1 ; set initial value
;
; Select the operating mode
;
CMP MODE,2 ; force INT 09H to be used?
JE INIT50 ; j if so
PUSH ES ; save ES
MOV AH,0C0H ; see if keyboard intercept supported
INT 15H ; get system configuration parameters
JNC INIT10 ; j if configuration call supported
POP ES ; recover ES
JMP SHORT INIT20 ; try for INT 09H mode
;
INIT10: TEST BYTE PTR ES:[BX+5],10H ; see if intercept flag set
POP ES ; recover ES
JNE INIT30 ; j if intercept supported - use it
;
INIT20: CMP MODE,1 ; force INT 15H mode?
JNE INIT40 ; j if not - use INT 09H mode
LEA DX,MES0 ; 'Sorry - this machine does not...'
MOV AH,9 ; output message
INT 21H ; do it
MOV AX,4C02H ; exit with error status
INT 21H
;
INIT30: MOV MODE,1 ; select INT 15H mode
JMP SHORT INIT50 ; check DOS version now
;
INIT40: MOV MODE,2 ; select INT 09H mode
;
; The INT 2FH code will work only on DOS 3.0 and above. See if it is OK
; to use it.
;
INIT50: MOV AX,3000H ; get DOS version
INT 21H ; returns minor in AH, major in AL
CMP AL,3 ; see if 3 or greater
JGE INIT60 ; j if so - OK
LEA DX,MES1 ; 'Sorry - DOS 3.0 or above is...'
MOV AH,9 ; output message
INT 21H ; do it
MOV AX,4C03H ; exit with error status
INT 21H
;
; See if already installed
;
INIT60: MOV AH,MPID ; multiplex ID
XOR AL,AL ; function 00H
INT 2FH ; call multiplex
OR AL,AL ; see if OK to install (AL unchanged)
JZ INIT70 ; j if so
CMP AL,0FFH ; already installed?
JE INIT100 ; j if so - skip installation
LEA DX,MES2 ; 'Cannot install program'
MOV AH,9 ; output message
INT 21H ; do it
MOV AX,4C01H ; exit with error status
INT 21H
;
; Program is not installed; install it now.
;
INIT70: PUSH ES ; save segment
MOV AX,352FH ; get old INT 2FH handler
INT 21H ; returns value in ES:BX
MOV I2FOFF,BX ; save offset
MOV I2FSEG,ES ; save segment
LEA DX,I2FHAN ; point to new INT 2FH handler
MOV AX,252FH ; set INT 2FH vector
INT 21H ; from DS:DX
;
; Perform installation conditional on the selected mode
;
CMP MODE,1 ; use INT 15H mode?
JNE INIT80 ; j if not - set up for INT 09H
;
; Use the INT 15H code, which uses the BIOS keyboard interrupt intercept
;
MOV AX,3515H ; get old INT 15H handler
INT 21H ; returns value in ES:BX
MOV INTOFF,BX ; save offset
MOV INTSEG,ES ; save segment
LEA DX,I15HAN ; point to new INT 15H handler
MOV AX,2515H ; set INT 15H vector
INT 21H ; from DS:DX
POP ES ; recover segment
MOV WORD PTR INTLEN,I15LEN ; save interrupt routine length
JMP SHORT INIT90 ; rejoin common code
;
; Use the INT 09H code, which uses the keyboard hardware interrupt
;
INIT80: MOV AX,3509H ; get old INT 09H handler
INT 21H ; returns value in ES:BX
MOV INTOFF,BX ; save offset
MOV INTSEG,ES ; save segment
LEA DX,I15HAN ; point to new INT 09H handler
; (where it WILL be)
MOV AX,2509H ; set INT 09H vector
INT 21H ; from DS:DX
POP ES ; recover segment
MOV CX,I09LEN ; get interrupt routine length
MOV INTLEN,CX ; save it
CLD ; autoincrement
MOV SI,OFFSET I09HAN ; get address of interrupt routine
MOV DI,OFFSET I15HAN ; where to move it
REP MOVSB ; do so
;
; Complete installation
;
INIT90: INC BYTE PTR RESFLAG ; remember to stay resident
;
; The program is now installed. Handle parameters.
;
INIT100:CLD ; autoincrement
MOV SI,81H ; offset of command tail
MOV DI,81H ; put characters back in same place
;
INIT110:LODSB ; get next command character
CMP AL,CR ; end of command?
JE INIT130 ; j if so
CMP AL,'a' ; check if lower case alphabetic
JL INIT120 ; j if not
CMP AL,'z' ; check range
JG INIT120 ; j if not in range
SUB AL,'a'-'A' ; convert to upper case
;
INIT120:STOSB ; return possibly modified character
JMP INIT110 ; keep scanning
;
INIT130:MOV SI,81H ; back to start of command tail
;
INIT140:LODSB ; get next character
CMP AL,' ' ; space?
JE INIT140 ; j if so - ignore
CMP AL,TAB ; tab?
JE INIT140 ; j if so - ignore
CMP AL,CR ; end of parameters?
JE INIT150 ; j if so
DEC SI ; point back to first non-space
MOV BX,SI ; save pointer
MOV CX,2 ; check for ON
LEA DI,ON ; 'ON'
REP CMPSB ; matched?
JE INIT190 ; j if so
MOV SI,BX ; recover pointer
MOV CX,3 ; check for OFF
LEA DI,OFF ; 'OFF'
REP CMPSB ; matched?
JE INIT180 ; j if so
LEA DX,MES4 ; 'Parameter must be ON or OFF'
MOV AH,9 ; output message
INT 21H ; do it
MOV AX,4C01H ; indicate error
INT 21H ; and exit
;
; No parameter given - just report status unless initial installation
;
INIT150:LEA DX,MES3 ; 'GOLD is '
MOV AH,9 ; output message
INT 21H ; do it
MOV AH,MPID ; multiplex ID
MOV AL,1 ; request status
INT 2FH ; returns AL=0 for OFF, AL=1 for ON
OR AL,AL ; test value
JNZ INIT160 ; j if ON
LEA DX,OFF ; 'OFF'
JMP SHORT INIT170 ; join common code
;
INIT160:LEA DX,ON ; 'ON'
;
INIT170:MOV AH,9 ; output message
INT 21H ; do it
JMP SHORT INIT220 ; use common code
;
INIT180:XOR DL,DL ; clear flag
JMP SHORT INIT200 ; jump to setting code
;
INIT190:MOV DL,1 ; set flag
;
; AL now contains the required GOLD setting flag. Check that the rest of
; the command line is blank, then if all is OK set the flag appropriately.
;
INIT200:LODSB ; get next character
CMP AL,' ' ; space?
JE INIT200 ; j if so - ignore
CMP AL,TAB ; tab?
JE INIT200 ; j if so - ignore
CMP AL,CR ; end of parameters?
JE INIT210 ; j if so
LEA DX,MES5 ; 'Invalid parameter'
MOV AH,9 ; output message
INT 21H ; do it
MOV AX,4C04H ; indicate error
INT 21H ; and exit
;
; The command line is OK. Set the GOLD flag.
;
INIT210:MOV AH,MPID ; multiplex ID
MOV AL,2 ; set flag from DL
INT 2FH ; set new flag value in resident copy
;
; If this is not the first load of GOLD, just exit.
;
INIT220:TEST BYTE PTR RESFLAG,1 ; make resident?
JNE INIT230 ; j if so
MOV AX,4C00H ; else just exit with success
INT 21H
;
; This is the first load of GOLD; terminate and stay resident
;
INIT230:MOV ES,ES:[2CH] ; get environment segment
MOV AH,49H ; free memory for it
INT 21H ; do it
MOV DX,OFFSET I15HAN ; size of common part
ADD DX,INTLEN ; add size of interrupt routine
ADD DX,15 ; round to next paragraph
MOV CL,4 ; amount to shift
SHR DX,CL ; convert to paragraphs
MOV AX,3100H ; exit with success status
INT 21H ; and stay resident
;
INTLEN DW ? ; Size of selected interrupt handler
RESFLAG DB 0 ; Set to 1 if to stay resident
;
ON DB 'ON',CR,LF,'$'
OFF DB 'OFF',CR,LF,'$'
MES0 DB 'Sorry - this machine does not support the GOLD utility',CR,LF
DB 'if the interrupt intercept mode is selected'
DB CR,LF,'$'
MES1 DB 'Sorry - DOS 3.0 or above is required for the GOLD utility'
DB CR,LF,'$'
MES2 DB 'Sorry - cannot install the GOLD utility',CR,LF,'$'
MES3 DB 'GOLD is $'
MES4 DB 'Parameter must be ON or OFF',CR,LF,'$'
MES5 DB 'Invalid parameter',CR,LF,'$'
;
INFO DB '====GOLD version 2.0===='
;
CSEG ENDS
;
END BEGIN