home *** CD-ROM | disk | FTP | other *** search
- 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.