home *** CD-ROM | disk | FTP | other *** search
- PAGE 60,132
- TITLE CRITTER - Critical error handler
-
- ; (C) Copyright 1987 Forest Hill Software, Inc.
- ; All rights reserved
- ;
- ; Note: This program was put together with code from a handler that
- ; was integrated with a larger project. Do not be supprised to
- ; find added references and code which do not seem pertinent.
- ; (it was also ported from Manx Assembler source code)
-
- DOSSEG
- .MODEL small
-
- .STACK 100h
-
- LINE equ 3 ;Starting line # of error window
- COLUMN equ 9 ;Starting column of error window
- LINES equ 4 ;# of lines in error window
- COLUMNS equ 25 ;# of columns in error window
- DISK_ER equ 80h ;Disk error flag bit
- ALERT_D equ 10 ;Alert tone duration
- ALERT_F equ 300 ;Alert tone frequency
- NOCURS equ 2000h ;Scan lines setting for no cursor
-
- ; Allowed action bits - provided in ah when entering INT 24
-
- QUI_BIT equ 08h ;Quit (fail) allowed bit
- RET_BIT equ 10h ;Retry allowed bit
- IGN_BIT equ 20h ;Ignore allowed bit
-
- ; Action key scan codes
-
- SCAN_R equ 19 ;Key 'R' pressed
- SCAN_I equ 23 ;Key 'I' pressed
-
- ; Actions which can be supplied back to DOS in al
-
- IGNORE equ 0 ;Ignore the error
- RETRY equ 1 ;Retry the operation
- ABORT equ 2 ;Abort the program
- FAIL equ 3 ;Fail the call
-
- ; Video attributes
-
- CO_NORM equ 17h ;Color text attributes - normal = white on blue
- CO_HIGH equ 1eh ; highlite = yellow on blue
- CO_ERRO equ 9ch ; error = flash red on blue
- BW_NORM equ 07h ;B/W text attributes - normal = low intensity
- BW_HIGH equ 0fh ; highlite = high intensity
- BW_ERRO equ 8fh ; error = flash high intens
- MO_NORM equ 07h ;Mono text attributes - normal = normal
- MO_HIGH equ 70h ; highlite = reverse
- MO_ERRO equ 87h ; error = flash reverse
-
- ; Interupts
-
- VIDEO equ 10h ;BIOS video services interupt
- SETSIZE equ 01h ;Set cursor size
- SETPOS equ 02h ;Set cursor position
- READCUR equ 03h ;Read cursor
- READCHR equ 08h ;Read character and attribute
- WRITCHR equ 09h ;Write character and attribute
- GETMODE equ 0fh ;Get video mode
- KEYBRD equ 16h ;BIOS keyboard services interupt
- READKBD equ 00h ;Read keypress
- TESTKBD equ 01h ;Test if keypress waiting
- DOS equ 21h ;DOS function call interrupt
- DISPSTR equ 09h ;Display $ terminated string
- SETVECT equ 2500h ;Set interrupt vector
- KEEPPGM equ 3100h ;Keep process (TSR)
- GETVECT equ 3500h ;Get interrupt vector
- EXITPGM equ 4C00h ;End process
- TICK equ 08h ;Clock tick interrupt
- CRITIC equ 24h ;Critical error handler interrupt
-
- .DATA
-
- logon db 13,10,'CRITTER - Your hyperactive critical error handler'
- db 13,10,' (C) Copyright 1987 by Forest Hill Software, Inc.'
- db 13,10,'$'
-
- .CODE
-
- ; Data to be kept in Code segment
-
- EVEN
-
- top_stk dw 0 ;Top of local stack
- old_cur dw 0 ;Original cursor scan lines
- old_pos dw 0 ;Original cursor position
- err_sta dw 0 ;Error status information
- err_num dw 0 ;Error number (code)
- tic_off dw 0 ;Saved INT 8 vector
- tic_seg dw 0
- crt_off dw 0 ;Saved INT 24 vector
- crt_seg dw 0
- our_sp dw 0 ;Our local stack
- our_ss dw 0
- sav_sp dw 0 ;Callers stack
- sav_ss dw 0
- scr_sav db LINES*COLUMNS*2 dup (0) ;Storage for used screen area
- scr_pag db 0 ;Current screen page
- lin_sav db 0 ;Temporary line # storage
- col_sav db 0 ;Temporary column # storage
- line_c db 0 ;Line counter
- colum_c db 0 ;Column counter
- att_nor db 0 ;Video attributes - normal
- att_hig db 0 ; highlite
- att_err db 0 ; error
-
- ; Error window background
-
- err_top db 213, 8 dup (205), 7 dup (' '), 8 dup (205), 184, '$'
- err_mid db 179, 23 dup (' '), 179, '$'
- err_bot db 212, 23 dup (205), 190, '$'
- err_nam db 'ERROR$'
-
- ; Critical Error Handler Messages
-
- ; |<-- width = 23 --->| Lower byte of reg di
-
- ERR_SIZ equ 24 ;Length of each error message inc $
-
- errors db ' Write Protected $' ;0
- db ' Unknown Device $' ;1
- db ' Drive Not Ready $' ;2
- db ' Unknown Command $' ;3
- db ' Data Error (CRC) $' ;4
- db ' Request Structure $' ;5
- db ' Seek Error $' ;6
- db ' Unknown Media $' ;7
- db ' Sector Not Found $' ;8
- db ' Out of Paper $' ;9
- db ' Write Fault $' ;a
- db ' Read Fault $' ;b
- db ' General Failure $' ;c
- db ' (reserved) $' ;d
- db ' (reserved) $' ;e
- db ' Invalid Disk Change $' ;f
-
- ; Actions
-
- actions db 'Ignore Retry Abort Fail$'
-
- ignor_c db 'I$'
- retry_c db 'R$'
- abort_c db 'A$'
- fail_c db 'F$'
-
- I_POS equ 1 ;Position of I in Ignore to highlite
- R_POS equ 8 ;Position of R in Retry to highlite
- A_POS equ 14 ;Position of A in Abort to highlite
- F_POS equ 20 ;Position of F in Fail to highlite
-
- ; Install critical error handler and stay resident
-
- start: mov ax, @DATA ;Initialize DS
- mov ds, ax
- mov ah, DISPSTR ;Display logon message
- mov dx, offset logon
- int DOS
- call install ;Install handler and tick watch
- mov ax, sp ;Determine paragraphs to keep
- mov cs:our_sp, ax ; also save sp for the handler
- ;fortunately there should be no fatal errors untill this TSR's
- mov cl, 4 ;starting with para's in stack
- shr ax, cl
- mov bx, ss ;Add that to stack segment
- mov cs:our_ss, bx ; also save ss for the handler
- add ax, bx
- mov bx, es ;Then subtract PSP segment
- sub ax, bx
- inc ax ;Add 1 para for safety
- mov dx, ax
- mov ax, KEEPPGM ;TSR with code 0
- int DOS
-
- ; Link vector check routine into timer interupt
-
- install proc
- push ds
- push es
- push cs
- pop ds
- mov ax, (GETVECT+CRITIC) ;Read existing INT 24 vector
- int DOS
- mov crt_off, bx
- mov crt_seg, es
- mov ax, (SETVECT+CRITIC) ;Set new INT 24 vector
- mov dx, offset crit_handler
- int DOS
- mov ax, (GETVECT+TICK) ;Read existing INT 8 vector
- int DOS
- mov tic_off, bx
- mov tic_seg, es
- mov ax, (SETVECT+TICK) ;Set new INT 8 vector
- mov dx, offset vect_check
- int DOS
- pop es
- pop ds
- ret
- install endp
-
- ; Remove critical error handler from interrupt
-
- remove proc
- push ds
- push cs
- pop ds
- mov dx, tic_off
- mov ax, (SETVECT+TICK)
- int DOS
- mov dx, crt_off
- mov ax, (SETVECT+CRITIC)
- int DOS
- pop ds
- ret
- remove endp
-
- ; Vector check
-
- vect_check proc
- sti
- push ax
- push bx
- push es
- xor ax, ax ;Get current INT 24 Vector
- mov es, ax
- mov bx, es:[CRITIC*4]
- mov ax, es:[CRITIC*4+2]
- cmp ax, seg crit_handler ;Does it point to our handler
- jne revect
- cmp bx, offset crit_handler
- je chkend
- revect: cmp ax, seg crit_handler ;Don't revector programs loaded after
- ja chkend ; this program
- mov cs:crt_off, bx ;If not, save current vector
- mov cs:crt_seg, ax
- cli ;then revector it to our handler
- mov es:[CRITIC*4], offset crit_handler
- mov es:word ptr [CRITIC*4+2], seg crit_handler
- sti
- chkend: pop es
- pop bx
- pop ax
- jmp dword ptr cs:[tic_off] ;Chain to previous tick handler
- vect_check endp
-
-
- ; Critical error interrupt handler
-
- crit_handler proc
- sti ;Enable interupts again
- push ds ;Save caller's data segment
- push cs ;data segment=codeseg
- pop ds
- mov sav_ss, ss ;Save caller's stack
- mov sav_sp, sp
- cli ;Set up local stack
- mov ss, our_ss
- mov sp, our_sp
- sti
- push bx ;Save required regs on local stack
- push cx
- push dx
- push bp
- push si
- push di
- push es
- ;
- mov err_sta, ax ;Save error status
- and di, 00ffh ;Mask out all but error number
- mov err_num, di ;Save error number
- call vid_mod ;Get video mode
- cmp al, 3 ;If mode 0-3 it's text
- jle text
- mov att_nor, MO_NORM ;Only remaining text mode is mono
- mov att_hig, MO_HIGH ;so set attributes just in case
- mov att_err, MO_ERRO
- cmp al, 7 ;If it is monochrome mode
- je mode_ok ;then all set
- ;
- call get_act ;Get action - no window in graphics
- jmp done ;Return with action code
- ;
- text: mov att_nor, BW_NORM ;Assume B/W attributes
- mov att_hig, BW_HIGH
- mov att_err, BW_ERRO
- test al, 1 ;unless it's a color mode
- je mode_ok
- ;
- color: mov att_nor, CO_NORM ;then use color attributes
- mov att_hig, CO_HIGH
- mov att_err, CO_ERRO
- ;
- mode_ok:call cur_off ;Turn cursor off
- call sav_scr ;Save underlying screen
- ; display window background and name
- mov bl, att_nor ;Use normal attribute for window
- mov bp, offset err_top ;Display top line of window
- mov dh, LINE ;Top line of window
- mov dl, COLUMN ;Left column of window
- call str_out ;Display this line
- mov bp, offset err_mid ;Display middle 2 lines (less text)
- inc dh ;on next line
- mov dl, COLUMN ;Yes! We have to keep setting it!
- call str_out
- mov bp, offset err_mid ;and the one following
- inc dh
- mov dl, COLUMN
- call str_out
- mov bp, offset err_bot ;Display bottom line
- inc dh
- mov dl, COLUMN
- call str_out
- mov bl, att_err ;Use highlite attribute
- mov bp, offset err_nam ;Display window name - "ERROR"
- mov dl, COLUMN+10 ;In middle of top line
- mov dh, LINE
- call str_out
- ; Display appropriate error message
- mov ax, err_num ;Calculate start of message
- mov bl, ERR_SIZ ;Where each message is ERR_SIZ long
- mul bl
- add ax, offset errors ;and the table base is "errors"
- mov bp, ax
- mov bl, att_nor ;Use normal attributes
- mov dh, LINE+1 ;Starting on seccond row
- mov dl, COLUMN+1 ;and the second column
- call str_out ;Display it
- ; Display allowed actions
- mov bl, att_nor ;Normal attr for all but R & I
- mov dh, LINE+2 ;Line where actions are displayed
- mov dl, COLUMN+1 ;Column where actions are displ.
- mov bp, offset actions ;Display actions
- call str_out
- mov dl, COLUMN+I_POS ;Overlay highlited "I"
- mov bp, offset ignor_c
- mov bl, att_hig
- call str_out
- mov dl, COLUMN+R_POS ;Overlay highlited "R"
- mov bp, offset retry_c
- mov bl, att_hig
- call str_out
- mov dl, COLUMN+A_POS ;Overlay highlited "A"
- mov bp, offset abort_c
- mov bl, att_hig
- call str_out
- mov dl, COLUMN+F_POS ;Overlay highlited "F"
- mov bp, offset fail_c
- mov bl, att_hig
- call str_out
- ; Convert error number to DOS standard
- add err_num, 19
- ; Get desired action from user
- call get_act ;Get desired action from user
- push ax ;Save action code
- call res_scr ;Restore screen under window
- call cur_on ;Restore original cursor
- pop ax ;Restore action code
- mov bx, err_sta ;Restore original error status
- mov bl, al ;with new action code
- mov ax, bx
- ;
- done: pop es ;Restore registers from local stack
- pop di
- pop si
- pop bp
- pop dx
- pop cx
- pop bx
- cli ;int's off...just in case
- mov ss, sav_ss ;Restore caller's stack
- mov sp, sav_sp
- sti
- pop ds
- iret ;At this point al contains action
- crit_handler endp
-
- ; Get video mode
-
- vid_mod proc
- mov ah, GETMODE ;Get video page
- int VIDEO
- mov scr_pag, bh
- ret
- vid_mod endp
-
- ; Turn cursor off
-
- cur_off proc
- mov bh, scr_pag ;Get cursor information
- mov ah, READCUR
- int VIDEO
- cmp cx, 0067h ;Test for BIOS bug
- jne cur_ok
- mov cx, 0607h ;fix it if required
- cur_ok: mov old_cur, cx ;Save cursor scan lines
- mov old_pos, dx ;Save cursor position
- mov ah, SETSIZE ;Set cursor off
- mov cx, NOCURS
- int VIDEO
- ret
- cur_off endp
-
- ; Turn cursor back on
-
- cur_on proc
- mov dx, old_pos ;Restore original cursor position
- mov bh, scr_pag
- mov ah, SETPOS
- int VIDEO
- mov cx, old_cur ;Restor original scan lines
- mov ah, SETSIZE
- int VIDEO
- ret
- cur_on endp
-
- ; Save the screen area under the window
-
- sav_scr proc
- mov al, LINE ;Starting at LINE
- mov line_c, al
- xor di, di ;Point to start of scr_save
- mov cx, LINES ;For each line
- lin_loo:push cx
- mov cx, COLUMNS ;For each column
- mov al, COLUMN ;Starting at COLUMN
- mov colum_c, al
- col_loo:mov ah, SETPOS ;Set position to read
- mov bh, scr_pag
- mov dh, line_c
- mov dl, colum_c
- int VIDEO
- mov ah, READCHR ;Read character & attribute
- mov bh, scr_pag
- int VIDEO
- mov scr_sav[di], ah ;Place attribute in scr_sav
- inc di ;Bump scr_sav pointer
- mov scr_sav[di], al ;Place character in scr_sav
- inc di
- inc colum_c ;Bump column pointer
- loop col_loo ;Till line is done
- inc line_c ;Bump line pointer
- pop cx ;Till window done
- loop lin_loo
- ret
- sav_scr endp
-
- ; Restore the area under the window
-
- res_scr proc near
- mov al, LINE ;Starting at LINE
- mov line_c, al
- xor di, di ;Point to start of scr_sav
- mov cx, LINES ;For each line
- lin_lo2:push cx
- mov cx, COLUMNS ;For each column
- mov al, COLUMN ;Point to starting column
- mov colum_c, al
- col_lo2:mov ah, SETPOS ;Set position to restore
- mov bh, scr_pag
- mov dh, line_c
- mov dl, colum_c
- int VIDEO
- push cx
- mov ah, WRITCHR ;Write character & attribute
- mov bl, scr_sav[di] ;Get attribute
- inc di ;Bump scr_sav pointer
- mov al, scr_sav[di] ;Get character
- inc di ;Bump scr_sav pointer
- mov bh, scr_pag ;Ensure we have correct page
- mov cx, 1 ;This character just once
- int VIDEO
- pop cx
- inc colum_c ;Bump column pointer
- loop col_lo2 ;Till line is done
- inc line_c ;Bump line pointer
- pop cx ;Till window done
- loop lin_lo2
- ret
- res_scr endp
-
- ; Display string - till '$' - No Wrap Allowed!
-
- ; call with: bp = pointer to string
- ; bl = attribute
- ; dh = screen row
- ; dl = starting column
-
- str_out proc
- push di ;We must save di reg
- push ax ;and ax reg
- mov bh, scr_pag ;Position cursor
- mov ah, SETPOS
- int VIDEO
- xor di, di ;Point to start of string
- str_loo:mov al, cs:[bp][di] ;Get current character
- cmp al, '$' ;Check for end of string
- je str_end
- mov cx, 1 ;Only 1 of each character
- mov ah, WRITCHR ;Write character to screen
- int VIDEO
- inc dl ;Point to next column
- mov ah, SETPOS ;Move cursor there
- int VIDEO
- inc di ;Point to next character in string
- jmp str_loo ;continue
- ;
- str_end:pop ax ;Restore ax reg
- pop di ;and di reg
- ret
- str_out endp
-
- ; Obtain response from user - Test for valid action
- ; when valid is specified set return code in al reg
-
- get_act proc
- push cx
- action: call alert ;Alert user
- ; Clear keyboard buffer
- tst_kbd:mov ah, TESTKBD ;Any characters in keyboard buffer?
- int KEYBRD
- jz buf_clr ;If nothing in buffer then it's clr
- mov ah, READKBD ;else dump this keypress
- int KEYBRD
- jmp tst_kbd
- buf_clr:
- ; Get a new keypress
- key_psd:mov ah, TESTKBD ;Any key pressed yet
- int KEYBRD
- jz key_psd ;If not then wait
- mov ah, READKBD ;else get keypress
- int KEYBRD
- and al, 0DFh ;Convert to lower case
- ; Test for valid key
- xor cx, cx
- cmp al, 'I' ;Test if 'I' pressed
- je goodkey
- inc cl
- cmp al, 'R' ;Test if 'R' pressed
- je goodkey
- inc cl
- cmp al, 'A' ;Test if 'A' pressed
- je goodkey
- inc cl
- cmp al, 'F' ;Test if 'F' pressed
- je goodkey
- jmp action
- goodkey:mov al, cl
- pop cx
- ret
- get_act endp
-
- ; Alert user with low beep tone
-
- alert proc
- push bx
- push di
- mov bx, ALERT_D ;Duration of alert tone
- mov di, ALERT_F ;Frequency of alert tone
- call abeep
- pop di
- pop bx
- ret
- alert endp
-
- ; Produce Beep
- ; BX = Duration
- ; DI = Frequency
-
- abeep proc
- push ax
- push bx
- push cx
- push dx
- push di
- mov al, 0B6h
- out 43h, al
- mov dx, 14h
- mov ax, 4F38h
- div di
- out 42h, al
- mov al, ah
- out 42h, al
- in al, 61h
- mov ah, al
- or al, 3
- out 61h, al
- delay: mov cx, 2801
- tone: loop tone
- dec bx
- jnz delay
- mov al, ah
- out 61h, al
- pop di
- pop dx
- pop cx
- pop bx
- pop ax
- ret
- abeep endp
-
- END start
-