[VFS] Improved initial loading time during "Install Content"
This commit is contained in:
@@ -791,45 +791,47 @@ X_STATUS Emulator::ProcessContentPackageHeader(
|
|||||||
installation_info.content_type_ = XContentType::kInvalid;
|
installation_info.content_type_ = XContentType::kInvalid;
|
||||||
installation_info.data_installation_path_ = xe::path_to_utf8(path.filename());
|
installation_info.data_installation_path_ = xe::path_to_utf8(path.filename());
|
||||||
|
|
||||||
std::unique_ptr<vfs::XContentContainerDevice> device =
|
const auto header = vfs::XContentContainerDevice::ReadContainerHeader(path);
|
||||||
vfs::XContentContainerDevice::CreateContentDevice("", path);
|
|
||||||
|
|
||||||
if (!device || !device->Initialize()) {
|
if (!header || !header->content_header.is_magic_valid()) {
|
||||||
installation_info.installation_result_ = X_STATUS_INVALID_PARAMETER;
|
installation_info.installation_result_ = X_STATUS_INVALID_PARAMETER;
|
||||||
installation_info.installation_error_message_ = "Invalid Package Type!";
|
installation_info.installation_error_message_ = "Invalid Package Type!";
|
||||||
XELOGE("Failed to initialize device");
|
XELOGE("Failed to initialize device");
|
||||||
return X_STATUS_INVALID_PARAMETER;
|
return X_STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always install savefiles to user signed to slot 0.
|
// Always install savefiles to user signed to slot 0.
|
||||||
const auto profile =
|
const auto profile =
|
||||||
kernel_state_->xam_state()->profile_manager()->GetProfile(
|
kernel_state_->xam_state()->profile_manager()->GetProfile(
|
||||||
static_cast<uint8_t>(0));
|
static_cast<uint8_t>(0));
|
||||||
|
|
||||||
uint64_t xuid = device->xuid();
|
uint64_t xuid = header->content_metadata.profile_id;
|
||||||
if (device->content_type() ==
|
if (header->content_metadata.content_type == XContentType::kSavedGame &&
|
||||||
static_cast<uint32_t>(XContentType::kSavedGame) &&
|
|
||||||
profile) {
|
profile) {
|
||||||
xuid = profile->xuid();
|
xuid = profile->xuid();
|
||||||
}
|
}
|
||||||
|
|
||||||
installation_info.data_installation_path_ =
|
installation_info.data_installation_path_ = fmt::format(
|
||||||
fmt::format("{:016X}/{:08X}/{:08X}/{}", xuid, device->title_id(),
|
"{:016X}/{:08X}/{:08X}/{}", xuid,
|
||||||
device->content_type(), path.filename());
|
header->content_metadata.execution_info.title_id.get(),
|
||||||
|
static_cast<uint32_t>(header->content_metadata.content_type.get()),
|
||||||
|
path.filename());
|
||||||
|
|
||||||
installation_info.header_installation_path_ =
|
installation_info.header_installation_path_ = fmt::format(
|
||||||
fmt::format("{:016X}/{:08X}/Headers/{:08X}/{}", xuid, device->title_id(),
|
"{:016X}/{:08X}/Headers/{:08X}/{}", xuid,
|
||||||
device->content_type(), path.filename());
|
header->content_metadata.execution_info.title_id.get(),
|
||||||
|
static_cast<uint32_t>(header->content_metadata.content_type.get()),
|
||||||
|
path.filename());
|
||||||
|
|
||||||
installation_info.name_ =
|
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_ =
|
installation_info.content_type_ =
|
||||||
static_cast<XContentType>(device->content_type());
|
static_cast<XContentType>(header->content_metadata.content_type);
|
||||||
installation_info.content_size_ = device->data_size();
|
installation_info.content_size_ = header->content_metadata.content_size;
|
||||||
|
|
||||||
installation_info.icon_ =
|
installation_info.icon_ = imgui_drawer_->LoadImGuiIcon(
|
||||||
imgui_drawer_->LoadImGuiIcon(std::span<const uint8_t>(
|
std::span<const uint8_t>(header->content_metadata.title_thumbnail,
|
||||||
device->GetContainerHeader()->content_metadata.title_thumbnail,
|
header->content_metadata.title_thumbnail_size));
|
||||||
device->GetContainerHeader()->content_metadata.title_thumbnail_size));
|
|
||||||
return X_STATUS_SUCCESS;
|
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);
|
vfs::VirtualFileSystem::ExtractContentHeader(device.get(), header_path);
|
||||||
|
|
||||||
X_STATUS error_code = vfs::VirtualFileSystem::ExtractContentFiles(
|
X_STATUS error_code = vfs::VirtualFileSystem::ExtractContentFiles(
|
||||||
|
|||||||
@@ -108,11 +108,32 @@ bool XContentContainerDevice::Initialize() {
|
|||||||
return Read() == Result::kSuccess;
|
return Read() == Result::kSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
XContentContainerHeader* XContentContainerDevice::ReadContainerHeader(
|
std::unique_ptr<XContentContainerHeader>
|
||||||
FILE* host_file) {
|
XContentContainerDevice::ReadContainerHeader(
|
||||||
XContentContainerHeader* header = new XContentContainerHeader();
|
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<XContentContainerHeader>
|
||||||
|
XContentContainerDevice::ReadContainerHeader(FILE* host_file) {
|
||||||
|
std::unique_ptr<XContentContainerHeader> header =
|
||||||
|
std::make_unique<XContentContainerHeader>();
|
||||||
|
|
||||||
// Read header & check signature
|
// 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 nullptr;
|
||||||
}
|
}
|
||||||
return header;
|
return header;
|
||||||
@@ -173,18 +194,17 @@ XContentContainerDevice::Result XContentContainerDevice::ReadHeaderAndVerify(
|
|||||||
return Result::kTooSmall;
|
return Result::kTooSmall;
|
||||||
}
|
}
|
||||||
|
|
||||||
const XContentContainerHeader* header = ReadContainerHeader(header_file);
|
auto header = ReadContainerHeader(header_file);
|
||||||
if (header == nullptr) {
|
if (header == nullptr) {
|
||||||
return Result::kReadError;
|
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.
|
// Unexpected format.
|
||||||
return Result::kFileMismatch;
|
return Result::kFileMismatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
header_ = std::move(header);
|
||||||
return Result::kSuccess;
|
return Result::kSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,12 @@ class XContentContainerDevice : public Device {
|
|||||||
const std::string_view mount_path,
|
const std::string_view mount_path,
|
||||||
const std::filesystem::path& host_path);
|
const std::filesystem::path& host_path);
|
||||||
|
|
||||||
|
static std::unique_ptr<XContentContainerHeader> ReadContainerHeader(
|
||||||
|
const std::filesystem::path& file_path);
|
||||||
|
|
||||||
|
static std::unique_ptr<XContentContainerHeader> ReadContainerHeader(
|
||||||
|
FILE* host_file);
|
||||||
|
|
||||||
~XContentContainerDevice() override;
|
~XContentContainerDevice() override;
|
||||||
|
|
||||||
bool Initialize() override;
|
bool Initialize() override;
|
||||||
@@ -117,9 +123,6 @@ class XContentContainerDevice : public Device {
|
|||||||
size_t files_total_size_;
|
size_t files_total_size_;
|
||||||
std::unique_ptr<Entry> root_entry_;
|
std::unique_ptr<Entry> root_entry_;
|
||||||
std::unique_ptr<XContentContainerHeader> header_;
|
std::unique_ptr<XContentContainerHeader> header_;
|
||||||
|
|
||||||
private:
|
|
||||||
static XContentContainerHeader* ReadContainerHeader(FILE* host_file);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace vfs
|
} // namespace vfs
|
||||||
|
|||||||
Reference in New Issue
Block a user