diff --git a/polymer/eduke32/source/gamevars.c b/polymer/eduke32/source/gamevars.c index 058b96646..218a34e8c 100644 --- a/polymer/eduke32/source/gamevars.c +++ b/polymer/eduke32/source/gamevars.c @@ -30,6 +30,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #define _gamevars_c_ +#define PLAYER_VAR_ALIGNMENT (sizeof(intptr_t)) +#define ACTOR_VAR_ALIGNMENT 16 + #ifdef LUNATIC int32_t g_noResetVars; LUNATIC_CB void (*A_ResetVars)(int32_t iActor); @@ -41,24 +44,18 @@ static void Gv_Free(void) /* called from Gv_ReadSave() and Gv_ResetVars() */ // call this function as many times as needed. int32_t i; - for (i=MAXGAMEVARS-1; i>=0; i--) + for (i=0; i= MAXGAMEARRAYS) continue; - if ((aGameArrays[i].dwFlags & GAMEARRAY_NORMAL) && aGameArrays[i].plValues) - { - Bfree(aGameArrays[i].plValues); - aGameArrays[i].plValues=NULL; - } + if (aGameArrays[i].dwFlags & GAMEARRAY_NORMAL) + ALIGNED_FREE_AND_NULL(aGameArrays[i].plValues); aGameArrays[i].dwFlags |= GAMEARRAY_RESET; } @@ -76,18 +73,16 @@ static void Gv_Clear(void) Gv_Free(); // Now, only do work that Gv_Free() hasn't done. - for (i=MAXGAMEVARS-1; i>=0; i--) + for (i=0; i= MAXGAMEARRAYS) continue; - Bfree(aGameArrays[i].szLabel); - aGameArrays[i].szLabel=NULL; + DO_FREE_AND_NULL(aGameArrays[i].szLabel); } } @@ -116,18 +111,18 @@ int32_t Gv_ReadSave(int32_t fil, int32_t newbehav) for (i=0; ivars[j]) - MapInfo[i].savedstate->vars[j] = (intptr_t *)Xcalloc(MAXPLAYERS,sizeof(intptr_t)); + MapInfo[i].savedstate->vars[j] = (intptr_t *)Xaligned_alloc(PLAYER_VAR_ALIGNMENT, MAXPLAYERS * sizeof(intptr_t)); if (kdfread(&MapInfo[i].savedstate->vars[j][0],sizeof(intptr_t) * MAXPLAYERS, 1, fil) != 1) goto corrupt; } else if (aGameVars[j].dwFlags & GAMEVAR_PERACTOR) { // if (!MapInfo[i].savedstate->vars[j]) - MapInfo[i].savedstate->vars[j] = (intptr_t *)Xcalloc(MAXSPRITES,sizeof(intptr_t)); + MapInfo[i].savedstate->vars[j] = (intptr_t *)Xaligned_alloc(ACTOR_VAR_ALIGNMENT, MAXSPRITES * sizeof(intptr_t)); if (kdfread(&MapInfo[i].savedstate->vars[j][0],sizeof(intptr_t), MAXSPRITES, fil) != MAXSPRITES) goto corrupt; } } @@ -426,11 +421,15 @@ int32_t Gv_NewArray(const char *pszLabel, void *arrayptr, intptr_t asize, uint32 if (aGameArrays[i].szLabel == NULL) aGameArrays[i].szLabel=(char *)Xcalloc(MAXVARLABEL,sizeof(uint8_t)); + if (aGameArrays[i].szLabel != pszLabel) Bstrcpy(aGameArrays[i].szLabel,pszLabel); if (!(dwFlags & GAMEARRAY_TYPE_MASK)) - aGameArrays[i].plValues=(intptr_t *)Xcalloc(asize,GAR_ELTSZ); + { + aGameArrays[i].plValues = (intptr_t *)Xaligned_alloc(ACTOR_VAR_ALIGNMENT, asize * GAR_ELTSZ); + Bmemset(aGameArrays[i].plValues, 0, asize * GAR_ELTSZ); + } else aGameArrays[i].plValues=(intptr_t *)arrayptr; @@ -495,18 +494,16 @@ int32_t Gv_NewVar(const char *pszLabel, intptr_t lValue, uint32_t dwFlags) // Allocate and set its label if (aGameVars[i].szLabel == NULL) aGameVars[i].szLabel = (char *)Xcalloc(MAXVARLABEL,sizeof(uint8_t)); + if (aGameVars[i].szLabel != pszLabel) Bstrcpy(aGameVars[i].szLabel,pszLabel); // and the flags aGameVars[i].dwFlags=dwFlags; + // only free if per-{actor,player} if (aGameVars[i].dwFlags & GAMEVAR_USER_MASK) - { - // only free if per-{actor,player} - Bfree(aGameVars[i].val.plValues); - aGameVars[i].val.plValues=NULL; - } + ALIGNED_FREE_AND_NULL(aGameVars[i].val.plValues); } // if existing is system, they only get to change default value.... @@ -523,14 +520,20 @@ int32_t Gv_NewVar(const char *pszLabel, intptr_t lValue, uint32_t dwFlags) if (aGameVars[i].dwFlags & GAMEVAR_PERPLAYER) { if (!aGameVars[i].val.plValues) - aGameVars[i].val.plValues = (intptr_t *)Xcalloc(MAXPLAYERS,sizeof(intptr_t)); + { + aGameVars[i].val.plValues = (intptr_t *) Xaligned_alloc(PLAYER_VAR_ALIGNMENT, MAXPLAYERS * sizeof(intptr_t)); + Bmemset(aGameVars[i].val.plValues, 0, MAXPLAYERS * sizeof(intptr_t)); + } for (j=MAXPLAYERS-1; j>=0; j--) aGameVars[i].val.plValues[j]=lValue; } else if (aGameVars[i].dwFlags & GAMEVAR_PERACTOR) { if (!aGameVars[i].val.plValues) - aGameVars[i].val.plValues = (intptr_t *)Xcalloc(MAXSPRITES,sizeof(intptr_t)); + { + aGameVars[i].val.plValues = (intptr_t *) Xaligned_alloc(ACTOR_VAR_ALIGNMENT, MAXSPRITES * sizeof(intptr_t)); + Bmemset(aGameVars[i].val.plValues, 0, MAXSPRITES * sizeof(intptr_t)); + } for (j=MAXSPRITES-1; j>=0; j--) aGameVars[i].val.plValues[j]=lValue; } @@ -539,17 +542,6 @@ int32_t Gv_NewVar(const char *pszLabel, intptr_t lValue, uint32_t dwFlags) return 1; } -void __fastcall A_ResetVars(int32_t iActor) -{ - int32_t i=(MAXGAMEVARS-1); - do - { - if ((aGameVars[i].dwFlags & (GAMEVAR_PERACTOR|GAMEVAR_NODEFAULT)) == GAMEVAR_PERACTOR) - aGameVars[i].val.plValues[iActor]=aGameVars[i].lDefault; - } - while (i--); -} - static int32_t Gv_GetVarIndex(const char *szGameLabel) { int32_t i = hash_find(&h_gamevars,szGameLabel); diff --git a/polymer/eduke32/source/gamevars.h b/polymer/eduke32/source/gamevars.h index 98c23461e..7e31f27f7 100644 --- a/polymer/eduke32/source/gamevars.h +++ b/polymer/eduke32/source/gamevars.h @@ -104,7 +104,16 @@ void __fastcall Gv_SetVarX(int32_t id, int32_t lValue); int32_t Gv_GetVarByLabel(const char *szGameLabel,int32_t lDefault,int32_t iActor,int32_t iPlayer); int32_t Gv_NewArray(const char *pszLabel,void *arrayptr,intptr_t asize,uint32_t dwFlags); int32_t Gv_NewVar(const char *pszLabel,intptr_t lValue,uint32_t dwFlags); -void __fastcall A_ResetVars(int32_t iActor); +static inline void A_ResetVars(int32_t iActor) +{ + int32_t i; + + for (i=0; i MAXPLAYERS-1)) break; \ - aGameVars[id].val.plValues[vm.g_p] operator lValue; \ - break; \ - case GAMEVAR_PERACTOR: \ - if (EDUKE32_PREDICT_FALSE((unsigned)vm.g_i > MAXSPRITES-1)) break; \ - aGameVars[id].val.plValues[vm.g_i] operator lValue; \ - break; \ - case GAMEVAR_INTPTR: \ - *((int32_t *)aGameVars[id].val.lValue) operator (int32_t)lValue; \ - break; \ - case GAMEVAR_SHORTPTR: \ - *((int16_t *)aGameVars[id].val.lValue) operator (int16_t)lValue; \ - break; \ - case GAMEVAR_CHARPTR: \ - *((uint8_t *)aGameVars[id].val.lValue) operator (uint8_t)lValue; \ - break; \ - } \ -} +#define VM_GAMEVAR_OPERATOR(func, operator) \ + static inline void __fastcall func(int32_t id, int32_t lValue) \ + { \ + switch (aGameVars[id].dwFlags & (GAMEVAR_USER_MASK | GAMEVAR_PTR_MASK)) \ + { \ + default: aGameVars[id].val.lValue operator lValue; break; \ + case GAMEVAR_PERPLAYER: \ + if (EDUKE32_PREDICT_FALSE((unsigned)vm.g_p > MAXPLAYERS - 1)) \ + break; \ + aGameVars[id].val.plValues[vm.g_p] operator lValue; \ + break; \ + case GAMEVAR_PERACTOR: \ + if (EDUKE32_PREDICT_FALSE((unsigned)vm.g_i > MAXSPRITES - 1)) \ + break; \ + aGameVars[id].val.plValues[vm.g_i] operator lValue; \ + break; \ + case GAMEVAR_INTPTR: *((int32_t *)aGameVars[id].val.lValue) operator(int32_t) lValue; break; \ + case GAMEVAR_SHORTPTR: *((int16_t *)aGameVars[id].val.lValue) operator(int16_t) lValue; break; \ + case GAMEVAR_CHARPTR: *((uint8_t *)aGameVars[id].val.lValue) operator(uint8_t) lValue; break; \ + } \ + } -// even though libdivide is faster than straight division (when using the LUT) the overhead makes this slower on x86 -// ARM, however, has no hardware integer division #if defined(__arm__) || defined(LIBDIVIDE_ALWAYS) static inline void __fastcall Gv_DivVar(int32_t id, int32_t lValue) { @@ -158,47 +160,49 @@ static inline void __fastcall Gv_DivVar(int32_t id, int32_t lValue) libdivide_s32_t *dptr = &sdiv; intptr_t *iptr = &aGameVars[id].val.lValue; - if (EDUKE32_PREDICT_FALSE((aGameVars[id].dwFlags & GAMEVAR_PERPLAYER && (unsigned) vm.g_p > MAXPLAYERS-1) || - (aGameVars[id].dwFlags & GAMEVAR_PERACTOR && (unsigned) vm.g_i > MAXSPRITES-1))) return; + if (EDUKE32_PREDICT_FALSE((aGameVars[id].dwFlags & GAMEVAR_PERPLAYER && (unsigned)vm.g_p > MAXPLAYERS - 1) || + (aGameVars[id].dwFlags & GAMEVAR_PERACTOR && (unsigned)vm.g_i > MAXSPRITES - 1))) + return; - if ((unsigned) lValue < DIVTABLESIZE) + if ((unsigned)lValue < DIVTABLESIZE) dptr = (libdivide_s32_t *)&divtable32[lValue]; else if (lValue != lastlValue) sdiv = libdivide_s32_gen(lValue), lastlValue = lValue; - switch (aGameVars[id].dwFlags & (GAMEVAR_USER_MASK|GAMEVAR_PTR_MASK)) + switch (aGameVars[id].dwFlags & (GAMEVAR_USER_MASK | GAMEVAR_PTR_MASK)) { - case GAMEVAR_PERPLAYER: - iptr = &aGameVars[id].val.plValues[vm.g_p]; - default: - break; - case GAMEVAR_PERACTOR: - iptr = &aGameVars[id].val.plValues[vm.g_i]; - break; - case GAMEVAR_INTPTR: - *((int32_t *) aGameVars[id].val.lValue) = (int32_t) libdivide_s32_do(*((int32_t *) aGameVars[id].val.lValue), dptr); - return; - case GAMEVAR_SHORTPTR: - *((int16_t *) aGameVars[id].val.lValue) = (int16_t) libdivide_s32_do(*((int16_t *) aGameVars[id].val.lValue), dptr); - return; - case GAMEVAR_CHARPTR: - *((uint8_t *) aGameVars[id].val.lValue) = (uint8_t) libdivide_s32_do(*((uint8_t *) aGameVars[id].val.lValue), dptr); - return; + case GAMEVAR_PERPLAYER: iptr = &aGameVars[id].val.plValues[vm.g_p]; + default: break; + case GAMEVAR_PERACTOR: iptr = &aGameVars[id].val.plValues[vm.g_i]; break; + case GAMEVAR_INTPTR: + *((int32_t *)aGameVars[id].val.lValue) = + (int32_t)libdivide_s32_do(*((int32_t *)aGameVars[id].val.lValue), dptr); + return; + case GAMEVAR_SHORTPTR: + *((int16_t *)aGameVars[id].val.lValue) = + (int16_t)libdivide_s32_do(*((int16_t *)aGameVars[id].val.lValue), dptr); + return; + case GAMEVAR_CHARPTR: + *((uint8_t *)aGameVars[id].val.lValue) = + (uint8_t)libdivide_s32_do(*((uint8_t *)aGameVars[id].val.lValue), dptr); + return; } *iptr = libdivide_s32_do(*iptr, dptr); } #else -GV_VAROP(Gv_DivVar, /=) +VM_GAMEVAR_OPERATOR(Gv_DivVar, /= ) #endif -GV_VAROP(Gv_AddVar, +=) -GV_VAROP(Gv_SubVar, -=) -GV_VAROP(Gv_MulVar, *=) -GV_VAROP(Gv_ModVar, %=) -GV_VAROP(Gv_AndVar, &=) -GV_VAROP(Gv_XorVar, ^=) -GV_VAROP(Gv_OrVar, |=) +VM_GAMEVAR_OPERATOR(Gv_AddVar, +=) +VM_GAMEVAR_OPERATOR(Gv_SubVar, -=) +VM_GAMEVAR_OPERATOR(Gv_MulVar, *=) +VM_GAMEVAR_OPERATOR(Gv_ModVar, %=) +VM_GAMEVAR_OPERATOR(Gv_AndVar, &=) +VM_GAMEVAR_OPERATOR(Gv_XorVar, ^=) +VM_GAMEVAR_OPERATOR(Gv_OrVar, |=) + +#undef VM_GAMEVAR_OPERATOR #endif