home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
magazine
/
pcmagazi
/
1990
/
15
/
conceal.asm
< prev
next >
Wrap
Assembly Source File
|
1990-07-01
|
72KB
|
2,035 lines
_TEXT SEGMENT PUBLIC 'CODE'
ASSUME CS:_TEXT,DS:_TEXT,ES:_TEXT,SS:_TEXT
ORG 80H
DTA LABEL BYTE
ORG 100H
START: JMP INITIALIZE
; DATA AREA
; ---------
CR EQU 13
LF EQU 10
FF EQU 12
CTRL_Z EQU 26
SPACE EQU 32
BOX EQU 254
BELL EQU 7
TAB EQU 9
SIGNATURE DB SPACE,CR,CR,LF
COPYRIGHT DB "CONCEAL 1.0 (c) 1990 Ziff Communications Co.",CR,LF
PROGRAMMER DB "PC Magazine ",BOX," Michael J. Mefford",CR,LF,LF,"$"
DB CTRL_Z
KB_FLAG EQU 17H
BUFFER_HEAD EQU 1AH
BUFFER_TAIL EQU 1CH
CTRL_STATE EQU 4
ALT_STATE EQU 8
COMBO DB "Z"
HOT_KEY_SCAN DB 2CH ;"Z"
HOT_SHIFT_KEY DB ALT_STATE
OLD8 DW ?,? ;Old interrupt addresses.
OLD9 DW ?,?
OLD21 DW ?,?
PORT_A EQU 60H
PORT_B EQU 61H
COMMAND_PORT EQU 20H
EOI EQU 20H
MATCHING STRUC
RESERVED DB 21 DUP (?)
ATTRIBUTE DB ?
FILE_TIME DW ?
FILE_DATE DW ?
SIZE_LOW DW ?
SIZE_HIGH DW ?
FILE_NAME DB 13 DUP (?)
MATCHING ENDS
PASS_CODE EQU 95H
PASSWORD DB "S" XOR 95H, "H" XOR 96H, "A" XOR 97H, "Z" XOR 98H
DB "A" XOR 99H, "M" XOR 9AH
PASS_LEN EQU $ - PASSWORD
DB 50 DUP (?)
PASSWORD_LEN EQU $ - PASSWORD
PASS_CNT DW PASS_LEN
PASS_MASK DB PASS_CODE
PASS_POINTER DW OFFSET DTA
TRAP_FUNCS LABEL BYTE
FCB_FUNCS DB 0FH, 13H, 17H ;Open, Delete, Rename.
HANDLE_FUNCS DB 3DH, 41H, 56H
TRAP_CNT EQU $ - TRAP_FUNCS
BOGUS_ARG DB 12 DUP (0)
FILESPEC DB 13 DUP (?)
EGA_INFO EQU 87H
EGA_ACTIVE EQU 00001000B
ADDR_6845 EQU 63H
CRT_MODE_SET EQU 65H
VIDEO_SIGNAL EQU 00001000B
CRT_MODE EQU 49H
SAVE_MODE DB ?
CRT_PALETTE EQU 66H
SAVE_PALETTE DB ?
CRT_COLS EQU 4AH
ACTIVE_PAGE EQU 62H
CURSOR_ADDR DW ?
CURSOR_POSN EQU 50H
CURSOR_POS DW ?
CURSOR_MODE DW ?
ON EQU 1
OFF EQU 0
SOFT_BLANK EQU 1
HARD_BLANK EQU 2
CONCEAL_FLAG DW OFF ; ON if files have been secured.
BLANK_FLAG DB OFF ; ON if /G ON or /B ON.
CGA_MONO EQU 0
EGA_VGA EQU 1
SOFTWARE EQU 2
BLANK_TYPE DB ? ; CGA_MONO, EGA_VGA or SOFTWARE blanked.
BLANK_SCREEN DB OFF ; ON if screen is blanked.
UNBLANK_FLAG DB OFF ; ON if password required to unblank.
BLANK_IT DB OFF ; ON if Hotkey pressed; timer will blank
UNBLANK_IT DB OFF ; ON if key pressed; timer will unblank
GRAPHIC_APPS DB OFF ; ON if Don't blank graphic apps.
BUFFER_FLAG DB OFF ; ON if installed with /G.
CHANGE_FLAG DB OFF ; ON if attribute to be changed.
CONCEAL_STATS EQU 0
ATTR_STATS EQU 1
STATS_FLAG DB ?
DEFAULT_TIME EQU 3 * 1092
TIMER_BUSY DB 0
TIME_OUT DW DEFAULT_TIME
COUNTER DW DEFAULT_TIME
CONCEAL_BUSY DB 0 ;=1 if DOS hook entered.
;----------------------------------------------;
DOS PROC FAR
CMP CS:CONCEAL_FLAG,ON
JNZ SKIP_CONCEAL2
CMP CONCEAL_BUSY,1
JZ SKIP_CONCEAL2
MOV CS:CONCEAL_BUSY,1
PUSH DS
PUSH ES
PUSH BX
PUSH CX
PUSH DX
PUSH SI
PUSH DI
PUSH AX
CMP AX,4301H ;Change file mode.
JNZ TRAP
PUSH AX
PUSH CX
MOV AX,4300H
INT 21H
MOV BX,CX
POP CX
POP AX
JC SKIP_CONCEAL1
TEST BX,4
JZ SKIP_CONCEAL1
TEST CX,4
JZ MAKE_CONCEAL
JMP SHORT SKIP_CONCEAL1
TRAP: CLD
MOV SI,DS ;Segment.
MOV CX,CS
MOV DS,CX
MOV ES,CX
XCHG AH,AL
MOV DI,OFFSET TRAP_FUNCS
MOV CX,TRAP_CNT
REPNZ SCASB
JNZ SKIP_CONCEAL1
MOV CX,DX ;Offset.
CMP DI,OFFSET HANDLE_FUNCS + 1
JAE DO_CONCEAL
CALL CONVERT_FCB
DO_CONCEAL: CALL CK_CONCEAL ;See if filespec has System attr.
JC MAKE_CONCEAL
SKIP_CONCEAL1: POP AX
POP DI
POP SI
POP DX
POP CX
POP BX
POP ES
POP DS
MOV CS:CONCEAL_BUSY,0
SKIP_CONCEAL2: JMP DWORD PTR CS:OLD21 ;Call keyboard handling routine.
MAKE_CONCEAL: PUSH CS
POP DS
MOV DX,OFFSET BOGUS_ARG ;To fail, pass the call with
POP AX ; an invalid argument.
PUSHF
CALL DWORD PTR CS:OLD21
POP DI
POP SI
POP DX
POP CX
POP BX
POP ES
POP DS
MOV CS:CONCEAL_BUSY,0
RET 2 ;Return with flags intact.
DOS ENDP
;----------------------------------------------;
; INPUT: SI:CX -> FCB; OUTPUT: SI:CX -> FILESPEC
CONVERT_FCB: XCHG SI,CX ;Convert a FCB format to
MOV DS,CX ; a handle format.
MOV DI,OFFSET FILESPEC
LODSB
CMP AL,-1 ;Extended FCB?
JNZ DRIVE
ADD SI,6
LODSB
DRIVE: OR AL,AL
JNZ STORE_DRIVE
MOV AH,19H ;Current disk.
PUSHF
CALL DWORD PTR CS:OLD21
INC AL
STORE_DRIVE: ADD AL,"A" - 1
STOSB
MOV AL,":"
STOSB
PUSH SI
MOV CX,8
NEXT_NAME: LODSB
CMP AL,SPACE
JBE EXTENSION
STOSB
LOOP NEXT_NAME
EXTENSION: MOV AL,"."
STOSB
POP SI
ADD SI,8
MOV CX,3
NEXT_EXT: LODSB
CMP AL,SPACE
JBE ASCIIZ
STOSB
LOOP NEXT_EXT
ASCIIZ: XOR AL,AL
STOSB
MOV SI,CS
MOV CX,OFFSET FILESPEC
RET
;----------------------------------------------;
; INPUT: SI:CX -> FILESPEC; OUTPUT: CF = 1 if FILESPEC has system attribute.
CK_CONCEAL: MOV AH,2FH ;Get disk transfer address
PUSHF
CALL DWORD PTR CS:OLD21
PUSH ES ; and save.
PUSH BX
PUSH CS
POP DS
MOV DX,OFFSET DTA
MOV AH,1AH ;Set disk transfer address
PUSHF ; to our DTA.
CALL DWORD PTR CS:OLD21
MOV DS,SI
MOV DX,CX
MOV CX,1 OR 2 OR 4 ;Read-only, hidden and system
MOV AH,4EH ; attributes.
PUSHF
CALL DWORD PTR CS:OLD21
CMC
JNC CK_CONCEAL_END
TEST CS:DTA.ATTRIBUTE,4 ;System attribute?
STC
JNZ CK_CONCEAL_END
CLC
CK_CONCEAL_END: POP DX
POP DS
PUSHF
MOV AH,1AH ;Restore DTA.
PUSHF
CALL DWORD PTR CS:OLD21
POPF
RET
;------------------------------------------------------------------------------
;Execution comes here thru interrupt 9 every time a key is pressed or released.
;------------------------------------------------------------------------------
KEYBOARD PROC NEAR
STI
PUSH AX
IN AL,PORT_A ;Get scan code.
PUSHF
CALL CS:DWORD PTR OLD9
CMP CS:BLANK_FLAG,OFF ;Blanking active?
JNZ CK_STATE
JMP KEYBOARD_END
CK_STATE: PUSH BX
PUSH SI
PUSH DI
PUSH DS
PUSH ES
MOV BX,CS
MOV DS,BX
MOV BX,40H
MOV ES,BX
CMP AL,HOT_KEY_SCAN ;Our hot key?
JNZ CK_DISABLED
MOV AL,ES:[KB_FLAG] ;Get keyboard shift status
TEST AL,HOT_SHIFT_KEY
JZ CK_DISABLED
CLI
MOV AX,ES:BUFFER_HEAD ;Flush keyboard buffer.
MOV ES:BUFFER_TAIL,AX
CMP BLANK_SCREEN,ON ;Screen already blanked?
JZ LILLY_JMP
MOV BLANK_IT,ON ;If no, request blank.
LILLY_JMP: JMP KEYBOARD_DONE
CK_DISABLED: CMP BLANK_SCREEN,ON
JNZ RESET_TIMER
TEST AL,80H ;Key release?
JNZ KEYBOARD_DONE ;If yes, ignore.
CMP UNBLANK_FLAG,ON ;Password required?
JNZ DO_UNBLANK
MOV BX,CS
MOV ES,BX
CLD
MOV AH,1
INT 16H
JZ KEYBOARD_DONE
XOR AH,AH ;Get password.
INT 16H
MOV DI,PASS_POINTER
CMP AL,CR ;If carriage return, decode.
JZ DECODE
CMP DI,OFFSET DTA + PASSWORD_LEN
JAE KEYBOARD_DONE
CMP AL,"a" ;Capitalize.
JB DO_STORE
CMP AL,"z"
JA DO_STORE
AND AL,5FH
DO_STORE: XOR AL,PASS_MASK ;Encode.
STOSB
MOV PASS_POINTER,DI
INC PASS_MASK
JMP SHORT KEYBOARD_DONE
DECODE: STOSB ;Carriage return.
MOV PASS_MASK,PASS_CODE
MOV DI,OFFSET DTA
MOV PASS_POINTER,DI
MOV SI,OFFSET PASSWORD
PUSH CX
MOV CX,PASS_CNT
REPZ CMPSB
POP CX
JNZ KEYBOARD_DONE ;Valid password?
CMP BYTE PTR [DI],CR
JNZ KEYBOARD_DONE
DO_UNBLANK: MOV UNBLANK_IT,ON ;Request unblank.
MOV BX,40H
MOV DS,BX
CLI
MOV AX,DS:BUFFER_HEAD ;Flush keyboard buffer.
MOV DS:BUFFER_TAIL,AX
JMP SHORT KEYBOARD_DONE
RESET_TIMER: MOV AX,TIME_OUT ;Reset time-out.
MOV COUNTER,AX
KEYBOARD_DONE: POP ES
POP DS
POP DI
POP SI
POP BX
KEYBOARD_END: POP AX
IRET
KEYBOARD ENDP
;------------------------------------------------------------------------------
;Interrupt 8 handling routine.
;------------------------------------------------------------------------------
TIMER PROC NEAR
CLI
PUSHF
CALL CS:DWORD PTR OLD8
CMP CS:BLANK_FLAG,OFF ;Blanking active?
JZ TIMER_END
PUSH AX
PUSH DS
MOV AX,CS
MOV DS,AX
CMP TIMER_BUSY,0
JNZ TIMER_DONE
INC TIMER_BUSY
CLD
CMP UNBLANK_IT,ON ;Request to unblank?
JZ ENABLE
CMP BLANK_IT,ON ;Request to blank?
JZ DO_BLANK
CMP COUNTER,0 ;If timed-out, keep blanked.
JZ KEEP_BLANK
DEC COUNTER ;Else, decrement counter.
JNZ TIMER_EXIT
DO_BLANK: CALL BLANK
JMP SHORT TIMER_EXIT
ENABLE: CALL UNBLANK
JMP SHORT TIMER_EXIT
KEEP_BLANK: CALL BLANK_MODE
TIMER_EXIT: CLI
DEC TIMER_BUSY
TIMER_DONE: POP DS
POP AX
TIMER_END: IRET
TIMER ENDP
;----------------------------------------------;
BLANK: MOV BLANK_IT,OFF ;Turn off blank request.
PUSH ES
PUSH BX
PUSH CX
PUSH DX
MOV AX,40H
MOV ES,AX
MOV AL,ES:[CRT_MODE]
CMP GRAPHIC_APPS,ON ;Blank graphics modes?
JNZ CK_TYPE
CMP AL,7 ;Mono?
JZ CK_TYPE
CMP AL,3 ;Text?
JBE CK_TYPE
MOV AX,TIME_OUT
MOV COUNTER,AX
JMP BLANK_END
CK_TYPE: MOV BLANK_SCREEN,ON ;Note screen will be blanked.
MOV COUNTER,0
STI
CMP BLANK_FLAG,HARD_BLANK ;Hardware blank?
JZ DO_HARDWARE
CMP AL,3 ;Text mode?
JA DO_HARDWARE
CMP ES:BYTE PTR [ACTIVE_PAGE],0
JNZ DO_HARDWARE
CMP ES:WORD PTR CRT_COLS,80
JA DO_HARDWARE
PUSH BP
PUSH ES
MOV DL,24 ;25 rows?
MOV AX,1130H
INT 10H
POP ES
POP BP
CMP DL,24
JA DO_HARDWARE
CALL SAVE_SCREEN ;Software blank.
MOV BLANK_TYPE,SOFTWARE
JMP SHORT BLANK_END
DO_HARDWARE: MOV BL,10H ;Ega or Vga?
MOV AH,12H
INT 10H
CMP BL,10H
JZ CGA_OR_MONO
TEST ES:BYTE PTR [EGA_INFO],EGA_ACTIVE
JNZ CGA_OR_MONO
CLI
MOV DX,3BAH ;Status register; read to
IN AL,DX ; initialize address register.
ADD DX,20H
IN AL,DX
SUB DX,1AH ;Attribute address register. 3C0h
XOR AL,AL ; Turn bit 5 off; palette address
OUT DX,AL ; source.
MOV BLANK_TYPE,EGA_VGA
JMP SHORT BLANK_END
CGA_OR_MONO: CLI
MOV BLANK_TYPE,CGA_MONO
MOV DX,ES:[ADDR_6845]
ADD DX,4 ;Control register.
MOV AL,ES:[CRT_MODE_SET] ;Get current setting.
AND AL,NOT VIDEO_SIGNAL ;Turn off video bit.
OUT DX,AL
MOV ES:[CRT_MODE_SET],AL ;Save this setting.
CMP BYTE PTR ES:[CRT_MODE],3 ;Text?
JA BLANK_END
MOV AL,ES:[CRT_PALETTE]
MOV SAVE_PALETTE,AL
INC DX ;Color select register.
AND AL,NOT 1111B ;Turn off border.
OUT DX,AL
BLANK_END: STI
POP DX
POP CX
POP BX
POP ES
RET
;----------------------------------------------;
UNBLANK: MOV UNBLANK_IT,OFF ;Turn off unblank request.
MOV BLANK_SCREEN,OFF
MOV AX,TIME_OUT
MOV COUNTER,AX
STI
PUSH ES
PUSH DX
CMP BLANK_TYPE,SOFTWARE
JZ UNBLANK_SOFT
CMP BLANK_TYPE,CGA_MONO
JZ UNBLANK_CGA
CLI
MOV DX,3BAH ;Ega, Vga unblank.
IN AL,DX ;Initialize address register.
ADD DX,20H
IN AL,DX
SUB DX,1AH
MOV AL,100000B ;Enable video signal.
OUT DX,AL
JMP SHORT UNBLANK_END
UNBLANK_CGA: MOV AX,40H
MOV ES,AX
MOV DX,ES:[ADDR_6845]
ADD DX,4
CLI
MOV AL,ES:[CRT_MODE_SET]
OR AL,VIDEO_SIGNAL ;Enable video signal.
OUT DX,AL
MOV ES:[CRT_MODE_SET],AL
CMP ES:BYTE PTR ES:[CRT_MODE],3
JA UNBLANK_END
MOV AL,SAVE_PALETTE
INC DX
OUT DX,AL ;Enable border.
JMP SHORT UNBLANK_END
UNBLANK_SOFT: CALL RESTORE_SCREEN
UNBLANK_END: STI
POP DX
POP ES
RET
;----------------------------------------------;
BLANK_MODE: CMP BLANK_TYPE,SOFTWARE
JZ BOUNCE_BALL
JMP BLANK
;----------------------------------------------;
SOFT_CODE LABEL BYTE
COUNT DW ?
PAUSE_CNT DW ?
OLD_X DW 0
X_POS DW 0
Y_POS DW 0
DELTA_X DB 56
DELTA_Y DB 56
X_DIR DW +1
Y_DIR DW +1
ERROR_TERM DB 0
SPIN_DIR DB +1
X_MAX EQU 319 - 7
Y_MAX EQU 199 - 6
SPIN_MIN EQU 6
SPIN_MAX EQU 106
BALL DB 00000000B, 00000000B, 00000000B, 00000000B
BALL_START LABEL BYTE
BALL_WIDTH EQU $ - BALL
DB 00000001B, 01010100B, 00000000B, 00000000B
DB 00000101B, 01010101B, 00000000B, 00000000B
DB 00010101B, 01010101B, 01000000B, 00000000B
DB 00010101B, 01010101B, 01000000B, 00000000B
DB 00000101B, 01010101B, 00000000B, 00000000B
DB 00000001B, 01010100B, 00000000B, 00000000B
BALL_END LABEL BYTE
BALL_IMAGE EQU $ - BALL_START
DB 00000000B, 00000000B, 00000000B, 00000000B
BALL_LEN EQU $ - BALL
BOUNCE_BALL: STI
PUSH ES
PUSH BX
PUSH CX
PUSH DX
PUSH SI
PUSH DI
MOV AX,CS
MOV ES,AX
; Bresenham's line drawing algorithm.
MOV BX,X_POS
MOV DX,Y_POS
MOV CL,ERROR_TERM
MOV AH,DELTA_X
MOV AL,DELTA_Y
CMP AH,AL
JB STEEP
ADD BX,X_DIR
JNS CK_X_MAX
INC BX
INC BX
JMP SHORT NEG_X_DIR
CK_X_MAX: CMP BX,X_MAX
JB STORE_X
DEC BX
DEC BX
NEG_X_DIR: NEG X_DIR
CALL SPIN
STORE_X: MOV X_POS,BX
ADD CL,AL
MOV CH,AH
SHR CH,1
CMP CL,CH
JBE SAVE_ERROR
SUB CL,AH
ADD DX,Y_DIR
JNS CK_Y_MAX
INC DX
INC DX
JMP SHORT NEG_Y_DIR
CK_Y_MAX: CMP DX,Y_MAX
JB STORE_Y
DEC DX
DEC DX
NEG_Y_DIR: NEG Y_DIR
CALL SPIN
STORE_Y: MOV Y_POS,DX
SAVE_ERROR: MOV ERROR_TERM,CL
JMP SHORT CALC_POS
;----------------;
STEEP: ADD DX,Y_DIR
JNS CK_Y_MAX2
INC DX
INC DX
JMP SHORT NEG_Y_DIR2
CK_Y_MAX2: CMP DX,Y_MAX
JB STORE_Y2
DEC DX
DEC DX
NEG_Y_DIR2: NEG Y_DIR
CALL SPIN
STORE_Y2: MOV Y_POS,DX
ADD CL,AH
MOV CH,AL
SHR CH,1
CMP CL,CH
JBE SAVE_ERROR2
SUB CL,AL
ADD BX,X_DIR
JNS CK_X_MAX2
INC BX
INC BX
JMP SHORT NEG_X_DIR2
CK_X_MAX2: CMP BX,X_MAX
JB STORE_X2
DEC BX
DEC BX
NEG_X_DIR2: NEG X_DIR
CALL SPIN
STORE_X2: MOV X_POS,BX
SAVE_ERROR2: MOV ERROR_TERM,CL
;----------------;
CALC_POS: XOR DI,DI
MOV CX,DX
SHR CX,1
JCXZ DO_Y
NEXT_X: ADD DI,80 ;Row address.
LOOP NEXT_X
DO_Y: MOV AX,BX
AND AX,NOT 3
SHR AX,1
SHR AX,1
ADD AX,DI ;Column address.
CMP BX,OLD_X ;Did column move?
MOV OLD_X,BX
JZ MOVE_BALL
CMP X_DIR,+1 ;Direction of move.
JNZ REVERSE
MOV SI,OFFSET BALL_START
MOV BX,BALL_IMAGE - BALL_WIDTH
NEXT_ROTATE: SHR BYTE PTR [SI+BX],1 ;Shift two pixels right.
RCR BYTE PTR [SI+BX+1],1
RCR BYTE PTR [SI+BX+2],1
RCR BYTE PTR [SI+BX+3],1
SHR BYTE PTR [SI+BX],1
RCR BYTE PTR [SI+BX+1],1
RCR BYTE PTR [SI+BX+2],1
RCR BYTE PTR [SI+BX+3],1
SUB BX,BALL_WIDTH
JNC NEXT_ROTATE
TEST X_POS,3 ;MOD 4 move pixels back a word.
JNZ MOVE_BALL
MOV DI,SI
INC SI
MOV CX,BALL_IMAGE
REP MOVSB
JMP SHORT MOVE_BALL
REVERSE: AND BX,3 ;MOD 4, copy first.
CMP BX,3
JNZ SHIFT_REVERSE
MOV DI,OFFSET BALL_END - 1
MOV SI,DI
DEC SI
STD
MOV CX,BALL_IMAGE
REP MOVSB
CLD
SHIFT_REVERSE: MOV SI,OFFSET BALL_START
MOV BX,BALL_IMAGE - BALL_WIDTH
NEXT_REVERSE: SHL BYTE PTR [SI+BX+3],1
RCL BYTE PTR [SI+BX+2],1 ;Shift two pixels left.
RCL BYTE PTR [SI+BX+1],1
RCL BYTE PTR [SI+BX],1
SHL BYTE PTR [SI+BX+3],1
RCL BYTE PTR [SI+BX+2],1
RCL BYTE PTR [SI+BX+1],1
RCL BYTE PTR [SI+BX],1
SUB BX,BALL_WIDTH
JNC NEXT_REVERSE
MOVE_BALL: MOV BX,AX ;Screen offset.
MOV SI,OFFSET BALL
MOV AX,0B800H ;Screen segment.
MOV ES,AX
MOV DI,BX
TEST DX,1 ;Odd?
JZ INTERLACE
ADD DI,2000H
INTERLACE: MOV CX,BALL_LEN / BALL_WIDTH / 2
NEXT_LACE: MOVSW
MOVSW
ADD SI,BALL_WIDTH
ADD DI,80 - BALL_WIDTH
LOOP NEXT_LACE
MOV SI,OFFSET BALL + BALL_WIDTH
MOV DI,BX
ADD DI,2000H
TEST DX,1
JZ INTERLACE2
SUB DI,2000H - 80
INTERLACE2: MOV CX,BALL_LEN / BALL_WIDTH / 2
NEXT_LACE2: MOVSW
MOVSW
ADD SI,BALL_WIDTH
ADD DI,80 - BALL_WIDTH
LOOP NEXT_LACE2
POP DI
POP SI
POP DX
POP CX
POP BX
POP ES
MOV AX,PAUSE_CNT ;Reset pause.
MOV COUNT,AX
NEXT_PAUSE: CMP UNBLANK_IT,ON ;If unblank request, exit.
JZ BLANK_MODE_END
DEC COUNT
JNZ NEXT_PAUSE
JMP BOUNCE_BALL
BLANK_MODE_END:RET
;----------------------------------------------;
SPIN: MOV CH,AH ;Delta x - delta y.
SUB CH,AL
ADD AH,SPIN_DIR ;Change delta x and y.
SUB AL,SPIN_DIR
CMP AH,SPIN_MIN ;Check bounds.
JA CK_SPIN
INC AH
INC AH
DEC AL
DEC AL
JMP SHORT NEG_SPIN
CK_SPIN: CMP AH,SPIN_MAX
JB STORE_SPIN
DEC AH
DEC AH
INC AL
INC AL
NEG_SPIN: NEG SPIN_DIR ;Reverse direction.
STORE_SPIN: MOV DELTA_X,AH
MOV DELTA_Y,AL
PUSH AX
SUB AH,AL ;Get difference and adjust
SUB CH,AH
ADD CL,CH ; error term.
POP AX
RET
;----------------------------------------------;
SAVE_SCREEN: PUSH DS
PUSH SI
PUSH DI
XOR BH,BH
MOV AH,3 ;Get cursor mode and save.
INT 10H
MOV CURSOR_MODE,CX
CALL GET_CUR_ADDR
CALL VIDEO_SETUP
MOV AL,ES:[CRT_MODE] ;Save video mode.
MOV SAVE_MODE,AL
MOV AX,ES:[CURSOR_POSN] ;Cursor position.
MOV CURSOR_POS,AX
MOV DS,CX ;Video segment.
PUSH CS
POP ES
XOR SI,SI
MOV DI,OFFSET VIDEO_BUFFER
CALL DO_SCREEN ;Save screen contents.
MOV AX,4 ;CGA graphics video mode.
INT 10H
POP DI
POP SI
POP DS
RET
;----------------------------------------------;
RESTORE_SCREEN:PUSH SI
PUSH DI
PUSH BX
PUSH CX
MOV AL,SAVE_MODE ;Restore video mode.
XOR AH,AH
INT 10H
XOR BH,BH ;Cursor position.
MOV DX,CURSOR_POS
MOV AH,2
INT 10H
MOV CX,CURSOR_MODE ;Cursor type.
MOV AH,1
INT 10H
MOV AX,40H
MOV ES,AX
MOV DX,ES:[ADDR_6845] ;Recover CRTC base address
MOV CX,CURSOR_ADDR ;Also, program registers
MOV AL,14 ; to cursor address for 1-2-3.
OUT DX,AL
INC DX
MOV AL,CH
OUT DX,AL
DEC DX
MOV AL,15
OUT DX,AL
INC DX
MOV AL,CL
OUT DX,AL
CALL VIDEO_SETUP
MOV ES,CX
MOV SI,OFFSET VIDEO_BUFFER
XOR DI,DI
CALL DO_SCREEN ;Restore screen contents.
POP CX
POP BX
POP DI
POP SI
RET
;----------------------------------------------;
DO_SCREEN: MOV CX,80 * 25
HORZ_RET: IN AL,DX ;Get status.
RCR AL,1 ;Is it low?
JC HORZ_RET ;If not, wait until it is.
CLI ;No more interrupts.
HWAIT: IN AL,DX ;Get status.
RCR AL,1 ;Is it high?
JNC HWAIT ;If no, wait until it is.
MOVSW
STI ;Interrupts back on.
LOOP HORZ_RET
RET ;Return
;----------------------------------------------;
GET_CUR_ADDR: MOV AX,40H
MOV ES,AX
MOV DX,ES:[ADDR_6845]
MOV AL,14
CLI
OUT DX,AL
INC DX
IN AL,DX
MOV AH,AL
DEC DX
MOV AL,15
OUT DX,AL
INC DX
IN AL,DX
STI
MOV CURSOR_ADDR,AX ;Cursor address.
RET
;----------------------------------------------;
; OUTPUT: DX = Status register; CX = Video segment. ES -> BIOS data area.
VIDEO_SETUP: MOV AX,40H
MOV ES,AX
MOV DX,ES:[ADDR_6845]
ADD DX,6
MOV CX,0B000H
CMP DL,0BAH ;Mono?
JZ SETUP_END
ADD CH,8
SETUP_END: RET
;**********************************************;
; End of resident code. ;
;**********************************************;
VIDEO_SIZE EQU 80 * 2 * 25
VIDEO_BUFFER LABEL BYTE
SOFT_STUFF EQU $ - SOFT_CODE + VIDEO_SIZE
RESIDENT_END DW SOFT_CODE
SYNTAX DB "Syntax: Conceal [/P password] [filespec] [options]",CR,LF
DB "/S = Conceal filespec attribute [ON | OFF]; default = ON",CR,LF
DB "/F = File security toggle [ON | OFF]; default is ON",CR,LF
DB "/A = Attribute [+|-A] [+|-S] [+|-H] [+|-R]",CR,LF
DB "/N = New password",CR,LF
DB "/B = Hardware blank [nn][ON | OFF]",CR,LF
DB "/G = Graphic blank [nn][ON | OFF]",CR,LF
DB " nn = 0 - 60 minutes; 0 = OFF; default = 3 minutes, ON",CR,LF
DB "/O = Over-graphics blanking [ON | OFF]; default = ON",CR,LF
DB "/T = Password required to unblank [ON | OFF]; default = ON",CR,LF
DB "/H = Hotkey for immediate blank; Ctrl or Alt plus new hotkey",CR,LF
DB " eg. /H Ctrl Y or /H Alt 1; default is Alt Z",CR,LF
DB "/U = Uninstall",CR,LF,LF,"$"
NOT_INSTALLED DB "Conceal not installed",CR,LF,"$"
UNLOAD_MSG DB "Conceal can't be uninstalled",CR,LF
DB "Uninstall resident programs in reverse order",CR,LF
DB "Conceal and blank mode has been turn off.",CR,LF,"$"
NOT_ENOUGH DB "Not enough memory to install Conceal",CR,LF,"$"
ALLOCATE_MSG DB "Memory allocation error",CR,LF,BELL,"$"
INSTALL_MSG DB CR,LF,"Conceal installed",CR,LF,"$"
UNINSTALL_MSG DB CR,LF,"Conceal uninstalled",CR,LF,"$"
INVALID_MSG DB "Invalid syntax",CR,LF,"$"
PASS_MSG DB "Invalid password; Access denied",BELL,CR,LF,"$"
BUFFER_MSG DB "Can't allocate memory for Graphics blank once installed.",CR,LF
DB "/U(ninstall) and then reinstall with /G(raphics).",CR,LF,"$"
PERM_MSG DB "Make new password permanent? Y/N $"
HOTKEY_MSG DB "Press $"
HOTKEY_MSG2 DB " to immediately blank screen."
CR_LF DB CR,LF,"$"
WRONG_VERSION DB "Needs DOS 2.0 or later$"
CONCEAL_COM DB "CONCEAL.COM",0
CONCEAL_LEN EQU $ - CONCEAL_COM
NOT_FOUND DB "Could not find Conceal.com",CR,LF
DB "Conceal.com must be in current directory",CR,LF
DB "or in DOS PATH= directory.",CR,LF,"$"
PATH DB "PATH="
PATH_LEN EQU $ - PATH
WORKSPACE DB 65 DUP (?)
ATTR_DTA DB SIZE MATCHING DUP (?)
PATH_END DW ?
NO_FILE DB "File not found",CR,LF,"$"
SCAN_CODES LABEL BYTE
DB "1",2,"2",3,"3",4,"4",5,"5",6,"6",7,"7",8,"8",9,"9",0AH,"0",0BH,"-",0CH
DB "=",0DH,"Q",10H,"W",11H,"E",12H,"R",13H,"T",14H,"Y",15H,"U",16H,"I",17H
DB "O",18H,"P",19H,"[",1AH,"]",1BH,"A",1EH,"S",1FH,"D",20H,"F",21H,"G",22H
DB "H",23H,"J",24H,"K",25H,"L",26H,";",27H,39,28H,96,29H,"\",2BH,"Z",2CH
DB "X",2DH,"C",2EH,"V",2FH,"B",30H,"N",31H,"M",32H,",",33H,".",34H,"/",35H
SCAN_COUNT EQU ($ - SCAN_CODES) / 2
TSR_SEGMENT DW ?
SYNTAX_FLAG DB 0 ; = 1 if syntax to be displayed.
INSTALL_FLAG DB 0 ; = 1 if should install.
PASS_FLAG DB 0 ; = 1 if correct password.
COM_FILESPEC DW 0 ; non-zero if filespec found.
AND_BITS DB ? ;Attributes.
OR_BITS DB ?
CONCEALED DB TAB,"Concealed",CR,LF,"$"
UNCONCEALED DB TAB,"Unconcealed",CR,LF,"$"
ALT DB " Alt $"
CTRL DB "Ctrl $"
ALT_CAPS DB "ALT"
CTRL_CAPS DB "CTRL"
SPACES DB 9 DUP (SPACE), "$"
ATTR_NAMES DB "Archive $System $Hidden $Read-Only$"
OPTIONS DB "PSFANBGOTHU"
OPTIONS_LEN EQU $ - OPTIONS
OPTIONS_CALLS DW PASS, CONCEAL, FILE_CONCEAL, ATTR, NEW_PASS, HARD, SOFT
DW DONT_BLANK, CONCEAL_BLANK, CHANGE_HOT, UNINSTALL
OPTIONS_END EQU $ - 2
;----------------------------------------------;
INITIALIZE PROC NEAR
CLD ;All string operations forward.
MOV DX,OFFSET ATTR_DTA ;Set up DTA.
MOV AH,1AH
INT 21H
MOV BX,OFFSET SIGNATURE ;Point to start of code.
NOT BYTE PTR [BX] ;Change a byte so no false match.
MOV AX,CS ;Store our segment in AX.
MOV DX,0A000H - 1
NEXT_PARAG: INC DX ;Next paragraph.
MOV ES,DX
CMP DX,AX ;Is it our segment?
JZ ANNOUNCE ;If yes, search is done.
MOV SI,BX ;Else, point to our signature.
MOV DI,BX ; and offset of possible match.
MOV CX,16 ;Check 16 bytes for match.
REP CMPSB
JNZ NEXT_PARAG ;If no match, keep looking.
;----------------------------------------------;
ANNOUNCE: MOV TSR_SEGMENT,ES
MOV DX,OFFSET SIGNATURE + 1 ;Display our signature.
CALL PRINT_STRING
MOV SI,81H ;Point to command line.
NEXT_CAP: LODSB ;Capitalize parameters.
CMP AL,CR
JZ PARSE
CMP AL,"a"
JB NEXT_CAP
CMP AL,"z"
JA NEXT_CAP
AND BYTE PTR [SI - 1],5FH
JMP SHORT NEXT_CAP
;----------------------------------------------;
PARSE: MOV SI,81H ;Point to command line again.
NEXT_PARSE: CALL FIND_START
LODSB
CMP AL,CR
JZ CK_INSTALL
CMP AL,"/"
JNZ FOUND_FILESPEC
MOV SYNTAX_FLAG,1 ;Parameter found; no need to
LODSB ; display syntax, unless error
PUSH CS ; found.
POP ES
MOV DI,OFFSET OPTIONS
MOV CX,OPTIONS_LEN ;Command line options.
REPNZ SCASB
MOV DX,OFFSET INVALID_MSG ;Exit if invalid.
JNZ MSG_EXIT
CALL FIND_START
SHL CX,1
MOV DI,OFFSET OPTIONS_END
SUB DI,CX
CALL [DI] ;Process option.
JMP NEXT_PARSE
FOUND_FILESPEC:DEC SI ;If not "/", then gotta be
MOV COM_FILESPEC,SI ; filespec.
CALL FIND_END
JMP NEXT_PARSE
;-------------------------------------------------------------------;
; Exit. Return ERRORLEVEL code 0 if successful, 1 if unsuccessful. ;
;-------------------------------------------------------------------;
MSG_EXIT: PUSH DX
MOV DX,OFFSET SYNTAX ;Display syntax if error.
CALL PRINT_STRING
POP DX ;Display error.
CALL PRINT_STRING
ERROR_EXIT: MOV AL,1 ;ERRORLEVEL = 1.
JMP SHORT TERMINATE
GOOD_EXIT: CMP SYNTAX_FLAG,1
JZ DO_HOT
MOV DX,OFFSET SYNTAX ;And syntax.
CALL PRINT_STRING
DO_HOT: CALL DISP_HOTKEY ;Display hot key if blank active.
XOR AL,AL ;ERRORLEVEL = 0.
TERMINATE: MOV AH,4CH ;Terminate.
INT 21H
;----------------------------------------------;
CK_INSTALL: CMP INSTALL_FLAG,1 ;Function requiring installation
JNZ GOOD_EXIT ; selected?
CALL CK_INSTALLED ;Are we already installed?
JNZ GOOD_EXIT
;----------------------------------------------;
CK_AVAILABLE: PUSH CS
POP ES
MOV AH,49H
INT 21H
MOV BX,0FFFFH
MOV AH,4AH
INT 21H
MOV AX,RESIDENT_END
ADD AX,15 ;Round up.
MOV CL,4
SHR AX,CL ;Convert to paragraphs.
CMP BX,AX
JAE GET_VERSION
MOV DX,OFFSET NOT_ENOUGH ;Exit if not enough
JMP MSG_EXIT ; with message.
GET_VERSION: MOV AH,30H ;Get DOS version
INT 21H
CMP AL,2
JAE GET_VECTORS
MOV DX,OFFSET WRONG_VERSION ;If not DOS 2 or above, exit.
JMP MSG_EXIT
GET_VECTORS: MOV AX,3508H ;INT 8
INT 21H
MOV OLD8[0],BX
MOV OLD8[2],ES
MOV DX,OFFSET TIMER ;Install new interrupt.
MOV AX,2508H
INT 21H
CALL SETUP_TIME ;Pause count for software blank.
MOV AX,3521H ;Get INT 21 interrupt.
INT 21H
MOV OLD21[0],BX ;Save old interrupt.
MOV OLD21[2],ES
MOV DX,OFFSET DOS ;Install new interrupt.
MOV AX,2521H
INT 21H
MOV AX,3509H ;Get INT 9 vector.
INT 21H
MOV OLD9[0],BX ;Save old interrupt.
MOV OLD9[2],ES
MOV DX,OFFSET KEYBOARD ;Install new interrupt.
MOV AX,2509H
INT 21H
MOV AX,DS:[2CH] ;Get environment segment.
MOV ES,AX
MOV AH,49H ;Free up environment.
INT 21H
MOV DX,OFFSET INSTALL_MSG ;Display install message.
CALL PRINT_STRING
CALL DISP_HOTKEY
MOV DX,RESIDENT_END
ADD DX,15 ;Round up.
MOV CL,4
SHR DX,CL ;Convert to paragraphs.
MOV AX,3100H ;Return error code of zero.
INT 21H ;Terminate but stay resident.
;----------------------------------------------;
SETUP_TIME: PUSH WORD PTR BLANK_FLAG
MOV BLANK_FLAG,ON
XOR CX,CX
MOV AX,COUNTER
GET_START: MOV BX,COUNTER ;Wait till start of a count.
CMP BX,AX
JZ GET_START
GET_TIME: INC CX ;Get loops for one tick.
MOV AX,COUNTER
CMP AX,BX
JZ GET_TIME
SHR CX,1 ;Adjust for delay loop.
SHR CX,1
SHR CX,1
SHR CX,1
MOV COUNT,CX
MOV PAUSE_CNT,CX
POP WORD PTR BLANK_FLAG
RET
;----------------------------------------------;
PASS: MOV DX,SI
MOV ES,TSR_SEGMENT
MOV AH,PASS_CODE
MOV CX,ES:PASS_CNT
NEXT_PASS: LODSB ;Get password.
CMP AL,SPACE
JBE DECODE2
CMP AL,"/"
JZ DECODE2
XOR [SI-1],AH
INC AH
LOOP NEXT_PASS
JMP SHORT DECODE3
DECODE2: DEC SI
DECODE3: PUSH SI
MOV SI,DX
MOV DI,OFFSET PASSWORD
MOV CX,ES:PASS_CNT
REPZ CMPSB ;Does it match?
JNZ BAD_PASS
LODSB
CMP AL,SPACE
JBE PASS_END
CMP AL,"/"
JZ PASS_END
BAD_PASS: MOV DX,OFFSET PASS_MSG
JMP MSG_EXIT
PASS_END: MOV PASS_FLAG,1 ;Password valid.
POP SI
RET
;----------------------------------------------;
CONCEAL: MOV ES,TSR_SEGMENT
CALL CK_ON_OFF ;Check for ON or OFF.
MOV BP,ES:CONCEAL_FLAG
MOV ES:CONCEAL_FLAG,OFF ;OFF so attributes can change.
MOV AND_BITS,4 ;System attribute.
MOV OR_BITS,0
CMP BL,OFF ;Turn it off?
JZ CONCEAL_PASS ;If yes, need password.
MOV AND_BITS,0
MOV OR_BITS,4 ;System attribute ON.
MOV BP,BX
MOV INSTALL_FLAG,1 ;Need to install.
JMP SHORT CK_FILESPEC
CONCEAL_PASS: CALL CK_PASSWORD
CK_FILESPEC: MOV DX,COM_FILESPEC ;Filespec?
OR DX,DX
JZ SAVE_CONCEAL ;If no, just set security state.
PUSH SI
MOV CHANGE_FLAG,ON ;Make a change to attributes.
MOV STATS_FLAG,CONCEAL_STATS ;Display secure message.
CALL ATTRIBUTES
CONCEAL_END: MOV ES,TSR_SEGMENT
MOV ES:CONCEAL_FLAG,BP ;Restore security state.
POP SI
RET
;----------------------------------------------;
FILE_CONCEAL: MOV ES,TSR_SEGMENT
CALL CK_ON_OFF
CMP BL,ON
JZ SAVE_CONCEAL
CALL CK_PASSWORD
SAVE_CONCEAL: MOV ES,TSR_SEGMENT
MOV ES:CONCEAL_FLAG,BX ;New security state; ON or OFF.
CMP BL,ON
JNZ FILE_END
MOV INSTALL_FLAG,1 ;Install if ON.
FILE_END: RET
;----------------------------------------------;
ATTRIBUTES: PUSH CS
POP ES
MOV DI,OFFSET WORKSPACE ;Find delimiters in filespec.
MOV PATH_END,DI
MOV DX,COM_FILESPEC
MOV SI,DX
NEXT_ASCII: LODSB
STOSB
CMP AL,SPACE
JBE ASCII_END
CMP AL,"/"
JZ ASCII_END
CMP AL,":"
JZ FOUND_DELIMIT
CMP AL,"\"
JNZ NEXT_ASCII
FOUND_DELIMIT: MOV PATH_END,DI
JMP NEXT_ASCII
ASCII_END: MOV BYTE PTR [SI - 1],0
NOT AND_BITS ;Flip NOT bits.
MOV CX,7H
MOV AH,4EH ;Find first.
INT 21H
JNC DISPLAY_NAME
MOV DX,OFFSET NO_FILE ;Exit if none.
JMP MSG_EXIT
;-----------------------;
DISPLAY_NAME: MOV SI,OFFSET ATTR_DTA.FILE_NAME
MOV DI,PATH_END ;Add filename to path, if any.
MOV CX,14
NEXT_NAME2: LODSB
STOSB
OR AL,AL
JZ PAD_NAME
CALL PRINT_CHAR ;Print name.
LOOP NEXT_NAME2
PAD_NAME: MOV AL,SPACE ;Tab over 14.
CALL PRINT_CHAR
LOOP PAD_NAME
MOV DX,OFFSET WORKSPACE
CMP CHANGE_FLAG,ON ;Change attributes?
JNZ DO_STATS
CHANGE_ATTR: MOV CL,[ATTR_DTA.ATTRIBUTE]
AND CL,AND_BITS ;Turn off some bits.
OR CL,OR_BITS ;Turn on some bits.
XOR CH,CH
MOV AX,4301H ;Change File Mode.
INT 21H
JC ATTRS_END
DO_STATS: CALL DISPLAY_STATS ;Display status message.
MOV AH,4FH ;Find next.
INT 21H
JNC DISPLAY_NAME ;Display it.
ATTRS_END: RET
;----------------------------------------------;
DISPLAY_STATS: CMP STATS_FLAG,CONCEAL_STATS ;Secure stats or attribute stats?
JZ STATS2
STATS1: MOV AX,4300H ;Get attribute.
INT 21H
MOV AL,TAB
CALL PRINT_CHAR
MOV BL,CL
SHL BL,1
SHL BL,1
MOV CX,4 ;Four attributes.
XOR DI,DI
NEXT_STAT: CMP CX,3 ;Skip volume and directory bits.
JNZ GET_BIT
SHL BL,1
SHL BL,1
GET_BIT: MOV DX,OFFSET SPACES ;Assume it's off.
SHL BL,1
JNC DISPLAY_BIT
MOV DX,OFFSET ATTR_NAMES ;Else, display the one that's on.
ADD DX,DI
DISPLAY_BIT: CALL PRINT_STRING
ADD DI,10
LOOP NEXT_STAT
MOV DX,OFFSET CR_LF ;New line.
CALL PRINT_STRING
JMP SHORT STATS_END
STATS2: MOV DX,OFFSET CONCEALED ;Display "Secured" or "Unsecured"
CMP OR_BITS,4
JZ DISP_STATS
MOV DX,OFFSET UNCONCEALED
DISP_STATS: CALL PRINT_STRING
STATS_END: RET
;----------------------------------------------;
PLUS EQU 0
MINUS EQU 1
SIGN_FLAG DB ?
FLAGS DB "ASHR"
FLAGS_LEN EQU $ - FLAGS
FLAGS_BITS DB 20H, 4, 2, 1
FLAGS_END EQU $ - 1
ATTR: MOV CHANGE_FLAG,OFF ;Assume no changes.
MOV SIGN_FLAG,PLUS ;Default is plus.
MOV AND_BITS,0
MOV OR_BITS,0
NEXT_ATTR: CALL FIND_START
LODSB
CMP AL,CR
JBE GOT_ATTR
CMP AL,"/"
JZ GOT_ATTR
CMP AL,"+"
JNZ CK_MINUS
MOV SIGN_FLAG,PLUS
JMP NEXT_ATTR
CK_MINUS: CMP AL,"-"
JNZ CK_FLAGS
MOV SIGN_FLAG,MINUS
JMP NEXT_ATTR
CK_FLAGS: MOV DI,OFFSET FLAGS
MOV CX,FLAGS_LEN
REPNZ SCASB
JZ GOT_FLAG
MOV DX,OFFSET INVALID_MSG
JMP MSG_EXIT
GOT_FLAG: MOV CHANGE_FLAG,ON ;Change attribute.
MOV BX,OFFSET FLAGS_END
SUB BX,CX
MOV AL,[BX]
MOV DI,OFFSET OR_BITS ;Assume plus.
CMP SIGN_FLAG,PLUS
JZ STORE_BIT
MOV DI,OFFSET AND_BITS
STORE_BIT: OR [DI],AL
JMP NEXT_ATTR
GOT_ATTR: DEC SI
PUSH SI
MOV ES,TSR_SEGMENT
PUSH ES:CONCEAL_FLAG
CMP CHANGE_FLAG,ON ;If no changes, don't need
JNZ ATTR_READY ; password.
CMP ES:CONCEAL_FLAG,ON ;Else, if security ON, then
JNZ ATTR_READY ; need password to change
CALL CK_PASSWORD ; attributes.
MOV ES:CONCEAL_FLAG,OFF ;Turn off security temporarily.
ATTR_READY: MOV STATS_FLAG,ATTR_STATS ;Display attribute messages.
CALL ATTRIBUTES
MOV ES,TSR_SEGMENT
POP ES:CONCEAL_FLAG ;Restore security status.
POP SI ;Command line pointer.
RET
;----------------------------------------------;
NEW_PASS: CALL CK_PASSWORD ;Need password to change password
MOV ES,TSR_SEGMENT
PUSH ES:CONCEAL_FLAG
MOV ES:CONCEAL_FLAG,OFF ;Security temporarily OFF.
CMP BYTE PTR [SI],SPACE ;Is there a password?
JA GOT_PASS
JMP NEW_END
GOT_PASS: MOV AH,PASS_CODE
MOV BP,SI ;Start of password.
XOR CX,CX
NEXT_PASS2: LODSB ;Get password.
CMP AL,SPACE
JBE STORE_PASS
CMP AL,"/"
JZ STORE_PASS
XOR BYTE PTR [SI - 1],AH
INC AH
INC CX
JMP NEXT_PASS2
STORE_PASS: DEC SI
PUSH SI
MOV ES:PASS_CNT,CX
MOV SI,BP
MOV DI,OFFSET PASSWORD ;Store new password.
REP MOVSB
;----------------------------------------------;
PUSH CS
POP ES
MOV DX,OFFSET PERM_MSG ;Make change permanent?
CALL PRINT_STRING
MOV AH,1
INT 21H
PUSH AX
MOV DX,OFFSET CR_LF
CALL PRINT_STRING
POP AX
AND AL,5FH
CMP AL,"Y"
JZ GET_VER
JMP NEW_DONE
GET_VER: MOV AH,30H ;Get DOS version.
INT 21H
CMP AL,3 ;Filename in environment
JB TRY_CURRENT ; not support before DOS 3.x.
MOV DS,DS:[2CH] ;Segment of environment.
XOR SI,SI
FIND_ENV_END: LODSB ;Find end of environment.
OR AL,AL
JNZ FIND_ENV_END
LODSB
OR AL,AL
JNZ FIND_ENV_END
INC SI ;Bump pointer past word count.
INC SI
MOV DI,OFFSET WORKSPACE ;Copy our name.
CALL COPY_NAME
PUSH CS
POP DS
MOV DX,OFFSET WORKSPACE ;Try to write answer.
CALL WRITE_ANS
JNC NEW_DONE
TRY_CURRENT: MOV DX,OFFSET CONCEAL_COM ;Try current directory.
CALL WRITE_ANS
JNC NEW_DONE
; See if PATH= is in environment.
MOV DS,DS:[2CH] ;Segment of environment.
LOOK_AT_PATH: MOV BX,-1 ;Offset zero in environment.
NEXT_PATH: INC BX
MOV SI,BX
CMP BYTE PTR [SI],0 ;Terminating null?
JNZ PATH_SEARCH
CMP BYTE PTR [SI+1],0 ;Double null?
JNZ NEXT_PATH
JMP SHORT CANT_SAVE ;If so, end of environment.
PATH_SEARCH: MOV DI,OFFSET PATH ;Search for "PATH=".
MOV CX,PATH_LEN
REP CMPSB
JNZ NEXT_PATH
; PATH= found; search for paths.
NEXT_STRING: CMP BYTE PTR [SI],0 ;Terminating null?
JZ CANT_SAVE
CMP BYTE PTR [SI-1],0 ;Double null?
JZ CANT_SAVE
MOVE_STRING: MOV DI,OFFSET WORKSPACE ;Get path.
NEXT_BYTE: LODSB
OR AL,AL
JZ SEARCH_PATH
CMP AL,";"
JZ SEARCH_PATH
STOSB
JMP NEXT_BYTE
SEARCH_PATH: CALL COPY_PATH ;Create filespec.
PUSH DS
PUSH CS
POP DS
MOV DX,OFFSET WORKSPACE
CALL WRITE_ANS ;Try to write answer.
POP DS
JC NEXT_STRING ;If failed, try next path.
JMP SHORT NEW_DONE ;Else, done.
CANT_SAVE: PUSH CS
POP DS
MOV DX,OFFSET NOT_FOUND ;Answer write error message.
CALL PRINT_STRING
NEW_DONE: POP SI
NEW_END: MOV ES,TSR_SEGMENT
POP ES:CONCEAL_FLAG
RET
;----------------------------------------------;
COPY_NAME: LODSB
STOSB
OR AL,AL
JNZ COPY_NAME
RET
;----------------------------------------------;
COPY_PATH: PUSH SI
PUSH DS
CMP DI,OFFSET WORKSPACE
JZ MOVE_NAME
CMP BYTE PTR ES:[DI-1],"\" ;Filespec delimiter?
JZ MOVE_NAME
CMP BYTE PTR ES:[DI-1],":"
JZ MOVE_NAME
MOV AL,"\" ;If no, add one.
STOSB
MOVE_NAME: PUSH CS
POP DS
MOV SI,OFFSET CONCEAL_COM ;Tack on "CONCEAL.COM".
MOV CX,CONCEAL_LEN
REP MOVSB
COPY_END: POP DS
POP SI
RET
;----------------------------------------------;
; INPUT: DX -> Compute.com filespec.
; OUTPUT: CY=0 if successful; CY=1 if failed.
WRITE_ANS: PUSH SI
MOV AX,3D02H ;Open for reading and writing.
INT 21H
JC WRITE_END
MOV BX,AX
MOV DX,OFFSET WORKSPACE
MOV CX,SIZE WORKSPACE
MOV AH,3FH ;Read signature.
INT 21H
JC WRITE_END
MOV SI,OFFSET SIGNATURE + 1 ;Make sure we found correct
MOV DI,OFFSET WORKSPACE - 100H ; Secure.com.
ADD DI,SI
SUB CX,OFFSET SIGNATURE + 1 - 100H
REP CMPSB
STC
JNZ WRITE_END
XOR CX,CX
MOV DX,OFFSET PASSWORD - 100H
MOV AX,4200H ;Seek offset of new password.
INT 21H
JC WRITE_END
PUSH DS
MOV DS,TSR_SEGMENT
MOV DX,OFFSET PASSWORD
MOV CX,PASSWORD_LEN + SIZE PASS_CNT
MOV AH,40H ;Write answer to disk.
INT 21H
POP DS
JC WRITE_END
MOV AH,3EH ;Close file.
INT 21H
WRITE_END: POP SI
RET
;----------------------------------------------;
CK_PASSWORD: CMP PASS_FLAG,1 ;Correct password on command
JZ CK_PASS_END ; line?
MOV DX,OFFSET PASS_MSG
JMP MSG_EXIT
CK_PASS_END: RET
;----------------------------------------------;
HARD: MOV CH,HARD_BLANK
JMP SHORT GET_BLANK
;----------------------------------------------;
SOFT: MOV CH,SOFT_BLANK
GET_BLANK: MOV ES,TSR_SEGMENT
CMP BYTE PTR [SI],"0" ;Time-out parameter?
JB CK_HARD
CMP BYTE PTR [SI],"9"
JA CK_HARD
LODSB
SUB AL,"0"
MOV BL,AL
LODSB
SUB AL,"0"
JC CK_TIME
CMP AL,9
JA CK_TIME
XCHG BL,AL
MOV BH,10
MUL BH
ADD BL,AL
INC SI
CK_TIME: DEC SI
OR BL,BL ;If no or zero time-out, just
JZ STORE_HARD ; store status.
CMP BL,60 ;60 minute max.
JBE MAKE_TIME
MOV DX,OFFSET INVALID_MSG
JMP MSG_EXIT
MAKE_TIME: MOV AX,1092 ;Convert minutes to timer ticks.
XOR BH,BH
MUL BX
MOV ES:TIME_OUT,AX
MOV ES:COUNTER,AX
CK_HARD: CALL CK_ON_OFF
CMP BL,ON
JZ DO_ON
STORE_HARD: MOV ES:BLANK_FLAG,BL ;Store blank status.
JMP SHORT HARD_END
DO_ON: CMP CH,SOFT_BLANK
JNZ STORE_ON
MOV BUFFER_FLAG,ON ;Graphics buffer required.
ADD RESIDENT_END,SOFT_STUFF
CALL CK_INSTALLED
JZ STORE_ON
CMP ES:BUFFER_FLAG,ON ;Is graphics buffer installed?
JZ STORE_ON
MOV DX,OFFSET BUFFER_MSG ;If no, complain.
JMP MSG_EXIT
STORE_ON: MOV ES:BLANK_FLAG,CH ;Store blank status.
MOV INSTALL_FLAG,1
HARD_END: RET
;----------------------------------------------;
DONT_BLANK: MOV ES,TSR_SEGMENT
CALL CK_ON_OFF
MOV ES:GRAPHIC_APPS,BL ;Store graphics app blank status.
RET
;----------------------------------------------;
CONCEAL_BLANK: MOV ES,TSR_SEGMENT ;Password unblanking status.
CALL CK_ON_OFF
CMP BL,ON
JZ STORE_CONCEAL
CALL CK_PASSWORD
STORE_CONCEAL: MOV ES:UNBLANK_FLAG,BL
RET
;----------------------------------------------;
CHANGE_HOT: MOV BP,TSR_SEGMENT ;Save segment.
MOV DX,CS
CALL FIND_START ;Find start of parameter.
CMP AL,CR
JZ HOT_END
MOV BX,SI
MOV ES,DX
MOV DI,OFFSET ALT_CAPS ;Is it "ALT"?
MOV CX,3
REP CMPSB
JNZ CK_CTRL
MOV ES,BP
MOV ES:HOT_SHIFT_KEY,ALT_STATE
JMP SHORT GET_HOT
CK_CTRL: MOV SI,BX
MOV DI,OFFSET CTRL_CAPS ;Is it "CTRL"?
MOV CX,4
REP CMPSB
JZ GOT_CTRL
MOV SI,BX
JMP SHORT GET_HOT
GOT_CTRL: MOV ES,BP
MOV ES:HOT_SHIFT_KEY,CTRL_STATE
GET_HOT: CALL FIND_START ;Find parameter start.
CMP AL,CR
JZ HOT_END
LODSB
MOV CX,SCAN_COUNT
MOV ES,DX
MOV DI,OFFSET SCAN_CODES
NEXT_HOT: SCASB ;Look up hotkey.
JZ FOUND_HOT
INC DI
LOOP NEXT_HOT
JMP SHORT HOT_END
FOUND_HOT: MOV AH,[DI]
MOV ES,BP
MOV ES:COMBO,AL ;Store hotkey ASCII
MOV ES:HOT_KEY_SCAN,AH ; and scan code.
HOT_END: RET
;---------------------------------------------------;
; This subroutine uninstalls the resident TSR. ;
;---------------------------------------------------;
UNINSTALL: CALL CK_INSTALLED ;Are we installed?
JNZ DO_VECTORS
MOV DX,OFFSET NOT_INSTALLED
JMP MSG_EXIT
DO_VECTORS: MOV CX,AX ;Save segment in CX.
MOV ES,AX
CMP ES:UNBLANK_FLAG,ON ;Password required to unblank?
JZ UN_PASS
CMP ES:CONCEAL_FLAG,OFF ;Security ON ?
JZ VARS_OFF
UN_PASS: CALL CK_PASSWORD
VARS_OFF: MOV ES:BLANK_FLAG,OFF ;Turn OFF in case can't uninstall
MOV ES:CONCEAL_FLAG,OFF
MOV AX,3508H ;Get interrupt 8h.
INT 21H
CMP BX,OFFSET TIMER ;Has it been hooked by another?
JNZ UNINSTALL_ERR ;If yes, exit with error message.
MOV BX,ES
CMP BX,CX ;Is the segment vector same?
JNZ UNINSTALL_ERR ;If no, exit with error message.
MOV AX,3521H ;Get interrupt 21h.
INT 21H
CMP BX,OFFSET DOS ;Has it been hooked by another?
JNZ UNINSTALL_ERR ;If yes, exit with error message.
MOV BX,ES
CMP BX,CX ;Is the segment vector same?
JNZ UNINSTALL_ERR ;If no, exit with error message.
MOV AX,3509H ;Get interrupt 9h.
INT 21H
CMP BX,OFFSET KEYBOARD ;Has it been hooked by another?
JNZ UNINSTALL_ERR ;If yes, exit with error message.
MOV BX,ES
CMP BX,CX ;Is the segment vector same?
JZ RESTORE_VECTOR ;If no, exit with error message.
UNINSTALL_ERR: MOV DX,OFFSET UNLOAD_MSG ;And exit with error message.
LILLY_ERR: JMP MSG_EXIT
RESTORE_VECTOR:MOV DX,ES:OLD9[0] ;Restore old INT 9.
MOV DS,ES:OLD9[2]
MOV AX,2509H
INT 21H
MOV DX,ES:OLD8[0] ;Restore old INT 8.
MOV DS,ES:OLD8[2]
MOV AX,2508H
INT 21H
MOV DX,ES:OLD21[0] ;Restore old INT 21.
MOV DS,ES:OLD21[2]
MOV AX,2521H
INT 21H
DEALLOCATE: MOV AH,49H ;Return memory to system pool.
INT 21H
PUSH CS
POP DS
MOV DX,OFFSET ALLOCATE_MSG
JC LILLY_ERR ;Display message if problem.
MOV DX,OFFSET UNINSTALL_MSG ;Display uninstall message.
CALL PRINT_STRING
JMP GOOD_EXIT
;----------------------------------------------;
; OUTPUT: BX = ON or OFF. If neither found, BL = ON.
CK_ON_OFF: CALL FIND_START
PUSH SI
MOV BX,ON ;Assume ON.
LODSB
CMP AL,"O"
JNZ ON_OFF_DONE
ADD SP,2
LODSB
CMP AL,"N"
JZ ON_OFF_END
CMP AL,"F"
JNZ ON_OFF_ERR
LODSB
CMP AL,"F"
JNZ ON_OFF_ERR
MOV BX,OFF
JMP SHORT ON_OFF_END
ON_OFF_DONE: POP SI
ON_OFF_END: RET
ON_OFF_ERR: MOV DX,OFFSET INVALID_MSG
JMP MSG_EXIT
;-------------------------------------------------------;
; OUTPUT: ZR = 1 if not installed; ZR = 0 if installed. ;
CK_INSTALLED: MOV AX,TSR_SEGMENT
MOV BX,CS
CMP AX,BX ;Compare segments.
RET
;----------------------------------------------;
FIND_START: LODSB
CMP AL,CR
JZ START_END
CMP AL,SPACE
JBE FIND_START
START_END: DEC SI
RET
;----------------------------------------------;
FIND_END: LODSB
CMP AL,CR
JZ END_END
CMP AL,"/"
JZ END_END
CMP AL,SPACE
JA FIND_END
END_END: DEC SI
RET
;----------------------------------------------;
DISP_HOTKEY: MOV ES,TSR_SEGMENT
CMP ES:BLANK_FLAG,OFF ;Blank status active?
JZ HOTKEY_END
PUSH DS
MOV DX,OFFSET HOTKEY_MSG ;Display hotkey message.
CALL PRINT_STRING
MOV DS,TSR_SEGMENT
MOV BL,COMBO
MOV DX,OFFSET ALT
CMP HOT_SHIFT_KEY,ALT_STATE
JZ DISP_STATE
MOV DX,OFFSET CTRL
DISP_STATE: POP DS
CALL PRINT_STRING ;And current hotkey.
MOV DL,BL
MOV AH,2
INT 21H
MOV DX,OFFSET HOTKEY_MSG2
CALL PRINT_STRING
HOTKEY_END: RET
;----------------------------------------------;
PRINT_CHAR: MOV DL,AL
MOV AH,2 ;Print character via DOS.
JMP SHORT DOS_INT
PRINT_STRING: MOV AH,9 ;Print string via DOS.
DOS_INT: INT 21H
RET
INITIALIZE ENDP
_TEXT ENDS
END START