home *** CD-ROM | disk | FTP | other *** search
- PAGE 60,132
- TITLE 4DOS24H2.ASM
- SUBTTL Critical Error Handler for 4DOS
- ;
- ; Copenhagen, August 3. 1992 (revised May 1992)
- ;
- ; The documentation, this source file and the compiled program are released
- ; to the Public Domain. Nobody is authorized to charge any amount of money
- ; for the included files. Feel free to modify the code but please don't put
- ; my name under if redistributed.
- ;
- ; As a common convention the comments in this source file are Pascal-like
- ; statements to allow for a better overwiev of the program.
- ;
- ; The code is highly optimized to minimize use of memory but without
- ; compromising the user interface. I don't think it is possible to squeeze
- ; this code much more than a few bytes, but I would like to hear from
- ; everybody who succeeds in making this program use less memory (without
- ; loosing features). Also any other comments about bugs or whatever it might
- ; be would be very appreciated.
- ;
- ; You can reach me with E-mail at the following Internet address:
- ;
- ; ehlig@ask.diku.dk
- ;
- ; please use subject: 4DOS24H2
- ;
- ; If you cannot reach me through E-mail you can write to the following address:
- ;
- ; Niels Jensen
- ; Vaerebrovej 40,7,3
- ; 2880 Bagsvaerd
- ; Denmark DK
- ;
- ; Niels Jensen
- ;
- ; --------------------------------------
- ;
- ;
- ; To re-assemble using Microsoft Macro Assembler (MASM) or Borlands Turbo
- ; Assembler (TASM):
- ;
- ; TASM or MASM 4DOS24H2;
- ; LINK 4DOS24H2;
- ; EXE2BIN 4DOS24H2 4DOS24H2.COM
- ; DEL 4DOS24H2.EXE
- ; DEL 4DOS24H2.OBJ
- ;
- ; If you want 4DOS24H2 to be compatible with the old 40 columns modes change
- ; the define option on the command line to reflect:
- ;
- ; /Dshadow=1
- ;
- ; If you hate shadow simulation change the define option of the command to:
- ;
- ; /Dshadow=0
- ;
- ;--- Conditional defines ------------------------+------------------------------
- ; The following code causes two shadow columns as default in case nothing or
- ; a wrong value is specified on the command line.
- ;------------------------------------------------+------------------------------
- IF1 ;
- IFDEF shadow ;
- IF (shadow GT 2) + (shadow LT 0) ; Default num. of shadow cols.
- shadow = 2 ; if not defined.
- ENDIF ;
- ELSE ;
- shadow = 2 ; Default num. of shadow cols.
- ENDIF ; if value outside prop. range.
- ENDIF ;
- ;
- ;--- Boolean constants --------------------------+------------------------------
- False EQU 0 ;
- True EQU 1 ;
- ;
- ;--- Bit constants ------------------------------+------------------------------
- Bit7 EQU 80h ;
- Bit6 EQU 40h ;
- Bit5 EQU 20h ;
- Bit4 EQU 10h ;
- Bit3 EQU 08h ;
- Bit2 EQU 04h ;
- Bit1 EQU 02h ;
- Bit0 EQU 01h ;
- ;
- ;--- Colour constants ---------------------------+------------------------------
- Black EQU 00h ; Low intensity colours
- Blue EQU 01h ;
- Green EQU 02h ;
- Cyan EQU 03h ;
- Red EQU 04h ;
- Magenta EQU 05h ;
- Brown EQU 06h ;
- LightGray EQU 07h ;
- ;------------------------------
- Gray EQU 08h ; High intensity colours
- LightBlue EQU 09h ;
- LightGreen EQU 0Ah ;
- LightCyan EQU 0Bh ;
- LightRed EQU 0Ch ;
- LightMagenta EQU 0Dh ;
- Yellow EQU 0Eh ;
- White EQU 0Fh ;
- ;
- ;--- Key Definitions ----------------------------+------------------------------
- Enter EQU 0Dh ; Enter-key
- Escape EQU 1Bh ; Escape-key
- CtrlC EQU 03h ; Ctrl-C (Ctrl-Break)
- CtrlP EQU 10h ; Ctrl-P (Printer on/off)
- ;
- ;--- Interrupt constants ------------------------+------------------------------
- Video EQU 10h ; BIOS Video service
- Equipmnt EQU 11h ; BIOS Equipment service
- KeyBoard EQU 16h ; BIOS Keyboard service
- ReadKey EQU 00h ; BIOS Keyboard: Read key
- TestKey EQU 01h ; BIOS Keyboard: Test for key
- Quit EQU 20h ; DOS Service: Terminate
- DOS EQU 21h ; DOS Service Interrupt
- GetKeyPress EQU 07h ; DOS Service: Get key (raw)
- DosReadKey EQU 08h ; DOS Service: Read keystroke
- PrintStr EQU 09h ; DOS Service: Print String
- SetVector EQU 25h ; DOS Service: Set int. vector
- GetVector EQU 35h ; DOS Service: Get int. vector
- FreeMem EQU 49h ; DOS Service: Free memory blk.
- BreakInt EQU 23h ; Interrupt 23h (Ctrl-Break)
- CritErrInt EQU 24h ; Interrupt 24h (Crit. Err.)
- TSR EQU 27h ; Terminate and stay resident
- MultiPlex EQU 2Fh ; Multiplex interrupt
- IDvector EQU 61h ; Vector used for identification
- ;
- ;--- Screen related addresses -------------------+------------------------------
- MonoSeg EQU 0B000h ; Segment adr. for mono-scr.
- ColrSeg EQU 0B800h ; Segment adr. for colour-scr.
- ScrRows EQU 0484h ; Ofs. adr. of screen rows
- ScrCols EQU 044Ah ; Ofs. adr. of screen columns
- RegenBufLen EQU 044Ch ; Ofs. adr. of regen.buf.length
- ;
- ;--- Response constants -------------------------+------------------------------
- IgnoreOK EQU Bit5 ; Set if ignore allowed
- RetryOK EQU Bit4 ; Set if retry allowed
- FailOK EQU Bit3 ; Set if fail allowed
-
- IgnoreResp EQU 0 ; Response in case of ignore
- RetryResp EQU 1 ; Response in case of retry
- AbortResp EQU 2 ; Response in case of abort
- FailResp EQU 3 ; Response in case of fail
- ;
- ;--- Window constants ---------------------------+------------------------------
- WinLins EQU 14 ; Num. of lines in window
-
- IF shadow EQ 0
- WinCols EQU 39 ; Num. of columns in window
- ELSE
- IF shadow EQ 1
- WinCols EQU 40 ; Num. of columns in window
- ELSE
- WinCols EQU 41 ; Num. of columns in window
- ENDIF
- ENDIF
-
- WinSize EQU WinLins*(WinCols-2) ; Num. of chars in window
- TopLines EQU 4 ; Num. of lines over window
- TxtAttr EQU Yellow+(Blue SHL 4) ; Attribute of the window text
- ;
- ; Note: Remember to change the colour of the abort-message in the
- ; window accordingly if you change TxtAttr
- ;
- ;--- Misc. Program Constants --------------------+------------------------------
- IDsign EQU '4D' ; Identification letters
- MemSwc EQU 'M' ; Memory information switch
- ;
- ;------------------------------------------------+------------------------------
- ;
- ; M A C R O S
- ;
- ;------------------------------------------------+------------------------------
- PushM MACRO regs ;; Push Multiple registers
- IRP register,<regs> ;; - Pushes all registers
- push register ;; between "<" and ">"
- ENDM ;; separated by commas.
- ENDM ;; Ex. PushM <ax,bx,cx>
- ;;
- PopM MACRO regs ;; Pop Multiple registers
- IRP register,<regs> ;; - Pops all registers
- pop register ;; between "<" and ">"
- ENDM ;; separated by commas.
- ENDM ;; Ex. PopM <cx,bx,ax>
- ;------------------------------------------------+------------------------------
- ;
- ; C O D E S T A R T
- ;
- ;------------------------------------------------+------------------------------
- Code SEGMENT
- ASSUME CS:Code, DS:Code, ES:Code, SS:Code
- ;--- PSP addresses ------------------------------+------------------------------
- ORG 12h ; - Offset address of old 24h
- PSP24hOfs LABEL WORD ; handler.
- ORG 14h ; - Segment address of old 24h
- PSP24hSeg LABEL WORD ; handler.
- ORG 16h ; - Segment address of parent
- ParentPSP LABEL WORD ; PSP.
- ORG 2Ch ; - Segment address of
- EnvSegm LABEL WORD ; environment block.
- ORG 5Ch ; - Offset where resident code
- FreePSP LABEL WORD ; overlays unused part of PSP.
- ORG 80h ; - Field indicating parameter
- ParLen LABEL BYTE ; length
- ORG 81h ; - Start of command line
- ParmStr LABEL BYTE ; parameter string
- ORG 100h ; - Starting offset for COM-prgs.
- ;------------------------------------------------+------------------------------
- Start: JMP Begin ; Go to installation process
- ORG 100h+FreePSP ; Start offset address 15Ch
- IDintOfs LABEL NEAR ; If ID-int goto old vect. adr.
- DB 0EAh ; JMP Far Ptr OldIDvector
- OldIDvectOfs DW ? ; { Original content of the }
- OldIDvectSeg DW ? ; { ID-vector. }
- ;
- ;--- Variables ----------------------------------+------------------------------
- IDword DW IDsign ; Identification word
- ScrSeg DW ColrSeg ; Screen address.
- DevHdr LABEL DWORD ; Device Header Pointer
- DevHdrOfs DW ? ; Address of the device
- DevHdrSeg DW ? ; in error from BP:SI.
- Errcode DW ? ; Error code from DI.
- ;
- ;--- Error message strings ----------------------+------------------------------
- ClrStr DB (WinCols-7) DUP(' '),0 ; Clear string for erasing
- Msg0 DB 'Disk is write protected',0 ; Disk write protected
- Msg1 DB 'Unknown unit',0 ; Device not known
- Msg2a DB 'Disk drive not ready',0 ; Disk drive not ready
- Msg2b DB 'Device not ready',0 ; Device not ready
- Msg3 DB 'Unknown command',0 ; Device command unrecognized
- Msg4 DB 'Data error (CRC)',0 ; Disk data error
- Msg5 DB 'Bad request struc. length',0; Device call format wrong
- Msg6 DB 'Seek error',0 ; Disk seek error
- Msg7 DB 'Unknown media type',0 ; Disk not recognized
- Msg8 DB 'Sector not found',0 ; Disk sector not found
- Msg9 DB 'Printer out of paper',0 ; Device out of paper
- MsgA DB 'Write fault',0 ; Device write fault
- MsgB DB 'Read fault',0 ; Device read fault
- MsgC DB 'General failure',0 ; Disk general error
- MsgF DB 'Invalid disk change',0 ; Disk is replaced
- Msg10h DB 'FCB unavailable',0 ; Device error
- Msg11h DB 'Sharing buffer overflow',0 ; Device error
- MsgU DB 'Unknown error',0 ; Wrong error code
- ;
- ErrMsg DW Msg0, Msg1, Msg2a, Msg3, Msg4; String pointer table with
- DW Msg5, Msg6, Msg7, Msg8, Msg9 ; pointers to the error
- DW MsgA, MsgB, MsgC, MsgU, MsgU ; messages
- DW MsgF, Msg10h, Msg11h ;
- ;
- ;--- Disk error message parts -------------------+------------------------------
- DskMsg1 DB 'Disk ',0 ;
- DskMsg2A DB 'read ',0 ;
- DskMsg2B DB 'write ',0 ;
- DskMsg3 DB 'error on drive ' ;
- Drive DB 'A: in ',0 ;
- DskMsg4A DB 'DOS system area',0 ;
- DskMsg4B DB 'FAT-area (File Allocation Table)',0
- DskMsg4C DB 'the root directory area',0 ;
- DskMsg4D DB 'the data area',0 ;
- DskMsg4 DW DskMsg4A,DskMsg4B,DskMsg4C,DskMsg4D
- ;
- ;--- Device error message parts -----------------+------------------------------
- DevMsg1 DB 'Device error on device ',0 ;
- DevMsg2 DB 'Memory copy of FAT is bad',0;
- ;
- ;--- Basic message window -----------------------+------------------------------
-
- IF shadow EQ 0
-
- MsgBuf DB '┌──── DOS Critical Error Handler ────┐'
- DB '│ Version 2.00 │'
- DB '│ │'
- DB '│ '
- MsgPos1 DB ' │'
- DB '│ '
- MsgPos2 DB ' │'
- DB '│ │'
- DB '│ Error: '
- MsgPos3 DB ' │'
- DB '│ │'
- DB '│ Please hit: │'
- DB '│ A - to Abort current operation │'
- DB '│ R - to Retry the operation │'
- DB '│ '
- MsgPos5 DB ' │'
- DB '│ '
- MsgPos6 DB ' │'
- DB '└─────────────────────────────────────┘'
-
- ELSE
- IF shadow EQ 1
-
- MsgBuf DB '┌──── DOS Critical Error Handler ────┐'
- DB '│ Version 2.00 │ '
- DB '│ │ '
- DB '│ '
- MsgPos1 DB ' │ '
- DB '│ '
- MsgPos2 DB ' │ '
- DB '│ │ '
- DB '│ Error: '
- MsgPos3 DB ' │ '
- DB '│ │ '
- DB '│ Please hit: │ '
- DB '│ A - to Abort current operation │ '
- DB '│ R - to Retry the operation │ '
- DB '│ '
- MsgPos5 DB ' │ '
- DB '│ '
- MsgPos6 DB ' │ '
- DB '└─────────────────────────────────────┘ '
- DB ' '
- ELSE
- MsgBuf DB '┌──── DOS Critical Error Handler ────┐'
- DB '│ Version 2.00 │ '
- DB '│ │ '
- DB '│ '
- MsgPos1 DB ' │ '
- DB '│ '
- MsgPos2 DB ' │ '
- DB '│ │ '
- DB '│ Error: '
- MsgPos3 DB ' │ '
- DB '│ │ '
- DB '│ Please hit: │ '
- DB '│ A - to Abort current operation │ '
- DB '│ R - to Retry the operation │ '
- DB '│ '
- MsgPos5 DB ' │ '
- DB '│ '
- MsgPos6 DB ' │ '
- DB '└─────────────────────────────────────┘ '
- DB ' '
- ENDIF
- ENDIF
- ;
- ;--- Response message parts ---------------------+------------------------------
- ; RetryMsg DB 'R - to Retry the operation',0;
- ; RetryMsgLen EQU $-RetryMsg-1 ;
-
- IgnoreMsg DB 'I - to Ignore the error ',0;
- IgnoreMsgLen EQU $-IgnoreMsg-1 ;
- FailMsg DB 'F - to Fail the operation',0;
- ;
- ;------------------------------------------------+------------------------------
- ;
- ; S U B R O U T I N E S
- ;
- ;-------------------------------------------------------------------------------
- ; S w a p
- ;-------------------------------------------------------------------------------
- ; Does : Swaps the buffer containing the message window with the data on
- ; the screen located where the window is to be displayed.
- ; On call : DS:SI = Source; ES:DI = Destination (MsgBuf/Screen)
- ; Uses : BX, BP, CX, SI, DI
- ; Changes : BX, BP, CX, SI, DI
- ;
- ;--- Start of Swap ------------------------------+------------------------------
- Swap PROC NEAR ; Procedure Swap;
- ; begin
- MOV SI, Offset MsgBuf ; ds:si:= MsgBuf;
- MOV DI, DX ; es:di:= Scr;
- IF shadow EQ 0
- MOV CX, WinLins ; cx:= WinLins;
- ELSE
- MOV CX, WinLins+1 ; cx:= WinLins+1;
- ENDIF
- Loop1: PUSH CX ; for cx1:= WinLins+1 downto 1 do
- IF shadow NE 0
- MOV AX, CX ;
- DEC AX ; ax:= cx1 - 1;
- ENDIF
- MOV CL, WinCols ; if (cx1 = WinLins+1) or
- IF shadow NE 0
- JE NoShadC ; (cx1 = 1)
- CMP AL, WinLins-1 ; then tmp:= WinCols
- JBE Loop11 ; else tmp:= WinCols+1;
- IF shadow EQ 1
- NoShadC: DEC CX ;
- ELSE
- NoShadC: SUB CL, 2 ; for cx2:= tmp downto 1 do begin
- ENDIF
- ENDIF
- Loop11: MOV BX, ES:[DI] ; bx:= Scr[ds:si];
- IF shadow NE 0
- CMP AL, WinLins-1 ; if (cx1 <= WinLins)
- JA NoShade ; then
- OR AX, AX ; if (cx2 <= 2) or
- JZ Shade ; (cx1 = 1)
- IF shadow EQ 1
- CMP CL, 1 ;
- JNE NoShade ;
- ELSE
- CMP CL, 2 ;
- JA NoShade ;
- ENDIF
- Shade: MOV [SI], BL ; then Buf[si]:= bl;
- ENDIF
- NoShade: MOVSW ; Scr[di]:= Buf[si];
- MOV [SI-2], BX ; di:= di+2; si:= si+2;
- LOOP Loop11 ; Buf[si-2]:= bx
- ; end; (* for cx2 ... *)
- IF shadow NE 0
- CMP AL, WinLins ; if (ax = WinLins) or
- JE Adj ; (ax = 1)
- CMP AL, 1 ;
- JNE NoAdj ; then
- IF shadow EQ 1
- Adj: INC DI ;
- INC DI ; di:= di + 2;
- ELSE
- Adj: ADD DI, 4 ; di:= di + 4;
- ENDIF
- ENDIF
- NoAdj: ADD DI, BP ; di:= di + bp;
- POP CX ;
- LOOP Loop1 ; end (* for cx1 ... *)
- RET ; end;
- Swap ENDP ;
- ;------------------------------------------------+------------------------------
- ; P u t S t r
- ;-------------------------------------------------------------------------------
- ; Does : Displays a null-teminated string. Length must be greater than 0.
- ; On call : AH = Attribute Byte;
- ; DS:SI = ^Source;
- ; ES:DI = ^Destination (Screen memory)
- ; Uses : AX, SI, DI, DS, ES
- ; Changes : AL, SI, DI
- ;
- ;------------------------------------------------+------------------------------
- PutStr PROC NEAR ; Procedure PutStr;
- again: LODSB ; begin
- STOSW ; repeat
- CMP Byte Ptr [SI], 0 ; al:= Buf[si]; write(ax);
- JNE again ; Inc(si)
- RET ; until Buf[si] = 0
- PutStr ENDP ; end;
- ;------------------------------------------------+------------------------------
- ;
- ; N e w i n t e r r u p t h a n d l e r
- ;
- ;-------------------------------------------------------------------------------
- ;
- ; In case of a critical error during a graphics session this handler would
- ; not behave normaly because the information window is written directly to
- ; the screen memory. Instead the handler checks for graphics modes and
- ; calls the old critical error handler in case the current mode is not a
- ; text mode.
- ;
- ; Graphics modes are detected automatically by checking the length of the
- ; screen regenerate buffer and compare it against the (last) text screen
- ; solution. This is only tested on a Tseng ET4000 based Super VGA card and
- ; therefore NOT garanteed to work with other display adapters.
- ;
- ;
- ; Special register use:
- ;
- ; BP: Holds the constant 2*(ScrCols-WinCols) used during swapping of
- ; the message window and the screen. The constant expresses the
- ; byte distance in display memory from the end of a line in the
- ; message window to the beginning of the next.
- ;
- ; DX: Holds the constant (TopLines*2*ScrCols + 2*Indent) which is the
- ; offset from the start of display memory to the upper left corner
- ; of the message window.
- ;
- ;------------------------------------------------+------------------------------
- New24h:
- PushM <BX,CX,DX,SI,DI,BP,DS,ES>; Save(registers);
- PUSH AX ; {AX = error locus info}
- PUSH CS ; ds:= cs;
- POP DS ; {BP:SI => dev. drv. header}
- MOV DevHdrOfs, SI ; DevHdrOfs:= si;
- MOV DevHdrSeg, BP ; DevHdrSeg:= bp;
- AND DI, 001Fh ; di:= di and 001Fh;
- MOV ErrCode, DI ; ErrCode:= di;
- XOR DX, DX ; dx:= 0;
- MOV ES, DX ; es:= dx;
- ;--- Check for graphics mode ---------------------------------------------------
- Patch1 LABEL WORD ; { Address for patching }
- MOV AL, 24 ; {$IF EGA} al:= ScrRows-1;
- NOP ; {$ELSE} al:= 24;
- NOP ; {$ENDIF}
- INC AX ; al:= al+1;
- MUL Byte Ptr ES:ScrCols ; ax:= ScrRows*ScrCols;
- SHL AX, 1 ; ax:= ax*2;
- MOV DX, ES:RegenBufLen ; dx:= RegenBufLength;
- SHR DX, 1 ; dx:= dx/2;
- JZ OldHandler ; if (dx=0) or (ax<=dx)
- CMP AX, DX ; then begin
- JA TxtMode ; { Jump to old handler }
- OldHandler: PopM <AX,ES,DS,BP,DI,SI,DX,CX,BX>; Rest(regs);
- DB 0EAh ; JMP Far Ptr OldHandler
- OldInt24hOfs DW ? ; { Pointer to original }
- OldInt24hSeg DW ? ; { int 24h handler }
- ; end;
- ;--- Calculate top margin and window start position ----------------------------
-
- TxtMode: MOV AX, ES:ScrCols ; ax:= ScrCols;
- MOV BP, AX ; bp:= ax;
- SUB BP, WinCols ; bp:= ScrCols - WinCols;
- MOV AH, TopLines*2 ; {Calc. byte cnt for topmarg}
- MUL AH ; ax:= TopLines * 2*ScrCols;
- ADD AX, BP ; ax:= ax + Indent;
- SHL BP, 1 ; bp:= 2 * bp;
- MOV DX, AX ; dx:= ax; { Window start pos }
- IF (WinCols AND 1) ; if Odd(WinCols)
- DEC DX ; then dx:= dx - 1;
- ENDIF ;
- PUSH CS ; { Setup ES }
- POP ES ; es:= cs;
-
- ;--- Test bit 7 for disk error -------------------------------------------------
-
- POP BX ; { Get org. AX in BX }
- PUSH BX ; bx:= ErrInfo;
- MOV AH, TxtAttr ; ah:= TxtAttr;
- MOV DI, Offset MsgPos1 ; di:= MsgPos1;
- TEST BH, Bit7 ; if DiskError
- JNZ GetName ; then begin
- ;--- Put disk error message ----------------------------------------------------
- MOV ErrMsg[2*2], Offset Msg2a; ErrMsg[2]:= Msg2a;
- MOV SI, Offset DskMsg1 ; si:= ^DskMsg1;
- CALL PutStr ; PutStr(si,di);
- ;--- Get error type info from bit 0 --------------------------------------------
- TEST BH, Bit0 ; if WriteError
- MOV SI, Offset DskMsg2A ; then si:= ^DskMsg2B
- JZ ReadError ; else si:= ^DskMsg2A;
- MOV SI, Offset DskMsg2B ; PutStr(si,di);
- ReadError: CALL PutStr ; { Patch drive letter }
- ADD Drive, BL ; Inc(DskMsg3[Drv],cl);
- MOV SI, Offset DskMsg3 ; si:= ^DskMsg3;
- CALL PutStr ; PutStr(si,di);
- MOV Drive, 'A' ; DskMsg3[Drv]:= 'A';
- ;--- Get error area info from bits 1 and 2 -------------------------------------
- MOV DI, Offset MsgPos2 ; di:= MsgPos2;
- PUSH DI ;
- MOV BL, BH ;
- AND BX, 0006h ; bx:= bx mod 7;
- MOV SI, Offset ClrStr ; si:= Ofs(ClrStr);
- CALL PutStr ; PutStr(si,di);
- POP DI ; di:= MsgPos2;
- MOV SI, DskMsg4[BX] ; si:= DskMsg4[bx];
- CALL PutStr ; PutStr(si,di)
- JMP Short GetError ; end
-
- ;--- Device error - test bit 15 of device attribute for char/blok device -------
- GetName:
- MOV ErrMsg[2*2], Offset Msg2b; else begin
- PUSH ES ; ErrMsg[2]:= Msg2b;
- LES SI, DevHdr ; es:si:= ^DeviceHeader;
- MOV CX, ES:[SI+4] ; cx:= DeviceAttr;
- MOV SI, Offset DevMsg1 ;
- TEST CH, Bit7 ; if CharDevice
- JNZ CharDev ; then si:= DevMsg1
- MOV SI, Offset DevMsg2 ; else si:= DevMsg2;
- CharDev: POP ES ;
- CALL PutStr ; PutStr(si,di);
- TEST CH, Bit7 ;
- JZ ClrMsgPos2 ; if CharDevice
- PUSH DS ; then begin {Get dev. name}
- LDS SI, DevHdr ; ds:si:= ^DeviceName;
- ADD SI, 10 ; for cx1:= 1 to 8 do begin
- MOV CX, 8 ; Win[di]:= DevName[si+10];
- GetLoop1: LODSB ; Inc(di); Inc(si)
- STOSW ; end
- LOOP GetLoop1 ; end;
- POP DS ; si:= ClrStr;
- ClrMsgPos2: MOV SI, Offset ClrStr ; di:= MsgPos2;
- MOV DI, Offset MsgPos2 ; PutStr(si,di)
- CALL PutStr ; end;
-
- ;--- Generate specific error information ---------------------------------------
- GetError:
- MOV DI, Offset MsgPos3 ; di:= MsgPos3;
- MOV SI, Offset ClrStr+6 ; si:= SubStr(6,ClrStr);
- CALL PutStr ; PutStr(si,di);
- MOV DI, Offset MsgPos3 ; di:= MsgPos3;
- MOV SI, Offset MsgU ;
- CMP ErrCode, 0011h ;
- JA NoValidCode ; if ErrCode > 11h
- MOV SI, ErrCode ; then si:= MsgU { Unkn. err. }
- SHL SI, 1 ; else si:= ErrMsg[ErrCode];
- MOV SI, ErrMsg[SI] ;
- NoValidCode: CALL PutStr ; PutStr(si,di);
-
- ;--- Find out what response is allowed -----------------------------------------
-
- MOV SI, Offset ClrStr ; si:= ClrStr;
- MOV DI, Offset MsgPos6 ; di:= MsgPos6;
- CALL PutStr ; PutStr(si,di);
- POP BX ; bx:= errlocus;
- MOV DI, Offset MsgPos5 ; { Test for retry }
- ; MOV DI, Offset MsgPos4 ; { Test for retry }
- ;TestRetry: ;
- ; TEST BH, RetryOK ; if RetryOK
- ; JZ TestIgnore ; then begin
- ; MOV SI, Offset RetryMsg ; PutStr(RetryMsg);
- ; CALL PutStr ; di:= NextPos
- ; ADD DI, 2*(WinCols-RetryMsgLen);
- TestIgnore: ; end;
- TEST BH, IgnoreOK ; if IgnoreOK
- JZ TestFail ; then begin
- MOV SI, Offset IgnoreMsg ; PutStr(IgnoreMsg);
- CALL PutStr ; di:= NextPos
- ADD DI, 2*(WinCols-IgnoreMsgLen);
- TestFail: ; end;
- MOV SI, Offset ClrStr+3 ; if FailOK
- TEST BH, FailOK ; then si:= FailMsg
- JZ EndRespTst ; else si:= ClrStr;
- MOV SI, Offset FailMsg ;
- EndRespTst: CALL PutStr ; PutStr(SI,DI);
- ;--- Show message window -------------------------------------------------------
- MOV ES, ScrSeg ; es:= ScrSeg;
- PUSH BX ;
- CALL Swap ; Swap(Screen,MsgBuf);
- POP BX ;
- ;--- Get user response ---------------------------------------------------------
- GetKey: MOV AH, TestKey ; { Get keystroke }
- INT KeyBoard ; repeat
- JZ GetKey ; while not KeyPrs do
- CMP AL, CtrlP ; TestKey(al);
- JNE NormalKey ; if al = '^P'
- MOV AH, DosReadKey ; then
- INT Dos ; DosReadKey(al)
- JMP Short GetKey ; until al <> '^P';
-
- NormalKey: MOV AH, ReadKey ;
- INT Keyboard ; ReadKey(al);
- SUB AL, 'A' ;
- CMP AL, ('Z'-'A') ; if al in ['A'..'Z']
- JA ProcessIgnore ; then
- ADD AL, 20h ; al:= LowCase(al);
- ;--- Process response ----------------------------------------------------------
- ; case al of
- ProcessIgnore: CMP AL, ('i'-'A') ; 'i': begin {** Ignore **}
- JNE ProcessRetry ; if Not IgnoreOK
- TEST BH, Bit5 ; then goto GetKey;
- JZ GetKey ; al:= 0;
- MOV AL, IgnoreResp ; end;
- ProcessRetry: CMP AL, ('r'-'A') ; 'r',
- JE RetryAct ;
- CMP AL, (Enter-'A') ; Enter,
- JE RetryAct ;
- CMP AL, (' '-'A') ; ' ': begin {** Retry **}
- JNE ProcessFail ; al:= 1
- RetryAct: MOV AL, RetryResp ; end;
- ;TEST BH, Bit4 ; if Not RetryOK
- ;JZ GetKey ; then goto GetKey;
- ProcessFail: CMP AL, ('f'-'A') ; 'f': begin {** Fail **}
- JNE ProcessAbort ; if Not IgnoreOK
- TEST BH, Bit3 ; then goto GetKey
- JZ GetKey ; al:= 3;
- MOV AL, FailResp ; end;
- ProcessAbort: CMP AL, ('a'-'A') ; 'a',
- JE AbortAct ;
- CMP AL, ('q'-'A') ; 'q',
- JE AbortAct ;
- CMP AL, ('x'-'A') ; 'x',
- JE AbortAct ;
- CMP AL, (CtrlC-'A') ; ^C ,
- JE AbortAct ;
- CMP AL, (Escape-'A') ; Esc: begin {** Abort **}
- JNE ElseCase ; AL:= 2
- AbortAct: MOV AL, AbortResp ; end;
- ElseCase: CMP AL, FailResp ; else goto GetKey
- JA GetKey ; end; { case }
- ;--- Restore screen and exit ---------------------------------------------------
- PUSH AX ;
- CALL Swap ; Swap(MsgBuf,Screen);
- POP AX ;
- XOR AH, AH ; ah:= 0;
- POPM <ES,DS,BP,DI,SI,DX,CX,BX>; Rest(regs)
- IRET ; end;
- EndOfCode EQU $ ;
- ;----------------------------------------------+--------------------------------
- ;
- ; E N D O F R E S I D E N T C O D E
- ;
- ;-------------------------------------------------------------------------------
- ; L o a d e r - p r o g r a m
- ;
- ; This part of the code is responsible for:
- ; - loading the handler
- ; - high load without trouble under 386Max or QEMM if required
- ; - detection of screen hardware
- ; - the handler being continuously active during shells
- ;
- ;------------------------------------------------+------------------------------
- ; P R O C E D U R E D E C L A R A T I O N S
- ;------------------------------------------------+------------------------------
- ; Procedure WriteInt (ax: int);
- ;------------------------------------------------+------------------------------
- WriteInt PROC NEAR ; Procedure WriteInt (ax:int);
- PushM <AX,BX,CX,DX,BP> ; { Writes int w/o leading 0 }
- MOV BX, 0007h ; begin
- MOV BP, 10000 ; bp:= 10000;
- XOR CX, CX ; cx:= 0;
- WriteLoop: XOR DX, DX ; repeat
- DIV BP ; dx:= ax mod bp;
- PUSH DX ; ax:= ax div bp;
- ADD CL, AL ; cl:= cl + al;
- JZ LeadZero ; if cl > 0
- ADD AL, '0' ; then begin
- MOV AH, 0Eh ; al:= Char(al);
- INT Video ; write(al)
- LeadZero: MOV AX, BP ; end;
- MOV BP, 10 ;
- XOR DX, DX ; dx:= 0;
- DIV BP ; bp:= bp div 10;
- MOV BP, AX ;
- POP AX ; ax:= dx
- CMP BP, 0 ; until bp <= 0;
- JG WriteLoop ; end;
- PopM <BP,DX,CX,BX,AX> ;
- RET ;
- WriteInt ENDP ;
- ;------------------------------------------------+------------------------------
- ; Procedure WriteHex (ax: int);
- ;------------------------------------------------+------------------------------
- WriteHex PROC NEAR ; Procedure WriteHex (ax:int);
- PushM <BX,CX,DX,AX> ; begin
- MOV AH, 2 ; ah:= 2;
- MOV CX, 4 ; cx:= 4;
- WriteLoop1: POP BX ; for i:= 1 to cx do begin
- ROL BX, 1 ; bx:= Rotate(bx,1);
- ROL BX, 1 ; bx:= Rotate(bx,1);
- ROL BX, 1 ; bx:= Rotate(bx,1);
- ROL BX, 1 ; bx:= Rotate(bx,1);
- PUSH BX ;
- AND BX, 000Fh ; bx:= bx mod 16;
- MOV DL, HexCif[BX] ; dl:= HexCif[bx];
- INT Dos ; write(dl);
- LOOP WriteLoop1 ; end
- PopM <AX,DX,CX,BX> ; end;
- RET ;
- ;------------------------------------------------+ { Local constant }
- HexCif DB '0123456789ABCDEF' ; const HexCif = '0..9ABCDEF';
- WriteHex ENDP ;
- ;------------------------------------------------+------------------------------
-
- ;--- Test if already installed -------------------------------------------------
-
- Begin: ; begin
- MOV AL, CritErrInt ;
- MOV AH, GetVector ;
- INT Dos ; GetVect(CritErrInt,es:bx);
- PUSH ES ; Save(Int24hSeg);
- PUSH BX ; Save(Int24hOfs);
- ; { Install by modifying PSP }
- MOV PSP24hOfs, Offset New24h ; PSP24hOfs:= Ofs(New24h);
- MOV AH, GetVector ; { See if already installed }
- MOV AL, IDvector ; GetVect(IDvector,es:bx);
- INT Dos ;
- CMP ES:IDword, IDsign ; if es:IDword = IDsign
- JNE NotInst ; then begin
-
- ;--- Handler already installed -------------------------------------------------
- ; { Reinstall handler }
- MOV PSP24hSeg, ES ; PSP24hSeg:= es;
- ; { Update stored address }
- ; { of old handler. }
- POP ES:OldInt24hOfs ; Rest(es:OldInt24hOfs);
- POP ES:OldInt24hSeg ; Rest(es:OldInt24hSeg);
- MOV AX, 4C00h ; Halt(0)
- INT Dos ; end;
-
- ;--- Handler not installed -----------------------------------------------------
-
- NotInst: MOV DX, Offset ProgInfo ; { Print program info }
- MOV AH, PrintStr ; write(ProgInfo);
- INT Dos ;
- MOV AX, 0D44Dh ; { Test if 4DOS is present }
- XOR BX, BX ; ax:= 0D44Dh;
- INT MultiPlex ; bx:= 0;
- CMP AX, 44DDh ; MultiPlex(ax,bx);
- JE Found4DOS ; if ax <> 44DDh
- MOV DX, Offset LoadErr1 ; then begin
- MOV AH, PrintStr ; { 4DOS not found }
- INT Dos ; write(LoadErr1);
- MOV AH, GetKeyPress ; { Wait for key press }
- INT Dos ; GetKeyPress;
- MOV AX, 4C01h ; Halt(1)
- INT Dos ; end
- Found4DOS: ; { Install by modifying PSP }
- POP OldInt24hOfs ; OldInt24hOfs:= Int24hOfs;
- POP OldInt24hSeg ; OldInt24hSeg:= Int24hSeg;
- ;
- MOV BX, CS ; { Calc. new segm. value }
- SUB BX, 10h ;
- MOV PSP24hSeg, BX ; PSP24hSeg:= Seg(New24h);
-
- ;--- Release Environment Block -------------------------------------------------
- MOV ES, CS:EnvSegm ; { Release environm. block }
- MOV AH, FreeMem ; ES:= ^Env;
- INT Dos ; FreeMem(ES);
- ;--- Screen-Detection ----------------------------------------------------------
- MOV AH, 12h ; { Test for EGA+ adapter }
- MOV BL, 10h ; bl:= 10h;
- INT Video ; GetEGAinfo(bl);
- CMP BL, 10h ; if bl <> 10h
- JE TestCOorBW ; then begin
- MOV Patch1, 0A026h ; PatchByte(Patch1);
- MOV [Patch1+2], 0484h ; PatchByte(Patch1+2)
- TestCOorBW: ; end;
- INT Equipmnt ; BIOS(Equip);
- TEST AX, Bit5+Bit4 ; if Bit4 and Bit5
- JNP EndDetect ; then ScrSeg:= MonoSeg
- MOV ScrSeg, MonoSeg ; else ScrSeg:= ColrSeg;
- EndDetect: ;
- ;--- Test for memory info switch as paramter -----------------------------------
- MOV SI, Offset ParmStr ; si:= Ofs(ParmStr);
- XOR CX, CX ; cx:= Length(ParmStr);
- MOV CL, ParLen ; if cx <> 0
- JCXZ NoMemStat ; then begin
- ; { ParmStr[1] always space }
- ; { or switch char ('/'). }
- ParTest: INC SI ; repeat
- OR Byte Ptr [SI], 20h ; Inc(si); Dec(cx);
- SwcTest: CMP Byte Ptr [SI], (MemSwc or 20h);LowCase([si]);
- LOOPNE ParTest ; until ([si]=MemSwc)or(cx=0);
- JNE NoMemStat ; if [si] = MemSwc
- ;--- Print Memory Statistics ---------------------------------------------------
- MOV DX, Offset MemInfo ; then begin
- MOV AH, PrintStr ; { Print memory status }
- INT Dos ; write(MemInfo);
- MOV AX, CS ; { Print load address }
- CALL WriteHex ; WriteHex(CS);
- MOV DX, Offset MemInfo1 ;
- MOV AH, PrintStr ; { Print memory usage }
- INT Dos ; write(MemInfo1);
- MOV AX, Offset EndOfCode-100h;
- CALL WriteInt ; WriteInt(EndOfCode-100);
- MOV DX, Offset MemInfo2 ;
- MOV AH, PrintStr ; writeln(MemInfo2);
- INT Dos ; writeln;
- ; end
- NoMemStat: ; end;
- ;--- Install Identification mark -----------------------------------------------
- MOV AL, IDvector ; { Install identification }
- MOV AH, GetVector ; GetVector(IDvect,es:bx);
- INT Dos ; OldIDvectSeg:= es;
- MOV OldIDvectOfs, BX ; OldIDvectOfs:= bx;
- MOV OldIDvectSeg, ES ;
- PUSH DS ; Save(ds); {!}
- MOV DS, PSP24hSeg ; ds:= Seg(IDintSeg);
- MOV DX, Offset IDintOfs ; dx:= Ofs(IDintOfs);
- MOV AH, SetVector ; SetVect(IDvect,ds:dx);
- INT Dos ;
- ;--- High Load precautions under QEMM and 386Max -------------------------------
- PUSH DS ; { Modify parent PSP. }
- MOV DS, CS:ParentPSP ; ds:= Seg(ParentPSP);
- MOV PSP24hOfs, Offset New24h ; ds:PSP24hOfs:= Ofs(New24h);
- POP PSP24hSeg ; ds:PSP24hSeg:= Seg(New24h);
- POP DS ; Rest(ds);
- ;--- Move code to overlay unused part of PSP -----------------------------------
- PUSH CS ; { Overlay FCB-area and
- POP ES ; parameters to save mem. }
- MOV DI, Offset FreePSP ; di:= Ofs(FreePSP);
- MOV SI, Offset IDintOfs ; si:= Ofs(code);
- MOV CX, Offset EndOfCode-IDintOfs; cx:= EndOfCode-IDintOfs;
- CLD ; for i:= 0 to cx-1 do
- REP MOVSB ; Mem[di+i]:= Mem[si+i];
- ;--- Terminate and Stay Resident ----------------+------------------------------
- MOV DX, Offset EndOfCode-(IDintOfs-FreePSP)
- INT TSR ; Keep
- ; end.
- ;----------------------------------------------+--------------------------------
-
- ProgInfo DB '4DOS Critical Error Handler Version 2.00, rev. B',10,13
- DB 'Written by Niels Jensen - May, 1993',13,10,'$'
-
- MemInfo DB 'Resident at address $'
- MemInfo1 DB ':0000 (hex) consuming $'
- MemInfo2 DB ' bytes of memory.',13,10,'$'
-
- LoadErr1 DB 10
- DB 'The critical error handler is not installed due to an error.',13,10,10
- DB 'The running command interpreter is not a version of 4DOS or NDOS.',10,13
- DB 'You need the 4DOS or NDOS command interpreter from JP Software to',10,13
- DB 'use this handler - it will not work under COMMAND.COM.',13,10,10
- DB 'Press any key to continue . . .$'
- ;------------------------------------------------+------------------------------
- Code ENDS
- END Start
-