Add support for LongSprites/ folder

This commit is contained in:
LJ Sonic 2024-03-15 21:22:12 +01:00
parent 42c610af9c
commit 99a9e5fcc9
5 changed files with 165 additions and 24 deletions

View file

@ -625,7 +625,7 @@ static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, ski
newlastlump++;
// load all sprite sets we are aware of... for super!
for (sprite2 = start_spr2; sprite2 < free_spr2; sprite2++)
R_AddSingleSpriteDef(spr2names[sprite2], &skin->super.sprites[sprite2], wadnum, newlastlump, *lastlump);
R_AddSingleSpriteDef(spr2names[sprite2], &skin->super.sprites[sprite2], wadnum, newlastlump, *lastlump, false);
newlastlump--;
*lastlump = newlastlump; // okay, make the normal sprite set loading end there
@ -633,7 +633,7 @@ static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, ski
// load all sprite sets we are aware of... for normal stuff.
for (sprite2 = start_spr2; sprite2 < free_spr2; sprite2++)
R_AddSingleSpriteDef(spr2names[sprite2], &skin->sprites[sprite2], wadnum, *lump, *lastlump);
R_AddSingleSpriteDef(spr2names[sprite2], &skin->sprites[sprite2], wadnum, *lump, *lastlump, false);
if (skin->sprites[0].numframes == 0)
CONS_Alert(CONS_ERROR, M_GetText("No frames found for sprite SPR2_%s\n"), spr2names[0]);

View file

@ -116,6 +116,14 @@ static INT32 drawsegs_xrange_count = 0;
//
// ==========================================================================
spritenum_t R_GetSpriteNumByName(const char *name)
{
for (spritenum_t i = 0; i < NUMSPRITES; i++)
if (!strcmp(name, sprnames[i]))
return i;
return NUMSPRITES;
}
//
//
//
@ -147,9 +155,9 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch
{
// the lump should be used for all rotations
if (sprtemp[frame].rotate == SRF_SINGLE)
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has multiple rot = 0 lump\n", spritename, cn);
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %d (%c) has multiple rot = 0 lump\n", spritename, frame, cn);
else if (sprtemp[frame].rotate != SRF_NONE) // Let's bundle 1-8/16 and L/R rotations into one debug message.
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has rotations and a rot = 0 lump\n", spritename, cn);
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %d (%c) has rotations and a rot = 0 lump\n", spritename, frame, cn);
sprtemp[frame].rotate = SRF_SINGLE;
for (r = 0; r < 16; r++)
@ -169,15 +177,15 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch
if (sprtemp[frame].rotate == SRF_NONE)
sprtemp[frame].rotate = SRF_SINGLE;
else if (sprtemp[frame].rotate == SRF_SINGLE)
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has L/R rotations and a rot = 0 lump\n", spritename, cn);
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %d (%c) has L/R rotations and a rot = 0 lump\n", spritename, frame, cn);
else if (sprtemp[frame].rotate == SRF_3D)
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has both L/R and 1-8 rotations\n", spritename, cn);
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %d (%c) has both L/R and 1-8 rotations\n", spritename, frame, cn);
else if (sprtemp[frame].rotate == SRF_3DGE)
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has both L/R and 1-G rotations\n", spritename, cn);
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %d (%c) has both L/R and 1-G rotations\n", spritename, frame, cn);
else if ((sprtemp[frame].rotate & SRF_LEFT) && (rotation == ROT_L))
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has multiple L rotations\n", spritename, cn);
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %d (%c) has multiple L rotations\n", spritename, frame, cn);
else if ((sprtemp[frame].rotate & SRF_RIGHT) && (rotation == ROT_R))
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has multiple R rotations\n", spritename, cn);
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %d (%c) has multiple R rotations\n", spritename, frame, cn);
sprtemp[frame].rotate |= ((rotation == ROT_R) ? SRF_RIGHT : SRF_LEFT);
if ((sprtemp[frame].rotate & SRF_2D) == SRF_2D)
@ -204,9 +212,9 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch
if (sprtemp[frame].rotate == SRF_NONE)
sprtemp[frame].rotate = SRF_SINGLE;
else if (sprtemp[frame].rotate == SRF_SINGLE)
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has 1-8/G rotations and a rot = 0 lump\n", spritename, cn);
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %d (%c) has 1-8/G rotations and a rot = 0 lump\n", spritename, frame, cn);
else if (sprtemp[frame].rotate & SRF_2D)
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has both L/R and 1-8/G rotations\n", spritename, cn);
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %d (%c) has both L/R and 1-8/G rotations\n", spritename, frame, cn);
// make 0 based
rotation--;
@ -226,7 +234,7 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch
}
if (sprtemp[frame].lumppat[rotation] != LUMPERROR)
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s: %c%c has two lumps mapped to it\n", spritename, cn, cr);
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s: %d_%c (%c%c) has two lumps mapped to it\n", spritename, frame, cr, cn, cr);
// lumppat & lumpid are the same for original Doom, but different
// when using sprites in pwad : the lumppat points the new graphics
@ -238,7 +246,7 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch
sprtemp[frame].flip &= ~(1<<rotation);
}
static boolean GetFramesAndRotationsFromLumpName(
static boolean GetFramesAndRotationsFromShortLumpName(
const char *name,
UINT8 *ret_frame,
UINT8 *ret_rotation,
@ -272,6 +280,40 @@ static boolean GetFramesAndRotationsFromLumpName(
return true;
}
static boolean GetFramesAndRotationsFromLongLumpName(
const char *name,
UINT8 *ret_frame,
UINT8 *ret_rotation,
UINT8 *ret_frame2,
UINT8 *ret_rotation2
)
{
const char *underscore = strchr(name, '_');
if (!underscore)
return false;
size_t framelen = underscore - name;
if (framelen < 1 || framelen > 4)
return false;
char framepart[4 + 1]; // Max 9999
strlcpy(framepart, name, framelen + 1);
for (size_t i = 0; i < framelen; i++)
if (!isdigit(framepart[i]))
return false;
*ret_frame = atoi(framepart);
*ret_rotation = R_Char2Rotation(*(underscore + 1));
if (*ret_frame >= 64 || *ret_rotation == 255)
return false;
*ret_frame2 = 255;
*ret_rotation2 = 255;
return true;
}
// Some checks to help development
static void CheckFrame(const char *sprname)
{
@ -283,7 +325,7 @@ static void CheckFrame(const char *sprname)
{
case SRF_NONE:
// no rotations were found for that frame at all
I_Error("R_AddSingleSpriteDef: No patches found for %s frame %c", sprname, R_Frame2Char(frame));
I_Error("R_AddSingleSpriteDef: No patches found for %s frame %d (%c)", sprname, frame, R_Frame2Char(frame));
break;
case SRF_SINGLE:
@ -293,8 +335,8 @@ static void CheckFrame(const char *sprname)
case SRF_2D: // both Left and Right rotations
// we test to see whether the left and right slots are present
if ((spriteframe->lumppat[2] == LUMPERROR) || (spriteframe->lumppat[6] == LUMPERROR))
I_Error("R_AddSingleSpriteDef: Sprite %s frame %c is missing rotations (L-R mode)",
sprname, R_Frame2Char(frame));
I_Error("R_AddSingleSpriteDef: Sprite %s frame %d (%c) is missing rotations (L-R mode)",
sprname, frame, R_Frame2Char(frame));
break;
default:
@ -305,8 +347,8 @@ static void CheckFrame(const char *sprname)
// we test the patch lump, or the id lump whatever
// if it was not loaded the two are LUMPERROR
if (spriteframe->lumppat[rotation] == LUMPERROR)
I_Error("R_AddSingleSpriteDef: Sprite %s frame %c is missing rotations (1-%c mode)",
sprname, R_Frame2Char(frame), ((spriteframe->rotate & SRF_3DGE) ? 'G' : '8'));
I_Error("R_AddSingleSpriteDef: Sprite %s frame %d (%c) is missing rotations (1-%c mode)",
sprname, frame, R_Frame2Char(frame), ((spriteframe->rotate & SRF_3DGE) ? 'G' : '8'));
}
break;
}
@ -317,16 +359,17 @@ static void CheckFrame(const char *sprname)
//
// (originally part of R_AddSpriteDefs)
//
// Pass: name of sprite : 4 chars
// Pass: name of sprite
// spritedef_t
// wadnum : wad number, indexes wadfiles[], where patches
// for frames are found
// startlump : first lump to search for sprite frames
// endlump : AFTER the last lump to search
// longname : whether to use long sprite names or 4-char names
//
// Returns true if the sprite was succesfully added
//
boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 wadnum, UINT16 startlump, UINT16 endlump)
boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 wadnum, UINT16 startlump, UINT16 endlump, boolean longname)
{
UINT16 l;
lumpinfo_t *lumpinfo;
@ -355,14 +398,18 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16
for (l = startlump; l < endlump; l++)
{
if (memcmp(lumpinfo[l].name,sprname,4)==0)
// For long sprites, the startlump-endlump range only includes
// relevant lumps, so no check needed in that case
if (longname || !memcmp(lumpinfo[l].name, sprname, 4))
{
INT16 width, height;
INT16 topoffset, leftoffset;
UINT8 frame, frame2;
UINT8 rotation, rotation2;
boolean good = GetFramesAndRotationsFromLumpName(lumpinfo[l].name, &frame, &rotation, &frame2, &rotation2);
boolean good = longname ?
GetFramesAndRotationsFromLongLumpName(lumpinfo[l].name, &frame, &rotation, &frame2, &rotation2) :
GetFramesAndRotationsFromShortLumpName(lumpinfo[l].name, &frame, &rotation, &frame2, &rotation2);
if (!good) // Give an actual NAME error -_-...
{
@ -504,7 +551,7 @@ static void AddShortSpriteDefs(UINT16 wadnum, size_t *ptr_spritesadded, size_t *
//
for (i = 0; i < numsprites; i++)
{
if (R_AddSingleSpriteDef(sprnames[i], &sprites[i], wadnum, start, end))
if (R_AddSingleSpriteDef(sprnames[i], &sprites[i], wadnum, start, end, false))
{
// if a new sprite was added (not just replaced)
(*ptr_spritesadded)++;
@ -517,6 +564,54 @@ static void AddShortSpriteDefs(UINT16 wadnum, size_t *ptr_spritesadded, size_t *
*ptr_framesadded += end - start;
}
static void AddLongSpriteDefs(UINT16 wadnum, size_t *ptr_spritesadded, size_t *ptr_framesadded)
{
if (!W_FileHasFolders(wadfiles[wadnum]))
return;
UINT16 start = W_CheckNumForFolderStartPK3("LongSprites/", wadnum, 0);
UINT16 end = W_CheckNumForFolderEndPK3("LongSprites/", wadnum, start);
if (start == INT16_MAX || end == INT16_MAX || start >= end)
return;
size_t lumpnum = start;
while (lumpnum < end)
{
if (W_IsLumpFolder(wadnum, lumpnum))
{
lumpnum++;
continue;
}
UINT16 folderstart, folderend;
char *folderpath = W_GetLumpFolderPathPK3(wadnum, lumpnum);
folderstart = lumpnum;
folderend = W_CheckNumForFolderEndPK3(folderpath, wadnum, lumpnum);
Z_Free(folderpath);
spritenum_t sprnum;
char *sprname = W_GetLumpFolderNamePK3(wadnum, lumpnum);
strupr(sprname);
sprnum = R_GetSpriteNumByName(sprname);
Z_Free(sprname);
if (sprnum != NUMSPRITES && R_AddSingleSpriteDef(sprname, &sprites[sprnum], wadnum, folderstart, folderend, true))
{
// A new sprite was added (not just replaced)
(*ptr_spritesadded)++;
#ifndef ZDEBUG
CONS_Debug(DBG_SETUP, "long sprite %s set in pwad %d\n", sprname, wadnum);
#endif
}
lumpnum = folderend;
}
*ptr_framesadded += end - start;
}
//
// Search for sprites replacements in a wad whose names are in namelist
//
@ -527,6 +622,7 @@ void R_AddSpriteDefs(UINT16 wadnum)
size_t framesadded = 0;
AddShortSpriteDefs(wadnum, &spritesadded, &framesadded);
AddLongSpriteDefs(wadnum, &spritesadded, &framesadded);
nameonly(strcpy(wadname, wadfiles[wadnum]->filename));
CONS_Printf(M_GetText("%s added %d frames in %s sprites\n"), wadname, framesadded, sizeu1(spritesadded));

View file

@ -27,7 +27,9 @@
#define FEETADJUST (4<<FRACBITS) // R_AddSingleSpriteDef
boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 wadnum, UINT16 startlump, UINT16 endlump);
spritenum_t R_GetSpriteNumByName(const char *name);
boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 wadnum, UINT16 startlump, UINT16 endlump, boolean longname);
//faB: find sprites in wadfile, replace existing, add new ones
// (only sprites from namelist are added or replaced)

View file

@ -1349,6 +1349,47 @@ UINT16 W_CheckNumForFolderEndPK3(const char *name, UINT16 wad, UINT16 startlump)
return i;
}
char *W_GetLumpFolderPathPK3(UINT16 wad, UINT16 lump)
{
const char *fullname = wadfiles[wad]->lumpinfo[lump].fullname;
const char *slash = strrchr(fullname, '/');
INT32 pathlen = slash ? slash - fullname : 0;
char *path = Z_Calloc(pathlen + 1, PU_STATIC, NULL);
strncpy(path, fullname, pathlen);
return path;
}
char *W_GetLumpFolderNamePK3(UINT16 wad, UINT16 lump)
{
const char *fullname = wadfiles[wad]->lumpinfo[lump].fullname;
size_t start, end;
INT32 i = strlen(fullname);
i--;
while (i >= 0 && fullname[i] != '/')
i--;
if (i < 0)
return NULL;
end = i;
i--;
while (i >= 0 && fullname[i] != '/')
i--;
if (i < 0)
return NULL;
start = i + 1;
size_t namelen = end - start;
char *foldername = Z_Calloc(namelen + 1, PU_STATIC, NULL);
strncpy(foldername, fullname + start, namelen);
return foldername;
}
void W_GetFolderLumpsPwad(const char *name, UINT16 wad, UINT32 **list, UINT16 *list_capacity, UINT16 *numlumps)
{
size_t name_length = strlen(name);

View file

@ -180,6 +180,8 @@ UINT16 W_CheckNumForMarkerStartPwad(const char *name, UINT16 wad, UINT16 startlu
UINT16 W_CheckNumForFullNamePK3(const char *name, UINT16 wad, UINT16 startlump);
UINT16 W_CheckNumForFolderStartPK3(const char *name, UINT16 wad, UINT16 startlump);
UINT16 W_CheckNumForFolderEndPK3(const char *name, UINT16 wad, UINT16 startlump);
char *W_GetLumpFolderPathPK3(UINT16 wad, UINT16 lump);
char *W_GetLumpFolderNamePK3(UINT16 wad, UINT16 lump);
void W_GetFolderLumpsPwad(const char *name, UINT16 wad, UINT32 **list, UINT16 *list_capacity, UINT16 *numlumps);
void W_GetFolderLumps(const char *name, UINT32 **list, UINT16 *list_capacity, UINT16 *numlumps);