1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // libwad: Doom WAD format interface library.
5 // Copyright (C) 2011 by Callum Dickinson.
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License
9 // as published by the Free Software Foundation; either version 2
10 // of the License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 //-----------------------------------------------------------------------------
17 /// \file lump.c
18 /// \brief Lump interface functionality.
19
20 #include "wad_static.h"
21
22 //
23 // Create a lump name from the file name
24 // of a lump. Used for when no name for
25 // a lump was given.
26 //
WAD_LumpNameFromFileName(char * path)27 char *WAD_LumpNameFromFileName(char *path)
28 {
29 wad_int32_t i;
30 char *name, *tempname, *file = WAD_BaseName(path);
31
32 if (!file)
33 return NULL;
34
35 //
36 // Process the filename for a suitable lump name.
37 //
38 // Get rid of any hidden file period.
39 if (file[0] == '.')
40 {
41 if (!(tempname = malloc(sizeof(*file) * strlen(&file[1]))))
42 {
43 free(file);
44 return NULL;
45 }
46 strcpy(tempname, &file[1]);
47 free(file);
48 }
49 else
50 tempname = file;
51
52 // Get rid of any extensions.
53 for (i = 0; tempname[i] != '.' && tempname[i] != '\0'; i++);
54
55 // Then, take the first eight characters of
56 // the resulting filename to get the lump name.
57 if (i > 8)
58 i = 8;
59
60 if (!(name = malloc(sizeof(*name) * (i+1))))
61 {
62 free(tempname);
63 return NULL;
64 }
65
66 strncpy(name, tempname, i);
67 name[i+1] = '\0';
68
69 //
70 // Done processing lump name.
71 //
72 free(tempname);
73 return name;
74 }
75
WAD_LumpInWADByNum(wad_t * wad,wad_uint32_t num)76 lump_t *WAD_LumpInWADByNum(wad_t *wad, wad_uint32_t num)
77 {
78 lump_t *lump;
79
80 if (!wad || !num)
81 return NULL;
82
83 for (lump = wad->lumps; lump; lump = lump->next)
84 if (num == lump->num)
85 return lump;
86
87 return NULL;
88 }
89
WAD_LumpInWADByName(wad_t * wad,const char * name)90 lump_t *WAD_LumpInWADByName(wad_t *wad, const char *name)
91 {
92 lump_t *lump;
93
94 if (!wad || !name)
95 return NULL;
96
97 for (lump = wad->lumps; lump; lump = lump->next)
98 if (!strcmp(name, lump->name))
99 return lump;
100
101 return NULL;
102 }
103
WAD_LumpByName(const char * name)104 lump_t *WAD_LumpByName(const char *name)
105 {
106 wad_uint32_t i;
107 lump_t *lump;
108
109 for (i = 0; i < wad_numwads; i = WAD_WADLoopAdvance(i))
110 if ((lump = WAD_LumpInWADByName(WAD_WADByNum(i), name)))
111 return lump;
112
113 return NULL;
114 }
115
WAD_LumpNum(lump_t * lump)116 inline wad_uint32_t WAD_LumpNum(lump_t *lump)
117 {
118 return lump->num;
119 }
120
WAD_LumpNumInWADByName(wad_t * wad,const char * name)121 inline wad_uint32_t WAD_LumpNumInWADByName(wad_t *wad, const char *name)
122 {
123 return WAD_LumpNum(WAD_LumpInWADByName(wad, name));
124 }
125
WAD_LumpNumByName(const char * name)126 inline wad_uint32_t WAD_LumpNumByName(const char *name)
127 {
128 return WAD_LumpNum(WAD_LumpByName(name));
129 }
130
WAD_LumpSize(lump_t * lump)131 inline size_t WAD_LumpSize(lump_t *lump)
132 {
133 return lump->size;
134 }
135
WAD_LumpSizeInWADByName(wad_t * wad,const char * name)136 inline size_t WAD_LumpSizeInWADByName(wad_t *wad, const char *name)
137 {
138 return WAD_LumpSize(WAD_LumpInWADByName(wad, name));
139 }
140
WAD_LumpSizeByName(const char * name)141 inline size_t WAD_LumpSizeByName(const char *name)
142 {
143 return WAD_LumpSize(WAD_LumpByName(name));
144 }
145
WAD_AddLumpToTree(lump_t * lump,lump_t * destlump)146 static void WAD_AddLumpToTree(lump_t *lump, lump_t *destlump)
147 {
148 lump_t *l;
149
150 if (destlump)
151 {
152 lump->wad = destlump->wad;
153 lump->num = destlump->num;
154 for (l = destlump; l; l = l->next)
155 l->num++;
156 if (destlump->prev)
157 destlump->prev->next = lump;
158 lump->prev = destlump->prev;
159 destlump->prev = lump;
160 lump->next = destlump;
161 }
162 else
163 {
164 for (l = lump->wad->lumps; l; l = l->next)
165 if (!l->next)
166 break;
167 lump->num = lump->wad->header->numlumps;
168 l->next = lump;
169 lump->prev = l;
170 lump->next = NULL;
171 }
172 lump->wad->header->numlumps++;
173 }
174
WAD_AddLump(wad_t * wad,lump_t * destlump,const char * name,const char * filename)175 lump_t *WAD_AddLump(wad_t *wad, lump_t *destlump, const char *name, const char *filename)
176 {
177 // The open lump file.
178 FILE *file = NULL;
179 // Pointer to the lump.
180 lump_t *lump;
181 // Lump structure.
182 wad_uint64_t disksize; // lump->disksize
183 size_t size; // lump->size
184 wad_boolean_t compressed;// lump->compressed
185 void *data; // lump->data
186
187 if (!wad)
188 return NULL;
189
190 if (!name && !filename)
191 return NULL;
192
193 if (filename)
194 {
195 if (!(file = fopen(filename, "rb")))
196 return NULL;
197
198 fseek(file, 0, SEEK_END);
199 disksize = size = (unsigned)ftell(file);
200 compressed = false;
201
202
203 if (!(data = malloc(size)))
204 {
205 fclose(file);
206 return NULL;
207 }
208
209 fseek(file, 0, SEEK_SET);
210 if (fread(data, disksize, 1, file) < 1)
211 return NULL;
212 fclose(file);
213 }
214 else
215 {
216 disksize = size = 0;
217 compressed = false;
218 data = NULL;
219 }
220
221
222 if (!(lump = malloc(sizeof(*lump))))
223 {
224 WAD_FreeMemory(NULL, NULL, NULL, lump, NULL);
225 return NULL;
226 }
227
228 lump->wad = wad;
229 if (!strcpy(lump->name, (name) ? name : WAD_LumpNameFromFileName((char *)filename)))
230 {
231 WAD_FreeMemory(NULL, NULL, NULL, lump, NULL);
232 return NULL;
233 }
234 lump->disksize = disksize;
235 lump->size = size;
236 lump->compressed = compressed;
237
238 lump->data = data;
239
240 WAD_AddLumpToTree(lump, destlump);
241
242 return lump;
243 }
244
WAD_AddLumpInWADByNum(wad_t * wad,wad_uint32_t num,const char * name,const char * filename)245 inline lump_t *WAD_AddLumpInWADByNum(wad_t *wad, wad_uint32_t num, const char *name, const char *filename)
246 {
247 return WAD_AddLump(wad, WAD_LumpInWADByNum(wad, num), name, filename);
248 }
249
WAD_AddLumpInWADByName(wad_t * wad,const char * destname,const char * name,const char * filename)250 inline lump_t *WAD_AddLumpInWADByName(wad_t *wad, const char *destname, const char *name, const char *filename)
251 {
252 return WAD_AddLump(wad, WAD_LumpInWADByName(wad, destname), name, filename);
253 }
254
WAD_AddLumpByName(const char * destname,const char * name,const char * filename)255 inline lump_t *WAD_AddLumpByName(const char *destname, const char *name, const char *filename)
256 {
257 lump_t *l = WAD_LumpByName(destname);
258 return WAD_AddLump(l->wad, l, name, filename);
259 }
260
WAD_CacheLump(lump_t * lump)261 lump_t *WAD_CacheLump(lump_t *lump)
262 {
263 return lump; // TODO: WAD_CacheLump, dynamic lump loading.
264 }
265
WAD_CacheLumpInWADByNum(wad_t * wad,wad_uint32_t num)266 inline lump_t *WAD_CacheLumpInWADByNum(wad_t *wad, wad_uint32_t num)
267 {
268 return WAD_CacheLump(WAD_LumpInWADByNum(wad, num));
269 }
270
WAD_CacheLumpInWADByName(wad_t * wad,const char * name)271 inline lump_t *WAD_CacheLumpInWADByName(wad_t *wad, const char *name)
272 {
273 return WAD_CacheLump(WAD_LumpInWADByName(wad, name));
274 }
275
WAD_CacheLumpByName(const char * name)276 inline lump_t *WAD_CacheLumpByName(const char *name)
277 {
278 return WAD_CacheLump(WAD_LumpByName(name));
279 }
280
WAD_MoveLump(lump_t * lump,lump_t * destlump)281 lump_t *WAD_MoveLump(lump_t *lump, lump_t *destlump)
282 {
283 lump_t *l;
284
285 if (!destlump)
286 return NULL;
287
288 //
289 // Link the previous and next nodes in the WAD tree with each other.
290 //
291 if (lump->next)
292 {
293 lump->next->prev = lump->prev;
294 for (l = lump->next; l; l = l->next)
295 l->num--;
296 }
297 if (lump->prev)
298 lump->prev->next = lump->next;
299 lump->wad->header->numlumps--;
300
301 //
302 WAD_AddLumpToTree(lump, destlump);
303
304 return lump;
305 }
306
WAD_MoveLumpInWADByNum(wad_t * wad,wad_uint32_t num,wad_t * destwad,wad_uint32_t destnum)307 inline lump_t *WAD_MoveLumpInWADByNum(wad_t *wad, wad_uint32_t num, wad_t *destwad, wad_uint32_t destnum)
308 {
309 return WAD_MoveLump(WAD_LumpInWADByNum(wad, num), WAD_LumpInWADByNum(destwad, destnum));
310 }
311
WAD_MoveLumpInWADByName(wad_t * wad,const char * name,wad_t * destwad,const char * destname)312 inline lump_t *WAD_MoveLumpInWADByName(wad_t *wad, const char *name, wad_t *destwad, const char *destname)
313 {
314 return WAD_MoveLump(WAD_LumpInWADByName(wad, name), WAD_LumpInWADByName(destwad, destname));
315 }
316
WAD_MoveLumpByName(const char * name,const char * destname)317 inline lump_t *WAD_MoveLumpByName(const char *name, const char *destname)
318 {
319 return WAD_MoveLump(WAD_LumpByName(name), WAD_LumpByName(destname));
320 }
321
WAD_UncacheLump(lump_t * lump)322 void WAD_UncacheLump(lump_t *lump)
323 {
324 (void)lump; // TODO: WAD_UncacheLump, dynamic lump loading.
325 }
326
WAD_UncacheLumpInWADByNum(wad_t * wad,wad_uint32_t num)327 inline void WAD_UncacheLumpInWADByNum(wad_t *wad, wad_uint32_t num)
328 {
329 WAD_UncacheLump(WAD_LumpInWADByNum(wad, num));
330 }
331
WAD_UncacheLumpInWADByName(wad_t * wad,const char * name)332 inline void WAD_UncacheLumpInWADByName(wad_t *wad, const char *name)
333 {
334 WAD_UncacheLump(WAD_LumpInWADByName(wad, name));
335 }
336
WAD_UncacheLumpByName(const char * name)337 inline void WAD_UncacheLumpByName(const char *name)
338 {
339 WAD_UncacheLump(WAD_LumpByName(name));
340 }
341
WAD_RemoveLump(lump_t * lump)342 void WAD_RemoveLump(lump_t *lump)
343 {
344 lump_t *l;
345
346 if (!lump)
347 return;
348
349 //
350 // Link the previous and next nodes in the WAD tree with each other.
351 //
352 lump->next->prev = lump->prev;
353 lump->prev->next = lump->next;
354
355 //
356 // Modify the lump numbers for all the subsequent lumps,
357 // and the total lumps in the WAD.
358 //
359 lump->wad->header->numlumps--;
360
361 if (lump->num == 0)
362 lump->wad->lumps = lump->next;
363
364 for (l = lump->next; l; l = l->next)
365 l->num--;
366
367 //
368 // While, at the same time, blanking the references
369 // to these nodes so they don't get removed.
370 //
371 lump->next = NULL;
372
373 //
374 // Free this lump's memory.
375 //
376 WAD_FreeMemory(NULL, NULL, NULL, lump, NULL);
377 }
378
WAD_RemoveLumpInWADByNum(wad_t * wad,wad_uint32_t num)379 inline void WAD_RemoveLumpInWADByNum(wad_t *wad, wad_uint32_t num)
380 {
381 WAD_RemoveLump(WAD_LumpInWADByNum(wad, num));
382 }
383
WAD_RemoveLumpInWADByName(wad_t * wad,const char * name)384 inline void WAD_RemoveLumpInWADByName(wad_t *wad, const char *name)
385 {
386 WAD_RemoveLump(WAD_LumpInWADByName(wad, name));
387 }
388
WAD_RemoveLumpByName(const char * name)389 inline void WAD_RemoveLumpByName(const char *name)
390 {
391 WAD_RemoveLump(WAD_LumpByName(name));
392 }
393