diff --git a/Core/System.cpp b/Core/System.cpp index 0b00b18463..b4a3b7c476 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -226,15 +226,37 @@ bool DiscIDFromGEDumpPath(const Path &path, FileLoader *fileLoader, std::string } } - // Fall back to using the filename. - std::string filename = path.GetFilename(); - // Could be more discerning, but hey.. - if (filename.size() > 10 && (filename[0] == 'U' || filename[0] == 'N') && filename[9] == '_') { - *id = filename.substr(0, 9); - return true; + // Fall back to the file name. + return DiscIDFromGEDumpFilename(path.GetFilename(), id); +} + +// PPSSPP names dumps ULUS10064_0001.ppdmp; the ppsspp-framedumps collection puts the GitHub issue number in +// front ("11928 ULUS10064_0001 OutRun water.ppdmp"). +bool DiscIDFromGEDumpFilename(std::string_view filename, std::string *id) { + size_t start = 0; + while (start < filename.size() && filename[start] >= '0' && filename[start] <= '9') { + start++; + } + if (start > 0 && start < filename.size() && filename[start] == ' ') { + start++; } else { + start = 0; + } + // The ID is followed by _NNNN, the extension, a description, or nothing. + if (filename.size() < start + 9) { return false; } + if (filename.size() > start + 9 && filename[start + 9] != '_' && filename[start + 9] != '.' && filename[start + 9] != ' ') { + return false; + } + for (size_t i = 0; i < 9; i++) { + const char c = filename[start + i]; + if (i < 4 ? !(c >= 'A' && c <= 'Z') : !(c >= '0' && c <= '9')) { + return false; + } + } + *id = std::string(filename.substr(start, 9)); + return true; } static void GetBootError(IdentifiedFileType type, std::string *errorString) { diff --git a/Core/System.h b/Core/System.h index 7019ebd8b3..8e241d294f 100644 --- a/Core/System.h +++ b/Core/System.h @@ -92,6 +92,9 @@ void PSP_ForceDebugStats(bool enable); void UpdateLoadedFile(FileLoader *fileLoader); +// The game ID in a frame dump's file name (ULUS10064_0001.ppdmp, or with a GitHub issue number in front). +bool DiscIDFromGEDumpFilename(std::string_view filename, std::string *id); + // NOTE: These are almost all derived from g_Config.memStickDirectory directly - // they are not stored anywhere. Path GetSysDirectory(PSPDirectories directoryType); diff --git a/unittest/UnitTest.cpp b/unittest/UnitTest.cpp index 32c0108a1b..44411c379d 100644 --- a/unittest/UnitTest.cpp +++ b/unittest/UnitTest.cpp @@ -97,6 +97,7 @@ #include #include #include "Core/CmdLine.h" +#include "Core/System.h" #include "Common/Data/Collections/Hashmaps.h" #include "Core/Util/BlockAllocator.h" #include "Core/Debugger/Breakpoints.h" @@ -2844,6 +2845,29 @@ bool TestFriendlyPath() { return true; } +bool TestGEDumpGameID() { + std::string id; + // PPSSPP's own dump names. + EXPECT_TRUE(DiscIDFromGEDumpFilename("ULUS10064_0001.ppdmp", &id)); + EXPECT_EQ_STR(id, std::string("ULUS10064")); + // ppsspp-framedumps: a GitHub issue number in front, a description after. + EXPECT_TRUE(DiscIDFromGEDumpFilename("11928 ULES00262_0003 OutRun water.ppdmp", &id)); + EXPECT_EQ_STR(id, std::string("ULES00262")); + EXPECT_TRUE(DiscIDFromGEDumpFilename("21127 WPCE02025_0001 WipEout Pure.ppdmp", &id)); + EXPECT_EQ_STR(id, std::string("WPCE02025")); + EXPECT_TRUE(DiscIDFromGEDumpFilename("ULUS10064.ppdmp", &id)); + EXPECT_EQ_STR(id, std::string("ULUS10064")); + EXPECT_TRUE(DiscIDFromGEDumpFilename("11928 ULUS10064.ppdmp", &id)); + EXPECT_EQ_STR(id, std::string("ULUS10064")); + // No ID in PPSSPP's form, even if one appears later in the name. + EXPECT_FALSE(DiscIDFromGEDumpFilename("11928 OutRun water ULUS10064.ppdmp", &id)); + EXPECT_FALSE(DiscIDFromGEDumpFilename("11928 Harvest Moon Graphic Issue on Adreno.ppdmp", &id)); + EXPECT_FALSE(DiscIDFromGEDumpFilename("ULUS1006A_0001.ppdmp", &id)); + EXPECT_FALSE(DiscIDFromGEDumpFilename("ULUS100641_0001.ppdmp", &id)); + EXPECT_FALSE(DiscIDFromGEDumpFilename("11928ULUS10064_0001.ppdmp", &id)); + return true; +} + bool TestCmdLine() { { const char *argv[] = { @@ -3171,6 +3195,7 @@ TestItem availableTests[] = { TEST_ITEM(TextureReplacer), TEST_ITEM(UITabOrder), TEST_ITEM(FatShortNames), + TEST_ITEM(GEDumpGameID), }; int main(int argc, const char *argv[]) {