From 92cdec077d04b65e09a8602b5549efcb4fdf048c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 12 Apr 2021 20:54:12 +0200 Subject: [PATCH 01/11] - fixed some bogus range checks in automap code. --- source/core/automap.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/source/core/automap.cpp b/source/core/automap.cpp index 187ca3bb1..370e48f77 100644 --- a/source/core/automap.cpp +++ b/source/core/automap.cpp @@ -428,9 +428,12 @@ void drawredlines(int cposx, int cposy, int czoom, int cang) for (j = startwall, wal = &wall[startwall]; j < endwall; j++, wal++) { int k = wal->nextwall; - if (k < 0 || k >= MAXWALLS) continue; + if (k < 0 || k >= numwalls) continue; - if (sector[wal->nextsector].ceilingz == z1 && sector[wal->nextsector].floorz == z2) + int s = wal->nextsector; + if (s < 0 || s >= numsectors) continue; + + if (sector[s].ceilingz == z1 && sector[s].floorz == z2) if (((wal->cstat | wall[wal->nextwall].cstat) & (16 + 32)) == 0) continue; if (ShowRedLine(j, i)) From 88fb2185fa7c453aafad341006af8e12188b5ab0 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 13 Apr 2021 00:01:33 +0200 Subject: [PATCH 02/11] - Blood: default skill is 2, not 3. --- source/core/menu/razemenu.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/core/menu/razemenu.cpp b/source/core/menu/razemenu.cpp index 08b5c84be..ae731bccd 100644 --- a/source/core/menu/razemenu.cpp +++ b/source/core/menu/razemenu.cpp @@ -421,7 +421,8 @@ static void BuildEpisodeMenu() #endif if (addedVolumes == 1) { - ld->mAutoselect = ld->mItems.Size() - (textadded ? 2 : 1); + if (!isBlood()) ld->mAutoselect = ld->mItems.Size() - (textadded ? 2 : 1); + else ld->mAutoselect = 2; } if (popped) ld->mItems.Push(popped); } From aba5099ccb21cad7e64e38eaaf240a980b5897a6 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 13 Apr 2021 00:10:22 +0200 Subject: [PATCH 03/11] - added widescreen graphics credits to the Engine Credits menu. --- wadsrc/static/menudef.txt | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 907b26f2d..4ddf92bca 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -1888,7 +1888,7 @@ OptionMenu "EngineCredits2" OptionMenu "EngineCredits2a" { title "$MNU_CREDITS" - Submenu " ---->", "EngineCredits3" + Submenu " ---->", "EngineCredits2b" StaticText "RedNukem / NBlood", 1 StaticText "Alexey \"Nuke.YKT\" Skrybykin", 0 StaticText "" @@ -1900,6 +1900,16 @@ OptionMenu "EngineCredits2a" StaticText "sirlemonhead", 0 } +OptionMenu "EngineCredits2b" +{ + title "$MNU_CREDITS" + Submenu " ---->", "EngineCredits3" + StaticText "Widescreen graphics", 1 + StaticText "James Manning   fgsfds            ", 0 + StaticText "Dzierzan    Phredreeke      ", 0 + StaticText "MaxED        Kinsie   ", 0 +} + OptionMenu "EngineCredits3" { title "$MNU_CREDITS" From eaebcfcd7d28b3a7ff06f92b79997b6835ce5e00 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 13 Apr 2021 00:20:26 +0200 Subject: [PATCH 04/11] - Exhumed: hotfix for moving on sloped floors --- source/games/exhumed/src/player.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/games/exhumed/src/player.cpp b/source/games/exhumed/src/player.cpp index 322fb6ecf..e8687d83d 100644 --- a/source/games/exhumed/src/player.cpp +++ b/source/games/exhumed/src/player.cpp @@ -1163,7 +1163,7 @@ void FuncPlayer(int a, int nDamage, int nRun) } sectdone: - if (!PlayerList[nPlayer].horizon.horiz.asbuild() || PlayerList[nPlayer].bIsFalling) + if ((!PlayerList[nPlayer].horizon.horiz.asbuild() || PlayerList[nPlayer].bIsFalling) && !(sector[sprite[nPlayerSprite].sectnum].floorstat & 2)) { // Calculate base pan amount based on how much the player is falling. fixed_t dVertPan = (spr_z - sprite[nPlayerSprite].z) << 9; From 7b57df3c8fb01b96c21c212f96c3da85b83a3c1f Mon Sep 17 00:00:00 2001 From: Mitchell Richters Date: Tue, 13 Apr 2021 21:56:01 +1000 Subject: [PATCH 05/11] - Exhumed: Redo player panning code. * Initial implementation from d32dcd5f8eb54720719d521b44d81bfcc7a2bf61 was not working properly and already had some workarounds for when the player was underwater, etc. * Re-read implementation in GDX and rebased off of it. * Fixes #303. --- source/games/exhumed/src/input.cpp | 5 +++ source/games/exhumed/src/player.cpp | 67 +++++++++++++++++------------ source/games/exhumed/src/player.h | 3 +- 3 files changed, 46 insertions(+), 29 deletions(-) diff --git a/source/games/exhumed/src/input.cpp b/source/games/exhumed/src/input.cpp index 9f67a2773..a471f6fc7 100644 --- a/source/games/exhumed/src/input.cpp +++ b/source/games/exhumed/src/input.cpp @@ -126,6 +126,11 @@ void GameInterface::GetInput(InputPacket* packet, ControlInfo* const hidInput) { applylook(&pPlayer->angle, input.avel, &sPlayerInput[nLocalPlayer].actions, scaleAdjust); sethorizon(&pPlayer->horizon, input.horz, &sPlayerInput[nLocalPlayer].actions, scaleAdjust); + + if (input.horz) + { + pPlayer->bPlayerPan = pPlayer->bLockPan = true; + } } pPlayer->angle.processhelpers(scaleAdjust); diff --git a/source/games/exhumed/src/player.cpp b/source/games/exhumed/src/player.cpp index e8687d83d..96df6d5b5 100644 --- a/source/games/exhumed/src/player.cpp +++ b/source/games/exhumed/src/player.cpp @@ -436,7 +436,7 @@ void RestartPlayer(short nPlayer) nYDamage[nPlayer] = 0; nXDamage[nPlayer] = 0; - plr->horizon.ohoriz = plr->horizon.horiz = q16horiz(0); + plr->nDestVertPan = plr->horizon.ohoriz = plr->horizon.horiz = q16horiz(0); nBreathTimer[nPlayer] = 90; nTauntTimer[nPlayer] = RandomSize(3) + 3; @@ -456,6 +456,8 @@ void RestartPlayer(short nPlayer) SetMagicFrame(); RestoreGreenPal(); + + plr->bPlayerPan = plr->bLockPan = false; } ototalvel[nPlayer] = totalvel[nPlayer] = 0; @@ -1030,13 +1032,14 @@ void FuncPlayer(int a, int nDamage, int nRun) StopLocalSound(); InitSpiritHead(); + PlayerList[nPlayer].nDestVertPan = q16horiz(0); if (currentLevel->levelNumber == 11) { - PlayerList[nPlayer].horizon.settarget(46); + PlayerList[nPlayer].nDestVertPan = q16horiz(46); } else { - PlayerList[nPlayer].horizon.settarget(11); + PlayerList[nPlayer].nDestVertPan = q16horiz(11); } } } @@ -1064,7 +1067,7 @@ void FuncPlayer(int a, int nDamage, int nRun) zVelB = -zVelB; } - if (zVelB > 512 && PlayerList[nPlayer].horizon.horiz.asq16() != 0 && (sPlayerInput[nPlayer].actions & (SB_AIMMODE))) { + if (zVelB > 512 && !PlayerList[nPlayer].horizon.horiz.asq16() && !(sPlayerInput[nPlayer].actions & SB_AIMMODE)) { sPlayerInput[nPlayer].actions |= SB_CENTERVIEW; } } @@ -1163,29 +1166,9 @@ void FuncPlayer(int a, int nDamage, int nRun) } sectdone: - if ((!PlayerList[nPlayer].horizon.horiz.asbuild() || PlayerList[nPlayer].bIsFalling) && !(sector[sprite[nPlayerSprite].sectnum].floorstat & 2)) + if (!PlayerList[nPlayer].bPlayerPan && !PlayerList[nPlayer].bLockPan) { - // Calculate base pan amount based on how much the player is falling. - fixed_t dVertPan = (spr_z - sprite[nPlayerSprite].z) << 9; - if (!bUnderwater && dVertPan != 0) - { - fixed_t adjustment; - - if (dVertPan >= IntToFixed(4)) - adjustment = 4; - else if (dVertPan <= -IntToFixed(4)) - adjustment = -4; - else - adjustment = dVertPan << 1; - - PlayerList[nPlayer].horizon.addadjustment(adjustment); - PlayerList[nPlayer].bIsFalling = true; - } - else - { - sPlayerInput[nPlayer].actions |= SB_CENTERVIEW; - PlayerList[nPlayer].bIsFalling = false; - } + PlayerList[nPlayer].nDestVertPan = q16horiz(clamp((spr_z - sprite[nPlayerSprite].z) << 9, gi->playerHorizMin(), gi->playerHorizMax())); } playerX -= sprite[nPlayerSprite].x; @@ -2653,11 +2636,40 @@ loc_1BD2E: PlayerList[nPlayer].field_2 = 0; } + Player* pPlayer = &PlayerList[nPlayer]; + + if (actions & (SB_LOOK_UP | SB_LOOK_DOWN)) + { + pPlayer->nDestVertPan = pPlayer->horizon.horiz; + pPlayer->bPlayerPan = pPlayer->bLockPan = true; + } + else if (actions & (SB_AIM_UP | SB_AIM_DOWN | SB_CENTERVIEW)) + { + pPlayer->nDestVertPan = pPlayer->horizon.horiz; + pPlayer->bPlayerPan = pPlayer->bLockPan = false; + } + if (SyncInput()) { - Player* pPlayer = &PlayerList[nPlayer]; sethorizon(&pPlayer->horizon, sPlayerInput[nPlayer].pan, &sPlayerInput[nLocalPlayer].actions); } + + if (sPlayerInput[nPlayer].pan) + { + pPlayer->nDestVertPan = pPlayer->horizon.horiz; + pPlayer->bPlayerPan = pPlayer->bLockPan = true; + } + + if (totalvel[nPlayer] > 20) + { + pPlayer->bPlayerPan = false; + } + + double nVertPan = (pPlayer->nDestVertPan - pPlayer->horizon.horiz).asq16() * (1. / (FRACUNIT << 2)); + if (nVertPan != 0) + { + pPlayer->horizon.addadjustment(abs(nVertPan) >= 4 ? clamp(nVertPan, -4, 4) : nVertPan * 2.); + } } else // else, player's health is less than 0 { @@ -2849,7 +2861,6 @@ FSerializer& Serialize(FSerializer& arc, const char* keyname, Player& w, Player* ("field38", w.field_38) ("field3a", w.field_3A) ("field3c", w.field_3C) - ("bIsFalling", w.bIsFalling) ("seq", w.nSeq) ("horizon", w.horizon) ("angle", w.angle) diff --git a/source/games/exhumed/src/player.h b/source/games/exhumed/src/player.h index 577883603..0715cdbd2 100644 --- a/source/games/exhumed/src/player.h +++ b/source/games/exhumed/src/player.h @@ -71,7 +71,8 @@ struct Player short field_3A; short field_3C; short nRun; - bool bIsFalling; + bool bPlayerPan, bLockPan; + fixedhoriz nDestVertPan; PlayerHorizon horizon; PlayerAngle angle; From 230312e7f3836b7dbbc8d03974a1deb6c63b55f2 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 13 Apr 2021 16:42:46 +0200 Subject: [PATCH 06/11] - re-fixed Blood skill selection. --- source/core/menu/razemenu.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/source/core/menu/razemenu.cpp b/source/core/menu/razemenu.cpp index ae731bccd..ddbf0be9e 100644 --- a/source/core/menu/razemenu.cpp +++ b/source/core/menu/razemenu.cpp @@ -421,8 +421,7 @@ static void BuildEpisodeMenu() #endif if (addedVolumes == 1) { - if (!isBlood()) ld->mAutoselect = ld->mItems.Size() - (textadded ? 2 : 1); - else ld->mAutoselect = 2; + ld->mAutoselect = ld->mItems.Size() - (textadded ? 2 : 1); } if (popped) ld->mItems.Push(popped); } @@ -438,7 +437,7 @@ static void BuildEpisodeMenu() { ld->mItems.Pop(popped); } - + if (isBlood()) gDefaultSkill = 2; ld->mSelectedItem = gDefaultSkill + ld->mItems.Size(); // account for pre-added items int y = ld->mYpos; From 6ad3ac8ef9d8a58eac88ffca68f5d4430b8d670e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 13 Apr 2021 16:59:49 +0200 Subject: [PATCH 07/11] - added GameID field to GrpInfo. This is for allowing new features easier referencing of the various records. --- source/core/searchpaths.cpp | 5 ++++ wadsrc/static/engine/grpinfo.txt | 46 ++++++++++++++++++++++++++++++-- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/source/core/searchpaths.cpp b/source/core/searchpaths.cpp index 61cae25a3..dd3a73af9 100644 --- a/source/core/searchpaths.cpp +++ b/source/core/searchpaths.cpp @@ -460,6 +460,11 @@ static TArray ParseGrpInfo(const char *fn, FileReader &fr, TMap Date: Tue, 13 Apr 2021 17:05:53 +0200 Subject: [PATCH 08/11] - used the newly added game ID as reference for GAMEINFO to autoselect which game to start a mod with. While in GZDoom this uses the IWAD name, the same approach is a lot more problematic here because of name duplications with far more incompatible content. So this allows targeting a group of base games instead of one specific version. --- source/core/gamecontrol.cpp | 21 ++++++++++++++++----- source/core/gamecontrol.h | 1 + source/core/initfs.cpp | 18 +++++++++--------- 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/source/core/gamecontrol.cpp b/source/core/gamecontrol.cpp index e2560c4a3..5bfdd21c6 100644 --- a/source/core/gamecontrol.cpp +++ b/source/core/gamecontrol.cpp @@ -123,7 +123,7 @@ FMemArena dump; // this is for memory blocks than cannot be deallocated without InputState inputState; int ShowStartupWindow(TArray &); -FString GetGameFronUserFiles(); +TArray GetGameFronUserFiles(); void InitFileSystem(TArray&); void I_SetWindowTitle(const char* caption); void S_ParseSndInfo(); @@ -643,14 +643,25 @@ static TArray SetupGame() int groupno = -1; - // If the user has specified a file name, let's see if we know it. - // - FString game = GetGameFronUserFiles(); + auto game = GetGameFronUserFiles(); if (userConfig.gamegrp.IsEmpty()) { - userConfig.gamegrp = game; + for (auto& str : game) + { + for (auto& grp : groups) + { + if (grp.FileInfo.gameid.CompareNoCase(str) == 0) + { + userConfig.gamegrp = grp.FileName; + goto foundit; + } + } + } } + foundit: + // If the user has specified a file name, let's see if we know it. + // if (userConfig.gamegrp.Len()) { FString gamegrplower = "/" + userConfig.gamegrp.MakeLower(); diff --git a/source/core/gamecontrol.h b/source/core/gamecontrol.h index 292c9a4b4..1316ed8d4 100644 --- a/source/core/gamecontrol.h +++ b/source/core/gamecontrol.h @@ -139,6 +139,7 @@ struct GrpInfo FString defname; FString rtsname; FString gamefilter; + FString gameid; uint32_t CRC = 0; uint32_t dependencyCRC = 0; size_t size = 0; diff --git a/source/core/initfs.cpp b/source/core/initfs.cpp index 3ad2283f4..b0e6da37c 100644 --- a/source/core/initfs.cpp +++ b/source/core/initfs.cpp @@ -60,10 +60,10 @@ static const char* validexts[] = { "*.grp", "*.zip", "*.pk3", "*.pk4", "*.7z", " // //========================================================================== -static FString ParseGameInfo(TArray& pwads, const char* fn, const char* data, int size) +static TArray ParseGameInfo(TArray& pwads, const char* fn, const char* data, int size) { FScanner sc; - FString iwad; + TArray bases; int pos = 0; const char* lastSlash = strrchr(fn, '/'); @@ -78,7 +78,7 @@ static FString ParseGameInfo(TArray& pwads, const char* fn, const char* if (!nextKey.CompareNoCase("GAME")) { sc.MustGetString(); - iwad = sc.String; + bases.Push(sc.String); } else if (!nextKey.CompareNoCase("LOAD")) { @@ -136,7 +136,7 @@ static FString ParseGameInfo(TArray& pwads, const char* fn, const char* } while (sc.CheckToken(',')); } } - return iwad; + return bases; } //========================================================================== // @@ -144,7 +144,7 @@ static FString ParseGameInfo(TArray& pwads, const char* fn, const char* // //========================================================================== -static FString CheckGameInfo(TArray& pwads) +static TArray CheckGameInfo(TArray& pwads) { // scan the list of WADs backwards to find the last one that contains a GAMEINFO lump for (int i = pwads.Size() - 1; i >= 0; i--) @@ -184,15 +184,15 @@ static FString CheckGameInfo(TArray& pwads) if (FName(lmp->getName(), true) == gameinfo) { // Found one! - FString iwad = ParseGameInfo(pwads, resfile->FileName, (const char*)lmp->Lock(), lmp->LumpSize); + auto bases = ParseGameInfo(pwads, resfile->FileName, (const char*)lmp->Lock(), lmp->LumpSize); delete resfile; - return iwad; + return bases; } } delete resfile; } } - return ""; + return TArray(); } //========================================================================== @@ -201,7 +201,7 @@ static FString CheckGameInfo(TArray& pwads) // //========================================================================== -FString GetGameFronUserFiles() +TArray GetGameFronUserFiles() { TArray Files; From b5dbc3cf29e4d287d3f78f97405c739b03b86d75 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 13 Apr 2021 17:08:04 +0200 Subject: [PATCH 09/11] - allow specifying startup .con files via GAMEINFO. --- source/common/engine/startupinfo.h | 2 +- source/core/gamecontrol.cpp | 2 +- source/core/initfs.cpp | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/source/common/engine/startupinfo.h b/source/common/engine/startupinfo.h index f47fa351f..ec4ee2b30 100644 --- a/source/common/engine/startupinfo.h +++ b/source/common/engine/startupinfo.h @@ -9,11 +9,11 @@ struct FStartupInfo uint32_t FgColor; // Foreground color for title banner uint32_t BkColor; // Background color for title banner FString Song; + FString con; int Type; int LoadLights = -1; int LoadBrightmaps = -1; int LoadWidescreen = -1; - int modern = 0; enum { DefaultStartup, diff --git a/source/core/gamecontrol.cpp b/source/core/gamecontrol.cpp index 5bfdd21c6..96431b3e6 100644 --- a/source/core/gamecontrol.cpp +++ b/source/core/gamecontrol.cpp @@ -757,7 +757,7 @@ static TArray SetupGame() if (ugroup.FileInfo.gamefilter.IsNotEmpty()) LumpFilter = ugroup.FileInfo.gamefilter; g_gameType |= ugroup.FileInfo.flags; } - if (userConfig.DefaultCon.IsEmpty()) userConfig.DefaultCon = selectedScript; + if (userConfig.DefaultCon.IsEmpty()) userConfig.DefaultCon = GameStartupInfo.con.IsNotEmpty()? GameStartupInfo.con : selectedScript; if (userConfig.DefaultDef.IsEmpty()) userConfig.DefaultDef = selectedDef; // This can only happen with a custom game that does not define any filter. diff --git a/source/core/initfs.cpp b/source/core/initfs.cpp index b0e6da37c..f511378ca 100644 --- a/source/core/initfs.cpp +++ b/source/core/initfs.cpp @@ -122,10 +122,10 @@ static TArray ParseGameInfo(TArray& pwads, const char* fn, con sc.MustGetString(); GameStartupInfo.BkColor = V_GetColor(NULL, sc); } - else if (!nextKey.CompareNoCase("MODERN")) + else if (!nextKey.CompareNoCase("CON")) { - sc.MustGetNumber(); - GameStartupInfo.modern = sc.Number ? 1 : -1; + sc.MustGetString(); + GameStartupInfo.con = sc.String;; } else { From bc007d75deb815b5de63329cd096e47189facfe2 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 14 Apr 2021 14:16:09 +0200 Subject: [PATCH 10/11] - make map art work. --- source/core/textures/buildtiles.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/source/core/textures/buildtiles.cpp b/source/core/textures/buildtiles.cpp index b08a70b0d..5a4c39554 100644 --- a/source/core/textures/buildtiles.cpp +++ b/source/core/textures/buildtiles.cpp @@ -598,13 +598,14 @@ void artClearMapArt(void) void artSetupMapArt(const char* filename) { - if (currentMapArt.CompareNoCase(filename)) return; - currentMapArt = filename; - artClearMapArt(); - - FString lcfilename = filename; + FString lcfilename = StripExtension(filename); lcfilename.MakeLower(); + if (currentMapArt.CompareNoCase(lcfilename) == 0) return; + artClearMapArt(); + currentMapArt = lcfilename; + + // Re-get from the texture manager if this map's tiles have already been created. if (TileFiles.maptilesadded.Find(lcfilename) < TileFiles.maptilesadded.Size()) { @@ -634,7 +635,7 @@ void artSetupMapArt(const char* filename) for (bssize_t i = 0; i < MAXARTFILES_TOTAL - MAXARTFILES_BASE; i++) { - FStringf fullname("%s_%02d.art", filename, i); + FStringf fullname("%s_%02d.art", lcfilename.GetChars(), i); TileFiles.LoadArtFile(fullname, filename); } } From f6c4c19b022a50328e7315888e3a64b0cc3021d8 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 14 Apr 2021 22:12:15 +0200 Subject: [PATCH 11/11] - added a filter to the directory loader to remove EDuke32's texture cache files. These cause problems with the texture manager. --- source/common/filesystem/file_directory.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/source/common/filesystem/file_directory.cpp b/source/common/filesystem/file_directory.cpp index 4f2c94eba..8c7b57876 100644 --- a/source/common/filesystem/file_directory.cpp +++ b/source/common/filesystem/file_directory.cpp @@ -154,13 +154,28 @@ int FDirectory::AddDirectory(const char *dirpath) } else { - if (strstr(fi, ".orig") || strstr(fi, ".bak")) + if (strstr(fi, ".orig") || strstr(fi, ".bak") || strstr(fi, ".cache")) { // We shouldn't add backup files to the file system continue; } size_t size = 0; FString fn = FString(dirpath) + fi; + + // The next one is courtesy of EDuke32. :( + // Putting cache files in the application directory is very bad style. + // Unfortunately, having a garbage file named "texture" present will cause serious problems down the line. + if (!stricmp(fi, "textures")) + { + FILE* f = fopen(fn, "rb"); + if (f) + { + char check[3]{}; + fread(check, 1, 3, f); + if (!memcmp(check, "LZ4", 3)) continue; + } + } + if (GetFileInfo(fn, &size, nullptr)) { AddEntry(fn, (int)size);