Skip to content

Commit

Permalink
Merge pull request #12216 from LillyJadeKatrin/retroachievements-rehash
Browse files Browse the repository at this point in the history
RetroAchievements - Improved Game Loading
  • Loading branch information
lioncash committed Dec 5, 2023
2 parents a65246e + 2bf6ebc commit b427604
Show file tree
Hide file tree
Showing 9 changed files with 345 additions and 114 deletions.
384 changes: 281 additions & 103 deletions Source/Core/Core/AchievementManager.cpp

Large diffs are not rendered by default.

31 changes: 27 additions & 4 deletions Source/Core/Core/AchievementManager.h
Expand Up @@ -18,6 +18,7 @@

#include "Common/Event.h"
#include "Common/WorkQueueThread.h"
#include "DiscIO/Volume.h"

namespace Core
{
Expand Down Expand Up @@ -51,6 +52,8 @@ class AchievementManager
u32 soft_points;
};

static constexpr size_t HASH_SIZE = 33;
using Hash = std::array<char, HASH_SIZE>;
using AchievementId = u32;
static constexpr size_t FORMAT_SIZE = 24;
using FormattedValue = std::array<char, FORMAT_SIZE>;
Expand Down Expand Up @@ -105,7 +108,8 @@ class AchievementManager
ResponseType Login(const std::string& password);
void LoginAsync(const std::string& password, const ResponseCallback& callback);
bool IsLoggedIn() const;
void LoadGameByFilenameAsync(const std::string& iso_path, const ResponseCallback& callback);
void HashGame(const std::string& file_path, const ResponseCallback& callback);
void HashGame(const DiscIO::Volume* volume, const ResponseCallback& callback);
bool IsGameLoaded() const;

void LoadUnlockData(const ResponseCallback& callback);
Expand All @@ -132,6 +136,8 @@ class AchievementManager
u32* target);
const std::unordered_map<AchievementId, LeaderboardStatus>& GetLeaderboardsInfo() const;
RichPresence GetRichPresence();
bool IsDisabled() const { return m_disabled; };
void SetDisabled(bool disabled);

void CloseGame();
void Logout();
Expand All @@ -140,15 +146,29 @@ class AchievementManager
private:
AchievementManager() = default;

static constexpr int HASH_LENGTH = 33;
struct FilereaderState
{
int64_t position = 0;
std::unique_ptr<DiscIO::Volume> volume;
};

static void* FilereaderOpenByFilepath(const char* path_utf8);
static void* FilereaderOpenByVolume(const char* path_utf8);
static void FilereaderSeek(void* file_handle, int64_t offset, int origin);
static int64_t FilereaderTell(void* file_handle);
static size_t FilereaderRead(void* file_handle, void* buffer, size_t requested_bytes);
static void FilereaderClose(void* file_handle);

ResponseType VerifyCredentials(const std::string& password);
ResponseType ResolveHash(std::array<char, HASH_LENGTH> game_hash);
ResponseType ResolveHash(const Hash& game_hash, u32* game_id);
void LoadGameSync(const ResponseCallback& callback);
ResponseType StartRASession();
ResponseType FetchGameData();
ResponseType FetchUnlockData(bool hardcore);
ResponseType FetchBoardInfo(AchievementId leaderboard_id);

std::unique_ptr<DiscIO::Volume>& GetLoadingVolume() { return m_loading_volume; };

void ActivateDeactivateAchievement(AchievementId id, bool enabled, bool unofficial, bool encore);
void GenerateRichPresence();

Expand All @@ -174,10 +194,12 @@ class AchievementManager
Core::System* m_system{};
bool m_is_runtime_initialized = false;
UpdateCallback m_update_callback;
std::unique_ptr<DiscIO::Volume> m_loading_volume;
bool m_disabled = false;
std::string m_display_name;
u32 m_player_score = 0;
BadgeStatus m_player_badge;
std::array<char, HASH_LENGTH> m_game_hash{};
Hash m_game_hash{};
u32 m_game_id = 0;
rc_api_fetch_game_data_response_t m_game_data{};
bool m_is_game_loaded = false;
Expand All @@ -192,6 +214,7 @@ class AchievementManager
Common::WorkQueueThread<std::function<void()>> m_queue;
Common::WorkQueueThread<std::function<void()>> m_image_queue;
mutable std::recursive_mutex m_lock;
std::recursive_mutex m_filereader_lock;
}; // class AchievementManager

#endif // USE_RETRO_ACHIEVEMENTS
6 changes: 6 additions & 0 deletions Source/Core/Core/Boot/Boot.cpp
Expand Up @@ -25,6 +25,7 @@
#include "Common/MsgHandler.h"
#include "Common/StringUtil.h"

#include "Core/AchievementManager.h"
#include "Core/Boot/DolReader.h"
#include "Core/Boot/ElfReader.h"
#include "Core/CommonTitles.h"
Expand Down Expand Up @@ -558,6 +559,11 @@ bool CBoot::BootUp(Core::System& system, const Core::CPUThreadGuard& guard,
SetupGCMemory(system, guard);
}

#ifdef USE_RETRO_ACHIEVEMENTS
AchievementManager::GetInstance()->HashGame(executable.path,
[](AchievementManager::ResponseType r_type) {});
#endif // USE_RETRO_ACHIEVEMENTS

if (!executable.reader->LoadIntoMemory(system))
{
PanicAlertFmtT("Failed to load the executable to memory.");
Expand Down
8 changes: 1 addition & 7 deletions Source/Core/Core/BootManager.cpp
Expand Up @@ -165,13 +165,7 @@ bool BootCore(std::unique_ptr<BootParameters> boot, const WindowSystemInfo& wsi)
}

#ifdef USE_RETRO_ACHIEVEMENTS
std::string path = "";
if (std::holds_alternative<BootParameters::Disc>(boot->parameters))
{
path = std::get<BootParameters::Disc>(boot->parameters).path;
}
AchievementManager::GetInstance()->LoadGameByFilenameAsync(
path, [](AchievementManager::ResponseType r_type) {});
AchievementManager::GetInstance()->SetDisabled(false);
#endif // USE_RETRO_ACHIEVEMENTS

const bool load_ipl = !StartUp.bWii && !Config::Get(Config::MAIN_SKIP_IPL) &&
Expand Down
5 changes: 5 additions & 0 deletions Source/Core/Core/ConfigManager.cpp
Expand Up @@ -30,6 +30,7 @@
#include "Common/StringUtil.h"
#include "Common/Version.h"

#include "Core/AchievementManager.h"
#include "Core/Boot/Boot.h"
#include "Core/CommonTitles.h"
#include "Core/Config/DefaultLocale.h"
Expand Down Expand Up @@ -168,6 +169,10 @@ void SConfig::SetRunningGameMetadata(const std::string& game_id, const std::stri
if (!was_changed)
return;

#ifdef USE_RETRO_ACHIEVEMENTS
AchievementManager::GetInstance()->SetDisabled(true);
#endif // USE_RETRO_ACHIEVEMENTS

if (game_id == "00000000")
{
m_title_name.clear();
Expand Down
6 changes: 6 additions & 0 deletions Source/Core/Core/HW/DVD/DVDInterface.cpp
Expand Up @@ -20,6 +20,7 @@
#include "Common/Config/Config.h"
#include "Common/Logging/Log.h"

#include "Core/AchievementManager.h"
#include "Core/Config/MainSettings.h"
#include "Core/Config/SessionSettings.h"
#include "Core/CoreTiming.h"
Expand Down Expand Up @@ -396,6 +397,11 @@ void DVDInterface::SetDisc(std::unique_ptr<DiscIO::VolumeDisc> disc,
m_auto_disc_change_index = 0;
}

#ifdef USE_RETRO_ACHIEVEMENTS
AchievementManager::GetInstance()->HashGame(disc.get(),
[](AchievementManager::ResponseType r_type) {});
#endif // USE_RETRO_ACHIEVEMENTS

// Assume that inserting a disc requires having an empty disc before
if (had_disc != has_disc)
ExpansionInterface::g_rtc_flags[ExpansionInterface::RTCFlag::DiscChanged] = true;
Expand Down
7 changes: 7 additions & 0 deletions Source/Core/Core/IOS/ES/ES.cpp
Expand Up @@ -16,6 +16,7 @@
#include "Common/NandPaths.h"
#include "Common/ScopeGuard.h"
#include "Common/StringUtil.h"
#include "Core/AchievementManager.h"
#include "Core/CommonTitles.h"
#include "Core/ConfigManager.h"
#include "Core/Core.h"
Expand Down Expand Up @@ -476,6 +477,12 @@ bool ESDevice::LaunchPPCTitle(u64 title_id)
if (!Core::IsRunningAndStarted())
return BootstrapPPC();

#ifdef USE_RETRO_ACHIEVEMENTS
INFO_LOG_FMT(ACHIEVEMENTS,
"WAD and NAND formats not currently supported by Achievement Manager.");
AchievementManager::GetInstance()->SetDisabled(true);
#endif // USE_RETRO_ACHIEVEMENTS

core_timing.RemoveEvent(s_bootstrap_ppc_for_launch_event);
core_timing.ScheduleEvent(ticks, s_bootstrap_ppc_for_launch_event);
return true;
Expand Down
11 changes: 11 additions & 0 deletions Source/Core/DolphinQt/Achievements/AchievementHeaderWidget.cpp
Expand Up @@ -37,6 +37,11 @@ AchievementHeaderWidget::AchievementHeaderWidget(QWidget* parent) : QWidget(pare
m_game_progress_hard = new QProgressBar();
m_game_progress_soft = new QProgressBar();
m_rich_presence = new QLabel();
m_locked_warning = new QLabel();

m_locked_warning->setText(tr("Achievements have been disabled.<br>Please close all running "
"games to re-enable achievements."));
m_locked_warning->setStyleSheet(QStringLiteral("QLabel { color : red; }"));

QSizePolicy sp_retain = m_game_progress_hard->sizePolicy();
sp_retain.setRetainSizeWhenHidden(true);
Expand All @@ -54,6 +59,7 @@ AchievementHeaderWidget::AchievementHeaderWidget(QWidget* parent) : QWidget(pare
text_col->addWidget(m_game_progress_hard);
text_col->addWidget(m_game_progress_soft);
text_col->addWidget(m_rich_presence);
text_col->addWidget(m_locked_warning);
QHBoxLayout* header_layout = new QHBoxLayout();
header_layout->addLayout(icon_col);
header_layout->addLayout(text_col);
Expand Down Expand Up @@ -148,6 +154,7 @@ void AchievementHeaderWidget::UpdateData()
QString::fromUtf8(AchievementManager::GetInstance()->GetRichPresence().data()));
if (!m_rich_presence->isVisible())
m_rich_presence->setVisible(Config::Get(Config::RA_RICH_PRESENCE_ENABLED));
m_locked_warning->setVisible(false);
}
else
{
Expand All @@ -157,6 +164,10 @@ void AchievementHeaderWidget::UpdateData()
m_game_progress_hard->setVisible(false);
m_game_progress_soft->setVisible(false);
m_rich_presence->setVisible(false);
if (AchievementManager::GetInstance()->IsDisabled())
{
m_locked_warning->setVisible(true);
}
}
}

Expand Down
Expand Up @@ -30,6 +30,7 @@ class AchievementHeaderWidget final : public QWidget
QProgressBar* m_game_progress_hard;
QProgressBar* m_game_progress_soft;
QLabel* m_rich_presence;
QLabel* m_locked_warning;
QGroupBox* m_header_box;
};

Expand Down

0 comments on commit b427604

Please sign in to comment.