array support based on a patch from Peter Green (plugwash)

git-svn-id: https://svn.eduke32.com/eduke32@676 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
terminx 2008-04-01 02:50:44 +00:00
parent ad97b339cc
commit 91145d9582
7 changed files with 317 additions and 13 deletions

View file

@ -798,9 +798,13 @@ enum events {
// store global game definitions
enum gamevarflags {
MAXGAMEVARS = 2048,
MAXGAMEVARS = 2048, // must be a power of two
MAXGAMEARRAYS = 256, // must be lower than MAXGAMEVARS
MAXVARLABEL = 26,
MAXARRAYLABEL = 26,
GAMEVAR_FLAG_NORMAL = 0, // normal
GAMEVAR_FLAG_PERPLAYER = 1, // per-player variable
GAMEVAR_FLAG_PERACTOR = 2, // per-actor variable
@ -824,9 +828,16 @@ typedef struct {
char *szLabel;
char bReset;
} gamevar_t;
typedef struct {
char *szLabel;
int *plValues; // array of values
int size;
char bReset;
} gamearray_t;
extern gamevar_t aGameVars[MAXGAMEVARS];
extern gamearray_t aGameArrays[MAXGAMEARRAYS];
extern int iGameVarCount;
extern int iGameArrayCount;
extern int spriteflags[MAXTILES];

View file

@ -220,7 +220,10 @@ extern int ReadGameVars(int fil);
extern int GetGameVarID(int id, int iActor, int iPlayer);
extern void SetGameVarID(int id, int lValue, int iActor, int iPlayer);
extern void SetGameArrayID(int id,int index, int lValue);
extern int AddGameVar(const char *pszLabel, int lValue, unsigned int dwFlags);
extern int AddGameArray(const char *pszLabel, int asize);
extern void ReportError(int iError);
extern void onvideomodechange(int newmode);

View file

@ -9648,6 +9648,14 @@ static void freeconmem(void)
Bfree(aGameVars[i].plValues);
}
for (i=iGameArrayCount-1;i>=0;i--)
{
if (aGameArrays[i].szLabel != NULL)
Bfree(aGameArrays[i].szLabel);
if (aGameArrays[i].plValues != NULL)
Bfree(aGameArrays[i].plValues);
}
for (i=MAXPLAYERS-1;i>=0;i--)
{
if (g_player[i].ps != NULL)

View file

@ -80,7 +80,9 @@ intptr_t *apScriptGameEvent[MAXGAMEEVENTS];
intptr_t *parsing_event=NULL;
gamevar_t aGameVars[MAXGAMEVARS];
gamearray_t aGameArrays[MAXGAMEARRAYS];
int iGameVarCount=0;
int iGameArrayCount=0;
extern int qsetmode;
@ -443,6 +445,8 @@ static const char *keyw[] =
"spritenopal", // 313
"hitradiusvar", // 314
"rotatesprite16", // 315
"gamearray", // 316
"setarray", // 317
"<null>"
};
@ -1203,7 +1207,23 @@ static int GetDefID(const char *szGameLabel)
}
return -1;
}
static int GetADefID(const char *szGameLabel)
{
int i;
// initprintf("iGameArrayCount is %i\n",iGameArrayCount);
for (i=0;i<iGameArrayCount;i++)
{
if (aGameArrays[i].szLabel != NULL)
{
if (Bstrcmp(szGameLabel, aGameArrays[i].szLabel) == 0)
{
return i;
}
}
}
// initprintf("game array %s not found\n",szGameLabel);
return -1;
}
static int ispecial(char c)
{
if (c == 0x0a)
@ -1274,7 +1294,7 @@ static void getlabel(void)
}
i = 0;
while (ispecial(*textptr) == 0 && *textptr!=']' && *textptr!='\t' && *textptr!='\n' && *textptr!='\r')
while (ispecial(*textptr) == 0 && *textptr!='['&& *textptr!=']' && *textptr!='\t' && *textptr!='\n' && *textptr!='\r')
label[(labelcnt<<6)+i++] = *(textptr++);
label[(labelcnt<<6)+i] = 0;
@ -1404,6 +1424,7 @@ static void transvartype(int type)
}
}
getlabel();
if (!nokeywordcheck)
for (i=0;i<NUMKEYWORDS;i++)
if (Bstrcmp(label+(labelcnt<<6),keyw[i]) == 0)
@ -1412,11 +1433,50 @@ static void transvartype(int type)
ReportError(ERROR_ISAKEYWORD);
return;
}
skipcomments(); //skip comments and whitespace
if ((*textptr == '[')) //read of array as a gamevar
{
// initprintf("got an array");
textptr++;
i=GetADefID(label+(labelcnt<<6));
if (i >= 0)
{
*scriptptr++=i+1+MAXGAMEVARS;
transvartype(0);
}
else
{
error++;
ReportError(ERROR_NOTAGAMEARRAY);
return;
}
skipcomments(); //skip comments and whitespace
if (*textptr != ']')
{
error++;
ReportError(ERROR_GAMEARRAYBNC);
return;
}
textptr++;
if (type) //writing arrays in this way is not supported because it would require too many changes to other code
{
error++;
ReportError(ERROR_INVALIDARRAYWRITE);
return;
}
return;
}
// initprintf("not an array");
i=GetDefID(label+(labelcnt<<6));
if (i<0)
if (i<0) //gamevar not found
{
if (!type && !labelsonly)
{
//try looking for a define instead
Bstrcpy(tempbuf,label+(labelcnt<<6));
for (i=0;i<labelcnt;i++)
{
@ -1426,19 +1486,18 @@ static void transvartype(int type)
initprintf("%s:%d: debug: accepted defined label `%s' instead of gamevar.\n",compilefile,line_number,label+(i<<6));
*scriptptr++=MAXGAMEVARS;
*scriptptr++=labelcode[i];
textptr++;
return;
}
}
error++;
ReportError(ERROR_NOTAGAMEVAR);
textptr++;
return;
}
error++;
ReportError(ERROR_NOTAGAMEVAR);
textptr++;
return;
}
if (type == GAMEVAR_FLAG_READONLY && aGameVars[i].dwFlags & GAMEVAR_FLAG_READONLY)
{
@ -1866,6 +1925,35 @@ static int parsecommand(void)
scriptptr -= 3; // no need to save in script...
return 0;
case CON_GAMEARRAY:
if (isdigit(*textptr) || (*textptr == '-'))
{
getlabel();
error++;
ReportError(ERROR_SYNTAXERROR);
transnum(LABEL_DEFINE);
transnum(LABEL_DEFINE);
scriptptr -= 3; // we complete the process anyways just to skip past the fucked up section
return 0;
}
getlabel();
//printf("Got Label '%.20s'\n",textptr);
// Check to see it's already defined
for (i=0;i<NUMKEYWORDS;i++)
if (Bstrcmp(label+(labelcnt<<6),keyw[i]) == 0)
{
error++;
ReportError(ERROR_ISAKEYWORD);
return 0;
}
transnum(LABEL_DEFINE);
AddGameArray(label+(labelcnt<<6),*(scriptptr-1));
scriptptr -= 2; // no need to save in script...
return 0;
case CON_DEFINE:
{
//printf("Got definition. Getting Label. '%.20s'\n",textptr);
@ -3255,6 +3343,34 @@ static int parsecommand(void)
transnum(LABEL_DEFINE); // the number to check against...
return 0;
case CON_SETARRAY:
getlabel();
i=GetADefID(label+(labelcnt<<6));
if (i > (-1))
{
*scriptptr++=i;
}
else
ReportError(ERROR_NOTAGAMEARRAY);
skipcomments();// skip comments and whitespace
if (*textptr != '[')
{
error++;
ReportError(ERROR_GAMEARRAYBNO);
return 1;
}
textptr++;
transvar();
skipcomments();// skip comments and whitespace
if (*textptr != ']')
{
error++;
ReportError(ERROR_GAMEARRAYBNC);
return 1;
}
textptr++;
transvar();
return 0;
case CON_RANDVARVAR:
if (!CheckEventSync(current_event))
ReportError(WARNING_EVENTSYNC);
@ -3697,7 +3813,9 @@ static int parsecommand(void)
j=CountCaseStatements();
// initprintf("Done Counting Case Statements for switch %d: found %d.\n", checking_switch,j);
scriptptr+=j*2;skipcomments();scriptptr-=j*2; // allocate buffer for the table
scriptptr+=j*2;
skipcomments();
scriptptr-=j*2; // allocate buffer for the table
tempscrptr = (intptr_t *)(script+tempoffset);
//AddLog(g_szBuf);
@ -5127,6 +5245,18 @@ void ReportError(int iError)
case ERROR_NOTAGAMEVAR:
initprintf("%s:%d: error: symbol `%s' is not a game variable.\n",compilefile,line_number,label+(labelcnt<<6));
break;
case ERROR_NOTAGAMEARRAY:
initprintf("%s:%d: error: symbol `%s' is not a game array.\n",compilefile,line_number,label+(labelcnt<<6));
break;
case ERROR_GAMEARRAYBNC:
initprintf("%s:%d: error: square brackets for index of game array not closed, expected ] found %c\n",compilefile,line_number,*textptr);
break;
case ERROR_GAMEARRAYBNO:
initprintf("%s:%d: error: square brackets for index of game array not opened, expected [ found %c\n",compilefile,line_number,*textptr);
break;
case ERROR_INVALIDARRAYWRITE:
initprintf("%s:%d: error: arrays can only be written using setarray %c\n",compilefile,line_number,*textptr);
break;
case ERROR_OPENBRACKET:
initprintf("%s:%d: error: found more `{' than `}' before `%s'.\n",compilefile,line_number,tempbuf);
break;

View file

@ -83,6 +83,10 @@ enum errors
ERROR_NOENDSWITCH,
ERROR_NOTAGAMEDEF,
ERROR_NOTAGAMEVAR,
ERROR_NOTAGAMEARRAY,
ERROR_GAMEARRAYBNC,
ERROR_GAMEARRAYBNO,
ERROR_INVALIDARRAYWRITE,
ERROR_OPENBRACKET,
ERROR_PARAMUNDEFINED,
ERROR_SYMBOLNOTRECOGNIZED,
@ -801,5 +805,6 @@ enum keywords
CON_SPRITENOPAL, // 313
CON_HITRADIUSVAR, // 314
CON_ROTATESPRITE16, // 315
END
CON_GAMEARRAY, // 316
CON_SETARRAY, // 317
};

View file

@ -6758,6 +6758,16 @@ static int parse(void)
SetGameVarID(*insptr, *(insptr+1), g_i, g_p);
insptr += 2;
break;
case CON_SETARRAY:
insptr++;
j=*insptr++;
{
int index = GetGameVarID(*insptr++, g_i, g_p);
int value = GetGameVarID(*insptr++, g_i, g_p);
SetGameArrayID(j,index,value);
break;
}
case CON_RANDVAR:
insptr++;
@ -7273,8 +7283,13 @@ static int parse(void)
break;
default:
OSD_Printf("fatal error: default processing: prev inst: %d, curr inst: %d, next inst: %d\ncurrent actor: %d (%d)\n",*(insptr-1),*insptr,*(insptr+1),g_i,g_sp->picnum);
gameexit("An error has occurred in the EDuke32 CON executor.\n\nPlease mail all of your CON files along with the file eduke32.log\nto terminx@gmail.com.\n\nThank you.");
OSD_Printf("fatal error: default processing: previous five values: %d, %d, %d, %d, %d, currrent opcode: %d, next five values: %d, %d, %d, %d, %d\ncurrent actor: %d (%d)\n",*(insptr-5),*(insptr-4),*(insptr-3),*(insptr-2),*(insptr-1),*insptr,*(insptr+1),*(insptr+2),*(insptr+3),*(insptr+4),*(insptr+5),g_i,g_sp->picnum);
gameexit("An error has occurred in the EDuke32 CON executor.\n\n\
If you are an end user, please e-mail the file eduke32.log\n\
along with links to any mods you're using to terminx@gmail.com.\n\n\
If you are a mod developer, please attach all of your CON files\n\
along with instructions on how to reproduce this error.\n\n\
Thank you.");
break;
}
return 0;

View file

@ -49,6 +49,14 @@ static void FreeGameVars(void)
aGameVars[i].bReset=1;
}
iGameVarCount=0;
for (i=0;i<MAXGAMEARRAYS;i++)
{
if (aGameArrays[i].plValues)
Bfree(aGameArrays[i].plValues);
aGameArrays[i].plValues=NULL;
aGameArrays[i].bReset=1;
}
iGameArrayCount=0;
return;
}
@ -73,6 +81,18 @@ static void ClearGameVars(void)
aGameVars[i].bReset=1;
}
iGameVarCount=0;
for (i=0;i<MAXGAMEARRAYS;i++)
{
if (aGameArrays[i].szLabel)
Bfree(aGameArrays[i].szLabel);
aGameArrays[i].szLabel=NULL;
if (aGameArrays[i].plValues)
Bfree(aGameArrays[i].plValues);
aGameArrays[i].plValues=NULL;
aGameArrays[i].bReset=1;
}
iGameArrayCount=0;
return;
}
@ -132,6 +152,29 @@ int ReadGameVars(int fil)
ResetPointerVars();
if (kdfread(&iGameArrayCount,sizeof(iGameArrayCount),1,fil) != 1) goto corrupt;
for (i=0;i<iGameArrayCount;i++)
{
if (kdfread(&(aGameArrays[i]),sizeof(gamearray_t),1,fil) != 1) goto corrupt;
aGameArrays[i].szLabel=Bcalloc(MAXARRAYLABEL,sizeof(char));
if (kdfread(aGameArrays[i].szLabel,sizeof(char) * MAXARRAYLABEL, 1, fil) != 1) goto corrupt;
}
// Bsprintf(g_szBuf,"CP:%s %d",__FILE__,__LINE__);
// AddLog(g_szBuf);
for (i=0;i<iGameArrayCount;i++)
{
aGameArrays[i].plValues=Bcalloc(aGameArrays[i].size,sizeof(int));
}
// Bsprintf(g_szBuf,"CP:%s %d",__FILE__,__LINE__);
// AddLog(g_szBuf);
for (i=0;i<iGameArrayCount;i++)
{
//Bsprintf(g_szBuf,"Reading value array for %s (%d)",aGameVars[i].szLabel,sizeof(int) * MAXPLAYERS);
//AddLog(g_szBuf);
if (kdfread(aGameArrays[i].plValues,sizeof(int) * aGameArrays[i].size, 1, fil) != 1) goto corrupt;
}
// Bsprintf(g_szBuf,"CP:%s %d",__FILE__,__LINE__);
// AddLog(g_szBuf);
if (kdfread(apScriptGameEvent,sizeof(apScriptGameEvent),1,fil) != 1) goto corrupt;
@ -200,6 +243,21 @@ void SaveGameVars(FILE *fil)
// else nothing 'extra...'
}
dfwrite(&iGameArrayCount,sizeof(iGameArrayCount),1,fil);
for (i=0;i<iGameArrayCount;i++)
{
dfwrite(&(aGameArrays[i]),sizeof(gamearray_t),1,fil);
dfwrite(aGameArrays[i].szLabel,sizeof(char) * MAXARRAYLABEL, 1, fil);
}
// dfwrite(&aGameVars,sizeof(aGameVars),1,fil);
for (i=0;i<iGameArrayCount;i++)
{
dfwrite(aGameArrays[i].plValues,sizeof(int) * aGameArrays[i].size, 1, fil);
}
for (i=0;i<MAXGAMEEVENTS;i++)
if (apScriptGameEvent[i])
{
@ -281,6 +339,56 @@ void ResetGameVars(void)
if (aGameVars[i].szLabel != NULL && aGameVars[i].bReset)
AddGameVar(aGameVars[i].szLabel,aGameVars[i].lDefault,aGameVars[i].dwFlags);
}
for (i=0;i<MAXGAMEARRAYS;i++)
{
//Bsprintf(g_szBuf,"Resetting %d: '%s' to %d",i,aDefaultGameVars[i].szLabel,
// aDefaultGameVars[i].lValue
// );
//AddLog(g_szBuf);
if (aGameArrays[i].szLabel != NULL && aGameArrays[i].bReset)
AddGameArray(aGameArrays[i].szLabel,aGameArrays[i].size);
}
}
int AddGameArray(const char *pszLabel, int asize)
{
int i;
if (Bstrlen(pszLabel) > (MAXARRAYLABEL-1))
{
error++;
ReportError(-1);
initprintf("%s:%d: error: array name `%s' exceeds limit of %d characters.\n",compilefile,line_number,pszLabel, MAXARRAYLABEL);
return 0;
}
for (i=0;i<iGameArrayCount;i++)
{
if (aGameVars[i].szLabel != NULL && !aGameArrays[i].bReset)
{
if (Bstrcmp(pszLabel,aGameArrays[i].szLabel) == 0)
{
// found it it's a duplicate in error
warning++;
ReportError(WARNING_DUPLICATEDEFINITION);
return 0;
}
}
}
if (i < MAXGAMEARRAYS)
{
if (aGameArrays[i].szLabel == NULL)
aGameArrays[i].szLabel=Bcalloc(MAXVARLABEL,sizeof(char));
if (aGameArrays[i].szLabel != pszLabel)
Bstrcpy(aGameArrays[i].szLabel,pszLabel);
aGameArrays[i].plValues=Bcalloc(asize,sizeof(int));
aGameArrays[i].size=asize;
aGameVars[i].bReset=0;
iGameArrayCount++;
return 1;
}
return 0;
}
int AddGameVar(const char *pszLabel, int lValue, unsigned int dwFlags)
@ -430,8 +538,21 @@ int GetGameVarID(int id, int iActor, int iPlayer)
if (id<0 || id >= iGameVarCount)
{
if (id==MAXGAMEVARS)
{
// OSD_Printf("GetGameVarID(): reading gamevar constant\n");
return(*insptr++);
}
if (id < MAXGAMEVARS+1+MAXGAMEARRAYS)
{
int index=0;
// OSD_Printf("GetGameVarID(): reading from array\n");
index=GetGameVarID(*insptr++,iActor,iPlayer);
if ((index < aGameArrays[id-MAXGAMEVARS-1].size)&&(index>=0))
inv =aGameArrays[id-MAXGAMEVARS-1].plValues[index];
else
gameexit("array");
return(inv);
}
if (!(id&(MAXGAMEVARS<<1)))
{
OSD_Printf("GetGameVarID(): invalid gamevar ID (%d)\n",id);
@ -491,7 +612,18 @@ int GetGameVarID(int id, int iActor, int iPlayer)
if (inv) return(-aGameVars[id].lValue);
return (aGameVars[id].lValue);
}
void SetGameArrayID(int id,int index, int lValue)
{
if (id<0 || id >= iGameArrayCount)
{
OSD_Printf("SetGameVarID(): tried to set invalid gamevar ID (%d) from sprite %d (%d), player %d\n",id,g_i,sprite[g_i].picnum,g_p);
return;
}
if ((index < aGameArrays[id].size)&&(index>=0))
aGameArrays[id].plValues[index]=lValue;
else
gameexit("array1");
}
void SetGameVarID(int id, int lValue, int iActor, int iPlayer)
{
if (id<0 || id >= iGameVarCount)