diff --git a/src/common/memory_patcher.cpp b/src/common/memory_patcher.cpp index 2517e3f22..429b11f86 100644 --- a/src/common/memory_patcher.cpp +++ b/src/common/memory_patcher.cpp @@ -8,6 +8,7 @@ #include #include #include +#include "common/config.h" #include "common/elf_info.h" #include "common/logging/log.h" #include "common/path_util.h" @@ -193,16 +194,56 @@ void OnGameLoaded() { ApplyPatchesFromXML(file_path); } } else if (EmulatorState::GetInstance()->IsAutoPatchesLoadEnabled()) { + if (g_game_serial.empty()) { + ApplyPendingPatches(); + return; + } for (auto const& repo : std::filesystem::directory_iterator(patch_dir)) { if (!repo.is_directory()) { continue; } - std::ifstream json_file{repo.path() / "files.json"}; - nlohmann::json available_patches = nlohmann::json::parse(json_file); + const auto json_path = repo.path() / "files.json"; + if (!std::filesystem::exists(json_path)) { + continue; + } + + std::ifstream json_file{json_path}; + if (!json_file.is_open()) { + LOG_ERROR(Loader, "Failed to open patch index: {}", json_path.string()); + continue; + } + + nlohmann::json available_patches; + try { + available_patches = nlohmann::json::parse(json_file); + } catch (const std::exception& e) { + LOG_ERROR(Loader, "Failed to parse patch index {}: {}", json_path.string(), + e.what()); + continue; + } + + if (!available_patches.is_object()) { + LOG_ERROR(Loader, "Invalid patch index (expected object): {}", json_path.string()); + continue; + } + std::filesystem::path game_patch_file; - for (auto const& [filename, serials] : available_patches.items()) { - if (std::find(serials.begin(), serials.end(), g_game_serial) != serials.end()) { - game_patch_file = repo.path() / filename; + for (auto it = available_patches.begin(); it != available_patches.end(); ++it) { + const auto& serials = it.value(); + if (!serials.is_array()) { + continue; + } + + bool matches = false; + for (const auto& serial : serials) { + if (serial.is_string() && + serial.get_ref() == g_game_serial) { + matches = true; + break; + } + } + if (matches) { + game_patch_file = repo.path() / it.key(); break; } } diff --git a/src/emulator.cpp b/src/emulator.cpp index 616a21ed1..429fc746c 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2025-2026 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include #include #include #include @@ -135,7 +136,7 @@ void Emulator::Run(std::filesystem::path file, std::vector args, std::string id; std::string title; std::string app_version; - u32 sdk_version; + u32 sdk_version{}; u32 fw_version; Common::PSFAttributes psf_attributes{}; if (param_sfo_exists) { @@ -144,10 +145,17 @@ void Emulator::Run(std::filesystem::path file, std::vector args, const auto content_id = param_sfo->GetString("CONTENT_ID"); const auto title_id = param_sfo->GetString("TITLE_ID"); - if (content_id.has_value() && !content_id->empty()) { - id = std::string(*content_id, 7, 9); - } else if (title_id.has_value()) { - id = *title_id; + if (content_id.has_value() && content_id->size() >= 16) { + id = content_id->substr(7, 9); + } else { + if (content_id.has_value()) { + LOG_WARNING(Loader, "CONTENT_ID too short to derive game id: {}", *content_id); + } else { + LOG_WARNING(Loader, "CONTENT_ID is missing"); + } + if (title_id.has_value() && !title_id->empty()) { + id = *title_id; + } } title = param_sfo->GetString("TITLE").value_or("Unknown title"); fw_version = param_sfo->GetInteger("SYSTEM_VER").value_or(0x4700000); @@ -167,16 +175,28 @@ void Emulator::Run(std::filesystem::path file, std::vector args, } else { // Increment offset to account for sdk_ver= part of string. sdk_ver_offset += 8; - u64 sdk_ver_len = pubtool_info.find(",", sdk_ver_offset); - if (sdk_ver_len == pubtool_info.npos) { - // If there's no more commas, this is likely the last entry of pubtool info. - // Use string length instead. - sdk_ver_len = pubtool_info.size(); + if (sdk_ver_offset > pubtool_info.size()) { + LOG_WARNING(Loader, "PUBTOOLINFO sdk_ver is malformed"); + sdk_version = fw_version; + } else { + u64 sdk_ver_len = pubtool_info.find(",", sdk_ver_offset); + if (sdk_ver_len == pubtool_info.npos) { + // If there's no more commas, this is likely the last entry of pubtool info. + // Use string length instead. + sdk_ver_len = pubtool_info.size(); + } + sdk_ver_len -= sdk_ver_offset; + std::string_view sdk_ver_string = pubtool_info.substr(sdk_ver_offset, sdk_ver_len); + // Number is stored in base 16. + auto result = + std::from_chars(sdk_ver_string.data(), + sdk_ver_string.data() + sdk_ver_string.size(), sdk_version, 16); + if (result.ec != std::errc()) { + LOG_WARNING(Loader, "Failed to parse sdk_ver '{}' from PUBTOOLINFO", + sdk_ver_string); + sdk_version = fw_version; + } } - sdk_ver_len -= sdk_ver_offset; - std::string sdk_ver_string = pubtool_info.substr(sdk_ver_offset, sdk_ver_len).data(); - // Number is stored in base 16. - sdk_version = std::stoi(sdk_ver_string, nullptr, 16); } }