diff --git a/stratosphere/fs_mitm/source/fsmitm_layeredrom.cpp b/stratosphere/fs_mitm/source/fsmitm_layeredrom.cpp index 68a259a06..c8033a831 100644 --- a/stratosphere/fs_mitm/source/fsmitm_layeredrom.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_layeredrom.cpp @@ -27,10 +27,6 @@ LayeredRomFS::LayeredRomFS(std::shared_ptr s_r, std::shared build_ctx.Build(this->p_source_infos.get()); } -LayeredRomFS::~LayeredRomFS() { - /* ... */ -} - Result LayeredRomFS::Read(void *buffer, size_t size, u64 offset) { /* Validate size. */ @@ -60,7 +56,6 @@ Result LayeredRomFS::Read(void *buffer, size_t size, u64 offset) { } } - Result rc; size_t read_so_far = 0; while (read_so_far < size) { RomFSSourceInfo *cur_source = &((*this->p_source_infos)[cur_source_ind]); @@ -69,47 +64,38 @@ Result LayeredRomFS::Read(void *buffer, size_t size, u64 offset) { if (cur_read_size > cur_source->size - (offset - cur_source->virtual_offset)) { cur_read_size = cur_source->size - (offset - cur_source->virtual_offset); } - switch (cur_source->type) { - case RomFSDataSource_LooseFile: - { - FsFile file; - if (R_FAILED((rc = Utils::OpenRomFSSdFile(this->title_id, cur_source->loose_source_info.path, FS_OPEN_READ, &file)))) { - fatalSimple(rc); - } - size_t out_read; - if (R_FAILED((rc = fsFileRead(&file, (offset - cur_source->virtual_offset), (void *)((uintptr_t)buffer + read_so_far), cur_read_size, &out_read)))) { - fatalSimple(rc); - } - if (out_read != cur_read_size) { - Reboot(); - } - fsFileClose(&file); + auto source_info_visitor = [&](auto& info) -> Result { + Result rc = 0; + if constexpr (std::is_same_v) { + FsFile file; + if (R_FAILED((rc = Utils::OpenRomFSSdFile(this->title_id, info.path, FS_OPEN_READ, &file)))) { + fatalSimple(rc); } - break; - case RomFSDataSource_Memory: - { - memcpy((void *)((uintptr_t)buffer + read_so_far), cur_source->memory_source_info.data + (offset - cur_source->virtual_offset), cur_read_size); + size_t out_read; + if (R_FAILED((rc = fsFileRead(&file, (offset - cur_source->virtual_offset), (void *)((uintptr_t)buffer + read_so_far), cur_read_size, &out_read)))) { + fatalSimple(rc); } - break; - case RomFSDataSource_BaseRomFS: - { - if (R_FAILED((rc = this->storage_romfs->Read((void *)((uintptr_t)buffer + read_so_far), cur_read_size, cur_source->base_source_info.offset + (offset - cur_source->virtual_offset))))) { - /* TODO: Can this ever happen? */ - /* fatalSimple(rc); */ - return rc; - } + if (out_read != cur_read_size) { + Reboot(); } - break; - case RomFSDataSource_FileRomFS: - { - if (R_FAILED((rc = this->file_romfs->Read((void *)((uintptr_t)buffer + read_so_far), cur_read_size, cur_source->base_source_info.offset + (offset - cur_source->virtual_offset))))) { - fatalSimple(rc); - } + fsFileClose(&file); + } else if constexpr (std::is_same_v) { + memcpy((void *)((uintptr_t)buffer + read_so_far), info.data + (offset - cur_source->virtual_offset), cur_read_size); + } else if constexpr (std::is_same_v) { + if (R_FAILED((rc = this->storage_romfs->Read((void *)((uintptr_t)buffer + read_so_far), cur_read_size, info.offset + (offset - cur_source->virtual_offset))))) { + /* TODO: Can this ever happen? */ + /* fatalSimple(rc); */ + return rc; } - break; - default: - fatalSimple(0xF601); - } + } else if constexpr (std::is_same_v) { + if (R_FAILED((rc = this->file_romfs->Read((void *)((uintptr_t)buffer + read_so_far), cur_read_size, info.offset + (offset - cur_source->virtual_offset))))) { + fatalSimple(rc); + } + } + return rc; + }; + Result rc = std::visit(source_info_visitor, cur_source->info); + read_so_far += cur_read_size; } else { /* Handle padding explicitly. */ @@ -132,4 +118,4 @@ Result LayeredRomFS::OperateRange(u32 operation_type, u64 offset, u64 size, FsRa *out_range_info = {0}; } return 0; -} \ No newline at end of file +} diff --git a/stratosphere/fs_mitm/source/fsmitm_layeredrom.hpp b/stratosphere/fs_mitm/source/fsmitm_layeredrom.hpp index a27f7c211..fea9ccecd 100644 --- a/stratosphere/fs_mitm/source/fsmitm_layeredrom.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_layeredrom.hpp @@ -23,7 +23,7 @@ class LayeredRomFS : public IROStorage { public: LayeredRomFS(std::shared_ptr s_r, std::shared_ptr f_r, u64 tid); - virtual ~LayeredRomFS(); + virtual ~LayeredRomFS() = default; Result Read(void *buffer, size_t size, u64 offset) override; Result GetSize(u64 *out_size) override; diff --git a/stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp b/stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp index a9beabc76..13a255035 100644 --- a/stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp @@ -359,13 +359,13 @@ void RomFSBuildContext::Build(std::vector *out_infos) { case RomFSDataSource_BaseRomFS: case RomFSDataSource_FileRomFS: /* Try to compact, if possible. */ - if (out_infos->back().type == cur_file->source) { + if (out_infos->back().GetType() == cur_file->source) { out_infos->back().size = cur_file->offset + ROMFS_FILEPARTITION_OFS + cur_file->size - out_infos->back().virtual_offset; } else { out_infos->push_back(RomFSSourceInfo(cur_file->offset + ROMFS_FILEPARTITION_OFS, cur_file->size, cur_file->orig_offset + ROMFS_FILEPARTITION_OFS, cur_file->source)); } break; - case RomFSDataSource_LooseFile: + case RomFSDataSource_LooseFile: { char *path = new char[cur_file->path_len + 1]; strcpy(path, cur_file->path); @@ -417,4 +417,4 @@ void RomFSBuildContext::Build(std::vector *out_infos) { header->file_table_ofs = header->file_hash_table_ofs + header->file_hash_table_size; out_infos->push_back(RomFSSourceInfo(header->dir_hash_table_ofs, this->dir_hash_table_size + this->dir_table_size + this->file_hash_table_size + this->file_table_size, metadata, RomFSDataSource_Memory)); -} \ No newline at end of file +} diff --git a/stratosphere/fs_mitm/source/fsmitm_romfsbuild.hpp b/stratosphere/fs_mitm/source/fsmitm_romfsbuild.hpp index 004da24ed..5192578b4 100644 --- a/stratosphere/fs_mitm/source/fsmitm_romfsbuild.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_romfsbuild.hpp @@ -1,5 +1,6 @@ #pragma once #include +#include #include "fsmitm_romstorage.hpp" @@ -30,66 +31,92 @@ struct RomFSMemorySourceInfo { const u8 *data; }; -struct RomFSSourceInfo { +class RomFSSourceInfo { + using InfoVariant = std::variant; + + static InfoVariant MakeInfoVariantFromOffset(u64 offset, RomFSDataSource t) { + switch(t) { + case RomFSDataSource_BaseRomFS: + return RomFSBaseSourceInfo { offset }; + + case RomFSDataSource_FileRomFS: + return RomFSFileSourceInfo { offset }; + + default: + fatalSimple(0xF601); + } + } + + static InfoVariant MakeInfoVariantFromPointer(const void *arg, RomFSDataSource t) { + switch(t) { + case RomFSDataSource_LooseFile: + return RomFSLooseSourceInfo { (decltype(RomFSLooseSourceInfo::path))arg }; + + case RomFSDataSource_Memory: + return RomFSMemorySourceInfo { (decltype(RomFSMemorySourceInfo::data))arg }; + + default: + fatalSimple(0xF601); + } + } + + struct InfoCleanupHelper { + void operator()(RomFSBaseSourceInfo& info) { + } + + void operator()(RomFSFileSourceInfo& info) { + } + + void operator()(RomFSLooseSourceInfo& info) { + delete info.path; + } + + void operator()(RomFSMemorySourceInfo& info) { + delete info.data; + } + }; + + struct GetTypeHelper { + RomFSDataSource operator()(const RomFSBaseSourceInfo& info) const { + return RomFSDataSource_BaseRomFS; + } + + RomFSDataSource operator()(const RomFSFileSourceInfo& info) const { + return RomFSDataSource_FileRomFS; + } + + RomFSDataSource operator()(const RomFSLooseSourceInfo& info) const { + return RomFSDataSource_LooseFile; + } + + RomFSDataSource operator()(const RomFSMemorySourceInfo& info) const { + return RomFSDataSource_Memory; + } + }; + +public: u64 virtual_offset; u64 size; - union { - RomFSBaseSourceInfo base_source_info; - RomFSFileSourceInfo file_source_info; - RomFSLooseSourceInfo loose_source_info; - RomFSMemorySourceInfo memory_source_info; - }; - RomFSDataSource type; - - RomFSSourceInfo(u64 v_o, u64 s, u64 offset, RomFSDataSource t) : virtual_offset(v_o), size(s), type(t) { - switch (this->type) { - case RomFSDataSource_BaseRomFS: - this->base_source_info.offset = offset; - break; - case RomFSDataSource_FileRomFS: - this->file_source_info.offset = offset; - break; - case RomFSDataSource_LooseFile: - case RomFSDataSource_Memory: - default: - fatalSimple(0xF601); - } + + InfoVariant info; + + RomFSSourceInfo(u64 v_o, u64 s, u64 offset, RomFSDataSource t) : virtual_offset(v_o), size(s), info(MakeInfoVariantFromOffset(offset, t)) { } - - RomFSSourceInfo(u64 v_o, u64 s, const void *arg, RomFSDataSource t) : virtual_offset(v_o), size(s), type(t) { - switch (this->type) { - case RomFSDataSource_LooseFile: - this->loose_source_info.path = (decltype(this->loose_source_info.path))arg; - break; - case RomFSDataSource_Memory: - this->memory_source_info.data = (decltype(this->memory_source_info.data))arg; - break; - case RomFSDataSource_BaseRomFS: - case RomFSDataSource_FileRomFS: - default: - fatalSimple(0xF601); - } + + RomFSSourceInfo(u64 v_o, u64 s, const void *arg, RomFSDataSource t) : virtual_offset(v_o), size(s), info(MakeInfoVariantFromPointer(arg, t)) { } - + void Cleanup() { - switch (this->type) { - case RomFSDataSource_BaseRomFS: - case RomFSDataSource_FileRomFS: - break; - case RomFSDataSource_LooseFile: - delete this->loose_source_info.path; - break; - case RomFSDataSource_Memory: - delete this->memory_source_info.data; - break; - default: - fatalSimple(0xF601); - } + std::visit(InfoCleanupHelper{}, info); } - + static bool Compare(RomFSSourceInfo *a, RomFSSourceInfo *b) { return (a->virtual_offset < b->virtual_offset); } + + RomFSDataSource GetType() const { + return std::visit(GetTypeHelper{}, info); + } }; /* Types for building a RomFS. */