X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=pr_edict.c;h=ac1f78353f203fe0d2cee719b6d89d52b9ed14b2;hb=66ae08799675241ffa3cc3bcaa211fddcd63387c;hp=4fc995070fa0e6c8db93f5efc35688c28ebac861;hpb=43ee5e136a693ac9cfb40cb03fceea7d3149104f;p=xonotic%2Fdarkplaces.git diff --git a/pr_edict.c b/pr_edict.c index 4fc99507..ac1f7835 100644 --- a/pr_edict.c +++ b/pr_edict.c @@ -68,6 +68,8 @@ cvar_t nehx18 = {0, "nehx18", "0"};cvar_t nehx19 = {0, "nehx19", "0"}; cvar_t cutscene = {0, "cutscene", "1"}; // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others)) cvar_t pr_boundscheck = {0, "pr_boundscheck", "1"}; +// LordHavoc: prints every opcode as it executes - warning: this is significant spew +cvar_t pr_traceqc = {0, "pr_traceqc", "0"}; #define MAX_FIELD_LEN 64 #define GEFV_CACHESIZE 2 @@ -182,7 +184,7 @@ Sets everything to NULL */ void ED_ClearEdict (edict_t *e) { - memset (&e->v, 0, progs->entityfields * 4); + memset (e->v, 0, progs->entityfields * 4); e->free = false; } @@ -237,16 +239,16 @@ void ED_Free (edict_t *ed) SV_UnlinkEdict (ed); // unlink from world bsp ed->free = true; - ed->v.model = 0; - ed->v.takedamage = 0; - ed->v.modelindex = 0; - ed->v.colormap = 0; - ed->v.skin = 0; - ed->v.frame = 0; - VectorClear(ed->v.origin); - VectorClear(ed->v.angles); - ed->v.nextthink = -1; - ed->v.solid = 0; + ed->v->model = 0; + ed->v->takedamage = 0; + ed->v->modelindex = 0; + ed->v->colormap = 0; + ed->v->skin = 0; + ed->v->frame = 0; + VectorClear(ed->v->origin); + VectorClear(ed->v->angles); + ed->v->nextthink = -1; + ed->v->solid = 0; ed->freetime = sv.time; } @@ -304,7 +306,7 @@ ddef_t *ED_FindField (const char *name) for (i=0 ; inumfielddefs ; i++) { def = &pr_fielddefs[i]; - if (!strcmp(pr_strings + def->s_name,name) ) + if (!strcmp(PR_GetString(def->s_name), name)) return def; } return NULL; @@ -323,7 +325,7 @@ ddef_t *ED_FindGlobal (const char *name) for (i=0 ; inumglobaldefs ; i++) { def = &pr_globaldefs[i]; - if (!strcmp(pr_strings + def->s_name,name) ) + if (!strcmp(PR_GetString(def->s_name), name)) return def; } return NULL; @@ -343,7 +345,7 @@ dfunction_t *ED_FindFunction (const char *name) for (i=0 ; inumfunctions ; i++) { func = &pr_functions[i]; - if (!strcmp(pr_strings + func->s_name,name) ) + if (!strcmp(PR_GetString(func->s_name), name)) return func; } return NULL; @@ -370,7 +372,7 @@ char *PR_ValueString (etype_t type, eval_t *val) switch (type) { case ev_string: - sprintf (line, "%s", pr_strings + val->string); + sprintf (line, "%s", PR_GetString(val->string)); break; case ev_entity: n = NoCrash_NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)); @@ -381,11 +383,11 @@ char *PR_ValueString (etype_t type, eval_t *val) break; case ev_function: f = pr_functions + val->function; - sprintf (line, "%s()", pr_strings + f->s_name); + sprintf (line, "%s()", PR_GetString(f->s_name)); break; case ev_field: def = ED_FieldAtOfs ( val->_int ); - sprintf (line, ".%s", pr_strings + def->s_name); + sprintf (line, ".%s", PR_GetString(def->s_name)); break; case ev_void: sprintf (line, "void"); @@ -430,22 +432,22 @@ char *PR_UglyValueString (etype_t type, eval_t *val) switch (type) { case ev_string: - sprintf (line, "%s", pr_strings + val->string); + sprintf (line, "%s", PR_GetString(val->string)); break; case ev_entity: sprintf (line, "%i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict))); break; case ev_function: f = pr_functions + val->function; - sprintf (line, "%s", pr_strings + f->s_name); + sprintf (line, "%s", PR_GetString(f->s_name)); break; case ev_field: def = ED_FieldAtOfs ( val->_int ); // LordHavoc: parse the string a bit to turn special characters // (like newline, specifically) into escape codes, // this fixes saving games from various mods - //sprintf (line, "%s", pr_strings + def->s_name); - s = pr_strings + def->s_name; + //sprintf (line, "%s", PR_GetString(def->s_name)); + s = PR_GetString(def->s_name); for (i = 0;i < 4095 && *s;) { if (*s == '\n') @@ -504,7 +506,7 @@ char *PR_GlobalString (int ofs) else { s = PR_ValueString (def->type, val); - sprintf (line,"%i(%s)%s", ofs, pr_strings + def->s_name, s); + sprintf (line,"%i(%s)%s", ofs, PR_GetString(def->s_name), s); } i = strlen(line); @@ -525,7 +527,7 @@ char *PR_GlobalStringNoContents (int ofs) if (!def) sprintf (line,"%i(?)", ofs); else - sprintf (line,"%i(%s)", ofs, pr_strings + def->s_name); + sprintf (line,"%i(%s)", ofs, PR_GetString(def->s_name)); i = strlen(line); for ( ; i<20 ; i++) @@ -566,11 +568,11 @@ void ED_Print (edict_t *ed) for (i=1 ; inumfielddefs ; i++) { d = &pr_fielddefs[i]; - name = pr_strings + d->s_name; + name = PR_GetString(d->s_name); if (name[strlen(name)-2] == '_') continue; // skip _x, _y, _z vars - v = (int *)((char *)&ed->v + d->ofs*4); + v = (int *)((char *)ed->v + d->ofs*4); // if the value is still all 0, skip the field type = d->type & ~DEF_SAVEGLOBAL; @@ -639,11 +641,11 @@ void ED_Write (QFile *f, edict_t *ed) for (i=1 ; inumfielddefs ; i++) { d = &pr_fielddefs[i]; - name = pr_strings + d->s_name; + name = PR_GetString(d->s_name); if (name[strlen(name)-2] == '_') continue; // skip _x, _y, _z vars - v = (int *)((char *)&ed->v + d->ofs*4); + v = (int *)((char *)ed->v + d->ofs*4); // if the value is still all 0, skip the field type = d->type & ~DEF_SAVEGLOBAL; @@ -721,11 +723,11 @@ void ED_Count (void) if (ent->free) continue; active++; - if (ent->v.solid) + if (ent->v->solid) solid++; - if (ent->v.model) + if (ent->v->model) models++; - if (ent->v.movetype == MOVETYPE_STEP) + if (ent->v->movetype == MOVETYPE_STEP) step++; } @@ -770,7 +772,7 @@ void ED_WriteGlobals (QFile *f) if (type != ev_string && type != ev_float && type != ev_entity) continue; - name = pr_strings + def->s_name; + name = PR_GetString(def->s_name); Qprintf (f,"\"%s\" ", name); Qprintf (f,"\"%s\"\n", PR_UglyValueString(type, (eval_t *)&pr_globals[def->ofs])); } @@ -873,7 +875,7 @@ qboolean ED_ParseEpair (void *base, ddef_t *key, const char *s) switch (key->type & ~DEF_SAVEGLOBAL) { case ev_string: - *(string_t *)d = ED_NewString (s) - pr_strings; + *(string_t *)d = PR_SetString(ED_NewString(s)); break; case ev_float: @@ -909,7 +911,7 @@ qboolean ED_ParseEpair (void *base, ddef_t *key, const char *s) } *(int *)d = G_INT(def->ofs); break; - + case ev_function: func = ED_FindFunction (s); if (!func) @@ -947,7 +949,7 @@ const char *ED_ParseEdict (const char *data, edict_t *ent) // clear it if (ent != sv.edicts) // hack - memset (&ent->v, 0, progs->entityfields * 4); + memset (ent->v, 0, progs->entityfields * 4); // go through all the dictionary pairs while (1) @@ -1010,7 +1012,7 @@ const char *ED_ParseEdict (const char *data, edict_t *ent) sprintf (com_token, "0 %s 0", temp); } - if (!ED_ParseEpair ((void *)&ent->v, key, com_token)) + if (!ED_ParseEpair ((void *)ent->v, key, com_token)) Host_Error ("ED_ParseEdict: parse error"); } @@ -1064,18 +1066,18 @@ void ED_LoadFromFile (const char *data) // remove things from different skill levels or deathmatch if (deathmatch.integer) { - if (((int)ent->v.spawnflags & SPAWNFLAG_NOT_DEATHMATCH)) + if (((int)ent->v->spawnflags & SPAWNFLAG_NOT_DEATHMATCH)) { ED_Free (ent); inhibit++; continue; } } - else if ((current_skill == 0 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_EASY )) - || (current_skill == 1 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_MEDIUM)) - || (current_skill >= 2 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_HARD ))) + else if ((current_skill == 0 && ((int)ent->v->spawnflags & SPAWNFLAG_NOT_EASY )) + || (current_skill == 1 && ((int)ent->v->spawnflags & SPAWNFLAG_NOT_MEDIUM)) + || (current_skill >= 2 && ((int)ent->v->spawnflags & SPAWNFLAG_NOT_HARD ))) { - ED_Free (ent); + ED_Free (ent); inhibit++; continue; } @@ -1083,7 +1085,7 @@ void ED_LoadFromFile (const char *data) // // immediately call spawn function // - if (!ent->v.classname) + if (!ent->v->classname) { Con_Printf ("No classname for:\n"); ED_Print (ent); @@ -1092,7 +1094,7 @@ void ED_LoadFromFile (const char *data) } // look for the spawn function - func = ED_FindFunction ( pr_strings + ent->v.classname ); + func = ED_FindFunction (PR_GetString(ent->v->classname)); if (!func) { @@ -1192,7 +1194,7 @@ void PR_LoadProgs (void) pr_crc = CRC_Block((qbyte *)progs, com_filesize); // byte swap the header - for (i=0 ; iversion != PROG_VERSION) @@ -1253,11 +1255,11 @@ void PR_LoadProgs (void) } // append the darkplaces fields - for (i = 0;i < DPFIELDS;i++) + for (i = 0;i < (int) DPFIELDS;i++) { pr_fielddefs[progs->numfielddefs].type = dpfields[i].type; pr_fielddefs[progs->numfielddefs].ofs = progs->entityfields; - pr_fielddefs[progs->numfielddefs].s_name = dpfields[i].string - pr_strings; + pr_fielddefs[progs->numfielddefs].s_name = PR_SetString(dpfields[i].string); if (pr_fielddefs[progs->numfielddefs].type == ev_vector) progs->entityfields += 3; else @@ -1269,8 +1271,8 @@ void PR_LoadProgs (void) ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]); // moved edict_size calculation down here, below field adding code - pr_edict_size = progs->entityfields * 4 + sizeof (edict_t) - sizeof(entvars_t); - + // LordHavoc: this no longer includes the edict_t header + pr_edict_size = progs->entityfields * 4; pr_edictareasize = pr_edict_size * MAX_EDICTS; // LordHavoc: bounds check anything static @@ -1399,10 +1401,10 @@ void PR_Fields_f (void) for (i = 1;i < progs->numfielddefs;i++) { d = &pr_fielddefs[i]; - name = pr_strings + d->s_name; + name = PR_GetString(d->s_name); if (name[strlen(name)-2] == '_') continue; // skip _x, _y, _z vars - v = (int *)((char *)&ed->v + d->ofs*4); + v = (int *)((char *)ed->v + d->ofs*4); // if the value is still all 0, skip the field for (j = 0;j < type_size[d->type & ~DEF_SAVEGLOBAL];j++) { @@ -1420,7 +1422,7 @@ void PR_Fields_f (void) for (i = 0;i < progs->numfielddefs;i++) { d = &pr_fielddefs[i]; - name = pr_strings + d->s_name; + name = PR_GetString(d->s_name); if (name[strlen(name)-2] == '_') continue; // skip _x, _y, _z vars switch(d->type & ~DEF_SAVEGLOBAL) @@ -1491,7 +1493,7 @@ void PR_Globals_f (void) return; } for (i = 0;i < progs->numglobaldefs;i++) - Con_Printf("%s\n", (pr_strings + pr_globaldefs[i].s_name)); + Con_Printf("%s\n", PR_GetString(pr_globaldefs[i].s_name)); Con_Printf("%i global variables, totalling %i bytes\n", progs->numglobals, progs->numglobals * 4); } @@ -1539,6 +1541,7 @@ void PR_Init (void) Cvar_RegisterVariable (&cutscene); // for Nehahra but useful to other mods as well // LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others)) Cvar_RegisterVariable (&pr_boundscheck); + Cvar_RegisterVariable (&pr_traceqc); progs_mempool = Mem_AllocPool("progs.dat"); edictstring_mempool = Mem_AllocPool("edict strings"); @@ -1553,22 +1556,34 @@ edict_t *EDICT_NUM_ERROR(int n) int NUM_FOR_EDICT(edict_t *e) { - int b; - - b = (qbyte *)e - (qbyte *)sv.edicts; - b = b / pr_edict_size; - - if (b < 0 || b >= sv.num_edicts) + int n; + n = e - sv.edicts; + if ((unsigned int)n >= MAX_EDICTS) Host_Error ("NUM_FOR_EDICT: bad pointer"); - return b; + return n; } int NoCrash_NUM_FOR_EDICT(edict_t *e) { - int b; + return e - sv.edicts; +} - b = (qbyte *)e - (qbyte *)sv.edicts; - b = b / pr_edict_size; - return b; +//#define EDICT_TO_PROG(e) ((qbyte *)(((edict_t *)e)->v) - (qbyte *)(sv.edictsfields)) +//#define PROG_TO_EDICT(e) (sv.edictstable[(e) / (progs->entityfields * 4)]) +int EDICT_TO_PROG(edict_t *e) +{ + int n; + n = e - sv.edicts; + if ((unsigned int)n >= (unsigned int)sv.max_edicts) + Host_Error("EDICT_TO_PROG: invalid edict %8p (number %i compared to world at %8p)\n", e, n, sv.edicts); + return n;// EXPERIMENTAL + //return (qbyte *)e->v - (qbyte *)sv.edictsfields; +} +edict_t *PROG_TO_EDICT(int n) +{ + if ((unsigned int)n >= (unsigned int)sv.max_edicts) + Host_Error("PROG_TO_EDICT: invalid edict number %i\n", n); + return sv.edictstable[n]; // EXPERIMENTAL + //return sv.edictstable[(n) / (progs->entityfields * 4)]; }