From fd1c3aa14ebda34687b7a4e4e58e1836f7394df8 Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Sun, 12 Jul 2020 04:31:01 -0400 Subject: [PATCH] fs: Fix RomFS building when zero byte files are present When zero byte files are present, the key (offset) for that file is identical to the file right after. A std::map isn't able to fit key-value pairs with identical keys (offsets), therefore, the solution is to use std::multimap which permits multiple entries with the same key. This most prominently fixes Pokemon Sword and Shield weather with any RomFS mod applied. --- src/core/file_sys/fsmitm_romfsbuild.cpp | 4 ++-- src/core/file_sys/fsmitm_romfsbuild.h | 2 +- src/core/file_sys/vfs_concat.cpp | 8 ++++---- src/core/file_sys/vfs_concat.h | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/core/file_sys/fsmitm_romfsbuild.cpp b/src/core/file_sys/fsmitm_romfsbuild.cpp index d126ae8dd0..2aff2708a5 100644 --- a/src/core/file_sys/fsmitm_romfsbuild.cpp +++ b/src/core/file_sys/fsmitm_romfsbuild.cpp @@ -240,7 +240,7 @@ RomFSBuildContext::RomFSBuildContext(VirtualDir base_, VirtualDir ext_) RomFSBuildContext::~RomFSBuildContext() = default; -std::map RomFSBuildContext::Build() { +std::multimap RomFSBuildContext::Build() { const u64 dir_hash_table_entry_count = romfs_get_hash_table_count(num_dirs); const u64 file_hash_table_entry_count = romfs_get_hash_table_count(num_files); dir_hash_table_size = 4 * dir_hash_table_entry_count; @@ -294,7 +294,7 @@ std::map RomFSBuildContext::Build() { cur_dir->parent->child = cur_dir; } - std::map out; + std::multimap out; // Populate file tables. for (const auto& it : files) { diff --git a/src/core/file_sys/fsmitm_romfsbuild.h b/src/core/file_sys/fsmitm_romfsbuild.h index a625021931..049de180b5 100644 --- a/src/core/file_sys/fsmitm_romfsbuild.h +++ b/src/core/file_sys/fsmitm_romfsbuild.h @@ -43,7 +43,7 @@ public: ~RomFSBuildContext(); // This finalizes the context. - std::map Build(); + std::multimap Build(); private: VirtualDir base; diff --git a/src/core/file_sys/vfs_concat.cpp b/src/core/file_sys/vfs_concat.cpp index 16d801c0c9..e0ff701749 100644 --- a/src/core/file_sys/vfs_concat.cpp +++ b/src/core/file_sys/vfs_concat.cpp @@ -11,7 +11,7 @@ namespace FileSys { -static bool VerifyConcatenationMapContinuity(const std::map& map) { +static bool VerifyConcatenationMapContinuity(const std::multimap& map) { const auto last_valid = --map.end(); for (auto iter = map.begin(); iter != last_valid;) { const auto old = iter++; @@ -27,12 +27,12 @@ ConcatenatedVfsFile::ConcatenatedVfsFile(std::vector files_, std::s : name(std::move(name)) { std::size_t next_offset = 0; for (const auto& file : files_) { - files[next_offset] = file; + files.emplace(next_offset, file); next_offset += file->GetSize(); } } -ConcatenatedVfsFile::ConcatenatedVfsFile(std::map files_, std::string name) +ConcatenatedVfsFile::ConcatenatedVfsFile(std::multimap files_, std::string name) : files(std::move(files_)), name(std::move(name)) { ASSERT(VerifyConcatenationMapContinuity(files)); } @@ -50,7 +50,7 @@ VirtualFile ConcatenatedVfsFile::MakeConcatenatedFile(std::vector f } VirtualFile ConcatenatedVfsFile::MakeConcatenatedFile(u8 filler_byte, - std::map files, + std::multimap files, std::string name) { if (files.empty()) return nullptr; diff --git a/src/core/file_sys/vfs_concat.h b/src/core/file_sys/vfs_concat.h index c90f9d5d1d..7a26343c0d 100644 --- a/src/core/file_sys/vfs_concat.h +++ b/src/core/file_sys/vfs_concat.h @@ -15,7 +15,7 @@ namespace FileSys { // read-only. class ConcatenatedVfsFile : public VfsFile { ConcatenatedVfsFile(std::vector files, std::string name); - ConcatenatedVfsFile(std::map files, std::string name); + ConcatenatedVfsFile(std::multimap files, std::string name); public: ~ConcatenatedVfsFile() override; @@ -25,7 +25,7 @@ public: /// Convenience function that turns a map of offsets to files into a concatenated file, filling /// gaps with a given filler byte. - static VirtualFile MakeConcatenatedFile(u8 filler_byte, std::map files, + static VirtualFile MakeConcatenatedFile(u8 filler_byte, std::multimap files, std::string name); std::string GetName() const override; @@ -40,7 +40,7 @@ public: private: // Maps starting offset to file -- more efficient. - std::map files; + std::multimap files; std::string name; };