This commit is contained in:
Antonino Di Guardo 2025-12-04 19:43:35 +02:00 committed by GitHub
commit 6ee55e899d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 1380 additions and 513 deletions

View file

@ -149,11 +149,6 @@ namespace rpcs3::utils
return emu_dir_.empty() ? fs::get_config_dir() : emu_dir_;
}
std::string get_games_dir()
{
return g_cfg_vfs.get(g_cfg_vfs.games_dir, get_emu_dir());
}
std::string get_hdd0_dir()
{
return g_cfg_vfs.get(g_cfg_vfs.dev_hdd0, get_emu_dir());
@ -184,6 +179,31 @@ namespace rpcs3::utils
return g_cfg_vfs.get(g_cfg_vfs.dev_bdvd, get_emu_dir());
}
std::string get_games_dir()
{
return g_cfg_vfs.get(g_cfg_vfs.games_dir, get_emu_dir());
}
std::string get_hdd0_game_dir()
{
return get_hdd0_dir() + "game/";
}
std::string get_hdd0_locks_dir()
{
return get_hdd0_game_dir() + "locks/";
}
std::string get_hdd1_cache_dir()
{
return get_hdd1_dir() + "caches/";
}
std::string get_games_shortcuts_dir()
{
return get_games_dir() + "shortcuts/";
}
u64 get_cache_disk_usage()
{
if (const u64 data_size = fs::get_dir_size(rpcs3::utils::get_cache_dir(), 1); data_size != umax)
@ -221,6 +241,103 @@ namespace rpcs3::utils
return cache_dir;
}
std::string get_data_dir()
{
return fs::get_config_dir() + "data/";
}
std::string get_icons_dir()
{
return fs::get_config_dir() + "Icons/game_icons/";
}
std::string get_savestates_dir()
{
return fs::get_config_dir() + "savestates/";
}
std::string get_captures_dir()
{
return fs::get_config_dir() + "captures/";
}
std::string get_recordings_dir()
{
return fs::get_config_dir() + "recordings/";
}
std::string get_screenshots_dir()
{
return fs::get_config_dir() + "screenshots/";
}
std::string get_cache_dir_by_serial(const std::string& serial)
{
return get_cache_dir() + (serial == "vsh.self" ? "vsh" : serial);
}
std::string get_data_dir(const std::string& serial)
{
return get_data_dir() + serial;
}
std::string get_icons_dir(const std::string& serial)
{
return get_icons_dir() + serial;
}
std::string get_savestates_dir(const std::string& serial)
{
return get_savestates_dir() + serial;
}
std::string get_recordings_dir(const std::string& serial)
{
return get_recordings_dir() + serial;
}
std::string get_screenshots_dir(const std::string& serial)
{
return get_screenshots_dir() + serial;
}
std::string get_existing_dir(const std::string& dir)
{
return fs::is_dir(dir) ? dir : "";
}
std::set<std::string> get_dir_list(const std::string& base_dir, const std::string& serial)
{
std::set<std::string> dir_list;
for (const auto& entry : fs::dir(base_dir))
{
// Check for sub folder starting with serial (e.g. BCES01118_BCES01118)
if (entry.is_directory && entry.name.starts_with(serial))
{
dir_list.insert(base_dir + entry.name);
}
}
return dir_list;
}
std::set<std::string> get_file_list(const std::string& base_dir, const std::string& serial)
{
std::set<std::string> file_list;
for (const auto& entry : fs::dir(base_dir))
{
// Check for files starting with serial (e.g. BCES01118_BCES01118)
if (!entry.is_directory && entry.name.starts_with(serial))
{
file_list.insert(base_dir + entry.name);
}
}
return file_list;
}
std::string get_rap_file_path(const std::string_view& rap)
{
const std::string home_dir = get_hdd0_dir() + "home";

View file

@ -2,6 +2,7 @@
#include "util/types.hpp"
#include <string>
#include <set>
enum class game_content_type
{
@ -26,19 +27,43 @@ namespace rpcs3::utils
// VFS directories and disk usage
std::vector<std::pair<std::string, u64>> get_vfs_disk_usage();
std::string get_emu_dir();
std::string get_games_dir();
std::string get_hdd0_dir();
std::string get_hdd1_dir();
std::string get_flash_dir();
std::string get_flash2_dir();
std::string get_flash3_dir();
std::string get_bdvd_dir();
std::string get_games_dir();
std::string get_hdd0_game_dir();
std::string get_hdd0_locks_dir();
std::string get_hdd1_cache_dir();
std::string get_games_shortcuts_dir();
// Cache directories and disk usage
u64 get_cache_disk_usage();
std::string get_cache_dir();
std::string get_cache_dir(std::string_view module_path);
std::string get_data_dir();
std::string get_icons_dir();
std::string get_savestates_dir();
std::string get_captures_dir();
std::string get_recordings_dir();
std::string get_screenshots_dir();
// get_cache_dir_by_serial() named in this way to avoid conflict (wrong invocation) with get_cache_dir()
std::string get_cache_dir_by_serial(const std::string& serial);
std::string get_data_dir(const std::string& serial);
std::string get_icons_dir(const std::string& serial);
std::string get_savestates_dir(const std::string& serial);
std::string get_recordings_dir(const std::string& serial);
std::string get_screenshots_dir(const std::string& serial);
std::string get_existing_dir(const std::string& dir);
std::set<std::string> get_dir_list(const std::string& base_dir, const std::string& serial);
std::set<std::string> get_file_list(const std::string& base_dir, const std::string& serial);
std::string get_rap_file_path(const std::string_view& rap);
bool verify_c00_unlock_edat(const std::string_view& content_id, bool fast = false);
std::string get_sfo_dir_from_game_path(const std::string& game_path, const std::string& title_id = "");

File diff suppressed because it is too large Load diff

View file

@ -63,13 +63,54 @@ public:
bool IsEntryVisible(const game_info& game, bool search_fallback = false) const;
enum content_type
{
NO_CONTENT = 0,
DISC = (1 << 0),
DATA = (1 << 1),
LOCKS = (1 << 2),
CACHES = (1 << 3),
CUSTOM_CONFIG = (1 << 4),
ICONS = (1 << 5),
SHORTCUTS = (1 << 6),
SAVESTATES = (1 << 7),
CAPTURES = (1 << 8),
RECORDINGS = (1 << 9),
SCREENSHOTS = (1 << 10)
};
struct content_info
{
u16 content_types = NO_CONTENT; // Always set by SetContentList()
bool clear_on_finish = true; // Always overridden by BatchRemoveContentLists()
bool is_single_selection = false;
u16 in_games_dir_count = 0;
QString info;
std::map<std::string, std::set<std::string>> name_list;
std::map<std::string, std::set<std::string>> path_list;
std::set<std::string> disc_list;
std::set<std::string> removed_disc_list; // Filled in by RemoveContentList()
};
public Q_SLOTS:
void BatchCreateCPUCaches(const std::vector<game_info>& game_data = {}, bool is_fast_compilation = false);
void BatchRemovePPUCaches();
void BatchRemoveSPUCaches();
void BatchRemoveCustomConfigurations();
void BatchRemoveCustomPadConfigurations();
void BatchRemoveShaderCaches();
void BatchCreateCPUCaches(const std::vector<game_info>& games = {}, bool is_fast_compilation = false, bool is_interactive = false);
void BatchRemoveCustomConfigurations(const std::vector<game_info>& games = {}, bool is_interactive = false);
void BatchRemoveCustomPadConfigurations(const std::vector<game_info>& games = {}, bool is_interactive = false);
void BatchRemoveShaderCaches(const std::vector<game_info>& games = {}, bool is_interactive = false);
void BatchRemovePPUCaches(const std::vector<game_info>& games = {}, bool is_interactive = false);
void BatchRemoveSPUCaches(const std::vector<game_info>& games = {}, bool is_interactive = false);
void BatchRemoveHDD1Caches(const std::vector<game_info>& games = {}, bool is_interactive = false);
void BatchRemoveAllCaches(const std::vector<game_info>& games = {}, bool is_interactive = false);
// NOTES:
// - SetContentList() MUST always be called to set the content's info to be removed by:
// - RemoveContentList()
// - BatchRemoveContentLists()
//
void SetContentList(u16 content_types, const content_info& content_info);
void BatchRemoveContentLists(const std::vector<game_info>& games = {}, bool is_interactive = false);
void SetListMode(bool is_list);
void SetSearchText(const QString& text);
void SetShowCompatibilityInGrid(bool show);
@ -133,22 +174,49 @@ private:
void ShowCustomConfigIcon(const game_info& game);
bool SearchMatchesApp(const QString& name, const QString& serial, bool fallback = false) const;
bool RemoveCustomConfiguration(const std::string& title_id, const game_info& game = nullptr, bool is_interactive = false);
bool RemoveCustomPadConfiguration(const std::string& title_id, const game_info& game = nullptr, bool is_interactive = false);
bool RemoveShadersCache(const std::string& base_dir, bool is_interactive = false);
bool RemovePPUCache(const std::string& base_dir, bool is_interactive = false);
bool RemoveSPUCache(const std::string& base_dir, bool is_interactive = false);
void RemoveHDD1Cache(const std::string& base_dir, const std::string& title_id, bool is_interactive = false);
void ShowSingleSelectionContextMenu(const game_info& gameinfo, QPoint& global_pos);
void ShowMultiSelectionContextMenu(const std::vector<game_info>& games, QPoint& global_pos);
// NOTE:
// m_content_info is used by:
// - SetContentList()
// - ClearContentList()
// - GetContentInfo()
// - RemoveContentList()
// - BatchRemoveContentLists()
//
content_info m_content_info;
void ClearContentList(bool refresh = false);
content_info GetContentInfo(const std::vector<game_info>& games);
void DialogRemoveGame(const std::vector<game_info>& games);
void DialogGameInfo(const std::vector<game_info>& games);
static bool IsGameRunning(const std::string& serial);
bool ValidateRemoval(const std::string& serial, const std::string& path, const std::string& desc, bool is_interactive = false);
bool ValidateBatchRemoval(const std::string& desc, bool is_interactive = false);
static bool CreateCPUCaches(const std::string& path, const std::string& serial = {}, bool is_fast_compilation = false);
static bool CreateCPUCaches(const game_info& game, bool is_fast_compilation = false);
bool RemoveCustomConfiguration(const std::string& serial, const game_info& game = nullptr, bool is_interactive = false);
bool RemoveCustomPadConfiguration(const std::string& serial, const game_info& game = nullptr, bool is_interactive = false);
bool RemoveShaderCache(const std::string& serial, bool is_interactive = false);
bool RemovePPUCache(const std::string& serial, bool is_interactive = false);
bool RemoveSPUCache(const std::string& serial, bool is_interactive = false);
bool RemoveHDD1Cache(const std::string& serial, bool is_interactive = false);
bool RemoveAllCaches(const std::string& serial, bool is_interactive = false);
bool RemoveContentList(const std::string& serial, bool is_interactive = false);
static bool RemoveContentPath(const std::string& path, const std::string& desc);
static u32 RemoveContentPathList(const std::vector<std::string>& path_list, const std::string& desc);
static u32 RemoveContentPathList(const std::set<std::string>& path_list, const std::string& desc);
static bool RemoveContentBySerial(const std::string& base_dir, const std::string& serial, const std::string& desc);
static std::vector<std::string> GetDirListBySerial(const std::string& base_dir, const std::string& serial);
void BatchActionBySerials(progress_dialog* pdlg, const std::set<std::string>& serials, QString progressLabel, std::function<bool(const std::string&)> action, std::function<void(u32, u32)> cancel_log, bool refresh_on_finish, bool can_be_concurrent = false, std::function<bool()> should_wait_cb = {});
static std::string GetCacheDirBySerial(const std::string& serial);
static std::string GetDataDirBySerial(const std::string& serial);
void BatchActionBySerials(progress_dialog* pdlg, const std::set<std::string>& serials,
QString progressLabel, std::function<bool(const std::string&)> action,
std::function<void(u32, u32)> cancel_log, std::function<void()> action_on_finish, bool refresh_on_finish,
bool can_be_concurrent = false, std::function<bool()> should_wait_cb = {});
std::string CurrentSelectionPath();
game_info GetGameInfoByMode(const QTableWidgetItem* item) const;

View file

@ -24,7 +24,7 @@ game_list_table::game_list_table(game_list_frame* frame, std::shared_ptr<persist
setItemDelegate(new game_list_delegate(this));
setEditTriggers(QAbstractItemView::NoEditTriggers);
setSelectionBehavior(QAbstractItemView::SelectRows);
setSelectionMode(QAbstractItemView::SingleSelection);
setSelectionMode(QAbstractItemView::ExtendedSelection);
setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
verticalScrollBar()->setSingleStep(20);

View file

@ -2782,15 +2782,43 @@ 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->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->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->batchCreateCPUCachesAct, &QAction::triggered, this, [this]()
{
m_game_list_frame->BatchCreateCPUCaches({}, false, true);
});
connect(ui->batchRemoveCustomConfigurationsAct, &QAction::triggered, this, [this]()
{
m_game_list_frame->BatchRemoveCustomConfigurations({}, true);
});
connect(ui->batchRemoveCustomPadConfigurationsAct, &QAction::triggered, this, [this]()
{
m_game_list_frame->BatchRemoveCustomPadConfigurations({}, true);
});
connect(ui->batchRemoveShaderCachesAct, &QAction::triggered, this, [this]()
{
m_game_list_frame->BatchRemoveShaderCaches({}, true);
});
connect(ui->batchRemovePPUCachesAct, &QAction::triggered, this, [this]()
{
m_game_list_frame->BatchRemovePPUCaches({}, true);
});
connect(ui->batchRemoveSPUCachesAct, &QAction::triggered, this, [this]()
{
m_game_list_frame->BatchRemoveSPUCaches({}, true);
});
connect(ui->removeHDD1CachesAct, &QAction::triggered, this, [this]()
{
m_game_list_frame->BatchRemoveHDD1Caches({}, true);
});
connect(ui->removeAllCachesAct, &QAction::triggered, this, [this]()
{
m_game_list_frame->BatchRemoveAllCaches({}, true);
});
connect(ui->removeSavestatesAct, &QAction::triggered, this, [this]()
{
m_game_list_frame->SetContentList(game_list_frame::content_type::SAVESTATES, {});
m_game_list_frame->BatchRemoveContentLists({}, true);
});
connect(ui->cleanUpGameListAct, &QAction::triggered, this, &main_window::CleanUpGameList);
connect(ui->removeFirmwareCacheAct, &QAction::triggered, this, &main_window::RemoveFirmwareCache);
@ -3712,67 +3740,6 @@ void main_window::SetIconSizeActions(int idx) const
ui->setIconSizeLargeAct->setChecked(true);
}
void main_window::RemoveHDD1Caches()
{
if (fs::remove_all(rpcs3::utils::get_hdd1_dir() + "caches", false))
{
QMessageBox::information(this, tr("HDD1 Caches Removed"), tr("HDD1 caches successfully removed"));
}
else
{
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 && QString::fromStdString(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"

View file

@ -115,9 +115,6 @@ private Q_SLOTS:
void SetIconSizeActions(int idx) const;
void ResizeIcons(int index);
void RemoveHDD1Caches();
void RemoveAllCaches();
void RemoveSavestates();
void CleanUpGameList();
void RemoveFirmwareCache();

View file

@ -1129,7 +1129,7 @@
</action>
<action name="batchRemoveCustomPadConfigurationsAct">
<property name="text">
<string>Remove Custom Pad Configurations</string>
<string>Remove Custom Gamepad Configurations</string>
</property>
</action>
<action name="batchRemoveShaderCachesAct">