From da0cc1b9bde87436bb72b144f85419af68f1aed2 Mon Sep 17 00:00:00 2001 From: terminx Date: Sat, 8 Jul 2017 19:41:43 +0000 Subject: [PATCH] Some work on CON arrays. Hopefully nothing is broken! git-svn-id: https://svn.eduke32.com/eduke32@6343 1a8010ca-5511-0410-912e-c29ae57300e0 --- source/duke3d/src/gamedef.cpp | 2 +- source/duke3d/src/gameexec.cpp | 237 +++++++++++++++------------------ source/duke3d/src/gamevars.cpp | 51 ++++--- source/duke3d/src/gamevars.h | 4 +- source/duke3d/src/savegame.cpp | 17 ++- 5 files changed, 161 insertions(+), 150 deletions(-) diff --git a/source/duke3d/src/gamedef.cpp b/source/duke3d/src/gamedef.cpp index 6b6767553..022fad1b1 100644 --- a/source/duke3d/src/gamedef.cpp +++ b/source/duke3d/src/gamedef.cpp @@ -4313,7 +4313,7 @@ DO_DEFSTATE: BITPTR_CLEAR(g_scriptPtr-apScript); *g_scriptPtr++ = i; - if (tw==CON_RESIZEARRAY && (aGameArrays[i].flags & GAMEARRAY_TYPE_MASK)) + if (tw==CON_RESIZEARRAY && (aGameArrays[i].flags & (GAMEARRAY_READONLY|GAMEARRAY_SYSTEM))) { C_ReportError(-1); initprintf("can't resize system array `%s'.", label+(g_labelCnt<<6)); diff --git a/source/duke3d/src/gameexec.cpp b/source/duke3d/src/gameexec.cpp index 96a34edd1..6a9d13bfb 100644 --- a/source/duke3d/src/gameexec.cpp +++ b/source/duke3d/src/gameexec.cpp @@ -2041,15 +2041,15 @@ skip_check: insptr++; { int const gameVar = *insptr++; - int const spriteNum = Gv_GetVarX(*insptr++); + int const statNum = Gv_GetVarX(*insptr++); - if (EDUKE32_PREDICT_FALSE((unsigned)spriteNum > MAXSTATUS)) + if (EDUKE32_PREDICT_FALSE((unsigned)statNum > MAXSTATUS)) { - CON_ERRPRINTF("invalid status list %d\n", spriteNum); + CON_ERRPRINTF("invalid status list %d\n", statNum); continue; } - Gv_SetVarX(gameVar, headspritestat[spriteNum]); + Gv_SetVarX(gameVar, headspritestat[statNum]); continue; } @@ -4632,7 +4632,6 @@ finish_qsprintf: continue; } - case CON_WRITEARRAYTOFILE: case CON_READARRAYFROMFILE: insptr++; { @@ -4645,41 +4644,68 @@ finish_qsprintf: continue; } - if (tw == CON_READARRAYFROMFILE) + int kFile = kopen4loadfrommod(apStrings[quoteFilename], 0); + + if (kFile < 0) + continue; + + int numElements = kfilelength(kFile) / Gv_GetArrayElementSize(arrayNum); + + if (numElements == 0) { - int32_t kFile = kopen4loadfrommod(apStrings[quoteFilename], 0); + Baligned_free(aGameArrays[arrayNum].pValues); + aGameArrays[arrayNum].pValues = NULL; + aGameArrays[arrayNum].size = numElements; + } + else if (numElements > 0) + { + int const numBytes = numElements * Gv_GetArrayElementSize(arrayNum); - if (kFile < 0) - continue; + Baligned_free(aGameArrays[arrayNum].pValues); - int32_t numElements = kfilelength(kFile) / sizeof(int32_t); + aGameArrays[arrayNum].pValues = (intptr_t *)Xaligned_alloc(ACTOR_VAR_ALIGNMENT, numElements * Gv_GetArrayElementSize(arrayNum)); + aGameArrays[arrayNum].size = numElements; - if (numElements == 0) + switch (aGameArrays[arrayNum].flags & GAMEARRAY_TYPE_MASK) { - Baligned_free(aGameArrays[arrayNum].pValues); - aGameArrays[arrayNum].pValues = NULL; - aGameArrays[arrayNum].size = numElements; - } - else if (numElements > 0) - { - int const numBytes = numElements * sizeof(int32_t); + case 0: #ifdef BITNESS64 - int32_t *pArray = (int32_t *)Xcalloc(numElements, sizeof(int32_t)); + { + int32_t * const pArray = (int32_t *)Xcalloc(1, numBytes); + kread(kFile, pArray, numBytes); -#endif - Baligned_free(aGameArrays[arrayNum].pValues); - aGameArrays[arrayNum].pValues = (intptr_t *)Xaligned_alloc(ACTOR_VAR_ALIGNMENT, numElements * GAR_ELTSZ); - aGameArrays[arrayNum].size = numElements; -#ifdef BITNESS64 - for (bssize_t i = 0; i < numElements; i++) - aGameArrays[arrayNum].pValues[i] = pArray[i]; // int32_t --> int64_t - Bfree(pArray); -#else - kread(kFile, aGameArrays[arrayNum].pValues, numBytes); -#endif - } - kclose(kFile); + for (bssize_t i = 0; i < numElements; i++) + aGameArrays[arrayNum].pValues[i] = pArray[i]; + + Bfree(pArray); + break; + } +#endif + case GAMEARRAY_INT32: + case GAMEARRAY_INT16: + case GAMEARRAY_UINT8: + kread(kFile, aGameArrays[arrayNum].pValues, numBytes); + break; + case GAMEARRAY_BITMAP: + kread(kFile, aGameArrays[arrayNum].pValues, (numElements + 7) >> 3); + break; + } + } + + kclose(kFile); + continue; + } + + case CON_WRITEARRAYTOFILE: + insptr++; + { + int const arrayNum = *insptr++; + int const quoteFilename = *insptr++; + + if (EDUKE32_PREDICT_FALSE(apStrings[quoteFilename] == NULL)) + { + CON_ERRPRINTF("null quote %d\n", quoteFilename); continue; } @@ -4691,7 +4717,7 @@ finish_qsprintf: continue; } - FILE *const fil = fopen(temp, "wb"); + FILE *const fil = Bfopen(temp, "wb"); if (EDUKE32_PREDICT_FALSE(fil == NULL)) { @@ -4699,15 +4725,34 @@ finish_qsprintf: continue; } - int const arraySize = aGameArrays[arrayNum].size; - int32_t * const pArray = (int32_t *)Xmalloc(sizeof(int32_t) * arraySize); + int const numElements = aGameArrays[arrayNum].size; + int const numBytes = numElements * Gv_GetArrayElementSize(arrayNum); - for (bssize_t k = 0; k < arraySize; k++) - pArray[k] = Gv_GetArrayValue(arrayNum, k); + switch (aGameArrays[arrayNum].flags & GAMEARRAY_TYPE_MASK) + { + case 0: +#ifdef BITNESS64 + { + int32_t * const pArray = (int32_t *)Xmalloc(numBytes); - fwrite(pArray, 1, sizeof(int32_t) * arraySize, fil); - Bfree(pArray); - fclose(fil); + for (bssize_t k = 0; k < numElements; k++) + pArray[k] = Gv_GetArrayValue(arrayNum, k); + + Bfwrite(pArray, 1, numBytes, fil); + Bfree(pArray); + break; + } +#endif + case GAMEARRAY_INT32: + case GAMEARRAY_INT16: + case GAMEARRAY_UINT8: + Bfwrite(aGameArrays[arrayNum].pValues, 1, numBytes, fil); + break; + case GAMEARRAY_BITMAP: + Bfwrite(aGameArrays[arrayNum].pValues, 1, (numElements + 7) >> 3, fil); + } + + Bfclose(fil); continue; } @@ -4732,21 +4777,22 @@ finish_qsprintf: // OSD_Printf(OSDTEXT_GREEN "CON_RESIZEARRAY: resizing array %s from %d to %d\n", // aGameArrays[j].szLabel, aGameArrays[j].size, newSize); - intptr_t * const pArray = oldSize != 0 ? (intptr_t *)Xmalloc(GAR_ELTSZ * oldSize) : NULL; + int const eltSize = Gv_GetArrayElementSize(tw); + intptr_t * const pArray = oldSize != 0 ? (intptr_t *)Xmalloc(eltSize * oldSize) : NULL; if (oldSize != 0) - Bmemcpy(pArray, aGameArrays[tw].pValues, GAR_ELTSZ * oldSize); + Bmemcpy(pArray, aGameArrays[tw].pValues, eltSize * oldSize); Baligned_free(aGameArrays[tw].pValues); - aGameArrays[tw].pValues = newSize != 0 ? (intptr_t *)Xaligned_alloc(ACTOR_VAR_ALIGNMENT, GAR_ELTSZ * newSize) : NULL; + aGameArrays[tw].pValues = newSize != 0 ? (intptr_t *)Xaligned_alloc(ACTOR_VAR_ALIGNMENT, eltSize * newSize) : NULL; aGameArrays[tw].size = newSize; if (oldSize != 0) - Bmemcpy(aGameArrays[tw].pValues, pArray, GAR_ELTSZ * min(oldSize, newSize)); + Bmemcpy(aGameArrays[tw].pValues, pArray, eltSize * min(oldSize, newSize)); if (newSize > oldSize) - Bmemset(&aGameArrays[tw].pValues[oldSize], 0, GAR_ELTSZ * (newSize - oldSize)); + Bmemset(&aGameArrays[tw].pValues[oldSize], 0, eltSize * (newSize - oldSize)); Bfree(pArray); } @@ -4762,28 +4808,6 @@ finish_qsprintf: int destArrayIndex = Gv_GetVarX(*insptr++); int numElements = Gv_GetVarX(*insptr++); - tw = 0; - - if (EDUKE32_PREDICT_FALSE((unsigned)srcArray>=(unsigned)g_gameArrayCount)) - { - CON_ERRPRINTF("Invalid array %d!", srcArray); - tw = 1; - } - - if (EDUKE32_PREDICT_FALSE((unsigned)destArray>=(unsigned)g_gameArrayCount)) - { - CON_ERRPRINTF("Invalid array %d!", destArray); - tw = 1; - } - - if (EDUKE32_PREDICT_FALSE(aGameArrays[destArray].flags & GAMEARRAY_READONLY)) - { - CON_ERRPRINTF("Array %d is read-only!", destArray); - tw = 1; - } - - if (EDUKE32_PREDICT_FALSE(tw)) continue; // dirty replacement for VMFLAG_ERROR - int const srcArraySize = (aGameArrays[srcArray].flags & GAMEARRAY_VARSIZE) ? Gv_GetVarX(aGameArrays[srcArray].size) : aGameArrays[srcArray].size; @@ -4802,75 +4826,36 @@ finish_qsprintf: numElements = destArraySize - destArrayIndex; // Switch depending on the source array type. - switch (aGameArrays[srcArray].flags & GAMEARRAY_TYPE_MASK) + + int const srcInc = 1 << (int)!!(EDUKE32_PREDICT_FALSE(aGameArrays[srcArray].flags & GAMEARRAY_STRIDE2)); + int const destInc = 1 << (int)!!(EDUKE32_PREDICT_FALSE(aGameArrays[destArray].flags & GAMEARRAY_STRIDE2)); + + // matching array types and no STRIDE2 flag + if ((aGameArrays[srcArray].flags & GAMEARRAY_TYPE_MASK) == (aGameArrays[destArray].flags & GAMEARRAY_TYPE_MASK) && (srcInc & destInc) == 1) + { + Bmemcpy(aGameArrays[destArray].pValues + destArrayIndex, aGameArrays[srcArray].pValues + srcArrayIndex, + numElements * Gv_GetArrayElementSize(srcArray)); + } + else switch (aGameArrays[destArray].flags & GAMEARRAY_TYPE_MASK) { case 0: - // CON array to CON array. - if (EDUKE32_PREDICT_FALSE(aGameArrays[srcArray].flags & GAMEARRAY_STRIDE2)) - { - for (; numElements>0; --numElements) - { - (aGameArrays[destArray].pValues)[destArrayIndex++] = - ((int32_t *)aGameArrays[srcArray].pValues)[srcArrayIndex += 2]; - } - break; - } - Bmemcpy(aGameArrays[destArray].pValues+destArrayIndex, aGameArrays[srcArray].pValues+srcArrayIndex, numElements*GAR_ELTSZ); + for (; numElements > 0; --numElements) + aGameArrays[destArray].pValues[destArrayIndex += destInc] = Gv_GetArrayValue(srcArray, srcArrayIndex += srcInc); break; case GAMEARRAY_INT32: - // From int32-sized array. Note that the CON array element - // type is intptr_t, so it is different-sized on 64-bit - // archs, but same-sized on 32-bit ones. - if (EDUKE32_PREDICT_FALSE(aGameArrays[srcArray].flags & GAMEARRAY_STRIDE2)) - { - for (; numElements>0; --numElements) - { - (aGameArrays[destArray].pValues)[destArrayIndex++] = - ((int32_t *)aGameArrays[srcArray].pValues)[srcArrayIndex += 2]; - } - break; - } - for (; numElements>0; --numElements) - { - (aGameArrays[destArray].pValues)[destArrayIndex++] = - ((int32_t *)aGameArrays[srcArray].pValues)[srcArrayIndex++]; - } + for (; numElements > 0; --numElements) + ((int32_t *)aGameArrays[destArray].pValues)[destArrayIndex += destInc] = Gv_GetArrayValue(srcArray, srcArrayIndex += srcInc); break; case GAMEARRAY_INT16: - // From int16_t array. Always different-sized. - if (EDUKE32_PREDICT_FALSE(aGameArrays[srcArray].flags & GAMEARRAY_STRIDE2)) - { - for (; numElements>0; --numElements) - { - (aGameArrays[destArray].pValues)[destArrayIndex++] = - ((int16_t *)aGameArrays[srcArray].pValues)[srcArrayIndex += 2]; - } - break; - } - for (; numElements>0; --numElements) - { - (aGameArrays[destArray].pValues)[destArrayIndex++] = - ((int16_t *)aGameArrays[srcArray].pValues)[srcArrayIndex++]; - } + for (; numElements > 0; --numElements) + ((int16_t *) aGameArrays[destArray].pValues)[destArrayIndex += destInc] = Gv_GetArrayValue(srcArray, srcArrayIndex += srcInc); break; case GAMEARRAY_UINT8: - // From char array. Always different-sized. - if (EDUKE32_PREDICT_FALSE(aGameArrays[srcArray].flags & GAMEARRAY_STRIDE2)) - { - for (; numElements>0; --numElements) - { - (aGameArrays[destArray].pValues)[destArrayIndex++] = - ((uint8_t *)aGameArrays[srcArray].pValues)[srcArrayIndex += 2]; - } - break; - } - for (; numElements>0; --numElements) - { - (aGameArrays[destArray].pValues)[destArrayIndex++] = - ((uint8_t *)aGameArrays[srcArray].pValues)[srcArrayIndex++]; - } + for (; numElements > 0; --numElements) + ((uint8_t *) aGameArrays[destArray].pValues)[destArrayIndex += destInc] = Gv_GetArrayValue(srcArray, srcArrayIndex += srcInc); break; } + continue; } diff --git a/source/duke3d/src/gamevars.cpp b/source/duke3d/src/gamevars.cpp index 7109c4bac..2e00b8873 100644 --- a/source/duke3d/src/gamevars.cpp +++ b/source/duke3d/src/gamevars.cpp @@ -179,8 +179,8 @@ int Gv_ReadSave(int32_t kFile) intptr_t const asize = aGameArrays[i].size; if (asize != 0) { - aGameArrays[i].pValues = (intptr_t *)Xaligned_alloc(ACTOR_VAR_ALIGNMENT, asize * GAR_ELTSZ); - if (kdfread(aGameArrays[i].pValues, GAR_ELTSZ * aGameArrays[i].size, 1, kFile) < 1) goto corrupt; + aGameArrays[i].pValues = (intptr_t *)Xaligned_alloc(ACTOR_VAR_ALIGNMENT, asize * Gv_GetArrayElementSize(i)); + if (kdfread(aGameArrays[i].pValues, Gv_GetArrayElementSize(i) * aGameArrays[i].size, 1, kFile) < 1) goto corrupt; } else aGameArrays[i].pValues = NULL; @@ -287,7 +287,7 @@ void Gv_WriteSave(FILE *fil) dfwrite(&aGameArrays[i],sizeof(gamearray_t),1,fil); dfwrite(aGameArrays[i].szLabel,sizeof(uint8_t) * MAXARRAYLABEL, 1, fil); - dfwrite(aGameArrays[i].pValues, GAR_ELTSZ * aGameArrays[i].size, 1, fil); + dfwrite(aGameArrays[i].pValues, Gv_GetArrayElementSize(i) * aGameArrays[i].size, 1, fil); } dfwrite(apScriptEvents,sizeof(apScriptEvents),1,fil); @@ -407,7 +407,7 @@ int32_t Gv_NewArray(const char *pszLabel, void *pArray, intptr_t arraySize, uint g_warningCnt++; - if (aGameArrays[i].flags & GAMEARRAY_TYPE_MASK) + if (aGameArrays[i].flags & GAMEARRAY_SYSTEM) { C_ReportError(-1); initprintf("ignored redefining system array `%s'.", pszLabel); @@ -421,31 +421,33 @@ int32_t Gv_NewArray(const char *pszLabel, void *pArray, intptr_t arraySize, uint i = g_gameArrayCount; if (aGameArrays[i].szLabel == NULL) - aGameArrays[i].szLabel = (char *)Xcalloc(MAXVARLABEL,sizeof(uint8_t)); + aGameArrays[i].szLabel = (char *)Xcalloc(MAXVARLABEL, sizeof(uint8_t)); if (aGameArrays[i].szLabel != pszLabel) Bstrcpy(aGameArrays[i].szLabel,pszLabel); - if (pArray == NULL) + if (pArray) + aGameArrays[i].pValues = (intptr_t *)pArray; + else { if (aGameArrays[i].flags & GAMEARRAY_ALLOCATED) Baligned_free(aGameArrays[i].pValues); - int typeSize; + int typeSize = 0; - switch (aGameArrays[i].flags & (GAMEARRAY_UINT8 | GAMEARRAY_INT16 | GAMEARRAY_INT32)) + switch (aGameArrays[i].flags & GAMEARRAY_TYPE_MASK) { + case 0: typeSize = sizeof(uintptr_t); break; case GAMEARRAY_UINT8: typeSize = sizeof(uint8_t); break; case GAMEARRAY_INT16: typeSize = sizeof(uint16_t); break; case GAMEARRAY_INT32: typeSize = sizeof(uint32_t); break; - default: typeSize = sizeof(uintptr_t); break; } - aGameArrays[i].pValues = (intptr_t *)Xaligned_alloc(ACTOR_VAR_ALIGNMENT, arraySize * typeSize); - Bmemset(aGameArrays[i].pValues, 0, arraySize * typeSize); + int const allocSize = typeSize ? arraySize * typeSize : (arraySize + 7) >> 3; + + aGameArrays[i].pValues = (intptr_t *) Xaligned_alloc(ACTOR_VAR_ALIGNMENT, allocSize); + Bmemset(aGameArrays[i].pValues, 0, allocSize); } - else - aGameArrays[i].pValues = (intptr_t *)pArray; aGameArrays[i].size = arraySize; aGameArrays[i].flags = nFlags & ~GAMEARRAY_RESET; @@ -567,6 +569,21 @@ static int Gv_GetVarIndex(const char *szGameLabel) return gameVar; } +int __fastcall Gv_GetArrayElementSize(int const arrayIdx) +{ + int typeSize = 0; + + switch (aGameArrays[arrayIdx].flags & GAMEARRAY_TYPE_MASK) + { + case 0: typeSize = sizeof(uintptr_t); break; + case GAMEARRAY_UINT8: typeSize = sizeof(uint8_t); break; + case GAMEARRAY_INT16: typeSize = sizeof(uint16_t); break; + case GAMEARRAY_INT32: typeSize = sizeof(uint32_t); break; + } + + return typeSize; +} + int __fastcall Gv_GetArrayValue(int const id, int index) { if (aGameArrays[id].flags & GAMEARRAY_STRIDE2) @@ -1529,10 +1546,10 @@ static void Gv_AddSystemVars(void) # endif // SYSTEM_GAMEARRAY - Gv_NewArray("tilesizx", (void *)&tilesiz[0].x, MAXTILES, GAMEARRAY_STRIDE2|GAMEARRAY_READONLY|GAMEARRAY_INT16); - Gv_NewArray("tilesizy", (void *)&tilesiz[0].y, MAXTILES, GAMEARRAY_STRIDE2|GAMEARRAY_READONLY|GAMEARRAY_INT16); - Gv_NewArray("walock", (void *) &walock[0], MAXTILES, GAMEARRAY_UINT8); - Gv_NewArray("gotpic", (void *) &gotpic[0], MAXTILES, GAMEARRAY_BITMAP); + Gv_NewArray("tilesizx", (void *)&tilesiz[0].x, MAXTILES, GAMEARRAY_SYSTEM|GAMEARRAY_STRIDE2|GAMEARRAY_READONLY|GAMEARRAY_INT16); + Gv_NewArray("tilesizy", (void *)&tilesiz[0].y, MAXTILES, GAMEARRAY_SYSTEM|GAMEARRAY_STRIDE2|GAMEARRAY_READONLY|GAMEARRAY_INT16); + Gv_NewArray("walock", (void *) &walock[0], MAXTILES, GAMEARRAY_SYSTEM|GAMEARRAY_UINT8); + Gv_NewArray("gotpic", (void *) &gotpic[0], MAXTILES, GAMEARRAY_SYSTEM|GAMEARRAY_BITMAP); #endif } diff --git a/source/duke3d/src/gamevars.h b/source/duke3d/src/gamevars.h index 40331d053..625583ae8 100644 --- a/source/duke3d/src/gamevars.h +++ b/source/duke3d/src/gamevars.h @@ -71,6 +71,7 @@ enum GamearrayFlags_t GAMEARRAY_STRIDE2 = 0x00000100, GAMEARRAY_ALLOCATED = 0x00000200, // memory allocated for user array GAMEARRAY_BITMAP = 0x00000400, + GAMEARRAY_SYSTEM = 0x00000800, GAMEARRAY_TYPE_MASK = GAMEARRAY_UINT8 | GAMEARRAY_INT16 | GAMEARRAY_INT32 | GAMEARRAY_BITMAP, }; @@ -96,13 +97,12 @@ typedef struct } gamearray_t; #pragma pack(pop) -# define GAR_ELTSZ (sizeof(aGameArrays[0].pValues[0])) - extern gamevar_t aGameVars[MAXGAMEVARS]; extern gamearray_t aGameArrays[MAXGAMEARRAYS]; extern int32_t g_gameVarCount; extern int32_t g_gameArrayCount; +int __fastcall Gv_GetArrayElementSize(int const arrayIdx); int __fastcall Gv_GetArrayValue(int const id, int index); int __fastcall Gv_GetVar(int id, int spriteNum, int playerNum); void __fastcall Gv_SetVar(int const id, int const lValue, int const spriteNum, int const playerNum); diff --git a/source/duke3d/src/savegame.cpp b/source/duke3d/src/savegame.cpp index 71507460e..a03771836 100644 --- a/source/duke3d/src/savegame.cpp +++ b/source/duke3d/src/savegame.cpp @@ -1204,7 +1204,7 @@ static void sv_makevarspec() numsavedvars += (aGameVars[i].flags&SV_SKIPMASK) ? 0 : 1; for (i=0; i> 3; + svgm_vars[j].cnt = 1; // assumed constant throughout demo, i.e. no RESIZEARRAY + } + else + { + svgm_vars[j].size = plValues == NULL ? 0 : sizeof(aGameArrays[0].pValues[0]); + svgm_vars[j].cnt = aGameArrays[i].size; // assumed constant throughout demo, i.e. no RESIZEARRAY + } j++; }