- gamevars should be working now, there was a bad case of out of bounds access in the implementation

This commit is contained in:
Christoph Oelckers 2020-05-13 21:24:17 +02:00
parent d3652f0ed9
commit 3c8c7acaf8
4 changed files with 69 additions and 76 deletions

View file

@ -21,7 +21,6 @@ set( PCH_SOURCES
src/zz_game.cpp src/zz_game.cpp
src/zz_gamedef.cpp src/zz_gamedef.cpp
src/zz_gameexec.cpp src/zz_gameexec.cpp
src/zz_gamevars.cpp
src/zz_global.cpp src/zz_global.cpp
src/zz_interpolate.cpp src/zz_interpolate.cpp
src/zz_namesdyn.cpp src/zz_namesdyn.cpp

View file

@ -67,12 +67,32 @@ spritetype *g_sp;
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// //
// to do //
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void SerializeGameVars(FSerializer &arc) void SerializeGameVars(FSerializer &arc)
{ {
if (arc.BeginObject("gamevars"))
{
// Only save the ones which hold their own data, i.e. skip pointer variables.
for (auto& gv : aGameVars)
{
if (!(gv.dwFlags & GAMEVAR_FLAG_PLONG))
{
if (arc.BeginObject(gv.szLabel))
{
arc("value", gv.lValue);
if (gv.dwFlags & (GAMEVAR_FLAG_PERPLAYER | GAMEVAR_FLAG_PERACTOR))
{
arc("array", gv.plArray);
}
arc.EndObject();
}
}
}
arc.EndObject();
}
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -81,31 +101,31 @@ void SerializeGameVars(FSerializer &arc)
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool AddGameVar(const char *pszLabel, intptr_t lValue, unsigned dwFlags) bool AddGameVar(const char* pszLabel, intptr_t lValue, unsigned dwFlags)
{ {
int i; int i;
int j; int j;
int b=0; int b = 0;
if(dwFlags & GAMEVAR_FLAG_PLONG) if (dwFlags & GAMEVAR_FLAG_PLONG)
dwFlags|=GAMEVAR_FLAG_SYSTEM; // force system if PLONG dwFlags |= GAMEVAR_FLAG_SYSTEM; // force system if PLONG
if(strlen(pszLabel) > (MAXVARLABEL-1) ) if (strlen(pszLabel) > (MAXVARLABEL - 1))
{ {
warningcount++; warningcount++;
Printf(TEXTCOLOR_RED " * WARNING.(L%ld) Variable Name '%s' too int (max is %d)\n", line_number, pszLabel, MAXVARLABEL - 1); Printf(TEXTCOLOR_RED " * WARNING.(L%ld) Variable Name '%s' too int (max is %d)\n", line_number, pszLabel, MAXVARLABEL - 1);
return 0; return 0;
} }
for(i=0;i<iGameVarCount;i++) for (i = 0; i < iGameVarCount; i++)
{ {
if( strcmp(pszLabel,aGameVars[i].szLabel) == 0 ) if (strcmp(pszLabel, aGameVars[i].szLabel) == 0)
{ {
// found it... // found it...
if( (aGameVars[i].dwFlags & GAMEVAR_FLAG_DEFAULT) if ((aGameVars[i].dwFlags & GAMEVAR_FLAG_DEFAULT)
|| (aGameVars[i].dwFlags & GAMEVAR_FLAG_SYSTEM) || (aGameVars[i].dwFlags & GAMEVAR_FLAG_SYSTEM)
) )
{ {
// it's OK to replace // it's OK to replace
break; break;
@ -114,60 +134,60 @@ bool AddGameVar(const char *pszLabel, intptr_t lValue, unsigned dwFlags)
{ {
// it's a duplicate in error // it's a duplicate in error
errorcount++; errorcount++;
Printf(TEXTCOLOR_RED " * ERROR.(L%ld) Duplicate Game definition '%s' ignored.\n",line_number,pszLabel); Printf(TEXTCOLOR_RED " * ERROR.(L%ld) Duplicate Game definition '%s' ignored.\n", line_number, pszLabel);
return 0; return 0;
} }
} }
} }
if( i < MAXGAMEVARS) if (i < MAXGAMEVARS)
{ {
// Set values // Set values
if(aGameVars[i].dwFlags & GAMEVAR_FLAG_SYSTEM && !(dwFlags & GAMEVAR_FLAG_PLONG)) if (aGameVars[i].dwFlags & GAMEVAR_FLAG_SYSTEM && !(dwFlags & GAMEVAR_FLAG_PLONG))
{ {
// if existing is system, they only get to change default value.... // if existing is system, they only get to change default value....
aGameVars[i].lValue=lValue; aGameVars[i].lValue = lValue;
if(!(dwFlags & GAMEVAR_FLAG_NODEFAULT)) if (!(dwFlags & GAMEVAR_FLAG_NODEFAULT))
{
aGameVars[i].defaultValue=lValue;
}
}
else
{
strcpy(aGameVars[i].szLabel,pszLabel);
aGameVars[i].dwFlags=dwFlags;
if (dwFlags & GAMEVAR_FLAG_PLONG)
{
aGameVars[i].plValue=(int*)lValue;
}
else
{
aGameVars[i].lValue=lValue;
}
if(!(dwFlags & GAMEVAR_FLAG_NODEFAULT))
{ {
aGameVars[i].defaultValue = lValue; aGameVars[i].defaultValue = lValue;
} }
} }
else
if(i==iGameVarCount) {
strcpy(aGameVars[i].szLabel, pszLabel);
aGameVars[i].dwFlags = dwFlags;
if (dwFlags & GAMEVAR_FLAG_PLONG)
{
aGameVars[i].plValue = (int*)lValue;
}
else
{
aGameVars[i].lValue = lValue;
}
if (!(dwFlags & GAMEVAR_FLAG_NODEFAULT))
{
aGameVars[i].defaultValue = lValue;
}
}
if (i == iGameVarCount)
{ {
// we're adding a new one. // we're adding a new one.
iGameVarCount++; iGameVarCount++;
} }
if(!(aGameVars[i].dwFlags & GAMEVAR_FLAG_SYSTEM)) if (!(aGameVars[i].dwFlags & GAMEVAR_FLAG_SYSTEM))
{ {
// only free if not system // only free if not system
aGameVars[i].plArray.Reset(); aGameVars[i].plArray.Reset();
} }
if(aGameVars[i].dwFlags & GAMEVAR_FLAG_PERPLAYER) if (aGameVars[i].dwFlags & GAMEVAR_FLAG_PERPLAYER)
{ {
aGameVars[i].plArray.Resize(MAXPLAYERS); aGameVars[i].plArray.Resize(MAXPLAYERS);
for(j=0;j<MAXPLAYERS;j++) for (j = 0; j < MAXPLAYERS; j++)
{ {
aGameVars[i].plArray[j]=lValue; aGameVars[i].plArray[j] = lValue;
} }
} }
else if( aGameVars[i].dwFlags & GAMEVAR_FLAG_PERACTOR) else if (aGameVars[i].dwFlags & GAMEVAR_FLAG_PERACTOR)
{ {
aGameVars[i].plArray.Resize(MAXSPRITES); aGameVars[i].plArray.Resize(MAXSPRITES);
for (j = 0; j < MAXSPRITES; j++) for (j = 0; j < MAXSPRITES; j++)
@ -176,14 +196,12 @@ bool AddGameVar(const char *pszLabel, intptr_t lValue, unsigned dwFlags)
} }
} }
return 1; return 1;
} }
else else
{ {
// no room to add... // no room to add...
return 0; return 0;
} }
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -230,30 +248,6 @@ int GetDefID(const char *szGameLabel)
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void FreeGameVars(void)
{
// call this function as many times as needed.
int i;
for(i=0;i<MAXGAMEVARS;i++)
{
if(!(aGameVars[i].dwFlags & GAMEVAR_FLAG_SYSTEM))
{
aGameVars[i].lValue=0;
aGameVars[i].szLabel[0]=0;
aGameVars[i].dwFlags=0;
}
aGameVars[i].plValue=NULL;
}
iGameVarCount=0;
return;
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void ClearGameVars(void) void ClearGameVars(void)
{ {
// only call this function ONCE (at game init)... // only call this function ONCE (at game init)...
@ -274,7 +268,6 @@ void ClearGameVars(void)
// "utterly broken by design" ... // "utterly broken by design" ...
// I hope this version is saner, there's really no need to tear down and // I hope this version is saner, there's really no need to tear down and
// rebuild the complete set of game vars just to reset them to the defaults... // rebuild the complete set of game vars just to reset them to the defaults...
// It makes no sense anyway for actor gamevars because the actor list is dynamic.
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -370,12 +363,14 @@ void SetGameVarID(int id, int lValue, int sActor, int sPlayer)
if( aGameVars[id].dwFlags & GAMEVAR_FLAG_PERPLAYER ) if( aGameVars[id].dwFlags & GAMEVAR_FLAG_PERPLAYER )
{ {
// for the current player // for the current player
aGameVars[id].plArray[sPlayer]=lValue; if (sPlayer >= 0) aGameVars[id].plArray[sPlayer] = lValue;
else for (auto& i : aGameVars[id].plArray) i = lValue; // -1 sets all players - was undefined OOB access in WW2GI.
} }
else if( aGameVars[id].dwFlags & GAMEVAR_FLAG_PERACTOR ) else if( aGameVars[id].dwFlags & GAMEVAR_FLAG_PERACTOR )
{ {
// for the current actor // for the current actor
aGameVars[id].plArray[sActor]=lValue; if (sActor >= 0) aGameVars[id].plArray[sActor]=lValue;
else for (auto& i : aGameVars[id].plArray) i = lValue; // -1 sets all actors - was undefined OOB access in WW2GI.
} }
else if( aGameVars[id].dwFlags & GAMEVAR_FLAG_PLONG ) else if( aGameVars[id].dwFlags & GAMEVAR_FLAG_PLONG )
{ {
@ -422,7 +417,7 @@ int *GetGameValuePtr(char *szGameLabel)
{ {
if(aGameVars[i].dwFlags & (GAMEVAR_FLAG_PERACTOR | GAMEVAR_FLAG_PERPLAYER)) if(aGameVars[i].dwFlags & (GAMEVAR_FLAG_PERACTOR | GAMEVAR_FLAG_PERPLAYER))
{ {
if(!aGameVars[i].plArray.Size() == 0) if(aGameVars[i].plArray.Size() == 0)
{ {
Printf("INTERNAL ERROR: NULL array !!!\n"); Printf("INTERNAL ERROR: NULL array !!!\n");
} }
@ -566,7 +561,7 @@ void InitGameVarPointers(void)
char aszBuf[64]; char aszBuf[64];
// called from game Init AND when level is loaded... // called from game Init AND when level is loaded...
for(i=0;i<MAX_WEAPONS;i++) for(i=0;i<12/*MAX_WEAPONS*/;i++) // Setup only exists for the original 12 weapons.
{ {
sprintf(aszBuf,"WEAPON%d_CLIP",i); sprintf(aszBuf,"WEAPON%d_CLIP",i);
aplWeaponClip[i]=GetGameValuePtr(aszBuf); aplWeaponClip[i]=GetGameValuePtr(aszBuf);
@ -1230,7 +1225,7 @@ void ResetSystemDefaults(void)
for(j=0;j<MAXPLAYERS;j++) for(j=0;j<MAXPLAYERS;j++)
{ {
for(i=0;i<MAX_WEAPONS;i++) for(i=0;i<12/*MAX_WEAPONS*/;i++)
{ {
sprintf(aszBuf,"WEAPON%d_CLIP",i); sprintf(aszBuf,"WEAPON%d_CLIP",i);
aplWeaponClip[i][j]=GetGameVar(aszBuf,0, -1, j); aplWeaponClip[i][j]=GetGameVar(aszBuf,0, -1, j);

View file

@ -169,7 +169,6 @@ extern uint8_t killit_flag;
bool AddGameVar(const char *pszLabel, intptr_t lValue, unsigned dwFlags); bool AddGameVar(const char *pszLabel, intptr_t lValue, unsigned dwFlags);
int GetGameID(const char *szGameLabel); int GetGameID(const char *szGameLabel);
int GetDefID(const char *szGameLabel); int GetDefID(const char *szGameLabel);
void FreeGameVars(void);
void ClearGameVars(void); void ClearGameVars(void);
void AddSystemVars(); void AddSystemVars();
void ResetGameVars(void); void ResetGameVars(void);

View file

@ -1939,7 +1939,7 @@ end_vol4a:
if (m_coop != 1) if (m_coop != 1)
{ {
for (bssize_t weaponNum = 0; weaponNum < MAX_WEAPONS; weaponNum++) for (bssize_t weaponNum = 0; weaponNum < 12/*MAX_WEAPONS*/; weaponNum++)
{ {
auto const worksLike = WW2GI ? PWEAPON(0, weaponNum, WorksLike) : weaponNum; auto const worksLike = WW2GI ? PWEAPON(0, weaponNum, WorksLike) : weaponNum;
if (worksLike == PISTOL_WEAPON) if (worksLike == PISTOL_WEAPON)