prvm_vec_t *edictsfields;
void *edictprivate;
+ struct {
+ prvm_edict_t *ed;
+ prvm_vec_t *fields;
+ void *priv;
+ } edicts2;
+
// size of the engine private struct
int edictprivate_size; // [INIT]
qboolean PRVM_ED_CanAlloc(prvm_prog_t *prog, prvm_edict_t *e);
prvm_edict_t *PRVM_ED_Alloc(prvm_prog_t *prog);
+prvm_edict_t *PRVM_ED_Alloc2(prvm_prog_t *prog);
void PRVM_ED_Free(prvm_prog_t *prog, prvm_edict_t *ed);
void PRVM_ED_ClearEdict(prvm_prog_t *prog, prvm_edict_t *e);
unsigned int PRVM_EDICT_NUM_ERROR(prvm_prog_t *prog, unsigned int n, const char *filename, int fileline);
#define PRVM_EDICT(n) (((unsigned)(n) < (unsigned int)prog->max_edicts) ? (unsigned int)(n) : PRVM_EDICT_NUM_ERROR(prog, (unsigned int)(n), __FILE__, __LINE__))
-#define PRVM_EDICT_NUM(n) (prog->edicts + PRVM_EDICT(n))
+#define PRVM_EDICT_NUM(n) (n >= 0 ? (prog->edicts + PRVM_EDICT(n)) : (prog->edicts2.ed + (-(n) - 1)))
+
+#define SPAWN2_LIMIT (8192)
//int NUM_FOR_EDICT_ERROR(prvm_edict_t *e);
-#define PRVM_NUM_FOR_EDICT(e) ((int)((prvm_edict_t *)(e) - prog->edicts))
+#define PRVM_NUM_FOR_EDICT(e) \
+ (((int)((prvm_edict_t *)(e) - prog->edicts2.ed) >= 0 \
+ && (int)((prvm_edict_t *)(e) - prog->edicts2.ed) < SPAWN2_LIMIT) \
+ ? (int)((prvm_edict_t *)(e) - prog->edicts2.ed) \
+ : (int)((prvm_edict_t *)(e) - prog->edicts))
//int PRVM_NUM_FOR_EDICT(prvm_edict_t *e);
#define PRVM_NEXT_EDICT(e) ((e) + 1)
prog->edicts[i].priv.required = (prvm_edict_private_t *)((unsigned char *)prog->edictprivate + i * prog->edictprivate_size);
prog->edicts[i].fields.fp = prog->edictsfields + i * prog->entityfields;
}
+
+ // pure entities
+ {
+ prog->edicts2.ed = (prvm_edict_t *)Mem_Alloc(prog->progs_mempool, SPAWN2_LIMIT * sizeof(prvm_edict_t));
+ prog->edicts2.priv = Mem_Alloc(prog->progs_mempool, SPAWN2_LIMIT * prog->edictprivate_size);
+ prog->edicts2.fields = (prvm_vec_t *)Mem_Alloc(prog->progs_mempool, SPAWN2_LIMIT * prog->entityfields * sizeof(prvm_vec_t));
+ for(i = 0; i < SPAWN2_LIMIT; ++i)
+ {
+ prog->edicts2.ed[i].priv.required = (prvm_edict_private_t *)((unsigned char *)prog->edicts2.priv + i * prog->edictprivate_size);
+ prog->edicts2.ed[i].priv.required->free = true;
+ prog->edicts2.ed[i].priv.required->freetime = -1337;
+ prog->edicts2.ed[i].fields.fp = prog->edicts2.fields + i * prog->entityfields;
+ }
+ }
}
/*
return e;
}
+prvm_edict_t *PRVM_ED_Alloc2(prvm_prog_t *prog)
+{
+ int i;
+ for (i = 0; i < SPAWN2_LIMIT; ++i)
+ {
+ prvm_edict_t *e = &prog->edicts2.ed[i];
+ if (PRVM_ED_CanAlloc(prog, e))
+ {
+ PRVM_ED_ClearEdict(prog, e);
+ return e;
+ }
+ }
+ prog->error_cmd("%s: PRVM_ED_Alloc2: no free edicts (%d)", prog->name, i);
+ return NULL;
+}
+
/*
=================
PRVM_ED_Free
unsigned int cached_entityfieldsarea_entityfields = prog->entityfieldsarea - prog->entityfields;
unsigned int cached_entityfieldsarea_3 = prog->entityfieldsarea - 3;
unsigned int cached_entityfieldsarea_entityfields_3 = prog->entityfieldsarea - prog->entityfields - 3;
- unsigned int cached_max_edicts = prog->max_edicts;
+ int cached_max_edicts = prog->max_edicts;
// these do not change
mstatement_t *cached_statements = prog->statements;
qboolean cached_allowworldwrites = prog->allowworldwrites;
unsigned int cached_entityfieldsarea_entityfields = prog->entityfieldsarea - prog->entityfields;
unsigned int cached_entityfieldsarea_3 = prog->entityfieldsarea - 3;
unsigned int cached_entityfieldsarea_entityfields_3 = prog->entityfieldsarea - prog->entityfields - 3;
- unsigned int cached_max_edicts = prog->max_edicts;
+ int cached_max_edicts = prog->max_edicts;
// these do not change
mstatement_t *cached_statements = prog->statements;
qboolean cached_allowworldwrites = prog->allowworldwrites;
unsigned int cached_entityfieldsarea_entityfields = prog->entityfieldsarea - prog->entityfields;
unsigned int cached_entityfieldsarea_3 = prog->entityfieldsarea - 3;
unsigned int cached_entityfieldsarea_entityfields_3 = prog->entityfieldsarea - prog->entityfields - 3;
- unsigned int cached_max_edicts = prog->max_edicts;
+ int cached_max_edicts = prog->max_edicts;
// these do not change
mstatement_t *cached_statements = prog->statements;
qboolean cached_allowworldwrites = prog->allowworldwrites;
HANDLE_OPCODE(OP_STOREP_FLD): // integers
HANDLE_OPCODE(OP_STOREP_S):
HANDLE_OPCODE(OP_STOREP_FNC): // pointers
- if ((prvm_uint_t)OPB->_int - cached_entityfields >= cached_entityfieldsarea_entityfields)
+ {
+ int i, fld;
+ if (OPB->_int >= 0) {
+ i = OPB->_int / cached_entityfields;
+ fld = OPB->_int % cached_entityfields;
+ } else {
+ int inp = -OPB->_int - 1;
+ i = -((inp / cached_entityfields) + 1);
+ fld = inp % cached_entityfields;
+ // VM_Warning(prog, "storep %i : %i . %i = %i\n", OPB->_int, i, fld);
+ }
+ if (i >= cached_max_edicts || i < -SPAWN2_LIMIT)
{
- if ((prvm_uint_t)OPB->_int >= cached_entityfieldsarea)
- {
- PRE_ERROR();
- prog->error_cmd("%s attempted to write to an out of bounds edict (%i)", prog->name, (int)OPB->_int);
- goto cleanup;
- }
- if ((prvm_uint_t)OPB->_int < cached_entityfields && !cached_allowworldwrites)
- {
- PRE_ERROR();
- VM_Warning(prog, "assignment to world.%s (field %i) in %s\n", PRVM_GetString(prog, PRVM_ED_FieldAtOfs(prog, OPB->_int)->s_name), (int)OPB->_int, prog->name);
- }
+ PRE_ERROR();
+ prog->error_cmd("%s attempted to write to an out of bounds edict (%i)", prog->name, i);
+ goto cleanup;
}
- ptr = (prvm_eval_t *)(cached_edictsfields + OPB->_int);
+ if (i == 0 && !cached_allowworldwrites)
+ {
+ PRE_ERROR();
+ VM_Warning(prog, "assignment to world.%s (field %i) in %s\n", PRVM_GetString(prog, PRVM_ED_FieldAtOfs(prog, OPB->_int)->s_name), (int)OPB->_int, prog->name);
+ }
+ ptr = i >= 0
+ ? (prvm_eval_t *)(cached_edictsfields + OPB->_int)
+ : (prvm_eval_t *)(prog->edicts2.fields + (-i - 1) * cached_entityfields + fld);
ptr->_int = OPA->_int;
DISPATCH_OPCODE();
+ }
HANDLE_OPCODE(OP_STOREP_V):
- if ((prvm_uint_t)OPB->_int - cached_entityfields > (prvm_uint_t)cached_entityfieldsarea_entityfields_3)
+ {
+ int i, fld;
+ if (OPB->_int >= 0) {
+ i = OPB->_int / cached_entityfields;
+ fld = OPB->_int % cached_entityfields;
+ } else {
+ int o = -OPB->_int - 1;
+ i = -((o / cached_entityfields) + 1);
+ fld = o % cached_entityfields;
+ // VM_Warning(prog, "storep %i : %i . %i = %i\n", OPB->_int, i, fld);
+ }
+ if (i >= cached_max_edicts || i < -SPAWN2_LIMIT)
{
- if ((prvm_uint_t)OPB->_int > cached_entityfieldsarea_3)
- {
- PRE_ERROR();
- prog->error_cmd("%s attempted to write to an out of bounds edict (%i)", prog->name, (int)OPB->_int);
- goto cleanup;
- }
- if ((prvm_uint_t)OPB->_int < cached_entityfields && !cached_allowworldwrites)
- {
- PRE_ERROR();
- VM_Warning(prog, "assignment to world.%s (field %i) in %s\n", PRVM_GetString(prog, PRVM_ED_FieldAtOfs(prog, OPB->_int)->s_name), (int)OPB->_int, prog->name);
- }
+ PRE_ERROR();
+ prog->error_cmd("%s attempted to write to an out of bounds edict (%i)", prog->name, i);
+ goto cleanup;
+ }
+ if (i == 0 && !cached_allowworldwrites)
+ {
+ PRE_ERROR();
+ VM_Warning(prog, "assignment to world.%s (field %i) in %s\n", PRVM_GetString(prog, PRVM_ED_FieldAtOfs(prog, OPB->_int)->s_name), (int)OPB->_int, prog->name);
}
- ptr = (prvm_eval_t *)(cached_edictsfields + OPB->_int);
+ ptr = i >= 0
+ ? (prvm_eval_t *)(cached_edictsfields + OPB->_int)
+ : (prvm_eval_t *)(prog->edicts2.fields + (-i - 1) * cached_entityfields + fld);
ptr->ivector[0] = OPA->ivector[0];
ptr->ivector[1] = OPA->ivector[1];
ptr->ivector[2] = OPA->ivector[2];
DISPATCH_OPCODE();
+ }
HANDLE_OPCODE(OP_ADDRESS):
- if ((prvm_uint_t)OPA->edict >= cached_max_edicts)
+ if (OPA->edict >= cached_max_edicts || OPA->edict < -SPAWN2_LIMIT)
{
PRE_ERROR();
prog->error_cmd("%s Progs attempted to address an out of bounds edict number", prog->name);
goto cleanup;
}
#endif
- OPC->_int = OPA->edict * cached_entityfields + OPB->_int;
+ if (OPA->edict >= 0)
+ OPC->_int = OPA->edict * cached_entityfields + OPB->_int;
+ else {
+ int e = -OPA->edict - 1;
+ int out = e * cached_entityfields + OPB->_int;
+ out = out + 1;
+ out = 0 - out;
+ //VM_Warning(prog, "addressing %i . %i = %i\n", OPA->edict, OPB->_int, out);
+ OPC->_int = out;
+ }
DISPATCH_OPCODE();
HANDLE_OPCODE(OP_LOAD_F):
HANDLE_OPCODE(OP_LOAD_ENT):
HANDLE_OPCODE(OP_LOAD_S):
HANDLE_OPCODE(OP_LOAD_FNC):
- if ((prvm_uint_t)OPA->edict >= cached_max_edicts)
+ if (OPA->edict >= cached_max_edicts || OPA->edict < -SPAWN2_LIMIT)
{
PRE_ERROR();
prog->error_cmd("%s Progs attempted to read an out of bounds edict number", prog->name);
DISPATCH_OPCODE();
HANDLE_OPCODE(OP_LOAD_V):
- if ((prvm_uint_t)OPA->edict >= cached_max_edicts)
+ if (OPA->edict >= cached_max_edicts || OPA->edict < -SPAWN2_LIMIT)
{
PRE_ERROR();
prog->error_cmd("%s Progs attempted to read an out of bounds edict number", prog->name);