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

Compare commits

...

10 Commits

Author SHA1 Message Date
TryTwo
b9db9bdd23
Merge b7361207cb into 10a95a4d5b 2024-06-25 14:40:13 -04: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
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
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
TryTwo
b7361207cb CodeWidget bugfix: Prevemt updates that use CPUThreadGuard during boot, when the core isn't ready.
GetState will report the State as paused at a certain point during boot, which will allow an update that requires CPUThreadGuard. Since it's too early to create a guard, this will cause buggy behavior.  Normally this doesn't happen, but sometimes a commit will appear that triggers updates during boot.
2024-05-31 18:46:37 -07:00
10 changed files with 50 additions and 12 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

@ -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

@ -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

@ -268,7 +268,7 @@ void CodeViewWidget::Update()
if (m_updating)
return;
if (Core::GetState(m_system) == Core::State::Paused)
if (Core::GetState(m_system) == Core::State::Paused && Core::IsRunningAndStarted())
{
Core::CPUThreadGuard guard(m_system);
Update(&guard);

View File

@ -340,7 +340,7 @@ void CodeWidget::UpdateCallstack()
{
m_callstack_list->clear();
if (Core::GetState(m_system) != Core::State::Paused)
if (Core::GetState(m_system) != Core::State::Paused || !Core::IsRunningAndStarted())
return;
std::vector<Dolphin_Debugger::CallstackEntry> stack;

View File

@ -223,6 +223,7 @@ signals:
void SDCardInsertionChanged(bool inserted);
void USBKeyboardConnectionChanged(bool connected);
void EnableGfxModsChanged(bool enabled);
void HardcoreStateChanged();
private:
Settings();

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);
}