NAME HZPCSAVE PAGE 55,132 TITLE 'SCREEN SAVER FOR HZ150 PC SERIES' ; ; SCRNSAVE patched for Heath/Zenith 150 PC series ;----------------------------------------------------------------------; ; This program was written by John Socha and published in SOFTALK for ; ; the IBM Personal Computer, December 1983. The program turns the ; ; screen display off after 3 minutes of no activity (ie: no data is ; ; sent to the screen). Pressing any key will reactivate the screen ; ; display. ; ; ; ; This version has been patched by Mike Berman to operate on the ; ; Heath/Zenith 150 PC series. The video board on these computers ; ; has been enhanced to stop blinking when scrolling, but this ; ; required an additional video register at port 3DA; when bit 0 of ; ; this register is enabled, the bit used to turn off the screen by ; ; the original version of this program is overriden, and nothing ; ; happens. ; ; ; ; CAVEAT: Since I don't know how to find the current contents of ; ; the 3DA port, this program assumes that all other bits = 0, which ; ; apparently is the default. If this is not true, the screen may ; ; be restored to a different state than when it was blanked. This ; ; doesn't cause problems with the software I use, but users of this ; ; routine should be aware of it. ; ; ; ; ACKNOWLEDGEMENT: Thanks to Dave Tweten for explaining it. ; ;----------------------------------------------------------------------; ; ;----------------------------------------------------------------------; ; These are the interrupt vectors for the clock, keyboard and video ; ; io calls. ; ;----------------------------------------------------------------------; ; VECTORS SEGMENT AT 0H ORG 8H*4 TIME_OF_DAY_VECTOR LABEL DWORD ;Clock interrupt, 18.2 per sec ORG 9H*4 KEYBOARD_INT_VECTOR LABEL DWORD ORG 10H*4 VIDEO_IO_VECTOR LABEL DWORD VECTORS ENDS ; ;----------------------------------------------------------------------; ; This is the data area starting at 400H used by the ROM BIOS ; ; routines. ADDR_6845 contains the base address, 3x4, of the current ; ; display adapter and CRT_MODE_SET contains the current setting of ; ; display mode -- the 3x8 register. The x is B for the monochrome ; ; display adapter, and D for the color-graphics adapter. ; ;----------------------------------------------------------------------; ; ROM_BIOS_DATA SEGMENT AT 40H ORG 10H EQUIP_FLAG DW ? ;Used to determine display type ORG 60H CURSOR_MODE DW ? ;Current cursor mode (start, stop line) ORG 63H ADDR_6845 DW ? ;Base address for active display card CRT_MODE_SET DB ? ;Current setting of 3x8 register ROM_BIOS_DATA ENDS ; ;----------------------------------------------------------------------; ; This is the start of the local data and executable code. ; ;----------------------------------------------------------------------; ; CODE_SEG SEGMENT ASSUME CS:CODE_SEG ORG 100H BEGIN: JMP INIT_VECTORS ;Initialize vectors and attach to DOS ; ROM_TIME_OF_DAY_INT DD ;Addresses for ROM routines ROM_KEYBOARD_INT DD ROM_VIDEO_IO_INT DD TIMER_DELAY DW 0CCCH ;Delay before turning off video THREE_MIN_COUNTER DW ? ;Clock ticks in 3 minutes OLD_CURSOR_TYPE DW 0 ;Hold the old cursor type ; ;----------------------------------------------------------------------; ; Turn the video display off after three minutes of no use. ; ; ; ; Calls: ROM_TIME_OF_DAY_INT ; ; Reads: ADDR-6845, CRT_MODE_SET ; ; Writes: THREE_MIN_COUNTER, OLD_CURSOR_TYPE ; ;----------------------------------------------------------------------; ; INTERCEPT_TIME_OF_DAY PROC NEAR PUSH AX PUSH DS MOV AX,CS ;Set data segment to current segment MOV DS,AX ASSUME DS:CODE_SEG DEC THREE_MIN_COUNTER ;Have 3 minutes elapsed? JZ TURN_VIDEO_OFF ;Yes, turn video off JG GOTO_ROM_TIME_OF_DAY ;No, keep video on MOV THREE_MIN_COUNTER,0 ;Video is off, reset counter to 0 again GOTO_ROM_TIME_OF_DAY: POP DS POP AX ASSUME DS:NOTHING JMP ROM_TIME_OF_DAY_INT TURN_VIDEO_OFF: ASSUME DS:CODE_SEG PUSH BX PUSH CX PUSH DX MOV AH,3 ;Get current cusor type into CX PUSHF ;Push flags to simulate INT with CALL CALL ROM_VIDEO_IO_INT ;Must use CALL since INT 10 points here MOV OLD_CURSOR_TYPE,CX ;And save it MOV CH,0FH ;Now remove cursor from screen MOV CL,0 MOV AH,1 PUSHF ;Push flags to simulate INT with CALL CALL ROM_VIDEO_IO_INT ;Must use CALL since INT 10 points here POP DX POP CX POP BX PUSH DX ;Turn the display video off MOV AX,ROM_BIOS_DATA MOV DS,AX ASSUME DS:ROM_BIOS_DATA MOV DX,ADDR_6845 ;Get base address for display adapter ADD DX,4 ;IO address for 3x8 register MOV AL,CRT_MODE_SET AND AL,0F7H ;Turn video off OUT DX,AL ;----------------------------------------------------------------------; ; HZ 150 PC Patch Starts Here ; ;----------------------------------------------------------------------; MOV DX,3DAH ;Auxiliary video register on HZ309 card MOV AL,0 OUT DX,AL ;Turn off Video Enable Override ;----------------------------------------------------------------------; ; END of Patch ; ;----------------------------------------------------------------------; POP DX JMP GOTO_ROM_TIME_OF_DAY ; INTERCEPT_TIME_OF_DAY ENDP ; ;----------------------------------------------------------------------; ; This procedure resets the timer count to 0CCCH and turns the ; ; display on if it was off. ; ;----------------------------------------------------------------------; ; RESET_COUNTER PROC NEAR PUSH AX PUSH DX PUSH DS MOV AX,CS MOV DS,AX ASSUME DS:CODE_SEG CMP THREE_MIN_COUNTER,0 ;Was the display off? JG VIDEO_NOT_OFF ;No, then just reset counter PUSH DS ;Yes, then turn video back on MOV AX,ROM_BIOS_DATA MOV DS,AX ASSUME DS:ROM_BIOS_DATA MOV DX,ADDR_6845 ;Get base address for display adapter ADD DX,4 ;IO address for 3x8 register MOV AL,CRT_MODE_SET OR AL,8 ;Turn video on again OUT DX,AL ;----------------------------------------------------------------------; ; HZ 150 PC Patch Starts Here ; ;----------------------------------------------------------------------; MOV DX,3DAH ;Auxiliary video register on HZ309 card MOV AL,1 OUT DX,AL ;Turn on Video Enable Override ;----------------------------------------------------------------------; ; END of Patch ; ;----------------------------------------------------------------------; POP DS ASSUME DS:CODE_SEG PUSH CX ;Now restore the cursor MOV CX,OLD_CURSOR_TYPE MOV AH,1 ;Restore the old cursor type PUSHF ;Push flags to simulate INT with CALL CALL ROM_VIDEO_IO_INT ;Must use CALL since INT 10 points here POP CX VIDEO_NOT_OFF: MOV AX,TIMER_DELAY MOV THREE_MIN_COUNTER,AX POP DS POP DX POP AX RET RESET_COUNTER ENDP ; INTERCEPT_KEYBOARD_INT PROC NEAR ASSUME DS:NOTHING CALL RESET_COUNTER ;Reset the time out counter JMP ROM_KEYBOARD_INT ;Pass control to ROM routine INTERCEPT_KEYBOARD_INT ENDP ; ;----------------------------------------------------------------------; ; This procedure resets the cursor type to the default type for the ; ; display adapter in use: 607H for the color/graphics adapter and ; ; 0C0BH for the monochrome display adapter. ; ;----------------------------------------------------------------------; ; SET_CURSOR_MODE PROC NEAR PUSH AX PUSH CX PUSH DS MOV AX,ROM_BIOS_DATA MOV DS,AX ;Point to ROM BIOS data area ASSUME DS:ROM_BIOS_DATA MOV AX,EQUIP_FLAG ;Determine which adapter is active AND AL,30H ;Isolate adapter information MOV CX,607H ;Set for color/graphics adapter CMP AL,30H ;Is monochrome display adapter active? JNE COLOR_ACTIVE ;No, set cursor type MOV CX,0B0CH ;Cursor mode for monochrome display COLOR_ACTIVE: MOV AH,1 PUSHF ;Simulate INT 10 with PUSHF and CALL CALL ROM_VIDEO_IO_INT POP DS POP CX POP AX RET SET_CURSOR_MODE ENDP ; ;----------------------------------------------------------------------; ; This procedure resets the time-out counter, and passes control on ; ; to the ROM VIDEO_IO routines. ; ;----------------------------------------------------------------------; ; INTERCEPT_VIDEO_IO PROC NEAR ASSUME DS:NOTHING CALL RESET_COUNTER ;Reset time-out counter PUSHF ;Simulate INT 10 with PUSHF and CALL CALL ROM_VIDEO_IO_INT ;Do VIDEO_IO function OR AH,AH ;Asking for set-mode function? JNZ NOT_MODE_SET ;No, then return CALL SET_CURSOR_MODE ;Yes, then set cursor mode to default ; NOT_MODE_SET: IRET ; INTERCEPT_VIDEO_IO ENDP ; ;----------------------------------------------------------------------; ; This procedure initializes the interrupt vectors. ; ;----------------------------------------------------------------------; ; INIT_VECTORS PROC NEAR ASSUME DS:VECTORS MOV AX,VECTORS ;Set up the data segment for vectors MOV DS,AX CLI ;Don't allow interrupts MOV AX,word ptr TIME_OF_DAY_VECTOR ;Save addresses of BIOS routines MOV word ptr ROM_TIME_OF_DAY_INT,AX MOV AX,word ptr TIME_OF_DAY_VECTOR[2] MOV word ptr ROM_TIME_OF_DAY_INT[2],AX MOV word ptr TIME_OF_DAY_VECTOR,OFFSET INTERCEPT_TIME_OF_DAY MOV word ptr TIME_OF_DAY_VECTOR[2],CS ; MOV AX,word ptr KEYBOARD_INT_VECTOR MOV word ptr ROM_KEYBOARD_INT,AX MOV AX,word ptr KEYBOARD_INT_VECTOR[2] MOV word ptr ROM_KEYBOARD_INT[2],AX MOV word ptr KEYBOARD_INT_VECTOR,OFFSET INTERCEPT_KEYBOARD_INT MOV word ptr KEYBOARD_INT_VECTOR[2],CS ; MOV AX,word ptr VIDEO_IO_VECTOR MOV word ptr ROM_VIDEO_IO_INT,AX MOV AX,word ptr VIDEO_IO_VECTOR[2] MOV word ptr ROM_VIDEO_IO_INT[2],AX MOV word ptr VIDEO_IO_VECTOR,OFFSET INTERCEPT_VIDEO_IO MOV word ptr VIDEO_IO_VECTOR[2],CS ; MOV AX,TIMER_DELAY ;Set the delay to 3 minutes MOV THREE_MIN_COUNTER,AX ; STI ;Allow interrupts again CALL SET_CURSOR_MODE ;Set cursor mode to default MOV DX,OFFSET INIT_VECTORS ;End of resident portion INT 27H ;Terminate but stay resident INIT_VECTORS ENDP ; CODE_SEG ENDS ; END BEGIN