|
|
|
@ -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); |
|
|
|
} |
|
|
|
|
|
|
|
|