From 5aacb2370d48fc392345a7b499af54caaef90a9a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 13 Feb 2021 10:05:46 +0100 Subject: [PATCH] - fixed game resource lookup. The algorithm was a bit too complicated and missed the smallest defined game resource. GrpInfo was renamed because there were two of them which created a debugger conflict. --- source/common/filesystem/file_grp.cpp | 6 +-- source/core/gamecontrol.h | 4 +- source/core/searchpaths.cpp | 58 +++++++++------------------ wadsrc/static/engine/grpinfo.txt | 12 ------ 4 files changed, 24 insertions(+), 56 deletions(-) diff --git a/source/common/filesystem/file_grp.cpp b/source/common/filesystem/file_grp.cpp index 1bf3bd7a4..97f17f17f 100644 --- a/source/common/filesystem/file_grp.cpp +++ b/source/common/filesystem/file_grp.cpp @@ -42,7 +42,7 @@ // //========================================================================== -struct GrpInfo +struct GrpHeader { uint32_t Magic[3]; uint32_t NumLumps; @@ -95,7 +95,7 @@ FGrpFile::FGrpFile(const char *filename, FileReader &file) bool FGrpFile::Open(bool quiet, LumpFilterInfo*) { - GrpInfo header; + GrpHeader header; Reader.Read(&header, sizeof(header)); NumLumps = LittleLong(header.NumLumps); @@ -105,7 +105,7 @@ bool FGrpFile::Open(bool quiet, LumpFilterInfo*) Lumps.Resize(NumLumps); - int Position = sizeof(GrpInfo) + NumLumps * sizeof(GrpLump); + int Position = sizeof(GrpHeader) + NumLumps * sizeof(GrpLump); for(uint32_t i = 0; i < NumLumps; i++) { diff --git a/source/core/gamecontrol.h b/source/core/gamecontrol.h index 4cbe7df25..dd104680a 100644 --- a/source/core/gamecontrol.h +++ b/source/core/gamecontrol.h @@ -133,7 +133,7 @@ enum }; -struct GrpInfo +struct GrpDefInfo { FString name; FString scriptname; @@ -156,7 +156,7 @@ struct GrpInfo struct GrpEntry { FString FileName; - GrpInfo FileInfo; + GrpDefInfo FileInfo; uint32_t FileIndex; }; extern int g_gameType; diff --git a/source/core/searchpaths.cpp b/source/core/searchpaths.cpp index 58dafaf0f..cd5b2550e 100644 --- a/source/core/searchpaths.cpp +++ b/source/core/searchpaths.cpp @@ -378,9 +378,9 @@ void SaveCRCs(TArray& crclist) // //========================================================================== -static TArray ParseGrpInfo(const char *fn, FileReader &fr, TMap &CRCMap) +static TArray ParseGrpInfo(const char *fn, FileReader &fr, TMap &CRCMap) { - TArray groups; + TArray groups; TMap FlagMap; FlagMap.Insert("GAMEFLAG_DUKE", GAMEFLAG_DUKE); @@ -580,9 +580,9 @@ static TArray ParseGrpInfo(const char *fn, FileReader &fr, TMap ParseAllGrpInfos(TArray& filelist) +TArray ParseAllGrpInfos(TArray& filelist) { - TArray groups; + TArray groups; TMap CRCMap; // This opens the base resource only for reading the grpinfo from it which we need before setting up the game state. std::unique_ptr engine_res; @@ -655,7 +655,7 @@ void GetCRC(FileEntry *entry, TArray &CRCCache) } } -GrpInfo *IdentifyGroup(FileEntry *entry, TArray &groups) +GrpDefInfo *IdentifyGroup(FileEntry *entry, TArray &groups) { for (auto g : groups) { @@ -671,7 +671,7 @@ GrpInfo *IdentifyGroup(FileEntry *entry, TArray &groups) // //========================================================================== -static bool CheckAddon(GrpInfo* addon, GrpInfo* main, const char* filename) +static bool CheckAddon(GrpDefInfo* addon, GrpDefInfo* main, const char* filename) { if (addon->dependencyCRC != main->CRC) return false; FString path = ExtractFilePath(filename); @@ -702,9 +702,9 @@ TArray GrpScan() TArray foundGames; TArray sortedFileList; - TArray sortedGroupList; - TArray contentGroupList; - TArray addonList; + TArray sortedGroupList; + TArray contentGroupList; + TArray addonList; auto allFiles = CollectAllFilesInSearchPath(); auto allGroups = ParseAllGrpInfos(allFiles); @@ -770,42 +770,22 @@ TArray GrpScan() } } + TMap sizeLookup; + TArray matchedFileList; - std::sort(sortedFileList.begin(), sortedFileList.end(), [](FileEntry* lhs, FileEntry* rhs) { return lhs->FileLength < rhs->FileLength; }); - std::sort(sortedGroupList.begin(), sortedGroupList.end(), [](GrpInfo* lhs, GrpInfo* rhs) { return lhs->size < rhs->size; }); - - int findex = sortedFileList.Size() - 1; - int gindex = sortedGroupList.Size() - 1; - - - while (findex > 0 && gindex > 0) + for (auto& entry : sortedGroupList) { - if (sortedFileList[findex]->FileLength > sortedGroupList[gindex]->size) - { - // File is larger than the largest known group so it cannot be a candidate. - sortedFileList.Delete(findex--); - } - else if (sortedFileList[findex]->FileLength < sortedGroupList[gindex]->size) - { - // The largest available file is smaller than this group so we cannot possibly have it. - sortedGroupList.Delete(gindex--); - } - else - { - findex--; - gindex--; - // We found a matching file. Skip over all other entries of the same size so we can analyze those later as well - while (findex > 0 && sortedFileList[findex]->FileLength == sortedFileList[findex + 1]->FileLength) findex--; - while (gindex > 0 && sortedGroupList[gindex]->size == sortedGroupList[gindex + 1]->size) gindex--; - } + sizeLookup.Insert(entry->size, true); + } + for (auto entry : sortedFileList) + { + if (sizeLookup.CheckKey(entry->FileLength)) matchedFileList.Push(entry); } - sortedFileList.Delete(0, findex + 1); - sortedGroupList.Delete(0, gindex + 1); - if (sortedGroupList.Size() == 0 || sortedFileList.Size() == 0) + if (matchedFileList.Size() == 0) return foundGames; - for (auto entry : sortedFileList) + for (auto entry : matchedFileList) { GetCRC(entry, cachedCRCs); auto grp = IdentifyGroup(entry, sortedGroupList); diff --git a/wadsrc/static/engine/grpinfo.txt b/wadsrc/static/engine/grpinfo.txt index a567ea8a6..b83487364 100644 --- a/wadsrc/static/engine/grpinfo.txt +++ b/wadsrc/static/engine/grpinfo.txt @@ -672,18 +672,6 @@ grpinfo gamefilter "Witchaven.Witchaven" } -grpinfo -{ - // The file identification info here is for joesnd which is one of two containers in the game data. - name "Witchaven" - flags GAMEFLAG_WITCHAVEN - crc 0x4CC892B7 - size 2797568 - defname "witchaven.def" - loadgrp "SONGS" - gamefilter "Witchaven.Witchaven" -} - grpinfo { // The file identification info here is for joesnd which is one of three containers in the game data.