home *** CD-ROM | disk | FTP | other *** search
/ Brotikasten / BROTCD01.iso / amiga / 1541.lha / getfiles.c < prev    next >
C/C++ Source or Header  |  1994-06-17  |  7KB  |  313 lines

  1. ;/*
  2. sc DisAsm=ram:getfiles.s NoCheckAbort getfiles.c ProgramName=getfiles ObjectName=ram: Ignore=73+306 GST=include:all.gst GSTImm NoIcon NoStackCheck UnsignedChar Parm=Register Opt OptSched OptInLocal OptDep=100 OptRDep=100 CommentNest Link
  3. quit
  4. */
  5.  
  6. /*
  7. 1541 disk-image-to-files converter
  8. Copyright ⌐ 1994 by Dan Babcock
  9.  
  10. Compiled with SAS/C V6.51
  11. */
  12.  
  13. typedef short bool; /* enum bool { FALSE, TRUE }; */
  14.  
  15. /* Buffers */
  16. #define DISKSIZE 683*256
  17. static __far char DiskImage[DISKSIZE];
  18. static usedsecs[683];
  19.  
  20. /* Command line parsing */
  21. enum cmdargs { FILENAME, DIROPT, EXT, NUMARGS };
  22. static struct RDArgs *rdargs;
  23. static LONG args[NUMARGS];
  24.  
  25. /* Misc */
  26. static char ver[]="$VER: getfiles 1.00 (16.6.94)\n";
  27. long __OSlibversion = 37;
  28.  
  29.  
  30. /* Returns the address (somewhere in DiskImage) corresponding to a given track and
  31.    sector, or NULL if the track/sector pair is invalid.
  32. */
  33. static char *GetTSAddress(unsigned track, unsigned sector)
  34. {
  35.     unsigned sec;
  36.  
  37.     if (track<1 || track>35 || sector>20)
  38.         return NULL;
  39.  
  40.     if (track < 18)    /* zone 1 */
  41.         sec=(track-1)*21+sector;
  42.     else if (track < 25)    /* zone 2 */
  43.         sec=357+(track-18)*19+sector;
  44.     else if (track < 31)    /* zone 3 */
  45.         sec=490+(track-25)*18+sector;
  46.     else    /* zone 4 */
  47.         sec=598+(track-31)*17+sector;
  48.  
  49.     if (sec>=683) return NULL;
  50.     if (usedsecs[sec]) return NULL; /* circular link or other weirdness */
  51.     usedsecs[sec]=1;
  52.     return DiskImage+(sec*256);
  53. }
  54.  
  55. /* Dumps the indicated file to disk */
  56. static void DumpFile(char track, char sector, char *file)
  57. {
  58.     struct datablock {
  59.         char nexttrack; /* or 0 for last sector */
  60.         char nextsector; /* or "N-1 data bytes on this sector" */
  61.         char data[254];
  62.     };
  63.  
  64.     struct datablock *data;
  65.     BPTR fh;
  66.     LONG length;
  67.     unsigned i;
  68.     bool illegal=FALSE;
  69.  
  70.     data=(struct datablock*)GetTSAddress(track, sector);
  71.     if (data==NULL) {
  72.         printf("        Invalid sector pointer - skipped\n");
  73.         return;
  74.     }
  75.  
  76.     /* Open output file. But first, scan for illegal characters and replace as
  77.        appropriate. */
  78.     for (i=0; file[i]; i++) {
  79.         switch (file[i]) {
  80.             case '/':
  81.                 file[i]='\\';
  82.                 illegal=TRUE;
  83.                 break;
  84.             case ':':
  85.                 file[i]=';';
  86.                 illegal=TRUE;
  87.                 break;
  88.             default:
  89.                 if (file[i]<=0x1F || (file[i]>=0x7F && file[i]<=0x9F)) {
  90.                     file[i]='-';
  91.                     illegal=TRUE;
  92.                 }
  93.                 break;
  94.         }
  95.     }
  96.     if (illegal)
  97.         printf("        Illegal file name changed to \"%s\"\n",file);
  98.  
  99.     fh=Open(file,MODE_NEWFILE);
  100.     if (fh==0) {
  101.         printf("        Can't create file\n");
  102.         return;
  103.     }
  104.  
  105.     while (data->nexttrack) {
  106.         length=Write(fh,data->data,254);
  107.         if (length != 254) {
  108.             printf("        Error writing file\n");
  109.             Close(fh);
  110.             return;
  111.         }
  112. //        printf("        Next: track %d, sector %d\n",(int)data->nexttrack,(int)data->nextsector);
  113.         data=(struct datablock*)GetTSAddress(data->nexttrack,data->nextsector);
  114.         if (data==NULL) {
  115.             printf("        Invalid sector pointer - aborted\n");
  116.             Close(fh);
  117.             return;
  118.         }
  119.     }
  120.  
  121.     if (strncmp(data->data,"LAZARUS",7)==0) {
  122.         printf("        File contains bad sector (corrupt)\n");
  123.     }
  124.  
  125.     if (data->nextsector >= 2) {
  126.         length=Write(fh,data->data,data->nextsector-1);
  127.         if (length != data->nextsector-1) {
  128.             printf("        Error writing file\n");
  129.         }
  130.     }
  131.     else {
  132.         printf("        Invalid sector length - file probably truncated\n");
  133.     }
  134.  
  135.     Close(fh);
  136. }
  137.  
  138.  
  139. /* Get a 1541 name (up to 16 characters padded with $A0) and place in a normal
  140.    C string.
  141. */
  142. static void Get1541Name(char *dest, const char *source)
  143. {
  144.     int i;
  145.  
  146.     for (i=0; (source[i] != 0xA0) && (i <= 15); i++) {
  147.         dest[i]=source[i];
  148.     }
  149.     dest[i]=0;
  150. }
  151.  
  152. /* Scans through the directory blocks calling DumpFile() as appropriate */
  153. static void Dump(void)
  154. {
  155.     struct BAM {
  156.         char startdirtrack;
  157.         char startdirsector;
  158.         char format;    /* ASCII "A" */
  159.         char notused1[1];
  160.         char bam[140];
  161.         char diskname[16];
  162.         char shiftedspaces[2];
  163.         char diskid[2];
  164.         char shiftedspace[1];
  165.         char dosversion[2];
  166.         char shiftedspaces2[4];
  167.         char notused2[85];
  168.     };
  169.     struct FileEntry {  /* repeated 8 times per sector */
  170.         char dirtrack;  /* chain: only valid for first entry */
  171.         char dirsector; /* chain: only valid for first entry */
  172.         char type;      /* file type */
  173.         char track;     /* start of file */
  174.         char sector;
  175.         char name[16];   /* file name padded with 0xA0 */
  176.         char notused[11];
  177.     };
  178.     struct BAM *BAM;
  179.     struct FileEntry *dir;
  180.     char track, sector;
  181.     char diskname[17];
  182.     unsigned i;
  183.  
  184.     /* initialize usedsecs[] to zero */
  185.     for (i=0; i <= 682; i++)
  186.         usedsecs[i]=0;
  187.  
  188.     BAM=(struct BAM*)GetTSAddress(18,0);
  189.     Get1541Name(diskname,BAM->diskname);
  190.     printf("    Disk name: %s\n",diskname);
  191.  
  192.     for (track=BAM->startdirtrack, sector=BAM->startdirsector;
  193.          dir=(struct FileEntry*)GetTSAddress(track, sector);
  194.          track=dir[0].dirtrack, sector=dir[0].dirsector) {
  195.         int entry;
  196.         for (entry=0; entry <= 7; entry++) {
  197.             if (dir[entry].type != 0) {
  198.                 char filename[21];
  199.                 char ext[4];
  200.                 Get1541Name(filename,dir[entry].name);
  201.                 switch (dir[entry].type & ~(1<<6)) {
  202.                     case 0x80:
  203.                         strcpy(ext,"DEL");
  204.                         break;
  205.                     case 0x81:
  206.                         strcpy(ext,"SEQ");
  207.                         break;
  208.                     case 0x82:
  209.                         strcpy(ext,"PRG");
  210.                         break;
  211.                     case 0x83:
  212.                         strcpy(ext,"USR");
  213.                         break;
  214.                     case 0x84:
  215.                         strcpy(ext,"REL");
  216.                         break;
  217.                     default:
  218.                         printf("    Skipped file \"%s\" of unknown type $%x\n",filename,(int)dir[entry].type);
  219.                         continue;
  220.                     }
  221.                 printf("    %-17s%s\n",filename,ext);
  222.                 if (args[EXT]) {
  223.                     strcat(filename,".");
  224.                     strcat(filename,ext);
  225.                 }
  226.                 if (!args[DIROPT])
  227.                     DumpFile(dir[entry].track,dir[entry].sector,filename);
  228.             }
  229.         }
  230.     }
  231. }
  232.  
  233. /* Reads in image file, creates and changes to a new directory for the file dump,
  234.    and calls Dump()
  235. */
  236. static void Convert(const char *filename)
  237. {
  238.     static char newdirname[100];
  239.     static char error[100];
  240.     char *period;
  241.     BPTR dir, olddir;
  242.     BPTR imagefile;
  243.     LONG size;
  244.  
  245.     /* read in image file */
  246.     imagefile=Open((char*)filename,MODE_OLDFILE);
  247.     if (imagefile==0) {
  248.         printf("Couldn't open file %s\n",filename);
  249.         return;
  250.     }
  251.     size=Read(imagefile,DiskImage,DISKSIZE);
  252.     Close(imagefile);
  253.     if (size != DISKSIZE) {
  254.         printf("Couldn't read file %s\n",filename);
  255.         return;
  256.     }
  257.  
  258.     printf("Converting %s\n",filename);
  259.  
  260.     if (args[DIROPT]) {
  261.         Dump();
  262.         return;
  263.     }
  264.  
  265.     /* form directory name (add ".files", omit ".#?") */
  266.     strcpy(newdirname,filename);
  267.     period=strchr(newdirname,'.');
  268.     if (period==0) period=newdirname+strlen(newdirname);
  269.     strcpy(period,".files");
  270.  
  271.     /* create directory */
  272.     dir=CreateDir(newdirname);
  273.     if (dir==0) {
  274.         printf("    Couldn't create directory %s ",newdirname);
  275.         Fault(IoErr(),"",error,100);
  276.         printf("%s\n",error);
  277.         return;
  278.     }
  279.  
  280.     olddir=CurrentDir(dir);
  281.     Dump();
  282.     CurrentDir(olddir);
  283.     UnLock(dir);
  284. }
  285.  
  286. /* Uses pattern matching routines to find files and calls Convert() */
  287. void main(void)
  288. {
  289.     static struct AnchorPath MyAp;
  290.     LONG match;
  291.     BPTR olddir;
  292.  
  293.     printf("getfiles - Copyright ⌐ 1994 by Dan Babcock\n");
  294.  
  295.     /* Handle command-line arguments */
  296.     rdargs=ReadArgs("FILENAME/A,DIR/S,EXT=EXTENSIONS/S",args,0);
  297.     if (rdargs == 0) {
  298.         printf("Invalid parameters\n");
  299.         return;
  300.     }
  301.  
  302.     MyAp.ap_BreakBits = SIGBREAKF_CTRL_C; /* Break on these bits */
  303.     for (match=MatchFirst((char*)args[FILENAME],&MyAp); match==0; match=MatchNext(&MyAp)) {
  304.         if ((MyAp.ap_Info.fib_DirEntryType < 0) && (MyAp.ap_Info.fib_Size==DISKSIZE)) {
  305.             olddir=CurrentDir(MyAp.ap_Current->an_Lock);
  306.             Convert(MyAp.ap_Info.fib_FileName);
  307.             CurrentDir(olddir);
  308.         }
  309.     }
  310.     MatchEnd(&MyAp);
  311.     FreeArgs(rdargs);
  312. }
  313.