Contributor: GREG ESTABROOKS UNIT Utils; { Misc Utilities Last Updates Nov 01/93 } { Copyright (C) 1992,93 Greg Estabrooks } INTERFACE { *********************************************************************} USES CRT,KeyIO,DOS; CONST FpuType :ARRAY[0..3] OF STRING[10] =('None','8087','80287','80387'); CPU :ARRAY[0..3] Of STRING[13] =('8088/V20','80286', '80386/80486','80486'); CONST { Define COM port Addresses } ComPort :ARRAY[1..4] Of WORD = (3ドルF8,2ドルF8,3ドルE8,2ドルE8); CONST Warm :WORD = 0000; { Predefined value for warm boot. } Cold :WORD = 0001; { Predefined value for cold boot. } VAR BiosDate :ARRAY[0..7] of CHAR Absolute $F000:$FFF5; EquipFlag :WORD Absolute 0000ドル:0410ドル; CompID :BYTE Absolute $F000:$FFFE; FUNCTION CoProcessorExist :BOOLEAN; FUNCTION NumPrinters :WORD; FUNCTION GameIOAttached :BOOLEAN; FUNCTION NumSerialPorts :INTEGER; FUNCTION NumDisketteDrives :INTEGER; FUNCTION InitialVideoMode :INTEGER; PROCEDURE Noise(Pitch, Duration :INTEGER); FUNCTION Time :STRING; FUNCTION WeekDate :STRING; FUNCTION DayOfWeek( Month, Day, Year :WORD ) :BYTE; { Returns 1-7 } FUNCTION PrinterOK :BOOLEAN; FUNCTION AdlibCard :BOOLEAN; FUNCTION TrueDosVer :WORD; PROCEDURE SetPrtScr( On_OFF :BOOLEAN ); FUNCTION CpuType :WORD; PROCEDURE IdePause; FUNCTION RingDetect( CPort :WORD) :BOOLEAN; function DetectOs2: Boolean; FUNCTION HiWord( Long :LONGINT ) :WORD; { Routine to return high word of a LongInt. } FUNCTION LoWord( Long :LONGINT ) :WORD; { Routine to return low word of a LongInt. } FUNCTION Running4DOS : Boolean; PROCEDURE Reboot( BootCode :WORD ); { Routine to reboot system according to boot code.} FUNCTION GetChar( X,Y :WORD; VAR Attrib:BYTE ) :CHAR; IMPLEMENTATION { *********************************************************************} FUNCTION CoProcessorExist :BOOLEAN; BEGIN CoProcessorExist := (EquipFlag And 2) = 2; END; FUNCTION NumPrinters :WORD; BEGIN NumPrinters := EquipFlag Shr 14; END; FUNCTION GameIOAttached :BOOLEAN; BEGIN GameIOAttached := (EquipFlag And 1000ドル) = 1; END; FUNCTION NumSerialPorts :INTEGER; BEGIN NumSerialPorts := (EquipFlag Shr 9) And 07ドル; END; FUNCTION NumDisketteDrives :INTEGER; BEGIN NumDisketteDrives := ((EquipFlag And 1) * (1+(EquipFlag Shr 6) And 03ドル)); END; FUNCTION InitialVideoMode :INTEGER; BEGIN InitialVideoMode := (EquipFlag Shr 4) And 03ドル; END; PROCEDURE Noise( Pitch, Duration :INTEGER ); BEGIN Sound(Pitch); Delay(Duration); NoSound; END; Function Time : String; VAR Hour,Min,Sec :STRING[2]; H,M,S,T :WORD; BEGIN GetTime(H,M,S,T); Str(H,Hour); Str(M,Min); Str(S,Sec); If S < 10 Then Sec := '0' + Sec; If M < 10 Then Min := '0' + Min; If H> 12 Then BEGIN Str(H - 12, Hour); IF Length(Hour) = 1 Then Hour := ' ' + Hour; Time := Hour + ':' + Min + ':' + Sec+' pm' END ELSE BEGIN If H = 0 Then Time := '12:' + Min + ':' + Sec + ' am' ELSE Time := Hour +':'+Min+':'+Sec+' am'; END; If H = 12 Then Time := Hour + ':' + Min + ':' + Sec + ' pm'; END; FUNCTION WeekDate :STRING; TYPE WeekDays = Array[0..6] Of STRING[9]; Months = Array[1..12] Of STRING[9]; CONST DayNames : WeekDays = ('Sunday','Monday','Tuesday','Wednesday', 'Thursday','Friday','Saturday'); MonthNames : Months = ('January','February','March','April','May', 'June','July','August','September', 'October','November','December'); VAR Y, M, D, DayOfWeek :WORD; Year :STRING; Day :STRING; BEGIN GetDate(Y,M,D,DayofWeek); Str(Y,Year); Str(D,Day); WeekDate := DayNames[DayOfWeek] + ' ' + MonthNames[M] + ' ' + Day+ ', ' + Year; END; FUNCTION DayOfWeek( Month, Day, Year :WORD ) :BYTE; VAR ivar1, ivar2 : Integer; BEGIN IF (Day> 0) AND (Day < 32) AND (Month> 0) AND (Month < 13) THEN BEGIN ivar1 := ( Year MOD 100 ); ivar2 := Day + ivar1 + ivar1 DIV 4; CASE Month OF 4, 7 : ivar1 := 0; 1, 10 : ivar1 := 1; 5 : ivar1 := 2; 8 : ivar1 := 3; 2,3,11 : ivar1 := 4; 6 : ivar1 := 5; 9,12 : ivar1 := 6; END; {case} ivar2 := ( ivar1 + ivar2 ) MOD 7; IF ( ivar2 = 0 ) THEN ivar2 := 7; END {IF} ELSE ivar2 := 0; DayOfWeek := BYTE( ivar2 ); END; FUNCTION PrinterOK :BOOLEAN; { Determine whether printer is on or off line } BEGIN If (Port[379ドル]) And (16) 16 Then PrinterOK := False Else PrinterOK := True; END; FUNCTION AdlibCard :BOOLEAN; { Routine to determine if a Adlib compatible card is installed } VAR Val1,Val2 :BYTE; BEGIN Port[388ドル] := 4; { Write 60h to register 4 } Delay(3); { Which resets timer 1 and 2 } Port[389ドル] := 60ドル; Delay(23); Port[388ドル] := 4; { Write 80h to register 4 } Delay(3); { Which enables interrupts } Port[389ドル] := 80ドル; Delay(23); Val1 := Port[388ドル]; { Read status byte } Port[388ドル] := 2; { Write ffh to register 2 } Delay(3); { Which is also Timer 1 } Port[389ドル] := $FF; Delay(23); Port[388ドル] := 4; { Write 21h to register 4 } Delay(3); { Which will Start Timer 1 } Port[389ドル] := 21ドル; Delay(85); { wait 85 microseconds } Val2 := Port[388ドル]; { read status byte } Port[388ドル] := 4; { Repeat the first to steps } Delay(3); { Which will reset both Timers } Port[389ドル] := 60ドル; Delay(23); Port[388ドル] := 4; Delay(3); Port[389ドル] := 80ドル; { Now test the status bytes saved } If ((Val1 And $E0) = 0) And ((Val2 And $E0) = $C0) Then AdlibCard := True { Card was found } Else AdlibCard := False; { No Card Installed } END; FUNCTION TrueDosVer :WORD; ASSEMBLER; { Returns true Dos Version. Not affected by Setver } ASM Mov AX,3306ドル { get true dos ver } Int 21ドル { Call Dos } Mov AX,BX { Return proper results } { DL = Revision Number } { DH = V Flags, 8h = Dos in ROM, 10h Dos in HMA } END;{TrueDosVer} PROCEDURE SetPrtScr( On_OFF :BOOLEAN ); { Routine to Enable or disable Print screen key } BEGIN If On_OFF Then { Turn it on } Mem[0050ドル:0000] := 0 Else Mem[0050ドル:0000] := 1; { Turn it off } END; FUNCTION CpuType :WORD; ASSEMBLER; { Returns a value depending on the type of CPU } { 0 = 8088/V20 or compatible } { 1 =わ 80286 2 =わ 80386/80486+ } ASM Xor DX,DX { Clear DX } Push DX PopF { Clear Flags } PushF Pop AX { Load Cleared Flags } And AX,0ドルF000 { Check hi bits for F0h } Cmp AX,0ドルF000 Je @Quit { Quit if 8088 } Inc DX Mov AX,0ドルF000 { Now Check For 80286 } Push AX PopF PushF Pop AX And AX,0ドルF000 { If The top 4 bits aren't set } Jz @Quit { Its a 80286+ } Inc DX { Else its a 80386 or better } @Quit: Mov AX,DX { Return Result in AX } END;{CpuType} procedure idepause; begin gotoxy(1,25); write('Press any key to return to IDE'); pausekey; end; FUNCTION RingDetect( CPort :WORD) :BOOLEAN; { Routine to detect whether or not the } { phone is ringing by checking the comport} BEGIN RingDetect := ODD( PORT[CPort] SHR 6 ); END; function DetectOs2: Boolean; begin { if you use Tpro, then write Hi(TpDos.DosVersion) } DetectOs2 := (Lo(Dos.DosVersion)> 10); end; FUNCTION HiWord( Long :LONGINT ) :WORD; ASSEMBLER; { Routine to return high word of a LongInt. } ASM Mov AX,Long.WORD[2] { Move High word into AX. } END; FUNCTION LoWord( Long :LONGINT ) :WORD; ASSEMBLER; { Routine to return low word of a LongInt. } ASM Mov AX,Long.WORD[0] { Move low word into AX. } END; FUNCTION Running4DOS : Boolean; VAR Regs : Registers; begin With Regs do begin ax := $D44D; bx := 00ドル; end; Intr (2ドルF, Regs); if Regs.ax = 44ドルDD then Running4DOS := TRUE else Running4DOS := FALSE end; PROCEDURE Reboot( BootCode :WORD ); { Routine to reboot system according to boot code.} { Also flushes all DOS buffers. } { NOTE: Doesn't update directory entries. } BEGIN Inline( $BE/0ドルD/ { MOV AH,0Dh } $CD/21ドル/ { INT 21h } $FB/ { STI } $B8/Bootcode/ { MOV AX,BootCode } 8ドルE/$D8/ { MOV DS,AX } $B8/34ドル/12ドル/ { MOV AX,1234h } $A3/72ドル/04ドル/ { MOV [0472h],AX } $EA/00ドル/00ドル/$FF/$FF); { JMP FFFFh:0000h } END; FUNCTION GetChar( X,Y :WORD; VAR Attrib:BYTE ) :CHAR; { Retrieves the character and attribute of } { coordinates X,Y. } VAR Ofs :WORD; BEGIN Ofs := ((Y-1) * 160) + ((X SHL 1) - 1); Attrib := MEM[$B800:Ofs]; GetChar := CHR( MEM[$B800:Ofs-1] ); END; BEGIN END.