Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Qt/System: Improve "add games" error handling #15084

Merged
merged 2 commits into from
Jan 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 39 additions & 15 deletions rpcs3/Emu/System.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ void fmt_class_string<game_boot_result>::format(std::string& out, u64 arg)
case game_boot_result::savestate_corrupted: return "Savestate data is corrupted or it's not an RPCS3 savestate";
case game_boot_result::savestate_version_unsupported: return "Savestate versioning data differs from your RPCS3 build.\nTry to use an older or newer RPCS3 build.\nEspecially if you know the build that created the savestate.";
case game_boot_result::still_running: return "Game is still running";
case game_boot_result::already_added: return "Game was already added";
}
return unknown;
});
Expand Down Expand Up @@ -1758,11 +1759,11 @@ game_boot_result Emulator::Load(const std::string& title_id, bool is_disc_patch,
}

// Store /dev_bdvd/ location
if (m_games_config.add_game(m_title_id, bdvd_dir))
if (games_config::result res = m_games_config.add_game(m_title_id, bdvd_dir); res == games_config::result::success)
{
sys_log.notice("Registered BDVD game directory for title '%s': %s", m_title_id, bdvd_dir);
}
else
else if (res == games_config::result::failure)
{
sys_log.error("Failed to save BDVD location of title '%s' (error=%s)", m_title_id, fs::g_tls_error);
}
Expand Down Expand Up @@ -1818,7 +1819,7 @@ game_boot_result Emulator::Load(const std::string& title_id, bool is_disc_patch,
std::string game_dir = m_sfo_dir;

// Add HG games not in HDD0 to games.yml
[[maybe_unused]] const bool res = m_games_config.add_external_hdd_game(m_title_id, game_dir);
[[maybe_unused]] const games_config::result res = m_games_config.add_external_hdd_game(m_title_id, game_dir);

const std::string dir = fmt::trim(game_dir.substr(fs::get_parent_dir_view(game_dir).size() + 1), fs::delim);
vfs::mount("/dev_hdd0/game/" + dir, game_dir + '/');
Expand All @@ -1844,11 +1845,11 @@ game_boot_result Emulator::Load(const std::string& title_id, bool is_disc_patch,
sys_log.notice("Game: %s", new_ps3_game);

// Store /dev_bdvd/PS3_GAME location
if (m_games_config.add_game(m_title_id, new_ps3_game + "/./"))
if (games_config::result res = m_games_config.add_game(m_title_id, new_ps3_game + "/./"); res == games_config::result::success)
{
sys_log.notice("Registered BDVD/PS3_GAME game directory for title '%s': %s", m_title_id, new_ps3_game);
}
else
else if (res == games_config::result::failure)
{
sys_log.error("Failed to save BDVD/PS3_GAME location of title '%s' (error=%s)", m_title_id, fs::g_tls_error);
}
Expand Down Expand Up @@ -3626,14 +3627,16 @@ std::set<std::string> Emulator::GetGameDirs() const
return dirs;
}

void Emulator::AddGamesFromDir(const std::string& path)
u32 Emulator::AddGamesFromDir(const std::string& path)
{
u32 games_added = 0;

m_games_config.set_save_on_dirty(false);

// search dropped path first or else the direct parent to an elf is wrongly skipped
if (const auto error = AddGame(path); error == game_boot_result::no_errors)
if (const game_boot_result error = AddGame(path); error == game_boot_result::no_errors)
{
// Nothing to do
games_added++;
}

process_qt_events();
Expand All @@ -3648,9 +3651,9 @@ void Emulator::AddGamesFromDir(const std::string& path)

const std::string dir_path = path + '/' + dir_entry.name;

if (const auto error = AddGame(dir_path); error == game_boot_result::no_errors)
if (const game_boot_result error = AddGame(dir_path); error == game_boot_result::no_errors)
{
// Nothing to do
games_added++;
}

process_qt_events();
Expand All @@ -3662,6 +3665,8 @@ void Emulator::AddGamesFromDir(const std::string& path)
{
sys_log.error("Failed to save games.yml after adding games");
}

return games_added;
}

game_boot_result Emulator::AddGame(const std::string& path)
Expand All @@ -3673,12 +3678,14 @@ game_boot_result Emulator::AddGame(const std::string& path)
}

game_boot_result result = game_boot_result::nothing_to_boot;
bool result_set = false;

std::string elf;
if (const game_boot_result res = GetElfPathFromDir(elf, path); res == game_boot_result::no_errors)
{
ensure(!elf.empty());
result = AddGameToYml(elf);
result_set = true;
}

for (auto&& entry : fs::dir{ path })
Expand All @@ -3696,7 +3703,11 @@ game_boot_result Emulator::AddGame(const std::string& path)
{
if (const auto err = AddGameToYml(elf); err != game_boot_result::no_errors)
{
result = err;
if (err != game_boot_result::already_added || !result_set)
{
result = err;
result_set = true;
}
}
}
}
Expand Down Expand Up @@ -3769,9 +3780,11 @@ game_boot_result Emulator::AddGameToYml(const std::string& path)
// Add HG games not in HDD0 to games.yml
if (cat == "HG")
{
if (m_games_config.add_external_hdd_game(title_id, sfo_dir))
switch (m_games_config.add_external_hdd_game(title_id, sfo_dir))
{
return game_boot_result::no_errors;
case games_config::result::failure: return game_boot_result::generic_error;
case games_config::result::success: return game_boot_result::no_errors;
case games_config::result::exists: return game_boot_result::already_added;
}

return game_boot_result::generic_error;
Expand All @@ -3786,13 +3799,24 @@ game_boot_result Emulator::AddGameToYml(const std::string& path)
}

// Store /dev_bdvd/ location
if (m_games_config.add_game(title_id, bdvd_dir))
switch (m_games_config.add_game(title_id, bdvd_dir))
{
case games_config::result::failure:
{
sys_log.error("Failed to save BDVD location of title '%s' (error=%s)", title_id, fs::g_tls_error);
return game_boot_result::generic_error;
}
case games_config::result::success:
{
sys_log.notice("Registered BDVD game directory for title '%s': %s", title_id, bdvd_dir);
return game_boot_result::no_errors;
}
case games_config::result::exists:
{
return game_boot_result::already_added;
}
}

sys_log.error("Failed to save BDVD location of title '%s' (error=%s)", title_id, fs::g_tls_error);
return game_boot_result::generic_error;
}

Expand Down
3 changes: 2 additions & 1 deletion rpcs3/Emu/System.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ enum class game_boot_result : u32
savestate_corrupted,
savestate_version_unsupported,
still_running,
already_added,
};

constexpr bool is_error(game_boot_result res)
Expand Down Expand Up @@ -369,7 +370,7 @@ class Emulator final
void ConfigurePPUCache(bool with_title_id = true) const;

std::set<std::string> GetGameDirs() const;
void AddGamesFromDir(const std::string& path);
u32 AddGamesFromDir(const std::string& path);
game_boot_result AddGame(const std::string& path);
game_boot_result AddGameToYml(const std::string& path);

Expand Down
27 changes: 17 additions & 10 deletions rpcs3/Emu/games_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ std::string games_config::get_path(const std::string& title_id) const
return {};
}

bool games_config::add_game(const std::string& key, const std::string& path)
games_config::result games_config::add_game(const std::string& key, const std::string& path)
{
std::lock_guard lock(m_mutex);

Expand All @@ -52,7 +52,7 @@ bool games_config::add_game(const std::string& key, const std::string& path)
if (it->second == path)
{
// Nothing to do
return true;
return result::exists;
}

it->second = path;
Expand All @@ -64,30 +64,37 @@ bool games_config::add_game(const std::string& key, const std::string& path)

m_dirty = true;

if (m_save_on_dirty)
if (m_save_on_dirty && !save_nl())
{
return save_nl();
return result::failure;
}

return true;
return result::success;
}

bool games_config::add_external_hdd_game(const std::string& key, std::string& path)
games_config::result games_config::add_external_hdd_game(const std::string& key, std::string& path)
{
// Don't use the C00 subdirectory in our game list
if (path.ends_with("/C00") || path.ends_with("\\C00"))
{
path = path.substr(0, path.size() - 4);
}

if (add_game(key, path))
const result res = add_game(key, path);

switch (res)
{
case result::failure:
cfg_log.error("Failed to save HG game location of title '%s' (error=%s)", key, fs::g_tls_error);
break;
case result::success:
cfg_log.notice("Registered HG game directory for title '%s': %s", key, path);
return true;
break;
case result::exists:
break;
}

cfg_log.error("Failed to save HG game location of title '%s' (error=%s)", key, fs::g_tls_error);
return false;
return res;
}

bool games_config::save_nl()
Expand Down
10 changes: 8 additions & 2 deletions rpcs3/Emu/games_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,14 @@ class games_config

std::string get_path(const std::string& title_id) const;

bool add_game(const std::string& key, const std::string& path);
bool add_external_hdd_game(const std::string& key, std::string& path);
enum class result
{
failure,
success,
exists
};
result add_game(const std::string& key, const std::string& path);
result add_external_hdd_game(const std::string& key, std::string& path);
bool save();

private:
Expand Down
8 changes: 7 additions & 1 deletion rpcs3/rpcs3qt/game_list_frame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,13 @@ void game_list_frame::Refresh(const bool from_drive, const bool scroll_after)
m_progress_dialog_timer->start();
}

Emu.AddGamesFromDir(g_cfg_vfs.get(g_cfg_vfs.games_dir, rpcs3::utils::get_emu_dir()));
const std::string games_dir = g_cfg_vfs.get(g_cfg_vfs.games_dir, rpcs3::utils::get_emu_dir());
const u32 games_added = Emu.AddGamesFromDir(games_dir);

if (games_added)
{
game_list_log.notice("Refresh added %d new entries found in %s", games_added, games_dir);
}

const std::string _hdd = Emu.GetCallbacks().resolve_path(rpcs3::utils::get_hdd0_dir()) + '/';

Expand Down
16 changes: 14 additions & 2 deletions rpcs3/rpcs3qt/main_window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,7 @@ void main_window::show_boot_error(game_boot_result status)
message = tr("A game or PS3 application is still running or has yet to be fully stopped.");
break;
case game_boot_result::firmware_missing: // Handled elsewhere
case game_boot_result::already_added: // Handled elsewhere
case game_boot_result::no_errors:
return;
case game_boot_result::generic_error:
Expand Down Expand Up @@ -3546,9 +3547,16 @@ void main_window::AddGamesFromDirs(QStringList&& paths)
}
}

u32 games_added = 0;

for (const QString& path : paths)
{
Emu.AddGamesFromDir(sstr(path));
games_added += Emu.AddGamesFromDir(sstr(path));
}

if (games_added)
{
gui_log.notice("AddGamesFromDirs added %d new entries", games_added);
}

m_game_list_frame->AddRefreshedSlot([this, paths = std::move(paths), existing = std::move(existing)](std::set<std::string>& claimed_paths)
Expand Down Expand Up @@ -3580,7 +3588,11 @@ void main_window::AddGamesFromDirs(QStringList&& paths)
}
}

if (!paths_added.empty())
if (paths_added.empty())
{
QMessageBox::information(this, tr("Nothing to add!"), tr("Could not find any new software."));
}
else
{
ShowOptionalGamePreparations(tr("Success!"), tr("Successfully added software to game list from path(s)!"), paths_added);
}
Expand Down