home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 September
/
Simtel20_Sept92.cdr
/
msdos
/
pcmag
/
vol7n12.arc
/
ALLKEYS.ASM
next >
Wrap
Assembly Source File
|
1988-06-28
|
21KB
|
465 lines
;=============================================================================
; AllKeys- Returns popup stolen key combinations back to the applications.
; Load "ALLKEYS" before and after your pop-ups.
; Then press Ctrl-Alt-Z to toggle ALLKEYS on/off.
; "beep..BEEP" signals all keys on. "BEEP..beep" signals all keys off.
;=============================================================================
CSEG SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:CSEG, DS:CSEG, ES:CSEG, SS:CSEG
ORG 100H
FIRST: JMP INIT
COPYRIGHT DB "ALLKEYS 1.0 (c) 1988 Ziff Communications Co.",13,10
DB "PC Magazine ",254," Robert L. Morton",13,10
DB "Low copy installed",13,10,"$"
MESG1 DB "ALLKEYS high copy installed",13,10
DB "Ctrl-Alt-Z to toggle tsr's on/off",13,10,"$"
MESG2 DB "ALLKEYS already installed high and low",13,10,"$"
MESG3 DB "Vectors could not be restored - ALLKEYS disabled",13,10,"$"
MESG4 DB "ALLKEYS not loaded yet",13,10,"$"
MESG5 DB "ALLKEYS un-installed",13,10,"$"
ORIG_INT9 DW 0,0 ;The original int 9 vector
ORIG_INT16 DW 0,0 ;The original int 16h vector
USED_INT9 DW 0,0 ;The used int 9 vector
USED_INT16 DW 0,0 ;The used int 16h vector
HOTKEY DB 44 ;Our HOT key: "Z"
SHIFT_MASK DB 0CH ;Our shift mask: "Ctrl-Alt"
ALLKEYS DB 0 ;Allkeys on/off status flag.
DISABLE DB 0 ;If set to 1, Allkeys will not respond
; to Ctrl-Alt-Z combination and all
; keystrokes will be processed normally.
TONE_LOW DW 500 ;Low boundary "beep"
TONE_HIGH DW 1500 ;High boundary "BEEP"
TONE_STEP DW 500 ;Step between tones
TONE_LENGTH DW 50 ;Length of each tone
;-----------------------------------------------------------------------------
; New interrupt 9 handling routine.
;-----------------------------------------------------------------------------
NEW_INT9 PROC NEAR
ASSUME CS:CSEG, DS:NOTHING, ES:NOTHING, SS:NOTHING
STI ;Enable interrupts
PUSH AX ;Save AX
CMP CS:DISABLE,0 ;Are we disabled?
JNE KB1 ;Jump out if so.
IN AL,60H ;Get key just pressed
CMP AL,CS:HOTKEY ;Was it our HOT key?
JNE KB2 ;If not, jump KB2
MOV AH,2 ;Get shift status.
INT 16H
AND AL,0FH ;Mask out shift keys
CMP AL,CS:SHIFT_MASK ;Was it our shift mask?
JNE KB2 ;If not, jump KB2
CALL KB_RESET ;Reset keyboard
XOR CS:ALLKEYS,0FFH ;Toggle request flag
CALL BEEP_STATUS ;Beep Allkeys' status
KB1: POP AX ;Restore AX
JMP DWORD PTR CS:USED_INT9 ;Exit through popup chain
KB2: CMP CS:ALLKEYS,0 ;Allkeys' request flag set?
JE KB1 ;If not, jump KB1
POP AX ;Restore AX
JMP DWORD PTR CS:ORIG_INT9 ;Skip popup chain and exit
; directly to original.
NEW_INT9 ENDP
;-----------------------------------------------------------------------------
; New interrupt 16h handling routine.
;-----------------------------------------------------------------------------
NEW_INT16 PROC NEAR
ASSUME CS:CSEG, DS:NOTHING, ES:NOTHING, SS:NOTHING
STI ;Enable interrupts
CMP CS:DISABLE,0 ;Are we disabled?
JNE INT16_OUT ;Jump out if so.
CMP CS:ALLKEYS,0 ;Allkeys' request flag set?
JE INT16_OUT ;No - Leave through used 16h
JMP DWORD PTR CS:ORIG_INT16 ;Yes- Leave through original
INT16_OUT: JMP DWORD PTR CS:USED_INT16
NEW_INT16 ENDP
;-----------------------------------------------------------------------------
; Routine to beep Allkeys' status through the speaker.
; If Allkeys is on, "beep..BEEP". If Allkeys is off, "BEEP..beep".
;-----------------------------------------------------------------------------
BEEP_STATUS PROC NEAR
ASSUME CS:CSEG, DS:NOTHING, ES:NOTHING, SS:NOTHING
PUSH CX ;Save needed registers
PUSH DS
PUSH CS ;Point DS to our data
POP DS
ASSUME DS:CSEG
CMP ALLKEYS,0 ;Allkeys off?
JE BS2 ;If so, jump BS2
;Allkeys on - Ascend from a LOW tone to a HIGH tone.
MOV CX,TONE_LOW ;Start at the bottom
BS1: CALL SOUND ;Make the sound
ADD CX,TONE_STEP ;Add the next step
CMP CX,TONE_HIGH ;Are we over the top?
JNA BS1 ;No - then keep on going
JMP BS_OUT ;Yes- then jump out
;Allkeys off- Descend from a HIGH tone to a LOW tone.
BS2: MOV CX,TONE_HIGH ;Start at the top
BS3: CALL SOUND ;Make the sound
SUB CX,TONE_STEP ;Subtract the next step
CMP CX,TONE_LOW ;Are we below the bottom?
JNB BS3 ;No, then keep on going
BS_OUT: POP DS ;Restore used registers
POP CX
RET
BEEP_STATUS ENDP
;-----------------------------------------------------------------------------
; Routine to produce a sound through the speaker.
; CX contains the frequency. Variable TONE_LENGTH contains the length.
;-----------------------------------------------------------------------------
SOUND PROC NEAR
ASSUME CS:CSEG, DS:CSEG, ES:NOTHING, SS:NOTHING
PUSH AX ;Save needed registers
PUSH CX
PUSH DX
;Convert the frequency.
MOV DX,12h ;Upper part
MOV AX,34DEh ;Lower part
DIV CX ;Divide by frequency
MOV CX,AX ;to get quotient.
;Set the tone.
MOV AL,CL ;Send low byte
OUT 42h,AL ;out to the timer.
MOV AL,CH ;Send high byte
OUT 42h,AL ;out to the timer.
;Turn the tone on.
IN AL,61h ;Get contents of system port B
OR AL,3 ;Turn speaker and timer on
OUT 61h,AL ;Send out new values to port B
;Delay
MOV CX,TONE_LENGTH ;Put delay count in CX
CALL DELAY ;Delay
;Turn the tone off.
IN AL,61h ;Get port B again
AND AL,0FCh ;Turn off timer and speaker
OUT 61h,AL
POP DX ;Restore used registers
POP CX
POP AX
RET
SOUND ENDP
;-----------------------------------------------------------------------------
; Routine to delay. CX contains the factor.
;-----------------------------------------------------------------------------
DELAY PROC NEAR
PUSH CX ;Save outside CX
MOV CX,0FFH ;Move timing constant in CX
DELAY1: LOOP DELAY1 ;Loop for inside
POP CX ;Restore outside CX
LOOP DELAY ;Loop for outside
RET
DELAY ENDP
;-----------------------------------------------------------------------------
; Routine to reset keyboard and 8259 interrupt controller.
;-----------------------------------------------------------------------------
KB_RESET PROC NEAR
IN AL,61H ;Get control port value
MOV AH,AL ;Save in AH
OR AL,80H ;Set bit 7
OUT 61H,AL ;Output reset value
MOV AL,AH ;Send original value...
JMP SHORT $+2 ;Take your time
OUT 61H,AL ;...to enable keyboard
CLI ;No interrupts now
MOV AL,20H ;Send end of interrupt
OUT 20H,AL ;value to 8259.
STI ;Re-enable interrupts
RET
KB_RESET ENDP
;-----------------------------------------------------------------------------
; Initialization for Allkeys....
;-----------------------------------------------------------------------------
INIT PROC NEAR
ASSUME CS:CSEG, DS:CSEG, ES:CSEG, SS:CSEG
;Check if the "/U" parameter was entered on the command line.
MOV SI,80h ;Point to parm line
CMP BYTE PTR [SI],0 ;Any chars entered?
JNE INIT1 ;Yes-jump init1
JMP INIT8 ;No -jump init8
INIT1: MOV CL,[SI] ;Put parm length in CL
XOR CH,CH ;Make 16 bit
INC SI ;Point to next byte
CLD ;Forward
INIT2: LODSB ;Load a byte into AL
CMP AL,"/" ;Is it our switch?
JE INIT3 ;Jump if so
LOOP INIT2 ;Keep on looking
JMP INIT8 ;No switch found. Jump init8.
INIT3: AND BYTE PTR [SI],0DFh ;Change char to uppercase
CMP BYTE PTR [SI],"U" ;Is it a "U"?
JE INIT4 ;Yes-jump init4
JMP INIT8 ;No -jump init8
;"/U" parameter found. Make sure we're loaded.
INIT4: CALL SEC_COPY ;Check for a second copy.
JC INIT5 ;Jump if found.
MOV DX,OFFSET MESG4 ;Print error message
ERR_EXIT: MOV AH,9
INT 21H
MOV AX,4C01h ;Terminate with errorlevel 1
INT 21H
;Modify resident copy to avoid future searches.
INIT5: ASSUME DS:CSEG, ES:NOTHING
PUSH ES ;Point DS at the resident
POP DS ; copy of Allkeys.
XOR AX,AX ;Point ES at the int vector
MOV ES,AX ; table at bottom of memory.
MOV WORD PTR [FIRST],0FFh ;This instruction modifies it
;Check if int 9 and 16h vectors point to the resident copy.
MOV AX,DS ;Put seg of orig copy in AX
CMP AX,ES:[ 9*4+2] ;Compare it to int 9 seg
JNE INIT6 ;Jump if different
CMP AX,ES:[16h*4+2] ;Compare it to int 16h seg
JNE INIT6 ;Jump if different
;Int 9 and 16h vectors point to resident copy.
;Restore int 9 and 16h vectors and release resident copy from memory.
;Then terminate.
ASSUME DS:NOTHING, ES:CSEG
PUSH DS ;Point ES at the resident
POP ES ; copy of Allkeys.
MOV AX,2509H ;Restore interrupt 9
MOV DX,ES:[USED_INT9 ]
MOV DS,ES:[USED_INT9+2]
INT 21H
MOV AX,2516H ;Restore interrupt 16h
MOV DX,ES:[USED_INT16 ]
MOV DS,ES:[USED_INT16+2]
INT 21H
MOV AH,49H ;Have DOS release it from
INT 21H ; memory.
ASSUME DS:CSEG, ES:CSEG
PUSH CS ;Point DS back at our data
POP DS
MOV DX,OFFSET MESG5 ;Display status message.
OK_EXIT: MOV AH,9
INT 21H
MOV AX,4C00h ;Terminate with no errorlevel
INT 21H
;Int 9 and 16h vectors do not point to resident copy.
;Check if resident copy was only installed LOW.
INIT6: CMP USED_INT9,0 ;Only installed LOW?
JNE INIT7 ;Jump if not
;Allkeys only installed LOW.
;Just simply release it from memory and terminate.
ASSUME DS:CSEG, ES:CSEG
PUSH DS ;Point ES at the resident
POP ES ; copy of Allkeys.
PUSH CS ;Point DS back to our data.
POP DS
MOV AH,49H ;Have DOS release it from
INT 21H ; memory.
MOV DX,OFFSET MESG5 ;Display OK message
JMP OK_EXIT ; and terminate.
;Allkeys installed HIGH and LOW.
;Set DISABLE flag to disable Allkeys. Then terminate.
INIT7: MOV DISABLE,1 ;Disable Allkeys
MOV DX,OFFSET MESG3 ;Print error message
JMP ERR_EXIT ; and terminate.
;"/U" parameter wasn't entered. Check to see if Allkeys already loaded.
INIT8: ASSUME DS:CSEG, ES:CSEG
CALL SEC_COPY ;Check for a second copy
JC INIT9 ;Jump if found
;Second copy not found.
;Release the environment to conserve memory.
;Save the current interrupts 9 and 16h. Then TSR.
ASSUME DS:CSEG, ES:NOTHING
MOV AX,WORD PTR DS:[2CH] ;Release the environment.
MOV ES,AX
MOV AH,49H
INT 21H
MOV AX,3509H ;Get interrupt 9
INT 21H
MOV [ORIG_INT9 ],BX ;Save the offset
MOV [ORIG_INT9+2],ES ;Save the segment
MOV AX,3516H ;Get interrupt 16h
INT 21H
MOV [ORIG_INT16 ],BX ;Save the offset
MOV [ORIG_INT16+2],ES ;Save the segment
MOV DX,OFFSET COPYRIGHT ;Display copyright
MOV AH,9
INT 21H
MOV AX,3100h ;Terminate and leave all
MOV DX,(OFFSET INIT - OFFSET CSEG + 15) SHR 4
INT 21H ; code but the init portion
; resident in memory. (TSR)
;Second copy was found.
;Make sure Allkeys not already installed high and low.
INIT9: ASSUME DS:CSEG, ES:CSEG
PUSH ES ;Point DS at the original
POP DS ; copy of Allkeys.
CMP USED_INT9,0 ;Already installed high & low?
JE INIT10 ;Jump if not.
MOV DX,OFFSET MESG2 ;Display error message
JMP ERR_EXIT ; and terminate.
;Obtain and save the used interrupts 9 and 16h to the original copy.
INIT10: ASSUME DS:CSEG, ES:NOTHING
MOV AX,3509H ;Get used interrupt 9
INT 21H
MOV [USED_INT9 ],BX ;Save the offset
MOV [USED_INT9+2],ES ;Save the segment
MOV AX,3516H ;Get used interrupt 16h
INT 21H
MOV [USED_INT16 ],BX ;Save the offset
MOV [USED_INT16+2],ES ;Save the segment
;Activate Allkeys by pointing interrupt vectors 9 and 16h
;to the resident copy's new interrupt 9 and 16h handlers.
MOV AX,2509H ;Set interrupt 9
MOV DX,OFFSET NEW_INT9
INT 21H
MOV AX,2516H ;Set interrupt 16h
MOV DX,OFFSET NEW_INT16
INT 21H
MOV DX,OFFSET MESG1 ;Display ready message
JMP OK_EXIT ; and terminate.
INIT ENDP
;-----------------------------------------------------------------------------
; Routine to search through memory for a previous loaded copy of Allkeys.
; If found, on return, CF will be set and ES will point to previous copy.
;-----------------------------------------------------------------------------
SEC_COPY PROC NEAR
ASSUME CS:CSEG, DS:CSEG, ES:NOTHING, SS:CSEG
MOV WORD PTR [FIRST],0 ;Modify to avoid false alarm
MOV BX,600h ;BX= start of our search
MOV AX,CS ;AX= end of our search
CLD ;Forward
NEXT_PARA:
INC BX ;Next paragraph
CMP AX,BX ;If current paragraph...
MOV ES,BX ;Set search segment
JE END_SEARCH ;...stop
MOV SI,OFFSET FIRST ;Compare FIRST label
MOV DI,SI ;Offset is same
MOV CX,16 ;Only FIRST 16 bytes
REP CMPSB ;Compare DS:SI TO ES:DI
OR CX,CX ;All matched?
JNZ NEXT_PARA ;No, keep on looking.
STC ;Found a copy in memory.
RET ; Set CF and RETurn.
END_SEARCH: CLC ;Didn't find a copy.
RET ; Clear CF and RETurn.
SEC_COPY ENDP
CSEG ENDS
END FIRST