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