mirror of
https://github.com/nzp-team/fteqw.git
synced 2025-02-01 13:10:47 +00:00
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:
parent
7da299ee88
commit
f1f54311f6
7 changed files with 133 additions and 71 deletions
|
@ -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;
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue