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.
{
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;
// 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
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;
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--)
{
int i = str & ~0x80000000;
if (i >= prinst->numallocedstrings)
{
+ printf("invalid string %x\n", str);
+ PR_StackTrace(progfuncs);
pr_trace = 1;
return "";
}
return prinst->allocedstrings[i];
else
{
+ printf("invalid string %x\n", str);
+ PR_StackTrace(progfuncs);
pr_trace = 1;
return ""; //urm, was freed...
}
int i = str & ~0x40000000;
if (i >= prinst->numtempstrings)
{
+ printf("invalid temp string %x\n", str);
+ PR_StackTrace(progfuncs);
pr_trace = 1;
return "";
}
}
}
- if (str >= progfuncs->stringtablesize)
+ if (str >= addressableused)
{
+ printf("invalid string offset %x\n", str);
+ PR_StackTrace(progfuncs);
pr_trace = 1;
return "";
}
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)
{
0,
PR_QueryField,
QC_ClearEdict,
- QC_FindPrefixedGlobals
+ QC_FindPrefixedGlobals,
+ PRAddressableAlloc,
+ PR_AllocTempStringLen
};
#undef printf
#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;