Subversion Repositories vaca_plus

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.     SSI File Unpacker
  3.     Copyright (c) 2003  Jonathon Fowler
  4.  
  5.     This program is free software; you can redistribute it and/or modify
  6.     it under the terms of the GNU General Public License as published by
  7.     the Free Software Foundation; either version 2 of the License, or
  8.     (at your option) any later version.
  9.  
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU General Public License
  16.     along with this program; if not, write to the Free Software
  17.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  */
  19.  
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22.  
  23. int main(int argc, char **argv)
  24. {
  25.         FILE *fp, *ofp;
  26.         long i,j;
  27.         long version;
  28.         long numfiles;
  29.         unsigned char numchars;
  30.         char title[33];
  31.         char description[3][71];
  32.         struct file {
  33.                 char name[13];
  34.                 long length;
  35.         } *filenames;
  36.         char runfile[13] = "<unknown>";
  37.         char buf[1024];
  38.         int mode=0, param;
  39.  
  40.         puts("unpackssi - .SSI File Unpacker\n"
  41.              "Copyright (c) 2003 Jonathon Fowler\n"
  42.              "This software is distributed under the terms of the GNU General Public License.");
  43.                
  44.         if (argc<2) {
  45.                 puts("\nUsage: unpackssi [-l] <ssifile.ssi> [ssifile2.ssi ...]");
  46.                 puts("  Unpacks the contents of an SSI file (like those which Sunstorm Interactive");
  47.                 puts("  expansion packs for Duke Nukem 3D are distributed in) to the current");
  48.                 puts("  directory. NOTE: Any files which already exist and have the same name as the");
  49.                 puts("  files contained in the SSI file will be overwritten when extracting.");
  50.                 puts("\nSwitches:");
  51.                 puts("  -l  List files (no extraction)\n");
  52.                 return -1;
  53.         } else {
  54.                 param = 1;
  55.                 if (argv[1][0] == '-') {
  56.                         param++;
  57.                         switch (argv[1][1]) {
  58.                                 case 'l': mode = 1; break;
  59.                                 default: printf("Unrecognised switch: %c.\n", argv[1][1]); break;
  60.                         }
  61.                 }
  62.         }
  63.  
  64.         while (param < argc) {
  65.                 puts("");
  66.  
  67.                 fp = fopen(argv[param],"rb");
  68.                 if (!fp) return -2;
  69.  
  70.                 fread(&version, 4, 1, fp);
  71.                 if (version != 1 && version != 2) {
  72.                         fclose(fp);
  73.                         puts("Error: Unrecognized SSI version.");
  74.                         return -1;
  75.                 }
  76.  
  77.                 printf("File is SSI Version %d\n", version);
  78.                
  79.                 fread(&numfiles, 4, 1, fp);
  80.  
  81.                 fread(&numchars, 1, 1, fp);
  82.                 if (numchars > 32) numchars = 32;
  83.                 fread(title, 32, 1, fp);
  84.                 title[numchars] = 0;
  85.  
  86.                 if (version == 2) {
  87.                         fread(&numchars, 1, 1, fp);
  88.                         if (numchars > 12) numchars = 12;
  89.                         fread(runfile, 12, 1, fp);
  90.                         runfile[numchars] = 0;
  91.                 }
  92.                
  93.                 for (i=0;i<3;i++) {
  94.                         fread(&numchars, 1, 1, fp);
  95.                         if (numchars > 70) numchars = 70;
  96.                         fread(description[i], 70, 1, fp);
  97.                         description[i][numchars] = 0;
  98.                 }
  99.  
  100.                 filenames = (struct file *)malloc(sizeof(struct file) * numfiles);
  101.                 if (!filenames) {
  102.                         fclose(fp);
  103.                         puts("Error: Failed allocating memory for file index.");
  104.                         return -2;
  105.                 }
  106.  
  107.                 for (i=0;i<numfiles;i++) {
  108.                         fread(&numchars, 1, 1, fp);
  109.                         if (numchars > 12) numchars = 12;
  110.                         fread(filenames[i].name, 12, 1, fp);
  111.                         filenames[i].name[numchars] = 0;
  112.  
  113.                         fread(&filenames[i].length, 4, 1, fp);
  114.  
  115.                         // seek past some stuff I can't seem to fully decipher at the moment
  116.                         fseek(fp, 34+1+69, SEEK_CUR);
  117.                 }
  118.        
  119.                 printf("File:           %s\n"
  120.                        "Package Title:  %s\n"
  121.                        "Description:    %s\n"
  122.                        "                %s\n"
  123.                        "                %s\n"
  124.                        "Run Filename:   %s\n\n"
  125.                        , argv[param], title, description[0], description[1], description[2], runfile);
  126.  
  127.                 if (mode == 1) {
  128.                         j=0;
  129.                         puts("File listing:");
  130.                 }
  131.                
  132.                 for (i=0;i<numfiles;i++) {
  133.                         if (mode == 0) {
  134.                                 ofp = fopen(filenames[i].name, "wb");
  135.                                 if (!ofp) {
  136.                                         printf("Error: Failed creating %s. Unpack operation cancelled.\n", filenames[i].name);
  137.                                         break;
  138.                                 }
  139.                        
  140.                                 printf("Unpacking %s (%d bytes)...", filenames[i].name, filenames[i].length);
  141.  
  142.                                 for (j=filenames[i].length; j>1024; j-=1024) {
  143.                                         fread(buf, 1024, 1, fp);
  144.                                         fwrite(buf, 1024, 1, ofp);
  145.                                 }
  146.                                 if (j) {
  147.                                         fread(buf, j, 1, fp);
  148.                                         fwrite(buf, j, 1, ofp);
  149.                                 }
  150.  
  151.                                 fclose(ofp);
  152.                                 puts("done");
  153.                         } else if (mode == 1) {
  154.                                 printf(" %-12s   %d bytes\n", filenames[i].name, filenames[i].length);
  155.                                 j += filenames[i].length;
  156.                         }
  157.                 }
  158.  
  159.                 if (mode == 1) {
  160.                         puts("");
  161.                         printf(" %d files, %d bytes\n", numfiles, j);
  162.                 }
  163.  
  164.                 fclose(fp);
  165.                 free(filenames);
  166.  
  167.                 param++;
  168.         }
  169.  
  170.         return 0;
  171. }
  172.