fix some bugs.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5209 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2018-02-04 13:16:25 +00:00
parent 7da299ee88
commit f1f54311f6
7 changed files with 133 additions and 71 deletions

View File

@ -1265,7 +1265,10 @@ void P_ParticleEffect_f(void)
ptype->t2 = atof(Cmd_Argv(4))/tscale;
ptype->randsmax = atoi(Cmd_Argv(6));
ptype->texsstride = atof(Cmd_Argv(7));
if (Cmd_Argc()>7)
ptype->texsstride = atof(Cmd_Argv(7));/*FIXME: divide-by-tscale missing */
else
ptype->texsstride = 1/tscale;
if (ptype->randsmax < 1 || ptype->texsstride == 0)
ptype->randsmax = 1;

View File

@ -1576,7 +1576,7 @@ void QCBUILTIN PF_R_PolygonEnd(pubprogfuncs_t *prinst, struct globalvars_s *pr_g
else
flags &= ~BEF_LINES;
if (flags != csqc_poly_flags)
if (flags != csqc_poly_flags || (cl_numstrisvert-csqc_poly_origvert) >= 32768)
{
int sv = cl_numstrisvert - nv;
cl_numstrisvert -= nv;
@ -2787,18 +2787,14 @@ static void QCBUILTIN PF_cs_SetModelIndex(pubprogfuncs_t *prinst, struct globalv
csqc_setmodel(prinst, ent, modelindex);
}
static void QCBUILTIN PF_cs_PrecacheModel(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
static int PF_cs_PrecacheModel_Internal(pubprogfuncs_t *prinst, const char *modelname, qboolean queryonly)
{
int modelindex, freei;
const char *modelname = PR_GetStringOfs(prinst, OFS_PARM0);
const char *fixedname;
int i;
if (!*modelname)
{
G_FLOAT(OFS_RETURN) = 0;
return;
}
return 0;
fixedname = Mod_FixName(modelname, csqc_world.worldmodel->publicname);
@ -2816,7 +2812,7 @@ static void QCBUILTIN PF_cs_PrecacheModel(pubprogfuncs_t *prinst, struct globalv
modelindex = CS_FindModel(modelname, &freei); //now load it
if (!modelindex)
if (!modelindex && !queryonly)
{
if (!freei)
Host_EndGame("CSQC ran out of model slots\n");
@ -2828,7 +2824,22 @@ static void QCBUILTIN PF_cs_PrecacheModel(pubprogfuncs_t *prinst, struct globalv
cl.model_csqcprecache[-freei] = Mod_ForName(fixedname, MLV_WARN);
}
G_FLOAT(OFS_RETURN) = modelindex;
return modelindex;
}
static void QCBUILTIN PF_cs_PrecacheModel (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
const char *s = PR_GetStringOfs(prinst, OFS_PARM0);
G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
PF_cs_PrecacheModel_Internal(prinst, s, false);
}
static void QCBUILTIN PF_cs_getmodelindex (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
const char *s = PR_GetStringOfs(prinst, OFS_PARM0);
qboolean queryonly = (prinst->callargc >= 2)?G_FLOAT(OFS_PARM1):false;
G_FLOAT(OFS_RETURN) = PF_cs_PrecacheModel_Internal(prinst, s, queryonly);
}
static void QCBUILTIN PF_cs_precachefile(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
@ -6043,7 +6054,7 @@ static struct {
{"localsound", PF_cl_localsound, 177},
//200
{"getmodelindex", PF_cs_PrecacheModel, 200},
{"getmodelindex", PF_cs_getmodelindex, 200},
{"externcall", PF_externcall, 201},
{"addprogs", PF_cs_addprogs, 202},
{"externvalue", PF_externvalue, 203},

View File

@ -447,7 +447,8 @@ qbyte *W_ConvertWAD3Texture(miptex_t *tex, size_t lumpsize, int *width, int *hei
}
out += 4;
}
BoostGamma(data, tex->width, tex->height);
if (!vid_hardwaregamma.value)
BoostGamma(data, tex->width, tex->height);
*usesalpha = !!alpha;
return data;
}

View File

@ -151,35 +151,51 @@ void *PRAddressableExtend(progfuncs_t *progfuncs, void *src, size_t srcsize, int
}
#define MARKER 0xF1E3E3E7u
#define MARKER_USED 0xC2A4F5A6u
#define MARKER_FREE 0xF1E3E3E7u
typedef struct
{
#ifdef _DEBUG
unsigned int marker;
#endif
unsigned int next;
unsigned int prev;
unsigned int size;
unsigned int size; //includes header size
} qcmemfreeblock_t;
typedef struct
{
unsigned int marker;
unsigned int size;
#ifdef _DEBUG
unsigned int next;
unsigned int prev;
#endif
unsigned int size; //includes header size
} qcmemusedblock_t;
static void PF_fmem_unlink(progfuncs_t *pr, qcmemfreeblock_t *p)
static void PF_fmem_unlink(progfuncs_t *progfuncs, qcmemfreeblock_t *p)
{
qcmemfreeblock_t *np;
#ifdef _DEBUG
if (p->marker != MARKER_FREE)
{
printf("PF_fmem_unlink: memory corruption\n");
PR_StackTrace(&progfuncs->funcs, false);
}
p->marker = 0;
#endif
if (p->prev)
{
np = (qcmemfreeblock_t*)(pr->funcs.stringtable + p->prev);
np = (qcmemfreeblock_t*)(progfuncs->funcs.stringtable + p->prev);
np->next = p->next;
}
else
pr->inst.mfreelist = p->next;
progfuncs->inst.mfreelist = p->next;
if (p->next)
{
np = (qcmemfreeblock_t*)(pr->funcs.stringtable + p->next);
np = (qcmemfreeblock_t*)(progfuncs->funcs.stringtable + p->next);
np->prev = p->prev;
}
}
/*
static void PR_memvalidate (progfuncs_t *progfuncs)
{
qcmemfreeblock_t *p;
@ -197,7 +213,11 @@ static void PR_memvalidate (progfuncs_t *progfuncs)
}
p = (qcmemfreeblock_t*)(progfuncs->funcs.stringtable + b);
if (p->prev != l ||
if (
#ifdef _DEBUG
p->marker != MARKER_FREE ||
#endif
p->prev != l ||
(p->next && p->next < b + p->size) ||
p->next >= prinst.addressableused ||
b + p->size >= prinst.addressableused ||
@ -211,7 +231,7 @@ static void PR_memvalidate (progfuncs_t *progfuncs)
b = p->next;
}
}
*/
static void *PDECL PR_memalloc (pubprogfuncs_t *ppf, unsigned int size)
{
progfuncs_t *progfuncs = (progfuncs_t*)ppf;
@ -221,6 +241,8 @@ static void *PDECL PR_memalloc (pubprogfuncs_t *ppf, unsigned int size)
/*round size up*/
size = (size+sizeof(qcmemusedblock_t) + 63) & ~63;
PR_memvalidate(progfuncs);
b = prinst.mfreelist;
while (b)
{
@ -249,6 +271,9 @@ static void *PDECL PR_memalloc (pubprogfuncs_t *ppf, unsigned int size)
/*make a new header just after it, with basically the same properties, and shift the important fields over*/
n = b + size;
np = (qcmemfreeblock_t*)(progfuncs->funcs.stringtable + b + size);
#ifdef _DEBUG
np->marker = MARKER_FREE;
#endif
np->prev = p->prev;
np->next = p->next;
np->size = p->size - size;
@ -289,10 +314,10 @@ static void *PDECL PR_memalloc (pubprogfuncs_t *ppf, unsigned int size)
//FIXME: merge with previous block
}
memset(ub, 0, size);
ub->marker = MARKER;
ub->marker = MARKER_USED;
ub->size = size;
// PR_memvalidate(progfuncs);
PR_memvalidate(progfuncs);
return ub+1;
}
@ -300,7 +325,7 @@ static void PDECL PR_memfree (pubprogfuncs_t *ppf, void *memptr)
{
progfuncs_t *progfuncs = (progfuncs_t*)ppf;
qcmemusedblock_t *ub;
qcmemfreeblock_t *p, *np, *pp;
qcmemfreeblock_t *b, *nb, *pb;
unsigned int pa, na; //prev addr, next addr
unsigned int size;
unsigned int ptr = memptr?((char*)memptr - progfuncs->funcs.stringtable):0;
@ -308,10 +333,12 @@ static void PDECL PR_memfree (pubprogfuncs_t *ppf, void *memptr)
/*freeing NULL is ignored*/
if (!ptr)
return;
// PR_memvalidate(progfuncs);
if (ptr < sizeof(qcmemusedblock_t) || ptr >= prinst.addressableused)
PR_memvalidate(progfuncs);
ptr -= sizeof(qcmemusedblock_t);
if (/*ptr < 0 ||*/ ptr >= prinst.addressableused)
{
if (ptr < sizeof(qcmemusedblock_t) && !*(char*)memptr)
ptr += sizeof(qcmemusedblock_t);
if (ptr < prinst.addressableused && !*(char*)memptr)
{
//the empty string is a point of contention. while we can detect it from fteqcc, its best to not give any special favours (other than nicer debugging, where possible)
//we might not actually spot it from other qccs, so warning about it where possible is probably a very good thing.
@ -323,18 +350,20 @@ static void PDECL PR_memfree (pubprogfuncs_t *ppf, void *memptr)
return;
}
//this is the used block that we're trying to free
ub = (qcmemusedblock_t*)(progfuncs->funcs.stringtable + ptr);
ub--;
ptr = (char*)ub - progfuncs->funcs.stringtable;
if (ub->marker != MARKER || ub->size <= sizeof(*ub) || ptr + ub->size > (unsigned int)prinst.addressableused)
if (ub->marker != MARKER_USED || ub->size <= sizeof(*ub) || ptr + ub->size > (unsigned int)prinst.addressableused)
{
printf("PR_memfree: pointer lacks marker - double-freed?\n");
PR_StackTrace(&progfuncs->funcs, false);
return;
}
ub->marker = 0;
ub->marker = 0; //invalidate it
size = ub->size;
ub = NULL;
//we have an (ordered) list of free blocks.
//in order to free our memory, we need to find the free block before+after the 'new' block
for (na = prinst.mfreelist, pa = 0; ;)
{
if (/*na < 0 ||*/ na >= prinst.addressableused)
@ -345,60 +374,74 @@ static void PDECL PR_memfree (pubprogfuncs_t *ppf, void *memptr)
}
if (!na || na >= ptr)
{
np = (qcmemfreeblock_t*)(progfuncs->funcs.stringtable + pa);
if (pa && pa+np->size>ptr)
{
pb = pa?(qcmemfreeblock_t*)(progfuncs->funcs.stringtable + pa):NULL;
if (pb && pa+pb->size>ptr)
{ //previous free block extends into the block that we're trying to free.
printf("PF_memfree: double free\n");
PR_StackTrace(&progfuncs->funcs, false);
return;
}
#ifdef _DEBUG
if (pb && pb->marker != MARKER_FREE)
{
printf("PF_memfree: use-after-free?\n");
PR_StackTrace(&progfuncs->funcs, false);
return;
}
#endif
nb = na?(qcmemfreeblock_t*)(progfuncs->funcs.stringtable + na):NULL;
if (nb && ptr+size > na)
{
printf("PF_memfree: block extends into neighbour\n");
PR_StackTrace(&progfuncs->funcs, false);
return;
}
#ifdef _DEBUG
if (nb && nb->marker != MARKER_FREE)
{
printf("PF_memfree: use-after-free?\n");
PR_StackTrace(&progfuncs->funcs, false);
return;
}
#endif
/*generate the free block, now we know its proper values*/
p = (qcmemfreeblock_t*)(progfuncs->funcs.stringtable + ptr);
np = na?(qcmemfreeblock_t*)(progfuncs->funcs.stringtable + na):NULL;
pp = pa?(qcmemfreeblock_t*)(progfuncs->funcs.stringtable + pa):NULL;
p->prev = pa;
p->next = na;
p->size = size;
/*update the next's previous*/
b = (qcmemfreeblock_t*)(progfuncs->funcs.stringtable + ptr);
#ifdef _DEBUG
b->marker = MARKER_FREE;
#endif
b->prev = pa;
b->next = na;
b->size = size;
if (na)
{
np->prev = ptr;
/*extend this block and kill the next if they are adjacent*/
if (p->next == ptr + size)
{
p->size += np->size;
PF_fmem_unlink(progfuncs, np);
}
}
/*update the link to get here*/
nb->prev = ptr;
if (!pa)
prinst.mfreelist = ptr;
else
pb->next = ptr;
/*extend this block and kill the next if they are adjacent*/
if (na && b->next == ptr + size)
{
pp->next = ptr;
/*we're adjacent to the previous block, so merge them by killing the newly freed region*/
if (na && pa + np->size == ptr)
{
p->size += np->size;
PF_fmem_unlink(progfuncs, np);
}
b->size += nb->size;
PF_fmem_unlink(progfuncs, nb);
}
/*we're adjacent to the previous block, so merge them by killing the newly freed region*/
if (pa && pa + pb->size == ptr)
{
pb->size += size;
PF_fmem_unlink(progfuncs, b);
}
break;
}
pa = na;
p = (qcmemfreeblock_t*)(progfuncs->funcs.stringtable + pa);
na = p->next;
b = (qcmemfreeblock_t*)(progfuncs->funcs.stringtable + pa);
na = b->next;
}
// PR_memvalidate(progfuncs);
PR_memvalidate(progfuncs);
}
void PRAddressableFlush(progfuncs_t *progfuncs, size_t totalammount)

View File

@ -5346,7 +5346,7 @@ QCC_sref_t QCC_PR_GenerateFunctionCallRef (QCC_sref_t newself, QCC_sref_t func,
if (callconvention == OP_CALL1H)
{
for (i = 0; i < parm && i < 2; i++)
if (args[i].ref.sym->generatedfor == &def_ret && args[i].ref.sym->refcount == 1)
if (args[i].ref.sym && args[i].ref.sym->generatedfor == &def_ret && args[i].ref.sym->refcount == 1)
{
QCC_FreeTemp(args[i].ref);
args[i].ref.sym = &def_ret;
@ -5427,7 +5427,7 @@ QCC_sref_t QCC_PR_GenerateFunctionCallRef (QCC_sref_t newself, QCC_sref_t func,
if (arglist[i]->readonly)
{
QCC_PR_ParseWarning(ERR_TYPEMISMATCHPARM, "Unable to write to out argument\n");
QCC_PR_ParseWarning(ERR_TYPEMISMATCHPARM, "Unable to write to read-only out argument");
continue;
}
if (parm>=MAX_PARMS)

View File

@ -7213,6 +7213,7 @@ const char *SV_CheckRejectConnection(netadr_t *adr, const char *uinfo, unsigned
}
return ret;
}
#ifndef SERVERONLY
void SV_AddDebugPolygons(void)
{
int i;
@ -7227,11 +7228,14 @@ void SV_AddDebugPolygons(void)
if (svs.clients[i].netchan.remote_address.type == NA_LOOPBACK)
pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, svs.clients[i].edict);
PR_ExecuteProgram (svprogfuncs, gfuncs.AddDebugPolygons);
if (R2D_Flush)
R2D_Flush();
#ifdef PROGS_DAT
csqc_dp_lastwas3d = false;
#endif
}
}
#endif
#ifdef HEXEN2
static void QCBUILTIN PF_h2AdvanceFrame(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)

View File

@ -1254,7 +1254,7 @@ static trace_t World_ClipMoveToEntity (world_t *w, wedict_t *ent, vec3_t eorg, v
VectorSubtract (ent->v->mins, maxs, boxmins);
VectorSubtract (ent->v->maxs, mins, boxmaxs);
if (hitcontentsmask & ((ent->v->solid == SOLID_CORPSE)?FTECONTENTS_CORPSE:FTECONTENTS_BODY))
if (hitcontentsmask & ((ent->v->solid == SOLID_CORPSE && w->usesolidcorpse)?FTECONTENTS_CORPSE:FTECONTENTS_BODY))
hitcontentsmask = FTECONTENTS_CORPSE|FTECONTENTS_BODY;
else
hitcontentsmask = 0;