PROGRAM cpmcopy; (*Written by J. M. Wierda This program will transfer a CP/M file from a disk in unit 5 to a Pascal disk in unit 4. Note that when the filename is requested, it must be 11 characters long and include all spaces. This program does not remove the LFs from the CP/M file as the transfer is made, so a replace command in the Pascal editor should be used to delete the LFs. During successful file transfers the program prints an expanded CP/M directory of the file being tranferred. Attempts to transfer empty or non-existent files are ignored.*) CONST blkslip = 2; quadsperblk = 4; trkslip = 6; blkspertrk = 6.5; secpergrp = 8; lastsec = 26; lasttrk = 76; TYPE groupbuffer = packed array[0..1023] of char; VAR sectortbl : ARRAY[1..lastsec] OF integer; grptrk : ARRAY[1..secpergrp] OF integer; grpsec : ARRAY[1..secpergrp] OF integer; quadmap : ARRAY[1..lastsec] OF integer; blockmap : ARRAY[1..lastsec] OF integer; blockbuffer : PACKED ARRAY[0..511] OF char; directbuffer : groupbuffer; transferbuffer : groupbuffer; prevtrk, filectr : integer; currfile, filename : string; outfile : string; file2 : text; PROCEDURE trackmap(track : integer); VAR sector,sect,blk,quad,firstsect : integer; firstblkquad : real; BEGIN IF track <> prevtrk THEN BEGIN firstblkquad := (track-1)*blkspertrk; blk := trunc(firstblkquad); firstsect := (((track-1)*trkslip)+1) MOD lastsec; quad := trunc((firstblkquad-blk)*quadsperblk); sect := firstsect; FOR sector := 1 TO lastsec DO BEGIN blockmap[sect] := blk; quadmap[sect] := quad; sect := (sect + blkslip) MOD lastsec; IF sect = 0 THEN sect := lastsec; IF sect = firstsect THEN sect := sect + 1; quad := (quad+1) MOD quadsperblk; IF quad = 0 THEN blk := blk + 1 END END END; PROCEDURE initsectbl; BEGIN sectortbl[1] := 1; sectortbl[2] := 7; sectortbl[3] := 13; sectortbl[4] := 19; sectortbl[5] := 25; sectortbl[6] := 5; sectortbl[7] := 11; sectortbl[8] := 17; sectortbl[9] := 23; sectortbl[10] := 3; sectortbl[11] := 9; sectortbl[12] := 15; sectortbl[13] := 21; sectortbl[14] := 2; sectortbl[15] := 8; sectortbl[16] := 14; sectortbl[17] := 20; sectortbl[18] := lastsec; sectortbl[19] := 6; sectortbl[20] := 12; sectortbl[21] := 18; sectortbl[22] := 24; sectortbl[23] := 4; sectortbl[24] := 10; sectortbl[25] := 16; sectortbl[lastsec] := 22 END; PROCEDURE cpmgrp(group : integer); VAR j, track, sector : integer; BEGIN track := ((group * 8) DIV lastsec) + 2; sector := ((group * 8) MOD lastsec) + 1; FOR j := 1 TO secpergrp DO BEGIN grptrk[j] := track; grpsec[j] := sectortbl[sector]; sector := sector + 1; IF sector > lastsec THEN BEGIN sector := 1; track := track + 1 END END END; procedure readgroup(group : integer; VAR buffer : groupbuffer); var j, k, l : integer; begin cpmgrp(group); l := 0; for j := 1 to secpergrp do begin trackmap(grptrk[j]); unitread(10,blockbuffer,512,blockmap[grpsec[j]],0); for k := ((quadmap[grpsec[j]])*128) to k+127 do begin buffer[l] := blockbuffer[k]; l := l+1 end end end; PROCEDURE printentries; VAR j, k : integer; begin j := 0; while j < 1024 do BEGIN IF (ord(directbuffer[j]) = 0) AND (ord(directbuffer[j+12]) = 0) AND (directbuffer[j+1] IN [' '..'Z']) THEN BEGIN FOR k := j+1 TO j+11 DO write(directbuffer[k]); filectr := filectr + 1; IF (filectr MOD 4) = 0 THEN writeln ELSE write(' ') END; j := j+32 END end; PROCEDURE findentry; VAR extent, sectors, j, k, l : integer; eoffound : boolean; BEGIN j := 0; WHILE j < 1024 DO BEGIN IF ord(directbuffer[j]) = 0 THEN BEGIN currfile := ' '; extent := ord(directbuffer[j+12]); sectors := ord(directbuffer[j+15]); FOR k := j+1 TO j+11 DO currfile[k-j] := directbuffer[k]; IF (currfile = filename) AND (sectors > 0) THEN BEGIN IF extent = 0 THEN BEGIN write('Output Filename.Ext ? '); readln(outfile); rewrite(file2, outfile); writeln(currfile); writeln('Ex Sec Groups') END; write(extent: 2,sectors: 4); FOR k := j+16 TO (k+((sectors-1) DIV 8)) DO begin write(ord(directbuffer[k]): 4); readgroup(ord(directbuffer[k]), transferbuffer); l := 0; eoffound := false; WHILE l <= 1023 DO begin IF (ord(transferbuffer[l]) <> 26) and (not eoffound) then write(file2, transferbuffer[l]) else begin eoffound := true; write(file2, chr(0)) end; l := l + 1 end; end; IF sectors < 128 THEN close(file2,lock); writeln END END; j := j+32 END END; BEGIN filectr := 0; prevtrk := 0; initsectbl; writeln('CP/M File Transfer, 7-Jun-79'); readgroup(0, directbuffer); printentries; readgroup(1, directbuffer); printentries; writeln; writeln(filectr,' Files'); REPEAT REPEAT writeln; write('Transfer which file ? '); readln(filename); IF NOT (length(filename) IN [0,11]) THEN BEGIN write('Enter 11 character filename exactly as listed'); writeln(', including spaces,'); writeln('or CR to exit program.') END UNTIL length(filename) IN [0,11]; IF length(filename) = 11 THEN BEGIN readgroup(0, directbuffer); findentry; readgroup(1, directbuffer); findentry END; UNTIL length(filename) = 0; END