1
0
mirror of https://github.com/dolphin-emu/dolphin synced 2024-06-28 22:46:42 +00:00

Compare commits

...

22 Commits

Author SHA1 Message Date
JosJuice
fde7dc1c43
Merge c0a1f5e123 into 10a95a4d5b 2024-06-25 23:00:20 +02:00
OatmealDome
10a95a4d5b
Merge pull request #12890 from OatmealDome/release-stuff
Miscellaneous release string updates
2024-06-25 01:25:08 -04:00
OatmealDome
04b0ceedcd Android: Update copyright year in About dialog to 2024 2024-06-24 15:08:12 -04:00
OatmealDome
9c432e960b AboutDialog: Update copyright year to 2024 2024-06-24 15:06:54 -04:00
OatmealDome
f8f117e599 GeneralPane: Update "Beta" auto update track to "Releases" 2024-06-24 15:06:37 -04:00
JMC47
c536754ffe
Merge pull request #12878 from LillyJadeKatrin/retroachievements-hardcore-state-changed
Decouple Hardcore from EmulationStateChanged
2024-06-23 18:13:56 -04:00
Admiral H. Curtiss
e9e29daca4
Merge pull request #12872 from LillyJadeKatrin/retroachievements-start-session-bug
Add MemoryVerifier to AchievementManager Startup
2024-06-23 21:18:34 +02:00
Admiral H. Curtiss
2aec195ec8
Merge pull request #12876 from dreamsyntax/advanced-cpu-clock-override-step-adjustment
DolphinQt: Adjust CPU Clock Override slider
2024-06-23 15:28:29 +02:00
Admiral H. Curtiss
c337ab6473
Merge pull request #12884 from Tilka/qt_this
DolphinQt: fix some warnings
2024-06-23 15:08:13 +02:00
Admiral H. Curtiss
a75c65bde2
Merge pull request #12879 from LillyJadeKatrin/retroachievements-1200-shines
Trim extra characters from measured progress
2024-06-23 15:05:09 +02:00
Admiral H. Curtiss
28692681ad
Merge pull request #12883 from LillyJadeKatrin/retroachievements-cutoff-text
Fix cut off text in Achievements dialog
2024-06-23 14:59:54 +02:00
LillyJadeKatrin
bf230a9909 Trim extra characters from measured progress
The measured_progress C string for achievements to display potentially contains junk data after the null terminator, which was rendering in the QString in the dialog. This trims those junk characters.
2024-06-22 23:36:06 -04:00
OatmealDome
883195f171
Merge pull request #12886 from AdmiralCurtiss/dual-core-lockup
Core/VideoCommon: Revert change from #12828
2024-06-22 22:22:52 -04:00
Admiral H. Curtiss
ce2f4101f3
Core/VideoCommon: Revert change from #12828
This causes Dual Core to lock up during the boot sequence, because it tries to wait for a not-yet-running GPU thread.

Fixes https://bugs.dolphin-emu.org/issues/13559
2024-06-23 03:44:05 +02:00
Tillmann Karras
8e7d11d1a1 DolphinQt: fix -Wunused-const-variable warning 2024-06-23 02:38:04 +01:00
Tillmann Karras
5c46716d28 DolphinQt: fix two -Wshadow-uncaptured-local warnings 2024-06-23 02:38:00 +01:00
Tillmann Karras
0f659508ea DolphinQt: fix two -Wunused-lambda-capture warnings
Also clean up signals a bit.
2024-06-23 00:13:58 +01:00
LillyJadeKatrin
aa393dfb6e Add MemoryVerifier to AchievementManager Startup
rc_client calls the provided memory peeker asynchronously in the callback for starting a session, to validate/invalidate the memory used for achievements. Dolphin cannot access memory from any thread but host or CPU so this access has a small chance of being invalid. This commit adds a MemoryVerifier that the AchievementManager will use to perform this, before changing the peek method back to the original MemoryPeeker for normal operation.
2024-06-22 09:31:00 -04:00
LillyJadeKatrin
e1a8dc65ce Fix cut off text in Achievements dialog 2024-06-22 00:26:52 -04:00
LillyJadeKatrin
29f1b82f5e Decouple Hardcore from EmulationStateChanged
Rerendering the entire Achievements dialog every EmulationStateChanged signal is far too often when it turns out that signal fires multiple times to confirm game close, for example. This change results in only the settings changing on EmulationStateChanged, and having the Hardcore mode toggle (which DOES require redrawing the entire dialog) emit its own signal alongside EmulationStateChanged.
2024-06-20 07:59:59 -04:00
dreamsyntax
55ba014fed DolphinQt: Adjust CPU Clock Override slider
CPU Clock Override slider now increments 1% in the UI, with the new lower limit
being 1% instead of 6%.

Prior implementation made it impossible to set exactly 150% in the GUI.
147% -> 152%. Now users can set exact clock % without needing to edit INIs.
2024-06-18 18:52:35 -07:00
JosJuice
c0a1f5e123 PPCAnalyst: Refactor mtspr handling code
Less magic numbers this way. No functional change.
2024-05-26 11:14:18 +02:00
17 changed files with 101 additions and 63 deletions

View File

@ -874,7 +874,7 @@ It can efficiently compress both junk data and encrypted Wii data.
<string name="about_website"><a href="https://dolphin-emu.org/">Website</a></string>
<string name="about_github"><a href="https://github.com/dolphin-emu/dolphin">GitHub</a></string>
<string name="about_support"><a href="https://forums.dolphin-emu.org/">Support</a></string>
<string name="about_copyright_warning">\u00A9 20032015+ Dolphin Team. \u201cGameCube\u201d and \u201cWii\u201d are trademarks of Nintendo. Dolphin is not affiliated with Nintendo in any way.</string>
<string name="about_copyright_warning">\u00A9 20032024+ Dolphin Team. \u201cGameCube\u201d and \u201cWii\u201d are trademarks of Nintendo. Dolphin is not affiliated with Nintendo in any way.</string>
<string name="system_driver">System driver</string>
<string name="system_driver_desc">The GPU driver that is part of the OS.</string>

View File

@ -13,6 +13,7 @@
#include <rcheevos/include/rc_api_info.h>
#include <rcheevos/include/rc_hash.h>
#include "Common/Assert.h"
#include "Common/CommonPaths.h"
#include "Common/FileUtil.h"
#include "Common/Image.h"
@ -22,6 +23,7 @@
#include "Common/WorkQueueThread.h"
#include "Core/Config/AchievementSettings.h"
#include "Core/Core.h"
#include "Core/HW/Memmap.h"
#include "Core/PowerPC/MMU.h"
#include "Core/System.h"
#include "DiscIO/Blob.h"
@ -44,7 +46,7 @@ void AchievementManager::Init()
LoadDefaultBadges();
if (!m_client && Config::Get(Config::RA_ENABLED))
{
m_client = rc_client_create(MemoryPeeker, Request);
m_client = rc_client_create(MemoryVerifier, Request);
std::string host_url = Config::Get(Config::RA_HOST_URL);
if (!host_url.empty())
rc_client_set_host(m_client, host_url.c_str());
@ -120,6 +122,7 @@ void AchievementManager::LoadGame(const std::string& file_path, const DiscIO::Vo
rc_client_set_unofficial_enabled(m_client, Config::Get(Config::RA_UNOFFICIAL_ENABLED));
rc_client_set_encore_mode_enabled(m_client, Config::Get(Config::RA_ENCORE_ENABLED));
rc_client_set_spectator_mode_enabled(m_client, Config::Get(Config::RA_SPECTATOR_ENABLED));
rc_client_set_read_memory_function(m_client, MemoryVerifier);
if (volume)
{
std::lock_guard lg{m_lock};
@ -679,13 +682,14 @@ void AchievementManager::LoadGameCallback(int result, const char* error_message,
}
INFO_LOG_FMT(ACHIEVEMENTS, "Loaded data for game ID {}.", game->id);
AchievementManager::GetInstance().m_display_welcome_message = true;
AchievementManager::GetInstance().FetchGameBadges();
AchievementManager::GetInstance().m_system = &Core::System::GetInstance();
AchievementManager::GetInstance().m_update_callback({.all = true});
auto& instance = AchievementManager::GetInstance();
rc_client_set_read_memory_function(instance.m_client, MemoryPeeker);
instance.m_display_welcome_message = true;
instance.FetchGameBadges();
instance.m_system = &Core::System::GetInstance();
instance.m_update_callback({.all = true});
// Set this to a value that will immediately trigger RP
AchievementManager::GetInstance().m_last_rp_time =
std::chrono::steady_clock::now() - std::chrono::minutes{2};
instance.m_last_rp_time = std::chrono::steady_clock::now() - std::chrono::minutes{2};
}
void AchievementManager::ChangeMediaCallback(int result, const char* error_message,
@ -706,6 +710,7 @@ void AchievementManager::ChangeMediaCallback(int result, const char* error_messa
ERROR_LOG_FMT(ACHIEVEMENTS, "RetroAchievements media change failed: {}", error_message);
}
rc_client_set_read_memory_function(AchievementManager::GetInstance().m_client, MemoryPeeker);
}
void AchievementManager::DisplayWelcomeMessage()
@ -914,11 +919,36 @@ void AchievementManager::Request(const rc_api_request_t* request,
});
}
// Currently, when rc_client calls the memory peek method provided in its constructor (or in
// rc_client_set_read_memory_function) it will do so on the thread that calls DoFrame, which is
// currently the host thread, with one exception: an asynchronous callback in the load game process.
// This is done to validate/invalidate each memory reference in the downloaded assets, mark assets
// as unsupported, and notify the player upon startup that there are unsupported assets and how
// many. As such, all that call needs to do is return the number of bytes that can be read with this
// call. As only the CPU and host threads are allowed to read from memory, I provide a separate
// method for this verification. In lieu of a more convenient set of steps, I provide MemoryVerifier
// to rc_client at construction, and in the Load Game callback, after the verification has been
// complete, I call rc_client_set_read_memory_function to switch to the usual MemoryPeeker for all
// future synchronous calls.
u32 AchievementManager::MemoryVerifier(u32 address, u8* buffer, u32 num_bytes, rc_client_t* client)
{
auto& system = Core::System::GetInstance();
u32 ram_size = system.GetMemory().GetRamSizeReal();
if (address >= ram_size)
return 0;
return std::min(ram_size - address, num_bytes);
}
u32 AchievementManager::MemoryPeeker(u32 address, u8* buffer, u32 num_bytes, rc_client_t* client)
{
if (buffer == nullptr)
return 0u;
auto& system = Core::System::GetInstance();
if (!(Core::IsHostThread() || Core::IsCPUThread()))
{
ASSERT_MSG(ACHIEVEMENTS, false, "MemoryPeeker called from wrong thread");
return 0;
}
Core::CPUThreadGuard threadguard(system);
for (u32 num_read = 0; num_read < num_bytes; num_read++)
{

View File

@ -177,6 +177,7 @@ private:
static void Request(const rc_api_request_t* request, rc_client_server_callback_t callback,
void* callback_data, rc_client_t* client);
static u32 MemoryVerifier(u32 address, u8* buffer, u32 num_bytes, rc_client_t* client);
static u32 MemoryPeeker(u32 address, u8* buffer, u32 num_bytes, rc_client_t* client);
void FetchBadge(Badge* badge, u32 badge_type, const BadgeNameFunction function,
const UpdatedItems callback_data);

View File

@ -202,21 +202,27 @@ static void AnalyzeFunction2(PPCSymbolDB* func_db, Common::Symbol* func)
func->flags = flags;
}
static bool IsMfspr(UGeckoInstruction inst)
{
return inst.OPCD == 31 && inst.SUBOP10 == 339;
}
static bool IsMtspr(UGeckoInstruction inst)
{
return inst.OPCD == 31 && inst.SUBOP10 == 467;
}
static bool IsSprInstructionUsingMmcr(UGeckoInstruction inst)
static u32 GetSPRIndex(UGeckoInstruction inst)
{
const u32 index = (inst.SPRU << 5) | (inst.SPRL & 0x1F);
return index == SPR_MMCR0 || index == SPR_MMCR1;
DEBUG_ASSERT(IsMfspr(inst) || IsMtspr(inst));
return (inst.SPRU << 5) | (inst.SPRL & 0x1F);
}
static bool InstructionCanEndBlock(const CodeOp& op)
{
return (op.opinfo->flags & FL_ENDBLOCK) &&
(!IsMtspr(op.inst) || IsSprInstructionUsingMmcr(op.inst));
(!IsMtspr(op.inst) || GetSPRIndex(op.inst) == SPR_MMCR0 ||
GetSPRIndex(op.inst) == SPR_MMCR1);
}
bool PPCAnalyzer::CanSwapAdjacentOps(const CodeOp& a, const CodeOp& b) const
@ -637,10 +643,10 @@ void PPCAnalyzer::SetInstructionStats(CodeBlock* block, CodeOp* code,
// mfspr/mtspr can affect/use XER, so be super careful here
// we need to note specifically that mfspr needs CA in XER, not in the x86 carry flag
if (code->inst.OPCD == 31 && code->inst.SUBOP10 == 339) // mfspr
code->wantsCA = ((code->inst.SPRU << 5) | (code->inst.SPRL & 0x1F)) == SPR_XER;
if (code->inst.OPCD == 31 && code->inst.SUBOP10 == 467) // mtspr
code->outputCA = ((code->inst.SPRU << 5) | (code->inst.SPRL & 0x1F)) == SPR_XER;
if (IsMfspr(code->inst))
code->wantsCA = GetSPRIndex(code->inst) == SPR_XER;
if (IsMtspr(code->inst))
code->outputCA = GetSPRIndex(code->inst) == SPR_XER;
code->regsIn = BitSet32(0);
code->regsOut = BitSet32(0);
@ -892,7 +898,7 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock* block, CodeBuffer* buffer,
// Through it would be easy to track the upper level of call/return,
// we can't guarantee the LR value. The PPC ABI forces all functions to push
// the LR value on the stack as there are no spare registers. So we'd need
// to check all store instruction to not alias with the stack.
// to check all store instructions to not alias with the stack.
follow = true;
found_call = false;
code[i].skip = true;
@ -901,16 +907,10 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock* block, CodeBuffer* buffer,
code[caller].skipLRStack = true;
}
}
else if (inst.OPCD == 31 && inst.SUBOP10 == 467)
else if (IsMtspr(inst) && GetSPRIndex(inst) == SPR_LR)
{
// mtspr, skip CALL/RET merging as LR is overwritten.
const u32 index = (inst.SPRU << 5) | (inst.SPRL & 0x1F);
if (index == SPR_LR)
{
// We give up to follow the return address
// because we have to check the register usage.
found_call = false;
}
// LR has been overwritten, so we give up on following the return address.
found_call = false;
}
}
@ -962,8 +962,8 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock* block, CodeBuffer* buffer,
}
if (conditional_continue)
{
// If we skip any conditional branch, we can't garantee to get the matching CALL/RET pair.
// So we stop inling the RET here and let the BLR optitmization handle this case.
// If we skip any conditional branch, we can't guarantee to get the matching CALL/RET pair.
// So we stop inlining the RET here and let the BLR optimization handle this case.
found_call = false;
}
}
@ -1142,9 +1142,9 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock* block, CodeBuffer* buffer,
gqrUsed[gqr] = true;
}
if (op.inst.OPCD == 31 && op.inst.SUBOP10 == 467) // mtspr
if (IsMtspr(op.inst))
{
const int gqr = ((op.inst.SPRU << 5) | op.inst.SPRL) - SPR_GQR0;
const int gqr = GetSPRIndex(op.inst) - SPR_GQR0;
if (gqr >= 0 && gqr <= 7)
gqrModified[gqr] = true;
}

View File

@ -89,7 +89,7 @@ AboutDialog::AboutDialog(QWidget* parent) : QDialog(parent)
// in your translation, please use the type of curly quotes that's appropriate for
// your language. If you aren't sure which type is appropriate, see
// https://en.wikipedia.org/wiki/Quotation_mark#Specific_language_features
tr("\u00A9 2003-2015+ Dolphin Team. \u201cGameCube\u201d and \u201cWii\u201d are "
tr("\u00A9 2003-2024+ Dolphin Team. \u201cGameCube\u201d and \u201cWii\u201d are "
"trademarks of Nintendo. Dolphin is not affiliated with Nintendo in any way.")));
QLabel* logo = new QLabel();

View File

@ -4,10 +4,12 @@
#ifdef USE_RETRO_ACHIEVEMENTS
#include "DolphinQt/Achievements/AchievementBox.h"
#include <QByteArray>
#include <QDateTime>
#include <QHBoxLayout>
#include <QLabel>
#include <QProgressBar>
#include <QSizePolicy>
#include <QVBoxLayout>
#include <QWidget>
@ -30,9 +32,11 @@ AchievementBox::AchievementBox(QWidget* parent, rc_client_achievement_t* achieve
m_badge = new QLabel();
QLabel* title = new QLabel(QString::fromUtf8(achievement->title, strlen(achievement->title)));
title->setWordWrap(true);
title->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
QLabel* description =
new QLabel(QString::fromUtf8(achievement->description, strlen(achievement->description)));
description->setWordWrap(true);
description->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
QLabel* points = new QLabel(tr("%1 points").arg(achievement->points));
m_status = new QLabel();
m_progress_bar = new QProgressBar();
@ -93,7 +97,9 @@ void AchievementBox::UpdateData()
m_progress_bar->setRange(0, 100);
m_progress_bar->setValue(m_achievement->measured_percent);
m_progress_bar->setTextVisible(false);
m_progress_label->setText(QString::fromUtf8(m_achievement->measured_progress, PROGRESS_LENGTH));
m_progress_label->setText(
QString::fromUtf8(m_achievement->measured_progress,
qstrnlen(m_achievement->measured_progress, PROGRESS_LENGTH)));
m_progress_bar->setVisible(true);
}
else

View File

@ -57,8 +57,10 @@ void AchievementLeaderboardWidget::UpdateData(bool clean_all)
m_leaderboard_order[leaderboard->id] = row;
QLabel* a_title = new QLabel(QString::fromUtf8(leaderboard->title));
a_title->setWordWrap(true);
a_title->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
QLabel* a_description = new QLabel(QString::fromUtf8(leaderboard->description));
a_description->setWordWrap(true);
a_description->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
QVBoxLayout* a_col_left = new QVBoxLayout();
a_col_left->addWidget(a_title);
a_col_left->addWidget(a_description);

View File

@ -236,7 +236,10 @@ void AchievementSettingsWidget::ToggleRAIntegration()
else
instance.Shutdown();
if (Config::Get(Config::RA_HARDCORE_ENABLED))
{
emit Settings::Instance().EmulationStateChanged(Core::GetState(Core::System::GetInstance()));
emit Settings::Instance().HardcoreStateChanged();
}
}
void AchievementSettingsWidget::Login()
@ -266,6 +269,7 @@ void AchievementSettingsWidget::ToggleHardcore()
Settings::Instance().SetDebugModeEnabled(false);
}
emit Settings::Instance().EmulationStateChanged(Core::GetState(Core::System::GetInstance()));
emit Settings::Instance().HardcoreStateChanged();
}
void AchievementSettingsWidget::ToggleUnofficial()

View File

@ -34,6 +34,8 @@ AchievementsWindow::AchievementsWindow(QWidget* parent) : QDialog(parent)
});
});
connect(&Settings::Instance(), &Settings::EmulationStateChanged, this,
[this] { m_settings_widget->UpdateData(); });
connect(&Settings::Instance(), &Settings::HardcoreStateChanged, this,
[this] { AchievementsWindow::UpdateData({.all = true}); });
}

View File

@ -59,8 +59,6 @@
#include "InputCommon/ControllerInterface/CoreDevice.h"
#include "InputCommon/InputConfig.h"
constexpr const char* PROFILES_DIR = "Profiles/";
MappingWindow::MappingWindow(QWidget* parent, Type type, int port_num)
: QDialog(parent), m_port(port_num)
{

View File

@ -299,16 +299,14 @@ void GameList::MakeEmptyView()
size_policy.setRetainSizeWhenHidden(true);
m_empty->setSizePolicy(size_policy);
connect(&Settings::Instance(), &Settings::GameListRefreshRequested, this,
[this, refreshing_msg = refreshing_msg] {
m_empty->setText(refreshing_msg);
m_empty->setEnabled(false);
});
connect(&Settings::Instance(), &Settings::GameListRefreshCompleted, this,
[this, empty_msg = empty_msg] {
m_empty->setText(empty_msg);
m_empty->setEnabled(true);
});
connect(&Settings::Instance(), &Settings::GameListRefreshRequested, this, [this, refreshing_msg] {
m_empty->setText(refreshing_msg);
m_empty->setEnabled(false);
});
connect(&Settings::Instance(), &Settings::GameListRefreshCompleted, this, [this, empty_msg] {
m_empty->setText(empty_msg);
m_empty->setEnabled(true);
});
}
void GameList::resizeEvent(QResizeEvent* event)

View File

@ -354,11 +354,6 @@ void Settings::NotifyRefreshGameListComplete()
emit GameListRefreshCompleted();
}
void Settings::RefreshMetadata()
{
emit MetadataRefreshRequested();
}
void Settings::NotifyMetadataRefreshComplete()
{
emit MetadataRefreshCompleted();

View File

@ -104,7 +104,6 @@ public:
void RefreshGameList();
void NotifyRefreshGameListStarted();
void NotifyRefreshGameListComplete();
void RefreshMetadata();
void NotifyMetadataRefreshComplete();
void ReloadTitleDB();
bool IsAutoRefreshEnabled() const;
@ -224,6 +223,7 @@ signals:
void SDCardInsertionChanged(bool inserted);
void USBKeyboardConnectionChanged(bool connected);
void EnableGfxModsChanged(bool enabled);
void HardcoreStateChanged();
private:
Settings();

View File

@ -100,7 +100,7 @@ void AdvancedPane::CreateLayout()
clock_override_layout->addLayout(cpu_clock_override_slider_layout);
m_cpu_clock_override_slider = new QSlider(Qt::Horizontal);
m_cpu_clock_override_slider->setRange(0, 150);
m_cpu_clock_override_slider->setRange(1, 400);
cpu_clock_override_slider_layout->addWidget(m_cpu_clock_override_slider);
m_cpu_clock_override_slider_label = new QLabel();
@ -203,8 +203,7 @@ void AdvancedPane::ConnectLayout()
});
connect(m_cpu_clock_override_slider, &QSlider::valueChanged, [this](int oc_factor) {
// Vaguely exponential scaling?
const float factor = std::exp2f((m_cpu_clock_override_slider->value() - 100.f) / 25.f);
const float factor = m_cpu_clock_override_slider->value() / 100.f;
Config::SetBaseOrCurrent(Config::MAIN_OVERCLOCK, factor);
Update();
});
@ -271,8 +270,8 @@ void AdvancedPane::Update()
{
const QSignalBlocker blocker(m_cpu_clock_override_slider);
m_cpu_clock_override_slider->setValue(static_cast<int>(
std::round(std::log2f(Config::Get(Config::MAIN_OVERCLOCK)) * 25.f + 100.f)));
m_cpu_clock_override_slider->setValue(
static_cast<int>(std::round(Config::Get(Config::MAIN_OVERCLOCK) * 100.f)));
}
m_cpu_clock_override_slider_label->setText([] {

View File

@ -194,7 +194,7 @@ void GeneralPane::CreateAutoUpdate()
auto_update_group_layout->addRow(tr("&Auto Update:"), m_combobox_update_track);
for (const QString& option :
{tr("Don't Update"), tr("Beta (once a month)"), tr("Dev (multiple times a day)")})
{tr("Don't Update"), tr("Releases (every few months)"), tr("Dev (multiple times a day)")})
m_combobox_update_track->addItem(option);
}

View File

@ -235,15 +235,15 @@ void InterfacePane::ConnectLayout()
connect(m_checkbox_use_builtin_title_database, &QCheckBox::toggled, &Settings::Instance(),
&Settings::GameListRefreshRequested);
connect(m_checkbox_use_covers, &QCheckBox::toggled, &Settings::Instance(),
&Settings::RefreshMetadata);
&Settings::MetadataRefreshRequested);
connect(m_checkbox_show_debugging_ui, &QCheckBox::toggled, &Settings::Instance(),
&Settings::SetDebugModeEnabled);
connect(m_combobox_theme, &QComboBox::currentIndexChanged, this,
[this](int index) { Settings::Instance().TriggerThemeChanged(); });
connect(m_combobox_theme, &QComboBox::currentIndexChanged, &Settings::Instance(),
&Settings::ThemeChanged);
connect(m_combobox_userstyle, &QComboBox::currentIndexChanged, this,
&InterfacePane::OnUserStyleChanged);
connect(m_combobox_language, &QComboBox::currentIndexChanged, this,
[this]() { OnLanguageChanged(); });
&InterfacePane::OnLanguageChanged);
connect(m_checkbox_top_window, &QCheckBox::toggled, &Settings::Instance(),
&Settings::KeepWindowOnTopChanged);
connect(m_radio_cursor_visible_movement, &ConfigRadioInt::OnSelected, &Settings::Instance(),
@ -253,7 +253,7 @@ void InterfacePane::ConnectLayout()
connect(m_radio_cursor_visible_always, &ConfigRadioInt::OnSelected, &Settings::Instance(),
&Settings::CursorVisibilityChanged);
connect(m_checkbox_lock_mouse, &QCheckBox::toggled, &Settings::Instance(),
[this]() { Settings::Instance().LockCursorChanged(); });
&Settings::LockCursorChanged);
}
void InterfacePane::UpdateShowDebuggingCheckbox()

View File

@ -66,12 +66,15 @@ void VideoConfig::Refresh()
CPUThreadConfigCallback::AddConfigChangedCallback([]() {
auto& system = Core::System::GetInstance();
system.GetFifo().PauseAndLock(true, false);
const bool lock_gpu_thread = Core::IsRunning(system);
if (lock_gpu_thread)
system.GetFifo().PauseAndLock(true, false);
g_Config.Refresh();
g_Config.VerifyValidity();
system.GetFifo().PauseAndLock(false, true);
if (lock_gpu_thread)
system.GetFifo().PauseAndLock(false, true);
});
s_has_registered_callback = true;
}