diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp
index 37351c5610..e94eed3b66 100644
--- a/src/core/file_sys/registered_cache.cpp
+++ b/src/core/file_sys/registered_cache.cpp
@@ -547,56 +547,6 @@ InstallResult RegisteredCache::InstallEntry(const XCI& xci, bool overwrite_if_ex
     return InstallEntry(*xci.GetSecurePartitionNSP(), overwrite_if_exists, copy);
 }
 
-bool RegisteredCache::RemoveExistingEntry(u64 title_id) {
-    const auto delete_nca = [this](const NcaID& id) {
-        const auto path = GetRelativePathFromNcaID(id, false, true, false);
-
-        if (dir->GetFileRelative(path) == nullptr) {
-            return false;
-        }
-
-        Core::Crypto::SHA256Hash hash{};
-        mbedtls_sha256_ret(id.data(), id.size(), hash.data(), 0);
-        const auto dirname = fmt::format("000000{:02X}", hash[0]);
-
-        const auto dir2 = GetOrCreateDirectoryRelative(dir, dirname);
-
-        const auto res = dir2->DeleteFile(fmt::format("{}.nca", Common::HexToString(id, false)));
-
-        return res;
-    };
-
-    // If an entry exists in the registered cache, remove it
-    if (HasEntry(title_id, ContentRecordType::Meta)) {
-        LOG_INFO(Loader,
-                 "Previously installed entry (v{}) for title_id={:016X} detected! "
-                 "Attempting to remove...",
-                 GetEntryVersion(title_id).value_or(0), title_id);
-        // Get all the ncas associated with the current CNMT and delete them
-        const auto meta_old_id =
-            GetNcaIDFromMetadata(title_id, ContentRecordType::Meta).value_or(NcaID{});
-        const auto program_id =
-            GetNcaIDFromMetadata(title_id, ContentRecordType::Program).value_or(NcaID{});
-        const auto data_id =
-            GetNcaIDFromMetadata(title_id, ContentRecordType::Data).value_or(NcaID{});
-        const auto control_id =
-            GetNcaIDFromMetadata(title_id, ContentRecordType::Control).value_or(NcaID{});
-        const auto html_id =
-            GetNcaIDFromMetadata(title_id, ContentRecordType::HtmlDocument).value_or(NcaID{});
-        const auto legal_id =
-            GetNcaIDFromMetadata(title_id, ContentRecordType::LegalInformation).value_or(NcaID{});
-
-        delete_nca(meta_old_id);
-        delete_nca(program_id);
-        delete_nca(data_id);
-        delete_nca(control_id);
-        delete_nca(html_id);
-        delete_nca(legal_id);
-        return true;
-    }
-    return false;
-}
-
 InstallResult RegisteredCache::InstallEntry(const NSP& nsp, bool overwrite_if_exists,
                                             const VfsCopyFunction& copy) {
     const auto ncas = nsp.GetNCAsCollapsed();
@@ -692,6 +642,57 @@ InstallResult RegisteredCache::InstallEntry(const NCA& nca, TitleType type,
     return RawInstallNCA(nca, copy, overwrite_if_exists, c_rec.nca_id);
 }
 
+bool RegisteredCache::RemoveExistingEntry(u64 title_id) const {
+    const auto delete_nca = [this](const NcaID& id) {
+        const auto path = GetRelativePathFromNcaID(id, false, true, false);
+
+        const bool isFile = dir->GetFileRelative(path) != nullptr;
+        const bool isDir = dir->GetDirectoryRelative(path) != nullptr;
+
+        if (isFile) {
+            return dir->DeleteFile(path);
+        } else if (isDir) {
+            return dir->DeleteSubdirectoryRecursive(path);
+        }
+
+        return false;
+    };
+
+    // If an entry exists in the registered cache, remove it
+    if (HasEntry(title_id, ContentRecordType::Meta)) {
+        LOG_INFO(Loader,
+                 "Previously installed entry (v{}) for title_id={:016X} detected! "
+                 "Attempting to remove...",
+                 GetEntryVersion(title_id).value_or(0), title_id);
+
+        // Get all the ncas associated with the current CNMT and delete them
+        const auto meta_old_id =
+            GetNcaIDFromMetadata(title_id, ContentRecordType::Meta).value_or(NcaID{});
+        const auto program_id =
+            GetNcaIDFromMetadata(title_id, ContentRecordType::Program).value_or(NcaID{});
+        const auto data_id =
+            GetNcaIDFromMetadata(title_id, ContentRecordType::Data).value_or(NcaID{});
+        const auto control_id =
+            GetNcaIDFromMetadata(title_id, ContentRecordType::Control).value_or(NcaID{});
+        const auto html_id =
+            GetNcaIDFromMetadata(title_id, ContentRecordType::HtmlDocument).value_or(NcaID{});
+        const auto legal_id =
+            GetNcaIDFromMetadata(title_id, ContentRecordType::LegalInformation).value_or(NcaID{});
+
+        const auto deleted_meta = delete_nca(meta_old_id);
+        const auto deleted_program = delete_nca(program_id);
+        const auto deleted_data = delete_nca(data_id);
+        const auto deleted_control = delete_nca(control_id);
+        const auto deleted_html = delete_nca(html_id);
+        const auto deleted_legal = delete_nca(legal_id);
+
+        return deleted_meta && (deleted_meta || deleted_program || deleted_data ||
+                                deleted_control || deleted_html || deleted_legal);
+    }
+
+    return false;
+}
+
 InstallResult RegisteredCache::RawInstallNCA(const NCA& nca, const VfsCopyFunction& copy,
                                              bool overwrite_if_exists,
                                              std::optional<NcaID> override_id) {
diff --git a/src/core/file_sys/registered_cache.h b/src/core/file_sys/registered_cache.h
index 29cf0d40c7..ec1d54f27c 100644
--- a/src/core/file_sys/registered_cache.h
+++ b/src/core/file_sys/registered_cache.h
@@ -155,9 +155,6 @@ public:
         std::optional<TitleType> title_type = {}, std::optional<ContentRecordType> record_type = {},
         std::optional<u64> title_id = {}) const override;
 
-    // Removes an existing entry based on title id
-    bool RemoveExistingEntry(u64 title_id);
-
     // Raw copies all the ncas from the xci/nsp to the csache. Does some quick checks to make sure
     // there is a meta NCA and all of them are accessible.
     InstallResult InstallEntry(const XCI& xci, bool overwrite_if_exists = false,
@@ -172,6 +169,9 @@ public:
     InstallResult InstallEntry(const NCA& nca, TitleType type, bool overwrite_if_exists = false,
                                const VfsCopyFunction& copy = &VfsRawCopy);
 
+    // Removes an existing entry based on title id
+    bool RemoveExistingEntry(u64 title_id) const;
+
 private:
     template <typename T>
     void IterateAllMetadata(std::vector<T>& out,
diff --git a/src/core/file_sys/xts_archive.cpp b/src/core/file_sys/xts_archive.cpp
index 86e06ccb9e..81413c684e 100644
--- a/src/core/file_sys/xts_archive.cpp
+++ b/src/core/file_sys/xts_archive.cpp
@@ -70,14 +70,18 @@ NAX::NAX(VirtualFile file_, std::array<u8, 0x10> nca_id)
 NAX::~NAX() = default;
 
 Loader::ResultStatus NAX::Parse(std::string_view path) {
-    if (file->ReadObject(header.get()) != sizeof(NAXHeader))
+    if (file == nullptr) {
+        return Loader::ResultStatus::ErrorNullFile;
+    }
+    if (file->ReadObject(header.get()) != sizeof(NAXHeader)) {
         return Loader::ResultStatus::ErrorBadNAXHeader;
-
-    if (header->magic != Common::MakeMagic('N', 'A', 'X', '0'))
+    }
+    if (header->magic != Common::MakeMagic('N', 'A', 'X', '0')) {
         return Loader::ResultStatus::ErrorBadNAXHeader;
-
-    if (file->GetSize() < NAX_HEADER_PADDING_SIZE + header->file_size)
+    }
+    if (file->GetSize() < NAX_HEADER_PADDING_SIZE + header->file_size) {
         return Loader::ResultStatus::ErrorIncorrectNAXFileSize;
+    }
 
     keys.DeriveSDSeedLazy();
     std::array<Core::Crypto::Key256, 2> sd_keys{};
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp
index ab7fc7a247..62acc37207 100644
--- a/src/yuzu/game_list.cpp
+++ b/src/yuzu/game_list.cpp
@@ -474,28 +474,56 @@ void GameList::PopupContextMenu(const QPoint& menu_location) {
 
 void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, std::string path) {
     QAction* open_save_location = context_menu.addAction(tr("Open Save Data Location"));
-    QAction* open_lfs_location = context_menu.addAction(tr("Open Mod Data Location"));
+    QAction* open_mod_location = context_menu.addAction(tr("Open Mod Data Location"));
     QAction* open_transferable_shader_cache =
         context_menu.addAction(tr("Open Transferable Shader Cache"));
     context_menu.addSeparator();
+    QMenu* remove_menu = context_menu.addMenu(tr("Remove"));
+    QAction* remove_update = remove_menu->addAction(tr("Remove Installed Update"));
+    QAction* remove_dlc = remove_menu->addAction(tr("Remove All Installed DLC"));
+    QAction* remove_shader_cache = remove_menu->addAction(tr("Remove Shader Cache"));
+    QAction* remove_custom_config = remove_menu->addAction(tr("Remove Custom Configuration"));
+    remove_menu->addSeparator();
+    QAction* remove_all_content = remove_menu->addAction(tr("Remove All Installed Contents"));
     QAction* dump_romfs = context_menu.addAction(tr("Dump RomFS"));
     QAction* copy_tid = context_menu.addAction(tr("Copy Title ID to Clipboard"));
     QAction* navigate_to_gamedb_entry = context_menu.addAction(tr("Navigate to GameDB entry"));
     context_menu.addSeparator();
     QAction* properties = context_menu.addAction(tr("Properties"));
 
-    open_save_location->setEnabled(program_id != 0);
+    open_save_location->setVisible(program_id != 0);
+    open_mod_location->setVisible(program_id != 0);
+    open_transferable_shader_cache->setVisible(program_id != 0);
+    remove_update->setVisible(program_id != 0);
+    remove_dlc->setVisible(program_id != 0);
+    remove_shader_cache->setVisible(program_id != 0);
+    remove_all_content->setVisible(program_id != 0);
     auto it = FindMatchingCompatibilityEntry(compatibility_list, program_id);
     navigate_to_gamedb_entry->setVisible(it != compatibility_list.end() && program_id != 0);
 
     connect(open_save_location, &QAction::triggered, [this, program_id, path]() {
         emit OpenFolderRequested(GameListOpenTarget::SaveData, path);
     });
-    connect(open_lfs_location, &QAction::triggered, [this, program_id, path]() {
+    connect(open_mod_location, &QAction::triggered, [this, program_id, path]() {
         emit OpenFolderRequested(GameListOpenTarget::ModData, path);
     });
     connect(open_transferable_shader_cache, &QAction::triggered,
             [this, program_id]() { emit OpenTransferableShaderCacheRequested(program_id); });
+    connect(remove_all_content, &QAction::triggered, [this, program_id]() {
+        emit RemoveInstalledEntryRequested(program_id, InstalledEntryType::Game);
+    });
+    connect(remove_update, &QAction::triggered, [this, program_id]() {
+        emit RemoveInstalledEntryRequested(program_id, InstalledEntryType::Update);
+    });
+    connect(remove_dlc, &QAction::triggered, [this, program_id]() {
+        emit RemoveInstalledEntryRequested(program_id, InstalledEntryType::AddOnContent);
+    });
+    connect(remove_shader_cache, &QAction::triggered, [this, program_id]() {
+        emit RemoveFileRequested(program_id, GameListRemoveTarget::ShaderCache);
+    });
+    connect(remove_custom_config, &QAction::triggered, [this, program_id]() {
+        emit RemoveFileRequested(program_id, GameListRemoveTarget::CustomConfiguration);
+    });
     connect(dump_romfs, &QAction::triggered,
             [this, program_id, path]() { emit DumpRomFSRequested(program_id, path); });
     connect(copy_tid, &QAction::triggered,
diff --git a/src/yuzu/game_list.h b/src/yuzu/game_list.h
index a38cb2fc35..483835cceb 100644
--- a/src/yuzu/game_list.h
+++ b/src/yuzu/game_list.h
@@ -39,6 +39,17 @@ enum class GameListOpenTarget {
     ModData,
 };
 
+enum class GameListRemoveTarget {
+    ShaderCache,
+    CustomConfiguration,
+};
+
+enum class InstalledEntryType {
+    Game,
+    Update,
+    AddOnContent,
+};
+
 class GameList : public QWidget {
     Q_OBJECT
 
@@ -75,6 +86,8 @@ signals:
     void ShouldCancelWorker();
     void OpenFolderRequested(GameListOpenTarget target, const std::string& game_path);
     void OpenTransferableShaderCacheRequested(u64 program_id);
+    void RemoveInstalledEntryRequested(u64 program_id, InstalledEntryType type);
+    void RemoveFileRequested(u64 program_id, GameListRemoveTarget target);
     void DumpRomFSRequested(u64 program_id, const std::string& game_path);
     void CopyTIDRequested(u64 program_id);
     void NavigateToGamedbEntryRequested(u64 program_id,
@@ -117,8 +130,6 @@ private:
     friend class GameListSearchField;
 };
 
-Q_DECLARE_METATYPE(GameListOpenTarget);
-
 class GameListPlaceholder : public QWidget {
     Q_OBJECT
 public:
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 31a6351769..276658c9e0 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -847,6 +847,9 @@ void GMainWindow::ConnectWidgetEvents() {
     connect(game_list, &GameList::OpenFolderRequested, this, &GMainWindow::OnGameListOpenFolder);
     connect(game_list, &GameList::OpenTransferableShaderCacheRequested, this,
             &GMainWindow::OnTransferableShaderCacheOpenFile);
+    connect(game_list, &GameList::RemoveInstalledEntryRequested, this,
+            &GMainWindow::OnGameListRemoveInstalledEntry);
+    connect(game_list, &GameList::RemoveFileRequested, this, &GMainWindow::OnGameListRemoveFile);
     connect(game_list, &GameList::DumpRomFSRequested, this, &GMainWindow::OnGameListDumpRomFS);
     connect(game_list, &GameList::CopyTIDRequested, this, &GMainWindow::OnGameListCopyTID);
     connect(game_list, &GameList::NavigateToGamedbEntryRequested, this,
@@ -1257,7 +1260,6 @@ void GMainWindow::OnGameListOpenFolder(GameListOpenTarget target, const std::str
     case GameListOpenTarget::SaveData: {
         open_target = tr("Save Data");
         const std::string nand_dir = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir);
-        ASSERT(program_id != 0);
 
         if (has_user_save) {
             // User save data
@@ -1322,14 +1324,12 @@ void GMainWindow::OnGameListOpenFolder(GameListOpenTarget target, const std::str
 }
 
 void GMainWindow::OnTransferableShaderCacheOpenFile(u64 program_id) {
-    ASSERT(program_id != 0);
-
     const QString shader_dir =
         QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::ShaderDir));
-    const QString tranferable_shader_cache_folder_path =
+    const QString transferable_shader_cache_folder_path =
         shader_dir + QStringLiteral("opengl") + QDir::separator() + QStringLiteral("transferable");
     const QString transferable_shader_cache_file_path =
-        tranferable_shader_cache_folder_path + QDir::separator() +
+        transferable_shader_cache_folder_path + QDir::separator() +
         QString::fromStdString(fmt::format("{:016X}.bin", program_id));
 
     if (!QFile::exists(transferable_shader_cache_file_path)) {
@@ -1350,7 +1350,7 @@ void GMainWindow::OnTransferableShaderCacheOpenFile(u64 program_id) {
     param << QDir::toNativeSeparators(transferable_shader_cache_file_path);
     QProcess::startDetached(explorer, param);
 #else
-    QDesktopServices::openUrl(QUrl::fromLocalFile(tranferable_shader_cache_folder_path));
+    QDesktopServices::openUrl(QUrl::fromLocalFile(transferable_shader_cache_folder_path));
 #endif
 }
 
@@ -1394,6 +1394,174 @@ static bool RomFSRawCopy(QProgressDialog& dialog, const FileSys::VirtualDir& src
     return true;
 }
 
+void GMainWindow::OnGameListRemoveInstalledEntry(u64 program_id, InstalledEntryType type) {
+    const QString entry_type = [this, type] {
+        switch (type) {
+        case InstalledEntryType::Game:
+            return tr("Contents");
+        case InstalledEntryType::Update:
+            return tr("Update");
+        case InstalledEntryType::AddOnContent:
+            return tr("DLC");
+        default:
+            return QString{};
+        }
+    }();
+
+    if (QMessageBox::question(
+            this, tr("Remove Entry"), tr("Remove Installed Game %1?").arg(entry_type),
+            QMessageBox::Yes | QMessageBox::No, QMessageBox::No) != QMessageBox::Yes) {
+        return;
+    }
+
+    switch (type) {
+    case InstalledEntryType::Game:
+        RemoveBaseContent(program_id, entry_type);
+        [[fallthrough]];
+    case InstalledEntryType::Update:
+        RemoveUpdateContent(program_id, entry_type);
+        if (type != InstalledEntryType::Game) {
+            break;
+        }
+        [[fallthrough]];
+    case InstalledEntryType::AddOnContent:
+        RemoveAddOnContent(program_id, entry_type);
+        break;
+    }
+    FileUtil::DeleteDirRecursively(FileUtil::GetUserPath(FileUtil::UserPath::CacheDir) + DIR_SEP +
+                                   "game_list");
+    game_list->PopulateAsync(UISettings::values.game_dirs);
+}
+
+void GMainWindow::RemoveBaseContent(u64 program_id, const QString& entry_type) {
+    const auto& fs_controller = Core::System::GetInstance().GetFileSystemController();
+    const auto res = fs_controller.GetUserNANDContents()->RemoveExistingEntry(program_id) ||
+                     fs_controller.GetSDMCContents()->RemoveExistingEntry(program_id);
+
+    if (res) {
+        QMessageBox::information(this, tr("Successfully Removed"),
+                                 tr("Successfully removed the installed base game."));
+    } else {
+        QMessageBox::warning(
+            this, tr("Error Removing %1").arg(entry_type),
+            tr("The base game is not installed in the NAND and cannot be removed."));
+    }
+}
+
+void GMainWindow::RemoveUpdateContent(u64 program_id, const QString& entry_type) {
+    const auto update_id = program_id | 0x800;
+    const auto& fs_controller = Core::System::GetInstance().GetFileSystemController();
+    const auto res = fs_controller.GetUserNANDContents()->RemoveExistingEntry(update_id) ||
+                     fs_controller.GetSDMCContents()->RemoveExistingEntry(update_id);
+
+    if (res) {
+        QMessageBox::information(this, tr("Successfully Removed"),
+                                 tr("Successfully removed the installed update."));
+    } else {
+        QMessageBox::warning(this, tr("Error Removing %1").arg(entry_type),
+                             tr("There is no update installed for this title."));
+    }
+}
+
+void GMainWindow::RemoveAddOnContent(u64 program_id, const QString& entry_type) {
+    u32 count{};
+    const auto& fs_controller = Core::System::GetInstance().GetFileSystemController();
+    const auto dlc_entries = Core::System::GetInstance().GetContentProvider().ListEntriesFilter(
+        FileSys::TitleType::AOC, FileSys::ContentRecordType::Data);
+
+    for (const auto& entry : dlc_entries) {
+        if ((entry.title_id & DLC_BASE_TITLE_ID_MASK) == program_id) {
+            const auto res =
+                fs_controller.GetUserNANDContents()->RemoveExistingEntry(entry.title_id) ||
+                fs_controller.GetSDMCContents()->RemoveExistingEntry(entry.title_id);
+            if (res) {
+                ++count;
+            }
+        }
+    }
+
+    if (count == 0) {
+        QMessageBox::warning(this, tr("Error Removing %1").arg(entry_type),
+                             tr("There are no DLC installed for this title."));
+        return;
+    }
+
+    QMessageBox::information(this, tr("Successfully Removed"),
+                             tr("Successfully removed %1 installed DLC.").arg(count));
+}
+
+void GMainWindow::OnGameListRemoveFile(u64 program_id, GameListRemoveTarget target) {
+    const QString question = [this, target] {
+        switch (target) {
+        case GameListRemoveTarget::ShaderCache:
+            return tr("Delete Transferable Shader Cache?");
+        case GameListRemoveTarget::CustomConfiguration:
+            return tr("Remove Custom Game Configuration?");
+        default:
+            return QString{};
+        }
+    }();
+
+    if (QMessageBox::question(this, tr("Remove File"), question, QMessageBox::Yes | QMessageBox::No,
+                              QMessageBox::No) != QMessageBox::Yes) {
+        return;
+    }
+
+    switch (target) {
+    case GameListRemoveTarget::ShaderCache:
+        RemoveTransferableShaderCache(program_id);
+        break;
+    case GameListRemoveTarget::CustomConfiguration:
+        RemoveCustomConfiguration(program_id);
+        break;
+    }
+}
+
+void GMainWindow::RemoveTransferableShaderCache(u64 program_id) {
+    const QString shader_dir =
+        QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::ShaderDir));
+    const QString transferable_shader_cache_folder_path =
+        shader_dir + QStringLiteral("opengl") + QDir::separator() + QStringLiteral("transferable");
+    const QString transferable_shader_cache_file_path =
+        transferable_shader_cache_folder_path + QDir::separator() +
+        QString::fromStdString(fmt::format("{:016X}.bin", program_id));
+
+    if (!QFile::exists(transferable_shader_cache_file_path)) {
+        QMessageBox::warning(this, tr("Error Removing Transferable Shader Cache"),
+                             tr("A shader cache for this title does not exist."));
+        return;
+    }
+
+    if (QFile::remove(transferable_shader_cache_file_path)) {
+        QMessageBox::information(this, tr("Successfully Removed"),
+                                 tr("Successfully removed the transferable shader cache."));
+    } else {
+        QMessageBox::warning(this, tr("Error Removing Transferable Shader Cache"),
+                             tr("Failed to remove the transferable shader cache."));
+    }
+}
+
+void GMainWindow::RemoveCustomConfiguration(u64 program_id) {
+    const QString config_dir =
+        QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::ConfigDir));
+    const QString custom_config_file_path =
+        config_dir + QString::fromStdString(fmt::format("{:016X}.ini", program_id));
+
+    if (!QFile::exists(custom_config_file_path)) {
+        QMessageBox::warning(this, tr("Error Removing Custom Configuration"),
+                             tr("A custom configuration for this title does not exist."));
+        return;
+    }
+
+    if (QFile::remove(custom_config_file_path)) {
+        QMessageBox::information(this, tr("Successfully Removed"),
+                                 tr("Successfully removed the custom game configuration."));
+    } else {
+        QMessageBox::warning(this, tr("Error Removing Custom Configuration"),
+                             tr("Failed to remove the custom game configuration."));
+    }
+}
+
 void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_path) {
     const auto failed = [this] {
         QMessageBox::warning(this, tr("RomFS Extraction Failed!"),
@@ -1714,9 +1882,9 @@ void GMainWindow::OnMenuInstallToNAND() {
                                 : tr("%n file(s) failed to install\n", "", failed_files.size()));
 
     QMessageBox::information(this, tr("Install Results"), install_results);
-    game_list->PopulateAsync(UISettings::values.game_dirs);
     FileUtil::DeleteDirRecursively(FileUtil::GetUserPath(FileUtil::UserPath::CacheDir) + DIR_SEP +
                                    "game_list");
+    game_list->PopulateAsync(UISettings::values.game_dirs);
     ui.action_Install_File_NAND->setEnabled(true);
 }
 
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index db573d6064..73a44a3bf5 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -32,6 +32,8 @@ class QPushButton;
 class QProgressDialog;
 class WaitTreeWidget;
 enum class GameListOpenTarget;
+enum class GameListRemoveTarget;
+enum class InstalledEntryType;
 class GameListPlaceholder;
 
 namespace Core::Frontend {
@@ -198,6 +200,8 @@ private slots:
     void OnGameListLoadFile(QString game_path);
     void OnGameListOpenFolder(GameListOpenTarget target, const std::string& game_path);
     void OnTransferableShaderCacheOpenFile(u64 program_id);
+    void OnGameListRemoveInstalledEntry(u64 program_id, InstalledEntryType type);
+    void OnGameListRemoveFile(u64 program_id, GameListRemoveTarget target);
     void OnGameListDumpRomFS(u64 program_id, const std::string& game_path);
     void OnGameListCopyTID(u64 program_id);
     void OnGameListNavigateToGamedbEntry(u64 program_id,
@@ -229,6 +233,11 @@ private slots:
     void OnLanguageChanged(const QString& locale);
 
 private:
+    void RemoveBaseContent(u64 program_id, const QString& entry_type);
+    void RemoveUpdateContent(u64 program_id, const QString& entry_type);
+    void RemoveAddOnContent(u64 program_id, const QString& entry_type);
+    void RemoveTransferableShaderCache(u64 program_id);
+    void RemoveCustomConfiguration(u64 program_id);
     std::optional<u64> SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id);
     InstallResult InstallNSPXCI(const QString& filename);
     InstallResult InstallNCA(const QString& filename);