home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
emulate
/
systems
/
read_pc
/
read-pc.pas
Wrap
Pascal/Delphi Source File
|
1986-12-12
|
13KB
|
508 lines
Program Read_PC;
{ Author: TS Kelso
Date: 22 February 1986
Description: This program is designed to read IBM PC diskettes (single or
double-sided) on a CP/M system and transfer them to a CP/M
file. This is particularly useful for transferring data files
from MS-DOS/PC-DOS to CP/M computers. Program requires that
the CP/M system be capable of reading comparable format CP/M
diskettes.
NOTE: Start address for compilation must be 2500H or greater!!}
{This program is placed in the public domain by the author and is available
for unrestricted use by individuals as long as this notice is maintained.
This program may not be used for any commercial purpose without express
written permission from the author.}
label
exit;
const
DMA_Address = $2100;
bytes = 512;
SPT = 9; {Sectors per track}
BPS = 4; {Blocks per sector}
RSS = 1; {Reserved sectors}
FATS = 2; {Number of FAT sectors}
NOF = 2; {Number of FATs}
TPS = 40; {Tracks per side}
{Configure to satisfy system requirements}
LDrive = 'A'; {Low system drive -- System dependent}
HDrive = 'D'; {High system drive -- System dependent}
target = 'C'; {CP/M target drive}
source = 'D'; {IBM diskette source drive}
type
string12 = string[12];
var
DMA : array [1..bytes] of byte absolute $2100;
FAT : array [1..NOF,1..1024] of byte;
Dir : array [1..bytes] of byte;
MD : byte; {Media Descriptor Byte}
sides, {Number of sides}
SPC, {Sectors per cluster}
SPD : integer; {Sectors per directory}
response : char;
valid : boolean;
Function Select_Disk(arg : char) : boolean;
var
param : integer;
begin
if arg in [LDrive..HDrive] then
begin
param := ord(arg)-ord('A');
BDOS(14,param);
Select_Disk := true;
end {if}
else
begin
GotoXY(1,24);
ClrEOL;
write('Disk Select Error -- Invalid Drive');
Delay(1000);
Select_Disk := false;
end; {else}
end; {Function Select_Disk}
Function Set_Track(arg : integer) : boolean;
begin
if arg in [0..sides*TPS-1] then
begin
BIOS(9,arg);
Set_Track := true;
end {if}
else
begin
GotoXY(1,24);
ClrEOL;
write('Track Select Error -- Not in range 0-',TPS-1);
Delay(1000);
Set_Track := false;
end; {else}
end; {Function Set_Track}
Procedure Set_DMA(arg : integer);
begin
BDOS(26,arg);
end; {Procedure Set_DMA}
Procedure Set_CPM_Sector(arg : integer);
begin
BIOS(10,arg);
end; {Procedure Set_Sector}
Function Read_Sector(arg1,arg2 : integer) : boolean;
var
n1,n2 : integer;
result : boolean;
begin
GotoXY(1,23);
ClrEOL;
write('Track ',arg1,', Sector ',arg2);
result := Set_Track(arg1);
if arg2 in [1..SPT] then
begin
for n1 := 1 to BPS do
begin
Set_DMA(DMA_Address + (n1-1)*$80);
n2 := (arg2-1)*BPS + n1;
Set_CPM_Sector(n2);
Delay(10);
if BIOS(12) <> 0 then
begin
GotoXY(1,24);
ClrEOL;
write('CP/M Sector ',n2,' read failed');
Delay(1000);
result := false;
end; {if BIOS(12)}
end; {for n1}
end {if}
else
begin
GotoXY(1,24);
ClrEOL;
write('Sector Select Error -- Not in range 1-',SPT);
Delay(1000);
result := false;
end; {else}
Read_Sector := result;
end; {Function Read_Sector}
Procedure Display_Sector;
const
columns = 64;
var
i1,i2,
pos,
lines : integer;
begin
lines := bytes div columns;
for i1 := 0 to lines-1 do
begin
for i2 := 1 to columns do
begin
pos := columns*i1 + i2;
if chr(DMA[pos]) in [' '..'~'] then
write(chr(DMA[pos]))
else
write('.');
if i2 mod 16 = 0 then
write(' ');
end; {for i2}
writeln;
end; {for i1}
end; {Procedure Display_Sector}
Procedure Transfer_to_FAT(index1,index2 : integer);
var
k : integer;
begin
for k := 1 to bytes do
FAT[index1,(index2-1)*bytes+k] := DMA[k];
end; {Procedure Transfer_to_FAT}
Procedure Read_FAT(number : integer);
var
start,i : integer;
begin
start := RSS + (number-1)*FATS;
for i := 1 to FATS do
begin
valid := Read_Sector(0,start+i);
if valid then
Transfer_to_FAT(number,i);
end; {for i}
end; {Procedure Read_FAT}
Function Compare_FATs : boolean;
const
total : integer = 0;
var
i : integer;
result : boolean;
begin
result := true;
for i := 1 to FATS*bytes do
if FAT[1,i] <> FAT[2,i] then
begin
total := total + 1;
result := false;
end; {if}
if not result then
begin
GotoXY(1,24);
ClrEOL;
write('File Allocation Table Error -- FATs do not compare!');
Delay(1000);
GotoXY(1,24);
ClrEOL;
write('Total disagreements = ',total);
Delay(1000);
end; {if}
Compare_FATs := result;
end; {Function Compare_FATs}
Function Convert_Filename(param : integer) : string12;
var
name : string12;
k : integer;
next : char;
begin
name := '';
for k := 1 to 8 do
begin
next := Chr(Dir[param+k]);
if next <> ' ' then
name := name + next;
end; {for}
name := name + '.';
for k := 9 to 11 do
begin
next := Chr(Dir[param+k]);
if next <> ' ' then
name := name + next;
end; {for}
Convert_Filename := name;
end; {Function Convert_Filename}
Function Convert_Date(param : integer) : string12;
const
months = 'JanFebMarAprMayJunJulAugSepOctNovDec';
var
date : string12;
mo,dy,yr : integer;
next : string[2];
begin
mo := ((Dir[param+26] and 1) shl 3) or (Dir[param+25] shr 5);
dy := (Dir[param+25] and $1F);
yr := (Dir[param+26] shr 1) + 80;
Str(dy:2,next);
if next[1] = ' ' then
next[1] := '0';
if mo in [1..12] then
begin
date := next + '-' + Copy(months,(mo-1)*3+1,3) + '-';
Str(yr:2,next);
date := date + next;
end
else
date := ' No Date ';
Convert_Date := date;
end; {Function Convert_Date}
Function Convert_Time(param : integer) : string12;
var
time : string12;
hr,mi,sc : integer;
next : string[2];
begin
mi := ((Dir[param+24] and 7) shl 3) or (Dir[param+23] shr 5);
sc := (Dir[param+23] and $1F) shl 1;
hr := (Dir[param+24] shr 3);
Str(hr:2,next);
if next[1] = ' ' then
next[1] := '0';
time := next + ':';
Str(mi:2,next);
if next[1] = ' ' then
next[1] := '0';
time := time + next + ':';
Str(sc:2,next);
if next[1] = ' ' then
next[1] := '0';
time := time + next;
Convert_Time := time;
end; {Function Convert_Time}
Function Convert_Size(param : integer) : real;
begin
Convert_Size := 16777216.0*Dir[param+32] + 65536.0*Dir[param+31]
+ 256.0*Dir[param+30] + Dir[param+29];
end; {Function Convert_Size}
Function Convert(param : integer) : integer;
begin
Convert := SPC*(param - 2) + RSS + NOF*FATS + SPD + 1;
end; {Function Convert}
Function Next_Cluster(param : integer) : integer;
var
next : integer;
begin
next := (3*param div 2) + 1;
next := 256*FAT[1,next+1] + FAT[1,next];
if param mod 2 = 0 then
next := next and $0FFF
else
next := next shr 4;
Next_Cluster := next;
end; {Function Next_Cluster}
Function Max(arg1,arg2 : real) : real;
begin
if arg1 >= arg2 then
Max := arg1
else
Max := arg2;
end; {Function Max}
Procedure Transfer_File(arg : integer);
var
outfile : file;
filename : string12;
size : real;
m,track,sector,
start,blocks,
cluster : integer;
done,result : boolean;
begin
done := false;
filename := Convert_Filename(arg);
Assign(outfile,target+':'+filename);
Rewrite(outfile);
size := Convert_Size(arg);
GotoXY(1,21);
ClrEOL;
write('File being transferred: ',
filename,' ',Convert_Time(arg),' ',
Convert_Date(arg),' ',size:8:0,' bytes');
cluster := 256*Dir[arg+28] + Dir[arg+27];
GotoXY(1,22);
ClrEOL;
write('Cluster ',cluster:3);
repeat
start := Convert(cluster);
for m := start to start+SPC-1 do
begin
track := (m-1) div SPT;
if (sides = 2) then
track := Abs((track mod 2)*(sides*TPS-1) - (track div 2));
sector := ((m-1) mod SPT) + 1;
result := Read_Sector(track,sector);
if size <> 0 then
begin
if size < bytes then
begin
blocks := Trunc((size-1)/128) + 1;
BlockWrite(outfile,DMA,blocks);
end {if size < bytes}
else
BlockWrite(outfile,DMA,4);
size := Max(0,size - bytes);
end; {if size <> 0}
end; {for m}
if Next_Cluster(cluster) >= $FF8 then
done := true
else
begin
cluster := Next_Cluster(cluster);
GotoXY(1,22);
ClrEOL;
write('Cluster ',cluster:3);
end;
until done;
Close(outfile);
end; {Procedure Transfer_File}
Procedure Check_Entries;
var
offset,j : integer;
check1,check2 : byte;
begin
for j := 1 to (bytes div 32) do
begin
offset := (j-1)*32;
check1 := Dir[offset+1];
check2 := Dir[offset+12];
if not (check1 in [$00,$2E,$E5]) and not (check2 in [$08,$10]) then
Transfer_File(offset);
end; {for j}
end; {Procedure Check_Entries}
Procedure Load_Directory;
var
k : integer;
begin
for k := 1 to bytes do
Dir[k] := DMA[k];
end; {Procedure Load_Directory}
Procedure Search_Directory;
var
track,
sector,
start,i : integer;
result : boolean;
begin
start := RSS + NOF*FATS;
for i := 1 to SPD do
begin
GotoXY(1,20);
ClrEOL;
write('Directory Sector ',i);
sector := start + i;
track := (sector-1) div SPT;
sector := ((sector-1) mod SPT) + 1;
if (sides = 2) then
track := Abs((track mod 2)*(sides*TPS-1) - (track div 2));
result := Read_Sector(track,sector);
Load_Directory;
Check_Entries;
end; {for i}
end; {Procedure Search_Directory}
BEGIN
ClrScr;
writeln('This program is designed to read IBM PC/XT diskettes,');
writeln('either SS or DS, and transfer the files on that diskette');
writeln('to a CP/M formatted diskette. While written for the H-89');
writeln('using the Magnolia disk controller, it should work on any');
writeln('CP/M system which supports a format compatible with the IBM');
writeln('format. It should also work for MS-DOS diskettes.');
writeln;
{Ensure system is prepared to read IBM format diskette}
writeln('Did you set the target drive to read IBM compatible format');
write('before running this program? ');
repeat
read(kbd,response);
response := Upcase(response);
valid := true;
case response of
'Y' : writeln('Yes');
'N' : begin
writeln('No');
writeln;
writeln('You must exit and configure target drive.');
goto exit;
end; {No}
else
valid := false;
end; {case}
until valid;
writeln;
{Specify drives to read IBM diskette from and write CP/M files on}
writeln('Insert CP/M (target) diskette in Drive ',target,': and IBM PC/XT');
writeln('(source) diskette in Drive ',source,':.');
writeln;
write('Hit any key to begin.');
read(kbd,response);
valid := Select_Disk(source);
writeln;
{Read FATs and compare}
GotoXY(1,16);
ClrEOL;
writeln('Reading FAT Number 1');
Read_FAT(1);
GotoXY(1,16);
ClrEOL;
writeln('Reading FAT Number 2');
Read_FAT(2);
GotoXY(1,16);
ClrEOL;
write('Comparing FATs -- ');
valid := Compare_FATs;
if valid then
writeln('Successful compare')
else
goto exit;
{Determine Media Type and set media-peculiar parameters}
MD := FAT[1,1];
case MD of
$FC : begin
sides := 1;
SPC := 1;
SPD := 4;
end; {MD = $FC}
$FD : begin
sides := 2;
SPC := 2;
SPD := 7;
end; {MD = $FD}
else
begin
GotoXY(1,24);
ClrEOL;
write('Unrecognized Media Descriptor Byte');
Delay(1000);
goto exit;
end; {else}
end; {case}
{Transfer files}
Search_Directory;
Set_DMA($0080);
GotoXY(1,24);
ClrEOL;
writeln('File transfer completed.');
exit:
END.