1 #include "cmdlib.h"
2 #include "filelib.h"
3 #include "messages.h"
4 #include "hlassert.h"
5 #include "log.h"
6 #include "mathlib.h"
7 #include "bspfile.h"
8 #include "scriplib.h"
9 #include "blockmem.h"
10
11 //=============================================================================
12
13 int g_max_map_miptex = DEFAULT_MAX_MAP_MIPTEX;
14 int g_max_map_lightdata = DEFAULT_MAX_MAP_LIGHTDATA;
15
16 int g_nummodels;
17 dmodel_t g_dmodels[MAX_MAP_MODELS];
18 int g_dmodels_checksum;
19
20 int g_visdatasize;
21 byte g_dvisdata[MAX_MAP_VISIBILITY];
22 int g_dvisdata_checksum;
23
24 int g_lightdatasize;
25 byte* g_dlightdata;
26 int g_dlightdata_checksum;
27
28 int g_texdatasize;
29 byte* g_dtexdata; // (dmiptexlump_t)
30 int g_dtexdata_checksum;
31
32 int g_entdatasize;
33 char g_dentdata[MAX_MAP_ENTSTRING];
34 int g_dentdata_checksum;
35
36 int g_numleafs;
37 dleaf_t g_dleafs[MAX_MAP_LEAFS];
38 int g_dleafs_checksum;
39
40 int g_numplanes;
41 dplane_t g_dplanes[MAX_INTERNAL_MAP_PLANES];
42 int g_dplanes_checksum;
43
44 int g_numvertexes;
45 dvertex_t g_dvertexes[MAX_MAP_VERTS];
46 int g_dvertexes_checksum;
47
48 int g_numnodes;
49 dnode_t g_dnodes[MAX_MAP_NODES];
50 int g_dnodes_checksum;
51
52 int g_numtexinfo;
53 texinfo_t g_texinfo[MAX_MAP_TEXINFO];
54 int g_texinfo_checksum;
55
56 int g_numfaces;
57 dface_t g_dfaces[MAX_MAP_FACES];
58 int g_dfaces_checksum;
59
60 int g_numclipnodes;
61 dclipnode_t g_dclipnodes[MAX_MAP_CLIPNODES];
62 int g_dclipnodes_checksum;
63
64 int g_numedges;
65 dedge_t g_dedges[MAX_MAP_EDGES];
66 int g_dedges_checksum;
67
68 int g_nummarksurfaces;
69 unsigned short g_dmarksurfaces[MAX_MAP_MARKSURFACES];
70 int g_dmarksurfaces_checksum;
71
72 int g_numsurfedges;
73 int g_dsurfedges[MAX_MAP_SURFEDGES];
74 int g_dsurfedges_checksum;
75
76 int g_numentities;
77 entity_t g_entities[MAX_MAP_ENTITIES];
78
79 /*
80 * ===============
81 * FastChecksum
82 * ===============
83 */
84
FastChecksum(const void * const buffer,int bytes)85 static int FastChecksum(const void* const buffer, int bytes)
86 {
87 int checksum = 0;
88 char* buf = (char*)buffer;
89
90 while (bytes--)
91 {
92 checksum = rotl(checksum, 4) ^ (*buf);
93 buf++;
94 }
95
96 return checksum;
97 }
98
99 /*
100 * ===============
101 * CompressVis
102 * ===============
103 */
CompressVis(const byte * const src,const unsigned int src_length,byte * dest,unsigned int dest_length)104 int CompressVis(const byte* const src, const unsigned int src_length, byte* dest, unsigned int dest_length)
105 {
106 unsigned int j;
107 byte* dest_p = dest;
108 unsigned int current_length = 0;
109
110 for (j = 0; j < src_length; j++)
111 {
112 current_length++;
113 hlassume(current_length <= dest_length, assume_COMPRESSVIS_OVERFLOW);
114
115 *dest_p = src[j];
116 dest_p++;
117
118 if (src[j])
119 {
120 continue;
121 }
122
123 unsigned char rep = 1;
124
125 for (j++; j < src_length; j++)
126 {
127 if (src[j] || rep == 255)
128 {
129 break;
130 }
131 else
132 {
133 rep++;
134 }
135 }
136 current_length++;
137 hlassume(current_length <= dest_length, assume_COMPRESSVIS_OVERFLOW);
138
139 *dest_p = rep;
140 dest_p++;
141 j--;
142 }
143
144 return dest_p - dest;
145 }
146
147 // =====================================================================================
148 // DecompressVis
149 //
150 // =====================================================================================
DecompressVis(const byte * src,byte * const dest,const unsigned int dest_length)151 void DecompressVis(const byte* src, byte* const dest, const unsigned int dest_length)
152 {
153 unsigned int current_length = 0;
154 int c;
155 byte* out;
156 int row;
157
158 row = (g_numleafs + 7) >> 3;
159 out = dest;
160
161 do
162 {
163 if (*src)
164 {
165 current_length++;
166 hlassume(current_length <= dest_length, assume_DECOMPRESSVIS_OVERFLOW);
167
168 *out = *src;
169 out++;
170 src++;
171 continue;
172 }
173
174 c = src[1];
175 src += 2;
176 while (c)
177 {
178 current_length++;
179 hlassume(current_length <= dest_length, assume_DECOMPRESSVIS_OVERFLOW);
180
181 *out = 0;
182 out++;
183 c--;
184
185 if (out - dest >= row)
186 {
187 return;
188 }
189 }
190 }
191 while (out - dest < row);
192 }
193
194 //
195 // =====================================================================================
196 //
197
198 // =====================================================================================
199 // SwapBSPFile
200 // byte swaps all data in a bsp file
201 // =====================================================================================
SwapBSPFile(const bool todisk)202 static void SwapBSPFile(const bool todisk)
203 {
204 int i, j, c;
205 dmodel_t* d;
206 dmiptexlump_t* mtl;
207
208 // models
209 for (i = 0; i < g_nummodels; i++)
210 {
211 d = &g_dmodels[i];
212
213 for (j = 0; j < MAX_MAP_HULLS; j++)
214 {
215 d->headnode[j] = LittleLong(d->headnode[j]);
216 }
217
218 d->visleafs = LittleLong(d->visleafs);
219 d->firstface = LittleLong(d->firstface);
220 d->numfaces = LittleLong(d->numfaces);
221
222 for (j = 0; j < 3; j++)
223 {
224 d->mins[j] = LittleFloat(d->mins[j]);
225 d->maxs[j] = LittleFloat(d->maxs[j]);
226 d->origin[j] = LittleFloat(d->origin[j]);
227 }
228 }
229
230 //
231 // vertexes
232 //
233 for (i = 0; i < g_numvertexes; i++)
234 {
235 for (j = 0; j < 3; j++)
236 {
237 g_dvertexes[i].point[j] = LittleFloat(g_dvertexes[i].point[j]);
238 }
239 }
240
241 //
242 // planes
243 //
244 for (i = 0; i < g_numplanes; i++)
245 {
246 for (j = 0; j < 3; j++)
247 {
248 g_dplanes[i].normal[j] = LittleFloat(g_dplanes[i].normal[j]);
249 }
250 g_dplanes[i].dist = LittleFloat(g_dplanes[i].dist);
251 g_dplanes[i].type = (planetypes)LittleLong(g_dplanes[i].type);
252 }
253
254 //
255 // texinfos
256 //
257 for (i = 0; i < g_numtexinfo; i++)
258 {
259 for (j = 0; j < 8; j++)
260 {
261 g_texinfo[i].vecs[0][j] = LittleFloat(g_texinfo[i].vecs[0][j]);
262 }
263 g_texinfo[i].miptex = LittleLong(g_texinfo[i].miptex);
264 g_texinfo[i].flags = LittleLong(g_texinfo[i].flags);
265 }
266
267 //
268 // faces
269 //
270 for (i = 0; i < g_numfaces; i++)
271 {
272 g_dfaces[i].texinfo = LittleShort(g_dfaces[i].texinfo);
273 g_dfaces[i].planenum = LittleShort(g_dfaces[i].planenum);
274 g_dfaces[i].side = LittleShort(g_dfaces[i].side);
275 g_dfaces[i].lightofs = LittleLong(g_dfaces[i].lightofs);
276 g_dfaces[i].firstedge = LittleLong(g_dfaces[i].firstedge);
277 g_dfaces[i].numedges = LittleShort(g_dfaces[i].numedges);
278 }
279
280 //
281 // nodes
282 //
283 for (i = 0; i < g_numnodes; i++)
284 {
285 g_dnodes[i].planenum = LittleLong(g_dnodes[i].planenum);
286 for (j = 0; j < 3; j++)
287 {
288 g_dnodes[i].mins[j] = LittleShort(g_dnodes[i].mins[j]);
289 g_dnodes[i].maxs[j] = LittleShort(g_dnodes[i].maxs[j]);
290 }
291 g_dnodes[i].children[0] = LittleShort(g_dnodes[i].children[0]);
292 g_dnodes[i].children[1] = LittleShort(g_dnodes[i].children[1]);
293 g_dnodes[i].firstface = LittleShort(g_dnodes[i].firstface);
294 g_dnodes[i].numfaces = LittleShort(g_dnodes[i].numfaces);
295 }
296
297 //
298 // leafs
299 //
300 for (i = 0; i < g_numleafs; i++)
301 {
302 g_dleafs[i].contents = LittleLong(g_dleafs[i].contents);
303 for (j = 0; j < 3; j++)
304 {
305 g_dleafs[i].mins[j] = LittleShort(g_dleafs[i].mins[j]);
306 g_dleafs[i].maxs[j] = LittleShort(g_dleafs[i].maxs[j]);
307 }
308
309 g_dleafs[i].firstmarksurface = LittleShort(g_dleafs[i].firstmarksurface);
310 g_dleafs[i].nummarksurfaces = LittleShort(g_dleafs[i].nummarksurfaces);
311 g_dleafs[i].visofs = LittleLong(g_dleafs[i].visofs);
312 }
313
314 //
315 // clipnodes
316 //
317 for (i = 0; i < g_numclipnodes; i++)
318 {
319 g_dclipnodes[i].planenum = LittleLong(g_dclipnodes[i].planenum);
320 g_dclipnodes[i].children[0] = LittleShort(g_dclipnodes[i].children[0]);
321 g_dclipnodes[i].children[1] = LittleShort(g_dclipnodes[i].children[1]);
322 }
323
324 //
325 // miptex
326 //
327 if (g_texdatasize)
328 {
329 mtl = (dmiptexlump_t*)g_dtexdata;
330 if (todisk)
331 {
332 c = mtl->nummiptex;
333 }
334 else
335 {
336 c = LittleLong(mtl->nummiptex);
337 }
338 mtl->nummiptex = LittleLong(mtl->nummiptex);
339 for (i = 0; i < c; i++)
340 {
341 mtl->dataofs[i] = LittleLong(mtl->dataofs[i]);
342 }
343 }
344
345 //
346 // marksurfaces
347 //
348 for (i = 0; i < g_nummarksurfaces; i++)
349 {
350 g_dmarksurfaces[i] = LittleShort(g_dmarksurfaces[i]);
351 }
352
353 //
354 // surfedges
355 //
356 for (i = 0; i < g_numsurfedges; i++)
357 {
358 g_dsurfedges[i] = LittleLong(g_dsurfedges[i]);
359 }
360
361 //
362 // edges
363 //
364 for (i = 0; i < g_numedges; i++)
365 {
366 g_dedges[i].v[0] = LittleShort(g_dedges[i].v[0]);
367 g_dedges[i].v[1] = LittleShort(g_dedges[i].v[1]);
368 }
369 }
370
371 // =====================================================================================
372 // CopyLump
373 // balh
374 // =====================================================================================
CopyLump(int lump,void * dest,int size,const dheader_t * const header)375 static int CopyLump(int lump, void* dest, int size, const dheader_t* const header)
376 {
377 int length, ofs;
378
379 length = header->lumps[lump].filelen;
380 ofs = header->lumps[lump].fileofs;
381
382 if (length % size)
383 {
384 Error("LoadBSPFile: odd lump size");
385 }
386
387 //special handling for tex and lightdata to keep things from exploding - KGP
388 if(lump == LUMP_TEXTURES && dest == (void*)g_dtexdata)
389 { hlassume(g_max_map_miptex > length,assume_MAX_MAP_MIPTEX); }
390 else if(lump == LUMP_LIGHTING && dest == (void*)g_dlightdata)
391 { hlassume(g_max_map_lightdata > length,assume_MAX_MAP_LIGHTING); }
392
393 memcpy(dest, (byte*) header + ofs, length);
394
395 return length / size;
396 }
397
398
399 // =====================================================================================
400 // LoadBSPFile
401 // balh
402 // =====================================================================================
LoadBSPFile(const char * const filename)403 void LoadBSPFile(const char* const filename)
404 {
405 dheader_t* header;
406 LoadFile(filename, (char**)&header);
407 LoadBSPImage(header);
408 }
409
410 // =====================================================================================
411 // LoadBSPImage
412 // balh
413 // =====================================================================================
LoadBSPImage(dheader_t * const header)414 void LoadBSPImage(dheader_t* const header)
415 {
416 unsigned int i;
417
418 // swap the header
419 for (i = 0; i < sizeof(dheader_t) / 4; i++)
420 {
421 ((int*)header)[i] = LittleLong(((int*)header)[i]);
422 }
423
424 if (header->version != BSPVERSION)
425 {
426 Error("BSP is version %i, not %i", header->version, BSPVERSION);
427 }
428
429 g_nummodels = CopyLump(LUMP_MODELS, g_dmodels, sizeof(dmodel_t), header);
430 g_numvertexes = CopyLump(LUMP_VERTEXES, g_dvertexes, sizeof(dvertex_t), header);
431 g_numplanes = CopyLump(LUMP_PLANES, g_dplanes, sizeof(dplane_t), header);
432 g_numleafs = CopyLump(LUMP_LEAFS, g_dleafs, sizeof(dleaf_t), header);
433 g_numnodes = CopyLump(LUMP_NODES, g_dnodes, sizeof(dnode_t), header);
434 g_numtexinfo = CopyLump(LUMP_TEXINFO, g_texinfo, sizeof(texinfo_t), header);
435 g_numclipnodes = CopyLump(LUMP_CLIPNODES, g_dclipnodes, sizeof(dclipnode_t), header);
436 g_numfaces = CopyLump(LUMP_FACES, g_dfaces, sizeof(dface_t), header);
437 g_nummarksurfaces = CopyLump(LUMP_MARKSURFACES, g_dmarksurfaces, sizeof(g_dmarksurfaces[0]), header);
438 g_numsurfedges = CopyLump(LUMP_SURFEDGES, g_dsurfedges, sizeof(g_dsurfedges[0]), header);
439 g_numedges = CopyLump(LUMP_EDGES, g_dedges, sizeof(dedge_t), header);
440 g_texdatasize = CopyLump(LUMP_TEXTURES, g_dtexdata, 1, header);
441 g_visdatasize = CopyLump(LUMP_VISIBILITY, g_dvisdata, 1, header);
442 g_lightdatasize = CopyLump(LUMP_LIGHTING, g_dlightdata, 1, header);
443 g_entdatasize = CopyLump(LUMP_ENTITIES, g_dentdata, 1, header);
444
445 Free(header); // everything has been copied out
446
447 //
448 // swap everything
449 //
450 SwapBSPFile(false);
451
452 g_dmodels_checksum = FastChecksum(g_dmodels, g_nummodels * sizeof(g_dmodels[0]));
453 g_dvertexes_checksum = FastChecksum(g_dvertexes, g_numvertexes * sizeof(g_dvertexes[0]));
454 g_dplanes_checksum = FastChecksum(g_dplanes, g_numplanes * sizeof(g_dplanes[0]));
455 g_dleafs_checksum = FastChecksum(g_dleafs, g_numleafs * sizeof(g_dleafs[0]));
456 g_dnodes_checksum = FastChecksum(g_dnodes, g_numnodes * sizeof(g_dnodes[0]));
457 g_texinfo_checksum = FastChecksum(g_texinfo, g_numtexinfo * sizeof(g_texinfo[0]));
458 g_dclipnodes_checksum = FastChecksum(g_dclipnodes, g_numclipnodes * sizeof(g_dclipnodes[0]));
459 g_dfaces_checksum = FastChecksum(g_dfaces, g_numfaces * sizeof(g_dfaces[0]));
460 g_dmarksurfaces_checksum = FastChecksum(g_dmarksurfaces, g_nummarksurfaces * sizeof(g_dmarksurfaces[0]));
461 g_dsurfedges_checksum = FastChecksum(g_dsurfedges, g_numsurfedges * sizeof(g_dsurfedges[0]));
462 g_dedges_checksum = FastChecksum(g_dedges, g_numedges * sizeof(g_dedges[0]));
463 g_dtexdata_checksum = FastChecksum(g_dtexdata, g_numedges * sizeof(g_dtexdata[0]));
464 g_dvisdata_checksum = FastChecksum(g_dvisdata, g_visdatasize * sizeof(g_dvisdata[0]));
465 g_dlightdata_checksum = FastChecksum(g_dlightdata, g_lightdatasize * sizeof(g_dlightdata[0]));
466 g_dentdata_checksum = FastChecksum(g_dentdata, g_entdatasize * sizeof(g_dentdata[0]));
467 }
468
469 //
470 // =====================================================================================
471 //
472
473 // =====================================================================================
474 // AddLump
475 // balh
476 // =====================================================================================
AddLump(int lumpnum,void * data,int len,dheader_t * header,FILE * bspfile)477 static void AddLump(int lumpnum, void* data, int len, dheader_t* header, FILE* bspfile)
478 {
479 lump_t* lump =&header->lumps[lumpnum];
480 lump->fileofs = LittleLong(ftell(bspfile));
481 lump->filelen = LittleLong(len);
482 SafeWrite(bspfile, data, (len + 3) & ~3);
483 }
484
485 // =====================================================================================
486 // WriteBSPFile
487 // Swaps the bsp file in place, so it should not be referenced again
488 // =====================================================================================
WriteBSPFile(const char * const filename)489 void WriteBSPFile(const char* const filename)
490 {
491 dheader_t outheader;
492 dheader_t* header;
493 FILE* bspfile;
494
495 header = &outheader;
496 memset(header, 0, sizeof(dheader_t));
497
498 SwapBSPFile(true);
499
500 header->version = LittleLong(BSPVERSION);
501
502 bspfile = SafeOpenWrite(filename);
503 SafeWrite(bspfile, header, sizeof(dheader_t)); // overwritten later
504
505 // LUMP TYPE DATA LENGTH HEADER BSPFILE
506 AddLump(LUMP_PLANES, g_dplanes, g_numplanes * sizeof(dplane_t), header, bspfile);
507 AddLump(LUMP_LEAFS, g_dleafs, g_numleafs * sizeof(dleaf_t), header, bspfile);
508 AddLump(LUMP_VERTEXES, g_dvertexes, g_numvertexes * sizeof(dvertex_t), header, bspfile);
509 AddLump(LUMP_NODES, g_dnodes, g_numnodes * sizeof(dnode_t), header, bspfile);
510 AddLump(LUMP_TEXINFO, g_texinfo, g_numtexinfo * sizeof(texinfo_t), header, bspfile);
511 AddLump(LUMP_FACES, g_dfaces, g_numfaces * sizeof(dface_t), header, bspfile);
512 AddLump(LUMP_CLIPNODES, g_dclipnodes, g_numclipnodes * sizeof(dclipnode_t), header, bspfile);
513
514 AddLump(LUMP_MARKSURFACES, g_dmarksurfaces, g_nummarksurfaces * sizeof(g_dmarksurfaces[0]), header, bspfile);
515 AddLump(LUMP_SURFEDGES, g_dsurfedges, g_numsurfedges * sizeof(g_dsurfedges[0]), header, bspfile);
516 AddLump(LUMP_EDGES, g_dedges, g_numedges * sizeof(dedge_t), header, bspfile);
517 AddLump(LUMP_MODELS, g_dmodels, g_nummodels * sizeof(dmodel_t), header, bspfile);
518
519 AddLump(LUMP_LIGHTING, g_dlightdata, g_lightdatasize, header, bspfile);
520 AddLump(LUMP_VISIBILITY,g_dvisdata, g_visdatasize, header, bspfile);
521 AddLump(LUMP_ENTITIES, g_dentdata, g_entdatasize, header, bspfile);
522 AddLump(LUMP_TEXTURES, g_dtexdata, g_texdatasize, header, bspfile);
523
524 fseek(bspfile, 0, SEEK_SET);
525 SafeWrite(bspfile, header, sizeof(dheader_t));
526
527 fclose(bspfile);
528 }
529
530 //
531 // =====================================================================================
532 //
533
534 #define ENTRIES(a) (sizeof(a)/sizeof(*(a)))
535 #define ENTRYSIZE(a) (sizeof(*(a)))
536
537 // =====================================================================================
538 // ArrayUsage
539 // blah
540 // =====================================================================================
ArrayUsage(const char * const szItem,const int items,const int maxitems,const int itemsize)541 static int ArrayUsage(const char* const szItem, const int items, const int maxitems, const int itemsize)
542 {
543 float percentage = maxitems ? items * 100.0 / maxitems : 0.0;
544
545 Log("%-12s %7i/%-7i %7i/%-7i (%4.1f%%)\n", szItem, items, maxitems, items * itemsize, maxitems * itemsize, percentage);
546
547 return items * itemsize;
548 }
549
550 // =====================================================================================
551 // GlobUsage
552 // pritn out global ussage line in chart
553 // =====================================================================================
GlobUsage(const char * const szItem,const int itemstorage,const int maxstorage)554 static int GlobUsage(const char* const szItem, const int itemstorage, const int maxstorage)
555 {
556 float percentage = maxstorage ? itemstorage * 100.0 / maxstorage : 0.0;
557
558 Log("%-12s [variable] %7i/%-7i (%4.1f%%)\n", szItem, itemstorage, maxstorage, percentage);
559
560 return itemstorage;
561 }
562
563 // =====================================================================================
564 // PrintBSPFileSizes
565 // Dumps info about current file
566 // =====================================================================================
PrintBSPFileSizes()567 void PrintBSPFileSizes()
568 {
569 int numtextures = g_texdatasize ? ((dmiptexlump_t*)g_dtexdata)->nummiptex : 0;
570 int totalmemory = 0;
571
572 Log("\n");
573 Log("Object names Objects/Maxobjs Memory / Maxmem Fullness\n");
574 Log("------------ --------------- --------------- --------\n");
575
576 totalmemory += ArrayUsage("models", g_nummodels, ENTRIES(g_dmodels), ENTRYSIZE(g_dmodels));
577 totalmemory += ArrayUsage("planes", g_numplanes, MAX_MAP_PLANES, ENTRYSIZE(g_dplanes));
578 totalmemory += ArrayUsage("vertexes", g_numvertexes, ENTRIES(g_dvertexes), ENTRYSIZE(g_dvertexes));
579 totalmemory += ArrayUsage("nodes", g_numnodes, ENTRIES(g_dnodes), ENTRYSIZE(g_dnodes));
580 totalmemory += ArrayUsage("texinfos", g_numtexinfo, ENTRIES(g_texinfo), ENTRYSIZE(g_texinfo));
581 totalmemory += ArrayUsage("faces", g_numfaces, ENTRIES(g_dfaces), ENTRYSIZE(g_dfaces));
582 totalmemory += ArrayUsage("clipnodes", g_numclipnodes, ENTRIES(g_dclipnodes), ENTRYSIZE(g_dclipnodes));
583 totalmemory += ArrayUsage("leaves", g_numleafs, ENTRIES(g_dleafs), ENTRYSIZE(g_dleafs));
584 totalmemory += ArrayUsage("marksurfaces", g_nummarksurfaces, ENTRIES(g_dmarksurfaces), ENTRYSIZE(g_dmarksurfaces));
585 totalmemory += ArrayUsage("surfedges", g_numsurfedges, ENTRIES(g_dsurfedges), ENTRYSIZE(g_dsurfedges));
586 totalmemory += ArrayUsage("edges", g_numedges, ENTRIES(g_dedges), ENTRYSIZE(g_dedges));
587
588 totalmemory += GlobUsage("texdata", g_texdatasize, g_max_map_miptex);
589 totalmemory += GlobUsage("lightdata", g_lightdatasize, g_max_map_lightdata);
590 totalmemory += GlobUsage("visdata", g_visdatasize, sizeof(g_dvisdata));
591 totalmemory += GlobUsage("entdata", g_entdatasize, sizeof(g_dentdata));
592
593 Log("%i textures referenced\n", numtextures);
594
595 Log("=== Total BSP file data space used: %d bytes ===\n", totalmemory);
596 }
597
598
599 // =====================================================================================
600 // ParseEpair
601 // entity key/value pairs
602 // =====================================================================================
ParseEpair()603 epair_t* ParseEpair()
604 {
605 epair_t* e;
606
607 e = (epair_t*)Alloc(sizeof(epair_t));
608
609 if (strlen(g_token) >= MAX_KEY - 1)
610 Error("ParseEpair: Key token too long (%i > MAX_KEY)", (int)strlen(g_token));
611
612 e->key = _strdup(g_token);
613 GetToken(false);
614
615 if (strlen(g_token) >= ZHLT3_MAX_VALUE - 1)
616 Error("ParseEpar: Value token too long (%i > ZHLT3_MAX_VALUE)", (int)strlen(g_token));
617
618 e->value = _strdup(g_token);
619
620 return e;
621 }
622
623 /*
624 * ================
625 * ParseEntity
626 * ================
627 */
628
629 #ifdef ZHLT_INFO_COMPILE_PARAMETERS
630 // AJM: each tool should have its own version of GetParamsFromEnt which parseentity calls
631 extern void GetParamsFromEnt(entity_t* mapent);
632 #endif
633
ParseEntity()634 bool ParseEntity()
635 {
636 epair_t* e;
637 entity_t* mapent;
638
639 if (!GetToken(true))
640 {
641 return false;
642 }
643
644 if (strcmp(g_token, "{"))
645 {
646 Error("ParseEntity: { not found");
647 }
648
649 if (g_numentities == MAX_MAP_ENTITIES)
650 {
651 Error("g_numentities == MAX_MAP_ENTITIES");
652 }
653
654 mapent = &g_entities[g_numentities];
655 g_numentities++;
656
657 while (1)
658 {
659 if (!GetToken(true))
660 {
661 Error("ParseEntity: EOF without closing brace");
662 }
663 if (!strcmp(g_token, "}"))
664 {
665 break;
666 }
667 e = ParseEpair();
668 e->next = mapent->epairs;
669 mapent->epairs = e;
670 }
671
672 #ifdef ZHLT_INFO_COMPILE_PARAMETERS // AJM
673 if (!strcmp(ValueForKey(mapent, "classname"), "info_compile_parameters"))
674 {
675 Log("Map entity info_compile_parameters detected, using compile settings\n");
676 GetParamsFromEnt(mapent);
677 }
678 #endif
679
680 return true;
681 }
682
683 // =====================================================================================
684 // ParseEntities
685 // Parses the dentdata string into entities
686 // =====================================================================================
ParseEntities()687 void ParseEntities()
688 {
689 g_numentities = 0;
690 ParseFromMemory(g_dentdata, g_entdatasize);
691
692 while (ParseEntity())
693 {
694 }
695 }
696
697 // =====================================================================================
698 // UnparseEntities
699 // Generates the dentdata string from all the entities
700 // =====================================================================================
UnparseEntities()701 void UnparseEntities()
702 {
703 char* buf;
704 char* end;
705 epair_t* ep;
706 char line[MAXTOKEN];
707 int i;
708
709 buf = g_dentdata;
710 end = buf;
711 *end = 0;
712
713 for (i = 0; i < g_numentities; i++)
714 {
715 ep = g_entities[i].epairs;
716 if (!ep)
717 {
718 continue; // ent got removed
719 }
720
721 strcat(end, "{\n");
722 end += 2;
723
724 for (ep = g_entities[i].epairs; ep; ep = ep->next)
725 {
726 sprintf(line, "\"%s\" \"%s\"\n", ep->key, ep->value);
727 strcat(end, line);
728 end += strlen(line);
729 }
730 strcat(end, "}\n");
731 end += 2;
732
733 if (end > buf + MAX_MAP_ENTSTRING)
734 {
735 Error("Entity text too long");
736 }
737 }
738 g_entdatasize = end - buf + 1;
739 }
740
741 // =====================================================================================
742 // SetKeyValue
743 // makes a keyvalue
744 // =====================================================================================
SetKeyValue(entity_t * ent,const char * const key,const char * const value)745 void SetKeyValue(entity_t* ent, const char* const key, const char* const value)
746 {
747 epair_t* ep;
748
749 for (ep = ent->epairs; ep; ep = ep->next)
750 {
751 if (!strcmp(ep->key, key))
752 {
753 Free(ep->value);
754 ep->value = strdup(value);
755 return;
756 }
757 }
758 ep = (epair_t*)Alloc(sizeof(*ep));
759 ep->next = ent->epairs;
760 ent->epairs = ep;
761 ep->key = strdup(key);
762 ep->value = strdup(value);
763 }
764
765 // =====================================================================================
766 // ValueForKey
767 // returns the value for a passed entity and key
768 // =====================================================================================
ValueForKey(const entity_t * const ent,const char * const key)769 const char* ValueForKey(const entity_t* const ent, const char* const key)
770 {
771 epair_t* ep;
772
773 for (ep = ent->epairs; ep; ep = ep->next)
774 {
775 if (!strcmp(ep->key, key))
776 {
777 return ep->value;
778 }
779 }
780 return "";
781 }
782
783 // =====================================================================================
784 // IntForKey
785 // =====================================================================================
IntForKey(const entity_t * const ent,const char * const key)786 int IntForKey(const entity_t* const ent, const char* const key)
787 {
788 return atoi(ValueForKey(ent, key));
789 }
790
791 // =====================================================================================
792 // FloatForKey
793 // =====================================================================================
FloatForKey(const entity_t * const ent,const char * const key)794 vec_t FloatForKey(const entity_t* const ent, const char* const key)
795 {
796 return atof(ValueForKey(ent, key));
797 }
798
799 // =====================================================================================
800 // GetVectorForKey
801 // returns value for key in vec[0-2]
802 // =====================================================================================
GetVectorForKey(const entity_t * const ent,const char * const key,vec3_t vec)803 void GetVectorForKey(const entity_t* const ent, const char* const key, vec3_t vec)
804 {
805 const char* k;
806 double v1, v2, v3;
807
808 k = ValueForKey(ent, key);
809 // scanf into doubles, then assign, so it is vec_t size independent
810 v1 = v2 = v3 = 0;
811 sscanf(k, "%lf %lf %lf", &v1, &v2, &v3);
812 vec[0] = v1;
813 vec[1] = v2;
814 vec[2] = v3;
815 }
816
817 // =====================================================================================
818 // FindTargetEntity
819 //
820 // =====================================================================================
FindTargetEntity(const char * const target)821 entity_t *FindTargetEntity(const char* const target)
822 {
823 int i;
824 const char* n;
825
826 for (i = 0; i < g_numentities; i++)
827 {
828 n = ValueForKey(&g_entities[i], "targetname");
829 if (!strcmp(n, target))
830 {
831 return &g_entities[i];
832 }
833 }
834
835 return NULL;
836 }
837
838
dtexdata_init()839 void dtexdata_init()
840 {
841 g_dtexdata = (byte*)AllocBlock(g_max_map_miptex);
842 hlassume(g_dtexdata != NULL, assume_NoMemory);
843 g_dlightdata = (byte*)AllocBlock(g_max_map_lightdata);
844 hlassume(g_dlightdata != NULL, assume_NoMemory);
845 }
846
dtexdata_free()847 void CDECL dtexdata_free()
848 {
849 FreeBlock(g_dtexdata);
850 g_dtexdata = NULL;
851 FreeBlock(g_dlightdata);
852 g_dlightdata = NULL;
853 }
854
855 // =====================================================================================
856 // GetTextureByNumber
857 // Touchy function, can fail with a page fault if all the data isnt kosher
858 // (i.e. map was compiled with missing textures)
859 // =====================================================================================
GetTextureByNumber(int texturenumber)860 char* GetTextureByNumber(int texturenumber)
861 {
862 texinfo_t* info;
863 miptex_t* miptex;
864 int ofs;
865
866 info = &g_texinfo[texturenumber];
867 ofs = ((dmiptexlump_t*)g_dtexdata)->dataofs[info->miptex];
868 miptex = (miptex_t*)(&g_dtexdata[ofs]);
869
870 return miptex->name;
871 }
872
873 // =====================================================================================
874 // EntityForModel
875 // returns entity addy for given modelnum
876 // =====================================================================================
EntityForModel(const int modnum)877 entity_t* EntityForModel(const int modnum)
878 {
879 int i;
880 const char* s;
881 char name[16];
882
883 sprintf(name, "*%i", modnum);
884 // search the entities for one using modnum
885 for (i = 0; i < g_numentities; i++)
886 {
887 s = ValueForKey(&g_entities[i], "model");
888 if (!strcmp(s, name))
889 {
890 return &g_entities[i];
891 }
892 }
893
894 return &g_entities[0];
895 }