]> git.xonotic.org Git - xonotic/darkplaces.git/commitdiff
spawn2 hack TimePath/spawn2_hack
authorTimePath <andrew.hardaker1995@gmail.com>
Mon, 28 Dec 2015 07:43:13 +0000 (18:43 +1100)
committerTimePath <andrew.hardaker1995@gmail.com>
Mon, 28 Dec 2015 07:43:13 +0000 (18:43 +1100)
clvm_cmds.c
mvm_cmds.c
progsvm.h
prvm_cmds.c
prvm_cmds.h
prvm_edict.c
prvm_exec.c
prvm_execprogram.h
svvm_cmds.c

index 9d41dda6d454fc4579c01839ef7f5b03e3ce6f9e..8fe3ed15154c487cf4ba27fe3f0621ed7027194f 100644 (file)
@@ -4938,7 +4938,7 @@ NULL,                                                     // #596
 NULL,                                                  // #597
 NULL,                                                  // #598
 NULL,                                                  // #599
-NULL,                                                  // #600
+VM_spawn2,                                             // #600
 NULL,                                                  // #601
 NULL,                                                  // #602
 NULL,                                                  // #603
index ace22bfa74c2ac5009dcde180ea00b2adb0e7dea..80ede5f113606c3c68c527d702fc72b8a70fe177 100644 (file)
@@ -1558,7 +1558,7 @@ NULL,                                                                     // #596
 NULL,                                                                  // #597
 NULL,                                                                  // #598
 NULL,                                                                  // #599
-NULL,                                                                  // #600
+VM_spawn2,                                                             // #600
 VM_M_setkeydest,                                       // #601 void setkeydest(float dest)
 VM_M_getkeydest,                                       // #602 float getkeydest(void)
 VM_M_setmousetarget,                           // #603 void setmousetarget(float trg)
index 8483fae981d7254f68d05d10ed6b44e3eea7e17b..7095b867a2a10daba7c63d1373ea30ee97e14b3a 100644 (file)
--- a/progsvm.h
+++ b/progsvm.h
@@ -653,6 +653,12 @@ typedef struct prvm_prog_s
        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]
 
@@ -809,6 +815,7 @@ void PRVM_MEM_IncreaseEdicts(prvm_prog_t *prog);
 
 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);
 
@@ -824,10 +831,16 @@ void PRVM_ED_LoadFromFile(prvm_prog_t *prog, const char *data);
 
 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)
index e1b248dd0169b05f10aa33ea16a110a746969751..715ef9755b432b364764372d196ef6f94dc5d0f8 100644 (file)
@@ -972,6 +972,15 @@ void VM_spawn(prvm_prog_t *prog)
        VM_RETURN_EDICT(ed);
 }
 
+void VM_spawn2(prvm_prog_t *prog)
+{
+       prvm_edict_t    *ed;
+       VM_SAFEPARMCOUNT(0, VM_spawn2);
+       prog->xfunction->builtinsprofile += 20;
+       ed = PRVM_ED_Alloc2(prog);
+       prog->globals.ip[OFS_RETURN] = -(int)(ed - prog->edicts2.ed) - 1;
+}
+
 /*
 =========
 VM_remove
index 0120975805c24be28016c5a7c3848b84c2a808b5..0df2c8eaf6de71ee09cfb233d546ecea41350c5a 100644 (file)
@@ -256,6 +256,7 @@ void VM_itof(prvm_prog_t *prog);
 void VM_ftoe(prvm_prog_t *prog);
 void VM_strftime(prvm_prog_t *prog);
 void VM_spawn (prvm_prog_t *prog);
+void VM_spawn2 (prvm_prog_t *prog);
 void VM_remove (prvm_prog_t *prog);
 void VM_find (prvm_prog_t *prog);
 void VM_findfloat (prvm_prog_t *prog);
index 77a1af71b053f5a9143496359961f2fb2c8e4684..88164ef446e59bdcf3de9ced94df04358bacdded 100644 (file)
@@ -84,6 +84,20 @@ static void PRVM_MEM_Alloc(prvm_prog_t *prog)
                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;
+               }
+       }
 }
 
 /*
@@ -287,6 +301,22 @@ prvm_edict_t *PRVM_ED_Alloc(prvm_prog_t *prog)
        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
index ad11c11316df51d17b3aa3216e0f7a38ebd58116..4a5d8a31265d83175010d480f420999039a4b32e 100644 (file)
@@ -753,7 +753,7 @@ void MVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessag
        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;
@@ -860,7 +860,7 @@ void CLVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessa
        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;
@@ -971,7 +971,7 @@ void PRVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessa
        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;
index 1607bcfe558a65d1e7d79a61c08d65b3ce7b27b1..88f925fc454b0324994426c73edcc37dce9e955d 100644 (file)
                        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);
index ff55c4fde46479e66de9f4ae38559fc6b2d974d5..ab7cc0873eee61065161b2f1564f0f1f4097d337 100644 (file)
@@ -3783,7 +3783,7 @@ NULL,                                                     // #596
 NULL,                                                  // #597
 NULL,                                                  // #598
 NULL,                                                  // #599
-NULL,                                                  // #600
+VM_spawn2,                                             // #600
 NULL,                                                  // #601
 NULL,                                                  // #602
 NULL,                                                  // #603