	page	55,132

abs0	segment at 0000h
abs0	ends

data	segment at 40h
	org	17h
kb_flag db	?		; keyboard flags area in low memory
caps_state	equ	40h	; caps state toggle bit
alt_shift	equ	08h	; alt shift key depressed
right_shift	equ	01h	; right shift key depressed
data	ends


cseg	segment para public 'code'
	assume cs:cseg,ds:cseg,es:cseg,ss:nothing

	org	100h

start	proc	far

	call	throw_away	; call init routine

start	endp

switch	       db      0       ; zero: don't clobber cpas_lock; not zero: do it
ptr_int9       equ     4*9h    ; ptr to int 9h

our_int9       label   dword   ; save area for cs:ip for new int 9h
	       dd      ?
kb_int	       label   dword   ; save area for cs:ip for system's int 9
	       dd      ?

int9   proc    far

	sti			; set interrupts back on
	pushf			; save flags
	call	cs:kb_int	; call real int 9 as if an interrupt

	push	ax		; sav some regs
	push	ds		; '
	mov	ax,data 	; load segment address
	mov	ds,ax		; into ds
	assume	ds:data

	test	kb_flag,alt_shift+right_shift ; are both alt and right shift on?
	jz	int9_010	; jump zero - don't change switch value
	jpo	int9_010	; jump parity odd - only one bit set - don't change switch value

	xor	cs:switch,01h	; toggle switch

int9_010:
	test	cs:switch,0ffh	   ; test switch  truth
	jz	int9_090	   ; jmp - zero - not on

	and	kb_flag,0ffh-caps_state ; turn off caps state

int9_090:
	pop	ds		;
	pop	ax		;
	iret

int9	endp
pgm_end   equ	  $		; end of resident code and begining of printer bufer area


instld_msg	db	0dh,0ah,'-caps_lock defeat v1.0 installed ',0dh,0ah
		db	'press alt + right shift to disable/enable caps lock',0dh,0ah,00


throw_away proc near
;
;
	push	si		; save si
	push	di		; save di
	push	ds		; save ds
	push	es		; save es

	push	cs		; establish addressabliltiy in this segment
	push	cs		;
	pop	ds		;
	pop	es		;
	assume cs:cseg,ds:cseg,es:cseg,ss:nothing

	mov	di,offset our_int9 ; ptr to uninitialized save area
	mov	ax,offset int9	; get ptr to our int9
	stosw			; init ip in save area
	mov	ax,cs		; get ptr to our cs
	stosw			; init cs in save area

	push	ds		; save ds
	mov	ax,abs0 	; get abs0
	mov	di,offset kb_int ; get ptr to orig kb_int save area
	mov	ds,ax		; make ds segment base 0:0
	assume	ds:abs0 	; establish addressability to segment 0:0
	mov	si,ptr_int9	; load ptr to actual int 9h entry

; move from ds:si to es:di
	movsw			; move first word  ip
	movsw			; move second word  cs:
	pop	ds		; recover ds
	assume	ds:cseg 	; and it's addressabiltiy

	mov	si,offset our_int9  ; load ptr to our int 9's ip:cs
	mov	di,ptr_int9	; load ptr to actual int 9h entry
	push	es		; save es
	mov	es,ax		; make es segment base at 0:0
	assume	es:abs0 	; establish addressability to segment 0:0
	cli			; turn off interrupts for a sec - until moves

; move from ds:si to es:di
	movsw			; move first word  ip
	movsw			; move second word  cs:
	sti			; enable interrupts
	pop	es		; recover es
	assume	es:cseg 	; and it's addressabiltiy

	mov	si,offset instld_msg  ; message
	xor	bx,bx		; set foreground and display page
throw_away_100:
	lodsb			; get byte to print
	or	al,al		; test for zero byte
	jz	throw_away_200	; exit on zero
	mov	ah,0eh		; teletype video routine
	int	10h		; bios call
	jmp   short throw_away_100  ; loop
throw_away_200:
	lea	dx,pgm_end	; last byte of resident program

	pop	es		; recover orig es
	pop	ds		; recover orig ds
	pop	di		; recover di
	pop	si		; recover si
	pop	ax		; throw away first call from stack

	int	27h		; exit don't delete
throw_away endp
cseg	ends

	end	start
