mirror of
https://github.com/stenzek/duckstation.git
synced 2025-06-07 03:55:33 +00:00
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 "achievements_private.h"
|
||||||
#include "bios.h"
|
#include "bios.h"
|
||||||
#include "bus.h"
|
#include "bus.h"
|
||||||
|
#include "cheats.h"
|
||||||
#include "cpu_core.h"
|
#include "cpu_core.h"
|
||||||
#include "fullscreen_ui.h"
|
#include "fullscreen_ui.h"
|
||||||
#include "game_list.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 ClearGameInfo();
|
||||||
static void ClearGameHash();
|
static void ClearGameHash();
|
||||||
static bool TryLoggingInWithToken();
|
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 IsLoggedInOrLoggingIn();
|
||||||
static bool CanEnableHardcoreMode();
|
|
||||||
static void FinishLogin(const rc_client_t* client);
|
static void FinishLogin(const rc_client_t* client);
|
||||||
static void ShowLoginNotification();
|
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 BeginLoadGame();
|
||||||
static void BeginChangeDisc();
|
|
||||||
static void UpdateGameSummary(bool update_progress_database, bool force_update_progress_database);
|
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 std::string GetLocalImagePath(const std::string_view image_name, int type);
|
||||||
static void DownloadImage(std::string url, std::string cache_path);
|
static void DownloadImage(std::string url, std::string cache_path);
|
||||||
@ -244,7 +245,6 @@ struct PauseMenuAchievementInfo
|
|||||||
struct State
|
struct State
|
||||||
{
|
{
|
||||||
rc_client_t* client = nullptr;
|
rc_client_t* client = nullptr;
|
||||||
bool hardcore_mode = false;
|
|
||||||
bool has_achievements = false;
|
bool has_achievements = false;
|
||||||
bool has_leaderboards = false;
|
bool has_leaderboards = false;
|
||||||
bool has_rich_presence = 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)
|
void Achievements::ReportError(std::string_view sv)
|
||||||
{
|
{
|
||||||
std::string error = fmt::format("Achievements error: {}", sv);
|
ERROR_LOG(sv);
|
||||||
ERROR_LOG(error.c_str());
|
Host::AddIconOSDWarning(std::string(), ICON_EMOJI_WARNING, std::string(sv), Host::OSD_CRITICAL_ERROR_DURATION);
|
||||||
Host::AddOSDMessage(std::move(error), Host::OSD_CRITICAL_ERROR_DURATION);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... T>
|
template<typename... T>
|
||||||
@ -581,7 +580,11 @@ bool Achievements::IsHardcoreModeActive()
|
|||||||
return RA_HardcoreModeIsActive() != 0;
|
return RA_HardcoreModeIsActive() != 0;
|
||||||
#endif
|
#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()
|
bool Achievements::HasActiveGame()
|
||||||
@ -651,25 +654,27 @@ bool Achievements::Initialize()
|
|||||||
if (!CreateClient(&s_state.client, &s_state.http_downloader))
|
if (!CreateClient(&s_state.client, &s_state.http_downloader))
|
||||||
return false;
|
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_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_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_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);
|
rc_client_set_spectator_mode_enabled(s_state.client, g_settings.achievements_spectator_mode);
|
||||||
|
|
||||||
// Begin disc identification early, before the login finishes.
|
// Start logging in. This can take a while.
|
||||||
if (System::IsValid())
|
|
||||||
IdentifyGame(System::GetDiscPath(), nullptr);
|
|
||||||
|
|
||||||
TryLoggingInWithToken();
|
TryLoggingInWithToken();
|
||||||
|
|
||||||
// Hardcore mode isn't enabled when achievements first starts, if a game is already running.
|
// Are we running a game?
|
||||||
if (System::IsValid() && IsLoggedInOrLoggingIn() && g_settings.achievements_hardcore_mode)
|
if (System::IsValid())
|
||||||
DisplayHardcoreDeferredMessage();
|
{
|
||||||
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
@ -753,7 +758,7 @@ void Achievements::UpdateSettings(const Settings& old_config)
|
|||||||
if (!g_settings.achievements_enabled)
|
if (!g_settings.achievements_enabled)
|
||||||
{
|
{
|
||||||
// we're done here
|
// we're done here
|
||||||
Shutdown(false);
|
Shutdown();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -766,26 +771,23 @@ void Achievements::UpdateSettings(const Settings& old_config)
|
|||||||
|
|
||||||
if (g_settings.achievements_hardcore_mode != old_config.achievements_hardcore_mode)
|
if (g_settings.achievements_hardcore_mode != old_config.achievements_hardcore_mode)
|
||||||
{
|
{
|
||||||
// Hardcore mode can only be enabled through reset (ResetChallengeMode()).
|
// Enables have to wait for reset, disables can go through immediately.
|
||||||
if (s_state.hardcore_mode && !g_settings.achievements_hardcore_mode)
|
if (g_settings.achievements_hardcore_mode)
|
||||||
{
|
DisplayHardcoreDeferredMessage();
|
||||||
ResetHardcoreMode(false);
|
else
|
||||||
}
|
DisableHardcoreMode(true, true);
|
||||||
else if (!s_state.hardcore_mode && g_settings.achievements_hardcore_mode)
|
|
||||||
{
|
|
||||||
if (HasActiveGame())
|
|
||||||
DisplayHardcoreDeferredMessage();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// These cannot be modified while a game is loaded, so just toss state and reload.
|
// These cannot be modified while a game is loaded, so just toss state and reload.
|
||||||
|
auto lock = GetLock();
|
||||||
if (HasActiveGame())
|
if (HasActiveGame())
|
||||||
{
|
{
|
||||||
|
lock.unlock();
|
||||||
if (g_settings.achievements_encore_mode != old_config.achievements_encore_mode ||
|
if (g_settings.achievements_encore_mode != old_config.achievements_encore_mode ||
|
||||||
g_settings.achievements_spectator_mode != old_config.achievements_spectator_mode ||
|
g_settings.achievements_spectator_mode != old_config.achievements_spectator_mode ||
|
||||||
g_settings.achievements_unofficial_test_mode != old_config.achievements_unofficial_test_mode)
|
g_settings.achievements_unofficial_test_mode != old_config.achievements_unofficial_test_mode)
|
||||||
{
|
{
|
||||||
Shutdown(false);
|
Shutdown();
|
||||||
Initialize();
|
Initialize();
|
||||||
return;
|
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())
|
if (!IsActive())
|
||||||
return true;
|
return;
|
||||||
|
|
||||||
auto lock = GetLock();
|
auto lock = GetLock();
|
||||||
Assert(s_state.client && s_state.http_downloader);
|
Assert(s_state.client && s_state.http_downloader);
|
||||||
|
|
||||||
ClearGameInfo();
|
ClearGameInfo();
|
||||||
ClearGameHash();
|
ClearGameHash();
|
||||||
DisableHardcoreMode();
|
DisableHardcoreMode(false, false);
|
||||||
UpdateGlyphRanges();
|
UpdateGlyphRanges();
|
||||||
CancelHashDatabaseRequests();
|
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)
|
if (s_state.login_request)
|
||||||
{
|
{
|
||||||
rc_client_abort_async(s_state.client, s_state.login_request);
|
rc_client_abort_async(s_state.client, s_state.login_request);
|
||||||
s_state.login_request = nullptr;
|
s_state.login_request = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
s_state.hardcore_mode = false;
|
|
||||||
DestroyClient(&s_state.client, &s_state.http_downloader);
|
DestroyClient(&s_state.client, &s_state.http_downloader);
|
||||||
|
|
||||||
Host::OnAchievementsRefreshed();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Achievements::ClientMessageCallback(const char* message, const rc_client_t* client)
|
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) :
|
RC_API_SERVER_RESPONSE_RETRYABLE_CLIENT_ERROR) :
|
||||||
status_code;
|
status_code;
|
||||||
rr.body_length = data.size();
|
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);
|
callback(&rr, callback_data);
|
||||||
};
|
};
|
||||||
@ -1147,40 +1128,109 @@ void Achievements::UpdateRichPresence(std::unique_lock<std::recursive_mutex>& lo
|
|||||||
lock.lock();
|
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);
|
std::unique_lock lock(s_state.mutex);
|
||||||
|
|
||||||
if (!IsActive())
|
if (!IsActive())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
IdentifyGame(path, image);
|
|
||||||
|
|
||||||
// if we're not logged in, and there's no login request, retry logging in
|
// 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.
|
// 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())
|
||||||
if (!IsLoggedInOrLoggingIn() && booting)
|
|
||||||
{
|
{
|
||||||
WARNING_LOG("Not logged in on game booting, trying again.");
|
WARNING_LOG("Not logged in on game booting, trying again.");
|
||||||
TryLoggingInWithToken();
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
std::unique_ptr<CDImage> temp_image;
|
// Do we need to enable hardcore mode?
|
||||||
if (!path.empty() && !image)
|
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);
|
// This will raise the silly reset event, but we can safely ignore that since we're immediately resetting the client
|
||||||
image = temp_image.get();
|
DEV_LOG("Enabling hardcore mode after reset");
|
||||||
if (!temp_image)
|
EnableHardcodeMode(true, true);
|
||||||
ERROR_LOG("Failed to open temporary CD image '{}'", path);
|
}
|
||||||
|
|
||||||
|
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;
|
std::optional<GameHash> game_hash;
|
||||||
@ -1189,63 +1239,64 @@ void Achievements::IdentifyGame(const std::string& path, CDImage* image)
|
|||||||
u32 bytes_hashed;
|
u32 bytes_hashed;
|
||||||
game_hash = GetGameHash(image, &bytes_hashed);
|
game_hash = GetGameHash(image, &bytes_hashed);
|
||||||
if (game_hash.has_value())
|
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)
|
if (s_state.game_hash == game_hash)
|
||||||
{
|
{
|
||||||
// only the path has changed - different format/save state/etc.
|
// only the path has changed - different format/save state/etc.
|
||||||
INFO_LOG("Detected path change from '{}' to '{}'", s_state.game_path, path);
|
INFO_LOG("Detected path change to '{}'", s_state.game_path);
|
||||||
s_state.game_path = path;
|
s_state.game_path = image->GetPath();
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClearGameHash();
|
s_state.game_hash = game_hash;
|
||||||
s_state.game_path = path;
|
|
||||||
s_state.game_hash = std::move(game_hash);
|
|
||||||
|
|
||||||
#ifdef ENABLE_RAINTEGRATION
|
#ifdef ENABLE_RAINTEGRATION
|
||||||
if (IsUsingRAIntegration())
|
if (IsUsingRAIntegration())
|
||||||
{
|
|
||||||
RAIntegration::GameChanged();
|
RAIntegration::GameChanged();
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// shouldn't have a load game request when we're not logged in.
|
return true;
|
||||||
Assert(IsLoggedInOrLoggingIn() || !s_state.load_game_request);
|
}
|
||||||
|
|
||||||
// bail out if we're not logged in, just save the hash
|
bool Achievements::IdentifyCurrentGame()
|
||||||
if (!IsLoggedInOrLoggingIn())
|
{
|
||||||
|
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.");
|
Error error;
|
||||||
DisableHardcoreMode();
|
temp_image = CDImage::Open(disc_path.c_str(), g_settings.cdrom_load_image_patches, &error);
|
||||||
return;
|
if (!temp_image)
|
||||||
|
ERROR_LOG("Failed to open disc for late game identification: {}", error.GetDescription());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rc_client_is_game_loaded(s_state.client))
|
return IdentifyGame(temp_image.get());
|
||||||
BeginLoadGame();
|
|
||||||
else
|
|
||||||
BeginChangeDisc();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Achievements::BeginLoadGame()
|
void Achievements::BeginLoadGame()
|
||||||
{
|
{
|
||||||
ClearGameInfo();
|
DebugAssert(IsLoggedInOrLoggingIn());
|
||||||
|
|
||||||
if (!s_state.game_hash.has_value())
|
if (!s_state.game_hash.has_value())
|
||||||
{
|
{
|
||||||
// when we're booting the bios, this will fail
|
// no need to go through ClientLoadGameCallback, just bail out straight away
|
||||||
if (!s_state.game_path.empty())
|
DisableHardcoreMode(false, false);
|
||||||
{
|
|
||||||
Host::AddKeyedOSDMessage(
|
|
||||||
"retroachievements_disc_read_failed",
|
|
||||||
TRANSLATE_STR("Achievements", "Failed to read executable from disc. Achievements disabled."),
|
|
||||||
Host::OSD_ERROR_DURATION);
|
|
||||||
}
|
|
||||||
|
|
||||||
DisableHardcoreMode();
|
|
||||||
UpdateGlyphRanges();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1253,37 +1304,6 @@ void Achievements::BeginLoadGame()
|
|||||||
ClientLoadGameCallback, nullptr);
|
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)
|
void Achievements::ClientLoadGameCallback(int result, const char* error_message, rc_client_t* client, void* userdata)
|
||||||
{
|
{
|
||||||
const bool was_disc_change = (userdata != nullptr);
|
const bool was_disc_change = (userdata != nullptr);
|
||||||
@ -1300,7 +1320,7 @@ void Achievements::ClientLoadGameCallback(int result, const char* error_message,
|
|||||||
UpdateGlyphRanges();
|
UpdateGlyphRanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
DisableHardcoreMode();
|
DisableHardcoreMode(false, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (result == RC_LOGIN_REQUIRED)
|
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.
|
// Once we've done so, we'll reload the game.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else if (result == RC_HARDCORE_DISABLED)
|
||||||
|
{
|
||||||
|
if (error_message)
|
||||||
|
ReportError(error_message);
|
||||||
|
|
||||||
|
OnHardcoreModeChanged(false, true, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
else if (result != RC_OK)
|
else if (result != RC_OK)
|
||||||
{
|
{
|
||||||
ReportFmtError("Loading game failed: {}", error_message);
|
ReportFmtError("Loading game failed: {}", error_message);
|
||||||
@ -1318,16 +1346,9 @@ void Achievements::ClientLoadGameCallback(int result, const char* error_message,
|
|||||||
UpdateGlyphRanges();
|
UpdateGlyphRanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
DisableHardcoreMode();
|
DisableHardcoreMode(false, false);
|
||||||
return;
|
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);
|
const rc_client_game_t* info = rc_client_get_game_info(s_state.client);
|
||||||
if (!info)
|
if (!info)
|
||||||
@ -1339,7 +1360,7 @@ void Achievements::ClientLoadGameCallback(int result, const char* error_message,
|
|||||||
UpdateGlyphRanges();
|
UpdateGlyphRanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
DisableHardcoreMode();
|
DisableHardcoreMode(false, false);
|
||||||
return;
|
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.
|
// 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);
|
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,
|
// If the game has a RetroAchievements entry but no achievements or leaderboards, enforcing hardcore mode
|
||||||
// enforcing hardcore mode is pointless.
|
// is pointless. Have to re-query leaderboards because hidden should still trip HC.
|
||||||
if (!has_achievements && !has_leaderboards)
|
if (!has_achievements && !rc_client_has_leaderboards(client, true))
|
||||||
DisableHardcoreMode();
|
DisableHardcoreMode(false, false);
|
||||||
|
|
||||||
// We should have matched hardcore mode state.
|
|
||||||
Assert(s_state.hardcore_mode == (rc_client_get_hardcore_enabled(client) != 0));
|
|
||||||
|
|
||||||
s_state.game_id = info->id;
|
s_state.game_id = info->id;
|
||||||
s_state.game_title = info->title;
|
s_state.game_title = info->title;
|
||||||
@ -1469,7 +1487,7 @@ void Achievements::DisplayAchievementSummary()
|
|||||||
|
|
||||||
void Achievements::DisplayHardcoreDeferredMessage()
|
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([]() {
|
GPUThread::RunOnThread([]() {
|
||||||
if (!FullscreenUI::Initialize())
|
if (!FullscreenUI::Initialize())
|
||||||
@ -1484,12 +1502,7 @@ void Achievements::DisplayHardcoreDeferredMessage()
|
|||||||
|
|
||||||
void Achievements::HandleResetEvent(const rc_client_event_t* event)
|
void Achievements::HandleResetEvent(const rc_client_event_t* event)
|
||||||
{
|
{
|
||||||
// We handle system resets ourselves, but still need to reset the client's state.
|
WARNING_LOG("Ignoring RC_CLIENT_EVENT_RESET.");
|
||||||
INFO_LOG("Resetting runtime due to reset event");
|
|
||||||
rc_client_reset(s_state.client);
|
|
||||||
|
|
||||||
if (HasActiveGame())
|
|
||||||
UpdateGameSummary(false, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Achievements::HandleUnlockEvent(const rc_client_event_t* event)
|
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
|
DebugAssert(IsActive());
|
||||||
if (IsUsingRAIntegration())
|
if (rc_client_get_hardcore_enabled(s_state.client))
|
||||||
{
|
|
||||||
RA_OnReset();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!IsActive())
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
DEV_LOG("Reset client");
|
rc_client_set_hardcore_enabled(s_state.client, true);
|
||||||
rc_client_reset(s_state.client);
|
OnHardcoreModeChanged(true, display_message, display_game_summary);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Achievements::OnSystemPaused(bool paused)
|
void Achievements::DisableHardcoreMode(bool show_message, bool display_game_summary)
|
||||||
{
|
|
||||||
#ifdef ENABLE_RAINTEGRATION
|
|
||||||
if (IsUsingRAIntegration())
|
|
||||||
RA_SetPaused(paused);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void Achievements::DisableHardcoreMode()
|
|
||||||
{
|
{
|
||||||
if (!IsActive())
|
if (!IsActive())
|
||||||
return;
|
return;
|
||||||
@ -1846,43 +1844,19 @@ void Achievements::DisableHardcoreMode()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!s_state.hardcore_mode)
|
|
||||||
return;
|
|
||||||
|
|
||||||
SetHardcoreMode(false, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Achievements::ResetHardcoreMode(bool is_booting)
|
|
||||||
{
|
|
||||||
if (!IsActive())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const auto lock = GetLock();
|
const auto lock = GetLock();
|
||||||
|
if (!rc_client_get_hardcore_enabled(s_state.client))
|
||||||
// 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)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// new mode
|
rc_client_set_hardcore_enabled(s_state.client, false);
|
||||||
s_state.hardcore_mode = enabled;
|
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]() {
|
GPUThread::RunOnThread([enabled]() {
|
||||||
if (!FullscreenUI::Initialize())
|
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);
|
if (HasActiveGame() && display_game_summary)
|
||||||
DebugAssert((rc_client_get_hardcore_enabled(s_state.client) != 0) == enabled);
|
|
||||||
if (HasActiveGame())
|
|
||||||
{
|
{
|
||||||
UpdateGameSummary(true, true);
|
UpdateGameSummary(true, true);
|
||||||
DisplayAchievementSummary();
|
DisplayAchievementSummary();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DebugAssert((rc_client_get_hardcore_enabled(s_state.client) != 0) == enabled);
|
||||||
|
|
||||||
// Reload setting to permit cheating-like things if we were just disabled.
|
// 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); });
|
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
|
// Toss away UI state, because it's invalid now
|
||||||
ClearUIState();
|
ClearUIState();
|
||||||
@ -1947,9 +1932,6 @@ bool Achievements::DoState(StateWrapper& sw)
|
|||||||
GPUThread::RunOnThread([]() { FullscreenUI::CloseLoadingScreen(); });
|
GPUThread::RunOnThread([]() { FullscreenUI::CloseLoadingScreen(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
// loading an old state without cheevos, so reset the runtime
|
|
||||||
Achievements::Reset();
|
|
||||||
|
|
||||||
u32 data_size = 0;
|
u32 data_size = 0;
|
||||||
sw.DoEx(&data_size, REQUIRED_VERSION, 0u);
|
sw.DoEx(&data_size, REQUIRED_VERSION, 0u);
|
||||||
if (data_size == 0)
|
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);
|
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)
|
bool Achievements::Login(const char* username, const char* password, Error* error)
|
||||||
{
|
{
|
||||||
auto lock = GetLock();
|
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 we were't a temporary client, get the game loaded.
|
||||||
if (System::IsValid() && !is_temporary_client)
|
if (System::IsValid() && !is_temporary_client)
|
||||||
|
{
|
||||||
|
IdentifyCurrentGame();
|
||||||
BeginLoadGame();
|
BeginLoadGame();
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -2223,9 +2202,6 @@ void Achievements::ClientLoginWithTokenCallback(int result, const char* error_me
|
|||||||
}
|
}
|
||||||
|
|
||||||
FinishLogin(client);
|
FinishLogin(client);
|
||||||
|
|
||||||
if (System::IsValid())
|
|
||||||
BeginLoadGame();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Achievements::FinishLogin(const rc_client_t* client)
|
void Achievements::FinishLogin(const rc_client_t* client)
|
||||||
@ -2338,7 +2314,7 @@ void Achievements::Logout()
|
|||||||
ClearProgressDatabase();
|
ClearProgressDatabase();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Achievements::ConfirmSystemReset()
|
bool Achievements::ConfirmGameChange()
|
||||||
{
|
{
|
||||||
#ifdef ENABLE_RAINTEGRATION
|
#ifdef ENABLE_RAINTEGRATION
|
||||||
if (IsUsingRAIntegration())
|
if (IsUsingRAIntegration())
|
||||||
@ -2364,7 +2340,7 @@ bool Achievements::ConfirmHardcoreModeDisable(const char* trigger)
|
|||||||
if (!confirmed)
|
if (!confirmed)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
DisableHardcoreMode();
|
DisableHardcoreMode(true, true);
|
||||||
return 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
|
// don't run the callback in the middle of rendering the UI
|
||||||
Host::RunOnCPUThread([callback = std::move(callback), res]() {
|
Host::RunOnCPUThread([callback = std::move(callback), res]() {
|
||||||
if (res)
|
if (res)
|
||||||
DisableHardcoreMode();
|
DisableHardcoreMode(true, true);
|
||||||
callback(res);
|
callback(res);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -2826,7 +2802,7 @@ void Achievements::DrawAchievementsWindow()
|
|||||||
using ImGuiFullscreen::RenderShadowedTextClipped;
|
using ImGuiFullscreen::RenderShadowedTextClipped;
|
||||||
using ImGuiFullscreen::UIStyle;
|
using ImGuiFullscreen::UIStyle;
|
||||||
|
|
||||||
auto lock = Achievements::GetLock();
|
const auto lock = Achievements::GetLock();
|
||||||
|
|
||||||
// achievements can get turned off via the main UI
|
// achievements can get turned off via the main UI
|
||||||
if (!s_state.achievement_list)
|
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));
|
const ImRect title_bb(ImVec2(left, top), ImVec2(right, top + UIStyle.LargeFont->FontSize));
|
||||||
text.assign(s_state.game_title);
|
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)"));
|
text.append(TRANSLATE_SV("Achievements", " (Hardcore Mode)"));
|
||||||
|
|
||||||
top += UIStyle.LargeFont->FontSize + spacing;
|
top += UIStyle.LargeFont->FontSize + spacing;
|
||||||
|
@ -77,18 +77,24 @@ bool Initialize();
|
|||||||
/// Updates achievements settings.
|
/// Updates achievements settings.
|
||||||
void UpdateSettings(const Settings& old_config);
|
void UpdateSettings(const Settings& old_config);
|
||||||
|
|
||||||
/// Resets the internal state of all achievement tracking. Call on system reset.
|
/// Shuts down the RetroAchievements client.
|
||||||
void Reset();
|
void Shutdown();
|
||||||
|
|
||||||
/// Called when the system is being reset. If it returns false, the reset should be aborted.
|
/// Called when the system is start. Engages hardcore mode if enabled.
|
||||||
bool ConfirmSystemReset();
|
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.
|
/// Called when the system is shutting down. If this returns false, the shutdown should be aborted.
|
||||||
bool Shutdown(bool allow_cancel);
|
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.
|
/// Called when the system is being paused and resumed.
|
||||||
void OnSystemPaused(bool paused);
|
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.
|
/// Called once a frame at vsync time on the CPU thread.
|
||||||
void FrameUpdate();
|
void FrameUpdate();
|
||||||
|
|
||||||
@ -108,14 +114,8 @@ bool Login(const char* username, const char* password, Error* error);
|
|||||||
/// Logs out of RetroAchievements, clearing any credentials.
|
/// Logs out of RetroAchievements, clearing any credentials.
|
||||||
void Logout();
|
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.
|
/// 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.
|
/// Prompts the user to disable hardcore mode, if they agree, returns true.
|
||||||
bool ConfirmHardcoreModeDisable(const char* trigger);
|
bool ConfirmHardcoreModeDisable(const char* trigger);
|
||||||
@ -127,6 +127,9 @@ bool IsHardcoreModeActive();
|
|||||||
/// RAIntegration only exists for Windows, so no point checking it on other platforms.
|
/// RAIntegration only exists for Windows, so no point checking it on other platforms.
|
||||||
bool IsUsingRAIntegration();
|
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.
|
/// Returns true if the achievement system is active. Achievements can be active without a valid client.
|
||||||
bool IsActive();
|
bool IsActive();
|
||||||
|
|
||||||
|
@ -542,7 +542,7 @@ void System::CPUThreadShutdown()
|
|||||||
ShutdownDiscordPresence();
|
ShutdownDiscordPresence();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Achievements::Shutdown(false);
|
Achievements::Shutdown();
|
||||||
|
|
||||||
InputManager::CloseSources();
|
InputManager::CloseSources();
|
||||||
|
|
||||||
@ -1349,12 +1349,17 @@ void System::ApplySettings(bool display_osd_messages)
|
|||||||
LoadSettings(display_osd_messages);
|
LoadSettings(display_osd_messages);
|
||||||
|
|
||||||
// If we've disabled/enabled game settings, we need to reload without it.
|
// 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)
|
if (g_settings.apply_game_settings != old_settings.apply_game_settings)
|
||||||
{
|
{
|
||||||
UpdateGameSettingsLayer();
|
UpdateGameSettingsLayer();
|
||||||
LoadSettings(display_osd_messages);
|
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);
|
CheckForSettingsChanges(old_settings);
|
||||||
Host::CheckForSettingsChanges(old_settings);
|
Host::CheckForSettingsChanges(old_settings);
|
||||||
@ -1546,19 +1551,9 @@ void System::UpdateInputSettingsLayer(std::string input_profile_name, std::uniqu
|
|||||||
|
|
||||||
void System::ResetSystem()
|
void System::ResetSystem()
|
||||||
{
|
{
|
||||||
if (!IsValid())
|
if (!IsValid() || !Achievements::ConfirmGameChange())
|
||||||
return;
|
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();
|
InternalReset();
|
||||||
|
|
||||||
// Reset boot mode/reload BIOS if needed. Preserve exe/psf boot.
|
// 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.
|
// Update running game, this will apply settings as well.
|
||||||
UpdateRunningGame(disc ? disc->GetPath() : parameters.filename, disc.get(), true);
|
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.
|
// 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;
|
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.
|
// Achievement hardcore checks before committing to anything.
|
||||||
if (disc)
|
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())
|
if ((!parameters.save_state.empty() || !exe_override.empty()) && Achievements::IsHardcoreModeActive())
|
||||||
{
|
{
|
||||||
const bool is_exe_override_boot = parameters.save_state.empty();
|
const bool is_exe_override_boot = parameters.save_state.empty();
|
||||||
@ -1794,10 +1783,6 @@ bool System::BootSystem(SystemBootParameters parameters, Error* error)
|
|||||||
return true;
|
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.
|
// Are we fast booting? Must be checked after updating game settings.
|
||||||
@ -1994,6 +1979,7 @@ void System::DestroySystem()
|
|||||||
CPU::Shutdown();
|
CPU::Shutdown();
|
||||||
Bus::Shutdown();
|
Bus::Shutdown();
|
||||||
TimingEvents::Shutdown();
|
TimingEvents::Shutdown();
|
||||||
|
Achievements::OnSystemDestroyed();
|
||||||
ClearRunningGame();
|
ClearRunningGame();
|
||||||
GPUThread::DestroyGPUBackend();
|
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,
|
Host::OnGameChanged(s_state.running_game_path, s_state.running_game_serial, s_state.running_game_title,
|
||||||
s_state.running_game_hash);
|
s_state.running_game_hash);
|
||||||
|
|
||||||
Achievements::GameChanged(s_state.running_game_path, nullptr, false);
|
|
||||||
|
|
||||||
UpdateRichPresence(true);
|
UpdateRichPresence(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2780,7 +2764,7 @@ void System::InternalReset()
|
|||||||
MDEC::Reset();
|
MDEC::Reset();
|
||||||
SIO::Reset();
|
SIO::Reset();
|
||||||
PCDrv::Reset();
|
PCDrv::Reset();
|
||||||
Achievements::Reset();
|
Achievements::OnSystemReset();
|
||||||
s_state.frame_number = 1;
|
s_state.frame_number = 1;
|
||||||
s_state.internal_frame_number = 0;
|
s_state.internal_frame_number = 0;
|
||||||
}
|
}
|
||||||
@ -2963,7 +2947,7 @@ bool System::LoadStateFromBuffer(const SaveStateBuffer& buffer, Error* error, bo
|
|||||||
ClearMemorySaveStates(false, false);
|
ClearMemorySaveStates(false, false);
|
||||||
|
|
||||||
// Updating game/loading settings can turn on hardcore mode. Catch this.
|
// 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);
|
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();
|
UpdateGameSettingsLayer();
|
||||||
|
ApplySettings(true);
|
||||||
|
|
||||||
if (!IsReplayingGPUDump())
|
if (!IsReplayingGPUDump())
|
||||||
{
|
{
|
||||||
Achievements::GameChanged(s_state.running_game_path, image, booting);
|
|
||||||
|
|
||||||
// Cheats are loaded later in Initialize().
|
// Cheats are loaded later in Initialize().
|
||||||
if (!booting)
|
if (!booting)
|
||||||
|
{
|
||||||
|
Achievements::GameChanged(image);
|
||||||
Cheats::ReloadCheats(true, true, false, true, true);
|
Cheats::ReloadCheats(true, true, false, true, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ApplySettings(true);
|
|
||||||
|
|
||||||
if (s_state.running_game_serial != prev_serial)
|
if (s_state.running_game_serial != prev_serial)
|
||||||
{
|
{
|
||||||
GPUThread::SetGameSerial(s_state.running_game_serial);
|
GPUThread::SetGameSerial(s_state.running_game_serial);
|
||||||
|
@ -56,7 +56,7 @@ void AchievementLoginDialog::cancelClicked()
|
|||||||
{
|
{
|
||||||
Host::RunOnCPUThread([]() {
|
Host::RunOnCPUThread([]() {
|
||||||
if (System::IsValid() && !Achievements::HasActiveGame())
|
if (System::IsValid() && !Achievements::HasActiveGame())
|
||||||
Achievements::DisableHardcoreMode();
|
Achievements::DisableHardcoreMode(false, false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,9 +138,11 @@ void AchievementSettingsWidget::onHardcoreModeStateChanged()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// don't bother prompting if the game doesn't have achievements
|
// don't bother prompting if the game doesn't have achievements
|
||||||
auto lock = Achievements::GetLock();
|
{
|
||||||
if (!Achievements::HasActiveGame())
|
auto lock = Achievements::GetLock();
|
||||||
return;
|
if (!Achievements::HasActiveGame())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (QMessageBox::question(
|
if (QMessageBox::question(
|
||||||
QtUtils::GetRootWidget(this), tr("Reset System"),
|
QtUtils::GetRootWidget(this), tr("Reset System"),
|
||||||
|
@ -104,8 +104,10 @@ MainWindow* g_main_window = nullptr;
|
|||||||
|
|
||||||
// UI thread VM validity.
|
// UI thread VM validity.
|
||||||
static bool s_disable_window_rounded_corners = false;
|
static bool s_disable_window_rounded_corners = false;
|
||||||
|
static bool s_system_starting = false;
|
||||||
static bool s_system_valid = false;
|
static bool s_system_valid = false;
|
||||||
static bool s_system_paused = false;
|
static bool s_system_paused = false;
|
||||||
|
static bool s_achievements_hardcore_mode = false;
|
||||||
static bool s_fullscreen_ui_started = false;
|
static bool s_fullscreen_ui_started = false;
|
||||||
static std::atomic_uint32_t s_system_locked{false};
|
static std::atomic_uint32_t s_system_locked{false};
|
||||||
static QString s_current_game_title;
|
static QString s_current_game_title;
|
||||||
@ -170,6 +172,7 @@ void MainWindow::initialize()
|
|||||||
m_ui.setupUi(this);
|
m_ui.setupUi(this);
|
||||||
setupAdditionalUi();
|
setupAdditionalUi();
|
||||||
updateToolbarActions();
|
updateToolbarActions();
|
||||||
|
updateEmulationActions(false, false, false);
|
||||||
connectSignals();
|
connectSignals();
|
||||||
|
|
||||||
restoreStateFromConfig();
|
restoreStateFromConfig();
|
||||||
@ -515,18 +518,20 @@ void MainWindow::onMouseModeRequested(bool relative_mode, bool hide_cursor)
|
|||||||
|
|
||||||
void MainWindow::onSystemStarting()
|
void MainWindow::onSystemStarting()
|
||||||
{
|
{
|
||||||
|
s_system_starting = true;
|
||||||
s_system_valid = false;
|
s_system_valid = false;
|
||||||
s_system_paused = false;
|
s_system_paused = false;
|
||||||
|
|
||||||
switchToEmulationView();
|
switchToEmulationView();
|
||||||
updateEmulationActions(true, false, Achievements::IsHardcoreModeActive());
|
updateEmulationActions(true, false, s_achievements_hardcore_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::onSystemStarted()
|
void MainWindow::onSystemStarted()
|
||||||
{
|
{
|
||||||
m_was_disc_change_request = false;
|
m_was_disc_change_request = false;
|
||||||
|
s_system_starting = false;
|
||||||
s_system_valid = true;
|
s_system_valid = true;
|
||||||
updateEmulationActions(false, true, Achievements::IsHardcoreModeActive());
|
updateEmulationActions(false, true, s_achievements_hardcore_mode);
|
||||||
updateWindowTitle();
|
updateWindowTitle();
|
||||||
updateStatusBarWidgetVisibility();
|
updateStatusBarWidgetVisibility();
|
||||||
updateDisplayWidgetCursor();
|
updateDisplayWidgetCursor();
|
||||||
@ -574,6 +579,7 @@ void MainWindow::onSystemDestroyed()
|
|||||||
m_ui.actionPause->setChecked(false);
|
m_ui.actionPause->setChecked(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s_system_starting = false;
|
||||||
s_system_valid = false;
|
s_system_valid = false;
|
||||||
s_system_paused = false;
|
s_system_paused = false;
|
||||||
|
|
||||||
@ -585,7 +591,7 @@ void MainWindow::onSystemDestroyed()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateEmulationActions(false, false, Achievements::IsHardcoreModeActive());
|
updateEmulationActions(false, false, s_achievements_hardcore_mode);
|
||||||
if (m_display_widget)
|
if (m_display_widget)
|
||||||
updateDisplayWidgetCursor();
|
updateDisplayWidgetCursor();
|
||||||
else
|
else
|
||||||
@ -770,7 +776,7 @@ void MainWindow::recreate()
|
|||||||
if (was_display_created)
|
if (was_display_created)
|
||||||
{
|
{
|
||||||
g_emu_thread->setSurfaceless(false);
|
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);
|
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));
|
std::vector<SaveStateInfo> available_states(System::GetAvailableSaveStates(entry->serial));
|
||||||
const QString timestamp_format = QLocale::system().dateTimeFormat(QLocale::ShortFormat);
|
const QString timestamp_format = QLocale::system().dateTimeFormat(QLocale::ShortFormat);
|
||||||
const bool challenge_mode = Achievements::IsHardcoreModeActive();
|
|
||||||
for (SaveStateInfo& ssi : available_states)
|
for (SaveStateInfo& ssi : available_states)
|
||||||
{
|
{
|
||||||
if (ssi.global)
|
if (ssi.global)
|
||||||
@ -835,7 +840,6 @@ void MainWindow::populateGameListContextMenu(const GameList::Entry* entry, QWidg
|
|||||||
if (slot < 0)
|
if (slot < 0)
|
||||||
{
|
{
|
||||||
resume_action->setText(tr("Resume (%1)").arg(timestamp_str));
|
resume_action->setText(tr("Resume (%1)").arg(timestamp_str));
|
||||||
resume_action->setEnabled(!challenge_mode);
|
|
||||||
action = resume_action;
|
action = resume_action;
|
||||||
}
|
}
|
||||||
else
|
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 = 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,
|
connect(action, &QAction::triggered,
|
||||||
[this, entry, path = std::move(ssi.path)]() { startFile(entry->path, std::move(path), std::nullopt); });
|
[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));
|
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]() {
|
connect(menu.addAction(tr("Boot and Debug")), &QAction::triggered, [this, entry]() {
|
||||||
openCPUDebugger();
|
openCPUDebugger();
|
||||||
|
|
||||||
std::shared_ptr<SystemBootParameters> boot_params = getSystemBootParameters(entry->path);
|
std::shared_ptr<SystemBootParameters> boot_params = getSystemBootParameters(entry->path);
|
||||||
boot_params->override_start_paused = true;
|
boot_params->override_start_paused = true;
|
||||||
|
boot_params->disable_achievements_hardcore_mode = true;
|
||||||
g_emu_thread->bootSystem(std::move(boot_params));
|
g_emu_thread->bootSystem(std::move(boot_params));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -1805,14 +1810,14 @@ void MainWindow::onToolbarContextMenuRequested(const QPoint& pos)
|
|||||||
updateToolbarActions();
|
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_running = (starting || running);
|
||||||
const bool starting_or_not_running = (starting || !running);
|
const bool starting_or_not_running = (starting || !running);
|
||||||
m_ui.actionStartFile->setDisabled(starting_or_running);
|
m_ui.actionStartFile->setDisabled(starting_or_running);
|
||||||
m_ui.actionStartDisc->setDisabled(starting_or_running);
|
m_ui.actionStartDisc->setDisabled(starting_or_running);
|
||||||
m_ui.actionStartBios->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.actionStartFullscreenUI->setDisabled(starting_or_running);
|
||||||
m_ui.actionStartFullscreenUI2->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.actionReset->setDisabled(starting_or_not_running);
|
||||||
m_ui.actionPause->setDisabled(starting_or_not_running);
|
m_ui.actionPause->setDisabled(starting_or_not_running);
|
||||||
m_ui.actionChangeDisc->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.actionScreenshot->setDisabled(starting_or_not_running);
|
||||||
m_ui.menuChangeDisc->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.menuCheats->setDisabled(starting_or_not_running || achievements_hardcore_mode);
|
||||||
m_ui.actionCPUDebugger->setDisabled(cheevos_challenge_mode);
|
m_ui.actionCPUDebugger->setDisabled(achievements_hardcore_mode);
|
||||||
m_ui.actionMemoryScanner->setDisabled(cheevos_challenge_mode);
|
m_ui.actionMemoryScanner->setDisabled(achievements_hardcore_mode);
|
||||||
m_ui.actionReloadTextureReplacements->setDisabled(starting_or_not_running);
|
m_ui.actionReloadTextureReplacements->setDisabled(starting_or_not_running);
|
||||||
m_ui.actionDumpRAM->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 || cheevos_challenge_mode);
|
m_ui.actionDumpVRAM->setDisabled(starting_or_not_running || achievements_hardcore_mode);
|
||||||
m_ui.actionDumpSPURAM->setDisabled(starting_or_not_running || cheevos_challenge_mode);
|
m_ui.actionDumpSPURAM->setDisabled(starting_or_not_running || achievements_hardcore_mode);
|
||||||
|
|
||||||
m_ui.actionSaveState->setDisabled(starting_or_not_running);
|
m_ui.actionSaveState->setDisabled(starting_or_not_running);
|
||||||
m_ui.menuSaveState->setDisabled(starting_or_not_running);
|
m_ui.menuSaveState->setDisabled(starting_or_not_running);
|
||||||
@ -2045,8 +2050,6 @@ void MainWindow::switchToEmulationView()
|
|||||||
|
|
||||||
void MainWindow::connectSignals()
|
void MainWindow::connectSignals()
|
||||||
{
|
{
|
||||||
updateEmulationActions(false, false, Achievements::IsHardcoreModeActive());
|
|
||||||
|
|
||||||
connect(qApp, &QGuiApplication::applicationStateChanged, this, &MainWindow::onApplicationStateChanged);
|
connect(qApp, &QGuiApplication::applicationStateChanged, this, &MainWindow::onApplicationStateChanged);
|
||||||
connect(m_ui.toolBar, &QToolBar::customContextMenuRequested, this, &MainWindow::onToolbarContextMenuRequested);
|
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::fullscreenUIStartedOrStopped, this, &MainWindow::onFullscreenUIStartedOrStopped);
|
||||||
connect(g_emu_thread, &EmuThread::achievementsLoginRequested, this, &MainWindow::onAchievementsLoginRequested);
|
connect(g_emu_thread, &EmuThread::achievementsLoginRequested, this, &MainWindow::onAchievementsLoginRequested);
|
||||||
connect(g_emu_thread, &EmuThread::achievementsLoginSuccess, this, &MainWindow::onAchievementsLoginSuccess);
|
connect(g_emu_thread, &EmuThread::achievementsLoginSuccess, this, &MainWindow::onAchievementsLoginSuccess);
|
||||||
connect(g_emu_thread, &EmuThread::achievementsChallengeModeChanged, this,
|
connect(g_emu_thread, &EmuThread::achievementsHardcoreModeChanged, this,
|
||||||
&MainWindow::onAchievementsChallengeModeChanged);
|
&MainWindow::onAchievementsHardcoreModeChanged);
|
||||||
connect(g_emu_thread, &EmuThread::onCoverDownloaderOpenRequested, this, &MainWindow::onToolsCoverDownloaderTriggered);
|
connect(g_emu_thread, &EmuThread::onCoverDownloaderOpenRequested, this, &MainWindow::onToolsCoverDownloaderTriggered);
|
||||||
connect(g_emu_thread, &EmuThread::onCreateAuxiliaryRenderWindow, this, &MainWindow::onCreateAuxiliaryRenderWindow,
|
connect(g_emu_thread, &EmuThread::onCreateAuxiliaryRenderWindow, this, &MainWindow::onCreateAuxiliaryRenderWindow,
|
||||||
Qt::BlockingQueuedConnection);
|
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)
|
if (enabled)
|
||||||
{
|
{
|
||||||
@ -2803,7 +2806,8 @@ void MainWindow::onAchievementsChallengeModeChanged(bool enabled)
|
|||||||
QtUtils::CloseAndDeleteWindow(m_memory_scanner_window);
|
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,
|
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()
|
void MainWindow::onToolsMemoryScannerTriggered()
|
||||||
{
|
{
|
||||||
if (Achievements::IsHardcoreModeActive())
|
if (s_achievements_hardcore_mode)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!m_memory_scanner_window)
|
if (!m_memory_scanner_window)
|
||||||
@ -2913,6 +2917,9 @@ void MainWindow::onToolsISOBrowserTriggered()
|
|||||||
|
|
||||||
void MainWindow::openCPUDebugger()
|
void MainWindow::openCPUDebugger()
|
||||||
{
|
{
|
||||||
|
if (s_achievements_hardcore_mode)
|
||||||
|
return;
|
||||||
|
|
||||||
if (!m_debugger_window)
|
if (!m_debugger_window)
|
||||||
{
|
{
|
||||||
m_debugger_window = new DebuggerWindow();
|
m_debugger_window = new DebuggerWindow();
|
||||||
|
@ -151,7 +151,7 @@ private Q_SLOTS:
|
|||||||
void onMediaCaptureStopped();
|
void onMediaCaptureStopped();
|
||||||
void onAchievementsLoginRequested(Achievements::LoginRequestReason reason);
|
void onAchievementsLoginRequested(Achievements::LoginRequestReason reason);
|
||||||
void onAchievementsLoginSuccess(const QString& username, quint32 points, quint32 sc_points, quint32 unread_messages);
|
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,
|
bool onCreateAuxiliaryRenderWindow(RenderAPI render_api, qint32 x, qint32 y, quint32 width, quint32 height,
|
||||||
const QString& title, const QString& icon_name,
|
const QString& title, const QString& icon_name,
|
||||||
Host::AuxiliaryRenderWindowUserData userdata,
|
Host::AuxiliaryRenderWindowUserData userdata,
|
||||||
|
@ -1677,7 +1677,7 @@ void Host::OnAchievementsRefreshed()
|
|||||||
|
|
||||||
void Host::OnAchievementsHardcoreModeChanged(bool enabled)
|
void Host::OnAchievementsHardcoreModeChanged(bool enabled)
|
||||||
{
|
{
|
||||||
emit g_emu_thread->achievementsChallengeModeChanged(enabled);
|
emit g_emu_thread->achievementsHardcoreModeChanged(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Host::OnCoverDownloaderOpenRequested()
|
void Host::OnCoverDownloaderOpenRequested()
|
||||||
|
@ -155,7 +155,7 @@ Q_SIGNALS:
|
|||||||
void achievementsLoginRequested(Achievements::LoginRequestReason reason);
|
void achievementsLoginRequested(Achievements::LoginRequestReason reason);
|
||||||
void achievementsLoginSuccess(const QString& username, quint32 points, quint32 sc_points, quint32 unread_messages);
|
void achievementsLoginSuccess(const QString& username, quint32 points, quint32 sc_points, quint32 unread_messages);
|
||||||
void achievementsRefreshed(quint32 id, const QString& game_info_string);
|
void achievementsRefreshed(quint32 id, const QString& game_info_string);
|
||||||
void achievementsChallengeModeChanged(bool enabled);
|
void achievementsHardcoreModeChanged(bool enabled);
|
||||||
void cheatEnabled(quint32 index, bool enabled);
|
void cheatEnabled(quint32 index, bool enabled);
|
||||||
void mediaCaptureStarted();
|
void mediaCaptureStarted();
|
||||||
void mediaCaptureStopped();
|
void mediaCaptureStopped();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user