From 229ed5a8527badbd35aebe0f262d4bc87dc4af07 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Sun, 21 Feb 2021 16:53:29 +1000 Subject: [PATCH] System: Add helpers for reading executables off discs --- src/core/system.cpp | 85 +++++++++++++++++++++++++++++++++++---------- src/core/system.h | 3 ++ 2 files changed, 70 insertions(+), 18 deletions(-) diff --git a/src/core/system.cpp b/src/core/system.cpp index eb3f2ea56..e4debf47c 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -395,10 +395,32 @@ std::string GetGameCodeForPath(const char* image_path) std::string GetGameCodeForImage(CDImage* cdi) { - ISOReader iso; - if (!iso.Open(cdi, 1)) + std::string code(GetExecutableNameForImage(cdi)); + if (code.empty()) return {}; + // SCES_123.45 -> SCES-12345 + for (std::string::size_type pos = 0; pos < code.size();) + { + if (code[pos] == '.') + { + code.erase(pos, 1); + continue; + } + + if (code[pos] == '_') + code[pos] = '-'; + else + code[pos] = static_cast(std::toupper(code[pos])); + + pos++; + } + + return code; +} + +static std::string GetExecutableNameForImage(CDImage* cdi, ISOReader& iso) +{ // Read SYSTEM.CNF std::vector system_cnf_data; if (!iso.ReadFile("SYSTEM.CNF", &system_cnf_data)) @@ -461,28 +483,55 @@ std::string GetGameCodeForImage(CDImage* cdi) code.erase(0, pos + 1); } - pos = code.find(';'); + // strip off ; or version number + pos = code.rfind(';'); if (pos != std::string::npos) code.erase(pos); - // SCES_123.45 -> SCES-12345 - for (pos = 0; pos < code.size();) + return code; +} + +std::string GetExecutableNameForImage(CDImage* cdi) +{ + ISOReader iso; + if (!iso.Open(cdi, 1)) + return {}; + + return GetExecutableNameForImage(cdi, iso); +} + +bool ReadExecutableFromImage(CDImage* cdi, std::string* out_executable_name, std::vector* out_executable_data) +{ + ISOReader iso; + if (!iso.Open(cdi, 1)) + return false; + + bool result = false; + + std::string executable_name(GetExecutableNameForImage(cdi, iso)); + if (!executable_name.empty()) { - if (code[pos] == '.') - { - code.erase(pos, 1); - continue; - } - - if (code[pos] == '_') - code[pos] = '-'; - else - code[pos] = static_cast(std::toupper(code[pos])); - - pos++; + result = iso.ReadFile(executable_name.c_str(), out_executable_data); + if (!result) + Log_ErrorPrintf("Failed to read executable '%s' from disc", executable_name.c_str()); } - return code; + if (!result) + { + // fallback to PSX.EXE + executable_name = "PSX.EXE"; + result = iso.ReadFile(executable_name.c_str(), out_executable_data); + if (!result) + Log_ErrorPrint("Failed to read fallback PSX.EXE from disc"); + } + + if (!result) + return false; + + if (out_executable_name) + *out_executable_name = std::move(executable_name); + + return true; } DiscRegion GetRegionForCode(std::string_view code) diff --git a/src/core/system.h b/src/core/system.h index 629219f94..1408839e2 100644 --- a/src/core/system.h +++ b/src/core/system.h @@ -75,6 +75,9 @@ std::vector ParseM3UFile(const char* path); /// Returns the preferred console type for a disc. ConsoleRegion GetConsoleRegionForDiscRegion(DiscRegion region); +std::string GetExecutableNameForImage(CDImage* cdi); +bool ReadExecutableFromImage(CDImage* cdi, std::string* out_executable_name, std::vector* out_executable_data); + std::string GetGameCodeForImage(CDImage* cdi); std::string GetGameCodeForPath(const char* image_path); DiscRegion GetRegionForCode(std::string_view code);