diff --git a/src/xenia/emulator.cc b/src/xenia/emulator.cc index 8f5d17074..b5720e562 100644 --- a/src/xenia/emulator.cc +++ b/src/xenia/emulator.cc @@ -791,45 +791,47 @@ X_STATUS Emulator::ProcessContentPackageHeader( installation_info.content_type_ = XContentType::kInvalid; installation_info.data_installation_path_ = xe::path_to_utf8(path.filename()); - std::unique_ptr device = - vfs::XContentContainerDevice::CreateContentDevice("", path); + const auto header = vfs::XContentContainerDevice::ReadContainerHeader(path); - if (!device || !device->Initialize()) { + if (!header || !header->content_header.is_magic_valid()) { installation_info.installation_result_ = X_STATUS_INVALID_PARAMETER; installation_info.installation_error_message_ = "Invalid Package Type!"; XELOGE("Failed to initialize device"); return X_STATUS_INVALID_PARAMETER; } + // Always install savefiles to user signed to slot 0. const auto profile = kernel_state_->xam_state()->profile_manager()->GetProfile( static_cast(0)); - uint64_t xuid = device->xuid(); - if (device->content_type() == - static_cast(XContentType::kSavedGame) && + uint64_t xuid = header->content_metadata.profile_id; + if (header->content_metadata.content_type == XContentType::kSavedGame && profile) { xuid = profile->xuid(); } - installation_info.data_installation_path_ = - fmt::format("{:016X}/{:08X}/{:08X}/{}", xuid, device->title_id(), - device->content_type(), path.filename()); + installation_info.data_installation_path_ = fmt::format( + "{:016X}/{:08X}/{:08X}/{}", xuid, + header->content_metadata.execution_info.title_id.get(), + static_cast(header->content_metadata.content_type.get()), + path.filename()); - installation_info.header_installation_path_ = - fmt::format("{:016X}/{:08X}/Headers/{:08X}/{}", xuid, device->title_id(), - device->content_type(), path.filename()); + installation_info.header_installation_path_ = fmt::format( + "{:016X}/{:08X}/Headers/{:08X}/{}", xuid, + header->content_metadata.execution_info.title_id.get(), + static_cast(header->content_metadata.content_type.get()), + path.filename()); installation_info.name_ = - xe::to_utf8(device->content_header().display_name()); + xe::to_utf8(header->content_metadata.display_name(XLanguage::kEnglish)); installation_info.content_type_ = - static_cast(device->content_type()); - installation_info.content_size_ = device->data_size(); + static_cast(header->content_metadata.content_type); + installation_info.content_size_ = header->content_metadata.content_size; - installation_info.icon_ = - imgui_drawer_->LoadImGuiIcon(std::span( - device->GetContainerHeader()->content_metadata.title_thumbnail, - device->GetContainerHeader()->content_metadata.title_thumbnail_size)); + installation_info.icon_ = imgui_drawer_->LoadImGuiIcon( + std::span(header->content_metadata.title_thumbnail, + header->content_metadata.title_thumbnail_size)); return X_STATUS_SUCCESS; } @@ -879,6 +881,8 @@ X_STATUS Emulator::InstallContentPackage( } } + installation_info.content_size_ = device->data_size(); + vfs::VirtualFileSystem::ExtractContentHeader(device.get(), header_path); X_STATUS error_code = vfs::VirtualFileSystem::ExtractContentFiles( diff --git a/src/xenia/vfs/devices/xcontent_container_device.cc b/src/xenia/vfs/devices/xcontent_container_device.cc index 7da3fd860..eb95bc45f 100644 --- a/src/xenia/vfs/devices/xcontent_container_device.cc +++ b/src/xenia/vfs/devices/xcontent_container_device.cc @@ -108,11 +108,32 @@ bool XContentContainerDevice::Initialize() { return Read() == Result::kSuccess; } -XContentContainerHeader* XContentContainerDevice::ReadContainerHeader( - FILE* host_file) { - XContentContainerHeader* header = new XContentContainerHeader(); +std::unique_ptr +XContentContainerDevice::ReadContainerHeader( + const std::filesystem::path& file_path) { + if (!std::filesystem::exists(file_path)) { + return {}; + } + + if (std::filesystem::file_size(file_path) < sizeof(XContentContainerHeader)) { + return {}; + } + + auto header_file = xe::filesystem::OpenFile(file_path, "rb"); + if (!header_file) { + return {}; + } + + return ReadContainerHeader(header_file); +} + +std::unique_ptr +XContentContainerDevice::ReadContainerHeader(FILE* host_file) { + std::unique_ptr header = + std::make_unique(); + // Read header & check signature - if (fread(header, sizeof(XContentContainerHeader), 1, host_file) != 1) { + if (fread(header.get(), sizeof(XContentContainerHeader), 1, host_file) != 1) { return nullptr; } return header; @@ -173,18 +194,17 @@ XContentContainerDevice::Result XContentContainerDevice::ReadHeaderAndVerify( return Result::kTooSmall; } - const XContentContainerHeader* header = ReadContainerHeader(header_file); + auto header = ReadContainerHeader(header_file); if (header == nullptr) { return Result::kReadError; } - std::memcpy(header_.get(), header, sizeof(XContentContainerHeader)); - - if (!header_->content_header.is_magic_valid()) { + if (!header->content_header.is_magic_valid()) { // Unexpected format. return Result::kFileMismatch; } + header_ = std::move(header); return Result::kSuccess; } diff --git a/src/xenia/vfs/devices/xcontent_container_device.h b/src/xenia/vfs/devices/xcontent_container_device.h index c44801a43..f1a738687 100644 --- a/src/xenia/vfs/devices/xcontent_container_device.h +++ b/src/xenia/vfs/devices/xcontent_container_device.h @@ -35,6 +35,12 @@ class XContentContainerDevice : public Device { const std::string_view mount_path, const std::filesystem::path& host_path); + static std::unique_ptr ReadContainerHeader( + const std::filesystem::path& file_path); + + static std::unique_ptr ReadContainerHeader( + FILE* host_file); + ~XContentContainerDevice() override; bool Initialize() override; @@ -117,9 +123,6 @@ class XContentContainerDevice : public Device { size_t files_total_size_; std::unique_ptr root_entry_; std::unique_ptr header_; - - private: - static XContentContainerHeader* ReadContainerHeader(FILE* host_file); }; } // namespace vfs