(*----------------------------------------------------------------------*)
(*         Int24, Int24ON, Int24OFF, --- handle critical DOS errors     *)
(*----------------------------------------------------------------------*)

(*----------------------------------------------------------------------*)
(*                                                                      *)
(*     Remarks:                                                         *)
(*                                                                      *)
(*        This code is slightly modified from some written by Bela      *)
(*        Lubkin.                                                       *)
(*                                                                      *)
(*----------------------------------------------------------------------*)

CONST

   INT24Err     : BOOLEAN = FALSE;
   INT24ErrCode : BYTE    = 0;
   OldINT24     : ARRAY[1..2] OF INTEGER = (0,0);

VAR
   RegisterSet: RegPack;

(*----------------------------------------------------------------------*)
(*         Int24 --- set up DOS Interrupt 24 critical error handler     *)
(*----------------------------------------------------------------------*)

PROCEDURE Int24;

BEGIN (* Int24 *)

   INLINE
     ($2E/$C6/$06/ INT24Err /$01/$89/$EC/$83/$C4/$08/$89/$F8/$2E/$A2/
      INT24ErrCode /$58/$B0/$FF/$5B/$59/$5A/$5E/$5F/$5D/$1F/$07/$CF);
    { Turbo:  PUSH BP                    (Save caller's stack frame
              MOV  BP,SP                   Set up this procedure's stack frame
              PUSH BP                     ?)
      Inline: MOV  BYTE CS:[INT24Err],1  Set INT24Err to True
              MOV  SP,BP                 Get correct SP;  ADD: Discard saved
              ADD  SP,8                    BP, INT 24 return address & flags
              MOV  AX,DI                 Get INT 24 error code
              MOV  CS:[INT24ErrCode],AL  Save it in INT24ErrCode
              POP  AX                    Pop all registers
              MOV  AL,0FFH               Set FCB call error flag:
              POP  BX                      will cause Turbo I/O error on file
              POP  CX                      operations, no error on character
              POP  DX                      operations
              POP  SI
              POP  DI
              POP  BP
              POP  DS
              POP  ES
              IRET                       Return to next instruction }

End   (* Int24 *);

(*----------------------------------------------------------------------*)
(*              Int24ON --- Turn ON handling of interrupt 24            *)
(*----------------------------------------------------------------------*)

PROCEDURE Int24On;

BEGIN (* Int24ON *)

   INT24Err:=False;

   WITH RegisterSet DO
      BEGIN

         AX:=$3524;

         MsDos(RegisterSet);

         IF ( OldINT24[1] OR OldINT24[2] ) = 0 THEN
            BEGIN
               OldINT24[1] := ES;
               OldINT24[2] := BX;
            END;

         DS := CSeg;
         DX := Ofs(INT24);
         AX := $2524;

         MsDos( RegisterSet );

     END;

END   (* Int24ON *);

(*----------------------------------------------------------------------*)
(*             Int24OFF --- Turn OFF handling of interrupt 24            *)
(*----------------------------------------------------------------------*)

PROCEDURE Int24OFF;

BEGIN (* Int24OFF *)

   INT24Err:=False;

   IF ( OldINT24[1] <> 0 ) THEN
      WITH RegisterSet DO
         BEGIN

            DS := OldINT24[1];
            DX := OldINT24[2];
            AX := $2524;

            MsDos( RegisterSet );

         END;

    OldINT24[1] := 0;
    OldINT24[2] := 0;

END   (* Int24OFF *);

(*----------------------------------------------------------------------*)
(*      Int24Result --- Check for Turbo I/O or critical DOS error       *)
(*----------------------------------------------------------------------*)

FUNCTION INT24Result: INTEGER;

VAR
   I : INTEGER;

BEGIN (* INT24Result *)

   I := IOResult;

   IF INT24Err THEN
      BEGIN
         I := I + 256 * INT24ErrCode;
         INT24On;
      END;

   INT24Result := I;

END   (* INT24Result *);
