LOCKOUT.ASM  ·  ASM  ·  8.3 KB  ·  1987-09-24  ·  from Compute-PC-Magazine-Disk_January-1988_Volume-2_No.1_Issue-3
        ;  Program: lockup.com
        ;
        ;  Author: Paul W. Carlson
        ;
        cseg	segment	para	public	'CODE'
        	assume	cs:cseg
        	org		100h
        begin:	jmp	init
        ;
        lkey	db	38			;scan code for L key
	adapt	db	0			;0 = CGA, 1 = MDA
        onflag	db	0			;busy flag
	vmode	db	0			;video mode
	dmode	db	0			;message display mode
	pal     db      0
        vpage	db	0			;video page
	bufsiz	dw	0			;video buffer size
	vidseg	dw	0			;video segment
	curpos	dw	0			;cursor position
        curmod	dw	0			;cursor mode
	envals	db	2ch,28h,2dh,29h,2ah,2eh,1eh
	messag	db	'C',135,'O',135,'M',135,'P',135,'U',135
		db	'T',135,'E',135,'R',135,' ',135,'I',135
		db	'S',135,' ',135,'I',135,'N',135,' ',135
		db	'U',135,'S',135,'E',135
        oldint	label	dword			;old interrupt vector
        oldvec	dw	2	dup (0)
	buffer	dw	offset init
        ;
        kbint	proc	near
        	cmp	onflag,0	;are we holding?
        	jne	leave		;yes, exit
        	sti			;enable interrupts
        	push	ax		;save registers
        	push	bx
        	push	cx
        	push	dx
        	push	si
        	push	di
        	push	ds
        	push	es
        	in	al,60h		;get keyboard scan code
        	cmp	al,lkey		;was the 'L' key pressed?
        	jne	exit		;no, exit
        	mov	ah,2		;get shift key status
        	int	16h		;BIOS does it
        	and	al,8		;is the Alt key depressed?
        	jne	gotit		;yes, continue
        exit:	pop	es		;no, restore registersand exit
        	pop	ds
        	pop	di
        	pop	si
        	pop	dx
        	pop	cx
        	pop	bx
        	pop	ax
        leave:	jmp	oldint		;exit to BIOS routine
        gotit:	call	kreset		;reset keyboard and send EOI
        	push	cs		;ds and es = cs
        	pop	ds
        	push	cs
        	pop	es
        	assume	ds:cseg
        	mov	ah,15		;get video mode and page
        	int	10h		;BIOS does it
		cmp	al,8		;is mode < 8 ?
		jb	modeok		;yes, mode ok
        done:	pop	es		;no, restore registers and exit
        	pop	ds
        	pop	di
        	pop	si
        	pop	dx
        	pop	cx
        	pop	bx
        	pop	ax
        	iret			;return from interrupt
	modeok:	mov	vmode,al	;save video mode
        	push 	es
                mov 	ax,40h
                mov 	es,ax
                mov 	al,es:[66h]
                mov 	pal,al
                pop 	es
		mov	vpage,bh	;save video page
                mov	onflag,1	;set flag to on
        	mov	ah,3		;get the cursor shape
        	int	10h		;BIOS does it
        	mov	curmod,cx	;save it
		mov	curpos,dx	;save cursor position
		cmp	adapt,0		;CGA?
		jne	sscrn		;no
        	call	discga		;disable CGA video
       sscrn: 	call	savscr		;save screen contents
        	call	dismes		;display the message
		cmp	adapt,0		;CGA?
		jne	getkey		;no
        	call	enacga		;enable CGA video
	getkey:	mov	ah,0		;wait for keypress
		int	16h		;BIOS does it
		cmp	ah,lkey		;was 'L' key pressed?
		jne	getkey		;no, try again
               	mov	ah,2		;check keyboard status flags
        	int	16h		;BIOS does it
        	and     al,8		;Alt key pressed?
		je	getkey		;no, try again
		cmp	adapt,0		;CGA?
		jne	setvmd		;no
                call	discga
	setvmd:	mov	ah,0		;set video mode
		mov	al,vmode
		int	10h		;BIOS does it
        	call	resscr		;restore video memory contents
		mov	ah,5		;set video page
		mov	al,vpage
		int	10h		;BIOS does it
		cmp	vmode,3		;is video mode > 3 ?
		jbe	docur		;no
		cmp	vmode,7		;video mode = 7 ?
		jne	nocur		;no, don't restore cursor
	docur:	mov	ah,2		;position cursor
		mov	bh,vpage
		mov	dx,curpos
		int	10h		;BIOS does it
		cmp	adapt,0		;CGA?
		jne	nocur		;no
        	call	enacga
	nocur:	mov	ah,1		;unblank the cursor
        	mov	cx,curmod	;restore cursor scan lines
        	int	10h		;BIOS does it
        	mov	onflag,0	;set flag to off
        	mov 	al,pal
		and 	al,32
		jz 	l1
		mov 	bl,1
		jmp 	l2
l1:     	mov 	bl,0
l2:		mov 	ah,11
        	mov 	bh,1
        	int	10h
        	mov     ah,11
        	mov     bh,0
        	mov     bl,pal
        	int     10h
        	jmp	done		;exit
        kbint	endp
        ;
        ;----	Procedure to save the user's screen
        savscr	proc	near
		push	ds		;save data segment
		assume	ds:nothing
		mov	ax,vidseg	;set ds to video RAM
		mov	ds,ax
		mov	di,buffer	;init. dest. index
		xor	si,si		;init. source index
		mov	cx,bufsiz	;no. of words to move
		cld			;forward direction
	rep	movsw			;move the screen data to buffer
		pop	ds		;restore data segment
		assume	ds:cseg
		ret
	savscr	endp
        ;
        ;----	Procedure to restore the screen
        resscr	proc	near
        	push	es		;save extra segment
        	assume	es:nothing
        	mov	ax,vidseg	;set ex to video RAM
        	mov	es,ax
        	mov	si,buffer	;init. source index
		xor	di,di		;init. dest. index
		mov	cx,bufsiz	;no. of words to move
		cld			;forward direction
	rep	movsw			;move buffer to screen
		pop	es		;restore extra segment
		assume	es:cseg
		ret
	resscr	endp
        ;
        ;----	Procedure to display the message
        dismes	proc	near
		mov	ah,0		;set video mode
		mov	al,dmode	;video mode 2
		int	10h		;BIOS does it
		mov	ah,5		;set video page
		mov	al,0		;video page 0
		int	10h		;BIOS does it
		mov	ax,0600h	;clear the screen
		xor	cx,cx		;from 0,0
		mov	dx,0184fh	;  to 24,79
		mov	bh,7		;set attribute
		int	10h		;BIOS does it
		mov	ah,1		;hide the cursor
		mov	ch,32		;set bit 5 of ch
		int	10h		;BIOS does it
        	push	es		;save extra segment
        	assume	es:nothing
		mov	ax,vidseg	;set es to video RAM
		mov	es,ax
        	lea	si,messag	;set si to message
        	mov	di,1982		;set di to video RAM offset
        	mov	cx,36		;36 bytes to move
	rep	movsb			;display message
		pop	es		;restore extra segment
		assume	es:cseg
		ret
	dismes	endp
        ;
        ;-----	Procedure to disable the CGA
        discga	proc	near
        	mov	dx,3DAh		;status register
        wait:	in	al,dx		;get status
        	test	al,8		;in vertical retrace?
        	je	wait		;no, try again
        	sub	dx,2		;mode select register
        	mov	al,25h		;turn off bit 3 to
              	out	dx,al		;   disable video
        	ret
        discga	endp
        ;
        ;----	Procedure to enable the CGA
        enacga	proc	near
		mov	ah,15		;get mode
		int	10h		;BIOS does it
		lea	bx,envals	;bx points to enable values
		xlat			;al has enable value
               	mov	dx,3D8h		;mode select register
        	out	dx,al		;enable video
        	ret
        enacga	endp
        ;
        ;---	Procedure to reset keyboard and send end-of-interrupt
        kreset	proc	near
        	in	al,61h		;get port value
        	mov	ah,al		;save it in ah
        	or	al,80h		;set bit 7
        	out	61h,al		;reset port
        	mov	al,ah		;send original value
        	out	61h,al		;   to enable keyboard
        	cli			;disable interrupts
        	mov	al,20h		;20h is EOI
        	out	20h,al		;send EOI
        	sti			;enable interrupts
        	ret
        kreset	endp
        ;
        ;----	Initialize, terminate and stay resident
        init	proc	near
        	mov	adapt,0		;assume CGA
        	mov	vidseg,0b800h
		mov	bufsiz,8096
		mov	dmode,2
        	mov	ah,15		;get video mode
        	int	10h
        	cmp	al,7		;is it mode 7?
        	jne	itscga		;no, it's a CGA 
        	inc	adapt		;yes, it's monochrome
		mov	bufsiz,2048
        	sub	vidseg,800h	;adjust segment for monochrome
        	mov	cx,0C0Dh	;monochrome cursor
		mov	dmode,7		;display message mode 7
        	cmp	al,7		;video mode 7?
        	jmp	short setcur	;yes
        itscga:	mov	cx,0607h	;no, cursor scan lines 6 and 7
        setcur:	mov	ah,1		;set cursor
        	int	10h
        ;---	Save the old interrupt 9 vector and replace it with ours
        	mov	ah,35h		;get keyboard (int 9) vector
        	mov	al,9
        	int	21h
        	mov	oldvec,bx	;save vector offset
        	mov	oldvec[2],es	;save vector segment
        	mov	ah,25h		;set vector to point to
        	mov	al,9		;   our procedure
        	lea	dx,kbint
        	int	21h
        ;---	Terminate and stay resident
        	mov	dx,offset init+16192
        	int	27h		;terminate and stay resident
        init	endp
        cseg	ends
        	end	begin