]> de.git.xonotic.org Git - voretournament/voretournament.git/blobdiff - misc/source/fteqcc-src/initlib.c
Update fteqcc source
[voretournament/voretournament.git] / misc / source / fteqcc-src / initlib.c
index 8ee0f99a2cef5f18de5767ae943304be93178766..e630395a4f155eed9e9464e2e31725d49f7da63c 100644 (file)
@@ -41,6 +41,38 @@ void PRHunkFree(progfuncs_t *progfuncs, int mark)
        return;
 }
 
+/*if we ran out of memory, the vm can allocate a new block, but doing so requires fixing up all sorts of pointers*/
+void PRAddressableRelocate(progfuncs_t *progfuncs, char *oldb, char *newb, int oldlen)
+{
+       unsigned int i;
+       edictrun_t *e;
+       for (i=0 ; i<maxedicts; i++)
+       {
+               e = (edictrun_t *)(prinst->edicttable[i]);
+               if (e && (char*)e->fields >= oldb && (char*)e->fields < oldb+oldlen)
+                       e->fields = ((char*)e->fields - oldb) + newb;
+       }
+
+       if (progfuncs->stringtable >= oldb && progfuncs->stringtable < oldb+oldlen)
+               progfuncs->stringtable = (progfuncs->stringtable - oldb) + newb;
+
+       for (i=0; i < maxprogs; i++)
+       {
+               if ((char*)prinst->progstate[i].globals >= oldb && (char*)prinst->progstate[i].globals < oldb+oldlen)
+                       prinst->progstate[i].globals = (float*)(((char*)prinst->progstate[i].globals - oldb) + newb);
+               if (prinst->progstate[i].strings >= oldb && prinst->progstate[i].strings < oldb+oldlen)
+                       prinst->progstate[i].strings = (prinst->progstate[i].strings - oldb) + newb;
+       }
+
+       for (i = 0; i < numfields; i++)
+       {
+               if (field[i].name >= oldb && field[i].name < oldb+oldlen)
+                       field[i].name = (field[i].name - oldb) + newb;
+       }
+
+       externs->addressablerelocated(progfuncs, oldb, newb, oldlen);
+}
+
 //for 64bit systems. :)
 //addressable memory is memory available to the vm itself for writing.
 //once allocated, it cannot be freed for the lifetime of the VM.
@@ -48,7 +80,46 @@ void *PRAddressableAlloc(progfuncs_t *progfuncs, int ammount)
 {
        ammount = (ammount + 4)&~3;     //round up to 4
        if (addressableused + ammount > addressablesize)
-               Sys_Error("Not enough addressable memory for progs VM");
+       {
+               /*only do this if the caller states that it can cope with addressable-block relocations/resizes*/
+               if (externs->addressablerelocated)
+               {
+#ifdef _WIN32
+                       char *newblock;
+               #if 0//def _DEBUG
+                       int oldtot = addressablesize;
+               #endif
+                       int newsize = (addressableused + ammount + 4096) & ~(4096-1);
+                       newblock = VirtualAlloc (NULL, addressablesize, MEM_RESERVE, PAGE_NOACCESS);
+                       if (newblock)
+                       {
+                               VirtualAlloc (newblock, addressableused, MEM_COMMIT, PAGE_READWRITE);
+                               memcpy(newblock, addressablehunk, addressableused);
+               #if 0//def _DEBUG
+                               VirtualAlloc (addressablehunk, oldtot, MEM_RESERVE, PAGE_NOACCESS);
+               #else
+                               VirtualFree (addressablehunk, 0, MEM_RELEASE);
+               #endif
+                               PRAddressableRelocate(progfuncs, addressablehunk, newblock, addressableused);
+                               addressablehunk = newblock;
+                               addressablesize = newsize;
+                       }
+#else
+                       char *newblock;
+                       int newsize = (addressableused + ammount + 1024*1024) & ~(1024*1024-1);
+                       newblock = realloc(newblock, addressablesize);
+                       if (newblock)
+                       {
+                               PRAddressableRelocate(progfuncs, addressablehunk, newblock, addressableused);
+                               addressablehunk = newblock;
+                               addressablesize = newsize;
+                       }
+#endif
+               }
+
+               if (addressableused + ammount > addressablesize)
+                       Sys_Error("Not enough addressable memory for progs VM");
+       }
 
        addressableused += ammount;
 
@@ -69,12 +140,17 @@ void PRAddressableFlush(progfuncs_t *progfuncs, int totalammount)
 //             return;
        }
 
-       if (addressablehunk)
 #ifdef _WIN32
-       VirtualFree(addressablehunk, 0, MEM_RELEASE);   //doesn't this look complicated? :p
-       addressablehunk = VirtualAlloc (NULL, totalammount, MEM_RESERVE, PAGE_NOACCESS);
+       if (addressablehunk && addressablesize != totalammount)
+       {
+               VirtualFree(addressablehunk, 0, MEM_RELEASE);   //doesn't this look complicated? :p
+               addressablehunk = NULL;
+       }
+       if (!addressablehunk)
+               addressablehunk = VirtualAlloc (addressablehunk, totalammount, MEM_RESERVE, PAGE_NOACCESS);
 #else
-       free(addressablehunk);
+       if (addressablehunk)
+               free(addressablehunk);
        addressablehunk = malloc(totalammount); //linux will allocate-on-use anyway, which is handy.
 //     memset(addressablehunk, 0xff, totalammount);
 #endif
@@ -160,7 +236,10 @@ struct globalvars_s *PR_globals (progfuncs_t *progfuncs, progsnum_t pnum)
        if (pnum < 0)
        {
                if (!current_progstate)
-                       return NULL;    //err.. you've not loaded one yet.
+               {
+                       static float fallback[RESERVED_OFS];
+                       return (struct globalvars_s *)fallback; //err.. you've not loaded one yet.
+               }
                return (struct globalvars_s *)current_progstate->globals;
        }
        return (struct globalvars_s *)pr_progstate[pnum].globals;
@@ -426,8 +505,8 @@ string_t PR_StringToProgs                   (progfuncs_t *progfuncs, char *str)
        if (!str)
                return 0;
 
-//     if (str-progfuncs->stringtable < progfuncs->stringtablesize)
-//             return str - progfuncs->stringtable;
+       if (str >= progfuncs->stringtable && str < progfuncs->stringtable + addressableused)
+               return str - progfuncs->stringtable;
 
        for (i = prinst->numallocedstrings-1; i >= 0; i--)
        {
@@ -507,6 +586,8 @@ char *ASMCALL PR_StringToNative                             (progfuncs_t *progfuncs, string_t str)
                        int i = str & ~0x80000000;
                        if (i >= prinst->numallocedstrings)
                        {
+                               printf("invalid string %x\n", str);
+                               PR_StackTrace(progfuncs);
                                pr_trace = 1;
                                return "";
                        }
@@ -514,6 +595,8 @@ char *ASMCALL PR_StringToNative                             (progfuncs_t *progfuncs, string_t str)
                                return prinst->allocedstrings[i];
                        else
                        {
+                               printf("invalid string %x\n", str);
+                               PR_StackTrace(progfuncs);
                                pr_trace = 1;
                                return "";      //urm, was freed...
                        }
@@ -523,6 +606,8 @@ char *ASMCALL PR_StringToNative                             (progfuncs_t *progfuncs, string_t str)
                        int i = str & ~0x40000000;
                        if (i >= prinst->numtempstrings)
                        {
+                               printf("invalid temp string %x\n", str);
+                               PR_StackTrace(progfuncs);
                                pr_trace = 1;
                                return "";
                        }
@@ -530,8 +615,10 @@ char *ASMCALL PR_StringToNative                            (progfuncs_t *progfuncs, string_t str)
                }
        }
 
-       if (str >= progfuncs->stringtablesize)
+       if (str >= addressableused)
        {
+               printf("invalid string offset %x\n", str);
+               PR_StackTrace(progfuncs);
                pr_trace = 1;
                return "";
        }
@@ -571,6 +658,38 @@ string_t PR_AllocTempString                        (progfuncs_t *progfuncs, char *str)
 
        return (string_t)((unsigned int)i | 0x40000000);
 }
+string_t PR_AllocTempStringLen                 (progfuncs_t *progfuncs, char **str, unsigned int len)
+{
+       char **ntable;
+       int newmax;
+       int i;
+
+       if (!str)
+               return 0;
+
+       if (prinst->numtempstrings == prinst->maxtempstrings)
+       {
+               newmax = prinst->maxtempstrings += 1024;
+               prinst->maxtempstrings += 1024;
+               ntable = memalloc(sizeof(char*) * newmax);
+               memcpy(ntable, prinst->tempstrings, sizeof(char*) * prinst->numtempstrings);
+               prinst->maxtempstrings = newmax;
+               if (prinst->tempstrings)
+                       memfree(prinst->tempstrings);
+               prinst->tempstrings = ntable;
+       }
+
+       i = prinst->numtempstrings;
+       if (i == 0x10000000)
+               return 0;
+
+       prinst->numtempstrings++;
+
+       prinst->tempstrings[i] = memalloc(len);
+       *str = prinst->tempstrings[i];
+
+       return (string_t)((unsigned int)i | 0x40000000);
+}
 
 void PR_FreeTemps                      (progfuncs_t *progfuncs, int depth)
 {
@@ -683,7 +802,9 @@ progfuncs_t deffuncs = {
        0,
        PR_QueryField,
        QC_ClearEdict,
-       QC_FindPrefixedGlobals
+       QC_FindPrefixedGlobals,
+       PRAddressableAlloc,
+       PR_AllocTempStringLen
 };
 #undef printf
 
@@ -774,8 +895,8 @@ void CloseProgs(progfuncs_t *inst)
 #endif
 
        if (inst->prinst->allocedstrings)
-                f(inst->prinst->allocedstrings);
-               inst->prinst->allocedstrings = NULL;
+               f(inst->prinst->allocedstrings);
+       inst->prinst->allocedstrings = NULL;
        if (inst->prinst->tempstrings)
                f(inst->prinst->tempstrings);
        inst->prinst->tempstrings = NULL;