1
0
Fork 0
forked from fte/fteqw

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->t2 = atof(Cmd_Argv(4))/tscale;
ptype->randsmax = atoi(Cmd_Argv(6)); 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) if (ptype->randsmax < 1 || ptype->texsstride == 0)
ptype->randsmax = 1; ptype->randsmax = 1;

View file

@ -1576,7 +1576,7 @@ void QCBUILTIN PF_R_PolygonEnd(pubprogfuncs_t *prinst, struct globalvars_s *pr_g
else else
flags &= ~BEF_LINES; flags &= ~BEF_LINES;
if (flags != csqc_poly_flags) if (flags != csqc_poly_flags || (cl_numstrisvert-csqc_poly_origvert) >= 32768)
{ {
int sv = cl_numstrisvert - nv; int sv = cl_numstrisvert - nv;
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); 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; int modelindex, freei;
const char *modelname = PR_GetStringOfs(prinst, OFS_PARM0);
const char *fixedname; const char *fixedname;
int i; int i;
if (!*modelname) if (!*modelname)
{ return 0;
G_FLOAT(OFS_RETURN) = 0;
return;
}
fixedname = Mod_FixName(modelname, csqc_world.worldmodel->publicname); 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 modelindex = CS_FindModel(modelname, &freei); //now load it
if (!modelindex) if (!modelindex && !queryonly)
{ {
if (!freei) if (!freei)
Host_EndGame("CSQC ran out of model slots\n"); 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); 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) 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}, {"localsound", PF_cl_localsound, 177},
//200 //200
{"getmodelindex", PF_cs_PrecacheModel, 200}, {"getmodelindex", PF_cs_getmodelindex, 200},
{"externcall", PF_externcall, 201}, {"externcall", PF_externcall, 201},
{"addprogs", PF_cs_addprogs, 202}, {"addprogs", PF_cs_addprogs, 202},
{"externvalue", PF_externvalue, 203}, {"externvalue", PF_externvalue, 203},

View file

@ -447,6 +447,7 @@ qbyte *W_ConvertWAD3Texture(miptex_t *tex, size_t lumpsize, int *width, int *hei
} }
out += 4; out += 4;
} }
if (!vid_hardwaregamma.value)
BoostGamma(data, tex->width, tex->height); BoostGamma(data, tex->width, tex->height);
*usesalpha = !!alpha; *usesalpha = !!alpha;
return data; 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 typedef struct
{ {
#ifdef _DEBUG
unsigned int marker;
#endif
unsigned int next; unsigned int next;
unsigned int prev; unsigned int prev;
unsigned int size; unsigned int size; //includes header size
} qcmemfreeblock_t; } qcmemfreeblock_t;
typedef struct typedef struct
{ {
unsigned int marker; unsigned int marker;
unsigned int size; #ifdef _DEBUG
unsigned int next;
unsigned int prev;
#endif
unsigned int size; //includes header size
} qcmemusedblock_t; } 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; 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) if (p->prev)
{ {
np = (qcmemfreeblock_t*)(pr->funcs.stringtable + p->prev); np = (qcmemfreeblock_t*)(progfuncs->funcs.stringtable + p->prev);
np->next = p->next; np->next = p->next;
} }
else else
pr->inst.mfreelist = p->next; progfuncs->inst.mfreelist = p->next;
if (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; np->prev = p->prev;
} }
} }
/*
static void PR_memvalidate (progfuncs_t *progfuncs) static void PR_memvalidate (progfuncs_t *progfuncs)
{ {
qcmemfreeblock_t *p; qcmemfreeblock_t *p;
@ -197,7 +213,11 @@ static void PR_memvalidate (progfuncs_t *progfuncs)
} }
p = (qcmemfreeblock_t*)(progfuncs->funcs.stringtable + b); 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 && p->next < b + p->size) ||
p->next >= prinst.addressableused || p->next >= prinst.addressableused ||
b + p->size >= prinst.addressableused || b + p->size >= prinst.addressableused ||
@ -211,7 +231,7 @@ static void PR_memvalidate (progfuncs_t *progfuncs)
b = p->next; b = p->next;
} }
} }
*/
static void *PDECL PR_memalloc (pubprogfuncs_t *ppf, unsigned int size) static void *PDECL PR_memalloc (pubprogfuncs_t *ppf, unsigned int size)
{ {
progfuncs_t *progfuncs = (progfuncs_t*)ppf; progfuncs_t *progfuncs = (progfuncs_t*)ppf;
@ -221,6 +241,8 @@ static void *PDECL PR_memalloc (pubprogfuncs_t *ppf, unsigned int size)
/*round size up*/ /*round size up*/
size = (size+sizeof(qcmemusedblock_t) + 63) & ~63; size = (size+sizeof(qcmemusedblock_t) + 63) & ~63;
PR_memvalidate(progfuncs);
b = prinst.mfreelist; b = prinst.mfreelist;
while (b) 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*/ /*make a new header just after it, with basically the same properties, and shift the important fields over*/
n = b + size; n = b + size;
np = (qcmemfreeblock_t*)(progfuncs->funcs.stringtable + b + size); np = (qcmemfreeblock_t*)(progfuncs->funcs.stringtable + b + size);
#ifdef _DEBUG
np->marker = MARKER_FREE;
#endif
np->prev = p->prev; np->prev = p->prev;
np->next = p->next; np->next = p->next;
np->size = p->size - size; 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 //FIXME: merge with previous block
} }
memset(ub, 0, size); memset(ub, 0, size);
ub->marker = MARKER; ub->marker = MARKER_USED;
ub->size = size; ub->size = size;
// PR_memvalidate(progfuncs); PR_memvalidate(progfuncs);
return ub+1; return ub+1;
} }
@ -300,7 +325,7 @@ static void PDECL PR_memfree (pubprogfuncs_t *ppf, void *memptr)
{ {
progfuncs_t *progfuncs = (progfuncs_t*)ppf; progfuncs_t *progfuncs = (progfuncs_t*)ppf;
qcmemusedblock_t *ub; qcmemusedblock_t *ub;
qcmemfreeblock_t *p, *np, *pp; qcmemfreeblock_t *b, *nb, *pb;
unsigned int pa, na; //prev addr, next addr unsigned int pa, na; //prev addr, next addr
unsigned int size; unsigned int size;
unsigned int ptr = memptr?((char*)memptr - progfuncs->funcs.stringtable):0; 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*/ /*freeing NULL is ignored*/
if (!ptr) if (!ptr)
return; return;
// PR_memvalidate(progfuncs); PR_memvalidate(progfuncs);
if (ptr < sizeof(qcmemusedblock_t) || ptr >= prinst.addressableused) 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) //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. //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; return;
} }
//this is the used block that we're trying to free
ub = (qcmemusedblock_t*)(progfuncs->funcs.stringtable + ptr); ub = (qcmemusedblock_t*)(progfuncs->funcs.stringtable + ptr);
ub--; if (ub->marker != MARKER_USED || ub->size <= sizeof(*ub) || ptr + ub->size > (unsigned int)prinst.addressableused)
ptr = (char*)ub - progfuncs->funcs.stringtable;
if (ub->marker != MARKER || ub->size <= sizeof(*ub) || ptr + ub->size > (unsigned int)prinst.addressableused)
{ {
printf("PR_memfree: pointer lacks marker - double-freed?\n"); printf("PR_memfree: pointer lacks marker - double-freed?\n");
PR_StackTrace(&progfuncs->funcs, false); PR_StackTrace(&progfuncs->funcs, false);
return; return;
} }
ub->marker = 0; ub->marker = 0; //invalidate it
size = ub->size; 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; ;) for (na = prinst.mfreelist, pa = 0; ;)
{ {
if (/*na < 0 ||*/ na >= prinst.addressableused) if (/*na < 0 ||*/ na >= prinst.addressableused)
@ -345,60 +374,74 @@ static void PDECL PR_memfree (pubprogfuncs_t *ppf, void *memptr)
} }
if (!na || na >= ptr) if (!na || na >= ptr)
{ {
np = (qcmemfreeblock_t*)(progfuncs->funcs.stringtable + pa); pb = pa?(qcmemfreeblock_t*)(progfuncs->funcs.stringtable + pa):NULL;
if (pa && pa+np->size>ptr) 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"); printf("PF_memfree: double free\n");
PR_StackTrace(&progfuncs->funcs, false); PR_StackTrace(&progfuncs->funcs, false);
return; 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*/ /*generate the free block, now we know its proper values*/
p = (qcmemfreeblock_t*)(progfuncs->funcs.stringtable + ptr); b = (qcmemfreeblock_t*)(progfuncs->funcs.stringtable + ptr);
np = na?(qcmemfreeblock_t*)(progfuncs->funcs.stringtable + na):NULL; #ifdef _DEBUG
pp = pa?(qcmemfreeblock_t*)(progfuncs->funcs.stringtable + pa):NULL; b->marker = MARKER_FREE;
#endif
p->prev = pa; b->prev = pa;
p->next = na; b->next = na;
p->size = size; b->size = size;
/*update the next's previous*/
if (na) if (na)
{ nb->prev = ptr;
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*/
if (!pa) if (!pa)
prinst.mfreelist = ptr; prinst.mfreelist = ptr;
else else
{ pb->next = ptr;
pp->next = ptr;
/*we're adjacent to the previous block, so merge them by killing the newly freed region*/ /*extend this block and kill the next if they are adjacent*/
if (na && pa + np->size == ptr) if (na && b->next == ptr + size)
{ {
p->size += np->size; b->size += nb->size;
PF_fmem_unlink(progfuncs, np); 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; break;
} }
pa = na; pa = na;
p = (qcmemfreeblock_t*)(progfuncs->funcs.stringtable + pa); b = (qcmemfreeblock_t*)(progfuncs->funcs.stringtable + pa);
na = p->next; na = b->next;
} }
// PR_memvalidate(progfuncs); PR_memvalidate(progfuncs);
} }
void PRAddressableFlush(progfuncs_t *progfuncs, size_t totalammount) 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) if (callconvention == OP_CALL1H)
{ {
for (i = 0; i < parm && i < 2; i++) 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); QCC_FreeTemp(args[i].ref);
args[i].ref.sym = &def_ret; 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) 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; continue;
} }
if (parm>=MAX_PARMS) if (parm>=MAX_PARMS)

View file

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