Some work on CON arrays. Hopefully nothing is broken!

git-svn-id: https://svn.eduke32.com/eduke32@6343 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
terminx 2017-07-08 19:41:43 +00:00
parent 19c58edb40
commit da0cc1b9bd
5 changed files with 161 additions and 150 deletions

View file

@ -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));

View file

@ -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,14 +4644,12 @@ finish_qsprintf:
continue;
}
if (tw == CON_READARRAYFROMFILE)
{
int32_t kFile = kopen4loadfrommod(apStrings[quoteFilename], 0);
int kFile = kopen4loadfrommod(apStrings[quoteFilename], 0);
if (kFile < 0)
continue;
int32_t numElements = kfilelength(kFile) / sizeof(int32_t);
int numElements = kfilelength(kFile) / Gv_GetArrayElementSize(arrayNum);
if (numElements == 0)
{
@ -4662,27 +4659,56 @@ finish_qsprintf:
}
else if (numElements > 0)
{
int const numBytes = numElements * sizeof(int32_t);
#ifdef BITNESS64
int32_t *pArray = (int32_t *)Xcalloc(numElements, sizeof(int32_t));
kread(kFile, pArray, numBytes);
#endif
int const numBytes = numElements * Gv_GetArrayElementSize(arrayNum);
Baligned_free(aGameArrays[arrayNum].pValues);
aGameArrays[arrayNum].pValues = (intptr_t *)Xaligned_alloc(ACTOR_VAR_ALIGNMENT, numElements * GAR_ELTSZ);
aGameArrays[arrayNum].pValues = (intptr_t *)Xaligned_alloc(ACTOR_VAR_ALIGNMENT, numElements * Gv_GetArrayElementSize(arrayNum));
aGameArrays[arrayNum].size = numElements;
switch (aGameArrays[arrayNum].flags & GAMEARRAY_TYPE_MASK)
{
case 0:
#ifdef BITNESS64
{
int32_t * const pArray = (int32_t *)Xcalloc(1, numBytes);
kread(kFile, pArray, numBytes);
for (bssize_t i = 0; i < numElements; i++)
aGameArrays[arrayNum].pValues[i] = pArray[i]; // int32_t --> int64_t
aGameArrays[arrayNum].pValues[i] = pArray[i];
Bfree(pArray);
#else
kread(kFile, aGameArrays[arrayNum].pValues, numBytes);
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;
}
char temp[BMAX_PATH];
if (EDUKE32_PREDICT_FALSE(G_ModDirSnprintf(temp, sizeof(temp), "%s", apStrings[quoteFilename])))
@ -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++)
switch (aGameArrays[arrayNum].flags & GAMEARRAY_TYPE_MASK)
{
case 0:
#ifdef BITNESS64
{
int32_t * const pArray = (int32_t *)Xmalloc(numBytes);
for (bssize_t k = 0; k < numElements; k++)
pArray[k] = Gv_GetArrayValue(arrayNum, k);
fwrite(pArray, 1, sizeof(int32_t) * arraySize, fil);
Bfwrite(pArray, 1, numBytes, fil);
Bfree(pArray);
fclose(fil);
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;
}

View file

@ -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
}

View file

@ -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);

View file

@ -1204,7 +1204,7 @@ static void sv_makevarspec()
numsavedvars += (aGameVars[i].flags&SV_SKIPMASK) ? 0 : 1;
for (i=0; i<g_gameArrayCount; i++)
numsavedarrays += !(aGameArrays[i].flags & GAMEARRAY_READONLY); // SYSTEM_GAMEARRAY
numsavedarrays += !(aGameArrays[i].flags & (GAMEARRAY_SYSTEM|GAMEARRAY_READONLY)); // SYSTEM_GAMEARRAY
Bfree(svgm_vars);
svgm_vars = (dataspec_gv_t *)Xmalloc((numsavedvars+numsavedarrays+2)*sizeof(dataspec_gv_t));
@ -1233,14 +1233,23 @@ static void sv_makevarspec()
// We must not update read-only SYSTEM_GAMEARRAY gamearrays: besides
// being questionable by itself, sizeof(...) may be e.g. 4 whereas the
// actual element type is int16_t (such as tilesizx[]/tilesizy[]).
if (aGameArrays[i].flags & GAMEARRAY_READONLY)
if (aGameArrays[i].flags & (GAMEARRAY_SYSTEM|GAMEARRAY_READONLY))
continue;
intptr_t * const plValues = aGameArrays[i].pValues;
svgm_vars[j].flags = 0;
svgm_vars[j].ptr = plValues;
if (aGameArrays[i].flags & GAMEARRAY_BITMAP)
{
svgm_vars[j].size = (aGameArrays[i].size + 7) >> 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++;
}