]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - plugins/vfswad/unwad.cpp
Merge pull request #21 from merlin1991/Q3-gamepack-fix
[xonotic/netradiant.git] / plugins / vfswad / unwad.cpp
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4
5 #include "unwad.h"
6
7
8 wadFile_t *wadCleanup( wadFile_t *wf ){
9         if ( wf ) {
10                 if ( wf->fin ) {
11                         fclose( wf->fin );
12                 }
13                 if ( wf->lpHeader ) {
14                         free( wf->lpHeader );
15                 }
16                 if ( wf->lpLump ) {
17                         free( wf->lpLump );
18                 }
19                 if ( wf->lpMip ) {
20                         free( wf->lpMip );
21                 }
22                 if ( wf->wadfilename ) {
23                         free( wf->wadfilename );
24                 }
25                 free( wf );
26                 wf = NULL;
27         }
28         return wf;
29 }
30
31 int wadGetCurrentFileInfo( wadFile_t *wf, char *szFileName, unsigned long fileNameBufferSize, unsigned long *filesize ){
32         /* returns 0 if error, or 1 for sucess */
33         // if this fails you'll need to re-position the fileposition
34         // before attempting any other calls.  e.g. call wadGoToFirstFile()
35
36         if ( fread( wf->lpLump,sizeof( WAD3_LUMP ),1,wf->fin ) != 1 ) {
37                 return 0;
38         }
39         strncpy( szFileName, wf->lpLump->name, fileNameBufferSize );
40         szFileName[fileNameBufferSize - 1] = 0; // null terminate
41
42         *filesize = wf->lpLump->size;
43
44         return 1;
45 }
46
47 int wadGoToFile( wadFile_t *wf, unsigned long filenum ){
48         if ( !wf ) {
49                 return 0;
50         }
51
52         if ( !wf->fin ) {
53                 return 0;
54         }
55
56         if ( filenum >= wf->lpHeader->numlumps ) {
57                 return 0;
58         }
59
60         if ( fseek( wf->fin,wf->lpHeader->infotableofs + ( filenum * sizeof( WAD3_LUMP ) ),SEEK_SET ) != 0 ) {
61                 return 0;
62         }
63
64         wf->currentfile = filenum;
65
66         return 1;
67 }
68
69 int wadGoToNextFile( wadFile_t *wf ){
70         return( wadGoToFile( wf, wf->currentfile + 1 ) );
71 }
72
73 int wadGoToFirstFile( wadFile_t *wf ){
74         /* returns 0 if error, or 1 for sucess */
75
76         if ( !wf ) {
77                 return 0;
78         }
79
80         if ( !wf->fin ) {
81                 return 0;
82         }
83
84         if ( fseek( wf->fin,wf->lpHeader->infotableofs,SEEK_SET ) != 0 ) {
85                 return 0;
86         }
87
88         wf->currentfile = 0;
89
90         return 1;
91 }
92
93 wadFile_t *wadOpen( const char* path ){
94
95         wadFile_t *wf = NULL;
96
97         if ( !path ) {
98                 return NULL;
99         }
100
101         wf = new wadFile_s;
102         memset( wf, 0, sizeof( *wf ) );
103
104         if ( !wf ) {
105                 return NULL;
106         }
107
108         wf->fin = fopen( path,"rb" );
109         if ( wf->fin == NULL ) {
110                 return wadCleanup( wf );
111         }
112
113         // get the file size
114         if ( fseek( wf->fin,0,SEEK_END ) != 0 ) {
115                 return wadCleanup( wf );
116         }
117
118         wf->FileSize = ftell( wf->fin );
119
120         // Make sure it's at least big enough to manipulate the header
121         if ( wf->FileSize < sizeof( WAD3_HEADER ) ) {
122                 // WAD3 file is malformed.
123                 return wadCleanup( wf );
124         }
125
126         // go back to the start
127         if ( fseek( wf->fin,0,SEEK_SET ) != 0 ) {
128                 return wadCleanup( wf );
129         }
130
131         // allocate buffers
132         wf->lpHeader = (LPWAD3_HEADER) malloc( sizeof( WAD3_HEADER ) );
133         wf->lpLump = (LPWAD3_LUMP) malloc( sizeof( WAD3_LUMP ) );
134         wf->lpMip = (LPWAD3_MIP) malloc( sizeof( WAD3_MIP ) );
135
136         if ( !( wf->lpHeader ) || !( wf->lpLump ) || !( wf->lpMip ) ) {
137                 return wadCleanup( wf );
138         }
139
140         // read the header.
141         if ( fread( wf->lpHeader,sizeof( WAD3_HEADER ),1,wf->fin ) != 1 ) {
142                 return wadCleanup( wf );
143         }
144
145         if ( wf->lpHeader->identification != WAD2_ID && wf->lpHeader->identification != WAD3_ID ) {
146                 // Invalid WAD3 header id.
147                 return wadCleanup( wf );
148         }
149
150         // Make sure our table is really there
151         if ( ( ( wf->lpHeader->numlumps * sizeof( WAD3_LUMP ) ) + wf->lpHeader->infotableofs ) > wf->FileSize ) {
152                 // WAD3 file is malformed.
153                 return wadCleanup( wf );
154         }
155
156         // Store the name of the wadfile
157         if ( !( wf->wadfilename = strdup( path ) ) ) {
158                 return wadCleanup( wf );
159         }
160
161         return wf;
162 }
163
164 int wadOpenCurrentFileByNum( wadFile_t *wf, unsigned long filenumber ){
165         /* returns 0 if error, or 1 for sucess */
166         return( wadGoToFile( wf, filenumber ) );
167 }
168
169 void wadCloseCurrentFile( wadFile_t *wf ){
170         // nothing to do really...
171 }
172
173 unsigned long wadReadCurrentFile( wadFile_t *wf, char *bufferptr, unsigned long size ){
174         // returns 0 if error, or the amount of data read into the buffer
175         if ( fread( wf->lpLump,sizeof( WAD3_LUMP ),1,wf->fin ) != 1 ) {
176                 return 0;
177         }
178
179         // dunno how to handle any other image types but this (yet)
180         if ( wf->lpLump->type != WAD2_TYPE_MIP && wf->lpLump->type != WAD3_TYPE_MIP ) {
181                 return 0;
182         }
183
184         // go to first mip
185         if ( fseek( wf->fin, wf->lpLump->filepos, SEEK_SET ) != 0 ) {
186                 return 0;
187         }
188
189         if ( fread( bufferptr,size,1,wf->fin ) == 1 ) {
190                 return ( size );
191         }
192         else{
193                 return 0;
194         }
195 }
196
197 /*
198
199    .. or we could do it the long way, and process the file as we go..
200
201
202  */
203 /*
204    unsigned long wadReadCurrentFile (wadFile_t *wf , char *bufferptr, unsigned long size)
205    {
206    // returns 0 if error, or the amount of data read into the buffer
207    unsigned long bufferpos;
208    unsigned long mipdatasize;
209    WORD palettesize;
210
211    if (fread(wf->lpLump,sizeof(WAD3_LUMP),1,wf->fin)!=1)
212         return 0;
213
214    if (wf->lpLump->type == WAD3_TYPE_MIP) // can we handle it ?
215    {
216
217     // bounds check.
218     if (wf->lpLump->filepos >= wf->FileSize)
219       return 0; // malformed wad3
220
221     // go to first mip
222     if (fseek(wf->fin, wf->lpLump->filepos, SEEK_SET) != 0)
223         return 0;
224
225     // and read it
226     if (fread(wf->lpMip,sizeof(WAD3_MIP),1,wf->fin)!=1)
227       return 0;
228
229     // store in buffer.
230     memcpy(bufferptr, wf->lpMip, sizeof(WAD3_MIP));
231     bufferpos = sizeof(WAD3_MIP);
232
233     // now read the MIP data.
234     // mip data
235     if (fseek(wf->fin, wf->lpLump->filepos + wf->lpMip->offsets[0], SEEK_SET) != 0)
236         return 0;
237
238     mipdatasize = GET_MIP_DATA_SIZE(wf->lpMip->width,wf->lpMip->height);
239
240     if (fread(bufferptr+bufferpos, mipdatasize, 1, wf->fin)!=1)
241       return 0;
242
243     bufferpos += mipdatasize;
244
245     // ok, that's the mip data itself, now grab the palette size.
246     if (fread(bufferptr+bufferpos,sizeof(WORD),1,wf->fin)!=1)
247       return 0;
248
249     palettesize = *(WORD *)(bufferptr+bufferpos);
250
251     bufferpos += sizeof(WORD);
252
253     // grab the palette itself
254     if (fread(bufferptr+bufferpos,palettesize*3,1,wf->fin)!=1)
255       return 0;
256
257     bufferpos += palettesize*3;
258
259     // and finally the one-word padding.
260     if (fread(bufferptr+bufferpos,sizeof(WORD),1,wf->fin)!=1)
261       return 0;
262
263     bufferpos += sizeof(WORD);
264
265     return(bufferpos); // return the amount of bytes read.
266    }
267    return 0;
268    }
269  */