home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C!T ROM 2
/
ctrom_ii_b.zip
/
ctrom_ii_b
/
PROGRAM
/
PASCAL
/
TPKERMIT
/
SYSFUNC.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1987-03-25
|
26KB
|
625 lines
(* +FILE+ SYSFUNC.PASMS *)
(* ================================================================= *)
(* MsDos SYSTEM dependent Routines for Kermit . *)
(* ================================================================= *)
(* Global Declaration *)
CONST
(* FLAGS in flag register *)
Cflag = $0001 ;
Pflag = $0004 ;
Aflag = $0010 ;
Zflag = $0040 ;
Tflag = $0100 ;
Iflag = $0200 ;
Dflag = $0400 ;
Oflag = $0800 ;
TYPE
regtype = record case layouts of
one: ( ax,bx,cx,dx,bp,si,di,ds,es,flags : integer ;);
two: ( al,ah,bl,bh,cl,ch,dl,dh : byte ; ) ;
three : ( Sectors,Clusters,BytesperSec,TotalClusters: integer;)
end ;
ScreenArray = array [1..4000] of byte ;
VAR
register : regtype ;
MyDTA : array [1..43] of byte ;
Remotecursor,LocalCursor : integer ;
Commandline : comstring absolute Cseg:$80 ;
MonoScreen : ScreenArray absolute $B000:$0000 ; (* Monchrome Video *)
ColorScreen : ScreenArray absolute $B800:$0000 ; (* Colour graphics *)
OldLocalScreen : ScreenArray ;
OldRemoteScreen : ScreenArray ;
NumLock,ScrollLock : byte ;
(* ------------------------------------------------------------------ *)
(* KeyChar - get a character from the Keyboard. *)
(* It returns TRUE if character found and the char is *)
(* returned in the parameter. *)
(* It returns FALSE if no keyboard character. *)
(* *)
(* ------------------------------------------------------------------ *)
Function KeyChar (var Achar,Bchar : byte): boolean ;
Begin (* KeyChar *)
with register do
begin
ah := 1;
intr($16,register);
if (Zflag and flags)=Zflag then
(* ------ The following code is required only if we want to us the ----- *)
(* ------ NUMLOCK and SCROLLLOCK key as function keys ----------------- *)
begin (* check for Numlck and Scroll Lck *)
ah := 2;
intr($16,register);
If (al and $10) <> ScrollLock then
Case (al and $0F) of
0: Bchar := $46 ; (* not shifted *)
1,2,3: Bchar := $86 ; (* shifted *)
4,5,6,7: Bchar := $87 ; (* control *)
else Bchar := $87 ; (* Alt *)
end (* case *)
else
If (al and $20) <> NumLock then
Case (al and $0F) of
0: Bchar := $45 ; (* not shifted *)
1,2,3: Bchar := $85 ; (* shifted *)
4,5,6,7: Bchar := $88 ; (* control *) (* Not Available *)
else Bchar := $88 ; (* Alt *)
End (* case *)
else Bchar := 0 ;
ScrollLock := (al and $10) ;
NumLock := (al and $20) ;
Achar := 0 ;
If Bchar <> 0 then KeyChar := true
else KeyChar := false
End (* check for Numlck and Scroll Lck *)
(*------ If you don't need this code, replace it with ------------------ *)
(* -------- KeyChar := False ----------------------------------------- *)
else
begin
ah := 0;
intr($16,register);
Achar := al ;
Bchar := ah ;
KeyChar := true;
end ;
end;
End ; (* KeyChar *)
(* ------------------------------------------------------------------ *)
(* CursorPosition - Returns Cursor Position in Reg DX. *)
(* ------------------------------------------------------------------ *)
Procedure CursorPosition ;
Begin (* CursorPosition *)
With register do
begin (* Get position *)
ah := 3;
intr($10,register);
end; (* Get position *)
End;
(* ------------------------------------------------------------------ *)
(* CursorUp - *)
(* ------------------------------------------------------------------ *)
Procedure CursorUp ;
Begin (* CursorUp *)
With register do
begin (* Move up *)
ah := 3; (* Function code 3 - Read Cursor Position *)
intr($10,register);
if dh > 1 then dh := dh - 1
else dh := 24 ;
ah := 2 ; (* Function code 2 - Set Cursor Position *)
intr($10,register);
end; (* Move up *)
End; (* CursorUp *)
(* ------------------------------------------------------------------ *)
(* CursorDown - *)
(* ------------------------------------------------------------------ *)
Procedure CursorDown ;
Begin (* CursorDown *)
With register do
begin (* Move Down *)
ah := 3; (* Function code 3 - Read Cursor Position *)
intr($10,register);
if dh < 24 then dh := dh + 1
else dh := 1 ;
ah := 2 ; (* Function code 2 - Set Cursor Position *)
intr($10,register);
end; (* Move Down *)
End; (* CursorDown *)
(* ------------------------------------------------------------------ *)
(* CursorRight - *)
(* ------------------------------------------------------------------ *)
Procedure CursorRight ;
Begin (* CursorRight *)
With register do
begin (* Move Right *)
ah := 3; (* Function code 3 - Read Cursor Position *)
intr($10,register);
if dl < 80 then dl := dl + 1
else dl := 1 ;
ah := 2 ; (* Function code 2 - Set Cursor Position *)
intr($10,register);
end; (* Move Right *)
End; (* CursorRight *)
(* ------------------------------------------------------------------ *)
(* CursorLeft - *)
(* ------------------------------------------------------------------ *)
Procedure CursorLeft ;
Begin (* CursorLeft *)
With register do
begin (* Move Left *)
ah := 3; (* Function code 3 - Read Cursor Position *)
intr($10,register);
if dl > 0 then dl := dl - 1
else dl := 80 ;
ah := 2 ; (* Function code 2 - Set Cursor Position *)
intr($10,register);
end; (* Move Left *)
End; (* CursorLeft *)
(* ------------------------------------------------------------------ *)
(* FatCursor - *)
(* ------------------------------------------------------------------ *)
Procedure FatCursor(flag :boolean);
Begin (* FatCursor *)
Port[$3D4] := $B ; (* Select Cursor end Register *)
If flag then Port[$3D5] := 9
else Port[$3D5] := 7 ;
End; (* FatCursor *)
(* ------------------------------------------------------------------ *)
(* RemoteScreen - Procedure *)
(* This procedure save the local screen and restores *)
(* the remote screen. *)
(* Also setup the 25th line to display settings *)
(* ------------------------------------------------------------------ *)
Procedure RemoteScreen ;
Begin (* RemoteScreen *)
If (OldRemoteScreen[4000]<>1) or (OldRemoteScreen[3999]<>32) then
Begin (* Initialize OldRemoteScreen *)
For i := 1 to 4000 do OldRemoteScreen[i] := 32 ;
OldRemoteScreen[4000] := 1 ;
RemoteCursor := $0000 ;
End ; (* Initialize OldRemoteScreen *)
With register do
begin (* Switch Screens *)
bx := 0 ;
ah := 15; (* Function code 15 - Return Current video State *)
intr($10,register);
if al < 7 then
Begin (* Color Screen *)
OldLocalScreen := ColorScreen ;
ColorScreen := OldRemoteScreen ;
End (* Color Screen *)
else
Begin (* MonoChrome Screen *)
OldLocalScreen := MonoScreen ;
MonoScreen := OldRemoteScreen ;
End (* MonoChrome Screen *)
end ; (* Switch Screens *)
With register do
begin (* Save ? Restore Cursor *)
bx := 0 ;
ah := 3; (* Function code 3 - Read Cursor Position *)
intr($10,register);
localcursor := dx ;
(* ---- set up 25th line with status ------ *)
ah := 2; (* Function code 2 - Set Cursor Position *)
DX := $1800; (* Set the cursor to Row 25 and column 0 *)
intr($10,Register);
Textcolor(Blue); Textbackground(Yellow);
Write (' Port ');
If PrimaryPort then Write('One : ')
else Write('Two : ');
Write(Baudrate,' baud, ');
Case paritytype(parity) of
OddP : write('Odd ');
EvenP: write('Even ');
MarkP: write('Mark ');
NoneP: write('None ');
end ; (* parity case *)
Write('parity, ');
If LocalEcho then Write('Half duplex, ')
else Write('Full duplex, ');
If XonXoff then write('Xon-Xoff ')
else if Series1 then write('Series/1 ')
else write('Standard ');
Write (' ExitChar=CTL ',chr($40+LocalChar),' ' ) ;
Textcolor(LightGreen); Textbackground(0);
(* -------------------------------------------- *)
dx := remotecursor ;
ah := 2 ; (* Function code 2 - Set Cursor Position *)
intr($10,register);
end; (* Save ? Restore Cursor *)
Window(1,1,80,24);
End; (* RemoteScreen *)
(* ------------------------------------------------------------------ *)
(* LocalScreen - Procedure *)
(* This procedure save the remote screen and restores *)
(* the local screen. *)
(* ------------------------------------------------------------------ *)
Procedure LocalScreen ;
Begin (* LocalScreen *)
With register do
begin (* Switch Screens *)
bx := 0 ;
ah := 15; (* Function code 15 - Return Current video State *)
intr($10,register);
if al < 7 then
Begin (* Color Screen *)
OldRemoteScreen := ColorScreen ;
ColorScreen := OldLocalScreen ;
End (* Color Screen *)
else
Begin (* MonoChrome Screen *)
OldRemoteScreen := MonoScreen ;
MonoScreen := OldLocalScreen ;
End (* MonoChrome Screen *)
end ; (* Switch Screens *)
With register do
begin (* Save and Restore Cursor *)
ah := 3; (* Function code 3 - Read Cursor Position *)
intr($10,register);
Remotecursor := dx ;
dx := Localcursor ;
ah := 2 ; (* Function code 2 - Set Cursor Position *)
intr($10,register);
end; (* Save and Restore Cursor *)
TextColor(Yellow); TextBackground(Black);
Window(1,1,80,25);
End; (* LocalScreen *)
(* ----------------------------------------------------------------- *)
(* FirstFile - Returns True if file found for file mask Myfile *)
(* and the first file name is returned in Filename *)
(* - Returns False if no file Found. *)
(* ----------------------------------------------------------------- *)
Function FirstFile(Myfile:Comstring; var Filename:Comstring): Boolean ;
Var
OldSegment,OldOffset,i : integer ;
Begin (* FirstFile Function *)
Myfile := concat(myfile,chr(0));
With Register do
Begin { Search for File }
Ax := $2F00 ; { Get DTA Dos Function }
MsDos(Register);
OldSegment := Es ; OldOffset := Bx ; (* save old DTA location *)
Ds := Seg(MyDTA); Dx := Ofs(MyDTA) ;
Ax := $1A00 ; { Set DTA Dos Function }
MsDos(Register); (* set my DTA location *)
Ax := $4E00 ; {get first directory entry }
Ds := Seg(Myfile); { mask location }
Dx := Ofs(Myfile)+1;
Cx := 2 ; {option}
MsDos(Register);
if al = 0 then { Got file }
Begin (* Got File *)
i := 1 ;
Repeat
Filename[i] := Chr (MyDTA[30 + i]) ;
i := i + 1 ;
until (not (Filename[i-1] in [' '..'~'])) ;
Filename[0] := chr(i - 2);
Firstfile := true ;
End (* Got file *)
else
Firstfile := False ;
Ds := OldSegment ; Dx := OldOffset ;
Ax := $1A00 ; { Set DTA Dos Function }
MsDos(Register); (* reset old DTA location *)
End; { Search for File }
End; { FirstFile Function }
(* ----------------------------------------------------------------- *)
(* NextFile - Returns True if file found for file mask Myfile *)
(* and the first file name is returned in Filename *)
(* - Returns False if no file Found. *)
(* ----------------------------------------------------------------- *)
Function NextFile(Var Myfile, Filename : Comstring): Boolean ;
Var
OldSegment,OldOffset,i : integer ;
Begin (* NextFile Function *)
With Register do
Begin { Search for File }
Ax := $2F00 ; { Get DTA Dos Function }
MsDos(Register);
OldSegment := Es ; OldOffset := Bx ; (* save old DTA location *)
Ds := Seg(MyDTA); Dx := Ofs(MyDTA) ;
Ax := $1A00 ; { Set DTA Dos Function }
MsDos(Register); (* set my DTA location *)
Ax := $4F00 ; { get next directory entry }
MsDos(Register);
if al = 0 then { Got file }
Begin (* Got File *)
i := 1 ;
Repeat
Filename[i] := chr (MyDTA[30 + i]) ;
i := i + 1 ;
until (not (Filename[i-1] in [' '..'~'])) ;
Filename[0] := chr(i - 2);
Nextfile := true ;
End (* Got file *)
else
Nextfile := False ;
Ds := OldSegment ; Dx := OldOffset ;
Ax := $1A00 ; { Set DTA Dos Function }
MsDos(Register); (* reset old DTA location *)
End; { Search for File }
End; { NextFile Function }
(* ------------------------------------------------------------------ *)
(* SetDefaultDrive - *)
(* ------------------------------------------------------------------ *)
Procedure SetDefaultDrive (Drive : Byte);
Begin (* SetDefaultDrive *)
With register do
begin (* Select disk *)
DL := Drive ;
Ax := $0E00 ; { Select default drive }
MsDos(Register);
end; (* Select disk *)
End; (* SetDefaultDrive *)
(* ------------------------------------------------------------------ *)
(* DefaultDrive - returns the value of the default drive *)
(* A=0,B=1,C=2 etc. *)
(* ------------------------------------------------------------------ *)
Function DefaultDrive : Byte ;
Begin (* DefaultDrive *)
With register do
begin (* Current disk *)
Ax := $1900 ; { Find default drive }
MsDos(Register);
DefaultDrive := al ;
end; (* Current disk *)
End; (* DefaultDrive *)
(* ----------------------------------------------------------------- *)
(* DisplayDiskStatus - Display the disk status for the default disk.*)
(* *)
(* ----------------------------------------------------------------- *)
Procedure DisplayDiskStatus ;
Var
Freebytes : real ;
Begin (* DisplayDiskStatus *)
With Register do
Begin { Get disk status }
dl := DefaultDrive + 1 ; (* use default drive *)
Write (' Disk Drive ',chr(DX+$40),': ');
Ax := $3600 ; { Get diskstatus Function }
MsDos(Register);
Writeln('Bytes/sector = ',BytesperSec,' Sector/cluster = ',Sectors);
Writeln('Total Clusters = ',TotalClusters);
FreeBytes := BytesperSec*Sectors; (* two steps required due to *)
FreeBytes := FreeBytes*Clusters ; (* integer overflow *)
Writeln('Free Clusters = ',Clusters,' i.e. ',Freebytes:7:0,' bytes free');
End; (* Get disk status *)
End; (* DisplayDiskStatus *)
(* ----------------------------------------------------------------- *)
(* MkDir - Make Directory. *)
(* ----------------------------------------------------------------- *)
Procedure MkDirFunc(DirName:Comstring) ;
Begin (* MkDir *)
DirName := DirName + chr(0) ;
With Register do
Begin { MD }
Ds := Seg(DirName); Dx := Ofs(DirName)+1 ;
Ax := $3900 ; { MkDir Function }
MsDos(Register);
While Mem[Ds:Dx] <> 0 Do
Begin Write(Chr(Mem[Ds:Dx])); Dx := Dx + 1 ; End ;
Case Al of
0: writeln(' - New Directory Made ');
3: writeln(' - Path not found');
5: writeln(' - Acess denied');
else writeln(' - Return code =',al);
end; (* case of Ax *)
End ; { MD }
End ; (* MkDir *)
(* ----------------------------------------------------------------- *)
(* RmDir - Remove Directory. *)
(* ----------------------------------------------------------------- *)
Procedure RmDirFunc(DirName:Comstring) ;
Begin (* RmDir *)
DirName := DirName + chr(0) ;
With Register do
Begin { Remove Directory }
Ds := Seg(DirName); Dx := Ofs(DirName)+1 ;
Ax := $3A00 ; { RmDir Function }
MsDos(Register);
While Mem[Ds:Dx] <> 0 Do
Begin Write(Chr(Mem[Ds:Dx])); Dx := Dx + 1 ; End ;
Case Al of
0: writeln(' - Directory Removed ');
3: writeln(' - Path not found');
5: writeln(' - Acess denied');
else writeln(' - Return code =',al);
end; (* case of Ax *)
End ; { Remove Directory }
End ; (* RmDir *)
(* ----------------------------------------------------------------- *)
(* ChDir - Change Directory. *)
(* ----------------------------------------------------------------- *)
Procedure ChDirFunc(DirName:Comstring) ;
Begin (* ChDir *)
DirName := DirName + chr(0) ;
With Register do
Begin { CD }
Ds := Seg(DirName); Dx := Ofs(DirName)+1 ;
Ax := $3B00 ; { ChDir Function }
MsDos(Register);
While Mem[Ds:Dx] <> 0 Do
Begin Write(Chr(Mem[Ds:Dx])); Dx := Dx + 1 ; End ;
Case Al of
0: writeln(' - Current Directory ');
3: writeln(' - Path not found');
5: writeln(' - Acess denied');
else writeln(' - Return code =',al);
end; (* case of Ax *)
End ; { CD }
End ; (* ChDir *)
(* ----------------------------------------------------------------- *)
(* EXECFile - Exec a file. *)
(* *)
(* ----------------------------------------------------------------- *)
Procedure EXECFile (Var RunString : comstring) ;
Type
FCB = record
Drive : char ;
filename : array [1..8] of char ;
filetype : array [1..3] of char ;
Curblock : integer ;
Recsize : integer ;
DosUse : array [1..16] of char ;
CurRec : byte ;
Randlow : integer ;
Randhigh : integer ;
end ;
PPBrecord = record
SegAddr : integer ;
ComlinePt : ^Comstring ;
FCB1pt,FCB2pt : ^FCB ;
end;
Var
PPB : PPBrecord ;
Myfile : comstring ;
FCB1,FCB2 : FCB ;
Begin (* RunFile *)
Myfile := Gettoken(Runstring);
If Pos('.',Myfile) = 0 then Myfile := Myfile + '.COM' ;
With Register do
Begin (* SetBlock - Modify allocated Memory Blocks *)
Ax := $4A00 ; (* Set Block - Free up unused memory *)
Es := CSeg ; (* Point to begining of block *)
Bx := SSeg ; (* Amount of memory in use *)
MsDos(Register);
Writeln(Register.BX,' paragraphs of memory in use .');
End ; (* SetBlock - Modify allocated Memory Blocks *)
Writeln(' Exec program ',Myfile);
Myfile := Myfile + chr($00) ;
With Register do
Begin (* Set up Run *)
Ax := $4B00 ; (* Load and EXEC Function *)
(* Ax := $4B03 ; *) (* Load Overlay Function *)
DS := Seg(Myfile); DX := Ofs(Myfile)+1 ; (* Point to Program name *)
ES := Seg(PPB) ; BX := Ofs(PPB); (* Point to Program Parm block *)
With PPB do
BEGIN (* set up Program Parameter Block *)
SegAddr := Memw[CSEG :$2C] ;
Comlinept := Addr(RunString);
FCB1pt := Addr(FCB1);
FCB2pt := Addr(FCB2);
End ; (* set up Program Parameter Block *)
(* MsDos(Register); *)
(* The following in line code does the same thing as the MsDos call *)
(* with the exception that it also save and restores the SS and SP reg. *)
Inline ( $BF/Register/ (* MOV DI,Register *)
$1E/ (* PUSH DS *)
$07/ (* POP ES *)
$1E/ (* PUSH DS *)
$06/ (* PUSH ES *)
$57/ (* PUSH DI *)
$55/ (* PUSH BP *)
$53/ (* PUSH BX *)
$B9/$09/$00/ (* MOV CX,0009 *)
$26/ (* ES: *)
$FF/$35/ (* PUSH [DI] *)
$47/ (* INC DI *)
$47/ (* INC DI *)
$E2/$F9/ (* LOOP back to PUSH [DI] *)
$07/ (* POP ES *)
$1F/ (* POP DS *)
$5F/ (* POP DI *)
$5E/ (* POP SI *)
$5D/ (* POP BP *)
$5A/ (* POP DX *)
$59/ (* POP CX *)
$5B/ (* POP BX *)
$58/ (* POP AX *)
(* Now save SS and SP in location 104 of Code Segment *)
$57/ (* PUSH DI *)
$BF/$0104/ (* MOV DI,0104 *)
$2E/ (* CS: *)
$8C/$15/ (* MOV [DI],SS *)
$47/ (* INC DI *)
$47/ (* INC DI *)
$2E/ (* CS: *)
$89/$25/ (* MOV [DI],SP *)
$5F/ (* POP DI *)
(* This dumb msdos call destroys all the register including SS and SP *)
$CD/$21/ (* ******** MsDos Call ******** *)
(* Restore the SS and SP register from location 104 of Code Segment *)
$BF/$0104/ (* MOV DI,0104 *)
$2E/ (* CS: *)
$8E/$15/ (* MOV SS,[DI] *)
$47/ (* INC DI *)
$47/ (* INC DI *)
$2E/ (* CS: *)
$8B/$25/ (* MOV SP,[DI] *)
$5F/ (* POP DI *)
(* Now restore the rest of the registers from the stack *)
$9C/ (* PUSH F *)
$06/ (* PUSH ES *)
$1E/ (* PUSH DS *)
$57/ (* PUSH DI *)
$56/ (* PUSH SI *)
$55/ (* PUSH BP *)
$52/ (* PUSH DX *)
$51/ (* PUSH CX *)
$53/ (* PUSH BX *)
$50/ (* PUSH AX *)
$8B/$EC/ (* MOV BP,SP *)
$8B/$7E/$18/ (* MOV DI,[BP+18] *)
$8E/$46/$1A/ (* MOV ES,[BP+1A] *)
$B9/$0A/$00/ (* MOV CX,000A *)
$26/ (* ES: *)
$8F/$05/ (* POP [DI] *)
$47/ (* INC DI *)
$47/ (* INC DI *)
$E2/$F9/ (* LOOP back to POP [DI] *)
$5B/ (* POP BX *)
$5D/ (* POP BP *)
$5F/ (* POP DI *)
$07/ (* POP ES *)
$1F); (* POP DS *)
Case Ax of
2: writeln('File >>> ',Myfile, ' <<< not found');
5: writeln('Acess denied');
8: writeln('Insufficient Memory to load program');
10: writeln('Invalid Environment');
end; (* case of Ax *)
End; (* Set up Run *)
Writeln(' Return from Execution of ',Myfile);
End; (* RunFile *)