From 469d062a509bb6d7ea7bf97ec09249ecedb61f4e Mon Sep 17 00:00:00 2001 From: Gliniak Date: Sat, 20 Aug 2022 12:47:43 +0200 Subject: [PATCH] [Emulator] Updated "Install Content" function to match PR status --- src/xenia/emulator.cc | 81 ++-------------------------- src/xenia/vfs/vfs_dump.cc | 72 ++----------------------- src/xenia/vfs/virtual_file_system.cc | 75 ++++++++++++++++++++++++++ src/xenia/vfs/virtual_file_system.h | 1 + 4 files changed, 84 insertions(+), 145 deletions(-) diff --git a/src/xenia/emulator.cc b/src/xenia/emulator.cc index f4400fb25..5d010c0d0 100644 --- a/src/xenia/emulator.cc +++ b/src/xenia/emulator.cc @@ -368,90 +368,19 @@ X_STATUS Emulator::InstallContentPackage(const std::filesystem::path& path) { std::filesystem::path installation_path = content_root() / fmt::format("{:08X}", device->title_id()) / - fmt::format("{:08X}", device->content_type()); + fmt::format("{:08X}", device->content_type()) / path.filename(); - if (std::filesystem::exists(installation_path / path.filename())) { - // TODO: Popup + if (std::filesystem::exists(installation_path)) { + // TODO(Gliniak): Popup // Do you want to overwrite already existing data? } else { std::error_code error_code; - std::filesystem::create_directories(installation_path / path.filename(), - error_code); + std::filesystem::create_directories(installation_path, error_code); if (error_code) { return error_code.value(); } } - - // Run through all the files, breadth-first style. - std::queue queue; - auto root = device->ResolvePath("/"); - queue.push(root); - - // Allocate a buffer when needed. - size_t buffer_size = 0; - uint8_t* buffer = nullptr; - - while (!queue.empty()) { - auto entry = queue.front(); - queue.pop(); - for (auto& entry : entry->children()) { - queue.push(entry.get()); - } - - auto dest_name = - installation_path / path.filename() / xe::to_path(entry->path()); - if (entry->attributes() & vfs::kFileAttributeDirectory) { - std::error_code error_code; - std::filesystem::create_directories(dest_name, error_code); - if (error_code) { - return error_code.value(); - } - continue; - } - - vfs::File* in_file = nullptr; - if (entry->Open(vfs::FileAccess::kFileReadData, &in_file) != - X_STATUS_SUCCESS) { - continue; - } - - auto file = xe::filesystem::OpenFile(dest_name, "wb"); - if (!file) { - in_file->Destroy(); - continue; - } - - if (entry->can_map()) { - auto map = entry->OpenMapped(xe::MappedMemory::Mode::kRead); - fwrite(map->data(), map->size(), 1, file); - map->Close(); - } else { - // Can't map the file into memory. Read it into a temporary buffer. - if (!buffer || entry->size() > buffer_size) { - // Resize the buffer. - if (buffer) { - delete[] buffer; - } - - // Allocate a buffer rounded up to the nearest 512MB. - buffer_size = xe::round_up(entry->size(), 512_MiB); - buffer = new uint8_t[buffer_size]; - } - - size_t bytes_read = 0; - in_file->ReadSync(buffer, entry->size(), 0, &bytes_read); - fwrite(buffer, bytes_read, 1, file); - } - - fclose(file); - in_file->Destroy(); - } - - if (buffer) { - delete[] buffer; - } - - return X_STATUS_SUCCESS; + return vfs::VirtualFileSystem::ExtractFiles(device.get(), installation_path); } void Emulator::Pause() { diff --git a/src/xenia/vfs/vfs_dump.cc b/src/xenia/vfs/vfs_dump.cc index f2416b59a..20994256d 100644 --- a/src/xenia/vfs/vfs_dump.cc +++ b/src/xenia/vfs/vfs_dump.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2021 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -19,12 +19,11 @@ #include "xenia/vfs/devices/stfs_container_device.h" #include "xenia/vfs/file.h" +#include "xenia/vfs/virtual_file_system.h" namespace xe { namespace vfs { -using namespace xe::literals; - DEFINE_transient_path(source, "", "Specifies the file to dump from.", "General"); @@ -46,72 +45,7 @@ int vfs_dump_main(const std::vector& args) { XELOGE("Failed to initialize device"); return 1; } - - // Run through all the files, breadth-first style. - std::queue queue; - auto root = device->ResolvePath("/"); - queue.push(root); - - // Allocate a buffer when needed. - size_t buffer_size = 0; - uint8_t* buffer = nullptr; - - while (!queue.empty()) { - auto entry = queue.front(); - queue.pop(); - for (auto& entry : entry->children()) { - queue.push(entry.get()); - } - - XELOGI("{}", entry->path()); - auto dest_name = base_path / xe::to_path(entry->path()); - if (entry->attributes() & kFileAttributeDirectory) { - std::filesystem::create_directories(dest_name); - continue; - } - - vfs::File* in_file = nullptr; - if (entry->Open(FileAccess::kFileReadData, &in_file) != X_STATUS_SUCCESS) { - continue; - } - - auto file = xe::filesystem::OpenFile(dest_name, "wb"); - if (!file) { - in_file->Destroy(); - continue; - } - - if (entry->can_map()) { - auto map = entry->OpenMapped(xe::MappedMemory::Mode::kRead); - fwrite(map->data(), map->size(), 1, file); - map->Close(); - } else { - // Can't map the file into memory. Read it into a temporary buffer. - if (!buffer || entry->size() > buffer_size) { - // Resize the buffer. - if (buffer) { - delete[] buffer; - } - - // Allocate a buffer rounded up to the nearest 512MB. - buffer_size = xe::round_up(entry->size(), 512_MiB); - buffer = new uint8_t[buffer_size]; - } - - size_t bytes_read = 0; - in_file->ReadSync(buffer, entry->size(), 0, &bytes_read); - fwrite(buffer, bytes_read, 1, file); - } - - fclose(file); - in_file->Destroy(); - } - - if (buffer) { - delete[] buffer; - } - - return 0; + return VirtualFileSystem::ExtractFiles(device.get(), base_path); } } // namespace vfs diff --git a/src/xenia/vfs/virtual_file_system.cc b/src/xenia/vfs/virtual_file_system.cc index 01f4761e6..7af2d3e6a 100644 --- a/src/xenia/vfs/virtual_file_system.cc +++ b/src/xenia/vfs/virtual_file_system.cc @@ -9,6 +9,7 @@ #include "xenia/vfs/virtual_file_system.h" +#include "xenia/base/literals.h" #include "xenia/base/logging.h" #include "xenia/base/string.h" #include "xenia/kernel/xfile.h" @@ -16,6 +17,8 @@ namespace xe { namespace vfs { +using namespace xe::literals; + VirtualFileSystem::VirtualFileSystem() {} VirtualFileSystem::~VirtualFileSystem() { @@ -307,5 +310,77 @@ X_STATUS VirtualFileSystem::OpenFile(Entry* root_entry, return result; } +X_STATUS VirtualFileSystem::ExtractFiles(Device* device, + std::filesystem::path base_path) { + // Run through all the files, breadth-first style. + std::queue queue; + auto root = device->ResolvePath("/"); + queue.push(root); + + // Allocate a buffer when needed. + size_t buffer_size = 0; + uint8_t* buffer = nullptr; + + while (!queue.empty()) { + auto entry = queue.front(); + queue.pop(); + for (auto& entry : entry->children()) { + queue.push(entry.get()); + } + + XELOGI("Extracting file: {}", entry->path()); + auto dest_name = base_path / xe::to_path(entry->path()); + if (entry->attributes() & kFileAttributeDirectory) { + std::error_code error_code; + std::filesystem::create_directories(dest_name, error_code); + if (error_code) { + return error_code.value(); + } + continue; + } + + vfs::File* in_file = nullptr; + if (entry->Open(FileAccess::kFileReadData, &in_file) != X_STATUS_SUCCESS) { + continue; + } + + auto file = xe::filesystem::OpenFile(dest_name, "wb"); + if (!file) { + in_file->Destroy(); + continue; + } + + if (entry->can_map()) { + auto map = entry->OpenMapped(xe::MappedMemory::Mode::kRead); + fwrite(map->data(), map->size(), 1, file); + map->Close(); + } else { + // Can't map the file into memory. Read it into a temporary buffer. + if (!buffer || entry->size() > buffer_size) { + // Resize the buffer. + if (buffer) { + delete[] buffer; + } + + // Allocate a buffer rounded up to the nearest 512MB. + buffer_size = xe::round_up(entry->size(), 512_MiB); + buffer = new uint8_t[buffer_size]; + } + + size_t bytes_read = 0; + in_file->ReadSync(buffer, entry->size(), 0, &bytes_read); + fwrite(buffer, bytes_read, 1, file); + } + + fclose(file); + in_file->Destroy(); + } + + if (buffer) { + delete[] buffer; + } + + return X_STATUS_SUCCESS; +} } // namespace vfs } // namespace xe diff --git a/src/xenia/vfs/virtual_file_system.h b/src/xenia/vfs/virtual_file_system.h index 49e9083dc..47ca5d947 100644 --- a/src/xenia/vfs/virtual_file_system.h +++ b/src/xenia/vfs/virtual_file_system.h @@ -47,6 +47,7 @@ class VirtualFileSystem { bool is_non_directory, File** out_file, FileAction* out_action); + static X_STATUS ExtractFiles(Device* device, std::filesystem::path base_path); private: xe::global_critical_region global_critical_region_; std::vector> devices_;