home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / MADTRB11.ZIP / PSYSTEM.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1985-08-05  |  9.3 KB  |  307 lines

  1. program psystem;
  2.  
  3. {
  4. This program will read files from a Diskette formatted under the
  5. UCSD p-system and transfer them to an MS-DOS diskette.  It assumes
  6. that the p-system diskette will be IN THE RIGHT-HAND DRIVE,
  7. and that the default diskette is NOT THE B-DISK.  It will read
  8. the directory, display it one file at a time, and then prompt the
  9. user for permission to copy the file.  It copies under the
  10. assumptions:
  11.  
  12.         1. Text files will be converted to ASCII, with the header
  13.            page (used by the p-system editor) discarded, and the
  14.            file converted to standard format. (see procedure pageout)
  15.  
  16.         2. Other files are copied as-is.
  17.  
  18.  
  19. (c) 1983, Paul Klarreich, Brooklyn, NY
  20.  
  21. This program is licensed for non-commercial use.
  22.  
  23. Source: "PSYSTEM: Converting UCSD Source Files To Turbo", TUG Lines Volume I Issue 3
  24. Author: Paul Klarreich
  25. Application: IBM PC UCSD Systems (modification required for use with CP/M machines)
  26.  
  27. }
  28.  
  29. type
  30.     direntry = packed record
  31.                         { This is the standard UCSD directory entry --
  32.                           same for all implementations.  The first one
  33.                           is always the volume entry. }
  34.         firstblok, lastblok : integer; { actually, lastblok -> beyond file }
  35.         filtype, blank : byte;
  36.         filname : string[15];
  37.         fillast, { # of bytes in the last block -- need for file size }
  38.         daterec : integer;
  39.     end;  { takes up 26 bytes }
  40.  
  41.     sectbuffer = array[0..511] of byte;  { For direct reading }
  42.     pagebuffer = array[0..1023] of byte; { For text files }
  43.     short = string[40];
  44.  
  45. var
  46.     mainbuf : sectbuffer;
  47.     textpage : pagebuffer;
  48.     directory : record case boolean of 
  49.         true : (dir : array[0..77] of direntry);
  50.         false: (bufs: array[0..3] of sectbuffer);
  51.     end;
  52.  
  53. { ------ Get a yes-no response from user -------- }
  54. function yes(message : short) : boolean;
  55. var resp : char;
  56. begin
  57.     write(message);
  58.     repeat read(kbd,resp);  resp := upcase(resp);
  59.     until resp in ['Y','N',chr(27)];
  60.     if resp = chr(27) then halt;
  61.     yes := resp = 'Y';
  62. end; { yes }
  63.  
  64. { ------------------ Print a directory entry --------------- }
  65. procedure printentry(var bb : direntry);
  66.  
  67. { print the file name, the number of blocks, and the type }
  68.  
  69. begin
  70.     { assume this is a live file -- test was made earlier }
  71.     with bb do write(filname : 16,'   ',lastblok - firstblok,
  72.         ' blocks,  ');
  73.     case bb.filtype of
  74.  
  75.         0,1,5 : write('data');
  76.         2     : write('code');
  77.         3     : write('text');
  78.         4     : write('foto');
  79.         6     : write('graf');
  80.         else write('????');
  81.     end;
  82.     writeln('-file');
  83. end;
  84.  
  85.  
  86. { -------------- Read a p-system block from 0..639 --------- }
  87.  
  88. function get1block(blockno : integer; var buffer : sectbuffer) : integer;
  89.  
  90. { tries to read the block.  Return code indicates the success }
  91.  
  92. var
  93.     returncode, sectorsdone, drive, side, track, sector,
  94.     sectorcount, bufsegment, bufoffset : integer;
  95. type 
  96.     regset = record
  97.         al, ah : byte;
  98.         bx : integer;
  99.         cl, ch, dl, dh : byte;
  100.         bp, si, di, ds, es, flags : integer;
  101.     end;
  102.  
  103. var
  104.     machine : regset;
  105.     otherbuffer : sectbuffer;
  106.  
  107.     { ----- Perform the mapping of block into side,track,sector ----}
  108.     { -----       Clearly this part is IBM-specific             ----}
  109.     procedure map(block : integer; var side,track,sector : integer);
  110.     begin
  111.         side := block div 320;
  112.         if side = 0 then
  113.             track := block div 8
  114.         else
  115.             track := 79 - block div 8;
  116.         sector := block mod 8 + 1;
  117.     end;
  118.     { ------------------------------------------------------------- }
  119.  
  120. begin { prepare the machine for an interrupt call }
  121.  
  122.     map(blockno, side, track, sector);
  123.  
  124.     with machine do begin
  125.         
  126.         dl := 1;  { drive 1 = the B-disk }
  127.         dh := side;  { which head to read from }
  128.         ch := track;
  129.         cl := sector;
  130.         al := 1;   { read just one sector }
  131.         es := seg(buffer);  { segment address of DMA operation }
  132.         bx := ofs(buffer);  { offset  address of DMA operation }
  133.         ah := 2;   { service code for reading sectors into memory }
  134.  
  135.     end;
  136.     { should be all set now }
  137.     writeln('Reading side ',side,' track ',track,' sector ',sector);
  138.     intr(19,machine);
  139.     { now check the result in ah }
  140.     returncode := machine.ah;
  141.  
  142.     if returncode = 9 then begin { DMA xfer across 64K boundary -- }
  143.                                  { can switch to auxiliary buffer  }
  144.         with machine do begin
  145.             al := 1;  ah := 2;
  146.             es := seg(otherbuffer);
  147.             bx := ofs(otherbuffer);
  148.         end;
  149.         intr(19,machine);
  150.         returncode := machine.ah;
  151.         if returncode = 0 then { OK this time } begin
  152.             move(otherbuffer,buffer,sizeof(sectbuffer));
  153.             get1block := 0;
  154.         end else get1block := returncode;
  155.     end else
  156.         get1block := returncode;
  157.  
  158. end; { get1block }
  159.  
  160.  
  161. { ----------- Read in the disk directory here -------------------- }
  162.  
  163. procedure readdir;
  164.  
  165. { read the four blocks that make up the directory.  They are always
  166.   at blocks 2,3,4,5 on the disk.   }
  167.  
  168. var count, result : integer;
  169.  
  170. begin
  171.     for count := 0 to 3 do begin
  172.  
  173.         result := get1block(count+2, directory.bufs[count]);
  174.         if result <> 0 then begin
  175.             writeln('Sorry -- read error in getting directory.');
  176.             halt;
  177.         end;
  178.  
  179.     end;
  180. end; { readdir }
  181.  
  182. { ---------------  Process a file here --------------------------- }
  183.  
  184. procedure getfile(var entry : direntry);
  185.  
  186. var
  187.     outfile : file of byte;
  188.     newname : string[16];
  189.     result, blockno, k : integer;
  190.  
  191.     { ------- Filter a page of a text file ---------- }
  192.     procedure pageout(var p : pagebuffer);
  193.     const
  194.         DLE = 16;  CR = 13;  ZERO = 0;  LF = 10;  BLANK = 32;
  195.     var cursor, nblanks : integer;
  196.         nextc, extra : byte;
  197.     begin
  198.         cursor := 0;
  199.         while cursor <= 1023 do begin
  200.  
  201.             nextc := p[cursor];  cursor := cursor + 1;
  202.             case nextc of
  203.                 CR : begin
  204.                          write(outfile,nextc);
  205.                          extra := LF; write(outfile,extra);
  206.                      end;
  207.               ZERO : ; { don't write the zeroes that pad the page }
  208.                DLE : begin { blank compression -- we expand it }
  209.                            extra := BLANK;
  210.                            nblanks := p[cursor] - 32; cursor := cursor + 1;
  211.                            while nblanks > 0 do begin
  212.                                write(outfile,extra);
  213.                                nblanks := nblanks - 1;
  214.                            end;
  215.                        end;
  216.                    else write(outfile,nextc);
  217.             end;
  218.  
  219.         end;
  220.     end; { pageout }
  221.  
  222.  
  223. begin { GETFILE here }
  224.  
  225.     write('Please give a DOS file name -->');
  226.     readln(newname);  assign(outfile,newname);
  227.     {$I-} rewrite(outfile); {$I+}
  228.     result := ioresult;
  229.     if result <> 0 then begin
  230.         writeln('Sorry -- cannot create the new file ',newname);
  231.         halt;
  232.     end;
  233.     with entry do  { use the entry to get the file }
  234.     if (filtype = 3 {text}) then begin
  235.  
  236.         writeln('Reading starts at ',firstblok + 2,' and goes for ',
  237.             lastblok - firstblok - 2,' blocks.');
  238.         blockno := firstblok + 2;
  239.         while blockno <= lastblok - 1 do begin
  240.  
  241.             result := get1block(blockno,mainbuf);
  242.             if result <> 0 then begin
  243.                 writeln('Sorry -- error reading the file.');
  244.                 halt;
  245.             end;
  246.             move(mainbuf,textpage,512);
  247.  
  248.             result := get1block(blockno + 1,mainbuf);
  249.             if result <> 0 then begin
  250.                 writeln('Sorry -- error reading the file.');
  251.                 halt;
  252.             end;
  253.             move(mainbuf,textpage[512],512);
  254.  
  255.             blockno := blockno + 2;
  256.             pageout(textpage);
  257.  
  258.         end;
  259.  
  260.     end else begin { not a text file }
  261.  
  262.         writeln('Reading starts at ',firstblok,' and goes for ',
  263.             lastblok - firstblok,' blocks.');
  264.         for blockno := firstblok to lastblok - 1 do begin
  265.  
  266.             result := get1block(blockno,mainbuf);
  267.             if result <> 0 then begin
  268.                 writeln('Sorry -- error reading the file.');
  269.                 halt;
  270.             end;
  271.             if blockno < lastblok - 1 then
  272.                 for k := 0 to 511 do write(outfile,mainbuf[k])
  273.             else
  274.                 for k := 0 to fillast do write(outfile,mainbuf[k]);
  275.  
  276.         end;  { for blockno }
  277.  
  278.     end;  { if text file }
  279.     close(outfile);
  280.     
  281. end; { getfile }
  282.  
  283. { ----------------------- MAIN PROGRAM -------------------- }
  284. var k : integer;
  285.  
  286. begin
  287.  
  288.     writeln('Place a p-system disk in the right-hand drive,');
  289.     writeln('then press enter.');  readln(kbd);
  290.  
  291.     readdir;
  292.     writeln('Finished reading the directory.');
  293.  
  294.     for k := 1 to 77 do begin
  295.         
  296.         { Find out if this is a live file. }
  297.  
  298.         if length(directory.dir[k].filname) in [1..15] then begin
  299.  
  300.             writeln;  printentry(directory.dir[k]);
  301.             if yes('Copy this file? (ESC to quit) ') then getfile(directory.dir[k]);
  302.  
  303.         end
  304.     end                
  305. end.
  306.  
  307.