diff --git a/systems/ps4.ixx b/systems/ps4.ixx index 78038d40..df63ed26 100644 --- a/systems/ps4.ixx +++ b/systems/ps4.ixx @@ -54,7 +54,73 @@ public: serial.insert(4, "-"); os << std::format(" serial: {}", serial) << std::endl; } + + std::string content_ids = getContentIds(root_directory, _PKG_FILE_NAMES); + + if(content_ids.empty()) + return; + + os << std::format(" content ID(s): {}", content_ids) << std::endl; } + +protected: + std::string getContentIds(std::shared_ptr root_directory, std::span pkg_file_names) const + { + auto app_directory = root_directory->subEntry("app"); + if(!app_directory) + return ""; + + auto app_directory_entries = app_directory->entries(); + std::string content_ids; + + for(auto &e : app_directory_entries) + { + if(!e->isDirectory()) + continue; + + for(const auto& pkg_file_name : pkg_file_names) + { + auto app_pkg_entry = e->subEntry(pkg_file_name); + if(!app_pkg_entry) + continue; + + auto app_pkg_raw = app_pkg_entry->read(); + + if(app_pkg_raw.size() < _PKG_HEADER_SIZE) + continue; + + uint32_t app_pkg_magic = + (static_cast(app_pkg_raw[_PKG_MAGIC_OFFSET + 0]) << 24) | + (static_cast(app_pkg_raw[_PKG_MAGIC_OFFSET + 1]) << 16) | + (static_cast(app_pkg_raw[_PKG_MAGIC_OFFSET + 2]) << 8) | + (static_cast(app_pkg_raw[_PKG_MAGIC_OFFSET + 3]) << 0); + + if(app_pkg_magic != _PKG_MAGIC) + continue; + + std::span app_pkg_content_id(app_pkg_raw.data() + _PKG_CONTENT_ID_OFFSET, _PKG_CONTENT_ID_SIZE); + + std::string_view app_pkg_content_id_text(reinterpret_cast(app_pkg_content_id.data()), _PKG_CONTENT_ID_SIZE); + + if(!content_ids.empty()) + content_ids += ", "; + + content_ids += app_pkg_content_id_text; + + break; + } + } + + return content_ids; + } + +private: + static constexpr uint32_t _PKG_HEADER_SIZE = 0x1000; + static constexpr uint32_t _PKG_MAGIC = 0x7F434E54; + static constexpr uint32_t _PKG_MAGIC_OFFSET = 0x00; + static constexpr uint32_t _PKG_CONTENT_ID_OFFSET = 0x40; + static constexpr uint32_t _PKG_CONTENT_ID_SIZE = 36; + static constexpr std::array _PKG_FILE_NAMES = {"app.pkg", "app_h.pkg", "app_0.pkg"}; }; } diff --git a/systems/ps5.ixx b/systems/ps5.ixx index aa3520ea..e078814a 100644 --- a/systems/ps5.ixx +++ b/systems/ps5.ixx @@ -11,6 +11,7 @@ export module systems.ps5; import filesystem.iso9660; import readers.data_reader; +import systems.ps4; import utils.misc; import utils.strings; @@ -19,7 +20,7 @@ import utils.strings; namespace gpsxre { -export class SystemPS5 : public System +export class SystemPS5 : public SystemPS4 { public: std::string getName() override @@ -48,9 +49,18 @@ public: if(auto it = param_json.find("masterDataId"); it != param_json.end()) os << std::format(" serial: {}", it->second.insert(4, "-")) << std::endl; + + std::string content_ids = getContentIds(root_directory, _PKG_FILE_NAMES); + + if(content_ids.empty()) + return; + + os << std::format(" content ID(s): {}", content_ids) << std::endl; } private: + static constexpr std::array _PKG_FILE_NAMES = {"app_sc.pkg"}; + std::map loadJSON(std::shared_ptr json_entry) const { std::map json;