diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp
index f96e08212dd011e41b1e5e04fa865111949436de..de44ccebdc39ac06db75fbe908a0bef318047327 100644
--- a/src/core/arm/dynarmic/arm_dynarmic.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic.cpp
@@ -9,6 +9,7 @@
 #include "common/logging/log.h"
 #include "core/arm/dynarmic/arm_dynarmic.h"
 #include "core/core.h"
+#include "core/core_cpu.h"
 #include "core/core_timing.h"
 #include "core/hle/kernel/process.h"
 #include "core/hle/kernel/svc.h"
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 75c259068f597d1c8bf771d41a1bda67df196d07..2cfae18dfb679e0700466179cb33f852354afe84 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -2,24 +2,35 @@
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
+#include <array>
+#include <map>
 #include <memory>
+#include <thread>
 #include <utility>
+
 #include "common/logging/log.h"
 #include "common/string_util.h"
+#include "core/arm/exclusive_monitor.h"
 #include "core/core.h"
+#include "core/core_cpu.h"
 #include "core/core_timing.h"
 #include "core/gdbstub/gdbstub.h"
 #include "core/hle/kernel/client_port.h"
 #include "core/hle/kernel/kernel.h"
 #include "core/hle/kernel/process.h"
+#include "core/hle/kernel/scheduler.h"
 #include "core/hle/kernel/thread.h"
 #include "core/hle/service/service.h"
 #include "core/hle/service/sm/controller.h"
 #include "core/hle/service/sm/sm.h"
 #include "core/loader/loader.h"
+#include "core/perf_stats.h"
 #include "core/settings.h"
+#include "core/telemetry_session.h"
 #include "file_sys/vfs_concat.h"
 #include "file_sys/vfs_real.h"
+#include "video_core/debug_utils/debug_utils.h"
+#include "video_core/gpu.h"
 #include "video_core/renderer_base.h"
 #include "video_core/video_core.h"
 
@@ -258,7 +269,7 @@ struct System::Impl {
         }
     }
 
-    PerfStats::Results GetAndResetPerfStats() {
+    PerfStatsResults GetAndResetPerfStats() {
         return perf_stats.GetAndResetStats(CoreTiming::GetGlobalTimeUs());
     }
 
@@ -326,7 +337,7 @@ void System::PrepareReschedule() {
     CurrentCpuCore().PrepareReschedule();
 }
 
-PerfStats::Results System::GetAndResetPerfStats() {
+PerfStatsResults System::GetAndResetPerfStats() {
     return impl->GetAndResetPerfStats();
 }
 
@@ -433,11 +444,11 @@ std::shared_ptr<Tegra::DebugContext> System::GetGPUDebugContext() const {
     return impl->debug_context;
 }
 
-void System::SetFilesystem(FileSys::VirtualFilesystem vfs) {
+void System::SetFilesystem(std::shared_ptr<FileSys::VfsFilesystem> vfs) {
     impl->virtual_filesystem = std::move(vfs);
 }
 
-FileSys::VirtualFilesystem System::GetFilesystem() const {
+std::shared_ptr<FileSys::VfsFilesystem> System::GetFilesystem() const {
     return impl->virtual_filesystem;
 }
 
diff --git a/src/core/core.h b/src/core/core.h
index 984e8f94c151d407185ddbcd7521a72989fb1e76..eee1fecc1520b9067678f2809b00168f6854e338 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -4,41 +4,55 @@
 
 #pragma once
 
-#include <array>
-#include <map>
+#include <cstddef>
 #include <memory>
 #include <string>
-#include <thread>
+
 #include "common/common_types.h"
-#include "core/arm/exclusive_monitor.h"
-#include "core/core_cpu.h"
-#include "core/hle/kernel/kernel.h"
 #include "core/hle/kernel/object.h"
-#include "core/hle/kernel/scheduler.h"
-#include "core/loader/loader.h"
-#include "core/memory.h"
-#include "core/perf_stats.h"
-#include "core/telemetry_session.h"
-#include "file_sys/vfs_real.h"
-#include "hle/service/filesystem/filesystem.h"
-#include "video_core/debug_utils/debug_utils.h"
-#include "video_core/gpu.h"
 
 namespace Core::Frontend {
 class EmuWindow;
-}
+} // namespace Core::Frontend
+
+namespace FileSys {
+class VfsFilesystem;
+} // namespace FileSys
+
+namespace Kernel {
+class KernelCore;
+class Process;
+class Scheduler;
+} // namespace Kernel
+
+namespace Loader {
+class AppLoader;
+enum class ResultStatus : u16;
+} // namespace Loader
 
 namespace Service::SM {
 class ServiceManager;
-}
+} // namespace Service::SM
+
+namespace Tegra {
+class DebugContext;
+class GPU;
+} // namespace Tegra
 
 namespace VideoCore {
 class RendererBase;
-}
+} // namespace VideoCore
 
 namespace Core {
 
 class ARM_Interface;
+class Cpu;
+class ExclusiveMonitor;
+class FrameLimiter;
+class PerfStats;
+class TelemetrySession;
+
+struct PerfStatsResults;
 
 class System {
 public:
@@ -125,7 +139,7 @@ public:
     void PrepareReschedule();
 
     /// Gets and resets core performance statistics
-    PerfStats::Results GetAndResetPerfStats();
+    PerfStatsResults GetAndResetPerfStats();
 
     /// Gets an ARM interface to the CPU core that is currently running
     ARM_Interface& CurrentArmInterface();
@@ -197,9 +211,9 @@ public:
 
     std::shared_ptr<Tegra::DebugContext> GetGPUDebugContext() const;
 
-    void SetFilesystem(FileSys::VirtualFilesystem vfs);
+    void SetFilesystem(std::shared_ptr<FileSys::VfsFilesystem> vfs);
 
-    FileSys::VirtualFilesystem GetFilesystem() const;
+    std::shared_ptr<FileSys::VfsFilesystem> GetFilesystem() const;
 
 private:
     System();
diff --git a/src/core/file_sys/savedata_factory.cpp b/src/core/file_sys/savedata_factory.cpp
index 034d3a78f9d2c61d7da16b8dafaa098168efdf23..952bd74b30f44772ffdbad9d1421ee1bf165d140 100644
--- a/src/core/file_sys/savedata_factory.cpp
+++ b/src/core/file_sys/savedata_factory.cpp
@@ -7,6 +7,7 @@
 #include "common/logging/log.h"
 #include "core/core.h"
 #include "core/file_sys/savedata_factory.h"
+#include "core/file_sys/vfs.h"
 #include "core/hle/kernel/process.h"
 
 namespace FileSys {
diff --git a/src/core/file_sys/savedata_factory.h b/src/core/file_sys/savedata_factory.h
index 368b3601702133b64863e8e58ee7d9ef3f541b5e..c6f9549f09eb8be714ef841a4a3c32034febd4ec 100644
--- a/src/core/file_sys/savedata_factory.h
+++ b/src/core/file_sys/savedata_factory.h
@@ -8,6 +8,7 @@
 #include <string>
 #include "common/common_types.h"
 #include "common/swap.h"
+#include "core/file_sys/vfs.h"
 #include "core/hle/result.h"
 
 namespace FileSys {
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp
index 03a954a9f9aa39ce6333c1d5e0880de05212cf03..6657accd56292153440a336af051012a3fc96334 100644
--- a/src/core/hle/kernel/address_arbiter.cpp
+++ b/src/core/hle/kernel/address_arbiter.cpp
@@ -8,9 +8,11 @@
 #include "common/assert.h"
 #include "common/common_types.h"
 #include "core/core.h"
+#include "core/core_cpu.h"
 #include "core/hle/kernel/errors.h"
 #include "core/hle/kernel/object.h"
 #include "core/hle/kernel/process.h"
+#include "core/hle/kernel/scheduler.h"
 #include "core/hle/kernel/thread.h"
 #include "core/hle/result.h"
 #include "core/memory.h"
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index db7aef76691636a56d75ba7c31775a19235ade0d..7264be9065b4fc1a5ef501e5f31364e9b989fdb2 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -18,6 +18,7 @@
 #include "core/hle/kernel/event.h"
 #include "core/hle/kernel/handle_table.h"
 #include "core/hle/kernel/hle_ipc.h"
+#include "core/hle/kernel/kernel.h"
 #include "core/hle/kernel/object.h"
 #include "core/hle/kernel/process.h"
 #include "core/hle/kernel/server_session.h"
diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp
index 90c9a5afffdeec527a291f08f97faac99b837e30..aba0cab964f6da7b63a6b8f7f48ff5887225d6a8 100644
--- a/src/core/hle/kernel/server_session.cpp
+++ b/src/core/hle/kernel/server_session.cpp
@@ -13,6 +13,7 @@
 #include "core/hle/kernel/client_session.h"
 #include "core/hle/kernel/handle_table.h"
 #include "core/hle/kernel/hle_ipc.h"
+#include "core/hle/kernel/kernel.h"
 #include "core/hle/kernel/process.h"
 #include "core/hle/kernel/server_session.h"
 #include "core/hle/kernel/session.h"
@@ -104,11 +105,10 @@ ResultCode ServerSession::HandleSyncRequest(SharedPtr<Thread> thread) {
     // The ServerSession received a sync request, this means that there's new data available
     // from its ClientSession, so wake up any threads that may be waiting on a svcReplyAndReceive or
     // similar.
-
-    auto& handle_table = Core::System::GetInstance().Kernel().HandleTable();
     Kernel::HLERequestContext context(this);
     u32* cmd_buf = (u32*)Memory::GetPointer(thread->GetTLSAddress());
-    context.PopulateFromIncomingCommandBuffer(cmd_buf, *Core::CurrentProcess(), handle_table);
+    context.PopulateFromIncomingCommandBuffer(cmd_buf, *Core::CurrentProcess(),
+                                              kernel.HandleTable());
 
     ResultCode result = RESULT_SUCCESS;
     // If the session has been converted to a domain, handle the domain request
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 099d1053f9d929e87d9912b5b4880072c8ccc061..5da71cff03e5ec13f2be0b2d207cc52a950f4de6 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -12,16 +12,20 @@
 #include "common/logging/log.h"
 #include "common/microprofile.h"
 #include "common/string_util.h"
+#include "core/arm/exclusive_monitor.h"
 #include "core/core.h"
+#include "core/core_cpu.h"
 #include "core/core_timing.h"
 #include "core/hle/kernel/address_arbiter.h"
 #include "core/hle/kernel/client_port.h"
 #include "core/hle/kernel/client_session.h"
 #include "core/hle/kernel/event.h"
 #include "core/hle/kernel/handle_table.h"
+#include "core/hle/kernel/kernel.h"
 #include "core/hle/kernel/mutex.h"
 #include "core/hle/kernel/process.h"
 #include "core/hle/kernel/resource_limit.h"
+#include "core/hle/kernel/scheduler.h"
 #include "core/hle/kernel/shared_memory.h"
 #include "core/hle/kernel/svc.h"
 #include "core/hle/kernel/svc_wrap.h"
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 520ea0853f34fb52c42fb3c8ead0e62c139b1a9a..3d10d9af22178222f85c76992b01f4c4128dc3e0 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -16,6 +16,7 @@
 #include "common/thread_queue_list.h"
 #include "core/arm/arm_interface.h"
 #include "core/core.h"
+#include "core/core_cpu.h"
 #include "core/core_timing.h"
 #include "core/core_timing_util.h"
 #include "core/hle/kernel/errors.h"
@@ -23,8 +24,8 @@
 #include "core/hle/kernel/kernel.h"
 #include "core/hle/kernel/object.h"
 #include "core/hle/kernel/process.h"
+#include "core/hle/kernel/scheduler.h"
 #include "core/hle/kernel/thread.h"
-#include "core/hle/lock.h"
 #include "core/hle/result.h"
 #include "core/memory.h"
 
diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h
index d88a6682522a61bbff5b1a245650cc2550a9db87..9ba0e2eab419df0439d705b38b3e5dbcc2699b9a 100644
--- a/src/core/hle/service/filesystem/filesystem.h
+++ b/src/core/hle/service/filesystem/filesystem.h
@@ -7,6 +7,7 @@
 #include <memory>
 #include "common/common_types.h"
 #include "core/file_sys/directory.h"
+#include "core/file_sys/vfs.h"
 #include "core/hle/result.h"
 
 namespace FileSys {
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp
index a53fa6e00cce1c9ca112f029b1a583e78270d51b..921b899e2dbb5b778d92c93bda4416016a2380dd 100644
--- a/src/core/loader/deconstructed_rom_directory.cpp
+++ b/src/core/loader/deconstructed_rom_directory.cpp
@@ -11,6 +11,7 @@
 #include "core/file_sys/control_metadata.h"
 #include "core/file_sys/romfs_factory.h"
 #include "core/gdbstub/gdbstub.h"
+#include "core/hle/kernel/kernel.h"
 #include "core/hle/kernel/process.h"
 #include "core/hle/kernel/resource_limit.h"
 #include "core/hle/service/filesystem/filesystem.h"
diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp
index 3702a84781f4b99420a1497450b848718b12bd0b..120e1e1334b3c7a7888580ab36770384a52a2100 100644
--- a/src/core/loader/elf.cpp
+++ b/src/core/loader/elf.cpp
@@ -10,6 +10,7 @@
 #include "common/file_util.h"
 #include "common/logging/log.h"
 #include "core/core.h"
+#include "core/hle/kernel/kernel.h"
 #include "core/hle/kernel/process.h"
 #include "core/hle/kernel/resource_limit.h"
 #include "core/loader/elf.h"
diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp
index 00205d1d2118e4b8b2ea8d6c2a41b0ae4b689c28..77026b850d6ac30e09f86f50ed0673222d533212 100644
--- a/src/core/loader/nro.cpp
+++ b/src/core/loader/nro.cpp
@@ -14,6 +14,7 @@
 #include "core/file_sys/control_metadata.h"
 #include "core/file_sys/vfs_offset.h"
 #include "core/gdbstub/gdbstub.h"
+#include "core/hle/kernel/kernel.h"
 #include "core/hle/kernel/process.h"
 #include "core/hle/kernel/resource_limit.h"
 #include "core/loader/nro.h"
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp
index 0c992d662b8f9287d950733b4b55abe03e13cb49..082a95d4055f0ccf8397a248f307ecb3f8e74ec5 100644
--- a/src/core/loader/nso.cpp
+++ b/src/core/loader/nso.cpp
@@ -11,6 +11,7 @@
 #include "common/swap.h"
 #include "core/core.h"
 #include "core/gdbstub/gdbstub.h"
+#include "core/hle/kernel/kernel.h"
 #include "core/hle/kernel/process.h"
 #include "core/hle/kernel/resource_limit.h"
 #include "core/loader/nso.h"
diff --git a/src/core/perf_stats.cpp b/src/core/perf_stats.cpp
index 93d23de210839203afaf6e82928deadfc213c31a..7d95816fe678508dcf3beecc475ddc74461c7093 100644
--- a/src/core/perf_stats.cpp
+++ b/src/core/perf_stats.cpp
@@ -40,7 +40,7 @@ void PerfStats::EndGameFrame() {
     game_frames += 1;
 }
 
-PerfStats::Results PerfStats::GetAndResetStats(microseconds current_system_time_us) {
+PerfStatsResults PerfStats::GetAndResetStats(microseconds current_system_time_us) {
     std::lock_guard<std::mutex> lock(object_mutex);
 
     const auto now = Clock::now();
@@ -49,7 +49,7 @@ PerfStats::Results PerfStats::GetAndResetStats(microseconds current_system_time_
 
     const auto system_us_per_second = (current_system_time_us - reset_point_system_us) / interval;
 
-    Results results{};
+    PerfStatsResults results{};
     results.system_fps = static_cast<double>(system_frames) / interval;
     results.game_fps = static_cast<double>(game_frames) / interval;
     results.frametime = duration_cast<DoubleSecs>(accumulated_frametime).count() /
diff --git a/src/core/perf_stats.h b/src/core/perf_stats.h
index 6e46197013d6db0ab6736bb7872186e986dc66a7..222ac1a639dcf228adb33f0df77db9ea3990542c 100644
--- a/src/core/perf_stats.h
+++ b/src/core/perf_stats.h
@@ -10,6 +10,17 @@
 
 namespace Core {
 
+struct PerfStatsResults {
+    /// System FPS (LCD VBlanks) in Hz
+    double system_fps;
+    /// Game FPS (GSP frame submissions) in Hz
+    double game_fps;
+    /// Walltime per system frame, in seconds, excluding any waits
+    double frametime;
+    /// Ratio of walltime / emulated time elapsed
+    double emulation_speed;
+};
+
 /**
  * Class to manage and query performance/timing statistics. All public functions of this class are
  * thread-safe unless stated otherwise.
@@ -18,22 +29,11 @@ class PerfStats {
 public:
     using Clock = std::chrono::high_resolution_clock;
 
-    struct Results {
-        /// System FPS (LCD VBlanks) in Hz
-        double system_fps;
-        /// Game FPS (GSP frame submissions) in Hz
-        double game_fps;
-        /// Walltime per system frame, in seconds, excluding any waits
-        double frametime;
-        /// Ratio of walltime / emulated time elapsed
-        double emulation_speed;
-    };
-
     void BeginSystemFrame();
     void EndSystemFrame();
     void EndGameFrame();
 
-    Results GetAndResetStats(std::chrono::microseconds current_system_time_us);
+    PerfStatsResults GetAndResetStats(std::chrono::microseconds current_system_time_us);
 
     /**
      * Gets the ratio between walltime and the emulated time of the previous system frame. This is
diff --git a/src/core/telemetry_session.cpp b/src/core/telemetry_session.cpp
index 827a1bbd045fbbfbbb823159e3a185f77f128fa1..65571b94865e6cd1a1b2be34e67c71c5ab321a1a 100644
--- a/src/core/telemetry_session.cpp
+++ b/src/core/telemetry_session.cpp
@@ -7,6 +7,7 @@
 #include "common/file_util.h"
 
 #include "core/core.h"
+#include "core/loader/loader.h"
 #include "core/settings.h"
 #include "core/telemetry_session.h"
 
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index f32a79d7b5f85423c9f2813386ebbaf03e2b9d46..68ff1e86b05aa67411a1d55ad69893edd2b6e07b 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -5,13 +5,12 @@
 #include <cinttypes>
 #include "common/assert.h"
 #include "core/core.h"
+#include "core/memory.h"
 #include "video_core/debug_utils/debug_utils.h"
 #include "video_core/engines/maxwell_3d.h"
 #include "video_core/rasterizer_interface.h"
 #include "video_core/renderer_base.h"
-#include "video_core/textures/decoders.h"
 #include "video_core/textures/texture.h"
-#include "video_core/video_core.h"
 
 namespace Tegra {
 namespace Engines {
diff --git a/src/video_core/rasterizer_cache.h b/src/video_core/rasterizer_cache.h
index de1eab86b2c60a39b0de84d75ec0d7902af5fb5b..083b283b027ffe5250b0a6856850ebbbcf445335 100644
--- a/src/video_core/rasterizer_cache.h
+++ b/src/video_core/rasterizer_cache.h
@@ -7,11 +7,10 @@
 #include <set>
 
 #include <boost/icl/interval_map.hpp>
+#include <boost/range/iterator_range_core.hpp>
 
 #include "common/common_types.h"
 #include "core/core.h"
-#include "core/memory.h"
-#include "video_core/memory_manager.h"
 #include "video_core/rasterizer_interface.h"
 #include "video_core/renderer_base.h"
 
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 3c4a9f17c5f947254668172dc5af00b074bee2bb..411a73d50f5ac0c67ed553a33c103a056a8f1d78 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -10,12 +10,14 @@
 #include <glad/glad.h>
 #include "common/assert.h"
 #include "common/logging/log.h"
+#include "common/telemetry.h"
 #include "core/core.h"
 #include "core/core_timing.h"
 #include "core/frontend/emu_window.h"
 #include "core/memory.h"
 #include "core/perf_stats.h"
 #include "core/settings.h"
+#include "core/telemetry_session.h"
 #include "core/tracer/recorder.h"
 #include "video_core/renderer_opengl/gl_rasterizer.h"
 #include "video_core/renderer_opengl/renderer_opengl.h"
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp
index eac0c05f274e7d3246d92283e28abdf864f184ec..6c2cd967ea2d1882908bb54059ff74c4fce06401 100644
--- a/src/yuzu/debugger/wait_tree.cpp
+++ b/src/yuzu/debugger/wait_tree.cpp
@@ -9,11 +9,14 @@
 #include "core/core.h"
 #include "core/hle/kernel/event.h"
 #include "core/hle/kernel/handle_table.h"
+#include "core/hle/kernel/kernel.h"
 #include "core/hle/kernel/mutex.h"
+#include "core/hle/kernel/scheduler.h"
 #include "core/hle/kernel/thread.h"
 #include "core/hle/kernel/timer.h"
 #include "core/hle/kernel/wait_object.h"
 
+WaitTreeItem::WaitTreeItem() = default;
 WaitTreeItem::~WaitTreeItem() = default;
 
 QColor WaitTreeItem::GetColor() const {
@@ -71,6 +74,7 @@ std::vector<std::unique_ptr<WaitTreeThread>> WaitTreeItem::MakeThreadItemList()
 }
 
 WaitTreeText::WaitTreeText(const QString& t) : text(t) {}
+WaitTreeText::~WaitTreeText() = default;
 
 QString WaitTreeText::GetText() const {
     return text;
@@ -84,6 +88,8 @@ WaitTreeMutexInfo::WaitTreeMutexInfo(VAddr mutex_address) : mutex_address(mutex_
     owner = handle_table.Get<Kernel::Thread>(owner_handle);
 }
 
+WaitTreeMutexInfo::~WaitTreeMutexInfo() = default;
+
 QString WaitTreeMutexInfo::GetText() const {
     return tr("waiting for mutex 0x%1").arg(mutex_address, 16, 16, QLatin1Char('0'));
 }
@@ -102,6 +108,7 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeMutexInfo::GetChildren() cons
 }
 
 WaitTreeCallstack::WaitTreeCallstack(const Kernel::Thread& thread) : thread(thread) {}
+WaitTreeCallstack::~WaitTreeCallstack() = default;
 
 QString WaitTreeCallstack::GetText() const {
     return tr("Call stack");
@@ -126,6 +133,10 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeCallstack::GetChildren() cons
 }
 
 WaitTreeWaitObject::WaitTreeWaitObject(const Kernel::WaitObject& o) : object(o) {}
+WaitTreeWaitObject::~WaitTreeWaitObject() = default;
+
+WaitTreeExpandableItem::WaitTreeExpandableItem() = default;
+WaitTreeExpandableItem::~WaitTreeExpandableItem() = default;
 
 bool WaitTreeExpandableItem::IsExpandable() const {
     return true;
@@ -180,6 +191,8 @@ WaitTreeObjectList::WaitTreeObjectList(
     const std::vector<Kernel::SharedPtr<Kernel::WaitObject>>& list, bool w_all)
     : object_list(list), wait_all(w_all) {}
 
+WaitTreeObjectList::~WaitTreeObjectList() = default;
+
 QString WaitTreeObjectList::GetText() const {
     if (wait_all)
         return tr("waiting for all objects");
@@ -194,6 +207,7 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeObjectList::GetChildren() con
 }
 
 WaitTreeThread::WaitTreeThread(const Kernel::Thread& thread) : WaitTreeWaitObject(thread) {}
+WaitTreeThread::~WaitTreeThread() = default;
 
 QString WaitTreeThread::GetText() const {
     const auto& thread = static_cast<const Kernel::Thread&>(object);
@@ -312,6 +326,7 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const {
 }
 
 WaitTreeEvent::WaitTreeEvent(const Kernel::Event& object) : WaitTreeWaitObject(object) {}
+WaitTreeEvent::~WaitTreeEvent() = default;
 
 std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeEvent::GetChildren() const {
     std::vector<std::unique_ptr<WaitTreeItem>> list(WaitTreeWaitObject::GetChildren());
@@ -323,6 +338,7 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeEvent::GetChildren() const {
 }
 
 WaitTreeTimer::WaitTreeTimer(const Kernel::Timer& object) : WaitTreeWaitObject(object) {}
+WaitTreeTimer::~WaitTreeTimer() = default;
 
 std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeTimer::GetChildren() const {
     std::vector<std::unique_ptr<WaitTreeItem>> list(WaitTreeWaitObject::GetChildren());
@@ -340,6 +356,7 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeTimer::GetChildren() const {
 
 WaitTreeThreadList::WaitTreeThreadList(const std::vector<Kernel::SharedPtr<Kernel::Thread>>& list)
     : thread_list(list) {}
+WaitTreeThreadList::~WaitTreeThreadList() = default;
 
 QString WaitTreeThreadList::GetText() const {
     return tr("waited by thread");
@@ -353,6 +370,7 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThreadList::GetChildren() con
 }
 
 WaitTreeModel::WaitTreeModel(QObject* parent) : QAbstractItemModel(parent) {}
+WaitTreeModel::~WaitTreeModel() = default;
 
 QModelIndex WaitTreeModel::index(int row, int column, const QModelIndex& parent) const {
     if (!hasIndex(row, column, parent))
@@ -421,6 +439,8 @@ WaitTreeWidget::WaitTreeWidget(QWidget* parent) : QDockWidget(tr("Wait Tree"), p
     setEnabled(false);
 }
 
+WaitTreeWidget::~WaitTreeWidget() = default;
+
 void WaitTreeWidget::OnDebugModeEntered() {
     if (!Core::System::GetInstance().IsPoweredOn())
         return;
diff --git a/src/yuzu/debugger/wait_tree.h b/src/yuzu/debugger/wait_tree.h
index 513b3c45d6f25df166c8b2e2a8b11d4f78a2ea78..defbf734fe8b26c7da3576248e700cd183137eec 100644
--- a/src/yuzu/debugger/wait_tree.h
+++ b/src/yuzu/debugger/wait_tree.h
@@ -4,11 +4,15 @@
 
 #pragma once
 
+#include <cstddef>
+#include <memory>
+#include <vector>
+
 #include <QAbstractItemModel>
 #include <QDockWidget>
 #include <QTreeView>
 #include <boost/container/flat_set.hpp>
-#include "core/core.h"
+#include "common/common_types.h"
 #include "core/hle/kernel/object.h"
 
 class EmuThread;
@@ -25,6 +29,7 @@ class WaitTreeThread;
 class WaitTreeItem : public QObject {
     Q_OBJECT
 public:
+    WaitTreeItem();
     ~WaitTreeItem() override;
 
     virtual bool IsExpandable() const;
@@ -49,6 +54,8 @@ class WaitTreeText : public WaitTreeItem {
     Q_OBJECT
 public:
     explicit WaitTreeText(const QString& text);
+    ~WaitTreeText() override;
+
     QString GetText() const override;
 
 private:
@@ -58,6 +65,9 @@ private:
 class WaitTreeExpandableItem : public WaitTreeItem {
     Q_OBJECT
 public:
+    WaitTreeExpandableItem();
+    ~WaitTreeExpandableItem() override;
+
     bool IsExpandable() const override;
 };
 
@@ -65,6 +75,8 @@ class WaitTreeMutexInfo : public WaitTreeExpandableItem {
     Q_OBJECT
 public:
     explicit WaitTreeMutexInfo(VAddr mutex_address);
+    ~WaitTreeMutexInfo() override;
+
     QString GetText() const override;
     std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
 
@@ -79,6 +91,8 @@ class WaitTreeCallstack : public WaitTreeExpandableItem {
     Q_OBJECT
 public:
     explicit WaitTreeCallstack(const Kernel::Thread& thread);
+    ~WaitTreeCallstack() override;
+
     QString GetText() const override;
     std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
 
@@ -90,6 +104,8 @@ class WaitTreeWaitObject : public WaitTreeExpandableItem {
     Q_OBJECT
 public:
     explicit WaitTreeWaitObject(const Kernel::WaitObject& object);
+    ~WaitTreeWaitObject() override;
+
     static std::unique_ptr<WaitTreeWaitObject> make(const Kernel::WaitObject& object);
     QString GetText() const override;
     std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
@@ -105,6 +121,8 @@ class WaitTreeObjectList : public WaitTreeExpandableItem {
 public:
     WaitTreeObjectList(const std::vector<Kernel::SharedPtr<Kernel::WaitObject>>& list,
                        bool wait_all);
+    ~WaitTreeObjectList() override;
+
     QString GetText() const override;
     std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
 
@@ -117,6 +135,8 @@ class WaitTreeThread : public WaitTreeWaitObject {
     Q_OBJECT
 public:
     explicit WaitTreeThread(const Kernel::Thread& thread);
+    ~WaitTreeThread() override;
+
     QString GetText() const override;
     QColor GetColor() const override;
     std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
@@ -126,6 +146,8 @@ class WaitTreeEvent : public WaitTreeWaitObject {
     Q_OBJECT
 public:
     explicit WaitTreeEvent(const Kernel::Event& object);
+    ~WaitTreeEvent() override;
+
     std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
 };
 
@@ -133,6 +155,8 @@ class WaitTreeTimer : public WaitTreeWaitObject {
     Q_OBJECT
 public:
     explicit WaitTreeTimer(const Kernel::Timer& object);
+    ~WaitTreeTimer() override;
+
     std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
 };
 
@@ -140,6 +164,8 @@ class WaitTreeThreadList : public WaitTreeExpandableItem {
     Q_OBJECT
 public:
     explicit WaitTreeThreadList(const std::vector<Kernel::SharedPtr<Kernel::Thread>>& list);
+    ~WaitTreeThreadList() override;
+
     QString GetText() const override;
     std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
 
@@ -152,6 +178,7 @@ class WaitTreeModel : public QAbstractItemModel {
 
 public:
     explicit WaitTreeModel(QObject* parent = nullptr);
+    ~WaitTreeModel() override;
 
     QVariant data(const QModelIndex& index, int role) const override;
     QModelIndex index(int row, int column, const QModelIndex& parent) const override;
@@ -171,6 +198,7 @@ class WaitTreeWidget : public QDockWidget {
 
 public:
     explicit WaitTreeWidget(QWidget* parent = nullptr);
+    ~WaitTreeWidget() override;
 
 public slots:
     void OnDebugModeEntered();
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp
index 27525938a8eb32620fe9c6779b2b8da119f3b275..d15242d59ac11ad07aa82110e97b5fdd42ffd0e0 100644
--- a/src/yuzu/game_list.cpp
+++ b/src/yuzu/game_list.cpp
@@ -23,10 +23,12 @@
 #include "core/file_sys/registered_cache.h"
 #include "core/file_sys/romfs.h"
 #include "core/file_sys/vfs_real.h"
+#include "core/hle/service/filesystem/filesystem.h"
 #include "core/loader/loader.h"
-#include "game_list.h"
-#include "game_list_p.h"
-#include "ui_settings.h"
+#include "yuzu/game_list.h"
+#include "yuzu/game_list_p.h"
+#include "yuzu/main.h"
+#include "yuzu/ui_settings.h"
 
 GameList::SearchField::KeyReleaseEater::KeyReleaseEater(GameList* gamelist) : gamelist{gamelist} {}
 
@@ -481,6 +483,14 @@ static void GetMetadataFromControlNCA(const std::shared_ptr<FileSys::NCA>& nca,
     }
 }
 
+GameListWorker::GameListWorker(
+    FileSys::VirtualFilesystem vfs, QString dir_path, bool deep_scan,
+    const std::unordered_map<std::string, std::pair<QString, QString>>& compatibility_list)
+    : vfs(std::move(vfs)), dir_path(std::move(dir_path)), deep_scan(deep_scan),
+      compatibility_list(compatibility_list) {}
+
+GameListWorker::~GameListWorker() = default;
+
 void GameListWorker::AddInstalledTitlesToGameList(std::shared_ptr<FileSys::RegisteredCache> cache) {
     const auto installed_games = cache->ListEntriesFilter(FileSys::TitleType::Application,
                                                           FileSys::ContentRecordType::Program);
diff --git a/src/yuzu/game_list.h b/src/yuzu/game_list.h
index c01351dc969df4c353486de1981cb123063d70b9..6a5c2f5f85a3440314a0b282d133bf3857b0211c 100644
--- a/src/yuzu/game_list.h
+++ b/src/yuzu/game_list.h
@@ -4,6 +4,8 @@
 
 #pragma once
 
+#include <unordered_map>
+
 #include <QFileSystemWatcher>
 #include <QHBoxLayout>
 #include <QLabel>
@@ -17,9 +19,13 @@
 #include <QTreeView>
 #include <QVBoxLayout>
 #include <QWidget>
-#include "main.h"
 
 class GameListWorker;
+class GMainWindow;
+
+namespace FileSys {
+class VfsFilesystem;
+}
 
 enum class GameListOpenTarget { SaveData };
 
@@ -62,7 +68,7 @@ public:
         QToolButton* button_filter_close = nullptr;
     };
 
-    explicit GameList(FileSys::VirtualFilesystem vfs, GMainWindow* parent = nullptr);
+    explicit GameList(std::shared_ptr<FileSys::VfsFilesystem> vfs, GMainWindow* parent = nullptr);
     ~GameList() override;
 
     void clearFilter();
@@ -97,7 +103,7 @@ private:
     void PopupContextMenu(const QPoint& menu_location);
     void RefreshGameDirectory();
 
-    FileSys::VirtualFilesystem vfs;
+    std::shared_ptr<FileSys::VfsFilesystem> vfs;
     SearchField* search_field;
     GMainWindow* main_window = nullptr;
     QVBoxLayout* layout = nullptr;
diff --git a/src/yuzu/game_list_p.h b/src/yuzu/game_list_p.h
index b9676d069b367fcd4e5ff4a4856245eb0da08c70..3624cb21ac77afb55f22e4900b854bcc2ee379fe 100644
--- a/src/yuzu/game_list_p.h
+++ b/src/yuzu/game_list_p.h
@@ -18,10 +18,15 @@
 #include <QString>
 #include "common/logging/log.h"
 #include "common/string_util.h"
-#include "core/file_sys/content_archive.h"
-#include "ui_settings.h"
+#include "yuzu/ui_settings.h"
 #include "yuzu/util/util.h"
 
+namespace FileSys {
+class NCA;
+class RegisteredCache;
+class VfsFilesystem;
+} // namespace FileSys
+
 /**
  * Gets the default icon (for games without valid SMDH)
  * @param large If true, returns large icon (48x48), otherwise returns small icon (24x24)
@@ -196,10 +201,9 @@ class GameListWorker : public QObject, public QRunnable {
 
 public:
     GameListWorker(
-        FileSys::VirtualFilesystem vfs, QString dir_path, bool deep_scan,
-        const std::unordered_map<std::string, std::pair<QString, QString>>& compatibility_list)
-        : vfs(std::move(vfs)), dir_path(std::move(dir_path)), deep_scan(deep_scan),
-          compatibility_list(compatibility_list) {}
+        std::shared_ptr<FileSys::VfsFilesystem> vfs, QString dir_path, bool deep_scan,
+        const std::unordered_map<std::string, std::pair<QString, QString>>& compatibility_list);
+    ~GameListWorker() override;
 
 public slots:
     /// Starts the processing of directory tree information.
@@ -222,7 +226,7 @@ signals:
     void Finished(QStringList watch_list);
 
 private:
-    FileSys::VirtualFilesystem vfs;
+    std::shared_ptr<FileSys::VfsFilesystem> vfs;
     std::map<u64, std::shared_ptr<FileSys::NCA>> nca_control_map;
     QStringList watch_list;
     QString dir_path;
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 1501aedc450b24b18bbdecf253441f3b704b0fab..e11ba7854b1485fc53fe7dd3f08c1319db079f2f 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -21,22 +21,22 @@
 #include "common/logging/backend.h"
 #include "common/logging/filter.h"
 #include "common/logging/log.h"
-#include "common/logging/text_formatter.h"
 #include "common/microprofile.h"
 #include "common/scm_rev.h"
 #include "common/scope_exit.h"
 #include "common/string_util.h"
+#include "common/telemetry.h"
 #include "core/core.h"
 #include "core/crypto/key_manager.h"
-#include "core/file_sys/bis_factory.h"
 #include "core/file_sys/card_image.h"
 #include "core/file_sys/registered_cache.h"
 #include "core/file_sys/savedata_factory.h"
 #include "core/file_sys/vfs_real.h"
-#include "core/gdbstub/gdbstub.h"
+#include "core/hle/service/filesystem/filesystem.h"
 #include "core/loader/loader.h"
+#include "core/perf_stats.h"
 #include "core/settings.h"
-#include "game_list_p.h"
+#include "core/telemetry_session.h"
 #include "video_core/debug_utils/debug_utils.h"
 #include "yuzu/about_dialog.h"
 #include "yuzu/bootmanager.h"
@@ -48,6 +48,7 @@
 #include "yuzu/debugger/profiler.h"
 #include "yuzu/debugger/wait_tree.h"
 #include "yuzu/game_list.h"
+#include "yuzu/game_list_p.h"
 #include "yuzu/hotkeys.h"
 #include "yuzu/main.h"
 #include "yuzu/ui_settings.h"
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index fd2436f4d901156e890df72cab36d11bd3a85425..0b97e8220a9686fe94b602905a3e79b27361bba9 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -5,6 +5,7 @@
 #pragma once
 
 #include <memory>
+#include <unordered_map>
 #include <QMainWindow>
 #include <QTimer>
 #include "core/core.h"
@@ -23,6 +24,10 @@ class ProfilerWidget;
 class WaitTreeWidget;
 enum class GameListOpenTarget;
 
+namespace FileSys {
+class VfsFilesystem;
+}
+
 namespace Tegra {
 class DebugContext;
 }
@@ -169,7 +174,7 @@ private:
     QString game_path;
 
     // FS
-    FileSys::VirtualFilesystem vfs;
+    std::shared_ptr<FileSys::VfsFilesystem> vfs;
 
     // Debugger panes
     ProfilerWidget* profilerWidget;
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp
index 9095cf27d39381e00519faf121983af6a06af41a..41e7da897f7128d29f1b9f06e4bd3c0362fb971b 100644
--- a/src/yuzu_cmd/yuzu.cpp
+++ b/src/yuzu_cmd/yuzu.cpp
@@ -17,10 +17,13 @@
 #include "common/scm_rev.h"
 #include "common/scope_exit.h"
 #include "common/string_util.h"
+#include "common/telemetry.h"
 #include "core/core.h"
+#include "core/file_sys/vfs_real.h"
 #include "core/gdbstub/gdbstub.h"
 #include "core/loader/loader.h"
 #include "core/settings.h"
+#include "core/telemetry_session.h"
 #include "yuzu_cmd/config.h"
 #include "yuzu_cmd/emu_window/emu_window_sdl2.h"