Address initial review comments + associated cleanup

- Grab thumbnail and minimap pictures even for base game maps
- Repair modified game event for replacement map load
- PU_STATIC thumbnail and minimap, freed on new file load lump discovery
- Fix W_CheckNumForMap to not SIGSEGV if no match
- Reduce the number of pointless map lump hunts, we've already got it stored
- Prevent use-after-free for map pictures on voting screen
- Cache "BLANKLVL" patch once
- Draw minimap on the time attack menu

Unfortunately cups are still broken and I'm not sure where to start on that, or if it's just not having a sample wad to test with that includes cups
This commit is contained in:
toaster 2022-09-16 15:01:49 +01:00
parent ae38b7091a
commit 46441092dc
9 changed files with 140 additions and 149 deletions

View file

@ -1190,15 +1190,10 @@ D_ConvertVersionNumbers (void)
// //
void D_SRB2Main(void) void D_SRB2Main(void)
{ {
INT32 numbasemapheaders;
INT32 i;
UINT16 wadnum;
char *name;
virtres_t *virtmap;
virtlump_t *minimap, *thumbnailPic;
INT32 p; INT32 p;
INT32 numbasemapheaders;
INT32 pstartmap = 1; INT32 pstartmap = 1;
boolean autostart = false; boolean autostart = false;
@ -1441,6 +1436,11 @@ void D_SRB2Main(void)
#endif //ifndef DEVELOP #endif //ifndef DEVELOP
//
// search for mainwad maps
//
P_InitMapData(0);
numbasemapheaders = nummapheaders; numbasemapheaders = nummapheaders;
CON_SetLoadingProgress(LOADED_IWAD); CON_SetLoadingProgress(LOADED_IWAD);
@ -1450,40 +1450,9 @@ void D_SRB2Main(void)
D_CleanFile(startuppwads); D_CleanFile(startuppwads);
// //
// search for maps // search for pwad maps
// //
for (wadnum = mainwads+1; wadnum < numwadfiles; wadnum++) P_InitMapData(numbasemapheaders);
{
for (i = 0; i < numbasemapheaders; ++i)
{
name = mapheaderinfo[i]->lumpname;
mapheaderinfo[i]->lumpnum = W_CheckNumForMap(name);
// Get map thumbnail and minimap
virtmap = vres_GetMap(mapheaderinfo[i]->lumpnum);
thumbnailPic = vres_Find(virtmap, "PICTURE");
minimap = vres_Find(virtmap, "MINIMAP");
if (thumbnailPic)
{
mapheaderinfo[i]->thumbnailPic = vres_GetPatch(thumbnailPic, PU_CACHE);
}
if (minimap)
{
mapheaderinfo[i]->minimapPic = vres_GetPatch(minimap, PU_HUDGFX);
}
vres_Free(virtmap);
if (W_CheckNumForMapPwad(name, wadnum, 0) != INT16_MAX)
{
G_SetGameModified(multiplayer, true); // oops, double-defined - no record attack privileges for you
CONS_Printf("%s\n", name);
}
}
}
CON_SetLoadingProgress(LOADED_PWAD); CON_SetLoadingProgress(LOADED_PWAD);

View file

@ -597,20 +597,7 @@ void G_SetGameModified(boolean silent, boolean major)
*/ */
const char *G_BuildMapName(INT32 map) const char *G_BuildMapName(INT32 map)
{ {
#if 0 if (map > 0 && map <= nummapheaders && mapheaderinfo[map - 1] != NULL)
if (map == 0) // hack???
{
if (gamestate == GS_TITLESCREEN)
map = -1;
else if (gamestate == GS_LEVEL)
map = gamemap-1;
else
map = prevmap;
map = G_RandMap(G_TOLFlag(cv_newgametype.value), map, 0, 0, false, NULL)+1;
}
#endif
if (map > 0 && map <= NUMMAPS && mapheaderinfo[map - 1] != NULL)
{ {
return mapheaderinfo[map - 1]->lumpname; return mapheaderinfo[map - 1]->lumpname;
} }
@ -4612,7 +4599,7 @@ void G_InitNew(UINT8 pencoremode, INT32 map, boolean resetplayer, boolean skippr
// internal game map // internal game map
// well this check is useless because it is done before (d_netcmd.c::command_map_f) // well this check is useless because it is done before (d_netcmd.c::command_map_f)
// but in case of for demos.... // but in case of for demos....
if (W_CheckNumForName(mapname) == LUMPERROR) if (mapheaderinfo[map-1]->lumpnum == LUMPERROR)
{ {
I_Error("Internal game map '%s' not found\n", mapname); I_Error("Internal game map '%s' not found\n", mapname);
Command_ExitGame_f(); Command_ExitGame_f();

View file

@ -93,6 +93,7 @@ static char hu_tick;
//------------------------------------------- //-------------------------------------------
patch_t *missingpat; patch_t *missingpat;
patch_t *blanklvl;
// song credits // song credits
static patch_t *songcreditbg; static patch_t *songcreditbg;
@ -180,6 +181,8 @@ void HU_LoadGraphics(void)
Font_Load(); Font_Load();
HU_UpdatePatch(&blanklvl, "BLANKLVL");
HU_UpdatePatch(&songcreditbg, "K_SONGCR"); HU_UpdatePatch(&songcreditbg, "K_SONGCR");
// cache ping gfx: // cache ping gfx:

View file

@ -1855,7 +1855,7 @@ static void M_DrawCupPreview(INT16 y, cupheader_t *cup)
} }
if (!PictureOfLevel) if (!PictureOfLevel)
PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); PictureOfLevel = blanklvl;
V_DrawSmallScaledPatch(x + 1, y+2, 0, PictureOfLevel); V_DrawSmallScaledPatch(x + 1, y+2, 0, PictureOfLevel);
i = (i+1) % cup->numlevels; i = (i+1) % cup->numlevels;
@ -2087,7 +2087,7 @@ static void M_DrawLevelSelectBlock(INT16 x, INT16 y, INT16 map, boolean redblink
} }
if (!PictureOfLevel) if (!PictureOfLevel)
PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); PictureOfLevel = blanklvl;
if (redblink) if (redblink)
V_DrawScaledPatch(3+x, y, 0, W_CachePatchName("LVLSEL2", PU_CACHE)); V_DrawScaledPatch(3+x, y, 0, W_CachePatchName("LVLSEL2", PU_CACHE));
@ -2163,12 +2163,10 @@ void M_DrawTimeAttack(void)
{ {
if (mapheaderinfo[map]) if (mapheaderinfo[map])
{ {
minimap = mapheaderinfo[map]->minimapPic; if ((minimap = mapheaderinfo[map]->minimapPic))
V_DrawScaledPatch(24-t, 82, 0, minimap);
} }
if (!minimap)
V_DrawScaledPatch(24-t, 82, 0, minimap);
V_DrawRightAlignedString(rightedge-12, 82, highlightflags, "BEST LAP:"); V_DrawRightAlignedString(rightedge-12, 82, highlightflags, "BEST LAP:");
K_drawKartTimestamp(0, 162+t, 88, 0, 2); K_drawKartTimestamp(0, 162+t, 88, 0, 2);

View file

@ -365,13 +365,13 @@ static void P_ClearSingleMapHeaderInfo(INT16 i)
if (mapheaderinfo[num]->thumbnailPic) if (mapheaderinfo[num]->thumbnailPic)
{ {
Z_Free(mapheaderinfo[num]->thumbnailPic); Patch_Free(mapheaderinfo[num]->thumbnailPic);
mapheaderinfo[num]->thumbnailPic = NULL; mapheaderinfo[num]->thumbnailPic = NULL;
} }
if (mapheaderinfo[num]->minimapPic) if (mapheaderinfo[num]->minimapPic)
{ {
Z_Free(mapheaderinfo[num]->minimapPic); Patch_Free(mapheaderinfo[num]->minimapPic);
mapheaderinfo[num]->minimapPic = NULL; mapheaderinfo[num]->minimapPic = NULL;
} }
@ -4339,8 +4339,8 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
} }
// internal game map // internal game map
maplumpname = G_BuildMapName(gamemap); maplumpname = mapheaderinfo[gamemap-1]->lumpname;
lastloadedmaplumpnum = W_CheckNumForMap(maplumpname); lastloadedmaplumpnum = mapheaderinfo[gamemap-1]->lumpnum;
if (lastloadedmaplumpnum == LUMPERROR) if (lastloadedmaplumpnum == LUMPERROR)
I_Error("Map %s not found.\n", maplumpname); I_Error("Map %s not found.\n", maplumpname);
@ -4655,6 +4655,87 @@ static lumpinfo_t* FindFolder(const char *folName, UINT16 *start, UINT16 *end, l
return lumpinfo; return lumpinfo;
} }
// Initialising map data (and catching replacements)...
UINT8 P_InitMapData(INT32 numexistingmapheaders)
{
UINT8 ret = 0;
INT32 i;
lumpnum_t maplump;
virtres_t *virtmap;
virtlump_t *minimap, *thumbnailPic;
char *name;
for (i = 0; i < nummapheaders; ++i)
{
name = mapheaderinfo[i]->lumpname;
maplump = W_CheckNumForMap(name);
// Doesn't exist?
if (maplump == INT16_MAX)
{
#ifndef DEVELOP
if (!numexistingmapheaders)
{
I_Error("P_InitMapData: Base map %s has a header but no level\n", name);
}
#endif
continue;
}
// No change?
if (mapheaderinfo[i]->lumpnum == maplump)
continue;
// Okay, it does...
{
ret |= MAPRET_ADDED;
CONS_Printf("%s\n", name);
if (numexistingmapheaders && mapheaderinfo[i]->lumpnum != LUMPERROR)
{
G_SetGameModified(multiplayer, true); // oops, double-defined - no record attack privileges for you
//If you replaced the map you're on, end the level when done.
if (i == gamemap - 1)
ret |= MAPRET_CURRENTREPLACED;
}
mapheaderinfo[i]->lumpnum = maplump;
// Get map thumbnail and minimap
virtmap = vres_GetMap(mapheaderinfo[i]->lumpnum);
thumbnailPic = vres_Find(virtmap, "PICTURE");
minimap = vres_Find(virtmap, "MINIMAP");
// Clear out existing graphics...
if (mapheaderinfo[i]->thumbnailPic)
{
Patch_Free(mapheaderinfo[i]->thumbnailPic);
}
if (mapheaderinfo[i]->minimapPic)
{
Patch_Free(mapheaderinfo[i]->minimapPic);
}
// Now apply the new ones!
if (thumbnailPic)
{
mapheaderinfo[i]->thumbnailPic = vres_GetPatch(thumbnailPic, PU_STATIC);
}
if (minimap)
{
mapheaderinfo[i]->minimapPic = vres_GetPatch(minimap, PU_STATIC);
}
vres_Free(virtmap);
}
}
return ret;
}
UINT16 p_adding_file = INT16_MAX; UINT16 p_adding_file = INT16_MAX;
// //
@ -4665,16 +4746,12 @@ boolean P_AddWadFile(const char *wadfilename)
{ {
size_t i, j, sreplaces = 0, mreplaces = 0, digmreplaces = 0; size_t i, j, sreplaces = 0, mreplaces = 0, digmreplaces = 0;
INT32 numexistingmapheaders = nummapheaders; INT32 numexistingmapheaders = nummapheaders;
INT32 map;
UINT16 numlumps, wadnum; UINT16 numlumps, wadnum;
char *name; char *name;
lumpinfo_t *lumpinfo; lumpinfo_t *lumpinfo;
virtres_t *virtmap;
virtlump_t *minimap, *thumbnailPic;
//boolean texturechange = false; ///\todo Useless; broken when back-frontporting PK3 changes? //boolean texturechange = false; ///\todo Useless; broken when back-frontporting PK3 changes?
boolean mapsadded = false; UINT8 mapsadded = 0;
boolean replacedcurrentmap = false;
// Vars to help us with the position start and amount of each resource type. // Vars to help us with the position start and amount of each resource type.
// Useful for PK3s since they use folders. // Useful for PK3s since they use folders.
@ -4824,44 +4901,7 @@ boolean P_AddWadFile(const char *wadfilename)
// //
// search for maps // search for maps
// //
for (map = 0; map < numexistingmapheaders; ++map) mapsadded = P_InitMapData(numexistingmapheaders);
{
name = mapheaderinfo[map]->lumpname;
if (mapheaderinfo[i]->lumpnum != W_CheckNumForMap(name))
{
mapheaderinfo[i]->lumpnum = W_CheckNumForMap(name);
// Get map thumbnail and minimap
virtmap = vres_GetMap(mapheaderinfo[i]->lumpnum);
thumbnailPic = vres_Find(virtmap, "PICTURE");
minimap = vres_Find(virtmap, "MINIMAP");
if (thumbnailPic)
{
mapheaderinfo[i]->thumbnailPic = vres_GetPatch(thumbnailPic, PU_CACHE);
}
if (minimap)
{
mapheaderinfo[i]->minimapPic = vres_GetPatch(minimap, PU_HUDGFX);
}
vres_Free(virtmap);
}
if (W_CheckNumForMapPwad(name, wadnum, 0) != INT16_MAX)
{
G_SetGameModified(multiplayer, true); // oops, double-defined - no record attack privileges for you
//If you replaced the map you're on, end the level when done.
if (map == gamemap - 1)
replacedcurrentmap = true;
CONS_Printf("%s\n", name);
mapsadded = true;
}
}
if (!mapsadded) if (!mapsadded)
CONS_Printf(M_GetText("No maps added\n")); CONS_Printf(M_GetText("No maps added\n"));
@ -4880,7 +4920,7 @@ boolean P_AddWadFile(const char *wadfilename)
if (cursaveslot > 0) if (cursaveslot > 0)
cursaveslot = 0; cursaveslot = 0;
if (replacedcurrentmap && gamestate == GS_LEVEL && (netgame || multiplayer)) if ((mapsadded & MAPRET_CURRENTREPLACED) && gamestate == GS_LEVEL && (netgame || multiplayer))
{ {
CONS_Printf(M_GetText("Current map %d replaced by added file, ending the level to ensure consistency.\n"), gamemap); CONS_Printf(M_GetText("Current map %d replaced by added file, ending the level to ensure consistency.\n"), gamemap);
if (server) if (server)

View file

@ -108,6 +108,11 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate);
void HWR_LoadLevel(void); void HWR_LoadLevel(void);
#endif #endif
boolean P_AddWadFile(const char *wadfilename); boolean P_AddWadFile(const char *wadfilename);
#define MAPRET_ADDED (1)
#define MAPRET_CURRENTREPLACED (1<<1)
UINT8 P_InitMapData(INT32 numexistingmapheaders);
boolean P_RunSOC(const char *socfilename); boolean P_RunSOC(const char *socfilename);
void P_LoadSoundsRange(UINT16 wadnum, UINT16 first, UINT16 num); void P_LoadSoundsRange(UINT16 wadnum, UINT16 first, UINT16 num);
void P_LoadMusicsRange(UINT16 wadnum, UINT16 first, UINT16 num); void P_LoadMusicsRange(UINT16 wadnum, UINT16 first, UINT16 num);

View file

@ -698,6 +698,7 @@ typedef struct
} patch_t; } patch_t;
extern patch_t *missingpat; extern patch_t *missingpat;
extern patch_t *blanklvl;
#if defined(_MSC_VER) #if defined(_MSC_VER)
#pragma pack(1) #pragma pack(1)

View file

@ -1274,7 +1274,7 @@ lumpnum_t W_CheckNumForMap(const char *name)
} }
} }
for (i = numwadfiles - 1; i < numwadfiles; i--) for (i = numwadfiles - 1; i >= 0; i--)
{ {
check = W_CheckNumForMapPwad(name, (UINT16)i, 0); check = W_CheckNumForMapPwad(name, (UINT16)i, 0);

View file

@ -111,7 +111,6 @@ typedef struct
char str[62]; char str[62];
UINT8 gtc; UINT8 gtc;
const char *gts; const char *gts;
patch_t *pic;
boolean encore; boolean encore;
} y_votelvlinfo; } y_votelvlinfo;
@ -1010,7 +1009,18 @@ void Y_VoteDrawer(void)
else else
{ {
str = levelinfo[i].str; str = levelinfo[i].str;
pic = levelinfo[i].pic;
pic = NULL;
if (mapheaderinfo[votelevels[i][0]])
{
pic = mapheaderinfo[votelevels[i][0]]->thumbnailPic;
}
if (!pic)
{
pic = blanklvl;
}
} }
if (selected[i]) if (selected[i])
@ -1130,9 +1140,23 @@ void Y_VoteDrawer(void)
patch_t *pic; patch_t *pic;
if (votes[i] >= 3 && (i != pickedvote || voteendtic == -1)) if (votes[i] >= 3 && (i != pickedvote || voteendtic == -1))
{
pic = randomlvl; pic = randomlvl;
}
else else
pic = levelinfo[votes[i]].pic; {
pic = NULL;
if (mapheaderinfo[votelevels[votes[i]][0]])
{
pic = mapheaderinfo[votelevels[votes[i]][0]]->thumbnailPic;
}
if (!pic)
{
pic = blanklvl;
}
}
if (!timer && i == voteclient.ranim) if (!timer && i == voteclient.ranim)
{ {
@ -1530,18 +1554,6 @@ void Y_StartVote(void)
levelinfo[i].gts = Gametype_Names[votelevels[i][1]]; levelinfo[i].gts = Gametype_Names[votelevels[i][1]];
else else
levelinfo[i].gts = NULL; levelinfo[i].gts = NULL;
// set up the pic
patch_t *thumbnailPic = NULL;
if (mapheaderinfo[votelevels[i][0]+1])
{
thumbnailPic = mapheaderinfo[votelevels[i][0]]->thumbnailPic;
}
if (thumbnailPic)
levelinfo[i].pic = thumbnailPic;
else
levelinfo[i].pic = W_CachePatchName("BLANKLVL", PU_STATIC);
} }
voteclient.loaded = true; voteclient.loaded = true;
@ -1561,8 +1573,6 @@ void Y_EndVote(void)
// //
static void Y_UnloadVoteData(void) static void Y_UnloadVoteData(void)
{ {
UINT8 i;
voteclient.loaded = false; voteclient.loaded = false;
if (rendermode != render_soft) if (rendermode != render_soft)
@ -1577,28 +1587,6 @@ static void Y_UnloadVoteData(void)
UNLOAD(cursor4); UNLOAD(cursor4);
UNLOAD(randomlvl); UNLOAD(randomlvl);
UNLOAD(rubyicon); UNLOAD(rubyicon);
// to prevent double frees...
for (i = 0; i < 4; i++)
{
// I went to all the trouble of doing this,
// but literally nowhere else frees level pics.
#if 0
UINT8 j;
if (!levelinfo[i].pic)
continue;
for (j = i+1; j < 4; j++)
{
if (levelinfo[j].pic == levelinfo[i].pic)
levelinfo[j].pic = NULL;
}
UNLOAD(levelinfo[i].pic);
#else
CLEANUP(levelinfo[i].pic);
#endif
}
} }
// //