Virtual Filesystem 2: Electric Boogaloo (#676)

* Virtual Filesystem

* Fix delete bug and documentate

* Review fixes + other stuff

* Fix puyo regression
This commit is contained in:
Zach Hilman
2018-07-18 21:07:11 -04:00
committed by bunnei
parent 924c473bb3
commit 29aff8d5ab
54 changed files with 1936 additions and 1969 deletions

View File

@@ -4,11 +4,10 @@
#include <cinttypes>
#include "common/common_funcs.h"
#include "common/common_paths.h"
#include "common/file_util.h"
#include "common/logging/log.h"
#include "common/string_util.h"
#include "core/file_sys/romfs_factory.h"
#include "core/file_sys/content_archive.h"
#include "core/gdbstub/gdbstub.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/resource_limit.h"
@@ -47,55 +46,11 @@ static std::string FindRomFS(const std::string& directory) {
return filepath_romfs;
}
AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileUtil::IOFile&& file,
std::string filepath)
: AppLoader(std::move(file)), filepath(std::move(filepath)) {}
AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys::VirtualFile file)
: AppLoader(std::move(file)) {}
FileType AppLoader_DeconstructedRomDirectory::IdentifyType(FileUtil::IOFile& file,
const std::string& filepath) {
bool is_main_found{};
bool is_npdm_found{};
bool is_rtld_found{};
bool is_sdk_found{};
const auto callback = [&](unsigned* num_entries_out, const std::string& directory,
const std::string& virtual_name) -> bool {
// Skip directories
std::string physical_name = directory + virtual_name;
if (FileUtil::IsDirectory(physical_name)) {
return true;
}
// Verify filename
if (Common::ToLower(virtual_name) == "main") {
is_main_found = true;
} else if (Common::ToLower(virtual_name) == "main.npdm") {
is_npdm_found = true;
return true;
} else if (Common::ToLower(virtual_name) == "rtld") {
is_rtld_found = true;
} else if (Common::ToLower(virtual_name) == "sdk") {
is_sdk_found = true;
} else {
// Continue searching
return true;
}
// Verify file is an NSO
FileUtil::IOFile file(physical_name, "rb");
if (AppLoader_NSO::IdentifyType(file, physical_name) != FileType::NSO) {
return false;
}
// We are done if we've found and verified all required NSOs
return !(is_main_found && is_npdm_found && is_rtld_found && is_sdk_found);
};
// Search the directory recursively, looking for the required modules
const std::string directory = filepath.substr(0, filepath.find_last_of("/\\")) + DIR_SEP;
FileUtil::ForeachDirectoryEntry(nullptr, directory, callback);
if (is_main_found && is_npdm_found && is_rtld_found && is_sdk_found) {
FileType AppLoader_DeconstructedRomDirectory::IdentifyType(const FileSys::VirtualFile& file) {
if (FileSys::IsDirectoryExeFS(file->GetContainingDirectory())) {
return FileType::DeconstructedRomDirectory;
}
@@ -107,14 +62,13 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(
if (is_loaded) {
return ResultStatus::ErrorAlreadyLoaded;
}
if (!file.IsOpen()) {
return ResultStatus::Error;
}
const std::string directory = filepath.substr(0, filepath.find_last_of("/\\")) + DIR_SEP;
const std::string npdm_path = directory + DIR_SEP + "main.npdm";
const FileSys::VirtualDir dir = file->GetContainingDirectory();
const FileSys::VirtualFile npdm = dir->GetFile("main.npdm");
if (npdm == nullptr)
return ResultStatus::ErrorInvalidFormat;
ResultStatus result = metadata.Load(npdm_path);
ResultStatus result = metadata.Load(npdm);
if (result != ResultStatus::Success) {
return result;
}
@@ -129,9 +83,10 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(
VAddr next_load_addr{Memory::PROCESS_IMAGE_VADDR};
for (const auto& module : {"rtld", "main", "subsdk0", "subsdk1", "subsdk2", "subsdk3",
"subsdk4", "subsdk5", "subsdk6", "subsdk7", "sdk"}) {
const std::string path = directory + DIR_SEP + module;
const VAddr load_addr = next_load_addr;
next_load_addr = AppLoader_NSO::LoadModule(path, load_addr);
const FileSys::VirtualFile module_file = dir->GetFile(module);
if (module_file != nullptr)
next_load_addr = AppLoader_NSO::LoadModule(module_file, load_addr);
if (next_load_addr) {
LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", module, load_addr);
// Register module with GDBStub
@@ -150,10 +105,15 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(
metadata.GetMainThreadStackSize());
// Find the RomFS by searching for a ".romfs" file in this directory
filepath_romfs = FindRomFS(directory);
const auto& files = dir->GetFiles();
const auto romfs_iter =
std::find_if(files.begin(), files.end(), [](const FileSys::VirtualFile& file) {
return file->GetName().find(".romfs") != std::string::npos;
});
// Register the RomFS if a ".romfs" file was found
if (!filepath_romfs.empty()) {
if (romfs_iter != files.end() && *romfs_iter != nullptr) {
romfs = *romfs_iter;
Service::FileSystem::RegisterRomFS(std::make_unique<FileSys::RomFSFactory>(*this));
}
@@ -161,29 +121,10 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(
return ResultStatus::Success;
}
ResultStatus AppLoader_DeconstructedRomDirectory::ReadRomFS(
std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset, u64& size) {
if (filepath_romfs.empty()) {
LOG_DEBUG(Loader, "No RomFS available");
ResultStatus AppLoader_DeconstructedRomDirectory::ReadRomFS(FileSys::VirtualFile& dir) {
if (romfs == nullptr)
return ResultStatus::ErrorNotUsed;
}
// We reopen the file, to allow its position to be independent
romfs_file = std::make_shared<FileUtil::IOFile>(filepath_romfs, "rb");
if (!romfs_file->IsOpen()) {
return ResultStatus::Error;
}
offset = 0;
size = romfs_file->GetSize();
LOG_DEBUG(Loader, "RomFS offset: 0x{:016X}", offset);
LOG_DEBUG(Loader, "RomFS size: 0x{:016X}", size);
// Reset read pointer
file.Seek(0, SEEK_SET);
dir = romfs;
return ResultStatus::Success;
}