renamed and altered SZ_HexDumpToConsole to be Com_HexDumpToConsole which takes a...
[divverent/darkplaces.git] / wad.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the 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 // wad.c
21
22 #include "quakedef.h"
23
24 static int                      wad_numlumps;
25 static lumpinfo_t       *wad_lumps;
26 static qbyte                    *wad_base = NULL;
27 static mempool_t        *wad_mempool = NULL;
28
29 void SwapPic (qpic_t *pic);
30
31 /*
32 ==================
33 W_CleanupName
34
35 Lowercases name and pads with spaces and a terminating 0 to the length of
36 lumpinfo_t->name.
37 Used so lumpname lookups can proceed rapidly by comparing 4 chars at a time
38 Space padding is so names can be printed nicely in tables.
39 Can safely be performed in place.
40 ==================
41 */
42 static void W_CleanupName (char *in, char *out)
43 {
44         int             i;
45         int             c;
46
47         for (i=0 ; i<16 ; i++ )
48         {
49                 c = in[i];
50                 if (!c)
51                         break;
52
53                 if (c >= 'A' && c <= 'Z')
54                         c += ('a' - 'A');
55                 out[i] = c;
56         }
57
58         for ( ; i< 16 ; i++ )
59                 out[i] = 0;
60 }
61
62
63
64 /*
65 ====================
66 W_LoadWadFile
67 ====================
68 */
69 void W_LoadWadFile (char *filename)
70 {
71         lumpinfo_t              *lump_p;
72         wadinfo_t               *header;
73         int                             i;
74         int                             infotableofs;
75         void                    *temp;
76
77         temp = COM_LoadFile (filename, false);
78         if (!temp)
79                 Sys_Error ("W_LoadWadFile: couldn't load %s", filename);
80
81         if (wad_mempool)
82                 Mem_FreePool(&wad_mempool);
83         wad_mempool = Mem_AllocPool(filename);
84         wad_base = Mem_Alloc(wad_mempool, loadsize);
85
86         memcpy(wad_base, temp, loadsize);
87         Mem_Free(temp);
88
89         header = (wadinfo_t *)wad_base;
90
91         if (memcmp(header->identification, "WAD2", 4))
92                 Sys_Error ("Wad file %s doesn't have WAD2 id\n",filename);
93
94         wad_numlumps = LittleLong(header->numlumps);
95         infotableofs = LittleLong(header->infotableofs);
96         wad_lumps = (lumpinfo_t *)(wad_base + infotableofs);
97
98         for (i=0, lump_p = wad_lumps ; i<wad_numlumps ; i++,lump_p++)
99         {
100                 lump_p->filepos = LittleLong(lump_p->filepos);
101                 lump_p->size = LittleLong(lump_p->size);
102                 W_CleanupName (lump_p->name, lump_p->name);
103                 if (lump_p->type == TYP_QPIC)
104                         SwapPic ( (qpic_t *)(wad_base + lump_p->filepos));
105         }
106 }
107
108 void *W_GetLumpName (char *name)
109 {
110         int             i;
111         lumpinfo_t      *lump;
112         char    clean[16];
113
114         W_CleanupName (name, clean);
115
116         for (lump = wad_lumps, i = 0;i < wad_numlumps;i++, lump++)
117                 if (!strcmp(clean, lump->name))
118                         return (void *)(wad_base + lump->filepos);
119
120         return NULL;
121 }
122
123 /*
124 =============================================================================
125
126 automatic byte swapping
127
128 =============================================================================
129 */
130
131 void SwapPic (qpic_t *pic)
132 {
133         pic->width = LittleLong(pic->width);
134         pic->height = LittleLong(pic->height);
135 }
136
137 // LordHavoc: added alternate WAD2/WAD3 system for HalfLife texture wads
138 #define TEXWAD_MAXIMAGES 16384
139 typedef struct
140 {
141         char name[16];
142         QFile *file;
143         int position;
144         int size;
145 } texwadlump_t;
146
147 static texwadlump_t texwadlump[TEXWAD_MAXIMAGES];
148
149 /*
150 ====================
151 W_LoadTextureWadFile
152 ====================
153 */
154 void W_LoadTextureWadFile (char *filename, int complain)
155 {
156         lumpinfo_t              *lumps, *lump_p;
157         wadinfo_t               header;
158         int                             i, j;
159         int                             infotableofs;
160         QFile                   *file;
161         int                             numlumps;
162
163         COM_FOpenFile (filename, &file, false, false);
164         if (!file)
165         {
166                 if (complain)
167                         Con_Printf ("W_LoadTextureWadFile: couldn't find %s", filename);
168                 return;
169         }
170
171         if (Qread(file, &header, sizeof(wadinfo_t)) != sizeof(wadinfo_t))
172         {Con_Printf ("W_LoadTextureWadFile: unable to read wad header");return;}
173
174         if(memcmp(header.identification, "WAD3", 4))
175         {Con_Printf ("W_LoadTextureWadFile: Wad file %s doesn't have WAD3 id\n",filename);return;}
176
177         numlumps = LittleLong(header.numlumps);
178         if (numlumps < 1 || numlumps > TEXWAD_MAXIMAGES)
179         {Con_Printf ("W_LoadTextureWadFile: invalid number of lumps (%i)\n", numlumps);return;}
180         infotableofs = LittleLong(header.infotableofs);
181         if (Qseek(file, infotableofs, SEEK_SET))
182         {Con_Printf ("W_LoadTextureWadFile: unable to seek to lump table");return;}
183         if (!(lumps = Mem_Alloc(tempmempool, sizeof(lumpinfo_t)*numlumps)))
184         {Con_Printf ("W_LoadTextureWadFile: unable to allocate temporary memory for lump table");return;}
185
186         if (Qread(file, lumps, sizeof(lumpinfo_t) * numlumps) != (int)sizeof(lumpinfo_t) * numlumps)
187         {Con_Printf ("W_LoadTextureWadFile: unable to read lump table");return;}
188
189         for (i=0, lump_p = lumps ; i<numlumps ; i++,lump_p++)
190         {
191                 W_CleanupName (lump_p->name, lump_p->name);
192                 for (j = 0;j < TEXWAD_MAXIMAGES;j++)
193                 {
194                         if (texwadlump[j].name[0]) // occupied slot, check the name
195                         {
196                                 if (!strcmp(lump_p->name, texwadlump[j].name)) // name match, replace old one
197                                         break;
198                         }
199                         else // empty slot
200                                 break;
201                 }
202                 if (j >= TEXWAD_MAXIMAGES)
203                         break; // abort loading
204                 W_CleanupName (lump_p->name, texwadlump[j].name);
205                 texwadlump[j].file = file;
206                 texwadlump[j].position = LittleLong(lump_p->filepos);
207                 texwadlump[j].size = LittleLong(lump_p->disksize);
208         }
209         Mem_Free(lumps);
210         // leaves the file open
211 }
212
213
214 qbyte *W_ConvertWAD3Texture(miptex_t *tex)
215 {
216         qbyte *in, *data, *out, *pal;
217         int d, p;
218
219         in = (qbyte *)((int) tex + tex->offsets[0]);
220         data = out = Mem_Alloc(tempmempool, tex->width * tex->height * 4);
221         if (!data)
222                 return NULL;
223         image_width = tex->width;
224         image_height = tex->height;
225         pal = in + (((image_width * image_height) * 85) >> 6);
226         pal += 2;
227         for (d = 0;d < image_width * image_height;d++)
228         {
229                 p = *in++;
230                 if (tex->name[0] == '{' && p == 255)
231                         out[0] = out[1] = out[2] = out[3] = 0;
232                 else
233                 {
234                         p *= 3;
235                         out[0] = pal[p];
236                         out[1] = pal[p+1];
237                         out[2] = pal[p+2];
238                         out[3] = 255;
239                 }
240                 out += 4;
241         }
242         return data;
243 }
244
245 qbyte *W_GetTexture(char *name)
246 {
247         char texname[17];
248         int i, j;
249         QFile *file;
250         miptex_t *tex;
251         qbyte *data;
252
253         texname[16] = 0;
254         W_CleanupName (name, texname);
255         for (i = 0;i < TEXWAD_MAXIMAGES;i++)
256         {
257                 if (texwadlump[i].name[0])
258                 {
259                         if (!strcmp(texname, texwadlump[i].name)) // found it
260                         {
261                                 file = texwadlump[i].file;
262                                 if (Qseek(file, texwadlump[i].position, SEEK_SET))
263                                 {Con_Printf("W_GetTexture: corrupt WAD3 file");return NULL;}
264
265                                 tex = Mem_Alloc(tempmempool, texwadlump[i].size);
266                                 if (!tex)
267                                         return NULL;
268                                 if (Qread(file, tex, texwadlump[i].size) < texwadlump[i].size)
269                                 {Con_Printf("W_GetTexture: corrupt WAD3 file");return NULL;}
270
271                                 tex->width = LittleLong(tex->width);
272                                 tex->height = LittleLong(tex->height);
273                                 for (j = 0;j < MIPLEVELS;j++)
274                                         tex->offsets[j] = LittleLong(tex->offsets[j]);
275                                 data = W_ConvertWAD3Texture(tex);
276                                 Mem_Free(tex);
277                                 return data;
278                         }
279                 }
280                 else
281                         break;
282         }
283         image_width = image_height = 0;
284         return NULL;
285 }
286