Achievements: Use rc_client as source of truth for HC mode
This commit is contained in:
parent
a0aac8ef17
commit
1bb1354d4e
|
@ -7,6 +7,7 @@
|
|||
#include "achievements_private.h"
|
||||
#include "bios.h"
|
||||
#include "bus.h"
|
||||
#include "cheats.h"
|
||||
#include "cpu_core.h"
|
||||
#include "fullscreen_ui.h"
|
||||
#include "game_list.h"
|
||||
|
@ -144,14 +145,14 @@ static void ReportRCError(int err, fmt::format_string<T...> fmt, T&&... args);
|
|||
static void ClearGameInfo();
|
||||
static void ClearGameHash();
|
||||
static bool TryLoggingInWithToken();
|
||||
static void SetHardcoreMode(bool enabled, bool force_display_message);
|
||||
static void EnableHardcodeMode(bool display_message, bool display_game_summary);
|
||||
static void OnHardcoreModeChanged(bool enabled, bool display_message, bool display_game_summary);
|
||||
static bool IsLoggedInOrLoggingIn();
|
||||
static bool CanEnableHardcoreMode();
|
||||
static void FinishLogin(const rc_client_t* client);
|
||||
static void ShowLoginNotification();
|
||||
static void IdentifyGame(const std::string& path, CDImage* image);
|
||||
static bool IdentifyGame(CDImage* image);
|
||||
static bool IdentifyCurrentGame();
|
||||
static void BeginLoadGame();
|
||||
static void BeginChangeDisc();
|
||||
static void UpdateGameSummary(bool update_progress_database, bool force_update_progress_database);
|
||||
static std::string GetLocalImagePath(const std::string_view image_name, int type);
|
||||
static void DownloadImage(std::string url, std::string cache_path);
|
||||
|
@ -244,7 +245,6 @@ struct PauseMenuAchievementInfo
|
|||
struct State
|
||||
{
|
||||
rc_client_t* client = nullptr;
|
||||
bool hardcore_mode = false;
|
||||
bool has_achievements = false;
|
||||
bool has_leaderboards = false;
|
||||
bool has_rich_presence = false;
|
||||
|
@ -330,9 +330,8 @@ const rc_client_user_game_summary_t& Achievements::GetGameSummary()
|
|||
|
||||
void Achievements::ReportError(std::string_view sv)
|
||||
{
|
||||
std::string error = fmt::format("Achievements error: {}", sv);
|
||||
ERROR_LOG(error.c_str());
|
||||
Host::AddOSDMessage(std::move(error), Host::OSD_CRITICAL_ERROR_DURATION);
|
||||
ERROR_LOG(sv);
|
||||
Host::AddIconOSDWarning(std::string(), ICON_EMOJI_WARNING, std::string(sv), Host::OSD_CRITICAL_ERROR_DURATION);
|
||||
}
|
||||
|
||||
template<typename... T>
|
||||
|
@ -581,7 +580,11 @@ bool Achievements::IsHardcoreModeActive()
|
|||
return RA_HardcoreModeIsActive() != 0;
|
||||
#endif
|
||||
|
||||
return s_state.hardcore_mode;
|
||||
if (!s_state.client)
|
||||
return false;
|
||||
|
||||
const auto lock = GetLock();
|
||||
return rc_client_get_hardcore_enabled(s_state.client);
|
||||
}
|
||||
|
||||
bool Achievements::HasActiveGame()
|
||||
|
@ -651,25 +654,27 @@ bool Achievements::Initialize()
|
|||
if (!CreateClient(&s_state.client, &s_state.http_downloader))
|
||||
return false;
|
||||
|
||||
// Hardcore starts off. We enable it on first boot.
|
||||
s_state.hardcore_mode = false;
|
||||
|
||||
rc_client_set_event_handler(s_state.client, ClientEventHandler);
|
||||
|
||||
rc_client_set_hardcore_enabled(s_state.client, s_state.hardcore_mode);
|
||||
// Hardcore starts off. We enable it on first boot.
|
||||
rc_client_set_hardcore_enabled(s_state.client, false);
|
||||
rc_client_set_encore_mode_enabled(s_state.client, g_settings.achievements_encore_mode);
|
||||
rc_client_set_unofficial_enabled(s_state.client, g_settings.achievements_unofficial_test_mode);
|
||||
rc_client_set_spectator_mode_enabled(s_state.client, g_settings.achievements_spectator_mode);
|
||||
|
||||
// Begin disc identification early, before the login finishes.
|
||||
if (System::IsValid())
|
||||
IdentifyGame(System::GetDiscPath(), nullptr);
|
||||
|
||||
// Start logging in. This can take a while.
|
||||
TryLoggingInWithToken();
|
||||
|
||||
// Hardcore mode isn't enabled when achievements first starts, if a game is already running.
|
||||
if (System::IsValid() && IsLoggedInOrLoggingIn() && g_settings.achievements_hardcore_mode)
|
||||
DisplayHardcoreDeferredMessage();
|
||||
// Are we running a game?
|
||||
if (System::IsValid())
|
||||
{
|
||||
IdentifyCurrentGame();
|
||||
BeginLoadGame();
|
||||
|
||||
// Hardcore mode isn't enabled when achievements first starts, if a game is already running.
|
||||
if (IsLoggedInOrLoggingIn() && g_settings.achievements_hardcore_mode)
|
||||
DisplayHardcoreDeferredMessage();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -753,7 +758,7 @@ void Achievements::UpdateSettings(const Settings& old_config)
|
|||
if (!g_settings.achievements_enabled)
|
||||
{
|
||||
// we're done here
|
||||
Shutdown(false);
|
||||
Shutdown();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -766,26 +771,23 @@ void Achievements::UpdateSettings(const Settings& old_config)
|
|||
|
||||
if (g_settings.achievements_hardcore_mode != old_config.achievements_hardcore_mode)
|
||||
{
|
||||
// Hardcore mode can only be enabled through reset (ResetChallengeMode()).
|
||||
if (s_state.hardcore_mode && !g_settings.achievements_hardcore_mode)
|
||||
{
|
||||
ResetHardcoreMode(false);
|
||||
}
|
||||
else if (!s_state.hardcore_mode && g_settings.achievements_hardcore_mode)
|
||||
{
|
||||
if (HasActiveGame())
|
||||
DisplayHardcoreDeferredMessage();
|
||||
}
|
||||
// Enables have to wait for reset, disables can go through immediately.
|
||||
if (g_settings.achievements_hardcore_mode)
|
||||
DisplayHardcoreDeferredMessage();
|
||||
else
|
||||
DisableHardcoreMode(true, true);
|
||||
}
|
||||
|
||||
// These cannot be modified while a game is loaded, so just toss state and reload.
|
||||
auto lock = GetLock();
|
||||
if (HasActiveGame())
|
||||
{
|
||||
lock.unlock();
|
||||
if (g_settings.achievements_encore_mode != old_config.achievements_encore_mode ||
|
||||
g_settings.achievements_spectator_mode != old_config.achievements_spectator_mode ||
|
||||
g_settings.achievements_unofficial_test_mode != old_config.achievements_unofficial_test_mode)
|
||||
{
|
||||
Shutdown(false);
|
||||
Shutdown();
|
||||
Initialize();
|
||||
return;
|
||||
}
|
||||
|
@ -801,48 +803,27 @@ void Achievements::UpdateSettings(const Settings& old_config)
|
|||
}
|
||||
}
|
||||
|
||||
bool Achievements::Shutdown(bool allow_cancel)
|
||||
void Achievements::Shutdown()
|
||||
{
|
||||
#ifdef ENABLE_RAINTEGRATION
|
||||
if (IsUsingRAIntegration())
|
||||
{
|
||||
if (System::IsValid() && allow_cancel && !RA_ConfirmLoadNewRom(true))
|
||||
return false;
|
||||
|
||||
RA_SetPaused(false);
|
||||
RA_ActivateGame(0);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!IsActive())
|
||||
return true;
|
||||
return;
|
||||
|
||||
auto lock = GetLock();
|
||||
Assert(s_state.client && s_state.http_downloader);
|
||||
|
||||
ClearGameInfo();
|
||||
ClearGameHash();
|
||||
DisableHardcoreMode();
|
||||
DisableHardcoreMode(false, false);
|
||||
UpdateGlyphRanges();
|
||||
CancelHashDatabaseRequests();
|
||||
|
||||
if (s_state.load_game_request)
|
||||
{
|
||||
rc_client_abort_async(s_state.client, s_state.load_game_request);
|
||||
s_state.load_game_request = nullptr;
|
||||
}
|
||||
if (s_state.login_request)
|
||||
{
|
||||
rc_client_abort_async(s_state.client, s_state.login_request);
|
||||
s_state.login_request = nullptr;
|
||||
}
|
||||
|
||||
s_state.hardcore_mode = false;
|
||||
DestroyClient(&s_state.client, &s_state.http_downloader);
|
||||
|
||||
Host::OnAchievementsRefreshed();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Achievements::ClientMessageCallback(const char* message, const rc_client_t* client)
|
||||
|
@ -892,7 +873,7 @@ void Achievements::ClientServerCall(const rc_api_request_t* request, rc_client_s
|
|||
RC_API_SERVER_RESPONSE_RETRYABLE_CLIENT_ERROR) :
|
||||
status_code;
|
||||
rr.body_length = data.size();
|
||||
rr.body = reinterpret_cast<const char*>(data.data());
|
||||
rr.body = data.empty() ? nullptr : reinterpret_cast<const char*>(data.data());
|
||||
|
||||
callback(&rr, callback_data);
|
||||
};
|
||||
|
@ -1147,40 +1128,109 @@ void Achievements::UpdateRichPresence(std::unique_lock<std::recursive_mutex>& lo
|
|||
lock.lock();
|
||||
}
|
||||
|
||||
void Achievements::GameChanged(const std::string& path, CDImage* image, bool booting)
|
||||
void Achievements::OnSystemStarting(CDImage* image, bool disable_hardcore_mode)
|
||||
{
|
||||
std::unique_lock lock(s_state.mutex);
|
||||
|
||||
if (!IsActive())
|
||||
return;
|
||||
|
||||
IdentifyGame(path, image);
|
||||
|
||||
// if we're not logged in, and there's no login request, retry logging in
|
||||
// this'll happen if we had no network connection on startup, but gained it before starting a game.
|
||||
// follow the same order as Initialize() - identify, then log in
|
||||
if (!IsLoggedInOrLoggingIn() && booting)
|
||||
if (!IsLoggedInOrLoggingIn())
|
||||
{
|
||||
WARNING_LOG("Not logged in on game booting, trying again.");
|
||||
TryLoggingInWithToken();
|
||||
}
|
||||
|
||||
// HC should have been disabled, we're now enabling it
|
||||
// only enable hardcore mode if we're logged in, or waiting for a login response
|
||||
AssertMsg(!rc_client_get_hardcore_enabled(s_state.client), "Hardcode mode should be disabled prior to boot");
|
||||
if (!disable_hardcore_mode && g_settings.achievements_hardcore_mode && IsLoggedInOrLoggingIn())
|
||||
EnableHardcodeMode(false, false);
|
||||
|
||||
// now we can finally identify the game
|
||||
IdentifyGame(image);
|
||||
BeginLoadGame();
|
||||
}
|
||||
|
||||
void Achievements::IdentifyGame(const std::string& path, CDImage* image)
|
||||
void Achievements::OnSystemDestroyed()
|
||||
{
|
||||
if (s_state.game_path == path)
|
||||
ClearGameInfo();
|
||||
ClearGameHash();
|
||||
DisableHardcoreMode(false, false);
|
||||
UpdateGlyphRanges();
|
||||
}
|
||||
|
||||
void Achievements::OnSystemPaused(bool paused)
|
||||
{
|
||||
#ifdef ENABLE_RAINTEGRATION
|
||||
if (IsUsingRAIntegration())
|
||||
RA_SetPaused(paused);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Achievements::OnSystemReset()
|
||||
{
|
||||
const auto lock = GetLock();
|
||||
if (!IsActive())
|
||||
return;
|
||||
|
||||
#ifdef ENABLE_RAINTEGRATION
|
||||
if (IsUsingRAIntegration())
|
||||
{
|
||||
WARNING_LOG("Game path is unchanged.");
|
||||
RA_OnReset();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
std::unique_ptr<CDImage> temp_image;
|
||||
if (!path.empty() && !image)
|
||||
// Do we need to enable hardcore mode?
|
||||
if (System::IsValid() && g_settings.achievements_hardcore_mode && !rc_client_get_hardcore_enabled(s_state.client))
|
||||
{
|
||||
temp_image = CDImage::Open(path.c_str(), g_settings.cdrom_load_image_patches, nullptr);
|
||||
image = temp_image.get();
|
||||
if (!temp_image)
|
||||
ERROR_LOG("Failed to open temporary CD image '{}'", path);
|
||||
// This will raise the silly reset event, but we can safely ignore that since we're immediately resetting the client
|
||||
DEV_LOG("Enabling hardcore mode after reset");
|
||||
EnableHardcodeMode(true, true);
|
||||
}
|
||||
|
||||
DEV_LOG("Reset client");
|
||||
rc_client_reset(s_state.client);
|
||||
}
|
||||
|
||||
void Achievements::GameChanged(CDImage* image)
|
||||
{
|
||||
std::unique_lock lock(s_state.mutex);
|
||||
|
||||
if (!IsActive())
|
||||
return;
|
||||
|
||||
// disc changed?
|
||||
if (!IdentifyGame(image))
|
||||
return;
|
||||
|
||||
// cancel previous requests
|
||||
if (s_state.load_game_request)
|
||||
{
|
||||
rc_client_abort_async(s_state.client, s_state.load_game_request);
|
||||
s_state.load_game_request = nullptr;
|
||||
}
|
||||
|
||||
// Use a hash that will never match if we removed the disc. See rc_client_begin_change_media().
|
||||
TinyString game_hash_str;
|
||||
if (s_state.game_hash.has_value())
|
||||
game_hash_str = GameHashToString(s_state.game_hash.value());
|
||||
else
|
||||
game_hash_str = "[NO HASH]";
|
||||
|
||||
s_state.load_game_request = rc_client_begin_change_media_from_hash(
|
||||
s_state.client, game_hash_str.c_str(), ClientLoadGameCallback, reinterpret_cast<void*>(static_cast<uintptr_t>(1)));
|
||||
}
|
||||
|
||||
bool Achievements::IdentifyGame(CDImage* image)
|
||||
{
|
||||
if (s_state.game_path == image->GetPath())
|
||||
{
|
||||
WARNING_LOG("Game path is unchanged.");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::optional<GameHash> game_hash;
|
||||
|
@ -1189,63 +1239,64 @@ void Achievements::IdentifyGame(const std::string& path, CDImage* image)
|
|||
u32 bytes_hashed;
|
||||
game_hash = GetGameHash(image, &bytes_hashed);
|
||||
if (game_hash.has_value())
|
||||
INFO_LOG("RA Hash: {} ({} bytes hashed)", GameHashToString(game_hash.value()), bytes_hashed);
|
||||
{
|
||||
INFO_COLOR_LOG(StrongOrange, "RA Hash: {} ({} bytes hashed)", GameHashToString(game_hash.value()), bytes_hashed);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we are starting with this game and it's bad, notify the user that this is why.
|
||||
Host::AddIconOSDWarning(
|
||||
"AchievementsHashFailed", ICON_EMOJI_WARNING,
|
||||
TRANSLATE_STR("Achievements", "Failed to read executable from disc. Achievements disabled."),
|
||||
Host::OSD_ERROR_DURATION);
|
||||
}
|
||||
}
|
||||
|
||||
s_state.game_path = image ? image->GetPath() : std::string();
|
||||
|
||||
if (s_state.game_hash == game_hash)
|
||||
{
|
||||
// only the path has changed - different format/save state/etc.
|
||||
INFO_LOG("Detected path change from '{}' to '{}'", s_state.game_path, path);
|
||||
s_state.game_path = path;
|
||||
return;
|
||||
INFO_LOG("Detected path change to '{}'", s_state.game_path);
|
||||
s_state.game_path = image->GetPath();
|
||||
return false;
|
||||
}
|
||||
|
||||
ClearGameHash();
|
||||
s_state.game_path = path;
|
||||
s_state.game_hash = std::move(game_hash);
|
||||
s_state.game_hash = game_hash;
|
||||
|
||||
#ifdef ENABLE_RAINTEGRATION
|
||||
if (IsUsingRAIntegration())
|
||||
{
|
||||
RAIntegration::GameChanged();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// shouldn't have a load game request when we're not logged in.
|
||||
Assert(IsLoggedInOrLoggingIn() || !s_state.load_game_request);
|
||||
return true;
|
||||
}
|
||||
|
||||
// bail out if we're not logged in, just save the hash
|
||||
if (!IsLoggedInOrLoggingIn())
|
||||
bool Achievements::IdentifyCurrentGame()
|
||||
{
|
||||
DebugAssert(System::IsValid());
|
||||
|
||||
// this crap is only needed because we can't grab the image from the reader...
|
||||
std::unique_ptr<CDImage> temp_image;
|
||||
if (const std::string& disc_path = System::GetDiscPath(); !disc_path.empty())
|
||||
{
|
||||
INFO_LOG("Skipping load game because we're not logged in.");
|
||||
DisableHardcoreMode();
|
||||
return;
|
||||
Error error;
|
||||
temp_image = CDImage::Open(disc_path.c_str(), g_settings.cdrom_load_image_patches, &error);
|
||||
if (!temp_image)
|
||||
ERROR_LOG("Failed to open disc for late game identification: {}", error.GetDescription());
|
||||
}
|
||||
|
||||
if (!rc_client_is_game_loaded(s_state.client))
|
||||
BeginLoadGame();
|
||||
else
|
||||
BeginChangeDisc();
|
||||
return IdentifyGame(temp_image.get());
|
||||
}
|
||||
|
||||
void Achievements::BeginLoadGame()
|
||||
{
|
||||
ClearGameInfo();
|
||||
DebugAssert(IsLoggedInOrLoggingIn());
|
||||
|
||||
if (!s_state.game_hash.has_value())
|
||||
{
|
||||
// when we're booting the bios, this will fail
|
||||
if (!s_state.game_path.empty())
|
||||
{
|
||||
Host::AddKeyedOSDMessage(
|
||||
"retroachievements_disc_read_failed",
|
||||
TRANSLATE_STR("Achievements", "Failed to read executable from disc. Achievements disabled."),
|
||||
Host::OSD_ERROR_DURATION);
|
||||
}
|
||||
|
||||
DisableHardcoreMode();
|
||||
UpdateGlyphRanges();
|
||||
// no need to go through ClientLoadGameCallback, just bail out straight away
|
||||
DisableHardcoreMode(false, false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1253,37 +1304,6 @@ void Achievements::BeginLoadGame()
|
|||
ClientLoadGameCallback, nullptr);
|
||||
}
|
||||
|
||||
void Achievements::BeginChangeDisc()
|
||||
{
|
||||
// cancel previous requests
|
||||
if (s_state.load_game_request)
|
||||
{
|
||||
rc_client_abort_async(s_state.client, s_state.load_game_request);
|
||||
s_state.load_game_request = nullptr;
|
||||
}
|
||||
|
||||
if (!s_state.game_hash.has_value())
|
||||
{
|
||||
// when we're booting the bios, this will fail
|
||||
if (!s_state.game_path.empty())
|
||||
{
|
||||
Host::AddKeyedOSDMessage(
|
||||
"retroachievements_disc_read_failed",
|
||||
TRANSLATE_STR("Achievements", "Failed to read executable from disc. Achievements disabled."),
|
||||
Host::OSD_ERROR_DURATION);
|
||||
}
|
||||
|
||||
ClearGameInfo();
|
||||
DisableHardcoreMode();
|
||||
UpdateGlyphRanges();
|
||||
return;
|
||||
}
|
||||
|
||||
s_state.load_game_request =
|
||||
rc_client_begin_change_media_from_hash(s_state.client, GameHashToString(s_state.game_hash.value()),
|
||||
ClientLoadGameCallback, reinterpret_cast<void*>(static_cast<uintptr_t>(1)));
|
||||
}
|
||||
|
||||
void Achievements::ClientLoadGameCallback(int result, const char* error_message, rc_client_t* client, void* userdata)
|
||||
{
|
||||
const bool was_disc_change = (userdata != nullptr);
|
||||
|
@ -1300,7 +1320,7 @@ void Achievements::ClientLoadGameCallback(int result, const char* error_message,
|
|||
UpdateGlyphRanges();
|
||||
}
|
||||
|
||||
DisableHardcoreMode();
|
||||
DisableHardcoreMode(false, false);
|
||||
return;
|
||||
}
|
||||
else if (result == RC_LOGIN_REQUIRED)
|
||||
|
@ -1309,6 +1329,14 @@ void Achievements::ClientLoadGameCallback(int result, const char* error_message,
|
|||
// Once we've done so, we'll reload the game.
|
||||
return;
|
||||
}
|
||||
else if (result == RC_HARDCORE_DISABLED)
|
||||
{
|
||||
if (error_message)
|
||||
ReportError(error_message);
|
||||
|
||||
OnHardcoreModeChanged(false, true, false);
|
||||
return;
|
||||
}
|
||||
else if (result != RC_OK)
|
||||
{
|
||||
ReportFmtError("Loading game failed: {}", error_message);
|
||||
|
@ -1318,16 +1346,9 @@ void Achievements::ClientLoadGameCallback(int result, const char* error_message,
|
|||
UpdateGlyphRanges();
|
||||
}
|
||||
|
||||
DisableHardcoreMode();
|
||||
DisableHardcoreMode(false, false);
|
||||
return;
|
||||
}
|
||||
else if (result == RC_HARDCORE_DISABLED)
|
||||
{
|
||||
if (error_message)
|
||||
ReportError(error_message);
|
||||
|
||||
DisableHardcoreMode();
|
||||
}
|
||||
|
||||
const rc_client_game_t* info = rc_client_get_game_info(s_state.client);
|
||||
if (!info)
|
||||
|
@ -1339,7 +1360,7 @@ void Achievements::ClientLoadGameCallback(int result, const char* error_message,
|
|||
UpdateGlyphRanges();
|
||||
}
|
||||
|
||||
DisableHardcoreMode();
|
||||
DisableHardcoreMode(false, false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1349,13 +1370,10 @@ void Achievements::ClientLoadGameCallback(int result, const char* error_message,
|
|||
// Only display summary if the game title has changed across discs.
|
||||
const bool display_summary = (s_state.game_id != info->id || s_state.game_title != info->title);
|
||||
|
||||
// If the game has a RetroAchievements entry but no achievements or leaderboards,
|
||||
// enforcing hardcore mode is pointless.
|
||||
if (!has_achievements && !has_leaderboards)
|
||||
DisableHardcoreMode();
|
||||
|
||||
// We should have matched hardcore mode state.
|
||||
Assert(s_state.hardcore_mode == (rc_client_get_hardcore_enabled(client) != 0));
|
||||
// If the game has a RetroAchievements entry but no achievements or leaderboards, enforcing hardcore mode
|
||||
// is pointless. Have to re-query leaderboards because hidden should still trip HC.
|
||||
if (!has_achievements && !rc_client_has_leaderboards(client, true))
|
||||
DisableHardcoreMode(false, false);
|
||||
|
||||
s_state.game_id = info->id;
|
||||
s_state.game_title = info->title;
|
||||
|
@ -1469,7 +1487,7 @@ void Achievements::DisplayAchievementSummary()
|
|||
|
||||
void Achievements::DisplayHardcoreDeferredMessage()
|
||||
{
|
||||
if (g_settings.achievements_hardcore_mode && !s_state.hardcore_mode && System::IsValid())
|
||||
if (g_settings.achievements_hardcore_mode && System::IsValid())
|
||||
{
|
||||
GPUThread::RunOnThread([]() {
|
||||
if (!FullscreenUI::Initialize())
|
||||
|
@ -1484,12 +1502,7 @@ void Achievements::DisplayHardcoreDeferredMessage()
|
|||
|
||||
void Achievements::HandleResetEvent(const rc_client_event_t* event)
|
||||
{
|
||||
// We handle system resets ourselves, but still need to reset the client's state.
|
||||
INFO_LOG("Resetting runtime due to reset event");
|
||||
rc_client_reset(s_state.client);
|
||||
|
||||
if (HasActiveGame())
|
||||
UpdateGameSummary(false, false);
|
||||
WARNING_LOG("Ignoring RC_CLIENT_EVENT_RESET.");
|
||||
}
|
||||
|
||||
void Achievements::HandleUnlockEvent(const rc_client_event_t* event)
|
||||
|
@ -1806,32 +1819,17 @@ void Achievements::HandleServerReconnectedEvent(const rc_client_event_t* event)
|
|||
});
|
||||
}
|
||||
|
||||
void Achievements::Reset()
|
||||
void Achievements::EnableHardcodeMode(bool display_message, bool display_game_summary)
|
||||
{
|
||||
#ifdef ENABLE_RAINTEGRATION
|
||||
if (IsUsingRAIntegration())
|
||||
{
|
||||
RA_OnReset();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!IsActive())
|
||||
DebugAssert(IsActive());
|
||||
if (rc_client_get_hardcore_enabled(s_state.client))
|
||||
return;
|
||||
|
||||
DEV_LOG("Reset client");
|
||||
rc_client_reset(s_state.client);
|
||||
rc_client_set_hardcore_enabled(s_state.client, true);
|
||||
OnHardcoreModeChanged(true, display_message, display_game_summary);
|
||||
}
|
||||
|
||||
void Achievements::OnSystemPaused(bool paused)
|
||||
{
|
||||
#ifdef ENABLE_RAINTEGRATION
|
||||
if (IsUsingRAIntegration())
|
||||
RA_SetPaused(paused);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Achievements::DisableHardcoreMode()
|
||||
void Achievements::DisableHardcoreMode(bool show_message, bool display_game_summary)
|
||||
{
|
||||
if (!IsActive())
|
||||
return;
|
||||
|
@ -1846,43 +1844,19 @@ void Achievements::DisableHardcoreMode()
|
|||
}
|
||||
#endif
|
||||
|
||||
if (!s_state.hardcore_mode)
|
||||
return;
|
||||
|
||||
SetHardcoreMode(false, true);
|
||||
}
|
||||
|
||||
bool Achievements::ResetHardcoreMode(bool is_booting)
|
||||
{
|
||||
if (!IsActive())
|
||||
return false;
|
||||
|
||||
const auto lock = GetLock();
|
||||
|
||||
// If we're not logged in, don't apply hardcore mode restrictions.
|
||||
// If we later log in, we'll start with it off anyway.
|
||||
const bool wanted_hardcore_mode = (IsLoggedInOrLoggingIn() || s_state.load_game_request) &&
|
||||
(HasActiveGame() || s_state.load_game_request) &&
|
||||
g_settings.achievements_hardcore_mode;
|
||||
if (s_state.hardcore_mode == wanted_hardcore_mode)
|
||||
return false;
|
||||
|
||||
if (!is_booting && wanted_hardcore_mode && !CanEnableHardcoreMode())
|
||||
return false;
|
||||
|
||||
SetHardcoreMode(wanted_hardcore_mode, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Achievements::SetHardcoreMode(bool enabled, bool force_display_message)
|
||||
{
|
||||
if (enabled == s_state.hardcore_mode)
|
||||
if (!rc_client_get_hardcore_enabled(s_state.client))
|
||||
return;
|
||||
|
||||
// new mode
|
||||
s_state.hardcore_mode = enabled;
|
||||
rc_client_set_hardcore_enabled(s_state.client, false);
|
||||
OnHardcoreModeChanged(false, show_message, display_game_summary);
|
||||
}
|
||||
|
||||
if (System::IsValid() && (HasActiveGame() || force_display_message))
|
||||
void Achievements::OnHardcoreModeChanged(bool enabled, bool display_message, bool display_game_summary)
|
||||
{
|
||||
INFO_COLOR_LOG(StrongYellow, "Hardcore mode/restrictions are now {}.", enabled ? "ACTIVE" : "inactive");
|
||||
|
||||
if (System::IsValid() && display_message)
|
||||
{
|
||||
GPUThread::RunOnThread([enabled]() {
|
||||
if (!FullscreenUI::Initialize())
|
||||
|
@ -1895,17 +1869,28 @@ void Achievements::SetHardcoreMode(bool enabled, bool force_display_message)
|
|||
});
|
||||
}
|
||||
|
||||
rc_client_set_hardcore_enabled(s_state.client, enabled);
|
||||
DebugAssert((rc_client_get_hardcore_enabled(s_state.client) != 0) == enabled);
|
||||
if (HasActiveGame())
|
||||
if (HasActiveGame() && display_game_summary)
|
||||
{
|
||||
UpdateGameSummary(true, true);
|
||||
DisplayAchievementSummary();
|
||||
}
|
||||
|
||||
DebugAssert((rc_client_get_hardcore_enabled(s_state.client) != 0) == enabled);
|
||||
|
||||
// Reload setting to permit cheating-like things if we were just disabled.
|
||||
if (!enabled && System::IsValid())
|
||||
if (System::IsValid())
|
||||
{
|
||||
// Make sure a pre-existing cheat file hasn't been loaded when resetting after enabling HC mode.
|
||||
Cheats::ReloadCheats(true, true, false, true, true);
|
||||
|
||||
// Defer settings update in case something is using it.
|
||||
Host::RunOnCPUThread([]() { System::ApplySettings(false); });
|
||||
}
|
||||
else if (System::GetState() == System::State::Starting)
|
||||
{
|
||||
// Initial HC enable, activate restrictions.
|
||||
System::ApplySettings(false);
|
||||
}
|
||||
|
||||
// Toss away UI state, because it's invalid now
|
||||
ClearUIState();
|
||||
|
@ -1947,9 +1932,6 @@ bool Achievements::DoState(StateWrapper& sw)
|
|||
GPUThread::RunOnThread([]() { FullscreenUI::CloseLoadingScreen(); });
|
||||
}
|
||||
|
||||
// loading an old state without cheevos, so reset the runtime
|
||||
Achievements::Reset();
|
||||
|
||||
u32 data_size = 0;
|
||||
sw.DoEx(&data_size, REQUIRED_VERSION, 0u);
|
||||
if (data_size == 0)
|
||||
|
@ -2096,12 +2078,6 @@ bool Achievements::IsLoggedInOrLoggingIn()
|
|||
return (rc_client_get_user_info(s_state.client) != nullptr || s_state.login_request);
|
||||
}
|
||||
|
||||
bool Achievements::CanEnableHardcoreMode()
|
||||
{
|
||||
// have to re-query leaderboards because hidden should still trip HC
|
||||
return (s_state.load_game_request || s_state.has_achievements || rc_client_has_leaderboards(s_state.client, true));
|
||||
}
|
||||
|
||||
bool Achievements::Login(const char* username, const char* password, Error* error)
|
||||
{
|
||||
auto lock = GetLock();
|
||||
|
@ -2145,7 +2121,10 @@ bool Achievements::Login(const char* username, const char* password, Error* erro
|
|||
|
||||
// If we were't a temporary client, get the game loaded.
|
||||
if (System::IsValid() && !is_temporary_client)
|
||||
{
|
||||
IdentifyCurrentGame();
|
||||
BeginLoadGame();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -2223,9 +2202,6 @@ void Achievements::ClientLoginWithTokenCallback(int result, const char* error_me
|
|||
}
|
||||
|
||||
FinishLogin(client);
|
||||
|
||||
if (System::IsValid())
|
||||
BeginLoadGame();
|
||||
}
|
||||
|
||||
void Achievements::FinishLogin(const rc_client_t* client)
|
||||
|
@ -2338,7 +2314,7 @@ void Achievements::Logout()
|
|||
ClearProgressDatabase();
|
||||
}
|
||||
|
||||
bool Achievements::ConfirmSystemReset()
|
||||
bool Achievements::ConfirmGameChange()
|
||||
{
|
||||
#ifdef ENABLE_RAINTEGRATION
|
||||
if (IsUsingRAIntegration())
|
||||
|
@ -2364,7 +2340,7 @@ bool Achievements::ConfirmHardcoreModeDisable(const char* trigger)
|
|||
if (!confirmed)
|
||||
return false;
|
||||
|
||||
DisableHardcoreMode();
|
||||
DisableHardcoreMode(true, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2374,7 +2350,7 @@ void Achievements::ConfirmHardcoreModeDisableAsync(const char* trigger, std::fun
|
|||
// don't run the callback in the middle of rendering the UI
|
||||
Host::RunOnCPUThread([callback = std::move(callback), res]() {
|
||||
if (res)
|
||||
DisableHardcoreMode();
|
||||
DisableHardcoreMode(true, true);
|
||||
callback(res);
|
||||
});
|
||||
};
|
||||
|
@ -2826,7 +2802,7 @@ void Achievements::DrawAchievementsWindow()
|
|||
using ImGuiFullscreen::RenderShadowedTextClipped;
|
||||
using ImGuiFullscreen::UIStyle;
|
||||
|
||||
auto lock = Achievements::GetLock();
|
||||
const auto lock = Achievements::GetLock();
|
||||
|
||||
// achievements can get turned off via the main UI
|
||||
if (!s_state.achievement_list)
|
||||
|
@ -2886,7 +2862,7 @@ void Achievements::DrawAchievementsWindow()
|
|||
const ImRect title_bb(ImVec2(left, top), ImVec2(right, top + UIStyle.LargeFont->FontSize));
|
||||
text.assign(s_state.game_title);
|
||||
|
||||
if (s_state.hardcore_mode)
|
||||
if (rc_client_get_hardcore_enabled(s_state.client))
|
||||
text.append(TRANSLATE_SV("Achievements", " (Hardcore Mode)"));
|
||||
|
||||
top += UIStyle.LargeFont->FontSize + spacing;
|
||||
|
|
|
@ -77,18 +77,24 @@ bool Initialize();
|
|||
/// Updates achievements settings.
|
||||
void UpdateSettings(const Settings& old_config);
|
||||
|
||||
/// Resets the internal state of all achievement tracking. Call on system reset.
|
||||
void Reset();
|
||||
/// Shuts down the RetroAchievements client.
|
||||
void Shutdown();
|
||||
|
||||
/// Called when the system is being reset. If it returns false, the reset should be aborted.
|
||||
bool ConfirmSystemReset();
|
||||
/// Called when the system is start. Engages hardcore mode if enabled.
|
||||
void OnSystemStarting(CDImage* image, bool disable_hardcore_mode);
|
||||
|
||||
/// Called when the system is being shut down. If Shutdown() returns false, the shutdown should be aborted.
|
||||
bool Shutdown(bool allow_cancel);
|
||||
/// Called when the system is shutting down. If this returns false, the shutdown should be aborted.
|
||||
void OnSystemDestroyed();
|
||||
|
||||
/// Called when the system is being reset. Resets the internal state of all achievement tracking.
|
||||
void OnSystemReset();
|
||||
|
||||
/// Called when the system is being paused and resumed.
|
||||
void OnSystemPaused(bool paused);
|
||||
|
||||
/// Called when the system changes game.
|
||||
void GameChanged(CDImage* image);
|
||||
|
||||
/// Called once a frame at vsync time on the CPU thread.
|
||||
void FrameUpdate();
|
||||
|
||||
|
@ -108,14 +114,8 @@ bool Login(const char* username, const char* password, Error* error);
|
|||
/// Logs out of RetroAchievements, clearing any credentials.
|
||||
void Logout();
|
||||
|
||||
/// Called when the system changes game, or is booting.
|
||||
void GameChanged(const std::string& path, CDImage* image, bool booting);
|
||||
|
||||
/// Re-enables hardcore mode if it is enabled in the settings.
|
||||
bool ResetHardcoreMode(bool is_booting);
|
||||
|
||||
/// Forces hardcore mode off until next reset.
|
||||
void DisableHardcoreMode();
|
||||
void DisableHardcoreMode(bool show_message, bool display_game_summary);
|
||||
|
||||
/// Prompts the user to disable hardcore mode, if they agree, returns true.
|
||||
bool ConfirmHardcoreModeDisable(const char* trigger);
|
||||
|
@ -127,6 +127,9 @@ bool IsHardcoreModeActive();
|
|||
/// RAIntegration only exists for Windows, so no point checking it on other platforms.
|
||||
bool IsUsingRAIntegration();
|
||||
|
||||
/// Hook for RAIntegration to confirm reset/shutdown.
|
||||
bool ConfirmGameChange();
|
||||
|
||||
/// Returns true if the achievement system is active. Achievements can be active without a valid client.
|
||||
bool IsActive();
|
||||
|
||||
|
|
|
@ -542,7 +542,7 @@ void System::CPUThreadShutdown()
|
|||
ShutdownDiscordPresence();
|
||||
#endif
|
||||
|
||||
Achievements::Shutdown(false);
|
||||
Achievements::Shutdown();
|
||||
|
||||
InputManager::CloseSources();
|
||||
|
||||
|
@ -1349,12 +1349,17 @@ void System::ApplySettings(bool display_osd_messages)
|
|||
LoadSettings(display_osd_messages);
|
||||
|
||||
// If we've disabled/enabled game settings, we need to reload without it.
|
||||
// Also reload cheats when safe mode is toggled, because patches might change.
|
||||
if (g_settings.apply_game_settings != old_settings.apply_game_settings)
|
||||
{
|
||||
UpdateGameSettingsLayer();
|
||||
LoadSettings(display_osd_messages);
|
||||
}
|
||||
else if (g_settings.achievements_hardcore_mode != old_settings.achievements_hardcore_mode)
|
||||
{
|
||||
// Hardcore mode enabled/disabled. May need to disable restrictions.
|
||||
Achievements::UpdateSettings(old_settings);
|
||||
LoadSettings(display_osd_messages);
|
||||
}
|
||||
|
||||
CheckForSettingsChanges(old_settings);
|
||||
Host::CheckForSettingsChanges(old_settings);
|
||||
|
@ -1546,19 +1551,9 @@ void System::UpdateInputSettingsLayer(std::string input_profile_name, std::uniqu
|
|||
|
||||
void System::ResetSystem()
|
||||
{
|
||||
if (!IsValid())
|
||||
if (!IsValid() || !Achievements::ConfirmGameChange())
|
||||
return;
|
||||
|
||||
if (!Achievements::ConfirmSystemReset())
|
||||
return;
|
||||
|
||||
if (Achievements::ResetHardcoreMode(false))
|
||||
{
|
||||
// Make sure a pre-existing cheat file hasn't been loaded when resetting after enabling HC mode.
|
||||
Cheats::ReloadCheats(true, true, false, true, true);
|
||||
ApplySettings(false);
|
||||
}
|
||||
|
||||
InternalReset();
|
||||
|
||||
// Reset boot mode/reload BIOS if needed. Preserve exe/psf boot.
|
||||
|
@ -1731,6 +1726,7 @@ bool System::BootSystem(SystemBootParameters parameters, Error* error)
|
|||
|
||||
// Update running game, this will apply settings as well.
|
||||
UpdateRunningGame(disc ? disc->GetPath() : parameters.filename, disc.get(), true);
|
||||
Achievements::OnSystemStarting(disc.get(), parameters.disable_achievements_hardcore_mode);
|
||||
|
||||
// Determine console region. Has to be done here, because gamesettings can override it.
|
||||
s_state.region = (g_settings.region == ConsoleRegion::Auto) ? auto_console_region : g_settings.region;
|
||||
|
@ -1755,13 +1751,6 @@ bool System::BootSystem(SystemBootParameters parameters, Error* error)
|
|||
// Achievement hardcore checks before committing to anything.
|
||||
if (disc)
|
||||
{
|
||||
// Check for resuming with hardcore mode.
|
||||
const bool hc_mode_was_enabled = Achievements::IsHardcoreModeActive();
|
||||
if (parameters.disable_achievements_hardcore_mode)
|
||||
Achievements::DisableHardcoreMode();
|
||||
else
|
||||
Achievements::ResetHardcoreMode(true);
|
||||
|
||||
if ((!parameters.save_state.empty() || !exe_override.empty()) && Achievements::IsHardcoreModeActive())
|
||||
{
|
||||
const bool is_exe_override_boot = parameters.save_state.empty();
|
||||
|
@ -1794,10 +1783,6 @@ bool System::BootSystem(SystemBootParameters parameters, Error* error)
|
|||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Need to reinit things like emulation speed, cpu overclock, etc.
|
||||
if (Achievements::IsHardcoreModeActive() != hc_mode_was_enabled)
|
||||
ApplySettings(false);
|
||||
}
|
||||
|
||||
// Are we fast booting? Must be checked after updating game settings.
|
||||
|
@ -1994,6 +1979,7 @@ void System::DestroySystem()
|
|||
CPU::Shutdown();
|
||||
Bus::Shutdown();
|
||||
TimingEvents::Shutdown();
|
||||
Achievements::OnSystemDestroyed();
|
||||
ClearRunningGame();
|
||||
GPUThread::DestroyGPUBackend();
|
||||
|
||||
|
@ -2043,8 +2029,6 @@ void System::ClearRunningGame()
|
|||
Host::OnGameChanged(s_state.running_game_path, s_state.running_game_serial, s_state.running_game_title,
|
||||
s_state.running_game_hash);
|
||||
|
||||
Achievements::GameChanged(s_state.running_game_path, nullptr, false);
|
||||
|
||||
UpdateRichPresence(true);
|
||||
}
|
||||
|
||||
|
@ -2780,7 +2764,7 @@ void System::InternalReset()
|
|||
MDEC::Reset();
|
||||
SIO::Reset();
|
||||
PCDrv::Reset();
|
||||
Achievements::Reset();
|
||||
Achievements::OnSystemReset();
|
||||
s_state.frame_number = 1;
|
||||
s_state.internal_frame_number = 0;
|
||||
}
|
||||
|
@ -2963,7 +2947,7 @@ bool System::LoadStateFromBuffer(const SaveStateBuffer& buffer, Error* error, bo
|
|||
ClearMemorySaveStates(false, false);
|
||||
|
||||
// Updating game/loading settings can turn on hardcore mode. Catch this.
|
||||
Achievements::DisableHardcoreMode();
|
||||
Achievements::DisableHardcoreMode(true, true);
|
||||
|
||||
return LoadStateDataFromBuffer(buffer.state_data.cspan(0, buffer.state_size), buffer.version, error, update_display);
|
||||
}
|
||||
|
@ -4205,18 +4189,18 @@ void System::UpdateRunningGame(const std::string& path, CDImage* image, bool boo
|
|||
}
|
||||
|
||||
UpdateGameSettingsLayer();
|
||||
ApplySettings(true);
|
||||
|
||||
if (!IsReplayingGPUDump())
|
||||
{
|
||||
Achievements::GameChanged(s_state.running_game_path, image, booting);
|
||||
|
||||
// Cheats are loaded later in Initialize().
|
||||
if (!booting)
|
||||
{
|
||||
Achievements::GameChanged(image);
|
||||
Cheats::ReloadCheats(true, true, false, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
ApplySettings(true);
|
||||
|
||||
if (s_state.running_game_serial != prev_serial)
|
||||
{
|
||||
GPUThread::SetGameSerial(s_state.running_game_serial);
|
||||
|
|
|
@ -56,7 +56,7 @@ void AchievementLoginDialog::cancelClicked()
|
|||
{
|
||||
Host::RunOnCPUThread([]() {
|
||||
if (System::IsValid() && !Achievements::HasActiveGame())
|
||||
Achievements::DisableHardcoreMode();
|
||||
Achievements::DisableHardcoreMode(false, false);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -138,9 +138,11 @@ void AchievementSettingsWidget::onHardcoreModeStateChanged()
|
|||
return;
|
||||
|
||||
// don't bother prompting if the game doesn't have achievements
|
||||
auto lock = Achievements::GetLock();
|
||||
if (!Achievements::HasActiveGame())
|
||||
return;
|
||||
{
|
||||
auto lock = Achievements::GetLock();
|
||||
if (!Achievements::HasActiveGame())
|
||||
return;
|
||||
}
|
||||
|
||||
if (QMessageBox::question(
|
||||
QtUtils::GetRootWidget(this), tr("Reset System"),
|
||||
|
|
|
@ -104,8 +104,10 @@ MainWindow* g_main_window = nullptr;
|
|||
|
||||
// UI thread VM validity.
|
||||
static bool s_disable_window_rounded_corners = false;
|
||||
static bool s_system_starting = false;
|
||||
static bool s_system_valid = false;
|
||||
static bool s_system_paused = false;
|
||||
static bool s_achievements_hardcore_mode = false;
|
||||
static bool s_fullscreen_ui_started = false;
|
||||
static std::atomic_uint32_t s_system_locked{false};
|
||||
static QString s_current_game_title;
|
||||
|
@ -170,6 +172,7 @@ void MainWindow::initialize()
|
|||
m_ui.setupUi(this);
|
||||
setupAdditionalUi();
|
||||
updateToolbarActions();
|
||||
updateEmulationActions(false, false, false);
|
||||
connectSignals();
|
||||
|
||||
restoreStateFromConfig();
|
||||
|
@ -515,18 +518,20 @@ void MainWindow::onMouseModeRequested(bool relative_mode, bool hide_cursor)
|
|||
|
||||
void MainWindow::onSystemStarting()
|
||||
{
|
||||
s_system_starting = true;
|
||||
s_system_valid = false;
|
||||
s_system_paused = false;
|
||||
|
||||
switchToEmulationView();
|
||||
updateEmulationActions(true, false, Achievements::IsHardcoreModeActive());
|
||||
updateEmulationActions(true, false, s_achievements_hardcore_mode);
|
||||
}
|
||||
|
||||
void MainWindow::onSystemStarted()
|
||||
{
|
||||
m_was_disc_change_request = false;
|
||||
s_system_starting = false;
|
||||
s_system_valid = true;
|
||||
updateEmulationActions(false, true, Achievements::IsHardcoreModeActive());
|
||||
updateEmulationActions(false, true, s_achievements_hardcore_mode);
|
||||
updateWindowTitle();
|
||||
updateStatusBarWidgetVisibility();
|
||||
updateDisplayWidgetCursor();
|
||||
|
@ -574,6 +579,7 @@ void MainWindow::onSystemDestroyed()
|
|||
m_ui.actionPause->setChecked(false);
|
||||
}
|
||||
|
||||
s_system_starting = false;
|
||||
s_system_valid = false;
|
||||
s_system_paused = false;
|
||||
|
||||
|
@ -585,7 +591,7 @@ void MainWindow::onSystemDestroyed()
|
|||
return;
|
||||
}
|
||||
|
||||
updateEmulationActions(false, false, Achievements::IsHardcoreModeActive());
|
||||
updateEmulationActions(false, false, s_achievements_hardcore_mode);
|
||||
if (m_display_widget)
|
||||
updateDisplayWidgetCursor();
|
||||
else
|
||||
|
@ -770,7 +776,7 @@ void MainWindow::recreate()
|
|||
if (was_display_created)
|
||||
{
|
||||
g_emu_thread->setSurfaceless(false);
|
||||
g_main_window->updateEmulationActions(false, System::IsValid(), Achievements::IsHardcoreModeActive());
|
||||
g_main_window->updateEmulationActions(false, s_system_valid, s_achievements_hardcore_mode);
|
||||
g_main_window->onFullscreenUIStartedOrStopped(s_fullscreen_ui_started);
|
||||
}
|
||||
|
||||
|
@ -821,7 +827,6 @@ void MainWindow::populateGameListContextMenu(const GameList::Entry* entry, QWidg
|
|||
{
|
||||
std::vector<SaveStateInfo> available_states(System::GetAvailableSaveStates(entry->serial));
|
||||
const QString timestamp_format = QLocale::system().dateTimeFormat(QLocale::ShortFormat);
|
||||
const bool challenge_mode = Achievements::IsHardcoreModeActive();
|
||||
for (SaveStateInfo& ssi : available_states)
|
||||
{
|
||||
if (ssi.global)
|
||||
|
@ -835,7 +840,6 @@ void MainWindow::populateGameListContextMenu(const GameList::Entry* entry, QWidg
|
|||
if (slot < 0)
|
||||
{
|
||||
resume_action->setText(tr("Resume (%1)").arg(timestamp_str));
|
||||
resume_action->setEnabled(!challenge_mode);
|
||||
action = resume_action;
|
||||
}
|
||||
else
|
||||
|
@ -844,7 +848,7 @@ void MainWindow::populateGameListContextMenu(const GameList::Entry* entry, QWidg
|
|||
action = load_state_menu->addAction(tr("Game Save %1 (%2)").arg(slot).arg(timestamp_str));
|
||||
}
|
||||
|
||||
action->setDisabled(challenge_mode);
|
||||
action->setDisabled(s_achievements_hardcore_mode);
|
||||
connect(action, &QAction::triggered,
|
||||
[this, entry, path = std::move(ssi.path)]() { startFile(entry->path, std::move(path), std::nullopt); });
|
||||
}
|
||||
|
@ -1494,13 +1498,14 @@ void MainWindow::onGameListEntryContextMenuRequested(const QPoint& point)
|
|||
g_emu_thread->bootSystem(std::move(boot_params));
|
||||
});
|
||||
|
||||
if (m_ui.menuDebug->menuAction()->isVisible() && !Achievements::IsHardcoreModeActive())
|
||||
if (m_ui.menuDebug->menuAction()->isVisible())
|
||||
{
|
||||
connect(menu.addAction(tr("Boot and Debug")), &QAction::triggered, [this, entry]() {
|
||||
openCPUDebugger();
|
||||
|
||||
std::shared_ptr<SystemBootParameters> boot_params = getSystemBootParameters(entry->path);
|
||||
boot_params->override_start_paused = true;
|
||||
boot_params->disable_achievements_hardcore_mode = true;
|
||||
g_emu_thread->bootSystem(std::move(boot_params));
|
||||
});
|
||||
}
|
||||
|
@ -1805,14 +1810,14 @@ void MainWindow::onToolbarContextMenuRequested(const QPoint& pos)
|
|||
updateToolbarActions();
|
||||
}
|
||||
|
||||
void MainWindow::updateEmulationActions(bool starting, bool running, bool cheevos_challenge_mode)
|
||||
void MainWindow::updateEmulationActions(bool starting, bool running, bool achievements_hardcore_mode)
|
||||
{
|
||||
const bool starting_or_running = (starting || running);
|
||||
const bool starting_or_not_running = (starting || !running);
|
||||
m_ui.actionStartFile->setDisabled(starting_or_running);
|
||||
m_ui.actionStartDisc->setDisabled(starting_or_running);
|
||||
m_ui.actionStartBios->setDisabled(starting_or_running);
|
||||
m_ui.actionResumeLastState->setDisabled(starting_or_running || cheevos_challenge_mode);
|
||||
m_ui.actionResumeLastState->setDisabled(starting_or_running || achievements_hardcore_mode);
|
||||
m_ui.actionStartFullscreenUI->setDisabled(starting_or_running);
|
||||
m_ui.actionStartFullscreenUI2->setDisabled(starting_or_running);
|
||||
|
||||
|
@ -1821,16 +1826,16 @@ void MainWindow::updateEmulationActions(bool starting, bool running, bool cheevo
|
|||
m_ui.actionReset->setDisabled(starting_or_not_running);
|
||||
m_ui.actionPause->setDisabled(starting_or_not_running);
|
||||
m_ui.actionChangeDisc->setDisabled(starting_or_not_running);
|
||||
m_ui.actionCheatsToolbar->setDisabled(starting_or_not_running || cheevos_challenge_mode);
|
||||
m_ui.actionCheatsToolbar->setDisabled(starting_or_not_running || achievements_hardcore_mode);
|
||||
m_ui.actionScreenshot->setDisabled(starting_or_not_running);
|
||||
m_ui.menuChangeDisc->setDisabled(starting_or_not_running);
|
||||
m_ui.menuCheats->setDisabled(starting_or_not_running || cheevos_challenge_mode);
|
||||
m_ui.actionCPUDebugger->setDisabled(cheevos_challenge_mode);
|
||||
m_ui.actionMemoryScanner->setDisabled(cheevos_challenge_mode);
|
||||
m_ui.menuCheats->setDisabled(starting_or_not_running || achievements_hardcore_mode);
|
||||
m_ui.actionCPUDebugger->setDisabled(achievements_hardcore_mode);
|
||||
m_ui.actionMemoryScanner->setDisabled(achievements_hardcore_mode);
|
||||
m_ui.actionReloadTextureReplacements->setDisabled(starting_or_not_running);
|
||||
m_ui.actionDumpRAM->setDisabled(starting_or_not_running || cheevos_challenge_mode);
|
||||
m_ui.actionDumpVRAM->setDisabled(starting_or_not_running || cheevos_challenge_mode);
|
||||
m_ui.actionDumpSPURAM->setDisabled(starting_or_not_running || cheevos_challenge_mode);
|
||||
m_ui.actionDumpRAM->setDisabled(starting_or_not_running || achievements_hardcore_mode);
|
||||
m_ui.actionDumpVRAM->setDisabled(starting_or_not_running || achievements_hardcore_mode);
|
||||
m_ui.actionDumpSPURAM->setDisabled(starting_or_not_running || achievements_hardcore_mode);
|
||||
|
||||
m_ui.actionSaveState->setDisabled(starting_or_not_running);
|
||||
m_ui.menuSaveState->setDisabled(starting_or_not_running);
|
||||
|
@ -2045,8 +2050,6 @@ void MainWindow::switchToEmulationView()
|
|||
|
||||
void MainWindow::connectSignals()
|
||||
{
|
||||
updateEmulationActions(false, false, Achievements::IsHardcoreModeActive());
|
||||
|
||||
connect(qApp, &QGuiApplication::applicationStateChanged, this, &MainWindow::onApplicationStateChanged);
|
||||
connect(m_ui.toolBar, &QToolBar::customContextMenuRequested, this, &MainWindow::onToolbarContextMenuRequested);
|
||||
|
||||
|
@ -2165,8 +2168,8 @@ void MainWindow::connectSignals()
|
|||
connect(g_emu_thread, &EmuThread::fullscreenUIStartedOrStopped, this, &MainWindow::onFullscreenUIStartedOrStopped);
|
||||
connect(g_emu_thread, &EmuThread::achievementsLoginRequested, this, &MainWindow::onAchievementsLoginRequested);
|
||||
connect(g_emu_thread, &EmuThread::achievementsLoginSuccess, this, &MainWindow::onAchievementsLoginSuccess);
|
||||
connect(g_emu_thread, &EmuThread::achievementsChallengeModeChanged, this,
|
||||
&MainWindow::onAchievementsChallengeModeChanged);
|
||||
connect(g_emu_thread, &EmuThread::achievementsHardcoreModeChanged, this,
|
||||
&MainWindow::onAchievementsHardcoreModeChanged);
|
||||
connect(g_emu_thread, &EmuThread::onCoverDownloaderOpenRequested, this, &MainWindow::onToolsCoverDownloaderTriggered);
|
||||
connect(g_emu_thread, &EmuThread::onCreateAuxiliaryRenderWindow, this, &MainWindow::onCreateAuxiliaryRenderWindow,
|
||||
Qt::BlockingQueuedConnection);
|
||||
|
@ -2795,7 +2798,7 @@ void MainWindow::onAchievementsLoginSuccess(const QString& username, quint32 poi
|
|||
}
|
||||
}
|
||||
|
||||
void MainWindow::onAchievementsChallengeModeChanged(bool enabled)
|
||||
void MainWindow::onAchievementsHardcoreModeChanged(bool enabled)
|
||||
{
|
||||
if (enabled)
|
||||
{
|
||||
|
@ -2803,7 +2806,8 @@ void MainWindow::onAchievementsChallengeModeChanged(bool enabled)
|
|||
QtUtils::CloseAndDeleteWindow(m_memory_scanner_window);
|
||||
}
|
||||
|
||||
updateEmulationActions(false, System::IsValid(), enabled);
|
||||
s_achievements_hardcore_mode = enabled;
|
||||
updateEmulationActions(s_system_starting, s_system_valid, enabled);
|
||||
}
|
||||
|
||||
bool MainWindow::onCreateAuxiliaryRenderWindow(RenderAPI render_api, qint32 x, qint32 y, quint32 width, quint32 height,
|
||||
|
@ -2889,7 +2893,7 @@ void MainWindow::onToolsMediaCaptureToggled(bool checked)
|
|||
|
||||
void MainWindow::onToolsMemoryScannerTriggered()
|
||||
{
|
||||
if (Achievements::IsHardcoreModeActive())
|
||||
if (s_achievements_hardcore_mode)
|
||||
return;
|
||||
|
||||
if (!m_memory_scanner_window)
|
||||
|
@ -2913,6 +2917,9 @@ void MainWindow::onToolsISOBrowserTriggered()
|
|||
|
||||
void MainWindow::openCPUDebugger()
|
||||
{
|
||||
if (s_achievements_hardcore_mode)
|
||||
return;
|
||||
|
||||
if (!m_debugger_window)
|
||||
{
|
||||
m_debugger_window = new DebuggerWindow();
|
||||
|
|
|
@ -151,7 +151,7 @@ private Q_SLOTS:
|
|||
void onMediaCaptureStopped();
|
||||
void onAchievementsLoginRequested(Achievements::LoginRequestReason reason);
|
||||
void onAchievementsLoginSuccess(const QString& username, quint32 points, quint32 sc_points, quint32 unread_messages);
|
||||
void onAchievementsChallengeModeChanged(bool enabled);
|
||||
void onAchievementsHardcoreModeChanged(bool enabled);
|
||||
bool onCreateAuxiliaryRenderWindow(RenderAPI render_api, qint32 x, qint32 y, quint32 width, quint32 height,
|
||||
const QString& title, const QString& icon_name,
|
||||
Host::AuxiliaryRenderWindowUserData userdata,
|
||||
|
|
|
@ -1677,7 +1677,7 @@ void Host::OnAchievementsRefreshed()
|
|||
|
||||
void Host::OnAchievementsHardcoreModeChanged(bool enabled)
|
||||
{
|
||||
emit g_emu_thread->achievementsChallengeModeChanged(enabled);
|
||||
emit g_emu_thread->achievementsHardcoreModeChanged(enabled);
|
||||
}
|
||||
|
||||
void Host::OnCoverDownloaderOpenRequested()
|
||||
|
|
|
@ -155,7 +155,7 @@ Q_SIGNALS:
|
|||
void achievementsLoginRequested(Achievements::LoginRequestReason reason);
|
||||
void achievementsLoginSuccess(const QString& username, quint32 points, quint32 sc_points, quint32 unread_messages);
|
||||
void achievementsRefreshed(quint32 id, const QString& game_info_string);
|
||||
void achievementsChallengeModeChanged(bool enabled);
|
||||
void achievementsHardcoreModeChanged(bool enabled);
|
||||
void cheatEnabled(quint32 index, bool enabled);
|
||||
void mediaCaptureStarted();
|
||||
void mediaCaptureStopped();
|
||||
|
|
Loading…
Reference in New Issue