home *** CD-ROM | disk | FTP | other *** search
- {****************************************************************************}
- { S T A Y S U B S . I N C }
- {****************************************************************************}
- {---------------------------------------------------------}
- { S E T D T A }
- {---------------------------------------------------------}
- Procedure SetDTA(var segment, offset : integer );
- BEGIN
- regs.ax := $1A00; { Function used to get current DTA address }
- regs.Ds := segment; { Segment of DTA returned by DOS }
- regs.Dx := offset; { Offset of DTA returned }
- MSDos( regs ); { Execute MSDos function request }
- END;
- {---------------------------------------------------------}
- { G E T D T A }
- {---------------------------------------------------------}
- Procedure GetDTA(var segment, offset : integer );
- BEGIN
- regs.ax := $2F00; { Function used to get current DTA address }
- MSDos( regs ); { Execute MSDos function request }
- segment := regs.ES; { Segment of DTA returned by DOS }
- offset := regs.Bx; { Offset of DTA returned }
- END;
- {---------------------------------------------------------}
- { S E T P S P }
- {---------------------------------------------------------}
- Procedure SetPSP(var segment : integer );
- BEGIN
-
- { A bug in DOS 2.0, 2.1, causes DOS to clobber its standard stack }
- { when the PSP get/set functions are issued at the DOS prompt. The }
- { following checks are made, forcing DOS to use the "critical" }
- { stack when the TSR enters at the INDOS level. }
-
- {If Version less then 3.0 and INDOS set }
- If DosVersion < 3 then { then set the Dos Critical Flag }
- If Mem[DosStat1.CS:DosStat1.IP] <> 0 then
- Mem[DosStat2.CS:DosStat2.IP] := $FF;
-
- regs.ax := $5000; { Function to set current PSP address }
- regs.bx := segment; { Segment of PSP to be used by DOS }
- MSDos( regs ); { Execute MSDos function request }
-
- {If Version less then 3.0 and INDOS set }
- If DosVersion < 3 then { then clear the Dos Critical Flag }
- If Mem[DosStat1.CS:DosStat1.IP] <> 0 then
- Mem[DosStat2.CS:DosStat2.IP] := $00;
-
- END;
- {---------------------------------------------------------}
- { G E T P S P }
- {---------------------------------------------------------}
- Procedure GetPSP(var segment : integer );
- BEGIN
-
- { A bug in DOS 2.0, 2.1, causes DOS to clobber its standard stack }
- { when the PSP get/set functions are issued at the DOS prompt. The }
- { following checks are made, forcing DOS to use the "critical" }
- { stack when the TSR enters at the INDOS level. }
-
- {If Version less then 3.0 and INDOS set }
- If DosVersion < 3 then { then set the Dos Critical Flag }
- If Mem[DosStat1.CS:DosStat1.IP] <> 0 then
- Mem[DosStat2.CS:DosStat2.IP] := $FF;
-
- regs.ax := $5100; { Function to get current PSP address }
- MSDos( regs ); { Execute MSDos function request }
- segment := regs.Bx; { Segment of PSP returned by DOS }
-
- {IF DOS Version less then 3.0 and INDOS set }
- If DosVersion < 3 then { then clear the Dos Critical Flag }
- If Mem[DosStat1.CS:DosStat1.IP] <> 0 then
- Mem[DosStat2.CS:DosStat2.IP] := $00;
-
- END;
- {---------------------------------------------------------------}
- { G e t C o n t r o l C (break) V e c t o r }
- {---------------------------------------------------------------}
- Type
- Arrayparam = array [1..2] of integer;
- Const
- SavedCtlC: arrayparam = (0,0);
- NewCtlC : arrayparam = (0,0);
- Procedure GetCtlC(SavedCtlC:arrayparam);
- Begin {Record the Current Ctrl-C Vector}
- With Regs Do
- Begin
- AX:=$3523;
- MsDos(Regs);
- SavedCtlC[1]:=BX;
- SavedCtlC[2]:=ES;
- End;
- End;
- {---------------------------------------------------------------}
- { S e t C o n t r o l C V e c t o r }
- {---------------------------------------------------------------}
- Procedure IRET; {Dummy Ctrl-C routine}
- Begin
- inline($5D/$5D/$CF); {Pop Bp/Pop Bp/Iret}
- end;
- Procedure SetCtlC(CtlCptr:arrayparam);
- Begin {Set the New Ctrl-C Vector}
- With Regs Do
- Begin
- AX:=$2523;
- DS:=CtlCptr[2];
- DX:=CtlCptr[1];
- MsDos(Regs);
- End;
- End;
- {----------------------------------------------------------------------}
- { K e y i n : R e a d K e a b o a r d }
- {----------------------------------------------------------------------}
- Function Keyin: char; { Get a key from the Keyboard }
- Var Ch : char; { If extended key, fold above 127 }
- Begin {---------------------------------------}
- Repeat until Keypressed;
- Read(Kbd,Ch);
- if (Ch = Esc) and KeyPressed then
- Begin
- Read(Kbd,Ch);
- Ch := Char(Ord(Ch) + 127);
- End;
- Keyin := Ch;
- End; {Keyin}
- {----------------------------------------------------------------------}
- { B e e p : S o u n d t h e H o r n }
- {----------------------------------------------------------------------}
- Procedure Beep(N :integer); {------------------------------------------}
- Begin { This routine sounds a tone of frequency }
- Sound(n); { N for approximately 100 ms }
- Delay(100); {------------------------------------------}
- Sound(n div 2);
- Delay(100);
- Nosound;
- End {Beep} ;
-
- {--------------------------------------------------------------}
- { I N T E R R U P T 2 4 }
- {--------------------------------------------------------------}
- { Version 2.0, 1/28/86
- - Bela Lubkin
- CompuServe 76703,3015
-
- Apologetically mangled by Lane Ferris
-
- For MS-DOS version 2.0 or greater, Turbo Pascal 1.0 or greater.
-
- Thanks to Marshall Brain for the original idea for these routines.
- Thanks to John Cooper for pointing out a small flaw in the code.
-
- These routines provide a method for Turbo Pascal programs to trap
- MS-DOS interrupt 24 (hex). INT 24h is called by DOS when a 'critical
- error' occurs, and it normally prints the familiar "Abort, Retry,
- Ignore?" message.
-
- With the INT 24h handler installed, errors of this type will be passed
- on to Turbo Pascal as an error. If I/O checking is on, this will cause
- a program crash. If I/O checking is off, IOResult will return an error
- code. The global variable INT24Err will be true if an INT 24h error
- has occurred. The variable INT24ErrorCode will contain the INT 24h
- error code as given by DOS. These errors can be found in the DOS
- Technical Reference Manual.
-
- It is intended that INT24Result be used in place of IOResult. Calling
- INT24Result clears IOResult. The simple way to use INT24Result is just
- to check that it returns zero, and if not, handle all errors the same.
- The more complicated way is to interpret the code. The integer
- returned by INT24Result can be looked at as two bytes. By assigning
- INT24Result to a variable, you can then examine the two bytes:
- (Hi(<variable>)-1) will give the DOS critical error code, or
- (<variable> And $FF00) will return an integer from the table listed in
- the INT24Result procedure (two ways of looking at the critical error);
- Lo(<variable>) will give Turbo's IOResult. A critical error will
- always be reflected in INT24Result, but the IOResult part of
- INT24Result will not necessarily be nonzero; in particular,
- unsuccessful writes to character devices will not register as a Turbo
- I/O error.
-
- INT24Result should be called after any operation which might cause a
- critical error, if Turbo's I/O checking is disabled. If it is enabled,
- the program will be aborted except in the above noted case of writes to
- character devices.
-
- Also note that different versions of DOS and the BIOS seem to react to
- printer errors at vastly different rates. Be prepared to wait a while
- for anything to happen (in an error situation) on some machines.
-
- These routines are known to work correctly with: Turbo Pascal 1.00B PC-DOS;
- Turbo Pascal 2.00B PC-DOS;
- Turbo Pascal 2.00B MS-DOS;
- Turbo Pascal 3.01A PC-DOS.
- Other MS-DOS and PC-DOS versions should work.
-
- Note that Turbo 2.0's normal IOResult codes for MS-DOS DO NOT
- correspond to the I/O error numbers given in Appendix I of the Turbo
- 2.0 manual, or to the error codes given in the I/O error nn,
- PC=aaaa/Program aborted message. Turbo 3.0 IOResult codes do match the
- manual. Here is a table of the correspondence (all numbers in
- hexadecimal):
-
- Turbo 2.0 IOResult Turbo error, Turbo 3.0 IOResult
- ------------------ -------------------------------------------------
- 00 00 none
- 01 90 record length mismatch
- 02 01 file does not exist
- 03 F1 directory is full
- 04 FF file disappeared
- 05 02 file not open for input
- 06 03 file not open for output
- 07 99 unexpected end of file
- 08 F0 disk write error
- 09 10 error in numeric format
- 0A 99 unexpected end of file
- 0B F2 file size overflow
- 0C 99 unexpected end of file
- 0D F0 disk write error
- 0E 91 seek beyond end of file
- 0F 04 file not open
- 10 20 operation not allowed on a logical device
- 11 21 not allowed in direct mode
- 12 22 assign to standard files is not allowed
- -- F3 Too many open files
-
- - Bela Lubkin
- CompuServe 76703,3015
- 1/28/86
- }
-
- Const
- INT24Err: Boolean=False;
- INT24ErrCode: Byte=0;
- OldINT24: Array [1..2] Of Integer=(0,0);
-
- Var
- RegisterSet: Record Case Integer Of
- 1: (AX,BX,CX,DX,BP,SI,DI,DS,ES,Flags: Integer);
- 2: (AL,AH,BL,BH,CL,CH,DL,DH: Byte);
- End;
-
- Procedure INT24; { Interrupt 24 Service Routine }
- Begin
-
- Inline( $2E/$C6/$06/ Int24Err / $01/$50/$89/$F8/$2E/$A2/ Int24ErrCode
- /$58/$B0/$00/$89/$EC/$5D/$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
- PUSH AX
- MOV AX,DI Get INT 25h error code
- MOV CS:[INT24ErrCode],AL Save it in INT24ErrCode
- POP AX
- MOV AL,0 Tell DOS to ignore the error
- MOV SP,BP Unwind stack frame
- POP BP
- IRET Let DOS handle it from here
- }
- End;
-
- {------------------------------------------------------------}
- { I N T 2 4 O N }
- {------------------------------------------------------------}
- { Grab the Critical error ptr from the previous user}
- Procedure INT24On; { Enable INT 24h trapping }
- Begin
- 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;
- {------------------------------------------------------------}
- { I N T 2 4 O F F }
- {------------------------------------------------------------}
- { Give Critical Error Service pointer back to previous user }
- Procedure INT24Off;
- Begin
- 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;
-
- Function INT24Result: Integer;
- Var
- I:Integer;
-
- Begin
- I:=IOResult;
- If INT24Err Then
- Begin
- I:=I+256*Succ(INT24ErrCode);
- INT24On;
- End;
- INT24Result:=I;
- End;
-
- { INT24Result returns all the regular Turbo IOResult codes if no critical
- error has occurred. If a critical error, then the following values are
- added to the error code from Turbo:
- 256: Attempt to write on write protected disk
- 512: Unknown unit [internal dos error]
- 768: Drive not ready [drive door open or bad drive]
- 1024: Unknown command [internal dos error]
- 1280: Data error (CRC) [bad sector or drive]
- 1536: Bad request structure length [internal dos error]
- 1792: Seek error [bad disk or drive]
- 2048: Unknown media type [bad disk or drive]
- 2304: Sector not found [bad disk or drive]
- 2560: Printer out of paper [anything that the printer might signal]
- 2816: Write fault [character device not ready]
- 3072: Read fault [character device not ready]
- 3328: General failure [several meanings]
-
- If you need the IOResult part, use
- I:=INT24Result and 255; [masks out the INT 24h code]
-
- For the INT 24h code, use
- I:=INT24Result Shr 8; [same as Div 256, except faster]
-
- INT24Result clears both error codes, so you must assign it to a variable if
- you want to extract both codes:
- J:=INT24Result;
- WriteLn('Turbo IOResult = ',J And 255);
- WriteLn('DOS INT 24h code = ',J Shr 8);
-
- Note that in most cases, errors on character devices (LST and AUX) will not
- return an IOResult, only an INT 24h error code. }
-
- { Main program. Delete next line to enable }
-
- {---------------------------------------------------------}
- { G E T E R R O R C O D E }
- {---------------------------------------------------------}
- Procedure GetErrorCode;
- Begin
- Error := IOresult; {Read the I/O result}
-
- If INT24Err Then
- Begin
- Error:=Error+256*Succ(INT24ErrCode);
- INT24On;
- End;
- Good := (Error = 0); {Set Boolean Result }
- End;
-
- {--------------------------------------------------------------}