Subversion Repositories vaca_plus

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 h266 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
}