Quake-2

Quake 2 GPL Source Release
Log | Files | Refs

q_shared.c (25593B)


      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 
     28 #ifdef _WIN32
     29 #pragma optimize( "", off )
     30 #endif
     31 
     32 void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees )
     33 {
     34 	float	m[3][3];
     35 	float	im[3][3];
     36 	float	zrot[3][3];
     37 	float	tmpmat[3][3];
     38 	float	rot[3][3];
     39 	int	i;
     40 	vec3_t vr, vup, vf;
     41 
     42 	vf[0] = dir[0];
     43 	vf[1] = dir[1];
     44 	vf[2] = dir[2];
     45 
     46 	PerpendicularVector( vr, dir );
     47 	CrossProduct( vr, vf, vup );
     48 
     49 	m[0][0] = vr[0];
     50 	m[1][0] = vr[1];
     51 	m[2][0] = vr[2];
     52 
     53 	m[0][1] = vup[0];
     54 	m[1][1] = vup[1];
     55 	m[2][1] = vup[2];
     56 
     57 	m[0][2] = vf[0];
     58 	m[1][2] = vf[1];
     59 	m[2][2] = vf[2];
     60 
     61 	memcpy( im, m, sizeof( im ) );
     62 
     63 	im[0][1] = m[1][0];
     64 	im[0][2] = m[2][0];
     65 	im[1][0] = m[0][1];
     66 	im[1][2] = m[2][1];
     67 	im[2][0] = m[0][2];
     68 	im[2][1] = m[1][2];
     69 
     70 	memset( zrot, 0, sizeof( zrot ) );
     71 	zrot[0][0] = zrot[1][1] = zrot[2][2] = 1.0F;
     72 
     73 	zrot[0][0] = cos( DEG2RAD( degrees ) );
     74 	zrot[0][1] = sin( DEG2RAD( degrees ) );
     75 	zrot[1][0] = -sin( DEG2RAD( degrees ) );
     76 	zrot[1][1] = cos( DEG2RAD( degrees ) );
     77 
     78 	R_ConcatRotations( m, zrot, tmpmat );
     79 	R_ConcatRotations( tmpmat, im, rot );
     80 
     81 	for ( i = 0; i < 3; i++ )
     82 	{
     83 		dst[i] = rot[i][0] * point[0] + rot[i][1] * point[1] + rot[i][2] * point[2];
     84 	}
     85 }
     86 
     87 #ifdef _WIN32
     88 #pragma optimize( "", on )
     89 #endif
     90 
     91 
     92 
     93 void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
     94 {
     95 	float		angle;
     96 	static float		sr, sp, sy, cr, cp, cy;
     97 	// static to help MS compiler fp bugs
     98 
     99 	angle = angles[YAW] * (M_PI*2 / 360);
    100 	sy = sin(angle);
    101 	cy = cos(angle);
    102 	angle = angles[PITCH] * (M_PI*2 / 360);
    103 	sp = sin(angle);
    104 	cp = cos(angle);
    105 	angle = angles[ROLL] * (M_PI*2 / 360);
    106 	sr = sin(angle);
    107 	cr = cos(angle);
    108 
    109 	if (forward)
    110 	{
    111 		forward[0] = cp*cy;
    112 		forward[1] = cp*sy;
    113 		forward[2] = -sp;
    114 	}
    115 	if (right)
    116 	{
    117 		right[0] = (-1*sr*sp*cy+-1*cr*-sy);
    118 		right[1] = (-1*sr*sp*sy+-1*cr*cy);
    119 		right[2] = -1*sr*cp;
    120 	}
    121 	if (up)
    122 	{
    123 		up[0] = (cr*sp*cy+-sr*-sy);
    124 		up[1] = (cr*sp*sy+-sr*cy);
    125 		up[2] = cr*cp;
    126 	}
    127 }
    128 
    129 
    130 void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal )
    131 {
    132 	float d;
    133 	vec3_t n;
    134 	float inv_denom;
    135 
    136 	inv_denom = 1.0F / DotProduct( normal, normal );
    137 
    138 	d = DotProduct( normal, p ) * inv_denom;
    139 
    140 	n[0] = normal[0] * inv_denom;
    141 	n[1] = normal[1] * inv_denom;
    142 	n[2] = normal[2] * inv_denom;
    143 
    144 	dst[0] = p[0] - d * n[0];
    145 	dst[1] = p[1] - d * n[1];
    146 	dst[2] = p[2] - d * n[2];
    147 }
    148 
    149 /*
    150 ** assumes "src" is normalized
    151 */
    152 void PerpendicularVector( vec3_t dst, const vec3_t src )
    153 {
    154 	int	pos;
    155 	int i;
    156 	float minelem = 1.0F;
    157 	vec3_t tempvec;
    158 
    159 	/*
    160 	** find the smallest magnitude axially aligned vector
    161 	*/
    162 	for ( pos = 0, i = 0; i < 3; i++ )
    163 	{
    164 		if ( fabs( src[i] ) < minelem )
    165 		{
    166 			pos = i;
    167 			minelem = fabs( src[i] );
    168 		}
    169 	}
    170 	tempvec[0] = tempvec[1] = tempvec[2] = 0.0F;
    171 	tempvec[pos] = 1.0F;
    172 
    173 	/*
    174 	** project the point onto the plane defined by src
    175 	*/
    176 	ProjectPointOnPlane( dst, tempvec, src );
    177 
    178 	/*
    179 	** normalize the result
    180 	*/
    181 	VectorNormalize( dst );
    182 }
    183 
    184 
    185 
    186 /*
    187 ================
    188 R_ConcatRotations
    189 ================
    190 */
    191 void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3])
    192 {
    193 	out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
    194 				in1[0][2] * in2[2][0];
    195 	out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
    196 				in1[0][2] * in2[2][1];
    197 	out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
    198 				in1[0][2] * in2[2][2];
    199 	out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
    200 				in1[1][2] * in2[2][0];
    201 	out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
    202 				in1[1][2] * in2[2][1];
    203 	out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
    204 				in1[1][2] * in2[2][2];
    205 	out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
    206 				in1[2][2] * in2[2][0];
    207 	out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
    208 				in1[2][2] * in2[2][1];
    209 	out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
    210 				in1[2][2] * in2[2][2];
    211 }
    212 
    213 
    214 /*
    215 ================
    216 R_ConcatTransforms
    217 ================
    218 */
    219 void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4])
    220 {
    221 	out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
    222 				in1[0][2] * in2[2][0];
    223 	out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
    224 				in1[0][2] * in2[2][1];
    225 	out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
    226 				in1[0][2] * in2[2][2];
    227 	out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] +
    228 				in1[0][2] * in2[2][3] + in1[0][3];
    229 	out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
    230 				in1[1][2] * in2[2][0];
    231 	out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
    232 				in1[1][2] * in2[2][1];
    233 	out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
    234 				in1[1][2] * in2[2][2];
    235 	out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] +
    236 				in1[1][2] * in2[2][3] + in1[1][3];
    237 	out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
    238 				in1[2][2] * in2[2][0];
    239 	out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
    240 				in1[2][2] * in2[2][1];
    241 	out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
    242 				in1[2][2] * in2[2][2];
    243 	out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] +
    244 				in1[2][2] * in2[2][3] + in1[2][3];
    245 }
    246 
    247 
    248 //============================================================================
    249 
    250 
    251 float Q_fabs (float f)
    252 {
    253 #if 0
    254 	if (f >= 0)
    255 		return f;
    256 	return -f;
    257 #else
    258 	int tmp = * ( int * ) &f;
    259 	tmp &= 0x7FFFFFFF;
    260 	return * ( float * ) &tmp;
    261 #endif
    262 }
    263 
    264 #if defined _M_IX86 && !defined C_ONLY
    265 #pragma warning (disable:4035)
    266 __declspec( naked ) long Q_ftol( float f )
    267 {
    268 	static int tmp;
    269 	__asm fld dword ptr [esp+4]
    270 	__asm fistp tmp
    271 	__asm mov eax, tmp
    272 	__asm ret
    273 }
    274 #pragma warning (default:4035)
    275 #endif
    276 
    277 /*
    278 ===============
    279 LerpAngle
    280 
    281 ===============
    282 */
    283 float LerpAngle (float a2, float a1, float frac)
    284 {
    285 	if (a1 - a2 > 180)
    286 		a1 -= 360;
    287 	if (a1 - a2 < -180)
    288 		a1 += 360;
    289 	return a2 + frac * (a1 - a2);
    290 }
    291 
    292 
    293 float	anglemod(float a)
    294 {
    295 #if 0
    296 	if (a >= 0)
    297 		a -= 360*(int)(a/360);
    298 	else
    299 		a += 360*( 1 + (int)(-a/360) );
    300 #endif
    301 	a = (360.0/65536) * ((int)(a*(65536/360.0)) & 65535);
    302 	return a;
    303 }
    304 
    305 	int		i;
    306 	vec3_t	corners[2];
    307 
    308 
    309 // this is the slow, general version
    310 int BoxOnPlaneSide2 (vec3_t emins, vec3_t emaxs, struct cplane_s *p)
    311 {
    312 	int		i;
    313 	float	dist1, dist2;
    314 	int		sides;
    315 	vec3_t	corners[2];
    316 
    317 	for (i=0 ; i<3 ; i++)
    318 	{
    319 		if (p->normal[i] < 0)
    320 		{
    321 			corners[0][i] = emins[i];
    322 			corners[1][i] = emaxs[i];
    323 		}
    324 		else
    325 		{
    326 			corners[1][i] = emins[i];
    327 			corners[0][i] = emaxs[i];
    328 		}
    329 	}
    330 	dist1 = DotProduct (p->normal, corners[0]) - p->dist;
    331 	dist2 = DotProduct (p->normal, corners[1]) - p->dist;
    332 	sides = 0;
    333 	if (dist1 >= 0)
    334 		sides = 1;
    335 	if (dist2 < 0)
    336 		sides |= 2;
    337 
    338 	return sides;
    339 }
    340 
    341 /*
    342 ==================
    343 BoxOnPlaneSide
    344 
    345 Returns 1, 2, or 1 + 2
    346 ==================
    347 */
    348 #if !id386
    349 int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, struct cplane_s *p)
    350 {
    351 	float	dist1, dist2;
    352 	int		sides;
    353 
    354 // fast axial cases
    355 	if (p->type < 3)
    356 	{
    357 		if (p->dist <= emins[p->type])
    358 			return 1;
    359 		if (p->dist >= emaxs[p->type])
    360 			return 2;
    361 		return 3;
    362 	}
    363 	
    364 // general case
    365 	switch (p->signbits)
    366 	{
    367 	case 0:
    368 dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
    369 dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
    370 		break;
    371 	case 1:
    372 dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
    373 dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
    374 		break;
    375 	case 2:
    376 dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
    377 dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
    378 		break;
    379 	case 3:
    380 dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
    381 dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
    382 		break;
    383 	case 4:
    384 dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
    385 dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
    386 		break;
    387 	case 5:
    388 dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
    389 dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
    390 		break;
    391 	case 6:
    392 dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
    393 dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
    394 		break;
    395 	case 7:
    396 dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
    397 dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
    398 		break;
    399 	default:
    400 		dist1 = dist2 = 0;		// shut up compiler
    401 		assert( 0 );
    402 		break;
    403 	}
    404 
    405 	sides = 0;
    406 	if (dist1 >= p->dist)
    407 		sides = 1;
    408 	if (dist2 < p->dist)
    409 		sides |= 2;
    410 
    411 	assert( sides != 0 );
    412 
    413 	return sides;
    414 }
    415 #else
    416 #pragma warning( disable: 4035 )
    417 
    418 __declspec( naked ) int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, struct cplane_s *p)
    419 {
    420 	static int bops_initialized;
    421 	static int Ljmptab[8];
    422 
    423 	__asm {
    424 
    425 		push ebx
    426 			
    427 		cmp bops_initialized, 1
    428 		je  initialized
    429 		mov bops_initialized, 1
    430 		
    431 		mov Ljmptab[0*4], offset Lcase0
    432 		mov Ljmptab[1*4], offset Lcase1
    433 		mov Ljmptab[2*4], offset Lcase2
    434 		mov Ljmptab[3*4], offset Lcase3
    435 		mov Ljmptab[4*4], offset Lcase4
    436 		mov Ljmptab[5*4], offset Lcase5
    437 		mov Ljmptab[6*4], offset Lcase6
    438 		mov Ljmptab[7*4], offset Lcase7
    439 			
    440 initialized:
    441 
    442 		mov edx,ds:dword ptr[4+12+esp]
    443 		mov ecx,ds:dword ptr[4+4+esp]
    444 		xor eax,eax
    445 		mov ebx,ds:dword ptr[4+8+esp]
    446 		mov al,ds:byte ptr[17+edx]
    447 		cmp al,8
    448 		jge Lerror
    449 		fld ds:dword ptr[0+edx]
    450 		fld st(0)
    451 		jmp dword ptr[Ljmptab+eax*4]
    452 Lcase0:
    453 		fmul ds:dword ptr[ebx]
    454 		fld ds:dword ptr[0+4+edx]
    455 		fxch st(2)
    456 		fmul ds:dword ptr[ecx]
    457 		fxch st(2)
    458 		fld st(0)
    459 		fmul ds:dword ptr[4+ebx]
    460 		fld ds:dword ptr[0+8+edx]
    461 		fxch st(2)
    462 		fmul ds:dword ptr[4+ecx]
    463 		fxch st(2)
    464 		fld st(0)
    465 		fmul ds:dword ptr[8+ebx]
    466 		fxch st(5)
    467 		faddp st(3),st(0)
    468 		fmul ds:dword ptr[8+ecx]
    469 		fxch st(1)
    470 		faddp st(3),st(0)
    471 		fxch st(3)
    472 		faddp st(2),st(0)
    473 		jmp LSetSides
    474 Lcase1:
    475 		fmul ds:dword ptr[ecx]
    476 		fld ds:dword ptr[0+4+edx]
    477 		fxch st(2)
    478 		fmul ds:dword ptr[ebx]
    479 		fxch st(2)
    480 		fld st(0)
    481 		fmul ds:dword ptr[4+ebx]
    482 		fld ds:dword ptr[0+8+edx]
    483 		fxch st(2)
    484 		fmul ds:dword ptr[4+ecx]
    485 		fxch st(2)
    486 		fld st(0)
    487 		fmul ds:dword ptr[8+ebx]
    488 		fxch st(5)
    489 		faddp st(3),st(0)
    490 		fmul ds:dword ptr[8+ecx]
    491 		fxch st(1)
    492 		faddp st(3),st(0)
    493 		fxch st(3)
    494 		faddp st(2),st(0)
    495 		jmp LSetSides
    496 Lcase2:
    497 		fmul ds:dword ptr[ebx]
    498 		fld ds:dword ptr[0+4+edx]
    499 		fxch st(2)
    500 		fmul ds:dword ptr[ecx]
    501 		fxch st(2)
    502 		fld st(0)
    503 		fmul ds:dword ptr[4+ecx]
    504 		fld ds:dword ptr[0+8+edx]
    505 		fxch st(2)
    506 		fmul ds:dword ptr[4+ebx]
    507 		fxch st(2)
    508 		fld st(0)
    509 		fmul ds:dword ptr[8+ebx]
    510 		fxch st(5)
    511 		faddp st(3),st(0)
    512 		fmul ds:dword ptr[8+ecx]
    513 		fxch st(1)
    514 		faddp st(3),st(0)
    515 		fxch st(3)
    516 		faddp st(2),st(0)
    517 		jmp LSetSides
    518 Lcase3:
    519 		fmul ds:dword ptr[ecx]
    520 		fld ds:dword ptr[0+4+edx]
    521 		fxch st(2)
    522 		fmul ds:dword ptr[ebx]
    523 		fxch st(2)
    524 		fld st(0)
    525 		fmul ds:dword ptr[4+ecx]
    526 		fld ds:dword ptr[0+8+edx]
    527 		fxch st(2)
    528 		fmul ds:dword ptr[4+ebx]
    529 		fxch st(2)
    530 		fld st(0)
    531 		fmul ds:dword ptr[8+ebx]
    532 		fxch st(5)
    533 		faddp st(3),st(0)
    534 		fmul ds:dword ptr[8+ecx]
    535 		fxch st(1)
    536 		faddp st(3),st(0)
    537 		fxch st(3)
    538 		faddp st(2),st(0)
    539 		jmp LSetSides
    540 Lcase4:
    541 		fmul ds:dword ptr[ebx]
    542 		fld ds:dword ptr[0+4+edx]
    543 		fxch st(2)
    544 		fmul ds:dword ptr[ecx]
    545 		fxch st(2)
    546 		fld st(0)
    547 		fmul ds:dword ptr[4+ebx]
    548 		fld ds:dword ptr[0+8+edx]
    549 		fxch st(2)
    550 		fmul ds:dword ptr[4+ecx]
    551 		fxch st(2)
    552 		fld st(0)
    553 		fmul ds:dword ptr[8+ecx]
    554 		fxch st(5)
    555 		faddp st(3),st(0)
    556 		fmul ds:dword ptr[8+ebx]
    557 		fxch st(1)
    558 		faddp st(3),st(0)
    559 		fxch st(3)
    560 		faddp st(2),st(0)
    561 		jmp LSetSides
    562 Lcase5:
    563 		fmul ds:dword ptr[ecx]
    564 		fld ds:dword ptr[0+4+edx]
    565 		fxch st(2)
    566 		fmul ds:dword ptr[ebx]
    567 		fxch st(2)
    568 		fld st(0)
    569 		fmul ds:dword ptr[4+ebx]
    570 		fld ds:dword ptr[0+8+edx]
    571 		fxch st(2)
    572 		fmul ds:dword ptr[4+ecx]
    573 		fxch st(2)
    574 		fld st(0)
    575 		fmul ds:dword ptr[8+ecx]
    576 		fxch st(5)
    577 		faddp st(3),st(0)
    578 		fmul ds:dword ptr[8+ebx]
    579 		fxch st(1)
    580 		faddp st(3),st(0)
    581 		fxch st(3)
    582 		faddp st(2),st(0)
    583 		jmp LSetSides
    584 Lcase6:
    585 		fmul ds:dword ptr[ebx]
    586 		fld ds:dword ptr[0+4+edx]
    587 		fxch st(2)
    588 		fmul ds:dword ptr[ecx]
    589 		fxch st(2)
    590 		fld st(0)
    591 		fmul ds:dword ptr[4+ecx]
    592 		fld ds:dword ptr[0+8+edx]
    593 		fxch st(2)
    594 		fmul ds:dword ptr[4+ebx]
    595 		fxch st(2)
    596 		fld st(0)
    597 		fmul ds:dword ptr[8+ecx]
    598 		fxch st(5)
    599 		faddp st(3),st(0)
    600 		fmul ds:dword ptr[8+ebx]
    601 		fxch st(1)
    602 		faddp st(3),st(0)
    603 		fxch st(3)
    604 		faddp st(2),st(0)
    605 		jmp LSetSides
    606 Lcase7:
    607 		fmul ds:dword ptr[ecx]
    608 		fld ds:dword ptr[0+4+edx]
    609 		fxch st(2)
    610 		fmul ds:dword ptr[ebx]
    611 		fxch st(2)
    612 		fld st(0)
    613 		fmul ds:dword ptr[4+ecx]
    614 		fld ds:dword ptr[0+8+edx]
    615 		fxch st(2)
    616 		fmul ds:dword ptr[4+ebx]
    617 		fxch st(2)
    618 		fld st(0)
    619 		fmul ds:dword ptr[8+ecx]
    620 		fxch st(5)
    621 		faddp st(3),st(0)
    622 		fmul ds:dword ptr[8+ebx]
    623 		fxch st(1)
    624 		faddp st(3),st(0)
    625 		fxch st(3)
    626 		faddp st(2),st(0)
    627 LSetSides:
    628 		faddp st(2),st(0)
    629 		fcomp ds:dword ptr[12+edx]
    630 		xor ecx,ecx
    631 		fnstsw ax
    632 		fcomp ds:dword ptr[12+edx]
    633 		and ah,1
    634 		xor ah,1
    635 		add cl,ah
    636 		fnstsw ax
    637 		and ah,1
    638 		add ah,ah
    639 		add cl,ah
    640 		pop ebx
    641 		mov eax,ecx
    642 		ret
    643 Lerror:
    644 		int 3
    645 	}
    646 }
    647 #pragma warning( default: 4035 )
    648 #endif
    649 
    650 void ClearBounds (vec3_t mins, vec3_t maxs)
    651 {
    652 	mins[0] = mins[1] = mins[2] = 99999;
    653 	maxs[0] = maxs[1] = maxs[2] = -99999;
    654 }
    655 
    656 void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs)
    657 {
    658 	int		i;
    659 	vec_t	val;
    660 
    661 	for (i=0 ; i<3 ; i++)
    662 	{
    663 		val = v[i];
    664 		if (val < mins[i])
    665 			mins[i] = val;
    666 		if (val > maxs[i])
    667 			maxs[i] = val;
    668 	}
    669 }
    670 
    671 
    672 int VectorCompare (vec3_t v1, vec3_t v2)
    673 {
    674 	if (v1[0] != v2[0] || v1[1] != v2[1] || v1[2] != v2[2])
    675 			return 0;
    676 			
    677 	return 1;
    678 }
    679 
    680 
    681 vec_t VectorNormalize (vec3_t v)
    682 {
    683 	float	length, ilength;
    684 
    685 	length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
    686 	length = sqrt (length);		// FIXME
    687 
    688 	if (length)
    689 	{
    690 		ilength = 1/length;
    691 		v[0] *= ilength;
    692 		v[1] *= ilength;
    693 		v[2] *= ilength;
    694 	}
    695 		
    696 	return length;
    697 
    698 }
    699 
    700 vec_t VectorNormalize2 (vec3_t v, vec3_t out)
    701 {
    702 	float	length, ilength;
    703 
    704 	length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
    705 	length = sqrt (length);		// FIXME
    706 
    707 	if (length)
    708 	{
    709 		ilength = 1/length;
    710 		out[0] = v[0]*ilength;
    711 		out[1] = v[1]*ilength;
    712 		out[2] = v[2]*ilength;
    713 	}
    714 		
    715 	return length;
    716 
    717 }
    718 
    719 void VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc)
    720 {
    721 	vecc[0] = veca[0] + scale*vecb[0];
    722 	vecc[1] = veca[1] + scale*vecb[1];
    723 	vecc[2] = veca[2] + scale*vecb[2];
    724 }
    725 
    726 
    727 vec_t _DotProduct (vec3_t v1, vec3_t v2)
    728 {
    729 	return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
    730 }
    731 
    732 void _VectorSubtract (vec3_t veca, vec3_t vecb, vec3_t out)
    733 {
    734 	out[0] = veca[0]-vecb[0];
    735 	out[1] = veca[1]-vecb[1];
    736 	out[2] = veca[2]-vecb[2];
    737 }
    738 
    739 void _VectorAdd (vec3_t veca, vec3_t vecb, vec3_t out)
    740 {
    741 	out[0] = veca[0]+vecb[0];
    742 	out[1] = veca[1]+vecb[1];
    743 	out[2] = veca[2]+vecb[2];
    744 }
    745 
    746 void _VectorCopy (vec3_t in, vec3_t out)
    747 {
    748 	out[0] = in[0];
    749 	out[1] = in[1];
    750 	out[2] = in[2];
    751 }
    752 
    753 void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross)
    754 {
    755 	cross[0] = v1[1]*v2[2] - v1[2]*v2[1];
    756 	cross[1] = v1[2]*v2[0] - v1[0]*v2[2];
    757 	cross[2] = v1[0]*v2[1] - v1[1]*v2[0];
    758 }
    759 
    760 double sqrt(double x);
    761 
    762 vec_t VectorLength(vec3_t v)
    763 {
    764 	int		i;
    765 	float	length;
    766 	
    767 	length = 0;
    768 	for (i=0 ; i< 3 ; i++)
    769 		length += v[i]*v[i];
    770 	length = sqrt (length);		// FIXME
    771 
    772 	return length;
    773 }
    774 
    775 void VectorInverse (vec3_t v)
    776 {
    777 	v[0] = -v[0];
    778 	v[1] = -v[1];
    779 	v[2] = -v[2];
    780 }
    781 
    782 void VectorScale (vec3_t in, vec_t scale, vec3_t out)
    783 {
    784 	out[0] = in[0]*scale;
    785 	out[1] = in[1]*scale;
    786 	out[2] = in[2]*scale;
    787 }
    788 
    789 
    790 int Q_log2(int val)
    791 {
    792 	int answer=0;
    793 	while (val>>=1)
    794 		answer++;
    795 	return answer;
    796 }
    797 
    798 
    799 
    800 //====================================================================================
    801 
    802 /*
    803 ============
    804 COM_SkipPath
    805 ============
    806 */
    807 char *COM_SkipPath (char *pathname)
    808 {
    809 	char	*last;
    810 	
    811 	last = pathname;
    812 	while (*pathname)
    813 	{
    814 		if (*pathname=='/')
    815 			last = pathname+1;
    816 		pathname++;
    817 	}
    818 	return last;
    819 }
    820 
    821 /*
    822 ============
    823 COM_StripExtension
    824 ============
    825 */
    826 void COM_StripExtension (char *in, char *out)
    827 {
    828 	while (*in && *in != '.')
    829 		*out++ = *in++;
    830 	*out = 0;
    831 }
    832 
    833 /*
    834 ============
    835 COM_FileExtension
    836 ============
    837 */
    838 char *COM_FileExtension (char *in)
    839 {
    840 	static char exten[8];
    841 	int		i;
    842 
    843 	while (*in && *in != '.')
    844 		in++;
    845 	if (!*in)
    846 		return "";
    847 	in++;
    848 	for (i=0 ; i<7 && *in ; i++,in++)
    849 		exten[i] = *in;
    850 	exten[i] = 0;
    851 	return exten;
    852 }
    853 
    854 /*
    855 ============
    856 COM_FileBase
    857 ============
    858 */
    859 void COM_FileBase (char *in, char *out)
    860 {
    861 	char *s, *s2;
    862 	
    863 	s = in + strlen(in) - 1;
    864 	
    865 	while (s != in && *s != '.')
    866 		s--;
    867 	
    868 	for (s2 = s ; s2 != in && *s2 != '/' ; s2--)
    869 	;
    870 	
    871 	if (s-s2 < 2)
    872 		out[0] = 0;
    873 	else
    874 	{
    875 		s--;
    876 		strncpy (out,s2+1, s-s2);
    877 		out[s-s2] = 0;
    878 	}
    879 }
    880 
    881 /*
    882 ============
    883 COM_FilePath
    884 
    885 Returns the path up to, but not including the last /
    886 ============
    887 */
    888 void COM_FilePath (char *in, char *out)
    889 {
    890 	char *s;
    891 	
    892 	s = in + strlen(in) - 1;
    893 	
    894 	while (s != in && *s != '/')
    895 		s--;
    896 
    897 	strncpy (out,in, s-in);
    898 	out[s-in] = 0;
    899 }
    900 
    901 
    902 /*
    903 ==================
    904 COM_DefaultExtension
    905 ==================
    906 */
    907 void COM_DefaultExtension (char *path, char *extension)
    908 {
    909 	char    *src;
    910 //
    911 // if path doesn't have a .EXT, append extension
    912 // (extension should include the .)
    913 //
    914 	src = path + strlen(path) - 1;
    915 
    916 	while (*src != '/' && src != path)
    917 	{
    918 		if (*src == '.')
    919 			return;                 // it has an extension
    920 		src--;
    921 	}
    922 
    923 	strcat (path, extension);
    924 }
    925 
    926 /*
    927 ============================================================================
    928 
    929 					BYTE ORDER FUNCTIONS
    930 
    931 ============================================================================
    932 */
    933 
    934 qboolean	bigendien;
    935 
    936 // can't just use function pointers, or dll linkage can
    937 // mess up when qcommon is included in multiple places
    938 short	(*_BigShort) (short l);
    939 short	(*_LittleShort) (short l);
    940 int		(*_BigLong) (int l);
    941 int		(*_LittleLong) (int l);
    942 float	(*_BigFloat) (float l);
    943 float	(*_LittleFloat) (float l);
    944 
    945 short	BigShort(short l){return _BigShort(l);}
    946 short	LittleShort(short l) {return _LittleShort(l);}
    947 int		BigLong (int l) {return _BigLong(l);}
    948 int		LittleLong (int l) {return _LittleLong(l);}
    949 float	BigFloat (float l) {return _BigFloat(l);}
    950 float	LittleFloat (float l) {return _LittleFloat(l);}
    951 
    952 short   ShortSwap (short l)
    953 {
    954 	byte    b1,b2;
    955 
    956 	b1 = l&255;
    957 	b2 = (l>>8)&255;
    958 
    959 	return (b1<<8) + b2;
    960 }
    961 
    962 short	ShortNoSwap (short l)
    963 {
    964 	return l;
    965 }
    966 
    967 int    LongSwap (int l)
    968 {
    969 	byte    b1,b2,b3,b4;
    970 
    971 	b1 = l&255;
    972 	b2 = (l>>8)&255;
    973 	b3 = (l>>16)&255;
    974 	b4 = (l>>24)&255;
    975 
    976 	return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
    977 }
    978 
    979 int	LongNoSwap (int l)
    980 {
    981 	return l;
    982 }
    983 
    984 float FloatSwap (float f)
    985 {
    986 	union
    987 	{
    988 		float	f;
    989 		byte	b[4];
    990 	} dat1, dat2;
    991 	
    992 	
    993 	dat1.f = f;
    994 	dat2.b[0] = dat1.b[3];
    995 	dat2.b[1] = dat1.b[2];
    996 	dat2.b[2] = dat1.b[1];
    997 	dat2.b[3] = dat1.b[0];
    998 	return dat2.f;
    999 }
   1000 
   1001 float FloatNoSwap (float f)
   1002 {
   1003 	return f;
   1004 }
   1005 
   1006 /*
   1007 ================
   1008 Swap_Init
   1009 ================
   1010 */
   1011 void Swap_Init (void)
   1012 {
   1013 	byte	swaptest[2] = {1,0};
   1014 
   1015 // set the byte swapping variables in a portable manner	
   1016 	if ( *(short *)swaptest == 1)
   1017 	{
   1018 		bigendien = false;
   1019 		_BigShort = ShortSwap;
   1020 		_LittleShort = ShortNoSwap;
   1021 		_BigLong = LongSwap;
   1022 		_LittleLong = LongNoSwap;
   1023 		_BigFloat = FloatSwap;
   1024 		_LittleFloat = FloatNoSwap;
   1025 	}
   1026 	else
   1027 	{
   1028 		bigendien = true;
   1029 		_BigShort = ShortNoSwap;
   1030 		_LittleShort = ShortSwap;
   1031 		_BigLong = LongNoSwap;
   1032 		_LittleLong = LongSwap;
   1033 		_BigFloat = FloatNoSwap;
   1034 		_LittleFloat = FloatSwap;
   1035 	}
   1036 
   1037 }
   1038 
   1039 
   1040 
   1041 /*
   1042 ============
   1043 va
   1044 
   1045 does a varargs printf into a temp buffer, so I don't need to have
   1046 varargs versions of all text functions.
   1047 FIXME: make this buffer size safe someday
   1048 ============
   1049 */
   1050 char	*va(char *format, ...)
   1051 {
   1052 	va_list		argptr;
   1053 	static char		string[1024];
   1054 	
   1055 	va_start (argptr, format);
   1056 	vsprintf (string, format,argptr);
   1057 	va_end (argptr);
   1058 
   1059 	return string;	
   1060 }
   1061 
   1062 
   1063 char	com_token[MAX_TOKEN_CHARS];
   1064 
   1065 /*
   1066 ==============
   1067 COM_Parse
   1068 
   1069 Parse a token out of a string
   1070 ==============
   1071 */
   1072 char *COM_Parse (char **data_p)
   1073 {
   1074 	int		c;
   1075 	int		len;
   1076 	char	*data;
   1077 
   1078 	data = *data_p;
   1079 	len = 0;
   1080 	com_token[0] = 0;
   1081 	
   1082 	if (!data)
   1083 	{
   1084 		*data_p = NULL;
   1085 		return "";
   1086 	}
   1087 		
   1088 // skip whitespace
   1089 skipwhite:
   1090 	while ( (c = *data) <= ' ')
   1091 	{
   1092 		if (c == 0)
   1093 		{
   1094 			*data_p = NULL;
   1095 			return "";
   1096 		}
   1097 		data++;
   1098 	}
   1099 	
   1100 // skip // comments
   1101 	if (c=='/' && data[1] == '/')
   1102 	{
   1103 		while (*data && *data != '\n')
   1104 			data++;
   1105 		goto skipwhite;
   1106 	}
   1107 	
   1108 
   1109 // handle quoted strings specially
   1110 	if (c == '\"')
   1111 	{
   1112 		data++;
   1113 		while (1)
   1114 		{
   1115 			c = *data++;
   1116 			if (c=='\"' || !c)
   1117 			{
   1118 				com_token[len] = 0;
   1119 				*data_p = data;
   1120 				return com_token;
   1121 			}
   1122 			if (len < MAX_TOKEN_CHARS)
   1123 			{
   1124 				com_token[len] = c;
   1125 				len++;
   1126 			}
   1127 		}
   1128 	}
   1129 
   1130 // parse a regular word
   1131 	do
   1132 	{
   1133 		if (len < MAX_TOKEN_CHARS)
   1134 		{
   1135 			com_token[len] = c;
   1136 			len++;
   1137 		}
   1138 		data++;
   1139 		c = *data;
   1140 	} while (c>32);
   1141 
   1142 	if (len == MAX_TOKEN_CHARS)
   1143 	{
   1144 //		Com_Printf ("Token exceeded %i chars, discarded.\n", MAX_TOKEN_CHARS);
   1145 		len = 0;
   1146 	}
   1147 	com_token[len] = 0;
   1148 
   1149 	*data_p = data;
   1150 	return com_token;
   1151 }
   1152 
   1153 
   1154 /*
   1155 ===============
   1156 Com_PageInMemory
   1157 
   1158 ===============
   1159 */
   1160 int	paged_total;
   1161 
   1162 void Com_PageInMemory (byte *buffer, int size)
   1163 {
   1164 	int		i;
   1165 
   1166 	for (i=size-1 ; i>0 ; i-=4096)
   1167 		paged_total += buffer[i];
   1168 }
   1169 
   1170 
   1171 
   1172 /*
   1173 ============================================================================
   1174 
   1175 					LIBRARY REPLACEMENT FUNCTIONS
   1176 
   1177 ============================================================================
   1178 */
   1179 
   1180 // FIXME: replace all Q_stricmp with Q_strcasecmp
   1181 int Q_stricmp (char *s1, char *s2)
   1182 {
   1183 #if defined(WIN32)
   1184 	return _stricmp (s1, s2);
   1185 #else
   1186 	return strcasecmp (s1, s2);
   1187 #endif
   1188 }
   1189 
   1190 
   1191 int Q_strncasecmp (char *s1, char *s2, int n)
   1192 {
   1193 	int		c1, c2;
   1194 	
   1195 	do
   1196 	{
   1197 		c1 = *s1++;
   1198 		c2 = *s2++;
   1199 
   1200 		if (!n--)
   1201 			return 0;		// strings are equal until end point
   1202 		
   1203 		if (c1 != c2)
   1204 		{
   1205 			if (c1 >= 'a' && c1 <= 'z')
   1206 				c1 -= ('a' - 'A');
   1207 			if (c2 >= 'a' && c2 <= 'z')
   1208 				c2 -= ('a' - 'A');
   1209 			if (c1 != c2)
   1210 				return -1;		// strings not equal
   1211 		}
   1212 	} while (c1);
   1213 	
   1214 	return 0;		// strings are equal
   1215 }
   1216 
   1217 int Q_strcasecmp (char *s1, char *s2)
   1218 {
   1219 	return Q_strncasecmp (s1, s2, 99999);
   1220 }
   1221 
   1222 
   1223 
   1224 void Com_sprintf (char *dest, int size, char *fmt, ...)
   1225 {
   1226 	int		len;
   1227 	va_list		argptr;
   1228 	char	bigbuffer[0x10000];
   1229 
   1230 	va_start (argptr,fmt);
   1231 	len = vsprintf (bigbuffer,fmt,argptr);
   1232 	va_end (argptr);
   1233 	if (len >= size)
   1234 		Com_Printf ("Com_sprintf: overflow of %i in %i\n", len, size);
   1235 	strncpy (dest, bigbuffer, size-1);
   1236 }
   1237 
   1238 /*
   1239 =====================================================================
   1240 
   1241   INFO STRINGS
   1242 
   1243 =====================================================================
   1244 */
   1245 
   1246 /*
   1247 ===============
   1248 Info_ValueForKey
   1249 
   1250 Searches the string for the given
   1251 key and returns the associated value, or an empty string.
   1252 ===============
   1253 */
   1254 char *Info_ValueForKey (char *s, char *key)
   1255 {
   1256 	char	pkey[512];
   1257 	static	char value[2][512];	// use two buffers so compares
   1258 								// work without stomping on each other
   1259 	static	int	valueindex;
   1260 	char	*o;
   1261 	
   1262 	valueindex ^= 1;
   1263 	if (*s == '\\')
   1264 		s++;
   1265 	while (1)
   1266 	{
   1267 		o = pkey;
   1268 		while (*s != '\\')
   1269 		{
   1270 			if (!*s)
   1271 				return "";
   1272 			*o++ = *s++;
   1273 		}
   1274 		*o = 0;
   1275 		s++;
   1276 
   1277 		o = value[valueindex];
   1278 
   1279 		while (*s != '\\' && *s)
   1280 		{
   1281 			if (!*s)
   1282 				return "";
   1283 			*o++ = *s++;
   1284 		}
   1285 		*o = 0;
   1286 
   1287 		if (!strcmp (key, pkey) )
   1288 			return value[valueindex];
   1289 
   1290 		if (!*s)
   1291 			return "";
   1292 		s++;
   1293 	}
   1294 }
   1295 
   1296 void Info_RemoveKey (char *s, char *key)
   1297 {
   1298 	char	*start;
   1299 	char	pkey[512];
   1300 	char	value[512];
   1301 	char	*o;
   1302 
   1303 	if (strstr (key, "\\"))
   1304 	{
   1305 //		Com_Printf ("Can't use a key with a \\\n");
   1306 		return;
   1307 	}
   1308 
   1309 	while (1)
   1310 	{
   1311 		start = s;
   1312 		if (*s == '\\')
   1313 			s++;
   1314 		o = pkey;
   1315 		while (*s != '\\')
   1316 		{
   1317 			if (!*s)
   1318 				return;
   1319 			*o++ = *s++;
   1320 		}
   1321 		*o = 0;
   1322 		s++;
   1323 
   1324 		o = value;
   1325 		while (*s != '\\' && *s)
   1326 		{
   1327 			if (!*s)
   1328 				return;
   1329 			*o++ = *s++;
   1330 		}
   1331 		*o = 0;
   1332 
   1333 		if (!strcmp (key, pkey) )
   1334 		{
   1335 			strcpy (start, s);	// remove this part
   1336 			return;
   1337 		}
   1338 
   1339 		if (!*s)
   1340 			return;
   1341 	}
   1342 
   1343 }
   1344 
   1345 
   1346 /*
   1347 ==================
   1348 Info_Validate
   1349 
   1350 Some characters are illegal in info strings because they
   1351 can mess up the server's parsing
   1352 ==================
   1353 */
   1354 qboolean Info_Validate (char *s)
   1355 {
   1356 	if (strstr (s, "\""))
   1357 		return false;
   1358 	if (strstr (s, ";"))
   1359 		return false;
   1360 	return true;
   1361 }
   1362 
   1363 void Info_SetValueForKey (char *s, char *key, char *value)
   1364 {
   1365 	char	newi[MAX_INFO_STRING], *v;
   1366 	int		c;
   1367 	int		maxsize = MAX_INFO_STRING;
   1368 
   1369 	if (strstr (key, "\\") || strstr (value, "\\") )
   1370 	{
   1371 		Com_Printf ("Can't use keys or values with a \\\n");
   1372 		return;
   1373 	}
   1374 
   1375 	if (strstr (key, ";") )
   1376 	{
   1377 		Com_Printf ("Can't use keys or values with a semicolon\n");
   1378 		return;
   1379 	}
   1380 
   1381 	if (strstr (key, "\"") || strstr (value, "\"") )
   1382 	{
   1383 		Com_Printf ("Can't use keys or values with a \"\n");
   1384 		return;
   1385 	}
   1386 
   1387 	if (strlen(key) > MAX_INFO_KEY-1 || strlen(value) > MAX_INFO_KEY-1)
   1388 	{
   1389 		Com_Printf ("Keys and values must be < 64 characters.\n");
   1390 		return;
   1391 	}
   1392 	Info_RemoveKey (s, key);
   1393 	if (!value || !strlen(value))
   1394 		return;
   1395 
   1396 	Com_sprintf (newi, sizeof(newi), "\\%s\\%s", key, value);
   1397 
   1398 	if (strlen(newi) + strlen(s) > maxsize)
   1399 	{
   1400 		Com_Printf ("Info string length exceeded\n");
   1401 		return;
   1402 	}
   1403 
   1404 	// only copy ascii values
   1405 	s += strlen(s);
   1406 	v = newi;
   1407 	while (*v)
   1408 	{
   1409 		c = *v++;
   1410 		c &= 127;		// strip high bits
   1411 		if (c >= 32 && c < 127)
   1412 			*s++ = c;
   1413 	}
   1414 	*s = 0;
   1415 }
   1416 
   1417 //====================================================================
   1418 
   1419