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