diff --git a/src/core/core.cpp b/src/core/core.cpp
index 50f0a42fb1c881a292e9b2b9705acee8b2fbc85d..7666354dc7e89c3ffedfba1abcc933980826ed34 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -64,7 +64,7 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
         if (concat.empty())
             return nullptr;
 
-        return FileSys::ConcatenateFiles(concat, dir->GetName());
+        return FileSys::ConcatenatedVfsFile::MakeConcatenatedFile(concat, dir->GetName());
     }
 
     return vfs->OpenFile(path, FileSys::Mode::Read);
diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp
index af3f9a78fe91349d538d5fb6d81504692593e6a9..561ad67a70f42f7eb2824ef8400afd6b1cc77761 100644
--- a/src/core/file_sys/patch_manager.cpp
+++ b/src/core/file_sys/patch_manager.cpp
@@ -90,10 +90,9 @@ static void ApplyLayeredFS(VirtualFile& romfs, u64 title_id, ContentRecordType t
 
             layers.push_back(std::move(extracted));
 
-            const auto layered = LayerDirectories(layers);
-
+            auto layered = LayeredVfsDirectory::MakeLayeredDirectory(std::move(layers));
             if (layered != nullptr) {
-                auto packed = CreateRomFS(layered);
+                auto packed = CreateRomFS(std::move(layered));
 
                 if (packed != nullptr) {
                     LOG_INFO(Loader, "    RomFS: LayeredFS patches applied successfully");
diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp
index 653ef2e7b95c1c514bf1fe857377d7d8cc4a78bb..e9b040689436bb8bdbf613ef38811b43d7381bb3 100644
--- a/src/core/file_sys/registered_cache.cpp
+++ b/src/core/file_sys/registered_cache.cpp
@@ -125,7 +125,7 @@ VirtualFile RegisteredCache::OpenFileOrDirectoryConcat(const VirtualDir& dir,
             if (concat.empty())
                 return nullptr;
 
-            file = FileSys::ConcatenateFiles(concat, concat.front()->GetName());
+            file = ConcatenatedVfsFile::MakeConcatenatedFile(concat, concat.front()->GetName());
         }
 
         return file;
diff --git a/src/core/file_sys/romfs.cpp b/src/core/file_sys/romfs.cpp
index 7804ef56d1242075e8d3c3019e2f9448234ab532..5910f7046b99d8bf35a6f9bfe3e72dd453118193 100644
--- a/src/core/file_sys/romfs.cpp
+++ b/src/core/file_sys/romfs.cpp
@@ -134,7 +134,7 @@ VirtualFile CreateRomFS(VirtualDir dir) {
         return nullptr;
 
     RomFSBuildContext ctx{dir};
-    return ConcatenateFiles(0, ctx.Build(), dir->GetName());
+    return ConcatenatedVfsFile::MakeConcatenatedFile(0, ctx.Build(), dir->GetName());
 }
 
 } // namespace FileSys
diff --git a/src/core/file_sys/vfs_concat.cpp b/src/core/file_sys/vfs_concat.cpp
index 8a0df508e8d704e7de20b0e5f8e15d71d767cb11..16d801c0c91a6f3b50605dbb27ce087af80e9c0b 100644
--- a/src/core/file_sys/vfs_concat.cpp
+++ b/src/core/file_sys/vfs_concat.cpp
@@ -39,6 +39,41 @@ ConcatenatedVfsFile::ConcatenatedVfsFile(std::map<u64, VirtualFile> files_, std:
 
 ConcatenatedVfsFile::~ConcatenatedVfsFile() = default;
 
+VirtualFile ConcatenatedVfsFile::MakeConcatenatedFile(std::vector<VirtualFile> files,
+                                                      std::string name) {
+    if (files.empty())
+        return nullptr;
+    if (files.size() == 1)
+        return files[0];
+
+    return std::shared_ptr<VfsFile>(new ConcatenatedVfsFile(std::move(files), std::move(name)));
+}
+
+VirtualFile ConcatenatedVfsFile::MakeConcatenatedFile(u8 filler_byte,
+                                                      std::map<u64, VirtualFile> files,
+                                                      std::string name) {
+    if (files.empty())
+        return nullptr;
+    if (files.size() == 1)
+        return files.begin()->second;
+
+    const auto last_valid = --files.end();
+    for (auto iter = files.begin(); iter != last_valid;) {
+        const auto old = iter++;
+        if (old->first + old->second->GetSize() != iter->first) {
+            files.emplace(old->first + old->second->GetSize(),
+                          std::make_shared<StaticVfsFile>(filler_byte, iter->first - old->first -
+                                                                           old->second->GetSize()));
+        }
+    }
+
+    // Ensure the map starts at offset 0 (start of file), otherwise pad to fill.
+    if (files.begin()->first != 0)
+        files.emplace(0, std::make_shared<StaticVfsFile>(filler_byte, files.begin()->first));
+
+    return std::shared_ptr<VfsFile>(new ConcatenatedVfsFile(std::move(files), std::move(name)));
+}
+
 std::string ConcatenatedVfsFile::GetName() const {
     if (files.empty())
         return "";
@@ -101,36 +136,4 @@ bool ConcatenatedVfsFile::Rename(std::string_view name) {
     return false;
 }
 
-VirtualFile ConcatenateFiles(std::vector<VirtualFile> files, std::string name) {
-    if (files.empty())
-        return nullptr;
-    if (files.size() == 1)
-        return files[0];
-
-    return std::shared_ptr<VfsFile>(new ConcatenatedVfsFile(std::move(files), std::move(name)));
-}
-
-VirtualFile ConcatenateFiles(u8 filler_byte, std::map<u64, VirtualFile> files, std::string name) {
-    if (files.empty())
-        return nullptr;
-    if (files.size() == 1)
-        return files.begin()->second;
-
-    const auto last_valid = --files.end();
-    for (auto iter = files.begin(); iter != last_valid;) {
-        const auto old = iter++;
-        if (old->first + old->second->GetSize() != iter->first) {
-            files.emplace(old->first + old->second->GetSize(),
-                          std::make_shared<StaticVfsFile>(filler_byte, iter->first - old->first -
-                                                                           old->second->GetSize()));
-        }
-    }
-
-    // Ensure the map starts at offset 0 (start of file), otherwise pad to fill.
-    if (files.begin()->first != 0)
-        files.emplace(0, std::make_shared<StaticVfsFile>(filler_byte, files.begin()->first));
-
-    return std::shared_ptr<VfsFile>(new ConcatenatedVfsFile(std::move(files), std::move(name)));
-}
-
 } // namespace FileSys
diff --git a/src/core/file_sys/vfs_concat.h b/src/core/file_sys/vfs_concat.h
index 17fa40adee20e4eb4f0c0a3e716a9a7fc9f52496..c90f9d5d1d8cc5d6999becc203dc18471684dbc9 100644
--- a/src/core/file_sys/vfs_concat.h
+++ b/src/core/file_sys/vfs_concat.h
@@ -14,16 +14,20 @@ namespace FileSys {
 // Class that wraps multiple vfs files and concatenates them, making reads seamless. Currently
 // read-only.
 class ConcatenatedVfsFile : public VfsFile {
-    friend VirtualFile ConcatenateFiles(std::vector<VirtualFile> files, std::string name);
-    friend VirtualFile ConcatenateFiles(u8 filler_byte, std::map<u64, VirtualFile> files,
-                                        std::string name);
-
     ConcatenatedVfsFile(std::vector<VirtualFile> files, std::string name);
     ConcatenatedVfsFile(std::map<u64, VirtualFile> files, std::string name);
 
 public:
     ~ConcatenatedVfsFile() override;
 
+    /// Wrapper function to allow for more efficient handling of files.size() == 0, 1 cases.
+    static VirtualFile MakeConcatenatedFile(std::vector<VirtualFile> files, std::string name);
+
+    /// 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<u64, VirtualFile> files,
+                                            std::string name);
+
     std::string GetName() const override;
     std::size_t GetSize() const override;
     bool Resize(std::size_t new_size) override;
@@ -40,11 +44,4 @@ private:
     std::string name;
 };
 
-// Wrapper function to allow for more efficient handling of files.size() == 0, 1 cases.
-VirtualFile ConcatenateFiles(std::vector<VirtualFile> files, std::string name);
-
-// Convenience function that turns a map of offsets to files into a concatenated file, filling gaps
-// with a given filler byte.
-VirtualFile ConcatenateFiles(u8 filler_byte, std::map<u64, VirtualFile> files, std::string name);
-
 } // namespace FileSys
diff --git a/src/core/file_sys/vfs_layered.cpp b/src/core/file_sys/vfs_layered.cpp
index 45563d7ae325e4355ee9030e3f168226c6c368ed..bfee017256d47fcf4dcd92cad0ca653f4d4a25f6 100644
--- a/src/core/file_sys/vfs_layered.cpp
+++ b/src/core/file_sys/vfs_layered.cpp
@@ -8,7 +8,13 @@
 
 namespace FileSys {
 
-VirtualDir LayerDirectories(std::vector<VirtualDir> dirs, std::string name) {
+LayeredVfsDirectory::LayeredVfsDirectory(std::vector<VirtualDir> dirs, std::string name)
+    : dirs(std::move(dirs)), name(std::move(name)) {}
+
+LayeredVfsDirectory::~LayeredVfsDirectory() = default;
+
+VirtualDir LayeredVfsDirectory::MakeLayeredDirectory(std::vector<VirtualDir> dirs,
+                                                     std::string name) {
     if (dirs.empty())
         return nullptr;
     if (dirs.size() == 1)
@@ -17,11 +23,6 @@ VirtualDir LayerDirectories(std::vector<VirtualDir> dirs, std::string name) {
     return std::shared_ptr<VfsDirectory>(new LayeredVfsDirectory(std::move(dirs), std::move(name)));
 }
 
-LayeredVfsDirectory::LayeredVfsDirectory(std::vector<VirtualDir> dirs, std::string name)
-    : dirs(std::move(dirs)), name(std::move(name)) {}
-
-LayeredVfsDirectory::~LayeredVfsDirectory() = default;
-
 std::shared_ptr<VfsFile> LayeredVfsDirectory::GetFileRelative(std::string_view path) const {
     for (const auto& layer : dirs) {
         const auto file = layer->GetFileRelative(path);
@@ -41,7 +42,7 @@ std::shared_ptr<VfsDirectory> LayeredVfsDirectory::GetDirectoryRelative(
             out.push_back(std::move(dir));
     }
 
-    return LayerDirectories(std::move(out));
+    return MakeLayeredDirectory(std::move(out));
 }
 
 std::shared_ptr<VfsFile> LayeredVfsDirectory::GetFile(std::string_view name) const {
diff --git a/src/core/file_sys/vfs_layered.h b/src/core/file_sys/vfs_layered.h
index 4f6e341abef016e5e678ea9e1a988e825ecaed02..d85310f57c83bf96d47a4a4d10a30bcfb53a0ed2 100644
--- a/src/core/file_sys/vfs_layered.h
+++ b/src/core/file_sys/vfs_layered.h
@@ -9,20 +9,18 @@
 
 namespace FileSys {
 
-// Wrapper function to allow for more efficient handling of dirs.size() == 0, 1 cases.
-VirtualDir LayerDirectories(std::vector<VirtualDir> dirs, std::string name = "");
-
 // Class that stacks multiple VfsDirectories on top of each other, attempting to read from the first
 // one and falling back to the one after. The highest priority directory (overwrites all others)
 // should be element 0 in the dirs vector.
 class LayeredVfsDirectory : public VfsDirectory {
-    friend VirtualDir LayerDirectories(std::vector<VirtualDir> dirs, std::string name);
-
     LayeredVfsDirectory(std::vector<VirtualDir> dirs, std::string name);
 
 public:
     ~LayeredVfsDirectory() override;
 
+    /// Wrapper function to allow for more efficient handling of dirs.size() == 0, 1 cases.
+    static VirtualDir MakeLayeredDirectory(std::vector<VirtualDir> dirs, std::string name = "");
+
     std::shared_ptr<VfsFile> GetFileRelative(std::string_view path) const override;
     std::shared_ptr<VfsDirectory> GetDirectoryRelative(std::string_view path) const override;
     std::shared_ptr<VfsFile> GetFile(std::string_view name) const override;