;        TITLE     CTRLLOCK - Ignore CTRL keystroke
;
;        After disk load, becomes resident
;        Attaches to interrupt
;
;        09h       Keystroke interrupt
;
;        Causes system to ignore CTRL key by decoding each
;        keystroke, and ignoring CTRL press
;
;        VERSION WITHOUT STACK AND DATA IN CSEG
;        DESIGNED TO BE RUN AS COM FILE
;
CR       EQU       0Dh       ;Carriage return
LF       EQU       0Ah       ;Line feed
BELL     EQU       07h       ;Beep speaker
ESC      EQU       01Bh      ;escape key
TERM     EQU       '$'       ;String display terminator
CHECK_SUM EQU      0FBFBh    ;To test if in memory already
CTRL_SCAN EQU      01Dh      ;Scan code for CTRL key
;
KEY_INT  EQU       09h       ;Keyboard interrupt
KEY_ADDR EQU       09h*4     ;Keyboard interrupt address in memory
;
;
CSEG     SEGMENT   PARA PUBLIC 'CODE'
         ASSUME    CS:CSEG,DS:CSEG
;
STARTNOW PROC      FAR
;
         ORG       0100h     ;Required for COM programs
;
START:   NOP
         JMP       SETUP     ;First time, attach to interrupt and
;                            ;stay in memory
;
         DW        CHECK_SUM ;For in memory test, do not insert anything
;                            ;before entry, checksum tested before
;
KEY_ENTRY:

;
         NOP
         STI                 ;Reset interrupts
         PUSH      DS        ;Save system
         PUSH      ES
         PUSH      AX
         PUSH      BX
         PUSH      CX
         PUSH      DX
         PUSH      SI
         PUSH      DI
         PUSH      BP
;
         MOV       SI,CS               ;Get segment value
         MOV       DS,SI               ;Into data segment
         MOV       ES,SI               ;And extra
;
         IN        AL,060h             ;Read keyboard input
;
         TEST      AL,080h             ;See if key release
         JNZ       KEY_RELEASED        ;Yes, ignore releases
;
         CMP       AL,CTRL_SCAN        ;See if CTRL key depressed
         JNZ       KEY_EXIT            ;No, go to normal handling
;
;                                      ;key we want, reset keyboard
;                                      ;port to acknowledge receipt
;                                      ;of keystroke info
;
         IN        AL,061h             ;Read 8255 port
         OR        AL,080h             ;Set acknowledge signal bit
         OUT       061h,AL             ;Send acknowledge to port
         AND       AL,07Fh             ;Reset acknowledge bit
         OUT       061h,AL             ;Restore original 8255 port status
;
         MOV       AL,020h             ;Send EOI to 8259 command reg
         OUT       020h,AL
;
         POP       BP
         POP       DI                  ;Restore
         POP       SI
         POP       DX
         POP       CX
         POP       BX
         POP       AX
         POP       ES
         POP       DS
         IRET                          ;Return from interrupt
;

KEY_RELEASED:
KEY_EXIT:                              ;Handle keystroke normally,
         POP       BP                  ;jump to regular keyboard handler
         POP       DI
         POP       SI                  ;Restore registers
         POP       DX
         POP       CX
         POP       BX
         POP       AX                  ;Jump to regular keyboard routine
         POP       ES
         POP       DS
;
                   DB        0EAh      ;This produces far jump to below
;
OLD_KEY_ADDR       DW        0         ;Store old keyboard int address
                   DW        0
;
; -----------------------------------------------------------------
;
         SUBTTL    SETUP routine for startup
         PAGE
;
SETUP_START:                           ;End of actual in-core program
;
SETUP:
         PUSH      CS
         POP       DS                  ;Point here
;
         MOV       AL,KEY_INT          ;Interrupt vector wanted
         MOV       AH,035h             ;Get vector
         INT       021h                ;To DOS
;                                      ;Returns ES:BX vector pointer
         MOV       CX,BX
         DEC       BX                  ;Back off to our checksum
         DEC       BX
         MOV       AX,ES:[BX]          ;Get the word in front of entry
         CMP       AX,CHECK_SUM        ;See if already installed
         JNE       KEEP_IN_MEMORY
;        JMP       ALREADY_INSTALLED   ;Yes
;
ALREADY_INSTALLED:
         MOV       DX,OFFSET ALREADY_INSTALLED_MESSAGE
         MOV       AH,09               ;Print string
         INT       021h
;
         INT       020h                ;Just exit
;
; -----------------------------------------------------------------------
KEEP_IN_MEMORY:

;
         MOV       SI,OFFSET OLD_KEY_ADDR
         MOV       CS:[SI],CX          ;Save in our program
         MOV       CS:[SI+2],ES
;
         MOV       DX,OFFSET KEY_ENTRY
         MOV       AL,KEY_INT          ;Keyboard interrupt
         MOV       AH,025h             ;Set interrupt vector to DS:DX
         INT       021h
;
         MOV       DX,OFFSET NOW_INSTALLED_MESSAGE
         MOV       AH,09               ;Print string
         INT       021h
;
         MOV       DX,OFFSET SETUP_START ;Point to end of resident area
         ADD       DX,0Fh              ;Leave some extra
         INT       027h                ;Exit but remain resident
;
; -----------------------------------------------------------------------
;
NOW_INSTALLED_MESSAGE:
         DB        CR,LF
         DB        'CTRLLOCK program now installed.'
         DB        CR,LF
         DB        TERM

ALREADY_INSTALLED_MESSAGE:
         DB        BELL
         DB        CR,LF
         DB        'CTRLLOCK program already installed.'
         DB        CR,LF
         DB        BELL
         DB        TERM
;
STARTNOW ENDP
;
CSEG     ENDS
         END       START
