home *** CD-ROM | disk | FTP | other *** search
- ; Program dscrnsav.asm
- ; David Markovitch 1/12/90
-
- IDEAL
-
- SEGMENT CODE
- ASSUME CS: CODE, DS: CODE
-
- org 100h
-
- start:
- jmp init ; jump to initialization
-
- load_msg db 13,10,"Dscrnsav screen saver resident - Delay is 5 min.",13,10
- db "Options: [d] disables, no parameter re-enables",13,10,"$"
- dsabl_msg db 13,10,"Dscrnsav disabled",13,10,"$"
- enabl_msg db 13,10,"Dscrnsav enabled",13,10,"$"
- err1_msg db 13,10,"Invalid command line parameter",13,10,"$"
- err2_msg db 13,10,"Dscrnsav not resident",13,10,"$"
-
- maxcount equ 5460 ; timer ticks for delay 5460 = 5 min
- shft_cnt equ 40 ; ticks between screen shifts 40 = 2 sec
-
- old9_ofs dw ? ; old int 9 address
- old9_seg dw ?
- old1C_ofs dw ? ; old int 1C address
- old1C_seg dw ?
- old_tail dw ? ; keyboard buffer tail
- off_flg db 0 ; 1 = disable blanking 0 = normal operation
- scr_offst dw 0 ; offset for shifting screen
- blank db 0 ; 1 = 'blank' screen 0 = normal screen
- turn_on db 0 ; 1 = unblank screen 0 = nothing
- count dw 0 ; tick counter for blanking
-
- ;------------------------------------------------------------------------------
-
- proc new9 ; new int 9 (keyboard)
- push es
- push ds
- push ax
- push cs
- pop ds
- mov ax,40h
- mov es,ax
- mov ax,[word es: 1Ch] ; save keyboard buffer tail pointer
- mov [old_tail],ax
- pushf ; do bios keyboard handler
- call [dword old9_ofs]
- cmp [blank],0 ; check for blank screen
- jne rest_scrn
- mov [count],0 ; reset tick counter
- jmp exit_9
-
- rest_scrn: ; set flag to unblank screen
- mov [turn_on],1
- mov ax,[old_tail] ; restore tail pointer to remove key from buffer
- mov [word es: 1Ch],ax
- exit_9:
- pop ax
- pop ds
- pop es
- iret
- endp new9
-
- ;------------------------------------------------------------------------------
-
- proc new1C ; new int 1C (timer tick)
- sti ; enable interrupts
- push es
- push ds
- push dx
- push ax
- push cs
- pop ds
- mov ax,40h
- mov es,ax
- cmp [turn_on],0 ; check if flag set to restore screen
- je if_blank ; jump to check for blank screen if flag not set
-
- mov [turn_on],0 ; restore original video buffer start
- mov [blank],0
- mov ax,[word es: 4Eh] ; get bios video buffer start (bytes)
- shr ax,1 ; convert to words
- push ax
- jmp do_crt ; set crt controller
-
- if_blank:
- cmp [off_flg],0 ; exit if disabled
- jne exit_1C
- cmp [blank],0 ; check if screen already blank
- jne chk_shift ; if blank then jump to check if ready to shift
-
- inc [count] ; screen not blank - check if time to blank
- cmp [count],maxcount
- jne exit_1C ; exit if not time to blank
-
- mov [blank],1 ; set blank screen flag
- jmp do_shift ; shift screen
-
- chk_shift: ; if screen blank - shift every shft_cnt ticks
- inc [count]
- cmp [count],shft_cnt
- jne exit_1C ; exit if not time to shift
-
- do_shift:
- mov ax,[scr_offst] ; get our video buffer offset (words)
- add ax,1003 ; shift 1003 words
- and ax,7FFh ; limit to first 4K of video buffer
- mov [scr_offst],ax ; save our new video buffer offset
- mov dx,[word es: 4Eh] ; get bios video buffer start (bytes)
- shr dx,1 ; convert to words
- add ax,dx ; add our offset
- push ax
-
- do_crt: ; set crt controller
- mov dx,[es: 63h] ; crt controller base address
- mov al,12 ; access register 12
- out dx,al
- inc dx
- pop ax ; pop starting address
- xchg ah,al
- out dx,al ; write hi (start address) to register 12
- dec dx
- push ax ; push starting address
- mov al,13 ; access register 13
- out dx,al
- inc dx
- pop ax ; pop starting address
- xchg ah,al
- out dx,al ; write lo (start address) to register 13
- mov [count],0 ; reset tick counter
-
- exit_1C:
- pop ax
- pop dx
- pop ds
- pop es
- jmp [dword cs: old1C_ofs]
-
-
-
- endp new1C
-
- ;------------------------------------------------------------------------------
-
- init: ; initialization
- mov si,81h
- mov dx,offset err1_msg ; "Invalid command line parameter"
- parse_loop: ; check for 'd' on command line
- lodsb
- cmp al," "
- je parse_loop ; skip spaces
- cmp al,13
- je end_parse ; jump if no parameter
- or al,20h ; convert to lower case
- cmp al,"d"
- jne out_err ; invalid parameter
- mov [off_flg],1 ; set disable flag
- end_parse:
- cld ; search for a previous copy
- mov [word start],0 ; fingerprint
- mov bx,0 ; bx = start segment
- mov ax,cs ; ax = current segment
- chk_prev:
- inc bx ; increment segment
- mov es,bx
- cmp ax,bx ; check if equals current segment
- je no_copies
- mov si,offset start
- mov di,si
- mov cx,16 ; compare first 16 bytes of each segment
- repe cmpsb
- jne chk_prev ; repeat if no match
-
- mov al,[off_flg] ; copy found - change enable/disable flag
- mov [es: off_flg],al
- mov [es: count],0 ; reset tick count
- mov dx,offset enabl_msg ; "Dscrnsav enabled"
- cmp al,0
- je out_msg ; copy enabled - errorlevel = 0
-
- mov dx,offset dsabl_msg ; "Dscrnsav disabled"
- mov al,0 ; errorlevel = 0
- jmp out_msg ; copy disabled
-
- no_copies:
- mov dx,offset err2_msg ; "Dscrnsav not resident"
- cmp [off_flg],0
- je install ; ok to install
-
- out_err:
- mov al,1
- out_msg:
- mov ah,9 ; display message
- int 21h
- mov ah,4Ch ; terminate with errorlevel = al
- int 21h
-
- install: ; make program resident
- mov ax,3509H ; get old int 9 address
- int 21H
- mov ax,es
- mov [old9_seg],ax ; save old int 9 address (keyboard)
- mov [old9_ofs],bx
- mov ax,351CH ; get old int 1C address (timer tick)
- int 21H
- mov ax,es
- mov [old1C_seg],ax ; save old int 1C address
- mov [old1C_ofs],bx
- mov dx,offset new9 ; set int 9 to point to our code
- mov ax,2509H
- int 21H
- mov dx,offset new1C ; set int 1C to point to our code
- mov ax,251CH
- int 21H
- mov dx,offset load_msg ; "Dscrnsav loaded"
- mov ah,9
- int 21h ; display message
- mov dx,(init - start + 256 + 16)/16
- mov ax,3100H ; terminate and stay resident
- int 21H
-
- ends
- end start
-