1 /*
2 Copyright (C) 1997-2001 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 //
21 // cm_q2_main.c
22 // Quake2 BSP map model loading
23 // FIXME TODO:
24 // - A lot of these allocations can be better sized (entity string for example).
25 //
26 
27 #include "cm_q2_local.h"
28 
29 static byte				*cm_q2_mapBuffer;
30 
31 static int				cm_q2_numEntityChars;
32 static char				cm_q2_emptyEntityString[1];
33 static char				*cm_q2_entityString;
34 
35 static int				cm_q2_numTexInfo;
36 static cQ2MapSurface_t	*cm_q2_surfaces;
37 static int				cm_q2_numTexInfoUnique;
38 static cQ2MapSurface_t	**cm_q2_surfacesUnique;
39 
40 int						cm_q2_numNodes;
41 cQ2BspNode_t			*cm_q2_nodes;
42 
43 int						cm_q2_numBrushSides;
44 cQ2BspBrushSide_t		*cm_q2_brushSides;
45 
46 int						cm_q2_numLeafs = 1;									// allow leaf funcs to be called without a map
47 int						cm_q2_emptyLeaf;
48 cQ2BspLeaf_t			*cm_q2_leafs;
49 
50 int						cm_q2_numLeafBrushes;
51 uint16					*cm_q2_leafBrushes;
52 
53 int						cm_q2_numBrushes;
54 cQ2BspBrush_t			*cm_q2_brushes;
55 
56 int						cm_q2_numAreas = 1;
57 cQ2BspArea_t			*cm_q2_areas;
58 
59 cQ2MapSurface_t			cm_q2_nullSurface;
60 
61 int						cm_q2_numPlanes;
62 cBspPlane_t				*cm_q2_planes;
63 
64 int						cm_q2_numVisibility;
65 dQ2BspVis_t				*cm_q2_visData;
66 
67 int						cm_q2_numAreaPortals;
68 dQ2BspAreaPortal_t		*cm_q2_areaPortals;
69 qBool					*cm_q2_portalOpen;
70 
71 int						cm_q2_numClusters = 1;
72 
73 /*
74 =============================================================================
75 
76 	QUAKE2 BSP LOADING
77 
78 =============================================================================
79 */
80 
81 /*
82 =================
83 CM_Q2BSP_LoadSurfaces
84 =================
85 */
CM_Q2BSP_LoadSurfaces(dQ2BspLump_t * l)86 static void CM_Q2BSP_LoadSurfaces (dQ2BspLump_t *l)
87 {
88 	dQ2BspTexInfo_t	*in;
89 	cQ2MapSurface_t	*out;
90 	int				i, j;
91 	int				unique;
92 
93 	// Sanity check lump size
94 	in = (void *)(cm_q2_mapBuffer + l->fileOfs);
95 	if (l->fileLen % sizeof (*in))
96 		Com_Error (ERR_DROP, "CM_Q2BSP_LoadSurfaces: funny lump size");
97 
98 	// Total
99 	cm_q2_numTexInfo = l->fileLen / sizeof (*in);
100 	if (cm_q2_numTexInfo < 1)
101 		Com_Error (ERR_DROP, "CM_Q2BSP_LoadSurfaces: Map with no surfaces");
102 	if (cm_q2_numTexInfo > Q2BSP_MAX_TEXINFO)
103 		Com_Error (ERR_DROP, "CM_Q2BSP_LoadSurfaces: Map has too many surfaces");
104 	cm_q2_surfaces = Mem_PoolAlloc (sizeof(cQ2MapSurface_t) * cm_q2_numTexInfo, com_cmodelSysPool, 0);
105 
106 	// Byte swap
107 	out = cm_q2_surfaces;
108 	for (i=0 ; i<cm_q2_numTexInfo ; i++, in++, out++) {
109 		Q_strncpyz (out->c.name, in->texture, sizeof (out->c.name));
110 		Q_strncpyz (out->rname, in->texture, sizeof (out->rname));
111 		out->c.flags = LittleLong (in->flags);
112 		out->c.value = LittleLong (in->value);
113 	}
114 
115 	// Find the total unique
116 	unique = 0;
117 	for (i=0 ; i<cm_q2_numTexInfo ; i++) {
118 		for (j=i-1 ; j>=0 ; j--) {
119 			if (!Q_stricmp (cm_q2_surfaces[i].rname, cm_q2_surfaces[j].rname))
120 				break;
121 		}
122 		if (j == -1)
123 			unique++;
124 	}
125 
126 	// Shouldn't really happen...
127 	if (!unique)
128 		return;
129 
130 	cm_q2_numTexInfoUnique = unique;
131 	cm_q2_surfacesUnique = Mem_PoolAlloc (sizeof(cQ2MapSurface_t *) * cm_q2_numTexInfoUnique, com_cmodelSysPool, 0);
132 	for (i=0, unique=0 ; i<cm_q2_numTexInfo ; i++) {
133 		for (j=i-1 ; j>=0 ; j--) {
134 			if (!Q_stricmp (cm_q2_surfaces[i].rname, cm_q2_surfaces[j].rname))
135 				break;
136 		}
137 		if (j == -1)
138 			cm_q2_surfacesUnique[unique++] = &cm_q2_surfaces[i];
139 	}
140 }
141 
142 
143 /*
144 =================
145 CM_Q2BSP_LoadLeafs
146 =================
147 */
CM_Q2BSP_LoadLeafs(dQ2BspLump_t * l)148 static void CM_Q2BSP_LoadLeafs (dQ2BspLump_t *l)
149 {
150 	int				i;
151 	cQ2BspLeaf_t	*out;
152 	dQ2BspLeaf_t	*in;
153 
154 	// Sanity check lump size
155 	in = (void *)(cm_q2_mapBuffer + l->fileOfs);
156 	if (l->fileLen % sizeof (*in))
157 		Com_Error (ERR_DROP, "CM_Q2BSP_LoadLeafs: funny lump size");
158 
159 	// Find the size and allocate (with extra for box hull)
160 	cm_q2_numLeafs = l->fileLen / sizeof (*in);
161 	if (cm_q2_numLeafs < 1)
162 		Com_Error (ERR_DROP, "CM_Q2BSP_LoadLeafs: Map with no leafs");
163 	if (cm_q2_numLeafs > Q2BSP_MAX_PLANES)
164 		Com_Error (ERR_DROP, "CM_Q2BSP_LoadLeafs: Map has too many planes");
165 	cm_q2_leafs = Mem_PoolAlloc (sizeof(cQ2BspLeaf_t) * (cm_q2_numLeafs+6), com_cmodelSysPool, 0);
166 
167 	// Byte swap
168 	out = cm_q2_leafs;
169 	cm_q2_numClusters = 0;
170 
171 	for (i=0 ; i<cm_q2_numLeafs ; i++, in++, out++) {
172 		out->contents = LittleLong (in->contents);
173 		out->cluster = LittleShort (in->cluster);
174 		out->area = LittleShort (in->area);
175 		out->firstLeafBrush = LittleShort (in->firstLeafBrush);
176 		out->numLeafBrushes = LittleShort (in->numLeafBrushes);
177 
178 		if (out->cluster >= cm_q2_numClusters)
179 			cm_q2_numClusters = out->cluster + 1;
180 	}
181 
182 	if (cm_q2_leafs[0].contents != CONTENTS_SOLID)
183 		Com_Error (ERR_DROP, "CM_Q2BSP_LoadLeafs: Map leaf 0 is not CONTENTS_SOLID");
184 
185 	cm_q2_emptyLeaf = -1;
186 	for (i=1 ; i<cm_q2_numLeafs ; i++) {
187 		if (!cm_q2_leafs[i].contents) {
188 			cm_q2_emptyLeaf = i;
189 			break;
190 		}
191 	}
192 	if (cm_q2_emptyLeaf == -1)
193 		Com_Error (ERR_DROP, "CM_Q2BSP_LoadLeafs: Map does not have an empty leaf");
194 }
195 
196 
197 /*
198 =================
199 CM_Q2BSP_LoadLeafBrushes
200 =================
201 */
CM_Q2BSP_LoadLeafBrushes(dQ2BspLump_t * l)202 static void CM_Q2BSP_LoadLeafBrushes (dQ2BspLump_t *l)
203 {
204 	int		i;
205 	uint16	*out;
206 	uint16	*in;
207 
208 	// Sanity check lump size
209 	in = (void *)(cm_q2_mapBuffer + l->fileOfs);
210 	if (l->fileLen % sizeof (*in))
211 		Com_Error (ERR_DROP, "CM_Q2BSP_LoadLeafBrushes: funny lump size");
212 
213 	// Find the size and allocate (with extra for box hull)
214 	cm_q2_numLeafBrushes = l->fileLen / sizeof (*in);
215 	if (cm_q2_numLeafBrushes < 1)
216 		Com_Error (ERR_DROP, "CM_Q2BSP_LoadLeafBrushes: Map with no planes");
217 	if (cm_q2_numLeafBrushes > Q2BSP_MAX_LEAFBRUSHES)
218 		Com_Error (ERR_DROP, "CM_Q2BSP_LoadLeafBrushes: Map has too many leafbrushes");
219 	cm_q2_leafBrushes = Mem_PoolAlloc (sizeof(uint16) * (cm_q2_numLeafBrushes+1), com_cmodelSysPool, 0);
220 
221 	// Byte swap
222 	out = cm_q2_leafBrushes;
223 	for (i=0 ; i<cm_q2_numLeafBrushes ; i++, in++, out++)
224 		*out = LittleShort (*in);
225 }
226 
227 
228 /*
229 =================
230 CM_Q2BSP_LoadPlanes
231 =================
232 */
CM_Q2BSP_LoadPlanes(dQ2BspLump_t * l)233 static void CM_Q2BSP_LoadPlanes (dQ2BspLump_t *l)
234 {
235 	int				i, j;
236 	cBspPlane_t		*out;
237 	dQ2BspPlane_t	*in;
238 	int				bits;
239 
240 	// Sanity check lump size
241 	in = (void *)(cm_q2_mapBuffer + l->fileOfs);
242 	if (l->fileLen % sizeof (*in))
243 		Com_Error (ERR_DROP, "CM_Q2BSP_LoadPlanes: funny lump size");
244 
245 	// Find the size and allocate (with extra for box hull)
246 	cm_q2_numPlanes = l->fileLen / sizeof (*in);
247 	if (cm_q2_numPlanes < 1)
248 		Com_Error (ERR_DROP, "CM_Q2BSP_LoadPlanes: Map with no planes");
249 	if (cm_q2_numPlanes > Q2BSP_MAX_PLANES)
250 		Com_Error (ERR_DROP, "CM_Q2BSP_LoadPlanes: Map has too many planes");
251 	cm_q2_planes = Mem_PoolAlloc (sizeof(cBspPlane_t) * (cm_q2_numPlanes+12), com_cmodelSysPool, 0);
252 
253 	// Byte swap
254 	out = cm_q2_planes;
255 	for (i=0 ; i<cm_q2_numPlanes ; i++, in++, out++) {
256 		bits = 0;
257 		for (j=0 ; j<3 ; j++) {
258 			out->normal[j] = LittleFloat (in->normal[j]);
259 			if (out->normal[j] < 0)
260 				bits |= 1<<j;
261 		}
262 
263 		out->dist = LittleFloat (in->dist);
264 		out->type = LittleLong (in->type);
265 		out->signBits = bits;
266 	}
267 }
268 
269 
270 /*
271 =================
272 CM_Q2BSP_LoadBrushes
273 =================
274 */
CM_Q2BSP_LoadBrushes(dQ2BspLump_t * l)275 static void CM_Q2BSP_LoadBrushes (dQ2BspLump_t *l)
276 {
277 	dQ2BspBrush_t	*in;
278 	cQ2BspBrush_t	*out;
279 	int				i;
280 
281 	// Sanity check lump size
282 	in = (void *)(cm_q2_mapBuffer + l->fileOfs);
283 	if (l->fileLen % sizeof (*in))
284 		Com_Error (ERR_DROP, "CM_Q2BSP_LoadBrushes: funny lump size");
285 
286 	// Find the size and allocate (with extra for box hull)
287 	cm_q2_numBrushes = l->fileLen / sizeof (*in);
288 	if (cm_q2_numBrushes > Q2BSP_MAX_BRUSHES)
289 		Com_Error (ERR_DROP, "CM_Q2BSP_LoadBrushes: Map has too many brushes");
290 	cm_q2_brushes = Mem_PoolAlloc (sizeof(cQ2BspBrush_t) * (cm_q2_numBrushes+1), com_cmodelSysPool, 0);
291 
292 	// Byte swap
293 	out = cm_q2_brushes;
294 	for (i=0 ; i<cm_q2_numBrushes ; i++, out++, in++) {
295 		out->firstBrushSide = LittleLong (in->firstSide);
296 		out->numSides = LittleLong (in->numSides);
297 		out->contents = LittleLong (in->contents);
298 	}
299 }
300 
301 
302 /*
303 =================
304 CM_Q2BSP_LoadBrushSides
305 =================
306 */
CM_Q2BSP_LoadBrushSides(dQ2BspLump_t * l)307 static void CM_Q2BSP_LoadBrushSides (dQ2BspLump_t *l)
308 {
309 	int					i, j;
310 	cQ2BspBrushSide_t	*out;
311 	dQ2BspBrushSide_t	*in;
312 	int					num;
313 
314 	// Sanity check lump size
315 	in = (void *)(cm_q2_mapBuffer + l->fileOfs);
316 	if (l->fileLen % sizeof (*in))
317 		Com_Error (ERR_DROP, "CM_Q2BSP_LoadBrushSides: funny lump size");
318 
319 	// Find the size and allocate (with extra for box hull)
320 	cm_q2_numBrushSides = l->fileLen / sizeof (*in);
321 	if (cm_q2_numBrushSides > Q2BSP_MAX_BRUSHSIDES)
322 		Com_Error (ERR_DROP, "CM_Q2BSP_LoadBrushSides: Map has too many planes");
323 	cm_q2_brushSides = Mem_PoolAlloc (sizeof(cQ2BspBrushSide_t) * (cm_q2_numBrushSides+6), com_cmodelSysPool, 0);
324 
325 	// Byte swap
326 	out = cm_q2_brushSides;
327 	for (i=0 ; i<cm_q2_numBrushSides ; i++, in++, out++) {
328 		num = LittleShort (in->planeNum);
329 		out->plane = &cm_q2_planes[num];
330 		j = LittleShort (in->texInfo);
331 		if (j >= cm_q2_numTexInfo)
332 			Com_Error (ERR_DROP, "CM_Q2BSP_LoadBrushSides: Bad brushside texInfo");
333 		out->surface = &cm_q2_surfaces[j];
334 	}
335 }
336 
337 
338 /*
339 =================
340 CM_Q2BSP_LoadSubmodels
341 =================
342 */
CM_Q2BSP_LoadSubmodels(dQ2BspLump_t * l)343 static void CM_Q2BSP_LoadSubmodels (dQ2BspLump_t *l)
344 {
345 	dQ2BspModel_t	*in;
346 	cBspModel_t		*out;
347 	int				i;
348 
349 	// Sanity check lump size
350 	in = (void *)(cm_q2_mapBuffer + l->fileOfs);
351 	if (l->fileLen % sizeof (*in))
352 		Com_Error (ERR_DROP, "CM_Q2BSP_LoadSubmodels: funny lump size");
353 
354 	// Find the size
355 	cm_numCModels = l->fileLen / sizeof (*in);
356 	if (cm_numCModels < 1)
357 		Com_Error (ERR_DROP, "CM_Q2BSP_LoadSubmodels: Map with no models");
358 	if (cm_numCModels > Q2BSP_MAX_MODELS)
359 		Com_Error (ERR_DROP, "CM_Q2BSP_LoadSubmodels: Map has too many models");
360 
361 	// Byte swap
362 	for (i=0 ; i<cm_numCModels ; i++, in++, out++) {
363 		out = &cm_mapCModels[i];
364 
365 		// Spread the mins / maxs by a pixel
366 		out->mins[0] = LittleFloat (in->mins[0]) - 1;
367 		out->mins[1] = LittleFloat (in->mins[1]) - 1;
368 		out->mins[2] = LittleFloat (in->mins[2]) - 1;
369 		out->maxs[0] = LittleFloat (in->maxs[0]) + 1;
370 		out->maxs[1] = LittleFloat (in->maxs[1]) + 1;
371 		out->maxs[2] = LittleFloat (in->maxs[2]) + 1;
372 
373 		// Head node
374 		out->headNode = LittleLong (in->headNode);
375 	}
376 }
377 
378 
379 /*
380 =================
381 CM_Q2BSP_LoadNodes
382 =================
383 */
CM_Q2BSP_LoadNodes(dQ2BspLump_t * l)384 static void CM_Q2BSP_LoadNodes (dQ2BspLump_t *l)
385 {
386 	dQ2BspNode_t	*in;
387 	cQ2BspNode_t	*out;
388 	int				i;
389 
390 	// Sanity check lump size
391 	in = (void *)(cm_q2_mapBuffer + l->fileOfs);
392 	if (l->fileLen % sizeof (*in))
393 		Com_Error (ERR_DROP, "CM_Q2BSP_LoadNodes: funny lump size");
394 
395 	// Find the size and allocate (with extra for box hull)
396 	cm_q2_numNodes = l->fileLen / sizeof (*in);
397 	if (cm_q2_numNodes < 1)
398 		Com_Error (ERR_DROP, "CM_Q2BSP_LoadNodes: Map has no nodes");
399 	if (cm_q2_numNodes > Q2BSP_MAX_NODES)
400 		Com_Error (ERR_DROP, "CM_Q2BSP_LoadNodes: Map has too many nodes");
401 	cm_q2_nodes = Mem_PoolAlloc (sizeof(cQ2BspNode_t) * (cm_q2_numNodes+6), com_cmodelSysPool, 0);
402 
403 	// Byte swap
404 	out = cm_q2_nodes;
405 	for (i=0 ; i<cm_q2_numNodes ; i++, out++, in++) {
406 		out->plane = cm_q2_planes + LittleLong (in->planeNum);
407 		out->children[0] = LittleLong (in->children[0]);
408 		out->children[1] = LittleLong (in->children[1]);
409 	}
410 }
411 
412 
413 /*
414 =================
415 CM_Q2BSP_LoadAreas
416 =================
417 */
CM_Q2BSP_LoadAreas(dQ2BspLump_t * l)418 static void CM_Q2BSP_LoadAreas (dQ2BspLump_t *l)
419 {
420 	int				i;
421 	cQ2BspArea_t	*out;
422 	dQ2BspArea_t	*in;
423 
424 	// Sanity check lump size
425 	in = (void *)(cm_q2_mapBuffer + l->fileOfs);
426 	if (l->fileLen % sizeof (*in))
427 		Com_Error (ERR_DROP, "CM_Q2BSP_LoadAreas: funny lump size");
428 
429 	// Find the size and allocate
430 	cm_q2_numAreas = l->fileLen / sizeof (*in);
431 	if (cm_q2_numAreas > Q2BSP_MAX_AREAS)
432 		Com_Error (ERR_DROP, "CM_Q2BSP_LoadAreas: Map has too many areas");
433 	cm_q2_areas = Mem_PoolAlloc (sizeof(cQ2BspArea_t) * cm_q2_numAreas, com_cmodelSysPool, 0);
434 
435 	// Byte swap
436 	out = cm_q2_areas;
437 	for (i=0 ; i<cm_q2_numAreas ; i++, in++, out++) {
438 		out->numAreaPortals = LittleLong (in->numAreaPortals);
439 		out->firstAreaPortal = LittleLong (in->firstAreaPortal);
440 		out->floodValid = 0;
441 		out->floodNum = 0;
442 	}
443 }
444 
445 
446 /*
447 =================
448 CM_Q2BSP_LoadAreaPortals
449 =================
450 */
CM_Q2BSP_LoadAreaPortals(dQ2BspLump_t * l)451 static void CM_Q2BSP_LoadAreaPortals (dQ2BspLump_t *l)
452 {
453 	int					i;
454 	dQ2BspAreaPortal_t	*out;
455 	dQ2BspAreaPortal_t	*in;
456 
457 	// Sanity check lump size
458 	in = (void *)(cm_q2_mapBuffer + l->fileOfs);
459 	if (l->fileLen % sizeof (*in))
460 		Com_Error (ERR_DROP, "CM_Q2BSP_LoadAreaPortals: funny lump size");
461 
462 	// Find the size and allocate
463 	cm_q2_numAreaPortals = l->fileLen / sizeof (*in);
464 	if (cm_q2_numAreaPortals > Q2BSP_MAX_AREAS)
465 		Com_Error (ERR_DROP, "CM_Q2BSP_LoadAreaPortals: Map has too many areas");
466 	cm_q2_areaPortals = Mem_PoolAlloc (sizeof(dQ2BspAreaPortal_t) * cm_q2_numAreaPortals, com_cmodelSysPool, 0);
467 
468 	// Byte swap
469 	out = cm_q2_areaPortals;
470 	for (i=0 ; i<cm_q2_numAreaPortals ; i++, in++, out++) {
471 		out->portalNum = LittleLong (in->portalNum);
472 		out->otherArea = LittleLong (in->otherArea);
473 	}
474 }
475 
476 
477 /*
478 =================
479 CM_Q2BSP_LoadVisibility
480 =================
481 */
CM_Q2BSP_LoadVisibility(dQ2BspLump_t * l)482 static void CM_Q2BSP_LoadVisibility (dQ2BspLump_t *l)
483 {
484 	int		i;
485 
486 	// Find the size and allocate
487 	cm_q2_numVisibility = l->fileLen;
488 	if (l->fileLen > Q2BSP_MAX_VISIBILITY)
489 		Com_Error (ERR_DROP, "CM_Q2BSP_LoadVisibility: Map has too large visibility lump");
490 
491 	// If there's no visibility, just store the number of clusters
492 	if (!cm_q2_numVisibility) {
493 		cm_q2_visData = Mem_PoolAlloc (sizeof(int), com_cmodelSysPool, 0);
494 		cm_q2_visData->numClusters = 0;
495 		return;
496 	}
497 
498 	// Byte swap
499 	cm_q2_visData = Mem_PoolAlloc (sizeof(int) + (sizeof(byte) * cm_q2_numVisibility), com_cmodelSysPool, 0);
500 	memcpy (cm_q2_visData, cm_q2_mapBuffer + l->fileOfs, l->fileLen);
501 	cm_q2_visData->numClusters = LittleLong (cm_q2_visData->numClusters);
502 	for (i=0 ; i<cm_q2_visData->numClusters ; i++) {
503 		cm_q2_visData->bitOfs[i][0] = LittleLong (cm_q2_visData->bitOfs[i][0]);
504 		cm_q2_visData->bitOfs[i][1] = LittleLong (cm_q2_visData->bitOfs[i][1]);
505 	}
506 }
507 
508 
509 /*
510 =================
511 CM_Q2BSP_LoadEntityString
512 =================
513 */
CM_Q2BSP_LoadEntityString(dQ2BspLump_t * l)514 static void CM_Q2BSP_LoadEntityString (dQ2BspLump_t *l)
515 {
516 	// Find the size and allocate (with extra for NULL termination)
517 	cm_q2_numEntityChars = l->fileLen;
518 	if (l->fileLen > Q2BSP_MAX_ENTSTRING)
519 		Com_Error (ERR_DROP, "CM_Q2BSP_LoadEntityString: Map has too large entity lump");
520 	cm_q2_entityString = Mem_PoolAlloc (sizeof(char) * (cm_q2_numEntityChars+1), com_cmodelSysPool, 0);
521 
522 	// Copy data
523 	memcpy (cm_q2_entityString, cm_q2_mapBuffer + l->fileOfs, l->fileLen);
524 }
525 
526 // ==========================================================================
527 
528 /*
529 ==================
530 CM_Q2BSP_LoadMap
531 
532 Loads in the map and all submodels
533 ==================
534 */
CM_Q2BSP_LoadMap(uint32 * buffer)535 cBspModel_t *CM_Q2BSP_LoadMap (uint32 *buffer)
536 {
537 	dQ2BspHeader_t	header;
538 	int				i;
539 
540 	//
541 	// Allocate space
542 	//
543 	cm_q2_portalOpen = Mem_PoolAlloc (sizeof(qBool) * Q2BSP_MAX_AREAPORTALS, com_cmodelSysPool, 0);
544 
545 	//
546 	// Byte swap
547 	//
548 	header = *(dQ2BspHeader_t *)buffer;
549 	for (i=0 ; i<sizeof (dQ2BspHeader_t)/4 ; i++)
550 		((int *)&header)[i] = LittleLong (((int *)&header)[i]);
551 	cm_q2_mapBuffer = (byte *)buffer;
552 
553 	//
554 	// Load into heap
555 	//
556 	CM_Q2BSP_LoadSurfaces		(&header.lumps[Q2BSP_LUMP_TEXINFO]);
557 	CM_Q2BSP_LoadLeafs			(&header.lumps[Q2BSP_LUMP_LEAFS]);
558 	CM_Q2BSP_LoadLeafBrushes	(&header.lumps[Q2BSP_LUMP_LEAFBRUSHES]);
559 	CM_Q2BSP_LoadPlanes			(&header.lumps[Q2BSP_LUMP_PLANES]);
560 	CM_Q2BSP_LoadBrushes		(&header.lumps[Q2BSP_LUMP_BRUSHES]);
561 	CM_Q2BSP_LoadBrushSides		(&header.lumps[Q2BSP_LUMP_BRUSHSIDES]);
562 	CM_Q2BSP_LoadSubmodels		(&header.lumps[Q2BSP_LUMP_MODELS]);
563 	CM_Q2BSP_LoadNodes			(&header.lumps[Q2BSP_LUMP_NODES]);
564 	CM_Q2BSP_LoadAreas			(&header.lumps[Q2BSP_LUMP_AREAS]);
565 	CM_Q2BSP_LoadAreaPortals	(&header.lumps[Q2BSP_LUMP_AREAPORTALS]);
566 	CM_Q2BSP_LoadVisibility		(&header.lumps[Q2BSP_LUMP_VISIBILITY]);
567 	CM_Q2BSP_LoadEntityString	(&header.lumps[Q2BSP_LUMP_ENTITIES]);
568 
569 	CM_Q2BSP_InitBoxHull ();
570 	CM_Q2BSP_PrepMap ();
571 
572 	return &cm_mapCModels[0];
573 }
574 
575 
576 /*
577 ==================
578 CM_Q2BSP_PrepMap
579 ==================
580 */
CM_Q2BSP_PrepMap(void)581 void CM_Q2BSP_PrepMap (void)
582 {
583 	if (!cm_q2_portalOpen)
584 		return;
585 
586 	memset (cm_q2_portalOpen, 0, sizeof(qBool) * Q2BSP_MAX_AREAPORTALS);
587 	CM_Q2BSP_FloodAreaConnections ();
588 }
589 
590 
591 /*
592 ==================
593 CM_Q2BSP_UnloadMap
594 ==================
595 */
CM_Q2BSP_UnloadMap(void)596 void CM_Q2BSP_UnloadMap (void)
597 {
598 	cm_q2_areaPortals = NULL;
599 	cm_q2_areas = NULL;
600 	cm_q2_brushes = NULL;
601 	cm_q2_brushSides = NULL;
602 	cm_q2_entityString = cm_q2_emptyEntityString;
603 	cm_q2_leafBrushes = NULL;
604 	cm_q2_leafs = NULL;
605 	cm_q2_nodes = NULL;
606 	cm_q2_planes = NULL;
607 	cm_q2_portalOpen = NULL;
608 	cm_q2_surfaces = NULL;
609 	cm_q2_surfacesUnique = NULL;
610 	cm_q2_visData = NULL;
611 
612 	cm_q2_numAreaPortals = 0;
613 	cm_q2_numAreas = 1;
614 	cm_q2_numBrushes = 0;
615 	cm_q2_numBrushSides = 0;
616 	cm_q2_numClusters = 1;
617 	cm_q2_numEntityChars = 0;
618 	cm_q2_numLeafBrushes = 0;
619 	cm_q2_numLeafs = 1;
620 	cm_q2_numNodes = 0;
621 	cm_q2_numPlanes = 0;
622 	cm_q2_numTexInfo = 0;
623 	cm_q2_numTexInfoUnique = 0;
624 	cm_q2_numVisibility = 0;
625 }
626 
627 /*
628 =============================================================================
629 
630 	QUAKE2 BSP INFORMATION
631 
632 =============================================================================
633 */
634 
635 /*
636 ==================
637 CM_Q2BSP_EntityString
638 ==================
639 */
CM_Q2BSP_EntityString(void)640 char *CM_Q2BSP_EntityString (void)
641 {
642 	return cm_q2_entityString;
643 }
644 
645 
646 /*
647 ==================
648 CM_Q2BSP_SurfRName
649 ==================
650 */
CM_Q2BSP_SurfRName(int texNum)651 char *CM_Q2BSP_SurfRName (int texNum)
652 {
653 	return cm_q2_surfacesUnique ? cm_q2_surfacesUnique[texNum]->rname : NULL;
654 }
655 
656 
657 /*
658 ==================
659 CM_Q2BSP_NumClusters
660 ==================
661 */
CM_Q2BSP_NumClusters(void)662 int CM_Q2BSP_NumClusters (void)
663 {
664 	return cm_q2_numClusters;
665 }
666 
667 
668 /*
669 ==================
670 CM_Q2BSP_NumTexInfo
671 ==================
672 */
CM_Q2BSP_NumTexInfo(void)673 int CM_Q2BSP_NumTexInfo (void)
674 {
675 	return cm_q2_numTexInfoUnique;
676 }
677