Fix ANIMDEFS parsing to allow overwrite.

ANIMATED and ANIMDEFS are now processed in reverse order,
and duplicate definitions in ANIMDEFS are dropped.
This commit is contained in:
Yukita Mayako 2016-10-19 03:17:36 -04:00
parent f72e8a8ff8
commit aa3e52f05e
1 changed files with 66 additions and 45 deletions

View File

@ -221,8 +221,8 @@ static animdef_t harddefs[] =
static animdef_t *animdefs = NULL; static animdef_t *animdefs = NULL;
// A prototype; here instead of p_spec.h, so they're "private" // A prototype; here instead of p_spec.h, so they're "private"
void P_ParseANIMDEFSLump(INT32 wadNum, UINT16 lumpnum, INT32 *i); void P_ParseANIMDEFSLump(INT32 wadNum, UINT16 lumpnum);
void P_ParseAnimationDefintion(SINT8 istexture, INT32 *i); void P_ParseAnimationDefintion(SINT8 istexture);
/** Sets up texture and flat animations. /** Sets up texture and flat animations.
* *
@ -232,24 +232,21 @@ void P_ParseAnimationDefintion(SINT8 istexture, INT32 *i);
* Issues an error if any animation cycles are invalid. * Issues an error if any animation cycles are invalid.
* *
* \sa P_FindAnimatedFlat, P_SetupLevelFlatAnims * \sa P_FindAnimatedFlat, P_SetupLevelFlatAnims
* \author Steven McGranahan (original), Shadow Hog (had to rewrite it to handle multiple WADs) * \author Steven McGranahan (original), Shadow Hog (had to rewrite it to handle multiple WADs), JTE (had to rewrite it to handle multiple WADs _correctly_)
*/ */
void P_InitPicAnims(void) void P_InitPicAnims(void)
{ {
// Init animation // Init animation
INT32 i; // Position in the animdefs array
INT32 w; // WAD INT32 w; // WAD
UINT8 *wadAnimdefs; // not to be confused with animdefs, the combined total of every ANIMATED lump in every WAD, or ANIMDEFS, the ZDoom lump I intend to implement later UINT8 *animatedLump;
UINT8 *currentPos; UINT8 *currentPos;
size_t i;
I_Assert(animdefs == NULL);
if (W_CheckNumForName("ANIMATED") != LUMPERROR || W_CheckNumForName("ANIMDEFS") != LUMPERROR) if (W_CheckNumForName("ANIMATED") != LUMPERROR || W_CheckNumForName("ANIMDEFS") != LUMPERROR)
{ {
if (animdefs) for (w = numwadfiles-1, maxanims = 0; w >= 0; w--)
{
Z_Free(animdefs);
animdefs = NULL;
}
for (w = 0, i = 0, maxanims = 0; w < numwadfiles; w++)
{ {
UINT16 animatedLumpNum; UINT16 animatedLumpNum;
UINT16 animdefsLumpNum; UINT16 animdefsLumpNum;
@ -258,20 +255,20 @@ void P_InitPicAnims(void)
animatedLumpNum = W_CheckNumForNamePwad("ANIMATED", w, 0); animatedLumpNum = W_CheckNumForNamePwad("ANIMATED", w, 0);
if (animatedLumpNum != INT16_MAX) if (animatedLumpNum != INT16_MAX)
{ {
wadAnimdefs = (UINT8 *)W_CacheLumpNumPwad(w, animatedLumpNum, PU_STATIC); animatedLump = (UINT8 *)W_CacheLumpNumPwad(w, animatedLumpNum, PU_STATIC);
// Get the number of animations in the file // Get the number of animations in the file
for (currentPos = wadAnimdefs; *currentPos != UINT8_MAX; maxanims++, currentPos+=23); i = maxanims;
for (currentPos = animatedLump; *currentPos != UINT8_MAX; maxanims++, currentPos+=23);
// Resize animdefs (or if it hasn't been created, create it) // Resize animdefs (or if it hasn't been created, create it)
animdefs = (animdef_t *)Z_Realloc(animdefs, sizeof(animdef_t)*(maxanims + 1), PU_STATIC, NULL); animdefs = (animdef_t *)Z_Realloc(animdefs, sizeof(animdef_t)*(maxanims + 1), PU_STATIC, NULL);
// Sanity check it // Sanity check it
if (!animdefs) { if (!animdefs)
I_Error("Not enough free memory for ANIMATED data"); I_Error("Not enough free memory for ANIMATED data");
}
// Populate the new array // Populate the new array
for (currentPos = wadAnimdefs; *currentPos != UINT8_MAX; i++, currentPos+=23) for (currentPos = animatedLump; *currentPos != UINT8_MAX; i++, currentPos+=23)
{ {
M_Memcpy(&(animdefs[i].istexture), currentPos, 1); // istexture, 1 byte M_Memcpy(&(animdefs[i].istexture), currentPos, 1); // istexture, 1 byte
M_Memcpy(animdefs[i].endname, (currentPos + 1), 9); // endname, 9 bytes M_Memcpy(animdefs[i].endname, (currentPos + 1), 9); // endname, 9 bytes
@ -279,15 +276,13 @@ void P_InitPicAnims(void)
M_Memcpy(&(animdefs[i].speed), (currentPos + 19), 4); // speed, 4 bytes M_Memcpy(&(animdefs[i].speed), (currentPos + 19), 4); // speed, 4 bytes
} }
Z_Free(wadAnimdefs); Z_Free(animatedLump);
} }
// Now find ANIMDEFS // Now find ANIMDEFS
animdefsLumpNum = W_CheckNumForNamePwad("ANIMDEFS", w, 0); animdefsLumpNum = W_CheckNumForNamePwad("ANIMDEFS", w, 0);
if (animdefsLumpNum != INT16_MAX) if (animdefsLumpNum != INT16_MAX)
{ P_ParseANIMDEFSLump(w, animdefsLumpNum);
P_ParseANIMDEFSLump(w, animdefsLumpNum, &i);
}
} }
// Define the last one // Define the last one
animdefs[maxanims].istexture = -1; animdefs[maxanims].istexture = -1;
@ -347,16 +342,20 @@ void P_InitPicAnims(void)
lastanim->istexture = -1; lastanim->istexture = -1;
R_ClearTextureNumCache(false); R_ClearTextureNumCache(false);
// Clear animdefs now that we're done with it.
// We'll only be using anims from now on.
if (animdefs != harddefs) if (animdefs != harddefs)
Z_ChangeTag(animdefs, PU_CACHE); Z_Free(animdefs);
animdefs = NULL;
} }
void P_ParseANIMDEFSLump(INT32 wadNum, UINT16 lumpnum, INT32 *i) void P_ParseANIMDEFSLump(INT32 wadNum, UINT16 lumpnum)
{ {
char *animdefsLump; char *animdefsLump;
size_t animdefsLumpLength; size_t animdefsLumpLength;
char *animdefsText; char *animdefsText;
char *animdefsToken; char *animdefsToken;
char *p;
// Since lumps AREN'T \0-terminated like I'd assumed they should be, I'll // Since lumps AREN'T \0-terminated like I'd assumed they should be, I'll
// need to make a space of memory where I can ensure that it will terminate // need to make a space of memory where I can ensure that it will terminate
@ -376,18 +375,19 @@ void P_ParseANIMDEFSLump(INT32 wadNum, UINT16 lumpnum, INT32 *i)
Z_Free(animdefsLump); Z_Free(animdefsLump);
// Now, let's start parsing this thing // Now, let's start parsing this thing
animdefsToken = M_GetToken(animdefsText); p = animdefsText;
animdefsToken = M_GetToken(p);
while (animdefsToken != NULL) while (animdefsToken != NULL)
{ {
if (stricmp(animdefsToken, "TEXTURE") == 0) if (stricmp(animdefsToken, "TEXTURE") == 0)
{ {
Z_Free(animdefsToken); Z_Free(animdefsToken);
P_ParseAnimationDefintion(1, i); P_ParseAnimationDefintion(1);
} }
else if (stricmp(animdefsToken, "FLAT") == 0) else if (stricmp(animdefsToken, "FLAT") == 0)
{ {
Z_Free(animdefsToken); Z_Free(animdefsToken);
P_ParseAnimationDefintion(0, i); P_ParseAnimationDefintion(0);
} }
else if (stricmp(animdefsToken, "OSCILLATE") == 0) else if (stricmp(animdefsToken, "OSCILLATE") == 0)
{ {
@ -398,23 +398,22 @@ void P_ParseANIMDEFSLump(INT32 wadNum, UINT16 lumpnum, INT32 *i)
{ {
I_Error("Error parsing ANIMDEFS lump: Expected \"TEXTURE\" or \"FLAT\", got \"%s\"",animdefsToken); I_Error("Error parsing ANIMDEFS lump: Expected \"TEXTURE\" or \"FLAT\", got \"%s\"",animdefsToken);
} }
animdefsToken = M_GetToken(NULL); // parse next line
while (*p != '\0' && *p != '\n') ++p;
if (*p == '\n') ++p;
animdefsToken = M_GetToken(p);
} }
Z_Free(animdefsToken); Z_Free(animdefsToken);
Z_Free((void *)animdefsText); Z_Free((void *)animdefsText);
} }
void P_ParseAnimationDefintion(SINT8 istexture, INT32 *i) void P_ParseAnimationDefintion(SINT8 istexture)
{ {
char *animdefsToken; char *animdefsToken;
size_t animdefsTokenLength; size_t animdefsTokenLength;
char *endPos; char *endPos;
INT32 animSpeed; INT32 animSpeed;
size_t i;
// Increase the size to make room for the new animation definition
maxanims++;
animdefs = (animdef_t *)Z_Realloc(animdefs, sizeof(animdef_t)*(maxanims + 1), PU_STATIC, NULL);
animdefs[*i].istexture = istexture;
// Startname // Startname
animdefsToken = M_GetToken(NULL); animdefsToken = M_GetToken(NULL);
@ -448,14 +447,39 @@ void P_ParseAnimationDefintion(SINT8 istexture, INT32 *i)
{ {
I_Error("Error parsing ANIMDEFS lump: lump name \"%s\" exceeds 8 characters", animdefsToken); I_Error("Error parsing ANIMDEFS lump: lump name \"%s\" exceeds 8 characters", animdefsToken);
} }
strncpy(animdefs[*i].startname, animdefsToken, 9);
// Search for existing animdef
for (i = 0; i < maxanims; i++)
if (stricmp(animdefsToken, animdefs[i].startname) == 0)
{
//CONS_Alert(CONS_NOTICE, "Duplicate animation: %s\n", animdefsToken);
// If we weren't parsing in reverse order, we would `break` here and parse the new data into the existing slot we found.
// Instead, we're just going to skip parsing the rest of this line entirely.
Z_Free(animdefsToken);
return;
}
// Not found
if (i == maxanims)
{
// Increase the size to make room for the new animation definition
maxanims++;
animdefs = (animdef_t *)Z_Realloc(animdefs, sizeof(animdef_t)*(maxanims + 1), PU_STATIC, NULL);
strncpy(animdefs[i].startname, animdefsToken, 9);
}
// animdefs[i].startname is now set to animdefsToken either way.
Z_Free(animdefsToken); Z_Free(animdefsToken);
// set texture type
animdefs[i].istexture = istexture;
// "RANGE" // "RANGE"
animdefsToken = M_GetToken(NULL); animdefsToken = M_GetToken(NULL);
if (animdefsToken == NULL) if (animdefsToken == NULL)
{ {
I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where \"RANGE\" after \"%s\"'s startname should be", animdefs[*i].startname); I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where \"RANGE\" after \"%s\"'s startname should be", animdefs[i].startname);
} }
if (stricmp(animdefsToken, "ALLOWDECALS") == 0) if (stricmp(animdefsToken, "ALLOWDECALS") == 0)
{ {
@ -470,7 +494,7 @@ void P_ParseAnimationDefintion(SINT8 istexture, INT32 *i)
} }
if (stricmp(animdefsToken, "RANGE") != 0) if (stricmp(animdefsToken, "RANGE") != 0)
{ {
I_Error("Error parsing ANIMDEFS lump: Expected \"RANGE\" after \"%s\"'s startname, got \"%s\"", animdefs[*i].startname, animdefsToken); I_Error("Error parsing ANIMDEFS lump: Expected \"RANGE\" after \"%s\"'s startname, got \"%s\"", animdefs[i].startname, animdefsToken);
} }
Z_Free(animdefsToken); Z_Free(animdefsToken);
@ -478,21 +502,21 @@ void P_ParseAnimationDefintion(SINT8 istexture, INT32 *i)
animdefsToken = M_GetToken(NULL); animdefsToken = M_GetToken(NULL);
if (animdefsToken == NULL) if (animdefsToken == NULL)
{ {
I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where \"%s\"'s end texture/flat name should be", animdefs[*i].startname); I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where \"%s\"'s end texture/flat name should be", animdefs[i].startname);
} }
animdefsTokenLength = strlen(animdefsToken); animdefsTokenLength = strlen(animdefsToken);
if (animdefsTokenLength>8) if (animdefsTokenLength>8)
{ {
I_Error("Error parsing ANIMDEFS lump: lump name \"%s\" exceeds 8 characters", animdefsToken); I_Error("Error parsing ANIMDEFS lump: lump name \"%s\" exceeds 8 characters", animdefsToken);
} }
strncpy(animdefs[*i].endname, animdefsToken, 9); strncpy(animdefs[i].endname, animdefsToken, 9);
Z_Free(animdefsToken); Z_Free(animdefsToken);
// "TICS" // "TICS"
animdefsToken = M_GetToken(NULL); animdefsToken = M_GetToken(NULL);
if (animdefsToken == NULL) if (animdefsToken == NULL)
{ {
I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where \"%s\"'s \"TICS\" should be", animdefs[*i].startname); I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where \"%s\"'s \"TICS\" should be", animdefs[i].startname);
} }
if (stricmp(animdefsToken, "RAND") == 0) if (stricmp(animdefsToken, "RAND") == 0)
{ {
@ -501,7 +525,7 @@ void P_ParseAnimationDefintion(SINT8 istexture, INT32 *i)
} }
if (stricmp(animdefsToken, "TICS") != 0) if (stricmp(animdefsToken, "TICS") != 0)
{ {
I_Error("Error parsing ANIMDEFS lump: Expected \"TICS\" in animation definition for \"%s\", got \"%s\"", animdefs[*i].startname, animdefsToken); I_Error("Error parsing ANIMDEFS lump: Expected \"TICS\" in animation definition for \"%s\", got \"%s\"", animdefs[i].startname, animdefsToken);
} }
Z_Free(animdefsToken); Z_Free(animdefsToken);
@ -509,7 +533,7 @@ void P_ParseAnimationDefintion(SINT8 istexture, INT32 *i)
animdefsToken = M_GetToken(NULL); animdefsToken = M_GetToken(NULL);
if (animdefsToken == NULL) if (animdefsToken == NULL)
{ {
I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where \"%s\"'s animation speed should be", animdefs[*i].startname); I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where \"%s\"'s animation speed should be", animdefs[i].startname);
} }
endPos = NULL; endPos = NULL;
#ifndef AVOID_ERRNO #ifndef AVOID_ERRNO
@ -523,13 +547,10 @@ void P_ParseAnimationDefintion(SINT8 istexture, INT32 *i)
#endif #endif
|| animSpeed < 0) // Number is not positive || animSpeed < 0) // Number is not positive
{ {
I_Error("Error parsing ANIMDEFS lump: Expected a positive integer for \"%s\"'s animation speed, got \"%s\"", animdefs[*i].startname, animdefsToken); I_Error("Error parsing ANIMDEFS lump: Expected a positive integer for \"%s\"'s animation speed, got \"%s\"", animdefs[i].startname, animdefsToken);
} }
animdefs[*i].speed = animSpeed; animdefs[i].speed = animSpeed;
Z_Free(animdefsToken); Z_Free(animdefsToken);
// Increment i before we go, so this doesn't cause issues later
(*i)++;
} }