[Emulator] Added summary window to Install Content option

This commit is contained in:
Gliniak 2024-06-26 13:06:53 +02:00 committed by Radosław Gliński
parent d6767dcd66
commit 49166f0bd1
4 changed files with 111 additions and 11 deletions

View File

@ -1045,20 +1045,58 @@ void EmulatorWindow::InstallContent() {
return; return;
} }
for (auto path : paths) { using content_installation_data =
std::tuple<X_STATUS, std::string, std::string>;
std::map<XContentType, std::vector<content_installation_data>>
content_installation_details;
for (const auto& path : paths) {
// Normalize the path and make absolute. // Normalize the path and make absolute.
auto abs_path = std::filesystem::absolute(path); auto abs_path = std::filesystem::absolute(path);
auto result = emulator_->InstallContentPackage(abs_path);
if (result != X_STATUS_SUCCESS) { Emulator::ContentInstallationInfo installation_info;
XELOGE("Failed to install content! Error code: {:08X}", result); auto result = emulator_->InstallContentPackage(abs_path, installation_info);
xe::ui::ImGuiDialog::ShowMessageBox( auto entry =
imgui_drawer_.get(), "Failed to install content!", content_installation_details.find(installation_info.content_type);
"Failed to install content!\n\nCheck xenia.log for technical "
"details."); // There is no entry with that specific type of XContent, so we must add it.
if (entry == content_installation_details.end()) {
content_installation_details.insert({installation_info.content_type, {}});
entry = content_installation_details.find(installation_info.content_type);
};
entry->second.push_back({result, installation_info.content_name,
installation_info.installation_path});
} }
// Prepare installation process summary message
std::string summary = "Installation result: \n";
for (const auto& content_type : content_installation_details) {
if (XContentTypeMap.find(content_type.first) != XContentTypeMap.cend()) {
summary += XContentTypeMap.at(content_type.first) + ":\n";
} else {
summary += "Unknown:\n";
} }
for (const auto& content_installation_entry : content_type.second) {
const std::string status =
std::get<0>(content_installation_entry) == X_STATUS_SUCCESS
? "Success"
: fmt::format("Failed (0x{:08X})",
std::get<0>(content_installation_entry));
summary += fmt::format("\t{} - {} => {}\n", status,
std::get<1>(content_installation_entry),
std::get<2>(content_installation_entry));
}
summary += "\n";
}
xe::ui::ImGuiDialog::ShowMessageBox(imgui_drawer_.get(),
"Content Installation Summary", summary);
} }
void EmulatorWindow::ExtractZarchive() { void EmulatorWindow::ExtractZarchive() {

View File

@ -593,9 +593,16 @@ X_STATUS Emulator::LaunchDefaultModule(const std::filesystem::path& path) {
return result; return result;
} }
X_STATUS Emulator::InstallContentPackage(const std::filesystem::path& path) { X_STATUS Emulator::InstallContentPackage(
const std::filesystem::path& path,
ContentInstallationInfo& installation_info) {
std::unique_ptr<vfs::Device> device = std::unique_ptr<vfs::Device> device =
vfs::XContentContainerDevice::CreateContentDevice("", path); vfs::XContentContainerDevice::CreateContentDevice("", path);
installation_info.content_name = "Invalid Content Package!";
installation_info.content_type = static_cast<XContentType>(0);
installation_info.installation_path = xe::path_to_utf8(path.filename());
if (!device || !device->Initialize()) { if (!device || !device->Initialize()) {
XELOGE("Failed to initialize device"); XELOGE("Failed to initialize device");
return X_STATUS_INVALID_PARAMETER; return X_STATUS_INVALID_PARAMETER;
@ -612,6 +619,15 @@ X_STATUS Emulator::InstallContentPackage(const std::filesystem::path& path) {
content_root() / fmt::format("{:08X}", dev->title_id()) / "Headers" / content_root() / fmt::format("{:08X}", dev->title_id()) / "Headers" /
fmt::format("{:08X}", dev->content_type()) / path.filename(); fmt::format("{:08X}", dev->content_type()) / path.filename();
installation_info.installation_path =
fmt::format("{:08X}/{:08X}/{}", dev->title_id(), dev->content_type(),
xe::path_to_utf8(path.filename()));
installation_info.content_name =
xe::to_utf8(dev->content_header().display_name());
installation_info.content_type =
static_cast<XContentType>(dev->content_type());
if (std::filesystem::exists(installation_path)) { if (std::filesystem::exists(installation_path)) {
// TODO(Gliniak): Popup // TODO(Gliniak): Popup
// Do you want to overwrite already existing data? // Do you want to overwrite already existing data?
@ -619,6 +635,7 @@ X_STATUS Emulator::InstallContentPackage(const std::filesystem::path& path) {
std::error_code error_code; std::error_code error_code;
std::filesystem::create_directories(installation_path, error_code); std::filesystem::create_directories(installation_path, error_code);
if (error_code) { if (error_code) {
installation_info.content_name = "Cannot Create Content Directory!";
return error_code.value(); return error_code.value();
} }
} }

View File

@ -223,8 +223,15 @@ class Emulator {
X_STATUS LaunchDefaultModule(const std::filesystem::path& path); X_STATUS LaunchDefaultModule(const std::filesystem::path& path);
struct ContentInstallationInfo {
XContentType content_type;
std::string installation_path;
std::string content_name;
};
// Extract content of package to content specific directory. // Extract content of package to content specific directory.
X_STATUS InstallContentPackage(const std::filesystem::path& path); X_STATUS InstallContentPackage(const std::filesystem::path& path,
ContentInstallationInfo& installation_info);
// Extract content of zar package to desired directory. // Extract content of zar package to desired directory.
X_STATUS Emulator::ExtractZarchivePackage( X_STATUS Emulator::ExtractZarchivePackage(

View File

@ -10,6 +10,7 @@
#ifndef XENIA_XBOX_H_ #ifndef XENIA_XBOX_H_
#define XENIA_XBOX_H_ #define XENIA_XBOX_H_
#include <map>
#include <string> #include <string>
#include "xenia/base/memory.h" #include "xenia/base/memory.h"
@ -438,6 +439,43 @@ enum class XContentType : uint32_t {
kCommunityGame = 0x02000000, kCommunityGame = 0x02000000,
}; };
const static std::map<XContentType, std::string> XContentTypeMap = {
{XContentType::kSavedGame, "Saved Game"},
{XContentType::kMarketplaceContent, "Marketplace Content"},
{XContentType::kPublisher, "Publisher"},
{XContentType::kXbox360Title, "Xbox 360 Title"},
{XContentType::kIptvPauseBuffer, "IPTV Pause Buffer"},
{XContentType::kXNACommunity, "XNA Community"},
{XContentType::kInstalledGame, "Installed Game"},
{XContentType::kXboxTitle, "Xbox Title"},
{XContentType::kSocialTitle, "Social Title"},
{XContentType::kGamesOnDemand, "Game on Demand"},
{XContentType::kSUStoragePack, "SU Storage Pack"},
{XContentType::kAvatarItem, "Avatar Item"},
{XContentType::kProfile, "Profile"},
{XContentType::kGamerPicture, "Gamer Picture"},
{XContentType::kTheme, "Theme"},
{XContentType::kCacheFile, "Cache File"},
{XContentType::kStorageDownload, "Storage Download"},
{XContentType::kXboxSavedGame, "Xbox Saved Game"},
{XContentType::kXboxDownload, "Xbox Download"},
{XContentType::kGameDemo, "Game Demo"},
{XContentType::kVideo, "Video"},
{XContentType::kGameTitle, "Game Title"},
{XContentType::kInstaller, "Installer"},
{XContentType::kGameTrailer, "Game Trailer"},
{XContentType::kArcadeTitle, "Arcade Title"},
{XContentType::kXNA, "XNA"},
{XContentType::kLicenseStore, "License Store"},
{XContentType::kMovie, "Movie"},
{XContentType::kTV, "TV"},
{XContentType::kMusicVideo, "Music Video"},
{XContentType::kGameVideo, "Game Video"},
{XContentType::kPodcastVideo, "Podcast Video"},
{XContentType::kViralVideo, "Viral Video"},
{XContentType::kCommunityGame, "Community Game"},
};
enum class XDeploymentType : uint32_t { enum class XDeploymentType : uint32_t {
kOpticalDisc = 0, kOpticalDisc = 0,
kHardDrive = 1, // Like extracted? kHardDrive = 1, // Like extracted?