Added reconciliation functions for game list file (games.yml) (#16061)

This commit is contained in:
Antonino Di Guardo 2024-09-20 08:46:51 +02:00 committed by GitHub
parent 5b5bfaf696
commit df9275819e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 160 additions and 34 deletions

View File

@ -4082,7 +4082,7 @@ game_boot_result Emulator::AddGameToYml(const std::string& path)
return game_boot_result::invalid_file_or_folder;
}
u32 Emulator::RemoveGames(const std::vector<std::string>& title_id_list)
u32 Emulator::RemoveGames(const std::vector<std::string>& title_id_list, bool save_on_disk)
{
if (title_id_list.empty())
{
@ -4103,7 +4103,7 @@ u32 Emulator::RemoveGames(const std::vector<std::string>& title_id_list)
m_games_config.set_save_on_dirty(true);
if (m_games_config.is_dirty() && !m_games_config.save())
if (save_on_disk && m_games_config.is_dirty() && !m_games_config.save())
{
sys_log.error("Failed to save games.yml after removing games");
}

View File

@ -379,7 +379,7 @@ public:
u32 AddGamesFromDir(const std::string& path);
game_boot_result AddGame(const std::string& path);
game_boot_result AddGameToYml(const std::string& path);
u32 RemoveGames(const std::vector<std::string>& title_id_list);
u32 RemoveGames(const std::vector<std::string>& title_id_list, bool save_on_disk = true);
game_boot_result RemoveGameFromYml(const std::string& title_id);
// Check if path is inside the specified directory

View File

@ -425,13 +425,27 @@ void game_list_frame::Refresh(const bool from_drive, const std::vector<std::stri
m_progress_dialog->SetValue(0);
}
// Remove the specified serials (title id) in "games.yml" file (if any)
Emu.RemoveGames(serials_to_remove_from_yml);
const std::string games_dir = rpcs3::utils::get_games_dir();
const u32 games_added = Emu.AddGamesFromDir(games_dir);
if (games_added)
// List of serials (title id) to remove in "games.yml" file (if any)
std::vector<std::string> serials_to_remove = serials_to_remove_from_yml; // Initialize the list with the specified serials (if any)
// Scan game list to detect the titles belonging to auto-detection "games" folder
for (const auto& [serial, path] : Emu.GetGamesConfig().get_games()) // Loop on game list file
{
// NOTE: Used starts_with(games_dir) instead of Emu.IsPathInsideDir(path, games_dir) due the latter would check also the existence of the paths
//
if (path.starts_with(games_dir)) // If game path belongs to auto-detection "games" folder, add the serial to the removal list
{
serials_to_remove.push_back(serial);
}
}
// Remove the specified and detected serials (title id) only from the game list in memory (not yet in "games.yml" file)
Emu.RemoveGames(serials_to_remove, false);
// Scan auto-detection "games" folder adding the detected titles to the game list plus flushing also all the other changes in "games.yml" file
if (const u32 games_added = Emu.AddGamesFromDir(games_dir); games_added != 0)
{
game_list_log.notice("Refresh added %d new entries found in %s", games_added, games_dir);
}
@ -1721,7 +1735,7 @@ void game_list_frame::ShowContextMenu(const QPoint &pos)
{
u64 total_data_size = 0;
text += tr("\nData Info:\n");
text += tr("\n%0 Info:\n").arg(is_disc_game ? tr("Game Data") : gameinfo->localized_category);
for (const std::string& data_dir : data_dir_list)
{
@ -1740,7 +1754,7 @@ void game_list_frame::ShowContextMenu(const QPoint &pos)
}
}
if (fs::device_stat stat{}; fs::statfs(rpcs3::utils::get_hdd0_dir(), stat)) // retrieve disk space info on data path's drive
if (fs::device_stat stat{}; fs::statfs(rpcs3::utils::get_hdd0_dir(), stat)) // Retrieve disk space info on data path's drive
{
text += tr("\nCurrent free disk space: %0\n").arg(gui::utils::format_byte_size(stat.avail_free));
}

View File

@ -1980,10 +1980,13 @@ void main_window::OnEmuStop()
#endif
}
ui->batchRemoveShaderCachesAct->setEnabled(true);
ui->batchRemovePPUCachesAct->setEnabled(true);
ui->batchRemoveSPUCachesAct->setEnabled(true);
ui->batchRemoveShaderCachesAct->setEnabled(true);
ui->removeDiskCacheAct->setEnabled(true);
ui->removeHDD1CachesAct->setEnabled(true);
ui->removeAllCachesAct->setEnabled(true);
ui->removeSavestatesAct->setEnabled(true);
ui->cleanupGameListAct->setEnabled(true);
ui->actionManage_Users->setEnabled(true);
ui->confCamerasAct->setEnabled(true);
@ -2030,10 +2033,13 @@ void main_window::OnEmuReady() const
ui->actionManage_Users->setEnabled(false);
ui->confCamerasAct->setEnabled(false);
ui->batchRemoveShaderCachesAct->setEnabled(false);
ui->batchRemovePPUCachesAct->setEnabled(false);
ui->batchRemoveSPUCachesAct->setEnabled(false);
ui->batchRemoveShaderCachesAct->setEnabled(false);
ui->removeDiskCacheAct->setEnabled(false);
ui->removeHDD1CachesAct->setEnabled(false);
ui->removeAllCachesAct->setEnabled(false);
ui->removeSavestatesAct->setEnabled(false);
ui->cleanupGameListAct->setEnabled(false);
}
void main_window::EnableMenus(bool enabled) const
@ -2680,13 +2686,15 @@ void main_window::CreateConnects()
connect(ui->exitAct, &QAction::triggered, this, &QWidget::close);
connect(ui->batchCreateCPUCachesAct, &QAction::triggered, m_game_list_frame, [list = m_game_list_frame]() { list->BatchCreateCPUCaches(); });
connect(ui->batchRemovePPUCachesAct, &QAction::triggered, m_game_list_frame, &game_list_frame::BatchRemovePPUCaches);
connect(ui->batchRemoveSPUCachesAct, &QAction::triggered, m_game_list_frame, &game_list_frame::BatchRemoveSPUCaches);
connect(ui->batchRemoveShaderCachesAct, &QAction::triggered, m_game_list_frame, &game_list_frame::BatchRemoveShaderCaches);
connect(ui->batchRemoveCustomConfigurationsAct, &QAction::triggered, m_game_list_frame, &game_list_frame::BatchRemoveCustomConfigurations);
connect(ui->batchRemoveCustomPadConfigurationsAct, &QAction::triggered, m_game_list_frame, &game_list_frame::BatchRemoveCustomPadConfigurations);
connect(ui->removeDiskCacheAct, &QAction::triggered, this, &main_window::RemoveDiskCache);
connect(ui->batchRemoveShaderCachesAct, &QAction::triggered, m_game_list_frame, &game_list_frame::BatchRemoveShaderCaches);
connect(ui->batchRemovePPUCachesAct, &QAction::triggered, m_game_list_frame, &game_list_frame::BatchRemovePPUCaches);
connect(ui->batchRemoveSPUCachesAct, &QAction::triggered, m_game_list_frame, &game_list_frame::BatchRemoveSPUCaches);
connect(ui->removeHDD1CachesAct, &QAction::triggered, this, &main_window::RemoveHDD1Caches);
connect(ui->removeAllCachesAct, &QAction::triggered, this, &main_window::RemoveAllCaches);
connect(ui->removeSavestatesAct, &QAction::triggered, this, &main_window::RemoveSavestates);
connect(ui->cleanupGameListAct, &QAction::triggered, this, &main_window::CleanupGameList);
connect(ui->removeFirmwareCacheAct, &QAction::triggered, this, &main_window::RemoveFirmwareCache);
connect(ui->createFirmwareCacheAct, &QAction::triggered, this, &main_window::CreateFirmwareCache);
@ -3531,20 +3539,102 @@ void main_window::SetIconSizeActions(int idx) const
ui->setIconSizeLargeAct->setChecked(true);
}
void main_window::RemoveDiskCache()
void main_window::RemoveHDD1Caches()
{
const std::string cache_dir = rpcs3::utils::get_hdd1_dir() + "/caches";
if (fs::remove_all(cache_dir, false))
if (fs::remove_all(rpcs3::utils::get_hdd1_dir() + "caches", false))
{
QMessageBox::information(this, tr("Cache Cleared"), tr("Disk cache was cleared successfully"));
QMessageBox::information(this, tr("HDD1 Caches Removed"), tr("HDD1 caches successfully removed"));
}
else
{
QMessageBox::warning(this, tr("Error"), tr("Could not remove disk cache"));
QMessageBox::warning(this, tr("Error"), tr("Could not remove HDD1 caches"));
}
}
void main_window::RemoveAllCaches()
{
if (QMessageBox::question(this, tr("Confirm Removal"), tr("Remove all caches?")) != QMessageBox::Yes)
return;
const std::string cache_base_dir = rpcs3::utils::get_cache_dir();
u64 caches_count = 0;
u64 caches_removed = 0;
for (const game_info& game : m_game_list_frame->GetGameInfo()) // Loop on detected games
{
if (game && qstr(game->info.category) != cat::cat_ps3_os && fs::exists(cache_base_dir + game->info.serial)) // If not OS category and cache exists
{
caches_count++;
if (fs::remove_all(cache_base_dir + game->info.serial))
{
caches_removed++;
}
}
}
if (caches_count == caches_removed)
{
QMessageBox::information(this, tr("Caches Removed"), tr("%0 cache(s) successfully removed").arg(caches_removed));
}
else
{
QMessageBox::warning(this, tr("Error"), tr("Could not remove %0 of %1 cache(s)").arg(caches_count - caches_removed).arg(caches_count));
}
RemoveHDD1Caches();
}
void main_window::RemoveSavestates()
{
if (QMessageBox::question(this, tr("Confirm Removal"), tr("Remove savestates?")) != QMessageBox::Yes)
return;
if (fs::remove_all(fs::get_config_dir() + "savestates", false))
{
QMessageBox::information(this, tr("Savestates Removed"), tr("Savestates successfully removed"));
}
else
{
QMessageBox::warning(this, tr("Error"), tr("Could not remove savestates"));
}
}
void main_window::CleanupGameList()
{
if (QMessageBox::question(this, tr("Confirm Removal"), tr("Remove invalid game paths from game list?\n"
"Undetectable games (zombies) as well as corrupted games will be removed from the game list file (games.yml)")) != QMessageBox::Yes)
{
return;
}
// List of serials (title id) to remove in "games.yml" file (if any)
std::vector<std::string> serials_to_remove_from_yml{};
for (const auto& [serial, path] : Emu.GetGamesConfig().get_games()) // Loop on game list file
{
bool found = false;
for (const game_info& game : m_game_list_frame->GetGameInfo()) // Loop on detected games
{
// If Disc Game and its serial is found in game list file
if (game && qstr(game->info.category) == cat::cat_disc_game && game->info.serial == serial)
{
found = true;
break;
}
}
if (!found) // If serial not found, add it to the removal list
{
serials_to_remove_from_yml.push_back(serial);
}
}
// Remove the found serials (title id) in "games.yml" file (if any)
QMessageBox::information(this, tr("Summary"), tr("%0 game(s) removed from game list").arg(Emu.RemoveGames(serials_to_remove_from_yml)));
}
void main_window::RemoveFirmwareCache()
{
const std::string cache_dir = rpcs3::utils::get_cache_dir();

View File

@ -128,7 +128,11 @@ private Q_SLOTS:
void SetIconSizeActions(int idx) const;
void ResizeIcons(int index);
void RemoveDiskCache();
void RemoveHDD1Caches();
void RemoveAllCaches();
void RemoveSavestates();
void CleanupGameList();
void RemoveFirmwareCache();
void CreateFirmwareCache();

View File

@ -186,11 +186,14 @@
<addaction name="separator"/>
<addaction name="batchRemoveCustomConfigurationsAct"/>
<addaction name="batchRemoveCustomPadConfigurationsAct"/>
<addaction name="batchRemoveShaderCachesAct"/>
<addaction name="batchRemovePPUCachesAct"/>
<addaction name="batchRemoveSPUCachesAct"/>
<addaction name="batchRemoveShaderCachesAct"/>
<addaction name="removeHDD1CachesAct"/>
<addaction name="removeAllCachesAct"/>
<addaction name="removeSavestatesAct"/>
<addaction name="separator"/>
<addaction name="removeDiskCacheAct"/>
<addaction name="cleanupGameListAct"/>
</widget>
<widget class="QMenu" name="menuFirmware">
<property name="title">
@ -1128,6 +1131,16 @@
<string>Remove Custom Configurations</string>
</property>
</action>
<action name="batchRemoveCustomPadConfigurationsAct">
<property name="text">
<string>Remove Custom Pad Configurations</string>
</property>
</action>
<action name="batchRemoveShaderCachesAct">
<property name="text">
<string>Remove Shader Caches</string>
</property>
</action>
<action name="batchRemovePPUCachesAct">
<property name="text">
<string>Remove PPU Caches</string>
@ -1138,19 +1151,24 @@
<string>Remove SPU Caches</string>
</property>
</action>
<action name="batchRemoveShaderCachesAct">
<action name="removeHDD1CachesAct">
<property name="text">
<string>Remove Shader Caches</string>
<string>Remove HDD1 Caches</string>
</property>
</action>
<action name="batchRemoveCustomPadConfigurationsAct">
<action name="removeAllCachesAct">
<property name="text">
<string>Remove Custom Pad Configurations</string>
<string>Remove All Caches</string>
</property>
</action>
<action name="removeDiskCacheAct">
<action name="removeSavestatesAct">
<property name="text">
<string>Remove Disk Cache</string>
<string>Remove Savestates</string>
</property>
</action>
<action name="cleanupGameListAct">
<property name="text">
<string>Clean up Game List</string>
</property>
</action>
<action name="actionManage_Skylanders_Portal">