Compare commits

...

3 Commits

Author SHA1 Message Date
LillyJadeKatrin
2ab1e6326d
Merge c68549e9ef into 1786e34bd3 2025-06-07 18:27:07 -05:00
LillyJadeKatrin
c68549e9ef AchievementManager - Load unknown games
Prior to this change, any game unrecognized by RetroAchievements would ultimately result in the game being "Closed" by AchievementManager. As a result, if any game was run while in this state without any other closing being done, AchievementManager would simply load it like a new game, despite memory already being accessed.
However, testing and documentation determined that the rcheevos client doesn't actually complain when it fails to hash a game; it just runs this as "Unidentified Game" with RA ID = 0. As such, this change utilizes that in AchievementManager to differentiate between no software running and unidentified software running.

As a result of this, now LoadGame needs to be called for every piece of runnable software, supported format or otherwise. If a supported format is not available, LoadGame can now be called with a nullptr to ensure that rcheevos still properly sets up an unidentified game.
2025-06-07 07:02:24 -04:00
LillyJadeKatrin
fd285f6348 AchievementManager - Minor cleanup
Deleting the unused m_game_data and m_is_game_loaded fields.
2025-05-29 18:35:30 -04:00
4 changed files with 37 additions and 42 deletions

View File

@ -165,17 +165,26 @@ void AchievementManager::LoadGame(const DiscIO::Volume* volume)
{
return;
}
if (volume == nullptr)
{
WARN_LOG_FMT(ACHIEVEMENTS, "Called Load Game without a game.");
return;
}
if (!m_client)
{
ERROR_LOG_FMT(ACHIEVEMENTS,
"Attempted to load game achievements without achievement client initialized.");
return;
}
if (volume == nullptr)
{
WARN_LOG_FMT(ACHIEVEMENTS, "Software format unsupported by AchievementManager.");
if (rc_client_get_game_info(m_client))
{
rc_client_begin_change_media_from_hash(m_client, "", ChangeMediaCallback, NULL);
}
else
{
rc_client_set_read_memory_function(m_client, MemoryVerifier);
rc_client_begin_load_game(m_client, "", LoadGameCallback, NULL);
}
return;
}
rc_client_set_unofficial_enabled(m_client, Config::Get(Config::RA_UNOFFICIAL_ENABLED));
rc_client_set_encore_mode_enabled(m_client, Config::Get(Config::RA_ENCORE_ENABLED));
rc_client_set_spectator_mode_enabled(m_client, Config::Get(Config::RA_SPECTATOR_ENABLED));
@ -598,11 +607,6 @@ rc_client_t* AchievementManager::GetClient()
return m_client;
}
rc_api_fetch_game_data_response_t* AchievementManager::GetGameData()
{
return &m_game_data;
}
const AchievementManager::Badge& AchievementManager::GetGameBadge() const
{
return m_game_badge.data.empty() ? m_default_game_badge : m_game_badge;
@ -736,12 +740,8 @@ void AchievementManager::CloseGame()
if (Config::Get(Config::RA_DISCORD_PRESENCE_ENABLED))
Discord::UpdateDiscordPresence();
if (rc_client_get_game_info(m_client))
{
rc_api_destroy_fetch_game_data_response(&m_game_data);
rc_client_unload_game(m_client);
}
INFO_LOG_FMT(ACHIEVEMENTS, "Game closed.");
m_game_data = {};
}
m_update_callback(UpdatedItems{.all = true});
@ -995,36 +995,30 @@ void AchievementManager::LoadGameCallback(int result, const char* error_message,
OSD::Color::RED);
return;
}
if (result == RC_NO_GAME_LOADED && instance.m_dll_found)
auto* game = rc_client_get_game_info(client);
if (result == RC_OK)
{
// Allow developer tools for unidentified games
rc_client_set_read_memory_function(instance.m_client, MemoryPeeker);
instance.m_system.store(&Core::System::GetInstance(), std::memory_order_release);
WARN_LOG_FMT(ACHIEVEMENTS, "Unrecognized title ready for development.");
OSD::AddMessage("Unrecognized title loaded for development.", OSD::Duration::VERY_LONG,
OSD::Color::YELLOW);
if (!game)
{
ERROR_LOG_FMT(ACHIEVEMENTS, "Failed to retrieve game information from client.");
OSD::AddMessage("Failed to load achievements for this title.", OSD::Duration::VERY_LONG,
OSD::Color::RED);
}
else
{
INFO_LOG_FMT(ACHIEVEMENTS, "Loaded data for game ID {}.", game->id);
instance.m_display_welcome_message = true;
}
}
if (result != RC_OK)
else
{
WARN_LOG_FMT(ACHIEVEMENTS, "Failed to load data for current game.");
OSD::AddMessage("Achievements are not supported for this title.", OSD::Duration::VERY_LONG,
OSD::Color::RED);
return;
}
auto* game = rc_client_get_game_info(client);
if (!game)
{
ERROR_LOG_FMT(ACHIEVEMENTS, "Failed to retrieve game information from client.");
OSD::AddMessage("Failed to load achievements for this title.", OSD::Duration::VERY_LONG,
OSD::Color::RED);
instance.CloseGame();
return;
}
INFO_LOG_FMT(ACHIEVEMENTS, "Loaded data for game ID {}.", game->id);
rc_client_set_read_memory_function(instance.m_client, MemoryPeeker);
instance.m_display_welcome_message = true;
instance.FetchGameBadges();
instance.m_system.store(&Core::System::GetInstance(), std::memory_order_release);
instance.m_update_callback({.all = true});

View File

@ -160,7 +160,6 @@ public:
const Badge& GetPlayerBadge() const;
std::string_view GetGameDisplayName() const;
rc_client_t* GetClient();
rc_api_fetch_game_data_response_t* GetGameData();
const Badge& GetGameBadge() const;
const Badge& GetAchievementBadge(AchievementId id, bool locked) const;
const LeaderboardStatus* GetLeaderboardInfo(AchievementId leaderboard_id);
@ -278,9 +277,6 @@ private:
std::atomic_bool m_background_execution_allowed = true;
Badge m_player_badge;
Hash m_game_hash{};
u32 m_game_id = 0;
rc_api_fetch_game_data_response_t m_game_data{};
bool m_is_game_loaded = false;
Badge m_game_badge;
bool m_display_welcome_message = false;
std::unordered_map<AchievementId, Badge> m_unlocked_badges;

View File

@ -603,6 +603,8 @@ bool CBoot::BootUp(Core::System& system, const Core::CPUThreadGuard& guard,
return false;
}
AchievementManager::GetInstance().LoadGame(nullptr);
SConfig::OnTitleDirectlyBooted(guard);
ppc_state.pc = executable.reader->GetEntryPoint();
@ -635,6 +637,8 @@ bool CBoot::BootUp(Core::System& system, const Core::CPUThreadGuard& guard,
if (!BootNANDTitle(system, nand_title.id))
return false;
AchievementManager::GetInstance().LoadGame(nullptr);
SConfig::OnTitleDirectlyBooted(guard);
return true;
}
@ -661,6 +665,8 @@ bool CBoot::BootUp(Core::System& system, const Core::CPUThreadGuard& guard,
ipl.disc->auto_disc_change_paths);
}
AchievementManager::GetInstance().LoadGame(nullptr);
SConfig::OnTitleDirectlyBooted(guard);
return true;
}
@ -668,6 +674,7 @@ bool CBoot::BootUp(Core::System& system, const Core::CPUThreadGuard& guard,
bool operator()(const BootParameters::DFF& dff) const
{
NOTICE_LOG_FMT(BOOT, "Booting DFF: {}", dff.dff_path);
AchievementManager::GetInstance().LoadGame(nullptr);
return system.GetFifoPlayer().Open(dff.dff_path);
}

View File

@ -479,9 +479,7 @@ bool ESDevice::LaunchPPCTitle(u64 title_id)
if (!Core::IsRunning(system))
return BootstrapPPC();
INFO_LOG_FMT(ACHIEVEMENTS,
"WAD and NAND formats not currently supported by Achievement Manager.");
AchievementManager::GetInstance().CloseGame();
AchievementManager::GetInstance().LoadGame(nullptr);
core_timing.RemoveEvent(s_bootstrap_ppc_for_launch_event);
core_timing.ScheduleEvent(ticks, s_bootstrap_ppc_for_launch_event);