GETCPM - Apple II CP/M to Pascal transfer program
Thor Hallen
thorh at tekig1.UUCP
Sun May 13 03:55:56 AEST 1984
--------------------------------------------------------------
(* UCSD Pascal to CP/M transfer program *)
(* by Tor Sj0wall, published in Nov.1980 Dr.Dobbs *)
(* typed and debugged by Rod Hart Feb.21,1980 *)
(* Modified for the Apple by David Neumann March 1981 *)
(* Sector mapping, new check for valid CP/M *)
(* directory and disk_reset are main Apple additions. *)
program GETCPM;
const void=229;
cpmeof=26;
cr=13;
lf=10;
tab=9;
null=0;
drivea=4;
driveb=5;
indent=4;
autolf=8;
num_of_blk=0;
offset_in_blk=1;
VERSION = 'November 12, 1982';
type nametype=packed array[0..10] of char;
namestring=string[30];
byte=0..255;
dirtype=packed array[0..2047] of byte;
maptype=packed array[0..15] of byte;
nonotype='N'..'n';
illetype=' '..']';
secttype=packed array[0..127] of byte;
legaltypes=(textfile,datafile,illegal);
blktype=packed array[1..512] of byte;
var iscpm:boolean;
filetype:legaltypes;
sourcename,destname:namestring;
nono:set of nonotype;
illechar:set of illetype;
filename:nametype;
textdest:text;
datadest:file of secttype;
directbuf:dirtype;
bigsectbuf:dirtype;
sec_map : array[0..31,0..1] of integer;
current_blk_buf : blktype;
lastsect : integer;
procedure INITIALIZE;
begin
illechar:=[' ','<','>',',','.',';',':','=','?','*','[',']'];
nono:=['N','n'];
lastsect := -2;
sec_map[0,num_of_blk] := 0;
sec_map[0,offset_in_blk] := 1;
sec_map[1,num_of_blk] := 0;
sec_map[1,offset_in_blk] := 129;
sec_map[2,num_of_blk] := 4;
sec_map[2,offset_in_blk] := 257;
sec_map[3,num_of_blk] := 4;
sec_map[3,offset_in_blk] := 385;
sec_map[4,num_of_blk] := 1;
sec_map[4,offset_in_blk] := 257;
sec_map[5,num_of_blk] := 1;
sec_map[5,offset_in_blk] := 385;
sec_map[6,num_of_blk] := 6;
sec_map[6,offset_in_blk] := 1;
sec_map[7,num_of_blk] := 6;
sec_map[7,offset_in_blk] := 129;
sec_map[8,num_of_blk] := 3;
sec_map[8,offset_in_blk] := 1;
sec_map[9,num_of_blk] := 3;
sec_map[9,offset_in_blk] := 129;
sec_map[10,num_of_blk] := 7;
sec_map[10,offset_in_blk] := 257;
sec_map[11,num_of_blk] := 7;
sec_map[11,offset_in_blk] := 385;
sec_map[12,num_of_blk] := 0;
sec_map[12,offset_in_blk] := 257;
sec_map[13,num_of_blk] := 0;
sec_map[13,offset_in_blk] := 385;
sec_map[14,num_of_blk] := 5;
sec_map[14,offset_in_blk] := 1;
sec_map[15,num_of_blk] := 5;
sec_map[15,offset_in_blk] := 129;
sec_map[16,num_of_blk] := 2;
sec_map[16,offset_in_blk] := 1;
sec_map[17,num_of_blk] := 2;
sec_map[17,offset_in_blk] := 129;
sec_map[18,num_of_blk] := 6;
sec_map[18,offset_in_blk] := 257;
sec_map[19,num_of_blk] := 6;
sec_map[19,offset_in_blk] := 385;
sec_map[20,num_of_blk] := 3;
sec_map[20,offset_in_blk] := 257;
sec_map[21,num_of_blk] := 3;
sec_map[21,offset_in_blk] := 385;
sec_map[22,num_of_blk] := 4;
sec_map[22,offset_in_blk] := 1;
sec_map[23,num_of_blk] := 4;
sec_map[23,offset_in_blk] := 129;
sec_map[24,num_of_blk] := 1;
sec_map[24,offset_in_blk] := 1;
sec_map[25,num_of_blk] := 1;
sec_map[25,offset_in_blk] := 129;
sec_map[26,num_of_blk] := 5;
sec_map[26,offset_in_blk] := 257;
sec_map[27,num_of_blk] := 5;
sec_map[27,offset_in_blk] := 385;
sec_map[28,num_of_blk] := 2;
sec_map[28,offset_in_blk] := 257;
sec_map[29,num_of_blk] := 2;
sec_map[29,offset_in_blk] := 385;
sec_map[30,num_of_blk] := 7;
sec_map[30,offset_in_blk] := 1;
sec_map[31,num_of_blk] := 7;
sec_map[31,offset_in_blk] := 129;
end;
function UPPERCASE (inchar:char):char;
begin
if inchar in ['a'..'z']
then uppercase:=chr(ord(inchar)-32)
else uppercase:=inchar;
end;
procedure CHECKTYPE (var filename:namestring;
var filetype:legaltype);
var i:integer;
hlp:namestring;
begin
for i=1 oiname[i]:=uppercase(filename[i]);
if length(filename)<>0 then
begin
if (filename[1]='*') or (filename[1]=':')
then
delete(filename,1,1);
if pos(':',filename)=0
then
fil filetype:=illegal;
if help='.TEXT' then filetype:=textfile;
if help[5]=':' then filetype:=textfile;
if help='.DATA' then filetype:=datafile;
end;
procedure CPMNAME (var wantname:nametype;
wantfile:namestring);
var i,j:integer;
begin
fillchar(wantname,11,' ');
i:=1;j:=0;
while((j<=10)and(i<=length(wantfile))) do
begin
if not(wantfile[i] in illechar)
then wantname[j]:=uppercase(wantfile[i])
else if (wantfile[i]='.')and(j<=8)then j:=7
else j:=10;
j:=j+1;i:=i+1
end
end;
procedure WRI do if flenameof_blk];
end;
function OFFgin
offset := sec_map[seqsect mod 32,offset_in_blk];
end;
procedure GETSECT(var buf:dirtype; bufoff,seqsect:integer);
var
off : integer;
begin
(* check to see if sector requested is *)
(* already in core. *)
if NOT (odd(seqsect) AND (seqsect = lastsect+1))
then
unitread(drivea,current_blk_buf,512,blocknum(seqsect));
off := offset(seqsect);
moveleft(current_blk_buf[off],buf[bufoff],128);
lastsect := seqsect;
end;
procedure DIRECTORY (var directbuf:dirtype;
var iscpm:boolean);
var i,seqsect:integer;
begin
seqsect := 3 * 32;
iscpm:=true;
getsect(directbuf,0,seqsect);
for i:=0 to 3 do
iscpm:=iscpm
and(directbuf[i*32+1]>=ord(' '))
and((directbuf[i*32+1]<128) or (directbuf[i*32+1]=void))
and not(chr(directbuf[i*32+1]mod 128) in illechar);
if iscpm then for i:=1 to 15 do
getsect(directbuf,i*128,seqsect+i);
end;
procedure PRINTDIRECT (directbuf:dirtype);
var i,dirbufpoint,filecount:integer;
begin
writeln ('CP/M directory listing :');
writeln('user name .type');
dirbufpoint:=0;
filecount:=0;
repeat
if(directbuf[dirbufpoint]<>void)and(directbuf
[dirbufpoint+12]=0)
then
begin
write(directbuf[dirbufpoint]:4,' ');
for i:=1 to 8 do
write(chr(directbuf[i+dirbufpoint] mod
128));
write(' ');
for i:=9 to 11 do
write(chr(directbuf[i+dirbufpoint] mod
128));
filecount:=filecount+1;
if(filecount mod 2)=0 then writeln else
write(' | ')
end;
dirbufpoint:=dirbufpoint+32
until dirbufpoint>=2048;
writeln;writeln(filecount,' files in directory.')
end;
procedure SCANDIRECT (var diskmap:maptype;
var found:boolean;
var size:byte;
dirbuf:dirtype;
filename:nametype;
extension:byte);
var dirbufpoint,i:integer;
namebuf:nametype;
begin
found:=false;
fillchar(namebuf,11,' ');
dirbufpoint:=0;
repeat
if dirbuf[dirbufpoint]<>void then
begin
for i:=0 to 10 do
namebuf[i]:=chr(dirbuf[dirbufpoint+i+1]
mod 128);
found:=(namebuf=filename)and(extension=
dirbuf[dirbufpoint+12]);
end;
dirbufpoint:=dirbufpoint+32;
until found or (dirbufpoint>=2048);
if found then
begin
dirbufpoint:=dirbufpoint-32;
size:=dirbuf[dirbufpoint+15];
for i:=0 to 15 do
diskmap[i]:=dirbuf[dirbufpoint+i+16]
end
end;
procedure COPYFILE (filename:nametype;
filetype:legaltypes);
var linepos:integer;
size,extension:byte;
found:boolean;
diskmap:maptype;
procedure COPYSECT (sectbuf:secttype);
begin
datadest^ :=sectbuf;
put(datadest)
end;
procedure COPYCHAR (inchar:byte);
begin
inchar:=inchar mod 128;
if inchar>=32
then
begin
linepos:=linepos+1;
write(textdest,chr(inchar))
end
else
begin
case inchar of
tab:begin
repeat
write(textdest,' ');
linepos:=linepos+1
until(linepos mod 8)=0;
exit(copychar)
end;
cr:begin
writeln(textdest);
linepos:=0;
exit(copychar)
end;
lf,null:exit(copychar);
cpmeof:begin
writeln;
writeln('End of file');
exit(copyfile)
end
end;
write(textdest,'?');
linepos:=linepos+1
end
end;
procedure COPYPAGE (valsects:integer;
cpmpage:byte);
var seqsect,j,temp:integer;
sectbuf:secttype;
begin
if cpmpage<>0 then
begin
seqsect := (cpmpage * 8) + (3 * 32);
temp:=seqsect+valsects;
while seqsect<temp do
begin
getsect(bigsectbuf,0,seqsect);
moveleft(bigsectbuf,sectbuf,128);
seqsect:=seqsect+1;
if filetype=textfile
then for j:=0 to 127 do copychar(sectbuf[j])
else copysect(sectbuf)
end
end
end;
procedure COPYEXTENSION (diskmap:maptype;
size:byte);
var i:integer;
begin
for i:=0 to (size div 8) - 1 do copypage
(8,diskmap[i]);
if(size mod 8)<>0 then copypage (size mod 8
,diskmap[size div 8])
end;
begin
extension :=0;
linepos :=0;
lastsect := -2;
repeat
scandirect(diskmap,found,size,directbuf,filename,
extension);
if found
then
begin
if(extension=0)and(size=0)
then writeln('File is empty')
else copyextension(diskmap,size);
extension:=extension+1
end
until not found;
if extension=0
then
begin
writename(filename);
writeln(' not found')
end
else
begin
writeln;writeln('End of file')
end
end;
procedure disk_reset;
var
out : text;
begin
(*$i-*)
reset(out,'#5');
close(out);
reset(out,'#4');
close(out);
(*$i+*)
end;
procedure cleanup;
begin
write('Insert Pascal boot volume in #4 and hit <return>'); readln;
disk_reset;
exit(program);
end;
(*main program*)
begin
initialize;
page(output);
writeln;writeln;
writeln('CP/M to UCSD Pascal file transfer');
writeln(' ',VERSION);
writeln;
writeln('Pascal diskette in drive #5');
writeln('CP/M diskette in drive #4');
writeln;
write('Press <return> when ready ');readln;writeln;
disk_reset;
directory(directbuf,iscpm);
if not iscpm
then
begin
writeln ('Not CP/M floppy in drive #4');
cleanup;
end;
repeat
printdirect(directbuf);
writeln;
writeln('<RETURN> to end.');
writeln;
write('Source CP/M file : ');
readln(sourcename);
if length(sourcename)=0
then
cleanup;
cpmname(filename,sourcename);
filetype:=illegal;
repeat
write('Destination Pascal file : ');
readln(destname);
if length(destname)=0
then
cleanup;
checktype(destname,filetype);
if filetype=illegal
then
begin
writeln('Illegal file name. (.TEXT or .DATA)');
writeln('Volume names (i.e. PRINTER:) are legal');
writeln('and are treated as TEXT transfers.');
end;
until filetype<>illegal;
if filetype=textfile
then
begin
writeln;writeln('TEXT file transfer');
rewrite (textdest,destname);
copyfile (filename,filetype);
close (textdest,lock);
end
else
begin
writeln;writeln('DATA file transfer');
rewrite (datadest,destname);
copyfile (filename,filetype);
close (datadest,lock)
end;
until false;
cleanup;
end.
More information about the Comp.sources.unix
mailing list