#define TABULA_IMPLEMENTATION
#include "q_shared.h"
#define DEG2RAD(a) (a * M_PI) / 180.0F
vec3_t vec3_origin = {0, 0, 0};
void RotatePointAroundVector(vec3_t dst, const vec3_t dir, const vec3_t point, float degrees) {
float m[3][3];
float im[3][3];
float zrot[3][3];
float tmpmat[3][3];
float rot[3][3];
int i;
vec3_t vr, vup, vf;
vf[0] = dir[0];
vf[1] = dir[1];
vf[2] = dir[2];
PerpendicularVector(vr, dir);
CrossProduct(vr, vf, vup);
m[0][0] = vr[0];
m[1][0] = vr[1];
m[2][0] = vr[2];
m[0][1] = vup[0];
m[1][1] = vup[1];
m[2][1] = vup[2];
m[0][2] = vf[0];
m[1][2] = vf[1];
m[2][2] = vf[2];
memcpy(im, m, sizeof(im));
im[0][1] = m[1][0];
im[0][2] = m[2][0];
im[1][0] = m[0][1];
im[1][2] = m[2][1];
im[2][0] = m[0][2];
im[2][1] = m[1][2];
memset(zrot, 0, sizeof(zrot));
zrot[0][0] = zrot[1][1] = zrot[2][2] = 1.0F;
zrot[0][0] = cos(DEG2RAD(degrees));
zrot[0][1] = sin(DEG2RAD(degrees));
zrot[1][0] = -sin(DEG2RAD(degrees));
zrot[1][1] = cos(DEG2RAD(degrees));
R_ConcatRotations(m, zrot, tmpmat);
R_ConcatRotations(tmpmat, im, rot);
for(i = 0; i < 3; i++) {
dst[i] = rot[i][0] * point[0] + rot[i][1] * point[1] + rot[i][2] * point[2];
}
}
void AngleVectors(vec3_t angles, vec3_t forward, vec3_t right, vec3_t up) {
float angle;
static float sr, sp, sy, cr, cp, cy;
angle = angles[YAW] * (M_PI * 2 / 360);
sy = sin(angle);
cy = cos(angle);
angle = angles[PITCH] * (M_PI * 2 / 360);
sp = sin(angle);
cp = cos(angle);
angle = angles[ROLL] * (M_PI * 2 / 360);
sr = sin(angle);
cr = cos(angle);
if(forward) {
forward[0] = cp * cy;
forward[1] = cp * sy;
forward[2] = -sp;
}
if(right) {
right[0] = (-1 * sr * sp * cy + -1 * cr * -sy);
right[1] = (-1 * sr * sp * sy + -1 * cr * cy);
right[2] = -1 * sr * cp;
}
if(up) {
up[0] = (cr * sp * cy + -sr * -sy);
up[1] = (cr * sp * sy + -sr * cy);
up[2] = cr * cp;
}
}
void ProjectPointOnPlane(vec3_t dst, const vec3_t p, const vec3_t normal) {
float d;
vec3_t n;
float inv_denom;
inv_denom = 1.0F / DotProduct(normal, normal);
d = DotProduct(normal, p) * inv_denom;
n[0] = normal[0] * inv_denom;
n[1] = normal[1] * inv_denom;
n[2] = normal[2] * inv_denom;
dst[0] = p[0] - d * n[0];
dst[1] = p[1] - d * n[1];
dst[2] = p[2] - d * n[2];
}
void PerpendicularVector(vec3_t dst, const vec3_t src) {
int pos;
int i;
float minelem = 1.0F;
vec3_t tempvec;
for(pos = 0, i = 0; i < 3; i++) {
if(fabs(src[i]) < minelem) {
pos = i;
minelem = fabs(src[i]);
}
}
tempvec[0] = tempvec[1] = tempvec[2] = 0.0F;
tempvec[pos] = 1.0F;
ProjectPointOnPlane(dst, tempvec, src);
VectorNormalize(dst);
}
void R_ConcatRotations(float in1[3][3], float in2[3][3], float out[3][3]) {
out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0];
out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1];
out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2];
out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0];
out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1];
out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2];
out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + in1[2][2] * in2[2][0];
out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1];
out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2];
}
void R_ConcatTransforms(float in1[3][4], float in2[3][4], float out[3][4]) {
out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0];
out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1];
out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2];
out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] + in1[0][2] * in2[2][3] + in1[0][3];
out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0];
out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1];
out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2];
out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] + in1[1][2] * in2[2][3] + in1[1][3];
out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + in1[2][2] * in2[2][0];
out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1];
out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2];
out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + in1[2][2] * in2[2][3] + in1[2][3];
}
float Q_fabs(float f) {
#if 0#else
int tmp = *(int *)&f;
tmp &= 0x7FFFFFFF;
return *(float *)&tmp;
#endif
}
#if defined _M_IX86 && !defined C_ONLY
#pragma warning(disable : 4035)
__declspec(naked) long Q_ftol(float f) {
static int tmp;
__asm fld dword ptr[esp + 4] __asm fistp tmp __asm mov eax, tmp __asm ret
}
#pragma warning(default : 4035)
#endif
float LerpAngle(float a2, float a1, float frac) {
if(a1 - a2 > 180)
a1 -= 360;
if(a1 - a2 < -180)
a1 += 360;
return a2 + frac * (a1 - a2);
}
float anglemod(float a) {
#if 0#endif
a = (360.0 / 65536) * ((int)(a * (65536 / 360.0)) & 65535);
return a;
}
int i;
vec3_t corners[2];
int BoxOnPlaneSide2(vec3_t emins, vec3_t emaxs, struct cplane_s *p) {
int i;
float dist1, dist2;
int sides;
vec3_t corners[2];
for(i = 0; i < 3; i++) {
if(p->normal[i] < 0) {
corners[0][i] = emins[i];
corners[1][i] = emaxs[i];
} else {
corners[1][i] = emins[i];
corners[0][i] = emaxs[i];
}
}
dist1 = DotProduct(p->normal, corners[0]) - p->dist;
dist2 = DotProduct(p->normal, corners[1]) - p->dist;
sides = 0;
if(dist1 >= 0)
sides = 1;
if(dist2 < 0)
sides |= 2;
return sides;
}
#if !id386 || defined __linux__
int BoxOnPlaneSide(vec3_t emins, vec3_t emaxs, struct cplane_s *p) {
float dist1, dist2;
int sides;
if(p->type < 3) {
if(p->dist <= emins[p->type])
return 1;
if(p->dist >= emaxs[p->type])
return 2;
return 3;
}
switch(p->signbits) {
case 0:
dist1 = p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2];
dist2 = p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2];
break;
case 1:
dist1 = p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2];
dist2 = p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2];
break;
case 2:
dist1 = p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2];
dist2 = p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2];
break;
case 3:
dist1 = p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2];
dist2 = p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2];
break;
case 4:
dist1 = p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2];
dist2 = p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2];
break;
case 5:
dist1 = p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2];
dist2 = p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2];
break;
case 6:
dist1 = p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2];
dist2 = p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2];
break;
case 7:
dist1 = p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2];
dist2 = p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2];
break;
default:
dist1 = dist2 = 0; assert(0);
break;
}
sides = 0;
if(dist1 >= p->dist)
sides = 1;
if(dist2 < p->dist)
sides |= 2;
assert(sides != 0);
return sides;
}
#else
#pragma warning(disable : 4035)
__declspec(naked) int BoxOnPlaneSide(vec3_t emins, vec3_t emaxs, struct cplane_s *p) {
static int bops_initialized;
static int Ljmptab[8];
__asm {
push ebx
cmp bops_initialized, 1
je initialized
mov bops_initialized, 1
mov Ljmptab[0*4], offset Lcase0
mov Ljmptab[1*4], offset Lcase1
mov Ljmptab[2*4], offset Lcase2
mov Ljmptab[3*4], offset Lcase3
mov Ljmptab[4*4], offset Lcase4
mov Ljmptab[5*4], offset Lcase5
mov Ljmptab[6*4], offset Lcase6
mov Ljmptab[7*4], offset Lcase7
initialized:
mov edx,ds:dword ptr[4+12+esp]
mov ecx,ds:dword ptr[4+4+esp]
xor eax,eax
mov ebx,ds:dword ptr[4+8+esp]
mov al,ds:byte ptr[17+edx]
cmp al,8
jge Lerror
fld ds:dword ptr[0+edx]
fld st(0)
jmp dword ptr[Ljmptab+eax*4]
Lcase0:
fmul ds:dword ptr[ebx]
fld ds:dword ptr[0+4+edx]
fxch st(2)
fmul ds:dword ptr[ecx]
fxch st(2)
fld st(0)
fmul ds:dword ptr[4+ebx]
fld ds:dword ptr[0+8+edx]
fxch st(2)
fmul ds:dword ptr[4+ecx]
fxch st(2)
fld st(0)
fmul ds:dword ptr[8+ebx]
fxch st(5)
faddp st(3),st(0)
fmul ds:dword ptr[8+ecx]
fxch st(1)
faddp st(3),st(0)
fxch st(3)
faddp st(2),st(0)
jmp LSetSides
Lcase1:
fmul ds:dword ptr[ecx]
fld ds:dword ptr[0+4+edx]
fxch st(2)
fmul ds:dword ptr[ebx]
fxch st(2)
fld st(0)
fmul ds:dword ptr[4+ebx]
fld ds:dword ptr[0+8+edx]
fxch st(2)
fmul ds:dword ptr[4+ecx]
fxch st(2)
fld st(0)
fmul ds:dword ptr[8+ebx]
fxch st(5)
faddp st(3),st(0)
fmul ds:dword ptr[8+ecx]
fxch st(1)
faddp st(3),st(0)
fxch st(3)
faddp st(2),st(0)
jmp LSetSides
Lcase2:
fmul ds:dword ptr[ebx]
fld ds:dword ptr[0+4+edx]
fxch st(2)
fmul ds:dword ptr[ecx]
fxch st(2)
fld st(0)
fmul ds:dword ptr[4+ecx]
fld ds:dword ptr[0+8+edx]
fxch st(2)
fmul ds:dword ptr[4+ebx]
fxch st(2)
fld st(0)
fmul ds:dword ptr[8+ebx]
fxch st(5)
faddp st(3),st(0)
fmul ds:dword ptr[8+ecx]
fxch st(1)
faddp st(3),st(0)
fxch st(3)
faddp st(2),st(0)
jmp LSetSides
Lcase3:
fmul ds:dword ptr[ecx]
fld ds:dword ptr[0+4+edx]
fxch st(2)
fmul ds:dword ptr[ebx]
fxch st(2)
fld st(0)
fmul ds:dword ptr[4+ecx]
fld ds:dword ptr[0+8+edx]
fxch st(2)
fmul ds:dword ptr[4+ebx]
fxch st(2)
fld st(0)
fmul ds:dword ptr[8+ebx]
fxch st(5)
faddp st(3),st(0)
fmul ds:dword ptr[8+ecx]
fxch st(1)
faddp st(3),st(0)
fxch st(3)
faddp st(2),st(0)
jmp LSetSides
Lcase4:
fmul ds:dword ptr[ebx]
fld ds:dword ptr[0+4+edx]
fxch st(2)
fmul ds:dword ptr[ecx]
fxch st(2)
fld st(0)
fmul ds:dword ptr[4+ebx]
fld ds:dword ptr[0+8+edx]
fxch st(2)
fmul ds:dword ptr[4+ecx]
fxch st(2)
fld st(0)
fmul ds:dword ptr[8+ecx]
fxch st(5)
faddp st(3),st(0)
fmul ds:dword ptr[8+ebx]
fxch st(1)
faddp st(3),st(0)
fxch st(3)
faddp st(2),st(0)
jmp LSetSides
Lcase5:
fmul ds:dword ptr[ecx]
fld ds:dword ptr[0+4+edx]
fxch st(2)
fmul ds:dword ptr[ebx]
fxch st(2)
fld st(0)
fmul ds:dword ptr[4+ebx]
fld ds:dword ptr[0+8+edx]
fxch st(2)
fmul ds:dword ptr[4+ecx]
fxch st(2)
fld st(0)
fmul ds:dword ptr[8+ecx]
fxch st(5)
faddp st(3),st(0)
fmul ds:dword ptr[8+ebx]
fxch st(1)
faddp st(3),st(0)
fxch st(3)
faddp st(2),st(0)
jmp LSetSides
Lcase6:
fmul ds:dword ptr[ebx]
fld ds:dword ptr[0+4+edx]
fxch st(2)
fmul ds:dword ptr[ecx]
fxch st(2)
fld st(0)
fmul ds:dword ptr[4+ecx]
fld ds:dword ptr[0+8+edx]
fxch st(2)
fmul ds:dword ptr[4+ebx]
fxch st(2)
fld st(0)
fmul ds:dword ptr[8+ecx]
fxch st(5)
faddp st(3),st(0)
fmul ds:dword ptr[8+ebx]
fxch st(1)
faddp st(3),st(0)
fxch st(3)
faddp st(2),st(0)
jmp LSetSides
Lcase7:
fmul ds:dword ptr[ecx]
fld ds:dword ptr[0+4+edx]
fxch st(2)
fmul ds:dword ptr[ebx]
fxch st(2)
fld st(0)
fmul ds:dword ptr[4+ecx]
fld ds:dword ptr[0+8+edx]
fxch st(2)
fmul ds:dword ptr[4+ebx]
fxch st(2)
fld st(0)
fmul ds:dword ptr[8+ecx]
fxch st(5)
faddp st(3),st(0)
fmul ds:dword ptr[8+ebx]
fxch st(1)
faddp st(3),st(0)
fxch st(3)
faddp st(2),st(0)
LSetSides:
faddp st(2),st(0)
fcomp ds:dword ptr[12+edx]
xor ecx,ecx
fnstsw ax
fcomp ds:dword ptr[12+edx]
and ah,1
xor ah,1
add cl,ah
fnstsw ax
and ah,1
add ah,ah
add cl,ah
pop ebx
mov eax,ecx
ret
Lerror:
int 3
}
}
#pragma warning(default : 4035)
#endif
void ClearBounds(vec3_t mins, vec3_t maxs) {
mins[0] = mins[1] = mins[2] = 99999;
maxs[0] = maxs[1] = maxs[2] = -99999;
}
void AddPointToBounds(vec3_t v, vec3_t mins, vec3_t maxs) {
int i;
vec_t val;
for(i = 0; i < 3; i++) {
val = v[i];
if(val < mins[i])
mins[i] = val;
if(val > maxs[i])
maxs[i] = val;
}
}
int VectorCompare(vec3_t v1, vec3_t v2) {
if(v1[0] != v2[0] || v1[1] != v2[1] || v1[2] != v2[2])
return 0;
return 1;
}
vec_t VectorNormalize(vec3_t v) {
float length, ilength;
length = v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
length = sqrt(length);
if(length) {
ilength = 1 / length;
v[0] *= ilength;
v[1] *= ilength;
v[2] *= ilength;
}
return length;
}
vec_t VectorNormalize2(vec3_t v, vec3_t out) {
float length, ilength;
length = v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
length = sqrt(length);
if(length) {
ilength = 1 / length;
out[0] = v[0] * ilength;
out[1] = v[1] * ilength;
out[2] = v[2] * ilength;
}
return length;
}
void VectorMA(vec3_t veca, float scale, vec3_t vecb, vec3_t vecc) {
vecc[0] = veca[0] + scale * vecb[0];
vecc[1] = veca[1] + scale * vecb[1];
vecc[2] = veca[2] + scale * vecb[2];
}
vec_t _DotProduct(vec3_t v1, vec3_t v2) { return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]; }
void _VectorSubtract(vec3_t veca, vec3_t vecb, vec3_t out) {
out[0] = veca[0] - vecb[0];
out[1] = veca[1] - vecb[1];
out[2] = veca[2] - vecb[2];
}
void _VectorAdd(vec3_t veca, vec3_t vecb, vec3_t out) {
out[0] = veca[0] + vecb[0];
out[1] = veca[1] + vecb[1];
out[2] = veca[2] + vecb[2];
}
void _VectorCopy(vec3_t in, vec3_t out) {
out[0] = in[0];
out[1] = in[1];
out[2] = in[2];
}
void CrossProduct(vec3_t v1, vec3_t v2, vec3_t cross) {
cross[0] = v1[1] * v2[2] - v1[2] * v2[1];
cross[1] = v1[2] * v2[0] - v1[0] * v2[2];
cross[2] = v1[0] * v2[1] - v1[1] * v2[0];
}
double sqrt(double x);
vec_t VectorLength(vec3_t v) {
int i;
float length;
length = 0;
for(i = 0; i < 3; i++)
length += v[i] * v[i];
length = sqrt(length);
return length;
}
void VectorInverse(vec3_t v) {
v[0] = -v[0];
v[1] = -v[1];
v[2] = -v[2];
}
void VectorScale(vec3_t in, vec_t scale, vec3_t out) {
out[0] = in[0] * scale;
out[1] = in[1] * scale;
out[2] = in[2] * scale;
}
int Q_log2(int val) {
int answer = 0;
while(val >>= 1)
answer++;
return answer;
}
char *COM_SkipPath(char *pathname) {
char *last;
last = pathname;
while(*pathname) {
if(*pathname == '/')
last = pathname + 1;
pathname++;
}
return last;
}
void COM_StripExtension(char *in, char *out) {
while(*in && *in != '.')
*out++ = *in++;
*out = 0;
}
char *COM_FileExtension(char *in) {
static char exten[8];
int i;
while(*in && *in != '.')
in++;
if(!*in)
return "";
in++;
for(i = 0; i < 7 && *in; i++, in++)
exten[i] = *in;
exten[i] = 0;
return exten;
}
void COM_FileBase(char *in, char *out) {
char *s, *s2;
s = in + strlen(in) - 1;
while(s != in && *s != '.')
s--;
for(s2 = s; s2 != in && *s2 != '/'; s2--)
;
if(s - s2 < 2)
out[0] = 0;
else {
s--;
strncpy(out, s2 + 1, s - s2);
out[s - s2] = 0;
}
}
void COM_FilePath(char *in, char *out) {
char *s;
s = in + strlen(in) - 1;
while(s != in && *s != '/')
s--;
strncpy(out, in, s - in);
out[s - in] = 0;
}
void COM_DefaultExtension(char *path, char *extension) {
char *src;
src = path + strlen(path) - 1;
while(*src != '/' && src != path) {
if(*src == '.')
return; src--;
}
strcat(path, extension);
}
#if 0#endif
void Swap_Init(void) {
#if 0#endif
}
char *va(char *format, ...) {
va_list argptr;
static char string[1024];
va_start(argptr, format);
vsprintf(string, sizeof(string), format, argptr);
va_end(argptr);
return string;
}
char com_token[MAX_TOKEN_CHARS];
char *COM_Parse(const char **data_p) {
int c;
int len;
const char *data;
data = *data_p;
len = 0;
com_token[0] = 0;
if(!data) {
*data_p = NULL;
return "";
}
skipwhite:
while((c = *data) <= ' ') {
if(c == 0) {
*data_p = NULL;
return "";
}
data++;
}
if(c == '/' && data[1] == '/') {
while(*data && *data != '\n')
data++;
goto skipwhite;
}
if(c == '\"') {
data++;
while(1) {
c = *data++;
if(c == '\"' || !c) {
com_token[len] = 0;
*data_p = data;
return com_token;
}
if(len < MAX_TOKEN_CHARS) {
com_token[len] = c;
len++;
}
}
}
do {
if(len < MAX_TOKEN_CHARS) {
com_token[len] = c;
len++;
}
data++;
c = *data;
} while(c > 32);
if(len == MAX_TOKEN_CHARS) {
len = 0;
}
com_token[len] = 0;
*data_p = data;
return com_token;
}
int paged_total;
void Com_PageInMemory(byte *buffer, int size) {
int i;
for(i = size - 1; i > 0; i -= 4096)
paged_total += buffer[i];
}
int Q_stricmp(const char *s1, const char *s2) {
#if defined(WIN32)
return _stricmp(s1, s2);
#else
return strcasecmp(s1, s2);
#endif
}
int Q_strncasecmp(const char *s1, const char *s2, int n) {
int c1, c2;
do {
c1 = *s1++;
c2 = *s2++;
if(!n--)
return 0;
if(c1 != c2) {
if(c1 >= 'a' && c1 <= 'z')
c1 -= ('a' - 'A');
if(c2 >= 'a' && c2 <= 'z')
c2 -= ('a' - 'A');
if(c1 != c2)
return -1; }
} while(c1);
return 0; }
int Q_strcasecmp(const char *s1, const char *s2) { return Q_strncasecmp(s1, s2, 99999); }
void Com_sprintf(char *dest, int size, const char *fmt, ...) {
int len;
va_list argptr;
char bigbuffer[0x10000];
va_start(argptr, fmt);
len = vsprintf(bigbuffer, sizeof(bigbuffer), fmt, argptr);
va_end(argptr);
if(len >= size)
Com_Printf("Com_sprintf: overflow of %i in %i\n", len, size);
strncpy(dest, bigbuffer, size - 1);
}
char *Info_ValueForKey(char *s, char *key) {
char pkey[512];
static char value[2][512]; static int valueindex;
char *o;
valueindex ^= 1;
if(*s == '\\')
s++;
while(1) {
o = pkey;
while(*s != '\\') {
if(!*s)
return "";
*o++ = *s++;
}
*o = 0;
s++;
o = value[valueindex];
while(*s != '\\' && *s) {
if(!*s)
return "";
*o++ = *s++;
}
*o = 0;
if(!strcmp(key, pkey))
return value[valueindex];
if(!*s)
return "";
s++;
}
}
void Info_RemoveKey(char *s, char *key) {
char *start;
char pkey[512];
char value[512];
char *o;
if(strstr(key, "\\")) {
return;
}
while(1) {
start = s;
if(*s == '\\')
s++;
o = pkey;
while(*s != '\\') {
if(!*s)
return;
*o++ = *s++;
}
*o = 0;
s++;
o = value;
while(*s != '\\' && *s) {
if(!*s)
return;
*o++ = *s++;
}
*o = 0;
if(!strcmp(key, pkey)) {
strcpy(start, s); return;
}
if(!*s)
return;
}
}
bool Info_Validate(char *s) {
if(strstr(s, "\""))
return false;
if(strstr(s, ";"))
return false;
return true;
}
void Info_SetValueForKey(char *s, char *key, char *value) {
char newi[MAX_INFO_STRING], *v;
int c;
int maxsize = MAX_INFO_STRING;
if(strstr(key, "\\") || strstr(value, "\\")) {
Com_Printf("Can't use keys or values with a \\\n");
return;
}
if(strstr(key, ";")) {
Com_Printf("Can't use keys or values with a semicolon\n");
return;
}
if(strstr(key, "\"") || strstr(value, "\"")) {
Com_Printf("Can't use keys or values with a \"\n");
return;
}
if(strlen(key) > MAX_INFO_KEY - 1 || strlen(value) > MAX_INFO_KEY - 1) {
Com_Printf("Keys and values must be < 64 characters.\n");
return;
}
Info_RemoveKey(s, key);
if(!value || !strlen(value))
return;
Com_sprintf(newi, sizeof(newi), "\\%s\\%s", key, value);
if(strlen(newi) + strlen(s) > maxsize) {
Com_Printf("Info string length exceeded\n");
return;
}
s += strlen(s);
v = newi;
while(*v) {
c = *v++;
c &= 127; if(c >= 32 && c < 127)
*s++ = c;
}
*s = 0;
}