home *** CD-ROM | disk | FTP | other *** search
/ Toolkit for DOOM / DOOMTOOL.ISO / editors / wadgc2.zip / NEWFLATS.C < prev    next >
C/C++ Source or Header  |  1994-07-31  |  9KB  |  351 lines

  1. /* NEWFLATS.C replace and/or add flats to an IWAD file */
  2. /* Stefan Gustavson 1994 */
  3.  
  4. #include <stdio.h>
  5.  
  6. typedef struct
  7. {
  8.   char name[8];
  9.   long pos, size;
  10. } direntry;
  11.  
  12. int getshort(filep)
  13.      FILE *filep;
  14. {
  15.   short s;
  16.   s = getc(filep) & 0xff;
  17.   s += (getc(filep) & 0xff)<<8;
  18.   return(s);
  19. }
  20.  
  21. int getlong(filep)
  22.      FILE *filep;
  23. {
  24.   int l;
  25.   l = getc(filep) & 0xff;
  26.   l += (getc(filep) & 0xff) <<8;
  27.   l += (getc(filep) & 0xff) <<16;
  28.   l += (getc(filep) & 0xff) <<24;
  29.   return(l);
  30. }
  31.  
  32. void putshort(d, filep)
  33.      short d;
  34.      FILE *filep;
  35. {
  36.   putc(d & 0xff, filep);
  37.   putc((d & 0xff00) >> 8, filep);  
  38. }
  39.  
  40. void putlong(d, filep)
  41.      long d;
  42.      FILE *filep;
  43. {
  44.   putc(d & 0xff, filep);
  45.   putc((d & 0xff00) >> 8, filep);
  46.   putc((d & 0xff0000) >> 16, filep);
  47.   putc((d & 0xff000000) >> 24, filep);
  48. }
  49.  
  50.  
  51. int readdir(dir, wadfile)
  52.      direntry dir[];
  53.      FILE *wadfile;
  54. {
  55.   int i, numentries, dirstart;
  56.   fseek(wadfile, 4, 0); /* Skip four bytes */
  57.   numentries = getlong(wadfile);
  58.   dirstart = getlong(wadfile);
  59.   if(fseek(wadfile, dirstart, 0))
  60.     {
  61.       fprintf(stderr, "File seek error.\n");
  62.       exit(-1);
  63.     }
  64.  for(i=0; i<numentries; i++)
  65.    {
  66.      dir[i].pos = getlong(wadfile);
  67.      dir[i].size = getlong(wadfile);
  68.      fread(dir[i].name, 8, 1, wadfile);
  69.    }
  70.   return numentries;
  71. }  
  72.  
  73.  
  74. void copytoflats(iwadfile, dir1, numentries1,
  75.          newiwadfile, dir3, numentries3)
  76.      FILE *iwadfile;
  77.      direntry dir1[];
  78.      int numentries1;
  79.      FILE *newiwadfile;
  80.      direntry dir3[];
  81.      int *numentries3;
  82. {
  83.   int i, j, pos;
  84.   fprintf(newiwadfile, "IWAD");
  85.   putlong(0, newiwadfile); /* Save for later */
  86.   putlong(0, newiwadfile); /* Save for later */
  87.   pos = 12;
  88.   i = 0;
  89.   while(strncmp(dir1[i].name, "F_START", 7))
  90.     {
  91.       fseek(iwadfile, dir1[i].pos, 0);
  92.       for(j=0; j<dir1[i].size; j++)
  93.     putc(getc(iwadfile), newiwadfile);
  94.       dir3[i].pos = pos;
  95.       dir3[i].size = dir1[i].size;
  96.       pos += dir3[i].size;
  97.       strncpy(dir3[i].name, dir1[i].name, 8);
  98.       i++;
  99.     }
  100.   *numentries3 = i;
  101. }
  102.  
  103.  
  104. void mergeflats(iwadfile, dir1, numentries1,
  105.          pwadfile, dir2, numentries2,
  106.          newiwadfile, dir3, numentries3)
  107.      FILE *iwadfile;
  108.      direntry dir1[];
  109.      int numentries1;
  110.      FILE *pwadfile;
  111.      direntry dir2[];
  112.      int numentries2;
  113.      FILE *newiwadfile;
  114.      direntry dir3[];
  115.      int *numentries3;
  116. {
  117.   int i1, i2, j, pos;
  118.   i1 = 0;
  119.   i2 = 0;
  120.   while(strcmp(dir1[i1].name, "F_START")) i1++;
  121.   while(strcmp(dir2[i2].name, "F_START")) i2++;
  122.  
  123.   /* Find out where the flats section starts in the NEW file. */
  124.   /* Note that this will not necessarily be the same position */
  125.   /* as in the original IWAD. There are holes in DOOM.WAD !   */
  126.   /* Also, don't trust the position of zero length entries.   */
  127.   for(j=0; ((*numentries3-j)>=0) & (dir3[*numentries3-j].size == 0); j++);
  128.   if((*numentries3-j)<0)
  129.     pos = 12; /* The flats start directly after the header */
  130.   else
  131.     /* The flats start after the closest preceding non-zero length entry */
  132.     pos = dir3[*numentries3-j].pos + dir3[*numentries3-j].size;
  133.   
  134.   while(strcmp(dir1[i1].name, "F1_END") & strcmp(dir2[i2].name, "F1_END"))
  135.     {
  136.       if(strncmp(dir1[i1].name, dir2[i2].name, 8))
  137.     {
  138.       /* No replacement - copy the old entry */
  139.       fseek(iwadfile, dir1[i1].pos, 0);
  140.       for(j=0; j<dir1[i1].size; j++)
  141.         putc(getc(iwadfile), newiwadfile);
  142.       dir3[*numentries3].pos = pos;
  143.       dir3[*numentries3].size = dir1[i1].size;
  144.       pos += dir3[*numentries3].size;
  145.       strncpy(dir3[*numentries3].name, dir1[i1].name, 8);
  146.       (*numentries3)++;
  147.       i1++;
  148.     }
  149.       else
  150.     /* Replacement entry - copy the new entry instead */
  151.     {
  152.       fseek(pwadfile, dir2[i2].pos, 0);
  153.       for(j=0; j<dir2[i2].size; j++)
  154.         putc(getc(pwadfile), newiwadfile);
  155.       dir3[*numentries3].pos = pos;
  156.       dir3[*numentries3].size = dir2[i2].size;
  157.       pos += dir3[*numentries3].size;
  158.       strncpy(dir3[*numentries3].name, dir2[i2].name, 8);
  159.       (*numentries3)++;
  160.       i1++;
  161.       i2++;
  162.     }
  163.     }
  164.   /* Copy any remaining original entries */
  165.   while(strcmp(dir1[i1].name, "F1_END"))
  166.     {
  167.       fseek(iwadfile, dir1[i1].pos, 0);
  168.       for(j=0; j<dir1[i1].size; j++)
  169.     putc(getc(iwadfile), newiwadfile);
  170.       dir3[*numentries3].pos = pos;
  171.       dir3[*numentries3].size = dir1[i1].size;
  172.       pos += dir3[*numentries3].size;
  173.       strncpy(dir3[*numentries3].name, dir1[i1].name, 8);
  174.       (*numentries3)++;
  175.       i1++;
  176.     }
  177.   /* Add new entries, if any */
  178.   while(strcmp(dir2[i2].name, "F1_END"))
  179.     {
  180.       fseek(pwadfile, dir2[i2].pos, 0);
  181.       for(j=0; j<dir2[i2].size; j++)
  182.     putc(getc(pwadfile), newiwadfile);
  183.       dir3[*numentries3].pos = pos;
  184.       dir3[*numentries3].size = dir2[i2].size;
  185.       pos += dir3[*numentries3].size;
  186.       strncpy(dir3[*numentries3].name, dir2[i2].name, 8);
  187.       (*numentries3)++;
  188.       i2++;
  189.     }
  190.   
  191.   /* Repeat the above procedure for the F2 section as well */
  192.  
  193.   while(strcmp(dir1[i1].name, "F2_END") & strcmp(dir2[i2].name, "F2_END"))
  194.     {
  195.       if(strncmp(dir1[i1].name, dir2[i2].name, 8))
  196.     {
  197.       /* No replacement - copy the old entry */
  198.       fseek(iwadfile, dir1[i1].pos, 0);
  199.       for(j=0; j<dir1[i1].size; j++)
  200.         putc(getc(iwadfile), newiwadfile);
  201.       dir3[*numentries3].pos = pos;
  202.       dir3[*numentries3].size = dir1[i1].size;
  203.       pos += dir3[*numentries3].size;
  204.       strncpy(dir3[*numentries3].name, dir1[i1].name, 8);
  205.       (*numentries3)++;
  206.       i1++;
  207.     }
  208.       else
  209.     /* Replacement entry - copy the new entry instead */
  210.     {
  211.       fseek(pwadfile, dir2[i2].pos, 0);
  212.       for(j=0; j<dir2[i2].size; j++)
  213.         putc(getc(pwadfile), newiwadfile);
  214.       dir3[*numentries3].pos = pos;
  215.       dir3[*numentries3].size = dir2[i2].size;
  216.       pos += dir3[*numentries3].size;
  217.       strncpy(dir3[*numentries3].name, dir2[i2].name, 8);
  218.       (*numentries3)++;
  219.       i1++;
  220.       i2++;
  221.     }
  222.     }
  223.   /* Copy any remaining original entries */
  224.   while(strcmp(dir1[i1].name, "F2_END"))
  225.     {
  226.       fseek(iwadfile, dir1[i1].pos, 0);
  227.       for(j=0; j<dir1[i1].size; j++)
  228.     putc(getc(iwadfile), newiwadfile);
  229.       dir3[*numentries3].pos = pos;
  230.       dir3[*numentries3].size = dir1[i1].size;
  231.       pos += dir3[*numentries3].size;
  232.       strncpy(dir3[*numentries3].name, dir1[i1].name, 8);
  233.       (*numentries3)++;
  234.       i1++;
  235.     }
  236.   /* Add new entries, if any */
  237.   while(strcmp(dir2[i2].name, "F2_END"))
  238.     {
  239.       fseek(pwadfile, dir2[i2].pos, 0);
  240.       for(j=0; j<dir2[i2].size; j++)
  241.     putc(getc(pwadfile), newiwadfile);
  242.       dir3[*numentries3].pos = pos;
  243.       dir3[*numentries3].size = dir2[i2].size;
  244.       pos += dir3[*numentries3].size;
  245.       strncpy(dir3[*numentries3].name, dir2[i2].name, 8);
  246.       (*numentries3)++;
  247.       i2++;
  248.     }
  249.   /* Write the F2_END and F_END markers and exit */
  250.   dir3[*numentries3].pos = pos;
  251.   dir3[*numentries3].size = 0;
  252.   strncpy(dir3[*numentries3].name, "F2_END", 8);
  253.   (*numentries3)++;
  254.   dir3[*numentries3].pos = pos;
  255.   dir3[*numentries3].size = 0;
  256.   strncpy(dir3[*numentries3].name, "F_END", 8);
  257.   (*numentries3)++;
  258. }
  259.  
  260.  
  261. void writedir(wadfile, dir, n)
  262.      FILE *wadfile;
  263.      direntry dir[];
  264.      int n;
  265. {
  266.   int i, dirstart;
  267.  
  268.   for(i=0; i<n; i++)
  269.     {
  270.       putlong(dir[i].pos, wadfile);
  271.       putlong(dir[i].size, wadfile);
  272.       fwrite(dir[i].name, 8, 1, wadfile);
  273.     }
  274.   for(i=0; ((n-i)>=0) & (dir[n-i].size == 0); i++);
  275.   if((n-i)<0)
  276.     dirstart = 12;
  277.   else
  278.     dirstart = dir[n-i].pos + dir[n-i].size;
  279.  
  280.   fseek(wadfile, 4, 0);
  281.   putlong(n, wadfile);
  282.   putlong(dirstart, wadfile);
  283. }
  284.  
  285.  
  286. main(argc, argv)
  287.      int argc;
  288.      char *argv[];
  289. {
  290.   FILE *iwadfile, *pwadfile, *newiwadfile;
  291.   char identifier[4];
  292.   int i, numentries1, numentries2, numentries3;
  293.   direntry dir1[4096], dir2[1024], dir3[4096];
  294.   
  295.   if (argc != 4)
  296.     {
  297.       fprintf(stderr, "Usage: %s iwad pwad newiwad\n", argv[0]);
  298.       exit(-1);
  299.     }
  300.   iwadfile = fopen(argv[1], "r");
  301.   if(iwadfile == NULL)
  302.     {
  303.       fprintf(stderr, "File %s not found.\n", argv[1]);
  304.       exit(-1);
  305.     }
  306.   fread(identifier, 4, 1, iwadfile);
  307.   if(strncmp("IWAD", identifier, 4))
  308.     {
  309.       fprintf(stderr, "File %s is not an IWAD file.\n", argv[1]);
  310.       exit(-1);
  311.     }
  312.   numentries1 = readdir(dir1, iwadfile);
  313.  
  314.   pwadfile = fopen(argv[2], "r");
  315.   if(pwadfile == NULL)
  316.     {
  317.       fprintf(stderr, "File %s not found.\n", argv[2]);
  318.       exit(-1);
  319.     }
  320.   fread(identifier, 4, 1, pwadfile);
  321.   if(strncmp("PWAD", identifier, 4))
  322.     {
  323.       fprintf(stderr, "File %s is not a PWAD file.\n", argv[2]);
  324.       exit(-1);
  325.     }
  326.   numentries2 = readdir(dir2, pwadfile);
  327.   newiwadfile = fopen(argv[3], "w");
  328.   if(pwadfile == NULL)
  329.     {
  330.       fprintf(stderr, "Unable to open output file %s.\n", argv[3]);
  331.       exit(-1);
  332.     }
  333.   printf("Copying other entries from %s to %s...\n", argv[1], argv[3]);
  334.   copytoflats(iwadfile, dir1, numentries1,
  335.           newiwadfile, dir3, &numentries3);
  336.   printf("Merging flat entries from %s and %s into %s...\n",
  337.      argv[1], argv[2], argv[3]);
  338.   mergeflats(iwadfile, dir1, numentries1,
  339.          pwadfile, dir2, numentries2,
  340.          newiwadfile, dir3, &numentries3);
  341.   printf("Writing directory to %s.\n", argv[3]);
  342.   writedir(newiwadfile, dir3, numentries3);
  343.  
  344.   fclose(iwadfile);
  345.   fclose(pwadfile);
  346.   fclose(newiwadfile);
  347. }
  348.  
  349.  
  350.  
  351.