Merge pull request #11904 from LillyJadeKatrin/retroachievements-hardcore-v2

RetroAchievements - Hardcore Mode (V2)
This commit is contained in:
Mai 2023-12-05 01:31:54 -05:00 committed by GitHub
commit 6e6695c24b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
57 changed files with 582 additions and 48 deletions

View File

@ -633,6 +633,18 @@ std::recursive_mutex* AchievementManager::GetLock()
return &m_lock;
}
bool AchievementManager::IsHardcoreModeActive() const
{
std::lock_guard lg{m_lock};
if (!Config::Get(Config::RA_HARDCORE_ENABLED))
return false;
if (!Core::IsRunning())
return true;
if (!IsGameLoaded())
return false;
return (m_runtime.trigger_count + m_runtime.lboard_count > 0);
}
std::string AchievementManager::GetPlayerDisplayName() const
{
return IsLoggedIn() ? m_display_name : "";

View File

@ -119,6 +119,7 @@ public:
void AchievementEventHandler(const rc_runtime_event_t* runtime_event);
std::recursive_mutex* GetLock();
bool IsHardcoreModeActive() const;
std::string GetPlayerDisplayName() const;
u32 GetPlayerScore() const;
const BadgeStatus& GetPlayerBadge() const;
@ -190,7 +191,7 @@ private:
Common::WorkQueueThread<std::function<void()>> m_queue;
Common::WorkQueueThread<std::function<void()>> m_image_queue;
std::recursive_mutex m_lock;
mutable std::recursive_mutex m_lock;
}; // class AchievementManager
#endif // USE_RETRO_ACHIEVEMENTS

View File

@ -114,7 +114,7 @@ struct ARAddr
// AR Remote Functions
void ApplyCodes(std::span<const ARCode> codes)
{
if (!Config::Get(Config::MAIN_ENABLE_CHEATS))
if (!Config::AreCheatsEnabled())
return;
std::lock_guard guard(s_lock);
@ -143,7 +143,7 @@ void UpdateSyncedCodes(std::span<const ARCode> codes)
std::vector<ARCode> ApplyAndReturnCodes(std::span<const ARCode> codes)
{
if (Config::Get(Config::MAIN_ENABLE_CHEATS))
if (Config::AreCheatsEnabled())
{
std::lock_guard guard(s_lock);
s_disable_logging = false;
@ -158,7 +158,7 @@ std::vector<ARCode> ApplyAndReturnCodes(std::span<const ARCode> codes)
void AddCode(ARCode code)
{
if (!Config::Get(Config::MAIN_ENABLE_CHEATS))
if (!Config::AreCheatsEnabled())
return;
if (code.enabled)
@ -990,7 +990,7 @@ static bool RunCodeLocked(const Core::CPUThreadGuard& guard, const ARCode& arcod
void RunAllActive(const Core::CPUThreadGuard& cpu_guard)
{
if (!Config::Get(Config::MAIN_ENABLE_CHEATS))
if (!Config::AreCheatsEnabled())
return;
// If the mutex is idle then acquiring it should be cheap, fast mutexes

View File

@ -16,6 +16,7 @@
#include "Common/BitUtils.h"
#include "Common/StringUtil.h"
#include "Core/Config/AchievementSettings.h"
#include "Core/Core.h"
#include "Core/HW/Memmap.h"
#include "Core/PowerPC/MMU.h"
@ -206,6 +207,10 @@ Cheats::NewSearch(const Core::CPUThreadGuard& guard,
PowerPC::RequestedAddressSpace address_space, bool aligned,
const std::function<bool(const T& value)>& validator)
{
#ifdef USE_RETRO_ACHIEVEMENTS
if (Config::Get(Config::RA_HARDCORE_ENABLED))
return Cheats::SearchErrorCode::DisabledInHardcoreMode;
#endif // USE_RETRO_ACHIEVEMENTS
const u32 data_size = sizeof(T);
std::vector<Cheats::SearchResult<T>> results;
Cheats::SearchErrorCode error_code = Cheats::SearchErrorCode::Success;
@ -269,6 +274,10 @@ Cheats::NextSearch(const Core::CPUThreadGuard& guard,
PowerPC::RequestedAddressSpace address_space,
const std::function<bool(const T& new_value, const T& old_value)>& validator)
{
#ifdef USE_RETRO_ACHIEVEMENTS
if (Config::Get(Config::RA_HARDCORE_ENABLED))
return Cheats::SearchErrorCode::DisabledInHardcoreMode;
#endif // USE_RETRO_ACHIEVEMENTS
std::vector<Cheats::SearchResult<T>> results;
Cheats::SearchErrorCode error_code = Cheats::SearchErrorCode::Success;
Core::RunAsCPUThread([&] {
@ -444,6 +453,10 @@ MakeCompareFunctionForLastValue(Cheats::CompareType op)
template <typename T>
Cheats::SearchErrorCode Cheats::CheatSearchSession<T>::RunSearch(const Core::CPUThreadGuard& guard)
{
#ifdef USE_RETRO_ACHIEVEMENTS
if (Config::Get(Config::RA_HARDCORE_ENABLED))
return Cheats::SearchErrorCode::DisabledInHardcoreMode;
#endif // USE_RETRO_ACHIEVEMENTS
Common::Result<SearchErrorCode, std::vector<SearchResult<T>>> result =
Cheats::SearchErrorCode::InvalidParameters;
if (m_filter_type == FilterType::CompareAgainstSpecificValue)

View File

@ -99,6 +99,11 @@ enum class SearchErrorCode
// This is returned if PowerPC::RequestedAddressSpace::Virtual is given but the MSR.DR flag is
// currently off in the emulated game.
VirtualAddressesCurrentlyNotAccessible,
#ifdef USE_RETRO_ACHIEVEMENTS
// Cheats and memory reading are disabled in RetroAchievements hardcore mode.
DisabledInHardcoreMode,
#endif // USE_RETRO_ACHIEVEMENTS
};
// Returns the corresponding DataType enum for the value currently held by the given SearchValue.

View File

@ -1,6 +1,7 @@
// Copyright 2023 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#ifdef USE_RETRO_ACHIEVEMENTS
#include "Core/Config/AchievementSettings.h"
#include <string>
@ -19,6 +20,8 @@ const Info<bool> RA_LEADERBOARDS_ENABLED{
{System::Achievements, "Achievements", "LeaderboardsEnabled"}, false};
const Info<bool> RA_RICH_PRESENCE_ENABLED{
{System::Achievements, "Achievements", "RichPresenceEnabled"}, false};
const Info<bool> RA_HARDCORE_ENABLED{{System::Achievements, "Achievements", "HardcoreEnabled"},
false};
const Info<bool> RA_PROGRESS_ENABLED{{System::Achievements, "Achievements", "ProgressEnabled"},
false};
const Info<bool> RA_BADGES_ENABLED{{System::Achievements, "Achievements", "BadgesEnabled"}, false};
@ -26,3 +29,5 @@ const Info<bool> RA_UNOFFICIAL_ENABLED{{System::Achievements, "Achievements", "U
false};
const Info<bool> RA_ENCORE_ENABLED{{System::Achievements, "Achievements", "EncoreEnabled"}, false};
} // namespace Config
#endif // USE_RETRO_ACHIEVEMENTS

View File

@ -1,6 +1,7 @@
// Copyright 2023 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#ifdef USE_RETRO_ACHIEVEMENTS
#pragma once
#include "Common/Config/Config.h"
@ -14,8 +15,11 @@ extern const Info<std::string> RA_API_TOKEN;
extern const Info<bool> RA_ACHIEVEMENTS_ENABLED;
extern const Info<bool> RA_LEADERBOARDS_ENABLED;
extern const Info<bool> RA_RICH_PRESENCE_ENABLED;
extern const Info<bool> RA_HARDCORE_ENABLED;
extern const Info<bool> RA_PROGRESS_ENABLED;
extern const Info<bool> RA_BADGES_ENABLED;
extern const Info<bool> RA_UNOFFICIAL_ENABLED;
extern const Info<bool> RA_ENCORE_ENABLED;
} // namespace Config
#endif // USE_RETRO_ACHIEVEMENTS

View File

@ -18,6 +18,7 @@
#include "Common/MathUtil.h"
#include "Common/StringUtil.h"
#include "Common/Version.h"
#include "Core/Config/AchievementSettings.h"
#include "Core/Config/DefaultLocale.h"
#include "Core/HW/EXI/EXI.h"
#include "Core/HW/EXI/EXI_Device.h"
@ -738,4 +739,24 @@ bool IsDefaultGCIFolderPathConfigured(ExpansionInterface::Slot slot)
{
return Config::Get(GetInfoForGCIPath(slot)).empty();
}
bool AreCheatsEnabled()
{
#ifdef USE_RETRO_ACHIEVEMENTS
return Config::Get(::Config::MAIN_ENABLE_CHEATS) && !::Config::Get(::Config::RA_HARDCORE_ENABLED);
#else // USE_RETRO_ACHIEVEMENTS
return Config::Get(::Config::MAIN_ENABLE_CHEATS);
#endif // USE_RETRO_ACHIEVEMENTS
}
bool IsDebuggingEnabled()
{
#ifdef USE_RETRO_ACHIEVEMENTS
return Config::Get(::Config::MAIN_ENABLE_DEBUGGING) &&
!::Config::Get(::Config::RA_HARDCORE_ENABLED);
#else // USE_RETRO_ACHIEVEMENTS
return Config::Get(::Config::MAIN_ENABLE_DEBUGGING);
#endif // USE_RETRO_ACHIEVEMENTS
}
} // namespace Config

View File

@ -378,4 +378,6 @@ std::string GetGCIFolderPath(ExpansionInterface::Slot slot, std::optional<DiscIO
std::string GetGCIFolderPath(std::string configured_folder, ExpansionInterface::Slot slot,
std::optional<DiscIO::Region> region);
bool IsDefaultGCIFolderPathConfigured(ExpansionInterface::Slot slot);
bool AreCheatsEnabled();
bool IsDebuggingEnabled();
} // namespace Config

View File

@ -42,6 +42,7 @@
#include "Core/Boot/Boot.h"
#include "Core/BootManager.h"
#include "Core/CPUThreadConfigCallback.h"
#include "Core/Config/AchievementSettings.h"
#include "Core/Config/MainSettings.h"
#include "Core/ConfigManager.h"
#include "Core/CoreTiming.h"
@ -1081,6 +1082,13 @@ void HostDispatchJobs()
// NOTE: Host Thread
void DoFrameStep()
{
#ifdef USE_RETRO_ACHIEVEMENTS
if (AchievementManager::GetInstance()->IsHardcoreModeActive())
{
OSD::AddMessage("Frame stepping is disabled in RetroAchievements hardcore mode");
return;
}
#endif // USE_RETRO_ACHIEVEMENTS
if (GetState() == State::Paused)
{
// if already paused, frame advance for 1 frame

View File

@ -16,13 +16,16 @@
#include "Common/Logging/Log.h"
#include "Common/SPSCQueue.h"
#include "Core/AchievementManager.h"
#include "Core/CPUThreadConfigCallback.h"
#include "Core/Config/AchievementSettings.h"
#include "Core/Config/MainSettings.h"
#include "Core/Core.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"
#include "VideoCommon/Fifo.h"
#include "VideoCommon/OnScreenDisplay.h"
#include "VideoCommon/PerformanceMetrics.h"
#include "VideoCommon/VideoBackendBase.h"
#include "VideoCommon/VideoConfig.h"
@ -135,6 +138,17 @@ void CoreTimingManager::RefreshConfig()
m_max_variance = std::chrono::duration_cast<DT>(DT_ms(Config::Get(Config::MAIN_TIMING_VARIANCE)));
#ifdef USE_RETRO_ACHIEVEMENTS
if (AchievementManager::GetInstance()->IsHardcoreModeActive() &&
Config::Get(Config::MAIN_EMULATION_SPEED) < 1.0f &&
Config::Get(Config::MAIN_EMULATION_SPEED) > 0.0f)
{
Config::SetCurrent(Config::MAIN_EMULATION_SPEED, 1.0f);
m_emulation_speed = 1.0f;
OSD::AddMessage("Minimum speed is 100% in Hardcore Mode");
}
#endif // USE_RETRO_ACHIEVEMENTS
m_emulation_speed = Config::Get(Config::MAIN_EMULATION_SPEED);
}

View File

@ -16,6 +16,7 @@
#include "Common/GekkoDisassembler.h"
#include "Common/StringUtil.h"
#include "Core/Config/AchievementSettings.h"
#include "Core/Config/MainSettings.h"
#include "Core/Core.h"
#include "Core/Debugger/OSThread.h"
@ -29,6 +30,10 @@
void ApplyMemoryPatch(const Core::CPUThreadGuard& guard, Common::Debug::MemoryPatch& patch,
bool store_existing_value)
{
#ifdef USE_RETRO_ACHIEVEMENTS
if (Config::Get(Config::RA_HARDCORE_ENABLED))
return;
#endif // USE_RETRO_ACHIEVEMENTS
if (patch.value.empty())
return;

View File

@ -3,7 +3,9 @@
#include "Core/FreeLookConfig.h"
#include "Core/AchievementManager.h"
#include "Core/CPUThreadConfigCallback.h"
#include "Core/Config/AchievementSettings.h"
#include "Core/Config/FreeLookSettings.h"
#include "Core/ConfigManager.h"
#include "Core/Core.h"
@ -44,6 +46,11 @@ void Config::Refresh()
}
camera_config.control_type = ::Config::Get(::Config::FL1_CONTROL_TYPE);
#ifdef USE_RETRO_ACHIEVEMENTS
enabled = ::Config::Get(::Config::FREE_LOOK_ENABLED) &&
!AchievementManager::GetInstance()->IsHardcoreModeActive();
#else // USE_RETRO_ACHIEVEMENTS
enabled = ::Config::Get(::Config::FREE_LOOK_ENABLED);
#endif // USE_RETRO_ACHIEVEMENTS
}
} // namespace FreeLook

View File

@ -71,7 +71,7 @@ void SetActiveCodes(std::span<const GeckoCode> gcodes)
std::lock_guard lk(s_active_codes_lock);
s_active_codes.clear();
if (Config::Get(Config::MAIN_ENABLE_CHEATS))
if (Config::AreCheatsEnabled())
{
s_active_codes.reserve(gcodes.size());
std::copy_if(gcodes.begin(), gcodes.end(), std::back_inserter(s_active_codes),
@ -103,7 +103,7 @@ std::vector<GeckoCode> SetAndReturnActiveCodes(std::span<const GeckoCode> gcodes
std::lock_guard lk(s_active_codes_lock);
s_active_codes.clear();
if (Config::Get(Config::MAIN_ENABLE_CHEATS))
if (Config::AreCheatsEnabled())
{
s_active_codes.reserve(gcodes.size());
std::copy_if(gcodes.begin(), gcodes.end(), std::back_inserter(s_active_codes),
@ -238,7 +238,7 @@ void Shutdown()
void RunCodeHandler(const Core::CPUThreadGuard& guard)
{
if (!Config::Get(Config::MAIN_ENABLE_CHEATS))
if (!Config::AreCheatsEnabled())
return;
// NOTE: Need to release the lock because of GUI deadlocks with PanicAlert in HostWrite_*

View File

@ -90,7 +90,7 @@ void PatchFixedFunctions(Core::System& system)
// HLE jump to loader (homebrew). Disabled when Gecko is active as it interferes with the code
// handler
if (!Config::Get(Config::MAIN_ENABLE_CHEATS))
if (!Config::AreCheatsEnabled())
{
Patch(system, 0x80001800, "HBReload");
auto& memory = system.GetMemory();
@ -219,7 +219,7 @@ TryReplaceFunctionResult TryReplaceFunction(u32 address)
bool IsEnabled(HookFlag flag)
{
return flag != HLE::HookFlag::Debug || Config::Get(Config::MAIN_ENABLE_DEBUGGING) ||
return flag != HLE::HookFlag::Debug || Config::IsDebuggingEnabled() ||
Core::System::GetInstance().GetPowerPC().GetMode() == PowerPC::CoreMode::Interpreter;
}

View File

@ -34,6 +34,7 @@
#include "Common/Version.h"
#include "Core/Boot/Boot.h"
#include "Core/Config/AchievementSettings.h"
#include "Core/Config/MainSettings.h"
#include "Core/Config/SYSCONFSettings.h"
#include "Core/Config/WiimoteSettings.h"
@ -974,6 +975,12 @@ bool PlayInput(const std::string& movie_path, std::optional<std::string>* savest
}
ReadHeader();
#ifdef USE_RETRO_ACHIEVEMENTS
if (Config::Get(Config::RA_HARDCORE_ENABLED))
return false;
#endif // USE_RETRO_ACHIEVEMENTS
s_totalFrames = tmpHeader.frameCount;
s_totalLagCount = tmpHeader.lagCount;
s_totalInputCount = tmpHeader.inputCount;
@ -1010,6 +1017,12 @@ bool PlayInput(const std::string& movie_path, std::optional<std::string>* savest
}
s_bRecordingFromSaveState = true;
#ifdef USE_RETRO_ACHIEVEMENTS
// On the chance someone tries to re-enable before the TAS can start
Config::SetBase(Config::RA_HARDCORE_ENABLED, false);
#endif // USE_RETRO_ACHIEVEMENTS
Movie::LoadInput(movie_path);
}

View File

@ -1356,7 +1356,7 @@ bool NetPlayServer::SetupNetSettings()
// Copy all relevant settings
settings.cpu_thread = Config::Get(Config::MAIN_CPU_THREAD);
settings.cpu_core = Config::Get(Config::MAIN_CPU_CORE);
settings.enable_cheats = Config::Get(Config::MAIN_ENABLE_CHEATS);
settings.enable_cheats = Config::AreCheatsEnabled();
settings.selected_language = Config::Get(Config::MAIN_GC_LANGUAGE);
settings.override_region_settings = Config::Get(Config::MAIN_OVERRIDE_REGION_SETTINGS);
settings.dsp_hle = Config::Get(Config::MAIN_DSP_HLE);

View File

@ -26,6 +26,7 @@
#include "Core/ActionReplay.h"
#include "Core/CheatCodes.h"
#include "Core/Config/AchievementSettings.h"
#include "Core/Config/SessionSettings.h"
#include "Core/ConfigManager.h"
#include "Core/Core.h"
@ -232,6 +233,10 @@ void LoadPatches()
static void ApplyPatches(const Core::CPUThreadGuard& guard, const std::vector<Patch>& patches)
{
#ifdef USE_RETRO_ACHIEVEMENTS
if (Config::Get(Config::RA_HARDCORE_ENABLED))
return;
#endif // USE_RETRO_ACHIEVEMENTS
for (const Patch& patch : patches)
{
if (patch.enabled)
@ -273,6 +278,10 @@ static void ApplyPatches(const Core::CPUThreadGuard& guard, const std::vector<Pa
static void ApplyMemoryPatches(const Core::CPUThreadGuard& guard,
std::span<const std::size_t> memory_patch_indices)
{
#ifdef USE_RETRO_ACHIEVEMENTS
if (Config::Get(Config::RA_HARDCORE_ENABLED))
return;
#endif // USE_RETRO_ACHIEVEMENTS
std::lock_guard lock(s_on_frame_memory_mutex);
for (std::size_t index : memory_patch_indices)
{

View File

@ -236,7 +236,7 @@ void Interpreter::Run()
core_timing.Advance();
// we have to check exceptions at branches apparently (or maybe just rfi?)
if (Config::Get(Config::MAIN_ENABLE_DEBUGGING))
if (Config::IsDebuggingEnabled())
{
#ifdef SHOW_HISTORY
s_pc_block_vec.push_back(m_ppc_state.pc);

View File

@ -44,7 +44,7 @@ void Jit64AsmRoutineManager::Regenerate()
void Jit64AsmRoutineManager::Generate()
{
const bool enable_debugging = Config::Get(Config::MAIN_ENABLE_DEBUGGING);
const bool enable_debugging = Config::IsDebuggingEnabled();
enter_code = AlignCode16();
// We need to own the beginning of RSP, so we do an extra stack adjustment

View File

@ -30,7 +30,7 @@ void JitArm64::GenerateAsm()
{
const Common::ScopedJITPageWriteAndNoExecute enable_jit_page_writes;
const bool enable_debugging = Config::Get(Config::MAIN_ENABLE_DEBUGGING);
const bool enable_debugging = Config::IsDebuggingEnabled();
// This value is all of the callee saved registers that we are required to save.
// According to the AACPS64 we need to save R19 ~ R30 and Q8 ~ Q15.

View File

@ -31,6 +31,8 @@
#include "Common/Version.h"
#include "Common/WorkQueueThread.h"
#include "Core/AchievementManager.h"
#include "Core/Config/AchievementSettings.h"
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/CoreTiming.h"
@ -204,6 +206,14 @@ void LoadFromBuffer(std::vector<u8>& buffer)
return;
}
#ifdef USE_RETRO_ACHIEVEMENTS
if (AchievementManager::GetInstance()->IsHardcoreModeActive())
{
OSD::AddMessage("Loading savestates is disabled in RetroAchievements hardcore mode");
return;
}
#endif // USE_RETRO_ACHIEVEMENTS
Core::RunOnCPUThread(
[&] {
u8* ptr = buffer.data();
@ -842,6 +852,14 @@ void LoadAs(const std::string& filename)
return;
}
#ifdef USE_RETRO_ACHIEVEMENTS
if (AchievementManager::GetInstance()->IsHardcoreModeActive())
{
OSD::AddMessage("Loading savestates is disabled in RetroAchievements hardcore mode");
return;
}
#endif // USE_RETRO_ACHIEVEMENTS
std::unique_lock lk(s_load_or_save_in_progress_mutex, std::try_to_lock);
if (!lk)
return;

View File

@ -14,6 +14,7 @@
#include "Common/FileUtil.h"
#include "Common/IOFile.h"
#include "Common/StringUtil.h"
#include "Core/Config/AchievementSettings.h"
#include "Core/HLE/HLE.h"
#include "Core/HW/Memmap.h"
#include "Core/IOS/FS/FileSystem.h"
@ -522,6 +523,11 @@ static bool MemoryMatchesAt(const Core::CPUThreadGuard& guard, u32 offset,
static void ApplyMemoryPatch(const Core::CPUThreadGuard& guard, u32 offset,
const std::vector<u8>& value, const std::vector<u8>& original)
{
#ifdef USE_RETRO_ACHIEVEMENTS
if (::Config::Get(::Config::RA_HARDCORE_ENABLED))
return;
#endif // USE_RETRO_ACHIEVEMENTS
if (value.empty())
return;

View File

@ -13,10 +13,11 @@
#include "Core/AchievementManager.h"
#include "Core/Config/AchievementSettings.h"
#include "Core/Config/FreeLookSettings.h"
#include "Core/Config/MainSettings.h"
#include "Core/Core.h"
#include "Core/Movie.h"
#include "DolphinQt/Achievements/AchievementsWindow.h"
#include "DolphinQt/Config/ControllerInterface/ControllerInterfaceWindow.h"
#include "DolphinQt/Config/ToolTipControls/ToolTipCheckBox.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
@ -24,11 +25,7 @@
#include "DolphinQt/QtUtils/SignalBlocking.h"
#include "DolphinQt/Settings.h"
static constexpr bool hardcore_mode_enabled = false;
AchievementSettingsWidget::AchievementSettingsWidget(QWidget* parent,
AchievementsWindow* parent_window)
: QWidget(parent), parent_window(parent_window)
AchievementSettingsWidget::AchievementSettingsWidget(QWidget* parent) : QWidget(parent)
{
CreateLayout();
LoadSettings();
@ -36,6 +33,15 @@ AchievementSettingsWidget::AchievementSettingsWidget(QWidget* parent,
connect(&Settings::Instance(), &Settings::ConfigChanged, this,
&AchievementSettingsWidget::LoadSettings);
// If hardcore is enabled when the emulator starts, make sure it turns off what it needs to
if (Config::Get(Config::RA_HARDCORE_ENABLED))
ToggleHardcore();
}
void AchievementSettingsWidget::UpdateData()
{
LoadSettings();
}
void AchievementSettingsWidget::CreateLayout()
@ -75,6 +81,20 @@ void AchievementSettingsWidget::CreateLayout()
"achievements.<br><br>Unofficial achievements may be optional or unfinished achievements "
"that have not been deemed official by RetroAchievements and may be useful for testing or "
"simply for fun."));
m_common_hardcore_enabled_input = new ToolTipCheckBox(tr("Enable Hardcore Mode"));
m_common_hardcore_enabled_input->SetDescription(
tr("Enable Hardcore Mode on RetroAchievements.<br><br>Hardcore Mode is intended to provide "
"an experience as close to gaming on the original hardware as possible. RetroAchievements "
"rankings are primarily oriented towards Hardcore points (Softcore points are tracked but "
"not as heavily emphasized) and leaderboards require Hardcore Mode to be on.<br><br>To "
"ensure this experience, the following features will be disabled, as they give emulator "
"players an advantage over console players:<br>- Loading states<br>-- Saving states is "
"allowed<br>- Emulator speeds below 100%<br>-- Frame advance is disabled<br>-- Turbo is "
"allowed<br>- Cheats<br>- Memory patches<br>-- File patches are allowed<br>- Debug "
"UI<br>- Freelook<br><br><dolphin_emphasis>This cannot be turned on while a game is "
"playing.</dolphin_emphasis><br>Close your current game before enabling.<br>Be aware that "
"turning Hardcore Mode off while a game is running requires the game to be closed before "
"re-enabling."));
m_common_progress_enabled_input = new ToolTipCheckBox(tr("Enable Progress Notifications"));
m_common_progress_enabled_input->SetDescription(
tr("Enable progress notifications on achievements.<br><br>Displays a brief popup message "
@ -102,6 +122,7 @@ void AchievementSettingsWidget::CreateLayout()
m_common_layout->addWidget(m_common_achievements_enabled_input);
m_common_layout->addWidget(m_common_leaderboards_enabled_input);
m_common_layout->addWidget(m_common_rich_presence_enabled_input);
m_common_layout->addWidget(m_common_hardcore_enabled_input);
m_common_layout->addWidget(m_common_progress_enabled_input);
m_common_layout->addWidget(m_common_badges_enabled_input);
m_common_layout->addWidget(m_common_unofficial_enabled_input);
@ -123,6 +144,8 @@ void AchievementSettingsWidget::ConnectWidgets()
&AchievementSettingsWidget::ToggleLeaderboards);
connect(m_common_rich_presence_enabled_input, &QCheckBox::toggled, this,
&AchievementSettingsWidget::ToggleRichPresence);
connect(m_common_hardcore_enabled_input, &QCheckBox::toggled, this,
&AchievementSettingsWidget::ToggleHardcore);
connect(m_common_progress_enabled_input, &QCheckBox::toggled, this,
&AchievementSettingsWidget::ToggleProgress);
connect(m_common_badges_enabled_input, &QCheckBox::toggled, this,
@ -145,6 +168,7 @@ void AchievementSettingsWidget::LoadSettings()
{
bool enabled = Config::Get(Config::RA_ENABLED);
bool achievements_enabled = Config::Get(Config::RA_ACHIEVEMENTS_ENABLED);
bool hardcore_enabled = Config::Get(Config::RA_HARDCORE_ENABLED);
bool logged_out = Config::Get(Config::RA_API_TOKEN).empty();
std::string username = Config::Get(Config::RA_USERNAME);
@ -167,12 +191,19 @@ void AchievementSettingsWidget::LoadSettings()
SignalBlocking(m_common_leaderboards_enabled_input)
->setChecked(Config::Get(Config::RA_LEADERBOARDS_ENABLED));
SignalBlocking(m_common_leaderboards_enabled_input)->setEnabled(enabled && hardcore_mode_enabled);
SignalBlocking(m_common_leaderboards_enabled_input)->setEnabled(enabled && hardcore_enabled);
SignalBlocking(m_common_rich_presence_enabled_input)
->setChecked(Config::Get(Config::RA_RICH_PRESENCE_ENABLED));
SignalBlocking(m_common_rich_presence_enabled_input)->setEnabled(enabled);
SignalBlocking(m_common_hardcore_enabled_input)
->setChecked(Config::Get(Config::RA_HARDCORE_ENABLED));
SignalBlocking(m_common_hardcore_enabled_input)
->setEnabled(enabled &&
(hardcore_enabled ||
(Core::GetState() == Core::State::Uninitialized && !Movie::IsPlayingInput())));
SignalBlocking(m_common_progress_enabled_input)
->setChecked(Config::Get(Config::RA_PROGRESS_ENABLED));
SignalBlocking(m_common_progress_enabled_input)->setEnabled(enabled && achievements_enabled);
@ -199,6 +230,8 @@ void AchievementSettingsWidget::SaveSettings()
m_common_leaderboards_enabled_input->isChecked());
Config::SetBaseOrCurrent(Config::RA_RICH_PRESENCE_ENABLED,
m_common_rich_presence_enabled_input->isChecked());
Config::SetBaseOrCurrent(Config::RA_HARDCORE_ENABLED,
m_common_hardcore_enabled_input->isChecked());
Config::SetBaseOrCurrent(Config::RA_PROGRESS_ENABLED,
m_common_unofficial_enabled_input->isChecked());
Config::SetBaseOrCurrent(Config::RA_BADGES_ENABLED, m_common_badges_enabled_input->isChecked());
@ -250,6 +283,20 @@ void AchievementSettingsWidget::ToggleRichPresence()
AchievementManager::GetInstance()->ActivateDeactivateRichPresence();
}
void AchievementSettingsWidget::ToggleHardcore()
{
SaveSettings();
if (Config::Get(Config::RA_HARDCORE_ENABLED))
{
if (Config::Get(Config::MAIN_EMULATION_SPEED) < 1.0f)
Config::SetBaseOrCurrent(Config::MAIN_EMULATION_SPEED, 1.0f);
Config::SetBaseOrCurrent(Config::FREE_LOOK_ENABLED, false);
Settings::Instance().SetCheatsEnabled(false);
Settings::Instance().SetDebugModeEnabled(false);
}
emit Settings::Instance().EmulationStateChanged(Core::GetState());
}
void AchievementSettingsWidget::ToggleProgress()
{
SaveSettings();

View File

@ -6,7 +6,6 @@
#ifdef USE_RETRO_ACHIEVEMENTS
#include <QWidget>
class AchievementsWindow;
class QGroupBox;
class QVBoxLayout;
class QLabel;
@ -18,7 +17,8 @@ class AchievementSettingsWidget final : public QWidget
{
Q_OBJECT
public:
explicit AchievementSettingsWidget(QWidget* parent, AchievementsWindow* parent_window);
explicit AchievementSettingsWidget(QWidget* parent);
void UpdateData();
private:
void OnControllerInterfaceConfigure();
@ -41,8 +41,6 @@ private:
void ToggleUnofficial();
void ToggleEncore();
AchievementsWindow* parent_window;
QGroupBox* m_common_box;
QVBoxLayout* m_common_layout;
ToolTipCheckBox* m_common_integration_enabled_input;
@ -56,6 +54,7 @@ private:
ToolTipCheckBox* m_common_achievements_enabled_input;
ToolTipCheckBox* m_common_leaderboards_enabled_input;
ToolTipCheckBox* m_common_rich_presence_enabled_input;
ToolTipCheckBox* m_common_hardcore_enabled_input;
ToolTipCheckBox* m_common_progress_enabled_input;
ToolTipCheckBox* m_common_badges_enabled_input;
ToolTipCheckBox* m_common_unofficial_enabled_input;

View File

@ -16,6 +16,7 @@
#include "DolphinQt/Achievements/AchievementSettingsWidget.h"
#include "DolphinQt/QtUtils/QueueOnObject.h"
#include "DolphinQt/QtUtils/WrapInScrollArea.h"
#include "DolphinQt/Settings.h"
AchievementsWindow::AchievementsWindow(QWidget* parent) : QDialog(parent)
{
@ -26,6 +27,8 @@ AchievementsWindow::AchievementsWindow(QWidget* parent) : QDialog(parent)
ConnectWidgets();
AchievementManager::GetInstance()->SetUpdateCallback(
[this] { QueueOnObject(this, &AchievementsWindow::UpdateData); });
connect(&Settings::Instance(), &Settings::EmulationStateChanged, this,
&AchievementsWindow::UpdateData);
UpdateData();
}
@ -42,11 +45,10 @@ void AchievementsWindow::CreateMainLayout()
m_header_widget = new AchievementHeaderWidget(this);
m_tab_widget = new QTabWidget();
m_settings_widget = new AchievementSettingsWidget(m_tab_widget);
m_progress_widget = new AchievementProgressWidget(m_tab_widget);
m_leaderboard_widget = new AchievementLeaderboardWidget(m_tab_widget);
m_tab_widget->addTab(
GetWrappedWidget(new AchievementSettingsWidget(m_tab_widget, this), this, 125, 100),
tr("Settings"));
m_tab_widget->addTab(GetWrappedWidget(m_settings_widget, this, 125, 100), tr("Settings"));
m_tab_widget->addTab(GetWrappedWidget(m_progress_widget, this, 125, 100), tr("Progress"));
m_tab_widget->setTabVisible(1, AchievementManager::GetInstance()->IsGameLoaded());
m_tab_widget->addTab(GetWrappedWidget(m_leaderboard_widget, this, 125, 100), tr("Leaderboards"));
@ -72,7 +74,7 @@ void AchievementsWindow::UpdateData()
std::lock_guard lg{*AchievementManager::GetInstance()->GetLock()};
m_header_widget->UpdateData();
m_header_widget->setVisible(AchievementManager::GetInstance()->IsLoggedIn());
// Settings tab handles its own updates ... indeed, that calls this
m_settings_widget->UpdateData();
m_progress_widget->UpdateData();
m_tab_widget->setTabVisible(1, AchievementManager::GetInstance()->IsGameLoaded());
m_leaderboard_widget->UpdateData();
@ -81,4 +83,9 @@ void AchievementsWindow::UpdateData()
update();
}
void AchievementsWindow::ForceSettingsTab()
{
m_tab_widget->setCurrentIndex(0);
}
#endif // USE_RETRO_ACHIEVEMENTS

View File

@ -11,6 +11,7 @@
class AchievementHeaderWidget;
class AchievementLeaderboardWidget;
class AchievementSettingsWidget;
class AchievementProgressWidget;
class QDialogButtonBox;
class QTabWidget;
@ -22,6 +23,7 @@ class AchievementsWindow : public QDialog
public:
explicit AchievementsWindow(QWidget* parent);
void UpdateData();
void ForceSettingsTab();
private:
void CreateMainLayout();
@ -30,6 +32,7 @@ private:
AchievementHeaderWidget* m_header_widget;
QTabWidget* m_tab_widget;
AchievementSettingsWidget* m_settings_widget;
AchievementProgressWidget* m_progress_widget;
AchievementLeaderboardWidget* m_leaderboard_widget;
QDialogButtonBox* m_button_box;

View File

@ -102,6 +102,8 @@ add_executable(dolphin-emu
Config/GraphicsModListWidget.h
Config/GraphicsModWarningWidget.cpp
Config/GraphicsModWarningWidget.h
Config/HardcoreWarningWidget.cpp
Config/HardcoreWarningWidget.h
Config/InfoWidget.cpp
Config/InfoWidget.h
Config/LogConfigWidget.cpp

View File

@ -143,6 +143,12 @@ void CheatsManager::RefreshCodeTabs(Core::State state, bool force)
connect(m_ar_code, &ARCodeWidget::OpenGeneralSettings, this, &CheatsManager::OpenGeneralSettings);
connect(m_gecko_code, &GeckoCodeWidget::OpenGeneralSettings, this,
&CheatsManager::OpenGeneralSettings);
#ifdef USE_RETRO_ACHIEVEMENTS
connect(m_ar_code, &ARCodeWidget::OpenAchievementSettings, this,
&CheatsManager::OpenAchievementSettings);
connect(m_gecko_code, &GeckoCodeWidget::OpenAchievementSettings, this,
&CheatsManager::OpenAchievementSettings);
#endif // USE_RETRO_ACHIEVEMENTS
}
void CheatsManager::CreateWidgets()

View File

@ -37,6 +37,9 @@ public:
signals:
void OpenGeneralSettings();
#ifdef USE_RETRO_ACHIEVEMENTS
void OpenAchievementSettings();
#endif // USE_RETRO_ACHIEVEMENTS
void ShowMemory(u32 address);
void RequestWatch(QString name, u32 address);

View File

@ -21,6 +21,7 @@
#include "DolphinQt/Config/CheatCodeEditor.h"
#include "DolphinQt/Config/CheatWarningWidget.h"
#include "DolphinQt/Config/HardcoreWarningWidget.h"
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
@ -55,6 +56,9 @@ ARCodeWidget::~ARCodeWidget() = default;
void ARCodeWidget::CreateWidgets()
{
m_warning = new CheatWarningWidget(m_game_id, m_restart_required, this);
#ifdef USE_RETRO_ACHIEVEMENTS
m_hc_warning = new HardcoreWarningWidget(this);
#endif // USE_RETRO_ACHIEVEMENTS
m_code_list = new QListWidget;
m_code_add = new NonDefaultQPushButton(tr("&Add New Code..."));
m_code_edit = new NonDefaultQPushButton(tr("&Edit Code..."));
@ -76,6 +80,9 @@ void ARCodeWidget::CreateWidgets()
QVBoxLayout* layout = new QVBoxLayout;
layout->addWidget(m_warning);
#ifdef USE_RETRO_ACHIEVEMENTS
layout->addWidget(m_hc_warning);
#endif // USE_RETRO_ACHIEVEMENTS
layout->addWidget(m_code_list);
layout->addLayout(button_layout);
@ -86,6 +93,10 @@ void ARCodeWidget::ConnectWidgets()
{
connect(m_warning, &CheatWarningWidget::OpenCheatEnableSettings, this,
&ARCodeWidget::OpenGeneralSettings);
#ifdef USE_RETRO_ACHIEVEMENTS
connect(m_hc_warning, &HardcoreWarningWidget::OpenAchievementSettings, this,
&ARCodeWidget::OpenAchievementSettings);
#endif // USE_RETRO_ACHIEVEMENTS
connect(m_code_list, &QListWidget::itemChanged, this, &ARCodeWidget::OnItemChanged);
connect(m_code_list, &QListWidget::itemSelectionChanged, this, &ARCodeWidget::OnSelectionChanged);

View File

@ -16,6 +16,9 @@ struct ARCode;
}
class CheatWarningWidget;
#ifdef USE_RETRO_ACHIEVEMENTS
class HardcoreWarningWidget;
#endif // USE_RETRO_ACHIEVEMENTS
class QLabel;
class QListWidget;
class QListWidgetItem;
@ -32,6 +35,9 @@ public:
signals:
void OpenGeneralSettings();
#ifdef USE_RETRO_ACHIEVEMENTS
void OpenAchievementSettings();
#endif // USE_RETRO_ACHIEVEMENTS
private:
void OnSelectionChanged();
@ -56,6 +62,9 @@ private:
u16 m_game_revision;
CheatWarningWidget* m_warning;
#ifdef USE_RETRO_ACHIEVEMENTS
HardcoreWarningWidget* m_hc_warning;
#endif // USE_RETRO_ACHIEVEMENTS
QListWidget* m_code_list;
QPushButton* m_code_add;
QPushButton* m_code_edit;

View File

@ -9,6 +9,8 @@
#include <QPushButton>
#include <QVBoxLayout>
#include "Core/AchievementManager.h"
#include "Core/Config/AchievementSettings.h"
#include "Core/Config/FreeLookSettings.h"
#include "Core/ConfigManager.h"
#include "Core/Core.h"
@ -36,6 +38,10 @@ void FreeLookWidget::CreateLayout()
m_enable_freelook->SetDescription(
tr("Allows manipulation of the in-game camera.<br><br><dolphin_emphasis>If unsure, "
"leave this unchecked.</dolphin_emphasis>"));
#ifdef USE_RETRO_ACHIEVEMENTS
bool hardcore = AchievementManager::GetInstance()->IsHardcoreModeActive();
m_enable_freelook->setEnabled(!hardcore);
#endif // USE_RETRO_ACHIEVEMENTS
m_freelook_controller_configure_button = new NonDefaultQPushButton(tr("Configure Controller"));
m_freelook_control_type = new ConfigChoice({tr("Six Axis"), tr("First Person"), tr("Orbital")},
@ -106,6 +112,10 @@ void FreeLookWidget::LoadSettings()
{
const bool checked = Config::Get(Config::FREE_LOOK_ENABLED);
m_enable_freelook->setChecked(checked);
#ifdef USE_RETRO_ACHIEVEMENTS
bool hardcore = AchievementManager::GetInstance()->IsHardcoreModeActive();
m_enable_freelook->setEnabled(!hardcore);
#endif // USE_RETRO_ACHIEVEMENTS
m_freelook_control_type->setEnabled(checked);
m_freelook_controller_configure_button->setEnabled(checked);
m_freelook_background_input->setEnabled(checked);

View File

@ -9,10 +9,12 @@
#include <QVBoxLayout>
#include "DolphinQt/Config/FreeLookWidget.h"
#include "DolphinQt/Config/HardcoreWarningWidget.h"
FreeLookWindow::FreeLookWindow(QWidget* parent) : QDialog(parent)
{
CreateMainLayout();
ConnectWidgets();
setWindowTitle(tr("Free Look Settings"));
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
@ -20,11 +22,26 @@ FreeLookWindow::FreeLookWindow(QWidget* parent) : QDialog(parent)
void FreeLookWindow::CreateMainLayout()
{
#ifdef USE_RETRO_ACHIEVEMENTS
m_hc_warning = new HardcoreWarningWidget(this);
#endif // USE_RETRO_ACHIEVEMENTS
m_button_box = new QDialogButtonBox(QDialogButtonBox::Close);
connect(m_button_box, &QDialogButtonBox::rejected, this, &QDialog::reject);
auto* main_layout = new QVBoxLayout();
#ifdef USE_RETRO_ACHIEVEMENTS
main_layout->addWidget(m_hc_warning);
#endif // USE_RETRO_ACHIEVEMENTS
main_layout->addWidget(new FreeLookWidget(this));
main_layout->addWidget(m_button_box);
setLayout(main_layout);
}
void FreeLookWindow::ConnectWidgets()
{
#ifdef USE_RETRO_ACHIEVEMENTS
connect(m_hc_warning, &HardcoreWarningWidget::OpenAchievementSettings, this,
&FreeLookWindow::OpenAchievementSettings);
#endif // USE_RETRO_ACHIEVEMENTS
}

View File

@ -5,6 +5,9 @@
#include <QDialog>
#ifdef USE_RETRO_ACHIEVEMENTS
class HardcoreWarningWidget;
#endif // USE_RETRO_ACHIEVEMENTS
class QDialogButtonBox;
class FreeLookWindow final : public QDialog
@ -13,8 +16,17 @@ class FreeLookWindow final : public QDialog
public:
explicit FreeLookWindow(QWidget* parent);
#ifdef USE_RETRO_ACHIEVEMENTS
signals:
void OpenAchievementSettings();
#endif // USE_RETRO_ACHIEVEMENTS
private:
void CreateMainLayout();
void ConnectWidgets();
#ifdef USE_RETRO_ACHIEVEMENTS
HardcoreWarningWidget* m_hc_warning;
#endif // USE_RETRO_ACHIEVEMENTS
QDialogButtonBox* m_button_box;
};

View File

@ -26,6 +26,7 @@
#include "DolphinQt/Config/CheatCodeEditor.h"
#include "DolphinQt/Config/CheatWarningWidget.h"
#include "DolphinQt/Config/HardcoreWarningWidget.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
@ -61,6 +62,9 @@ GeckoCodeWidget::~GeckoCodeWidget() = default;
void GeckoCodeWidget::CreateWidgets()
{
m_warning = new CheatWarningWidget(m_game_id, m_restart_required, this);
#ifdef USE_RETRO_ACHIEVEMENTS
m_hc_warning = new HardcoreWarningWidget(this);
#endif // USE_RETRO_ACHIEVEMENTS
m_code_list = new QListWidget;
m_name_label = new QLabel;
m_creator_label = new QLabel;
@ -102,6 +106,9 @@ void GeckoCodeWidget::CreateWidgets()
auto* layout = new QVBoxLayout;
layout->addWidget(m_warning);
#ifdef USE_RETRO_ACHIEVEMENTS
layout->addWidget(m_hc_warning);
#endif // USE_RETRO_ACHIEVEMENTS
layout->addWidget(m_code_list);
auto* info_layout = new QFormLayout;
@ -150,6 +157,10 @@ void GeckoCodeWidget::ConnectWidgets()
connect(m_download_codes, &QPushButton::clicked, this, &GeckoCodeWidget::DownloadCodes);
connect(m_warning, &CheatWarningWidget::OpenCheatEnableSettings, this,
&GeckoCodeWidget::OpenGeneralSettings);
#ifdef USE_RETRO_ACHIEVEMENTS
connect(m_hc_warning, &HardcoreWarningWidget::OpenAchievementSettings, this,
&GeckoCodeWidget::OpenAchievementSettings);
#endif // USE_RETRO_ACHIEVEMENTS
}
void GeckoCodeWidget::OnSelectionChanged()

View File

@ -11,6 +11,9 @@
#include "Common/CommonTypes.h"
class CheatWarningWidget;
#ifdef USE_RETRO_ACHIEVEMENTS
class HardcoreWarningWidget;
#endif // USE_RETRO_ACHIEVEMENTS
class QLabel;
class QListWidget;
class QListWidgetItem;
@ -32,6 +35,9 @@ public:
signals:
void OpenGeneralSettings();
#ifdef USE_RETRO_ACHIEVEMENTS
void OpenAchievementSettings();
#endif // USE_RETRO_ACHIEVEMENTS
private:
void OnSelectionChanged();
@ -56,6 +62,9 @@ private:
u16 m_game_revision;
CheatWarningWidget* m_warning;
#ifdef USE_RETRO_ACHIEVEMENTS
HardcoreWarningWidget* m_hc_warning;
#endif // USE_RETRO_ACHIEVEMENTS
QListWidget* m_code_list;
QLabel* m_name_label;
QLabel* m_creator_label;

View File

@ -0,0 +1,62 @@
// Copyright 2023 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#ifdef USE_RETRO_ACHIEVEMENTS
#include "DolphinQt/Config/HardcoreWarningWidget.h"
#include <QHBoxLayout>
#include <QLabel>
#include <QPixmap>
#include <QPushButton>
#include <QStyle>
#include "Core/Config/AchievementSettings.h"
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "DolphinQt/Settings.h"
HardcoreWarningWidget::HardcoreWarningWidget(QWidget* parent) : QWidget(parent)
{
CreateWidgets();
ConnectWidgets();
connect(&Settings::Instance(), &Settings::EmulationStateChanged, this, [this] { Update(); });
Update();
}
void HardcoreWarningWidget::CreateWidgets()
{
const auto size = 1.5 * QFontMetrics(font()).height();
QPixmap warning_icon = style()->standardIcon(QStyle::SP_MessageBoxWarning).pixmap(size, size);
auto* icon = new QLabel;
icon->setPixmap(warning_icon);
m_text = new QLabel(tr("This feature is disabled in hardcore mode."));
m_settings_button = new QPushButton(tr("Achievement Settings"));
auto* layout = new QHBoxLayout;
layout->addWidget(icon);
layout->addWidget(m_text, 1);
layout->addWidget(m_settings_button);
layout->setContentsMargins(0, 0, 0, 0);
setLayout(layout);
}
void HardcoreWarningWidget::ConnectWidgets()
{
connect(m_settings_button, &QPushButton::clicked, this,
&HardcoreWarningWidget::OpenAchievementSettings);
}
void HardcoreWarningWidget::Update()
{
setHidden(!Config::Get(Config::RA_HARDCORE_ENABLED));
}
#endif // USE_RETRO_ACHIEVEMENTS

View File

@ -0,0 +1,30 @@
// Copyright 2023 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#ifdef USE_RETRO_ACHIEVEMENTS
#include <QWidget>
class QLabel;
class QPushButton;
class HardcoreWarningWidget : public QWidget
{
Q_OBJECT
public:
explicit HardcoreWarningWidget(QWidget* parent);
signals:
void OpenAchievementSettings();
private:
void CreateWidgets();
void ConnectWidgets();
void Update();
QLabel* m_text;
QPushButton* m_settings_button;
};
#endif // USE_RETRO_ACHIEVEMENTS

View File

@ -14,6 +14,7 @@
#include "Core/ConfigManager.h"
#include "Core/PatchEngine.h"
#include "DolphinQt/Config/HardcoreWarningWidget.h"
#include "DolphinQt/Config/NewPatchDialog.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
@ -40,23 +41,38 @@ PatchesWidget::PatchesWidget(const UICommon::GameFile& game)
void PatchesWidget::CreateWidgets()
{
#ifdef USE_RETRO_ACHIEVEMENTS
m_hc_warning = new HardcoreWarningWidget(this);
#endif // USE_RETRO_ACHIEVEMENTS
m_list = new QListWidget;
m_add_button = new QPushButton(tr("&Add..."));
m_edit_button = new QPushButton();
m_remove_button = new QPushButton(tr("&Remove"));
auto* layout = new QGridLayout;
auto* grid_layout = new QGridLayout;
layout->addWidget(m_list, 0, 0, 1, -1);
layout->addWidget(m_add_button, 1, 0);
layout->addWidget(m_edit_button, 1, 2);
layout->addWidget(m_remove_button, 1, 1);
grid_layout->addWidget(m_list, 0, 0, 1, -1);
grid_layout->addWidget(m_add_button, 1, 0);
grid_layout->addWidget(m_edit_button, 1, 2);
grid_layout->addWidget(m_remove_button, 1, 1);
auto* layout = new QVBoxLayout;
#ifdef USE_RETRO_ACHIEVEMENTS
layout->addWidget(m_hc_warning);
#endif // USE_RETRO_ACHIEVEMENTS
layout->addLayout(grid_layout);
setLayout(layout);
}
void PatchesWidget::ConnectWidgets()
{
#ifdef USE_RETRO_ACHIEVEMENTS
connect(m_hc_warning, &HardcoreWarningWidget::OpenAchievementSettings, this,
&PatchesWidget::OpenAchievementSettings);
#endif // USE_RETRO_ACHIEVEMENTS
connect(m_list, &QListWidget::itemSelectionChanged, this, &PatchesWidget::UpdateActions);
connect(m_list, &QListWidget::itemChanged, this, &PatchesWidget::OnItemChanged);
connect(m_remove_button, &QPushButton::clicked, this, &PatchesWidget::OnRemove);

View File

@ -9,12 +9,11 @@
#include <QWidget>
#include "Common/CommonTypes.h"
#include "Core/PatchEngine.h"
namespace PatchEngine
{
struct Patch;
}
#ifdef USE_RETRO_ACHIEVEMENTS
class HardcoreWarningWidget;
#endif // USE_RETRO_ACHIEVEMENTS
class QListWidget;
class QListWidgetItem;
class QPushButton;
@ -26,9 +25,15 @@ class GameFile;
class PatchesWidget : public QWidget
{
Q_OBJECT
public:
explicit PatchesWidget(const UICommon::GameFile& game);
#ifdef USE_RETRO_ACHIEVEMENTS
signals:
void OpenAchievementSettings();
#endif // USE_RETRO_ACHIEVEMENTS
private:
void CreateWidgets();
void ConnectWidgets();
@ -41,6 +46,9 @@ private:
void OnRemove();
void OnEdit();
#ifdef USE_RETRO_ACHIEVEMENTS
HardcoreWarningWidget* m_hc_warning;
#endif // USE_RETRO_ACHIEVEMENTS
QListWidget* m_list;
QPushButton* m_add_button;
QPushButton* m_edit_button;

View File

@ -51,6 +51,14 @@ PropertiesDialog::PropertiesDialog(QWidget* parent, const UICommon::GameFile& ga
&PropertiesDialog::OpenGeneralSettings);
connect(ar, &ARCodeWidget::OpenGeneralSettings, this, &PropertiesDialog::OpenGeneralSettings);
#ifdef USE_RETRO_ACHIEVEMENTS
connect(ar, &ARCodeWidget::OpenAchievementSettings, this,
&PropertiesDialog::OpenAchievementSettings);
connect(gecko, &GeckoCodeWidget::OpenAchievementSettings, this,
&PropertiesDialog::OpenAchievementSettings);
connect(patches, &PatchesWidget::OpenAchievementSettings, this,
&PropertiesDialog::OpenAchievementSettings);
#endif // USE_RETRO_ACHIEVEMENTS
connect(graphics_mod_list, &GraphicsModListWidget::OpenGraphicsSettings, this,
&PropertiesDialog::OpenGraphicsSettings);

View File

@ -19,4 +19,7 @@ public:
signals:
void OpenGeneralSettings();
void OpenGraphicsSettings();
#ifdef USE_RETRO_ACHIEVEMENTS
void OpenAchievementSettings();
#endif // USE_RETRO_ACHIEVEMENTS
};

View File

@ -160,7 +160,7 @@ void JITWidget::Update()
PPCAnalyst::BlockRegStats fpa;
PPCAnalyst::CodeBlock code_block;
PPCAnalyst::PPCAnalyzer analyzer;
analyzer.SetDebuggingEnabled(Config::Get(Config::MAIN_ENABLE_DEBUGGING));
analyzer.SetDebuggingEnabled(Config::IsDebuggingEnabled());
analyzer.SetBranchFollowingEnabled(Config::Get(Config::MAIN_JIT_FOLLOW_BRANCH));
analyzer.SetFloatExceptionsEnabled(Config::Get(Config::MAIN_FLOAT_EXCEPTIONS));
analyzer.SetDivByZeroExceptionsEnabled(Config::Get(Config::MAIN_DIVIDE_BY_ZERO_EXCEPTIONS));

View File

@ -31,10 +31,8 @@
<AdditionalIncludeDirectories>$(ProjectDir)Settings;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(ProjectDir)TAS;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(ProjectDir)VideoInterface;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<!--Qt 6.3.0 headers use std::aligned_storage instead of alignas-->
<PreprocessorDefinitions>_SILENCE_CXX23_ALIGNED_STORAGE_DEPRECATION_WARNING;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<!--Jump through some hoops to generate a pch file local to this project-->
<AdditionalIncludeDirectories>$(SourceDir)PCH;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>Use</PrecompiledHeader>
@ -87,6 +85,7 @@
<ClCompile Include="Config\Graphics\PostProcessingConfigWindow.cpp" />
<ClCompile Include="Config\GraphicsModListWidget.cpp" />
<ClCompile Include="Config\GraphicsModWarningWidget.cpp" />
<ClCompile Include="Config\HardcoreWarningWidget.cpp" />
<ClCompile Include="Config\InfoWidget.cpp" />
<ClCompile Include="Config\LogConfigWidget.cpp" />
<ClCompile Include="Config\LogWidget.cpp" />
@ -239,7 +238,7 @@
<ClInclude Include="Config\Mapping\MappingIndicator.h" />
<ClInclude Include="Config\Mapping\MappingNumeric.h" />
<ClInclude Include="Config\NewPatchDialog.h" />
<ClInclude Include="Config\PatchesWidget.h" />
<QtMoc Include="Config\PatchesWidget.h" />
<ClInclude Include="Debugger\RegisterColumn.h" />
<ClInclude Include="GBAHost.h" />
<ClInclude Include="QtUtils\ActionHelper.h" />
@ -298,6 +297,7 @@
<QtMoc Include="Config\Graphics\PostProcessingConfigWindow.h" />
<QtMoc Include="Config\GraphicsModListWidget.h" />
<QtMoc Include="Config\GraphicsModWarningWidget.h" />
<QtMoc Include="Config\HardcoreWarningWidget.h" />
<QtMoc Include="Config\InfoWidget.h" />
<QtMoc Include="Config\LogConfigWidget.h" />
<QtMoc Include="Config\LogWidget.h" />

View File

@ -552,6 +552,10 @@ void GameList::OpenProperties()
connect(properties, &PropertiesDialog::OpenGeneralSettings, this, &GameList::OpenGeneralSettings);
connect(properties, &PropertiesDialog::OpenGraphicsSettings, this,
&GameList::OpenGraphicsSettings);
#ifdef USE_RETRO_ACHIEVEMENTS
connect(properties, &PropertiesDialog::OpenAchievementSettings, this,
&GameList::OpenAchievementSettings);
#endif // USE_RETRO_ACHIEVEMENTS
SetQWidgetWindowDecorations(properties);
properties->show();

View File

@ -56,6 +56,9 @@ signals:
void SelectionChanged(std::shared_ptr<const UICommon::GameFile> game_file);
void OpenGeneralSettings();
void OpenGraphicsSettings();
#ifdef USE_RETRO_ACHIEVEMENTS
void OpenAchievementSettings();
#endif // USE_RETRO_ACHIEVEMENTS
private:
void ShowHeaderContextMenu(const QPoint& pos);

View File

@ -17,6 +17,8 @@
#include "Common/Config/Config.h"
#include "Common/Thread.h"
#include "Core/AchievementManager.h"
#include "Core/Config/AchievementSettings.h"
#include "Core/Config/FreeLookSettings.h"
#include "Core/Config/GraphicsSettings.h"
#include "Core/Config/MainSettings.h"
@ -257,7 +259,7 @@ void HotkeyScheduler::Run()
if (auto bt = WiiUtils::GetBluetoothRealDevice())
bt->UpdateSyncButtonState(IsHotkey(HK_TRIGGER_SYNC_BUTTON, true));
if (Config::Get(Config::MAIN_ENABLE_DEBUGGING))
if (Config::IsDebuggingEnabled())
{
CheckDebuggingHotkeys();
}
@ -579,7 +581,15 @@ void HotkeyScheduler::Run()
{
const bool new_value = !Config::Get(Config::FREE_LOOK_ENABLED);
Config::SetCurrent(Config::FREE_LOOK_ENABLED, new_value);
#ifdef USE_RETRO_ACHIEVEMENTS
bool hardcore = AchievementManager::GetInstance()->IsHardcoreModeActive();
if (hardcore)
OSD::AddMessage("Free Look is Disabled in Hardcore Mode");
else
OSD::AddMessage(fmt::format("Free Look: {}", new_value ? "Enabled" : "Disabled"));
#else // USE_RETRO_ACHIEVEMENTS
OSD::AddMessage(fmt::format("Free Look: {}", new_value ? "Enabled" : "Disabled"));
#endif // USE_RETRO_ACHIEVEMENTS
}
// Savestates

View File

@ -246,6 +246,13 @@ MainWindow::MainWindow(std::unique_ptr<BootParameters> boot_parameters,
connect(m_cheats_manager, &CheatsManager::OpenGeneralSettings, this,
&MainWindow::ShowGeneralWindow);
#ifdef USE_RETRO_ACHIEVEMENTS
connect(m_cheats_manager, &CheatsManager::OpenAchievementSettings, this,
&MainWindow::ShowAchievementSettings);
connect(m_game_list, &GameList::OpenAchievementSettings, this,
&MainWindow::ShowAchievementSettings);
#endif // USE_RETRO_ACHIEVEMENTS
InitCoreCallbacks();
NetPlayInit();
@ -1239,6 +1246,11 @@ void MainWindow::ShowFreeLookWindow()
{
m_freelook_window = new FreeLookWindow(this);
InstallHotkeyFilter(m_freelook_window);
#ifdef USE_RETRO_ACHIEVEMENTS
connect(m_freelook_window, &FreeLookWindow::OpenAchievementSettings, this,
&MainWindow::ShowAchievementSettings);
#endif // USE_RETRO_ACHIEVEMENTS
}
SetQWidgetWindowDecorations(m_freelook_window);
@ -1971,6 +1983,12 @@ void MainWindow::ShowAchievementsWindow()
m_achievements_window->raise();
m_achievements_window->activateWindow();
}
void MainWindow::ShowAchievementSettings()
{
ShowAchievementsWindow();
m_achievements_window->ForceSettingsTab();
}
#endif // USE_RETRO_ACHIEVEMENTS
void MainWindow::ShowMemcardManager()
@ -2011,6 +2029,12 @@ void MainWindow::ShowRiivolutionBootWidget(const UICommon::GameFile& game)
RiivolutionBootWidget w(disc.volume->GetGameID(), disc.volume->GetRevision(),
disc.volume->GetDiscNumber(), game.GetFilePath(), this);
SetQWidgetWindowDecorations(&w);
#ifdef USE_RETRO_ACHIEVEMENTS
connect(&w, &RiivolutionBootWidget::OpenAchievementSettings, this,
&MainWindow::ShowAchievementSettings);
#endif // USE_RETRO_ACHIEVEMENTS
w.exec();
if (!w.ShouldBoot())
return;

View File

@ -175,6 +175,7 @@ private:
#ifdef USE_RETRO_ACHIEVEMENTS
void ShowAchievementsWindow();
void ShowAchievementSettings();
#endif // USE_RETRO_ACHIEVEMENTS
void NetPlayInit();

View File

@ -20,6 +20,7 @@
#include "Common/FileUtil.h"
#include "Common/StringUtil.h"
#include "Core/AchievementManager.h"
#include "Core/Boot/Boot.h"
#include "Core/CommonTitles.h"
#include "Core/Config/AchievementSettings.h"
@ -120,11 +121,18 @@ void MenuBar::OnEmulationStateChanged(Core::State state)
m_stop_action->setVisible(running);
m_reset_action->setEnabled(running);
m_fullscreen_action->setEnabled(running);
m_frame_advance_action->setEnabled(running);
m_screenshot_action->setEnabled(running);
m_state_load_menu->setEnabled(running);
m_state_save_menu->setEnabled(running);
#ifdef USE_RETRO_ACHIEVEMENTS
bool hardcore = AchievementManager::GetInstance()->IsHardcoreModeActive();
m_state_load_menu->setEnabled(running && !hardcore);
m_frame_advance_action->setEnabled(running && !hardcore);
#else // USE_RETRO_ACHIEVEMENTS
m_state_load_menu->setEnabled(running);
m_frame_advance_action->setEnabled(running);
#endif // USE_RETRO_ACHIEVEMENTS
// Movie
m_recording_read_only->setEnabled(running);
if (!running)
@ -133,6 +141,11 @@ void MenuBar::OnEmulationStateChanged(Core::State state)
m_recording_export->setEnabled(false);
}
m_recording_play->setEnabled(m_game_selected && !running);
#ifdef USE_RETRO_ACHIEVEMENTS
m_recording_play->setEnabled(m_game_selected && !running && !hardcore);
#else // USE_RETRO_ACHIEVEMENTS
m_recording_play->setEnabled(m_game_selected && !running);
#endif // USE_RETRO_ACHIEVEMENTS
m_recording_start->setEnabled((m_game_selected || running) && !Movie::IsPlayingInput());
// JIT

View File

@ -26,6 +26,7 @@
#include "DiscIO/GameModDescriptor.h"
#include "DiscIO/RiivolutionParser.h"
#include "DiscIO/RiivolutionPatcher.h"
#include "DolphinQt/Config/HardcoreWarningWidget.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
struct GuiRiivolutionPatchIndex
@ -48,6 +49,7 @@ RiivolutionBootWidget::RiivolutionBootWidget(std::string game_id, std::optional<
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
CreateWidgets();
ConnectWidgets();
LoadMatchingXMLs();
resize(QSize(400, 600));
@ -57,6 +59,9 @@ RiivolutionBootWidget::~RiivolutionBootWidget() = default;
void RiivolutionBootWidget::CreateWidgets()
{
#ifdef USE_RETRO_ACHIEVEMENTS
m_hc_warning = new HardcoreWarningWidget(this);
#endif // USE_RETRO_ACHIEVEMENTS
auto* open_xml_button = new QPushButton(tr("Open Riivolution XML..."));
auto* boot_game_button = new QPushButton(tr("Start"));
boot_game_button->setDefault(true);
@ -79,6 +84,9 @@ void RiivolutionBootWidget::CreateWidgets()
button_layout->addWidget(boot_game_button, 0, Qt::AlignRight);
auto* layout = new QVBoxLayout();
#ifdef USE_RETRO_ACHIEVEMENTS
layout->addWidget(m_hc_warning);
#endif // USE_RETRO_ACHIEVEMENTS
layout->addWidget(scroll_area);
layout->addLayout(button_layout);
setLayout(layout);
@ -88,6 +96,16 @@ void RiivolutionBootWidget::CreateWidgets()
connect(save_preset_button, &QPushButton::clicked, this, &RiivolutionBootWidget::SaveAsPreset);
}
void RiivolutionBootWidget::ConnectWidgets()
{
#ifdef USE_RETRO_ACHIEVEMENTS
connect(m_hc_warning, &HardcoreWarningWidget::OpenAchievementSettings, this,
&RiivolutionBootWidget::OpenAchievementSettings);
connect(m_hc_warning, &HardcoreWarningWidget::OpenAchievementSettings, this,
&RiivolutionBootWidget::reject);
#endif // USE_RETRO_ACHIEVEMENTS
}
void RiivolutionBootWidget::LoadMatchingXMLs()
{
const std::string& riivolution_dir = File::GetUserPath(D_RIIVOLUTION_IDX);

View File

@ -11,6 +11,9 @@
#include "Common/CommonTypes.h"
#include "DiscIO/RiivolutionParser.h"
#ifdef USE_RETRO_ACHIEVEMENTS
class HardcoreWarningWidget;
#endif // USE_RETRO_ACHIEVEMENTS
class QPushButton;
class QVBoxLayout;
@ -26,8 +29,14 @@ public:
bool ShouldBoot() const { return m_should_boot; }
std::vector<DiscIO::Riivolution::Patch>& GetPatches() { return m_patches; }
#ifdef USE_RETRO_ACHIEVEMENTS
signals:
void OpenAchievementSettings();
#endif // USE_RETRO_ACHIEVEMENTS
private:
void CreateWidgets();
void ConnectWidgets();
void LoadMatchingXMLs();
void OpenXML();
@ -38,6 +47,9 @@ private:
void BootGame();
void SaveAsPreset();
#ifdef USE_RETRO_ACHIEVEMENTS
HardcoreWarningWidget* m_hc_warning;
#endif // USE_RETRO_ACHIEVEMENTS
std::string m_game_id;
std::optional<u16> m_revision;
std::optional<u8> m_disc_number;

View File

@ -33,6 +33,7 @@
#include "Common/FileUtil.h"
#include "Common/StringUtil.h"
#include "Core/Config/AchievementSettings.h"
#include "Core/Config/GraphicsSettings.h"
#include "Core/Config/MainSettings.h"
#include "Core/ConfigManager.h"
@ -563,6 +564,10 @@ void Settings::SetCheatsEnabled(bool enabled)
void Settings::SetDebugModeEnabled(bool enabled)
{
#ifdef USE_RETRO_ACHIEVEMENTS
if (Config::Get(Config::RA_HARDCORE_ENABLED))
enabled = false;
#endif // USE_RETRO_ACHIEVEMENTS
if (IsDebugModeEnabled() != enabled)
{
Config::SetBaseOrCurrent(Config::MAIN_ENABLE_DEBUGGING, enabled);

View File

@ -15,6 +15,7 @@
#include <QVBoxLayout>
#include <QWidget>
#include "Core/Config/AchievementSettings.h"
#include "Core/Config/MainSettings.h"
#include "Core/Config/UISettings.h"
#include "Core/ConfigManager.h"
@ -84,7 +85,12 @@ void GeneralPane::OnEmulationStateChanged(Core::State state)
const bool running = state != Core::State::Uninitialized;
m_checkbox_dualcore->setEnabled(!running);
#ifdef USE_RETRO_ACHIEVEMENTS
bool hardcore = Config::Get(Config::RA_HARDCORE_ENABLED);
m_checkbox_cheats->setEnabled(!running && !hardcore);
#else // USE_RETRO_ACHIEVEMENTS
m_checkbox_cheats->setEnabled(!running);
#endif // USE_RETRO_ACHIEVEMENTS
m_checkbox_override_region_settings->setEnabled(!running);
#ifdef USE_DISCORD_PRESENCE
m_checkbox_discord_presence->setEnabled(!running);

View File

@ -19,9 +19,11 @@
#include "Common/MsgHandler.h"
#include "Common/StringUtil.h"
#include "Core/Config/AchievementSettings.h"
#include "Core/Config/MainSettings.h"
#include "Core/Config/UISettings.h"
#include "DolphinQt/Config/ToolTipControls/ToolTipCheckBox.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/SignalBlocking.h"
#include "DolphinQt/Settings.h"
@ -84,6 +86,9 @@ InterfacePane::InterfacePane(QWidget* parent) : QWidget(parent)
CreateLayout();
LoadConfig();
ConnectLayout();
connect(&Settings::Instance(), &Settings::EmulationStateChanged, this,
&InterfacePane::LoadConfig);
}
void InterfacePane::CreateLayout()
@ -151,7 +156,7 @@ void InterfacePane::CreateUI()
m_checkbox_use_builtin_title_database = new QCheckBox(tr("Use Built-In Database of Game Names"));
m_checkbox_use_covers =
new QCheckBox(tr("Download Game Covers from GameTDB.com for Use in Grid Mode"));
m_checkbox_show_debugging_ui = new QCheckBox(tr("Enable Debugging UI"));
m_checkbox_show_debugging_ui = new ToolTipCheckBox(tr("Enable Debugging UI"));
m_checkbox_focused_hotkeys = new QCheckBox(tr("Hotkeys Require Window Focus"));
m_checkbox_disable_screensaver = new QCheckBox(tr("Inhibit Screensaver During Emulation"));
@ -249,6 +254,21 @@ void InterfacePane::LoadConfig()
->setChecked(Config::Get(Config::MAIN_USE_BUILT_IN_TITLE_DATABASE));
SignalBlocking(m_checkbox_show_debugging_ui)
->setChecked(Settings::Instance().IsDebugModeEnabled());
#ifdef USE_RETRO_ACHIEVEMENTS
bool hardcore = Config::Get(Config::RA_HARDCORE_ENABLED);
SignalBlocking(m_checkbox_show_debugging_ui)->setEnabled(!hardcore);
if (hardcore)
{
m_checkbox_show_debugging_ui->SetDescription(
tr("<dolphin_emphasis>Disabled in Hardcore Mode.</dolphin_emphasis>"));
}
else
{
m_checkbox_show_debugging_ui->SetDescription({});
}
#endif // USE_RETRO_ACHIEVEMENTS
SignalBlocking(m_combobox_language)
->setCurrentIndex(m_combobox_language->findData(
QString::fromStdString(Config::Get(Config::MAIN_INTERFACE_LANGUAGE))));

View File

@ -10,6 +10,7 @@ class QComboBox;
class QLabel;
class QRadioButton;
class QVBoxLayout;
class ToolTipCheckBox;
class InterfacePane final : public QWidget
{
@ -36,7 +37,8 @@ private:
QLabel* m_label_userstyle;
QCheckBox* m_checkbox_top_window;
QCheckBox* m_checkbox_use_builtin_title_database;
QCheckBox* m_checkbox_show_debugging_ui;
QCheckBox* m_checkbox_use_userstyle;
ToolTipCheckBox* m_checkbox_show_debugging_ui;
QCheckBox* m_checkbox_focused_hotkeys;
QCheckBox* m_checkbox_use_covers;
QCheckBox* m_checkbox_disable_screensaver;