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 #include "q_shared.h"
21 
22 #define DEG2RAD( a ) (( a * M_PI ) / 180.0F)
23 
24 vec3_t vec3_origin = {0,0,0};
25 
26 //============================================================================
27 
RotatePointAroundVector(vec3_t dst,const vec3_t dir,const vec3_t point,float degrees)28 void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees )
29 {
30 	float	m[3][3];
31 	float	im[3][3];
32 	float	zrot[3][3];
33 	float	tmpmat[3][3];
34 	float	rot[3][3];
35 
36 	vec3_t vr, vup, vf;
37 
38 	vf[0] = dir[0];
39 	vf[1] = dir[1];
40 	vf[2] = dir[2];
41 
42 	PerpendicularVector( vr, dir );
43 	CrossProduct( vr, vf, vup );
44 
45 	m[0][0] = vr[0];
46 	m[1][0] = vr[1];
47 	m[2][0] = vr[2];
48 
49 	m[0][1] = vup[0];
50 	m[1][1] = vup[1];
51 	m[2][1] = vup[2];
52 
53 	m[0][2] = vf[0];
54 	m[1][2] = vf[1];
55 	m[2][2] = vf[2];
56 
57 	//r1: copies a bunch of stuff we overwrite, better to do individually
58 	//memcpy( im, m, sizeof( im ) );
59 
60 	im[0][0] = m[0][0]; //r1
61 	im[0][1] = m[1][0];
62 	im[0][2] = m[2][0];
63 
64 	im[1][0] = m[0][1];
65 	im[1][1] = m[1][1]; //r1
66 	im[1][2] = m[2][1];
67 
68 	im[2][0] = m[0][2];
69 	im[2][1] = m[1][2];
70 	im[2][2] = m[2][2]; //r1
71 
72 	//wtf?
73 	//memset( zrot, 0, sizeof( zrot ) );
74 	//zrot[0][0] = zrot[1][1] = zrot[2][2] = 1.0F;
75 
76 	zrot[0][0] = (float)cos( DEG2RAD( degrees ) );
77 	zrot[0][1] = (float)sin( DEG2RAD( degrees ) );
78 	zrot[0][2] = 0;
79 
80 	zrot[1][0] = (float)-sin( DEG2RAD( degrees ) );
81 	zrot[1][1] = (float)cos( DEG2RAD( degrees ) );
82 	zrot[1][2] = 0;
83 
84 	zrot[2][0] = 0.0f;
85 	zrot[2][1] = 0.0f;
86 	zrot[2][2] = 1.0f;
87 
88 	R_ConcatRotations( m, zrot, tmpmat );
89 	R_ConcatRotations( tmpmat, im, rot );
90 
91 	dst[0] = rot[0][0] * point[0] + rot[0][1] * point[1] + rot[0][2] * point[2];
92 	dst[1] = rot[1][0] * point[0] + rot[1][1] * point[1] + rot[1][2] * point[2];
93 	dst[2] = rot[2][0] * point[0] + rot[2][1] * point[1] + rot[2][2] * point[2];
94 }
95 
_Q_assert(char * expression,char * function,uint32 line)96 void _Q_assert (char *expression, char *function, uint32 line)
97 {
98 	Com_Printf ("Q_assert: Assertion '%s' failed on %s:%u\n", LOG_GENERAL, expression, function, line);
99 #ifndef GAME_DLL
100 	Sys_DebugBreak ();
101 #endif
102 }
103 
AngleVectors(vec3_t angles,vec3_t forward,vec3_t right,vec3_t up)104 void AngleVectors (vec3_t angles, vec3_t /*@out@*//*@null@*/ forward, vec3_t /*@out@*//*@null@*/right, vec3_t /*@out@*//*@null@*/up)
105 {
106 	float		angle;
107 	static float		sr, sp, sy, cr, cp, cy;
108 	// static to help MS compiler fp bugs
109 
110 	angle = angles[YAW] * M_PI2_DIV_360;
111 	sy = (float)sin(angle);
112 	cy = (float)cos(angle);
113 
114 	angle = angles[PITCH] * M_PI2_DIV_360;
115 	sp = (float)sin(angle);
116 	cp = (float)cos(angle);
117 
118 	if (right || up)
119 	{
120 		angle = angles[ROLL] * M_PI2_DIV_360;
121 		sr = (float)sin(angle);
122 		cr = (float)cos(angle);
123 	}
124 
125 	if (forward)
126 	{
127 		forward[0] = cp*cy;
128 		forward[1] = cp*sy;
129 		forward[2] = -sp;
130 	}
131 
132 	if (right)
133 	{
134 		right[0] = (-1*sr*sp*cy+-1*cr*-sy);
135 		right[1] = (-1*sr*sp*sy+-1*cr*cy);
136 		right[2] = -1*sr*cp;
137 	}
138 
139 	if (up)
140 	{
141 		up[0] = (cr*sp*cy+-sr*-sy);
142 		up[1] = (cr*sp*sy+-sr*cy);
143 		up[2] = cr*cp;
144 	}
145 }
146 
147 
ProjectPointOnPlane(vec3_t dst,const vec3_t p,const vec3_t normal)148 void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal )
149 {
150 	float d;
151 	vec3_t n;
152 	float inv_denom;
153 
154 	inv_denom = 1.0F / DotProduct( normal, normal );
155 
156 	d = DotProduct( normal, p ) * inv_denom;
157 
158 	n[0] = normal[0] * inv_denom;
159 	n[1] = normal[1] * inv_denom;
160 	n[2] = normal[2] * inv_denom;
161 
162 	dst[0] = p[0] - d * n[0];
163 	dst[1] = p[1] - d * n[1];
164 	dst[2] = p[2] - d * n[2];
165 }
166 
167 /*
168 ** assumes "src" is normalized
169 */
PerpendicularVector(vec3_t dst,const vec3_t src)170 void PerpendicularVector( vec3_t dst, const vec3_t src )
171 {
172 	int	pos;
173 	int i;
174 	float minelem = 1.0F;
175 	vec3_t tempvec = {0.0, 0.0, 0.0};
176 
177 	/*
178 	** find the smallest magnitude axially aligned vector
179 	*/
180 	for ( pos = 0, i = 0; i < 3; i++ )
181 	{
182 		if ( (float)fabs( src[i] ) < minelem )
183 		{
184 			pos = i;
185 			minelem = (float)(float)fabs( src[i] );
186 		}
187 	}
188 	tempvec[pos] = 1.0F;
189 
190 	/*
191 	** project the point onto the plane defined by src
192 	*/
193 	ProjectPointOnPlane( dst, tempvec, src );
194 
195 	/*
196 	** normalize the result
197 	*/
198 	VectorNormalize( dst );
199 }
200 
201 
202 
203 /*
204 ================
205 R_ConcatRotations
206 ================
207 */
R_ConcatRotations(float in1[3][3],float in2[3][3],float out[3][3])208 void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3])
209 {
210 	out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
211 				in1[0][2] * in2[2][0];
212 	out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
213 				in1[0][2] * in2[2][1];
214 	out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
215 				in1[0][2] * in2[2][2];
216 	out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
217 				in1[1][2] * in2[2][0];
218 	out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
219 				in1[1][2] * in2[2][1];
220 	out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
221 				in1[1][2] * in2[2][2];
222 	out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
223 				in1[2][2] * in2[2][0];
224 	out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
225 				in1[2][2] * in2[2][1];
226 	out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
227 				in1[2][2] * in2[2][2];
228 }
229 
230 
231 /*
232 ================
233 R_ConcatTransforms
234 ================
235 */
R_ConcatTransforms(float in1[3][4],float in2[3][4],float out[3][4])236 void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4])
237 {
238 	out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
239 				in1[0][2] * in2[2][0];
240 	out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
241 				in1[0][2] * in2[2][1];
242 	out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
243 				in1[0][2] * in2[2][2];
244 	out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] +
245 				in1[0][2] * in2[2][3] + in1[0][3];
246 	out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
247 				in1[1][2] * in2[2][0];
248 	out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
249 				in1[1][2] * in2[2][1];
250 	out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
251 				in1[1][2] * in2[2][2];
252 	out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] +
253 				in1[1][2] * in2[2][3] + in1[1][3];
254 	out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
255 				in1[2][2] * in2[2][0];
256 	out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
257 				in1[2][2] * in2[2][1];
258 	out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
259 				in1[2][2] * in2[2][2];
260 	out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] +
261 				in1[2][2] * in2[2][3] + in1[2][3];
262 }
263 
264 
265 //============================================================================
266 
267 //int sse2_enabled = 0;
268 
269 #if defined _M_IX86 && !defined C_ONLY && !defined linux && !defined SSE2
270 
271 
272 /*__declspec( naked ) void __cdecl Q_ftol2( float f, int *out )
273 {
274 	__asm fld dword ptr [esp+4]
275 	__asm fistp dword ptr [esp+8]
276 	__asm ret
277 }*/
278 
Q_ftol(float f)279 __declspec( naked ) int EXPORT Q_ftol( float f )
280 {
281 	__asm
282 	{
283 		fld dword ptr [esp+4]
284 		push eax
285 		fistp dword ptr [esp]
286 		pop eax
287 		ret
288 	}
289 }
290 
291 /*__declspec( naked ) void __cdecl Q_ftolsse( float f, int *out )
292 {
293 	__asm movd xmm0, [esp+4]
294 	__asm cvttss2si eax, xmm0
295 	__asm mov [esp+8], eax
296 	__asm ret
297 }
298 
299 __declspec( naked ) void __cdecl Q_ftol( float f, int *out )
300 {
301 	__asm cmp sse2_enabled, 0
302 	__asm jz nonsse
303 	__asm call Q_ftolsse
304 	__asm ret
305 nonsse:
306 	__asm call Q_ftol86
307 	__asm ret
308 }
309 
310 __declspec (naked) void __cdecl Q_sseinit (void)
311 {
312 	__asm mov eax, 1
313 	__asm cpuid
314 	__asm test edx, 4000000h
315 	__asm jz nosse
316 	__asm mov sse2_enabled, 1
317 nosse:
318 	__asm ret
319 }*/
320 
Q_fastfloats(float * f,int * outptr)321 __declspec (naked) void EXPORT Q_fastfloats (float *f, int *outptr)
322 {
323 	/*__asm cmp sse2_enabled, 0
324 	__asm jz nonsse
325 	__asm mov eax, [esp+4]
326 	__asm movups xmm1, [eax]
327 	__asm cvttps2dq xmm0, xmm1
328 	__asm mov eax, [esp+8]
329 	__asm movdqu [eax], xmm0
330 	__asm ret
331 nonsse:*/
332 	__asm mov eax, [esp+8]
333 	__asm mov ebx, [esp+4]
334 
335 	__asm fld dword ptr [ebx]
336 	__asm fistp dword ptr [eax]
337 	__asm fld dword ptr [ebx+4]
338 	__asm fistp dword ptr [eax+4]
339 	__asm fld dword ptr [ebx+8]
340 	__asm fistp dword ptr [eax+8]
341 	__asm ret
342 }
343 
344 #else
345 
Q_ftol(float f)346 int EXPORT Q_ftol( float f )
347 {
348 	return (int)f;
349 }
350 
Q_fastfloats(float * f,int * outptr)351 void EXPORT Q_fastfloats (float *f, int *outptr)
352 {
353 	outptr[0] = (int)f[0];
354 	outptr[1] = (int)f[1];
355 	outptr[2] = (int)f[2];
356 }
357 
358 /*void Q_ftol2 (float f, int *out)
359 {
360 	*out = (int)f;
361 }*/
362 
363 #endif
364 
365 /*
366 ===============
367 LerpAngle
368 
369 ===============
370 */
LerpAngle(float a2,float a1,float frac)371 float LerpAngle (float a2, float a1, float frac)
372 {
373 	if (a1 - a2 > 180)
374 		a1 -= 360;
375 	if (a1 - a2 < -180)
376 		a1 += 360;
377 	return a2 + frac * (a1 - a2);
378 }
379 
380 
anglemod(float a)381 float	anglemod(float a)
382 {
383 #if 0
384 	if (a >= 0)
385 		a -= 360*(int)(a/360);
386 	else
387 		a += 360*( 1 + (int)(-a/360) );
388 #else
389 	//a = (0.0054931640625f) * ((int)(a*(182.0444444444444444444444444444444444444444444444444444444444444444f))& 65535);
390 	a = (360.0f/65536.0f) * ((int)(a*(65536.0f/360.0f)) & 65535);
391 #endif
392 	return a;
393 }
394 
395 //int		i;
396 //vec3_t	corners[2];
397 
398 
399 // this is the slow, general version
BoxOnPlaneSide2(vec3_t emins,vec3_t emaxs,struct cplane_s * p)400 int BoxOnPlaneSide2 (vec3_t emins, vec3_t emaxs, struct cplane_s *p)
401 {
402 	int		i;
403 	float	dist1, dist2;
404 	int		sides;
405 	vec3_t	corners[2];
406 
407 	for (i=0 ; i<3 ; i++)
408 	{
409 		if (FLOAT_LT_ZERO(p->normal[i]))
410 		{
411 			corners[0][i] = emins[i];
412 			corners[1][i] = emaxs[i];
413 		}
414 		else
415 		{
416 			corners[1][i] = emins[i];
417 			corners[0][i] = emaxs[i];
418 		}
419 	}
420 	dist1 = DotProduct (p->normal, corners[0]) - p->dist;
421 	dist2 = DotProduct (p->normal, corners[1]) - p->dist;
422 	sides = 0;
423 	if (FLOAT_GE_ZERO(dist1))
424 		sides = 1;
425 	if (FLOAT_LT_ZERO(dist2))
426 		sides |= 2;
427 
428 	return sides;
429 }
430 
431 /*
432 ==================
433 BoxOnPlaneSide
434 
435 Returns 1, 2, or 1 + 2
436 ==================
437 */
438 #if !id386 || defined __linux__ || defined __FreeBSD__
BoxOnPlaneSide(vec3_t emins,vec3_t emaxs,struct cplane_s * p)439 int EXPORT BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, struct cplane_s *p)
440 {
441 	float	dist1, dist2;
442 	int		sides;
443 
444 // fast axial cases
445 	//r1: these never seem to hit?
446 	/*if (p->type < 3)
447 	{
448 		Sys_DebugBreak ();
449 		if (p->dist <= emins[p->type])
450 			return 1;
451 		if (p->dist >= emaxs[p->type])
452 			return 2;
453 		return 3;
454 	}*/
455 
456 // general case
457 	switch (p->signbits)
458 	{
459 	case 0:
460 dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
461 dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
462 		break;
463 	case 1:
464 dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
465 dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
466 		break;
467 	case 2:
468 dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
469 dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
470 		break;
471 	case 3:
472 dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
473 dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
474 		break;
475 	case 4:
476 dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
477 dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
478 		break;
479 	case 5:
480 dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
481 dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
482 		break;
483 	case 6:
484 dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
485 dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
486 		break;
487 	case 7:
488 dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
489 dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
490 		break;
491 	default:
492 		dist1 = dist2 = 0;		// shut up compiler
493 		break;
494 	}
495 
496 	sides = 0;
497 	if (dist1 >= p->dist)
498 		sides = 1;
499 	if (dist2 < p->dist)
500 		sides |= 2;
501 
502 	return sides;
503 }
504 #else
505 //#pragma warning( disable: 4035 )
506 
BoxOnPlaneSide(vec3_t emins,vec3_t emaxs,struct cplane_s * p)507 __declspec( naked ) int __cdecl BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, struct cplane_s *p)
508 {
509 	//static int bops_initialized;
510 	static int Ljmptab[8];
511 
512 	__asm
513 	{
514 		push esi
515 		push ebx
516 
517 		lea eax, Ljmptab
518 
519 		cmp dword ptr [eax], 0
520 		je short notinitialized
521 		//mov bops_initialized, 1
522 
523 initialized:
524 
525 		mov ecx,ds:dword ptr[8+4+esp]
526 		mov ebx,ds:dword ptr[8+8+esp]
527 		mov edx,ds:dword ptr[8+12+esp]
528 		;xor eax,eax
529 		;mov al,ds:byte ptr[17+edx]
530 		movzx esi, ds:byte ptr[17+edx]
531 		;r1 - removed, Lerror will crash and so will illegal access, this should
532 		;never happen anyway and just causes a branch
533 		;cmp al,8
534 		;jge Lerror
535 		fld ds:dword ptr[0+edx]
536 		fld st(0)
537 		jmp dword ptr[eax+esi*4]
538 Lcase0:
539 		fmul ds:dword ptr[ebx]
540 		fld ds:dword ptr[0+4+edx]
541 		fxch st(2)
542 		fmul ds:dword ptr[ecx]
543 		fxch st(2)
544 		fld st(0)
545 		fmul ds:dword ptr[4+ebx]
546 		fld ds:dword ptr[0+8+edx]
547 		fxch st(2)
548 		fmul ds:dword ptr[4+ecx]
549 		fxch st(2)
550 		fld st(0)
551 		fmul ds:dword ptr[8+ebx]
552 		fxch st(5)
553 		faddp st(3),st(0)
554 		fmul ds:dword ptr[8+ecx]
555 		fxch st(1)
556 		faddp st(3),st(0)
557 		fxch st(3)
558 		faddp st(2),st(0)
559 		jmp short LSetSides
560 Lcase1:
561 		fmul ds:dword ptr[ecx]
562 		fld ds:dword ptr[0+4+edx]
563 		fxch st(2)
564 		fmul ds:dword ptr[ebx]
565 		fxch st(2)
566 		fld st(0)
567 		fmul ds:dword ptr[4+ebx]
568 		fld ds:dword ptr[0+8+edx]
569 		fxch st(2)
570 		fmul ds:dword ptr[4+ecx]
571 		fxch st(2)
572 		fld st(0)
573 		fmul ds:dword ptr[8+ebx]
574 		fxch st(5)
575 		faddp st(3),st(0)
576 		fmul ds:dword ptr[8+ecx]
577 		fxch st(1)
578 		faddp st(3),st(0)
579 		fxch st(3)
580 		faddp st(2),st(0)
581 		jmp short LSetSides
582 Lcase2:
583 		fmul ds:dword ptr[ebx]
584 		fld ds:dword ptr[0+4+edx]
585 		fxch st(2)
586 		fmul ds:dword ptr[ecx]
587 		fxch st(2)
588 		fld st(0)
589 		fmul ds:dword ptr[4+ecx]
590 		fld ds:dword ptr[0+8+edx]
591 		fxch st(2)
592 		fmul ds:dword ptr[4+ebx]
593 		fxch st(2)
594 		fld st(0)
595 		fmul ds:dword ptr[8+ebx]
596 		fxch st(5)
597 		faddp st(3),st(0)
598 		fmul ds:dword ptr[8+ecx]
599 		fxch st(1)
600 		faddp st(3),st(0)
601 		fxch st(3)
602 		faddp st(2),st(0)
603 		jmp short LSetSides
604 Lcase3:
605 		fmul ds:dword ptr[ecx]
606 		fld ds:dword ptr[0+4+edx]
607 		fxch st(2)
608 		fmul ds:dword ptr[ebx]
609 		fxch st(2)
610 		fld st(0)
611 		fmul ds:dword ptr[4+ecx]
612 		fld ds:dword ptr[0+8+edx]
613 		fxch st(2)
614 		fmul ds:dword ptr[4+ebx]
615 		fxch st(2)
616 		fld st(0)
617 		fmul ds:dword ptr[8+ebx]
618 		fxch st(5)
619 		faddp st(3),st(0)
620 		fmul ds:dword ptr[8+ecx]
621 		fxch st(1)
622 		faddp st(3),st(0)
623 		fxch st(3)
624 		faddp st(2),st(0)
625 		jmp short LSetSides
626 Lcase4:
627 		fmul ds:dword ptr[ebx]
628 		fld ds:dword ptr[0+4+edx]
629 		fxch st(2)
630 		fmul ds:dword ptr[ecx]
631 		fxch st(2)
632 		fld st(0)
633 		fmul ds:dword ptr[4+ebx]
634 		fld ds:dword ptr[0+8+edx]
635 		fxch st(2)
636 		fmul ds:dword ptr[4+ecx]
637 		fxch st(2)
638 		fld st(0)
639 		fmul ds:dword ptr[8+ecx]
640 		fxch st(5)
641 		faddp st(3),st(0)
642 		fmul ds:dword ptr[8+ebx]
643 		fxch st(1)
644 		faddp st(3),st(0)
645 		fxch st(3)
646 		faddp st(2),st(0)
647 		jmp short LSetSides
648 Lcase5:
649 		fmul ds:dword ptr[ecx]
650 		fld ds:dword ptr[0+4+edx]
651 		fxch st(2)
652 		fmul ds:dword ptr[ebx]
653 		fxch st(2)
654 		fld st(0)
655 		fmul ds:dword ptr[4+ebx]
656 		fld ds:dword ptr[0+8+edx]
657 		fxch st(2)
658 		fmul ds:dword ptr[4+ecx]
659 		fxch st(2)
660 		fld st(0)
661 		fmul ds:dword ptr[8+ecx]
662 		fxch st(5)
663 		faddp st(3),st(0)
664 		fmul ds:dword ptr[8+ebx]
665 		fxch st(1)
666 		faddp st(3),st(0)
667 		fxch st(3)
668 		faddp st(2),st(0)
669 		jmp short LSetSides
670 Lcase6:
671 		fmul ds:dword ptr[ebx]
672 		fld ds:dword ptr[0+4+edx]
673 		fxch st(2)
674 		fmul ds:dword ptr[ecx]
675 		fxch st(2)
676 		fld st(0)
677 		fmul ds:dword ptr[4+ecx]
678 		fld ds:dword ptr[0+8+edx]
679 		fxch st(2)
680 		fmul ds:dword ptr[4+ebx]
681 		fxch st(2)
682 		fld st(0)
683 		fmul ds:dword ptr[8+ecx]
684 		fxch st(5)
685 		faddp st(3),st(0)
686 		fmul ds:dword ptr[8+ebx]
687 		fxch st(1)
688 		faddp st(3),st(0)
689 		fxch st(3)
690 		faddp st(2),st(0)
691 		jmp short LSetSides
692 Lcase7:
693 		fmul ds:dword ptr[ecx]
694 		fld ds:dword ptr[0+4+edx]
695 		fxch st(2)
696 		fmul ds:dword ptr[ebx]
697 		fxch st(2)
698 		fld st(0)
699 		fmul ds:dword ptr[4+ecx]
700 		fld ds:dword ptr[0+8+edx]
701 		fxch st(2)
702 		fmul ds:dword ptr[4+ebx]
703 		fxch st(2)
704 		fld st(0)
705 		fmul ds:dword ptr[8+ecx]
706 		fxch st(5)
707 		faddp st(3),st(0)
708 		fmul ds:dword ptr[8+ebx]
709 		fxch st(1)
710 		faddp st(3),st(0)
711 		fxch st(3)
712 		faddp st(2),st(0)
713 
714 		;padding for LSetsides
715 		lea esp, [esp]
716 		lea esp, [esp]
717 LSetSides:
718 		faddp st(2),st(0)
719 		fcomp ds:dword ptr[12+edx]
720 		xor ecx,ecx
721 		fnstsw ax
722 		fcomp ds:dword ptr[12+edx]
723 		and ah,1
724 		xor ah,1
725 		add cl,ah
726 		fnstsw ax
727 		and ah,1
728 		add ah,ah
729 		add cl,ah
730 		pop ebx
731 		pop esi
732 		mov eax,ecx
733 		ret
734 //Lerror:
735 //		int 3
736 notinitialized:
737 		mov dword ptr [eax], offset Lcase0
738 		mov dword ptr [eax+4], offset Lcase1
739 		mov dword ptr [eax+8], offset Lcase2
740 		mov dword ptr [eax+12], offset Lcase3
741 		mov dword ptr [eax+16], offset Lcase4
742 		mov dword ptr [eax+20], offset Lcase5
743 		mov dword ptr [eax+24], offset Lcase6
744 		mov dword ptr [eax+28], offset Lcase7
745 		jmp initialized
746 	}
747 }
748 //#pragma warning( default: 4035 )
749 #endif
750 
751 /*void ClearBounds (vec3_t mins, vec3_t maxs)
752 {
753 	mins[0] = mins[1] = mins[2] = 99999;
754 	maxs[0] = maxs[1] = maxs[2] = -99999;
755 }*/
756 
AddPointToBounds(vec3_t v,vec3_t mins,vec3_t maxs)757 void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs)
758 {
759 	if (v[0] < mins[0])
760 		mins[0] = v[0];
761 
762 	if (v[0] > maxs[0])
763 		maxs[0] = v[0];
764 
765 	if (v[1] < mins[1])
766 		mins[1] = v[1];
767 
768 	if (v[1] > maxs[1])
769 		maxs[1] = v[1];
770 
771 	if (v[2] < mins[2])
772 		mins[2] = v[2];
773 
774 	if (v[2] > maxs[2])
775 		maxs[2] = v[2];
776 }
777 
778 
779 //r1: macroified
780 /*int VectorCompare (vec3_t v1, vec3_t v2)
781 {
782 	if (v1[0] != v2[0] || v1[1] != v2[1] || v1[2] != v2[2])
783 			return 0;
784 
785 	return 1;
786 }*/
787 
788 
VectorNormalize(vec3_t v)789 vec_t VectorNormalize (vec3_t v)
790 {
791 	float	length, ilength;
792 
793 	length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
794 	length = (float)sqrt (length);		// FIXME
795 
796 	if (FLOAT_NE_ZERO(length))
797 	{
798 		ilength = 1/length;
799 		v[0] *= ilength;
800 		v[1] *= ilength;
801 		v[2] *= ilength;
802 	}
803 
804 	return length;
805 
806 }
807 
VectorNormalize2(vec3_t v,vec3_t out)808 vec_t VectorNormalize2 (vec3_t v, vec3_t out)
809 {
810 	float	length, ilength;
811 
812 	length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
813 	length = (float)sqrt (length);		// FIXME
814 
815 	if (FLOAT_NE_ZERO(length))
816 	{
817 		ilength = 1/length;
818 		out[0] = v[0]*ilength;
819 		out[1] = v[1]*ilength;
820 		out[2] = v[2]*ilength;
821 	}
822 
823 	return length;
824 }
825 
826 /*void VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc)
827 {
828 	vecc[0] = veca[0] + scale*vecb[0];
829 	vecc[1] = veca[1] + scale*vecb[1];
830 	vecc[2] = veca[2] + scale*vecb[2];
831 }*/
832 
833 
_DotProduct(vec3_t v1,vec3_t v2)834 vec_t _DotProduct (vec3_t v1, vec3_t v2)
835 {
836 	return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
837 }
838 
_VectorSubtract(vec3_t veca,vec3_t vecb,vec3_t out)839 void _VectorSubtract (vec3_t veca, vec3_t vecb, vec3_t out)
840 {
841 	out[0] = veca[0]-vecb[0];
842 	out[1] = veca[1]-vecb[1];
843 	out[2] = veca[2]-vecb[2];
844 }
845 
_VectorAdd(vec3_t veca,vec3_t vecb,vec3_t out)846 void _VectorAdd (vec3_t veca, vec3_t vecb, vec3_t out)
847 {
848 	out[0] = veca[0]+vecb[0];
849 	out[1] = veca[1]+vecb[1];
850 	out[2] = veca[2]+vecb[2];
851 }
852 
_VectorCopy(vec3_t in,vec3_t out)853 void _VectorCopy (vec3_t in, vec3_t out)
854 {
855 	out[0] = in[0];
856 	out[1] = in[1];
857 	out[2] = in[2];
858 }
859 
860 /*void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross)
861 {
862 	cross[0] = v1[1]*v2[2] - v1[2]*v2[1];
863 	cross[1] = v1[2]*v2[0] - v1[0]*v2[2];
864 	cross[2] = v1[0]*v2[1] - v1[1]*v2[0];
865 }*/
866 
867 double EXPORT sqrt(double x);
868 
VectorLength(vec3_t v)869 vec_t VectorLength(vec3_t v)
870 {
871 	float	length;
872 
873 	length = 0;
874 
875 	length += v[0]*v[0];
876 	length += v[1]*v[1];
877 	length += v[2]*v[2];
878 
879 	length = (float)sqrtf (length);		// FIXME
880 
881 	return length;
882 }
883 
884 /*void VectorInverse (vec3_t v)
885 {
886 	v[0] = -v[0];
887 	v[1] = -v[1];
888 	v[2] = -v[2];
889 }
890 
891 void VectorScale (vec3_t in, vec_t scale, vec3_t out)
892 {
893 	out[0] = in[0]*scale;
894 	out[1] = in[1]*scale;
895 	out[2] = in[2]*scale;
896 }*/
897 
898 
Q_log2(int val)899 int Q_log2(int val)
900 {
901 	int answer=0;
902 	while (val>>=1)
903 		answer++;
904 	return answer;
905 }
906 
907 
908 
909 //====================================================================================
910 
911 /*
912 ============
913 COM_SkipPath
914 ============
915 */
COM_SkipPath(char * pathname)916 char *COM_SkipPath (char *pathname)
917 {
918 	char	*last;
919 
920 	last = pathname;
921 	while (pathname[0])
922 	{
923 		if (pathname[0] == '/')
924 			last = pathname+1;
925 		pathname++;
926 	}
927 	return last;
928 }
929 
930 /*
931 ============
932 COM_StripExtension
933 ============
934 */
COM_StripExtension(const char * in,char * out)935 void COM_StripExtension (const char *in, char *out)
936 {
937 	while (*in && *in != '.')
938 		*out++ = *in++;
939 	*out = 0;
940 }
941 
942 /*
943 ============
944 COM_FileExtension
945 ============
946 */
COM_FileExtension(char * in)947 char *COM_FileExtension (char *in)
948 {
949 	static char exten[8];
950 	int		i;
951 
952 	while (*in && *in != '.')
953 		in++;
954 	if (!*in)
955 		return "";
956 	in++;
957 	for (i=0 ; i<7 && *in ; i++,in++)
958 		exten[i] = *in;
959 	exten[i] = 0;
960 	return exten;
961 }
962 
963 /*
964 ============
965 COM_FileBase
966 ============
967 */
COM_FileBase(char * in,char * out)968 void COM_FileBase (char *in, char *out)
969 {
970 	char *s, *s2;
971 
972 	s = in + strlen(in) - 1;
973 
974 	while (s != in && *s != '.')
975 		s--;
976 
977 	for (s2 = s ; s2 != in && *s2 != '/' ; s2--)
978 	;
979 
980 	if (s-s2 < 2)
981 		out[0] = 0;
982 	else
983 	{
984 		s--;
985 		strncpy (out,s2+1, s-s2);
986 		out[s-s2] = 0;
987 	}
988 }
989 
990 /*
991 ============
992 COM_FilePath
993 
994 Returns the path up to, but not including the last /
995 ============
996 */
COM_FilePath(const char * in,char * out)997 void COM_FilePath (const char *in, char *out)
998 {
999 	const char *s;
1000 
1001 	s = in + strlen(in) - 1;
1002 
1003 	while (s != in && *s != '/')
1004 		s--;
1005 
1006 	strncpy (out, in, s-in);
1007 	out[s-in] = 0;
1008 }
1009 
1010 
1011 /*
1012 ==================
1013 COM_DefaultExtension
1014 ==================
1015 */
COM_DefaultExtension(char * path,const char * extension)1016 void COM_DefaultExtension (char *path, const char *extension)
1017 {
1018 	char    *src;
1019 //
1020 // if path doesn't have a .EXT, append extension
1021 // (extension should include the .)
1022 //
1023 	src = path + strlen(path) - 1;
1024 
1025 	while (*src != '/' && src != path)
1026 	{
1027 		if (*src == '.')
1028 			return;                 // it has an extension
1029 		src--;
1030 	}
1031 
1032 	strcat (path, extension);
1033 }
1034 
1035 /*
1036 ============================================================================
1037 
1038 					BYTE ORDER FUNCTIONS
1039 
1040 ============================================================================
1041 */
1042 
1043 //r1: endianness sucks. this is a waste of function calls for everything.
1044 //define Q_BIGENDIAN if you're on a mac or some other big endian system.
1045 
1046 //need this for network ports
ShortSwap(int16 l)1047 int16 ShortSwap (int16 l)
1048 {
1049 	byte    b1,b2;
1050 
1051 	b1 = l&255;
1052 	b2 = (l>>8)&255;
1053 
1054 	return (b1<<8) + b2;
1055 }
1056 
LongSwap(int32 l)1057 int32 LongSwap (int32 l)
1058 {
1059 	byte    b1,b2,b3,b4;
1060 
1061 	b1 = l&255;
1062 	b2 = (l>>8)&255;
1063 	b3 = (l>>16)&255;
1064 	b4 = (l>>24)&255;
1065 
1066 	return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
1067 }
1068 
1069 #if Q_BIGENDIAN
1070 
1071 qboolean	bigendien;
1072 
1073 // can't just use function pointers, or dll linkage can
1074 // mess up when qcommon is included in multiple places
1075 
1076 int16	(*_LittleShort) (int16 l);
1077 int32		(*_LittleLong) (int32 l);
1078 float	(*_LittleFloat) (float l);
1079 
LittleShort(int16 l)1080 int16	LittleShort(int16 l) {return _LittleShort(l);}
LittleLong(int32 l)1081 int32		LittleLong (int32 l) {return _LittleLong(l);}
LittleFloat(float l)1082 float	LittleFloat (float l) {return _LittleFloat(l);}
1083 
ShortNoSwap(int16 l)1084 int16	ShortNoSwap (int16 l)
1085 {
1086 	return l;
1087 }
1088 
LongNoSwap(int32 l)1089 int32	LongNoSwap (int32 l)
1090 {
1091 	return l;
1092 }
1093 
FloatSwap(float f)1094 float FloatSwap (float f)
1095 {
1096 	union
1097 	{
1098 		float	f;
1099 		byte	b[4];
1100 	} dat1, dat2;
1101 
1102 
1103 	dat1.f = f;
1104 	dat2.b[0] = dat1.b[3];
1105 	dat2.b[1] = dat1.b[2];
1106 	dat2.b[2] = dat1.b[1];
1107 	dat2.b[3] = dat1.b[0];
1108 	return dat2.f;
1109 }
1110 
FloatNoSwap(float f)1111 float FloatNoSwap (float f)
1112 {
1113 	return f;
1114 }
1115 
1116 /*
1117 ================
1118 Swap_Init
1119 ================
1120 */
Swap_Init(void)1121 void Swap_Init (void)
1122 {
1123 	byte	swaptest[2] = {1,0};
1124 
1125 // set the byte swapping variables in a portable manner
1126 	if ( *(int16 *)swaptest == 1)
1127 	{
1128 		bigendien = false;
1129 		_LittleShort = ShortNoSwap;
1130 		_LittleLong = LongNoSwap;
1131 		_LittleFloat = FloatNoSwap;
1132 	}
1133 	else
1134 	{
1135 		bigendien = true;
1136 		_LittleShort = ShortSwap;
1137 		_LittleLong = LongSwap;
1138 		_LittleFloat = FloatSwap;
1139 	}
1140 }
1141 #else
Swap_Init(void)1142 void Swap_Init (void){}
1143 #endif
1144 
1145 /*
1146 ============
1147 va
1148 
1149 does a varargs printf into a temp buffer, so I don't need to have
1150 varargs versions of all text functions.
1151 FIXME: make this buffer size safe someday
1152 ============
1153 */
va(const char * format,...)1154 char	*va(const char *format, ...)
1155 {
1156 	va_list		argptr;
1157 
1158 	static char		string[2][1024];
1159 	static int		index;
1160 
1161 	index  ^= 1;
1162 
1163 	va_start (argptr, format);
1164 	vsnprintf (string[index], sizeof(string[index])-1, format, argptr);
1165 	va_end (argptr);
1166 
1167 	return string[index];
1168 }
1169 
1170 
1171 char	com_token[MAX_TOKEN_CHARS];
1172 
1173 /*
1174 ==============
1175 COM_Parse
1176 
1177 Parse a token out of a string
1178 ==============
1179 */
COM_Parse(char ** data_p)1180 const char *COM_Parse (char **data_p)
1181 {
1182 	int		c;
1183 	int		len;
1184 	char	*data;
1185 
1186 	data = *data_p;
1187 	len = 0;
1188 	com_token[0] = 0;
1189 
1190 	if (!data)
1191 	{
1192 		*data_p = NULL;
1193 		return "";
1194 	}
1195 
1196 // skip whitespace
1197 skipwhite:
1198 	while ( (c = *data) <= ' ')
1199 	{
1200 		if (c == 0)
1201 		{
1202 			*data_p = NULL;
1203 			return "";
1204 		}
1205 		data++;
1206 	}
1207 
1208 // skip // comments
1209 	if (c=='/' && data[1] == '/')
1210 	{
1211 		while (*data && *data != '\n')
1212 			data++;
1213 		goto skipwhite;
1214 	}
1215 
1216 // handle quoted strings specially
1217 	if (c == '\"')
1218 	{
1219 		data++;
1220 		for (;;)
1221 		{
1222 			c = *data++;
1223 			if (c== '\"' || !c)
1224 			{
1225 				//bugfix from skuller
1226 				goto finish;
1227 			}
1228 			if (len < MAX_TOKEN_CHARS)
1229 			{
1230 				com_token[len] = c;
1231 				len++;
1232 			}
1233 		}
1234 	}
1235 
1236 // parse a regular word
1237 	do
1238 	{
1239 		if (len < MAX_TOKEN_CHARS)
1240 		{
1241 			com_token[len] = c;
1242 			len++;
1243 		}
1244 		data++;
1245 		c = *data;
1246 	} while (c>32);
1247 
1248 finish:
1249 
1250 	if (len == MAX_TOKEN_CHARS)
1251 	{
1252 		len = 0;
1253 	}
1254 	com_token[len] = 0;
1255 
1256 	*data_p = data;
1257 	return com_token;
1258 }
1259 
1260 
1261 /*
1262 ===============
1263 Com_PageInMemory
1264 
1265 ===============
1266 */
1267 int	paged_total;
1268 
Com_PageInMemory(byte * buffer,int size)1269 void Com_PageInMemory (byte *buffer, int size)
1270 {
1271 	int		i;
1272 
1273 	for (i=size-1 ; i>0 ; i-=4096)
1274 		paged_total += buffer[i];
1275 }
1276 
1277 
1278 
1279 /*
1280 ============================================================================
1281 
1282 					LIBRARY REPLACEMENT FUNCTIONS
1283 
1284 ============================================================================
1285 */
1286 
1287 // FIXME: replace all Q_stricmp with Q_stricmp
1288 #if defined _WIN32 && defined _M_AMD64
Q_strncasecmp(const char * s1,const char * s2,size_t n)1289 int Q_strncasecmp (const char *s1, const char *s2, size_t n)
1290 {
1291 	int		c1, c2;
1292 
1293 	do
1294 	{
1295 		c1 = *s1++;
1296 		c2 = *s2++;
1297 
1298 		if (!n--)
1299 			return 0;		// strings are equal until end point
1300 
1301 		if (c1 != c2)
1302 		{
1303 			if (c1 >= 'a' && c1 <= 'z')
1304 				c1 -= ('a' - 'A');
1305 			if (c2 >= 'a' && c2 <= 'z')
1306 				c2 -= ('a' - 'A');
1307 			if (c1 != c2)
1308 				return -1;		// strings not equal
1309 		}
1310 	} while (c1);
1311 
1312 	return 0;		// strings are equal
1313 }
1314 
Q_stricmp(const char * s1,const char * s2)1315 int Q_stricmp (const char *s1, const char *s2)
1316 {
1317 	return Q_strncasecmp (s1, s2, 99999);
1318 }
1319 #endif
1320 
1321 
Com_sprintf(char * dest,int size,const char * fmt,...)1322 int Com_sprintf (char /*@out@*/*dest, int size, const char *fmt, ...)
1323 {
1324 	int			len;
1325 	va_list		argptr;
1326 	char		bigbuffer[0x10000];
1327 
1328 	va_start (argptr,fmt);
1329 	len = Q_vsnprintf (bigbuffer, sizeof(bigbuffer), fmt, argptr);
1330 	va_end (argptr);
1331 
1332 	if (len == -1 || len == size)
1333 	{
1334 		Com_Printf ("Com_sprintf: overflow of size %d\n", LOG_GENERAL, size);
1335 		len = size-1;
1336 	}
1337 
1338 	bigbuffer[size-1] = '\0';
1339 	strcpy (dest, bigbuffer);
1340 
1341 	return len;
1342 }
1343 
1344 /*
1345 =====================================================================
1346 
1347   INFO STRINGS
1348 
1349 =====================================================================
1350 */
1351 
1352 /*
1353 ===============
1354 Info_ValueForKey
1355 
1356 Searches the string for the given
1357 key and returns the associated value, or an empty string.
1358 ===============
1359 */
Info_ValueForKey(const char * s,const char * key)1360 char *Info_ValueForKey (const char *s, const char *key)
1361 {
1362 	char	pkey[512];
1363 	static	char value[2][512];	// use two buffers so compares
1364 								// work without stomping on each other
1365 	static	int	valueindex;
1366 	char	*o;
1367 
1368 	valueindex ^= 1;
1369 	if (*s == '\\')
1370 		s++;
1371 	for (;;)
1372 	{
1373 		o = pkey;
1374 		while (*s != '\\')
1375 		{
1376 			if (!*s)
1377 				return "";
1378 			*o++ = *s++;
1379 		}
1380 		*o = 0;
1381 		s++;
1382 
1383 		o = value[valueindex];
1384 
1385 		while (*s != '\\' && *s)
1386 		{
1387 			if (!*s)
1388 				return "";
1389 			*o++ = *s++;
1390 		}
1391 		*o = 0;
1392 
1393 		if (!strcmp (key, pkey) )
1394 			return value[valueindex];
1395 
1396 		if (!*s)
1397 			return "";
1398 		s++;
1399 	}
1400 }
1401 
Info_KeyExists(const char * s,const char * key)1402 qboolean Info_KeyExists (const char *s, const char *key)
1403 {
1404 	char	pkey[512];
1405 	char	*o;
1406 
1407 	if (*s == '\\')
1408 		s++;
1409 
1410 	for (;;)
1411 	{
1412 		o = pkey;
1413 		while (*s != '\\')
1414 		{
1415 			if (!*s)
1416 				return false;
1417 			*o++ = *s++;
1418 		}
1419 		*o = 0;
1420 		s++;
1421 
1422 		while (*s != '\\' && *s)
1423 			s++;
1424 
1425 		if (!strcmp (key, pkey) )
1426 			return true;
1427 
1428 		if (!*s)
1429 			return false;
1430 		s++;
1431 	}
1432 }
1433 
Info_RemoveKey(char * s,const char * key)1434 void Info_RemoveKey (char *s, const char *key)
1435 {
1436 	char	*start;
1437 	char	pkey[512];
1438 	char	value[512];
1439 	char	*o;
1440 
1441 	if (strchr (key, '\\'))
1442 	{
1443 		Com_Printf ("Info_RemoveKey: Tried to remove illegal key '%s'\n", LOG_WARNING|LOG_GENERAL, key);
1444 		return;
1445 	}
1446 
1447 	for (;;)
1448 	{
1449 		start = s;
1450 		if (*s == '\\')
1451 			s++;
1452 		o = pkey;
1453 		while (*s != '\\')
1454 		{
1455 			if (!*s)
1456 				return;
1457 			*o++ = *s++;
1458 		}
1459 		*o = 0;
1460 		s++;
1461 
1462 		o = value;
1463 		while (*s != '\\' && *s)
1464 		{
1465 			if (!*s)
1466 				return;
1467 			*o++ = *s++;
1468 		}
1469 		*o = 0;
1470 
1471 		if (!strcmp (key, pkey) )
1472 		{
1473 			//r1: overlapping src+dst with strcpy = no
1474 			//strcpy (start, s);	// remove this part
1475 			size_t memlen;
1476 
1477 			memlen = strlen(s);
1478 			memmove (start, s, memlen);
1479 			start[memlen] = 0;
1480 			return;
1481 		}
1482 
1483 		if (!*s)
1484 			return;
1485 	}
1486 
1487 }
1488 
1489 
1490 /*
1491 ==================
1492 Info_Validate
1493 
1494 Some characters are illegal in info strings because they
1495 can mess up the server's parsing
1496 ==================
1497 */
Info_Validate(const char * s)1498 qboolean Info_Validate (const char *s)
1499 {
1500 	if (strchr (s, '"'))
1501 		return false;
1502 
1503 	if (strchr (s, ';'))
1504 		return false;
1505 
1506 	return true;
1507 }
1508 
Info_CheckBytes(const char * s)1509 qboolean Info_CheckBytes (const char *s)
1510 {
1511 	while (s[0])
1512 	{
1513 		if (s[0] < 32 || s[0] >= 127)
1514 			return false;
1515 		s++;
1516 	}
1517 
1518 	return true;
1519 }
1520 
Info_SetValueForKey(char * s,const char * key,const char * value)1521 void Info_SetValueForKey (char *s, const char *key, const char *value)
1522 {
1523 	char	newi[MAX_INFO_STRING], *v;
1524 	int		c;
1525 
1526 	if (strchr (key, '\\') || strchr (value, '\\') )
1527 	{
1528 		Com_Printf ("Can't use keys or values with a \\ (attempted to set key '%s')\n", LOG_GENERAL, key);
1529 		return;
1530 	}
1531 
1532 	if (strchr (key, ';') || strchr (value, ';') )
1533 	{
1534 		Com_Printf ("Can't use keys or values with a semicolon (attempted to set key '%s')\n", LOG_GENERAL, key);
1535 		return;
1536 	}
1537 
1538 	if (strchr (key, '"') || strchr (value, '"') )
1539 	{
1540 		Com_Printf ("Can't use keys or values with a \" (attempted to set key '%s')\n", LOG_GENERAL, key);
1541 		return;
1542 	}
1543 
1544 	if (strlen(key) > MAX_INFO_KEY-1 || strlen(value) > MAX_INFO_KEY-1)
1545 	{
1546 		Com_Printf ("Keys and values must be < 64 characters (attempted to set key '%s')\n", LOG_GENERAL, key);
1547 		return;
1548 	}
1549 
1550 	Info_RemoveKey (s, key);
1551 
1552 	if (!value || !value[0])
1553 		return;
1554 
1555 	Com_sprintf (newi, sizeof(newi), "\\%s\\%s", key, value);
1556 
1557 	if (strlen(newi) + strlen(s) > MAX_INFO_STRING)
1558 	{
1559 		Com_Printf ("Info string length exceeded while trying to set '%s'\n", LOG_GENERAL, newi);
1560 		return;
1561 	}
1562 
1563 	// only copy ascii values
1564 	s += strlen(s);
1565 	v = newi;
1566 	while (*v)
1567 	{
1568 		c = *v++;
1569 		c &= 127;		// strip high bits
1570 		if (c >= 32 && c < 127)
1571 			*s++ = c;
1572 	}
1573 	s[0] = 0;
1574 }
1575 
1576 //====================================================================
1577 
1578 #ifndef _WIN32
Q_vsnprintf(char * buff,size_t len,const char * fmt,va_list va)1579 int Q_vsnprintf (char *buff, size_t len, const char *fmt, va_list va)
1580 {
1581 	int ret;
1582 
1583 	ret = vsnprintf (buff, len, fmt, va);
1584 	if (ret > -1 && ret < len)
1585 		return ret;
1586 
1587 	return -1;
1588 }
1589 
1590 /*int Q_snprintf (char *buff, size_t len, const char *fmt, ...)
1591 {
1592 	int ret;
1593 
1594 	va_list argptr;
1595 
1596 	va_start (argptr, fmt);
1597 	ret = Q_vsnprintf (buff, len, fmt, argptr);
1598 	va_end (argptr);
1599 
1600 	return ret;
1601 }*/
1602 
Q_strlwr(char * str)1603 void Q_strlwr (char *str)
1604 {
1605 	while (*str)
1606 	{
1607 		if (isupper(*str))
1608 			*str = tolower(*str);
1609 		str++;
1610 	}
1611 }
1612 #endif
1613 
1614 /*
1615   Copyright (C) 1996, 1997, 1998, 1999, 2000 Florian Schintke
1616 
1617   This is free software; you can redistribute it and/or modify it under
1618   the terms of the GNU General Public License as published by the Free
1619   Software Foundation; either version 2, or (at your option) any later
1620   version.
1621 
1622   This is distributed in the hope that it will be useful, but WITHOUT
1623   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1624   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1625   for more details.
1626 
1627   You should have received a copy of the GNU General Public License with
1628   the c2html, java2html, pas2html or perl2html source package as the
1629   file COPYING. If not, write to the Free Software Foundation, Inc.,
1630   59 Temple Place - Suite 330, Boston, MA
1631   02111-1307, USA.
1632 */
1633 
1634 /* Documenttitle and purpose:                                       */
1635 /*   Implementation of the UN*X wildcards in C. So they are         */
1636 /*   available in a portable way and can be used whereever          */
1637 /*   needed.                                                        */
1638 /*                                                                  */
1639 /* Version:                                                         */
1640 /*   1.2                                                            */
1641 /*                                                                  */
1642 /* Test cases:                                                      */
1643 /*   Please look into the Shellscript testwildcards.main            */
1644 /*                                                                  */
1645 /* Author(s):                                                       */
1646 /*   Florian Schintke (schintke@gmx.de)                             */
1647 /*                                                                  */
1648 /* Tester:                                                          */
1649 /*   Florian Schintke (schintke@gmx.de)                             */
1650 /*                                                                  */
1651 /* Testing state:                                                   */
1652 /*   tested with the atac tool                                      */
1653 /*   Latest test state is documented in testwildcards.report        */
1654 /*   The program that tested this functions is available as         */
1655 /*   testwildcards.c                                                */
1656 /*                                                                  */
1657 /* Dates:                                                           */
1658 /*   First editing: unknown, but before 04/02/1997                  */
1659 /*   Last Change  : 04/07/2000                                      */
1660 /*                                                                  */
1661 /* Known Bugs:                                                      */
1662 /*                                                                  */
1663 
1664 int set (char **wildcard, char **test);
1665 /* Scans a set of characters and returns 0 if the set mismatches at this */
1666 /* position in the teststring and 1 if it is matching                    */
1667 /* wildcard is set to the closing ] and test is unmodified if mismatched */
1668 /* and otherwise the char pointer is pointing to the next character      */
1669 
1670 int asterisk (char **wildcard, char **test);
1671 /* scans an asterisk */
1672 
wildcardfit(char * wildcard,char * test)1673 int wildcardfit (char *wildcard, char *test)
1674 {
1675   int fit = 1;
1676 
1677   for (; ('\000' != *wildcard) && (1 == fit) && ('\000' != *test); wildcard++)
1678     {
1679       switch (*wildcard)
1680         {
1681         case '[':
1682 	  wildcard++; /* leave out the opening square bracket */
1683           fit = set (&wildcard, &test);
1684 	  /* we don't need to decrement the wildcard as in case */
1685 	  /* of asterisk because the closing ] is still there */
1686           break;
1687         case '?':
1688           test++;
1689           break;
1690         case '*':
1691           fit = asterisk (&wildcard, &test);
1692 	  /* the asterisk was skipped by asterisk() but the loop will */
1693 	  /* increment by itself. So we have to decrement */
1694 	  wildcard--;
1695           break;
1696         default:
1697           fit = (int) (*wildcard == *test);
1698           test++;
1699         }
1700     }
1701   while ((*wildcard == '*') && (1 == fit))
1702     /* here the teststring is empty otherwise you cannot */
1703     /* leave the previous loop */
1704     wildcard++;
1705   return (int) ((1 == fit) && ('\0' == *test) && ('\0' == *wildcard));
1706 }
1707 
set(char ** wildcard,char ** test)1708 int set (char **wildcard, char **test)
1709 {
1710   int fit = 0;
1711   int negation = 0;
1712   int at_beginning = 1;
1713 
1714   if ('!' == **wildcard)
1715     {
1716       negation = 1;
1717       (*wildcard)++;
1718     }
1719   while ((']' != **wildcard) || (1 == at_beginning))
1720     {
1721       if (0 == fit)
1722         {
1723           if (('-' == **wildcard)
1724               && ((*(*wildcard - 1)) < (*(*wildcard + 1)))
1725               && (']' != *(*wildcard + 1))
1726 	      && (0 == at_beginning))
1727             {
1728               if (((**test) >= (*(*wildcard - 1)))
1729                   && ((**test) <= (*(*wildcard + 1))))
1730                 {
1731                   fit = 1;
1732                   (*wildcard)++;
1733                 }
1734             }
1735           else if ((**wildcard) == (**test))
1736             {
1737               fit = 1;
1738             }
1739         }
1740       (*wildcard)++;
1741       at_beginning = 0;
1742     }
1743   if (1 == negation)
1744     /* change from zero to one and vice versa */
1745     fit = 1 - fit;
1746   if (1 == fit)
1747     (*test)++;
1748 
1749   return (fit);
1750 }
1751 
asterisk(char ** wildcard,char ** test)1752 int asterisk (char **wildcard, char **test)
1753 {
1754   /* Warning: uses multiple returns */
1755   int fit = 1;
1756 
1757   /* erase the leading asterisk */
1758   (*wildcard)++;
1759   while (('\000' != (**test))
1760 	 && (('?' == **wildcard)
1761 	     || ('*' == **wildcard)))
1762     {
1763       if ('?' == **wildcard)
1764 	(*test)++;
1765       (*wildcard)++;
1766     }
1767   /* Now it could be that test is empty and wildcard contains */
1768   /* aterisks. Then we delete them to get a proper state */
1769   while ('*' == (**wildcard))
1770     (*wildcard)++;
1771 
1772   if (('\0' == (**test)) && ('\0' != (**wildcard)))
1773     return (fit = 0);
1774   if (('\0' == (**test)) && ('\0' == (**wildcard)))
1775     return (fit = 1);
1776   else
1777     {
1778       /* Neither test nor wildcard are empty!          */
1779       /* the first character of wildcard isn't in [*?] */
1780       if (0 == wildcardfit(*wildcard, (*test)))
1781 	{
1782 	  do
1783 	    {
1784 	      (*test)++;
1785 	      /* skip as much characters as possible in the teststring */
1786 	      /* stop if a character match occurs */
1787 	      while (((**wildcard) != (**test))
1788 		     && ('['  != (**wildcard))
1789 		     && ('\0' != (**test)))
1790 		(*test)++;
1791 	    }
1792 	  while ((('\0' != **test))?
1793 		 (0 == wildcardfit (*wildcard, (*test)))
1794 		 : (0 != (fit = 0)));
1795 	}
1796       if (('\0' == **test) && ('\0' == **wildcard))
1797 	fit = 1;
1798       return (fit);
1799     }
1800 }
1801