mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-09 15:49:25 +01:00
Merge pull request #11669 from LillyJadeKatrin/retroachievements-rcheevos-integration
Retroachievements rcheevos integration
This commit is contained in:
commit
b63b574a3f
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -51,3 +51,6 @@
|
|||||||
[submodule "Externals/gtest"]
|
[submodule "Externals/gtest"]
|
||||||
path = Externals/gtest
|
path = Externals/gtest
|
||||||
url = https://github.com/google/googletest.git
|
url = https://github.com/google/googletest.git
|
||||||
|
[submodule "Externals/rcheevos/rcheevos"]
|
||||||
|
path = Externals/rcheevos/rcheevos
|
||||||
|
url = https://github.com/RetroAchievements/rcheevos.git
|
||||||
|
@ -72,6 +72,7 @@ option(USE_DISCORD_PRESENCE "Enables Discord Rich Presence, show the current gam
|
|||||||
option(USE_MGBA "Enables GBA controllers emulation using libmgba" ON)
|
option(USE_MGBA "Enables GBA controllers emulation using libmgba" ON)
|
||||||
option(ENABLE_AUTOUPDATE "Enables support for automatic updates" ON)
|
option(ENABLE_AUTOUPDATE "Enables support for automatic updates" ON)
|
||||||
option(STEAM "Creates a build for Steam" OFF)
|
option(STEAM "Creates a build for Steam" OFF)
|
||||||
|
option(USE_RETRO_ACHIEVEMENTS "Enables integration with retroachievements.org" ON)
|
||||||
|
|
||||||
# Maintainers: if you consider blanket disabling this for your users, please
|
# Maintainers: if you consider blanket disabling this for your users, please
|
||||||
# consider the following points:
|
# consider the following points:
|
||||||
@ -975,6 +976,10 @@ add_subdirectory(Externals/rangeset)
|
|||||||
|
|
||||||
add_subdirectory(Externals/FatFs)
|
add_subdirectory(Externals/FatFs)
|
||||||
|
|
||||||
|
if (USE_RETRO_ACHIEVEMENTS)
|
||||||
|
add_subdirectory(Externals/rcheevos)
|
||||||
|
endif()
|
||||||
|
|
||||||
########################################
|
########################################
|
||||||
# Pre-build events: Define configuration variables and write SCM info header
|
# Pre-build events: Define configuration variables and write SCM info header
|
||||||
#
|
#
|
||||||
|
49
Externals/rcheevos/CMakeLists.txt
vendored
Normal file
49
Externals/rcheevos/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
add_library(rcheevos
|
||||||
|
rcheevos/include/rc_api_editor.h
|
||||||
|
rcheevos/include/rc_api_info.h
|
||||||
|
rcheevos/include/rc_api_request.h
|
||||||
|
rcheevos/include/rc_api_runtime.h
|
||||||
|
rcheevos/include/rc_api_user.h
|
||||||
|
rcheevos/include/rc_consoles.h
|
||||||
|
rcheevos/include/rc_error.h
|
||||||
|
rcheevos/include/rc_hash.h
|
||||||
|
rcheevos/include/rcheevos.h
|
||||||
|
rcheevos/include/rc_runtime.h
|
||||||
|
rcheevos/include/rc_runtime_types.h
|
||||||
|
rcheevos/include/rc_url.h
|
||||||
|
rcheevos/src/rapi/rc_api_common.c
|
||||||
|
rcheevos/src/rapi/rc_api_common.h
|
||||||
|
rcheevos/src/rapi/rc_api_editor.c
|
||||||
|
rcheevos/src/rapi/rc_api_info.c
|
||||||
|
rcheevos/src/rapi/rc_api_runtime.c
|
||||||
|
rcheevos/src/rapi/rc_api_user.c
|
||||||
|
rcheevos/src/rcheevos/alloc.c
|
||||||
|
rcheevos/src/rcheevos/compat.c
|
||||||
|
rcheevos/src/rcheevos/condition.c
|
||||||
|
rcheevos/src/rcheevos/condset.c
|
||||||
|
rcheevos/src/rcheevos/consoleinfo.c
|
||||||
|
rcheevos/src/rcheevos/format.c
|
||||||
|
rcheevos/src/rcheevos/lboard.c
|
||||||
|
rcheevos/src/rcheevos/memref.c
|
||||||
|
rcheevos/src/rcheevos/operand.c
|
||||||
|
rcheevos/src/rcheevos/rc_compat.h
|
||||||
|
rcheevos/src/rcheevos/rc_internal.h
|
||||||
|
rcheevos/src/rcheevos/rc_validate.c
|
||||||
|
rcheevos/src/rcheevos/rc_validate.h
|
||||||
|
rcheevos/src/rcheevos/richpresence.c
|
||||||
|
rcheevos/src/rcheevos/runtime.c
|
||||||
|
rcheevos/src/rcheevos/runtime_progress.c
|
||||||
|
rcheevos/src/rcheevos/trigger.c
|
||||||
|
rcheevos/src/rcheevos/value.c
|
||||||
|
rcheevos/src/rhash/hash.c
|
||||||
|
rcheevos/src/rhash/md5.c
|
||||||
|
rcheevos/src/rhash/md5.h
|
||||||
|
rcheevos/src/rurl/url.c
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(rcheevos PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/rcheevos/include")
|
||||||
|
target_include_directories(rcheevos INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
|
target_compile_definitions(rcheevos PRIVATE "RC_DISABLE_LUA=1" "RCHEEVOS_URL_SSL")
|
||||||
|
if(CMAKE_SYSTEM_NAME MATCHES "Windows")
|
||||||
|
target_compile_definitions(rcheevos PRIVATE "_CRT_SECURE_NO_WARNINGS")
|
||||||
|
endif()
|
13
Externals/rcheevos/exports.props
vendored
Normal file
13
Externals/rcheevos/exports.props
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project>
|
||||||
|
<ItemDefinitionGroup>
|
||||||
|
<ClCompile>
|
||||||
|
<AdditionalIncludeDirectories>$(ExternalsDir)rcheevos;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="$(ExternalsDir)rcheevos\rcheevos.vcxproj">
|
||||||
|
<Project>{CC99A910-3752-4465-95AA-7DC240D92A99}</Project>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
1
Externals/rcheevos/rcheevos
vendored
Submodule
1
Externals/rcheevos/rcheevos
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit c5304a61bcf256ae80fcd1c8f64ad9646aaea757
|
71
Externals/rcheevos/rcheevos.vcxproj
vendored
Normal file
71
Externals/rcheevos/rcheevos.vcxproj
vendored
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project>
|
||||||
|
<Import Project="..\..\Source\VSProps\Base.Macros.props" />
|
||||||
|
<Import Project="$(VSPropsDir)Base.Targets.props" />
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectGuid>{CC99A910-3752-4465-95AA-7DC240D92A99}</ProjectGuid>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<Import Project="$(VSPropsDir)Configuration.StaticLibrary.props" />
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings" />
|
||||||
|
<ImportGroup Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="$(VSPropsDir)Base.props" />
|
||||||
|
<Import Project="$(VSPropsDir)ClDisableAllWarnings.props" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="rcheevos\src\rapi\rc_api_common.c" />
|
||||||
|
<ClCompile Include="rcheevos\src\rapi\rc_api_editor.c" />
|
||||||
|
<ClCompile Include="rcheevos\src\rapi\rc_api_info.c" />
|
||||||
|
<ClCompile Include="rcheevos\src\rapi\rc_api_runtime.c" />
|
||||||
|
<ClCompile Include="rcheevos\src\rapi\rc_api_user.c" />
|
||||||
|
<ClCompile Include="rcheevos\src\rcheevos\alloc.c" />
|
||||||
|
<ClCompile Include="rcheevos\src\rcheevos\compat.c" />
|
||||||
|
<ClCompile Include="rcheevos\src\rcheevos\condition.c" />
|
||||||
|
<ClCompile Include="rcheevos\src\rcheevos\condset.c" />
|
||||||
|
<ClCompile Include="rcheevos\src\rcheevos\consoleinfo.c" />
|
||||||
|
<ClCompile Include="rcheevos\src\rcheevos\format.c" />
|
||||||
|
<ClCompile Include="rcheevos\src\rcheevos\lboard.c" />
|
||||||
|
<ClCompile Include="rcheevos\src\rcheevos\memref.c" />
|
||||||
|
<ClCompile Include="rcheevos\src\rcheevos\operand.c" />
|
||||||
|
<ClCompile Include="rcheevos\src\rcheevos\rc_validate.c" />
|
||||||
|
<ClCompile Include="rcheevos\src\rcheevos\richpresence.c" />
|
||||||
|
<ClCompile Include="rcheevos\src\rcheevos\runtime.c" />
|
||||||
|
<ClCompile Include="rcheevos\src\rcheevos\runtime_progress.c" />
|
||||||
|
<ClCompile Include="rcheevos\src\rcheevos\trigger.c" />
|
||||||
|
<ClCompile Include="rcheevos\src\rcheevos\value.c" />
|
||||||
|
<ClCompile Include="rcheevos\src\rhash\hash.c" />
|
||||||
|
<ClCompile Include="rcheevos\src\rhash\md5.c" />
|
||||||
|
<ClCompile Include="rcheevos\src\rurl\url.c" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="rcheevos\include\rcheevos.h" />
|
||||||
|
<ClInclude Include="rcheevos\include\rc_api_editor.h" />
|
||||||
|
<ClInclude Include="rcheevos\include\rc_api_info.h" />
|
||||||
|
<ClInclude Include="rcheevos\include\rc_api_request.h" />
|
||||||
|
<ClInclude Include="rcheevos\include\rc_api_runtime.h" />
|
||||||
|
<ClInclude Include="rcheevos\include\rc_api_user.h" />
|
||||||
|
<ClInclude Include="rcheevos\include\rc_consoles.h" />
|
||||||
|
<ClInclude Include="rcheevos\include\rc_error.h" />
|
||||||
|
<ClInclude Include="rcheevos\include\rc_hash.h" />
|
||||||
|
<ClInclude Include="rcheevos\include\rc_runtime.h" />
|
||||||
|
<ClInclude Include="rcheevos\include\rc_runtime_types.h" />
|
||||||
|
<ClInclude Include="rcheevos\include\rc_url.h" />
|
||||||
|
<ClInclude Include="rcheevos\src\rapi\rc_api_common.h" />
|
||||||
|
<ClInclude Include="rcheevos\src\rcheevos\rc_compat.h" />
|
||||||
|
<ClInclude Include="rcheevos\src\rcheevos\rc_internal.h" />
|
||||||
|
<ClInclude Include="rcheevos\src\rcheevos\rc_validate.h" />
|
||||||
|
<ClInclude Include="rcheevos\src\rhash\md5.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemDefinitionGroup>
|
||||||
|
<ClCompile>
|
||||||
|
<PreprocessorDefinitions>RC_DISABLE_LUA;RCHEEVOS_URL_SSL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<AdditionalIncludeDirectories>$(ProjectDir)rcheevos\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
@ -112,6 +112,7 @@
|
|||||||
#define LOGGER_CONFIG "Logger.ini"
|
#define LOGGER_CONFIG "Logger.ini"
|
||||||
#define DUALSHOCKUDPCLIENT_CONFIG "DSUClient.ini"
|
#define DUALSHOCKUDPCLIENT_CONFIG "DSUClient.ini"
|
||||||
#define FREELOOK_CONFIG "FreeLook.ini"
|
#define FREELOOK_CONFIG "FreeLook.ini"
|
||||||
|
#define RETROACHIEVEMENTS_CONFIG "RetroAchievements.ini"
|
||||||
|
|
||||||
// Files in the directory returned by GetUserPath(D_LOGS_IDX)
|
// Files in the directory returned by GetUserPath(D_LOGS_IDX)
|
||||||
#define MAIN_LOG "dolphin.log"
|
#define MAIN_LOG "dolphin.log"
|
||||||
|
@ -160,7 +160,8 @@ static const std::map<System, std::string> system_to_name = {
|
|||||||
{System::DualShockUDPClient, "DualShockUDPClient"},
|
{System::DualShockUDPClient, "DualShockUDPClient"},
|
||||||
{System::FreeLook, "FreeLook"},
|
{System::FreeLook, "FreeLook"},
|
||||||
{System::Session, "Session"},
|
{System::Session, "Session"},
|
||||||
{System::GameSettingsOnly, "GameSettingsOnly"}};
|
{System::GameSettingsOnly, "GameSettingsOnly"},
|
||||||
|
{System::Achievements, "Achievements"}};
|
||||||
|
|
||||||
const std::string& GetSystemName(System system)
|
const std::string& GetSystemName(System system)
|
||||||
{
|
{
|
||||||
|
@ -34,6 +34,7 @@ enum class System
|
|||||||
FreeLook,
|
FreeLook,
|
||||||
Session,
|
Session,
|
||||||
GameSettingsOnly,
|
GameSettingsOnly,
|
||||||
|
Achievements,
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr std::array<LayerType, 7> SEARCH_ORDER{{
|
constexpr std::array<LayerType, 7> SEARCH_ORDER{{
|
||||||
|
@ -847,6 +847,8 @@ static void RebuildUserDirectories(unsigned int dir_index)
|
|||||||
s_user_paths[F_DUALSHOCKUDPCLIENTCONFIG_IDX] =
|
s_user_paths[F_DUALSHOCKUDPCLIENTCONFIG_IDX] =
|
||||||
s_user_paths[D_CONFIG_IDX] + DUALSHOCKUDPCLIENT_CONFIG;
|
s_user_paths[D_CONFIG_IDX] + DUALSHOCKUDPCLIENT_CONFIG;
|
||||||
s_user_paths[F_FREELOOKCONFIG_IDX] = s_user_paths[D_CONFIG_IDX] + FREELOOK_CONFIG;
|
s_user_paths[F_FREELOOKCONFIG_IDX] = s_user_paths[D_CONFIG_IDX] + FREELOOK_CONFIG;
|
||||||
|
s_user_paths[F_RETROACHIEVEMENTSCONFIG_IDX] =
|
||||||
|
s_user_paths[D_CONFIG_IDX] + RETROACHIEVEMENTS_CONFIG;
|
||||||
s_user_paths[F_MAINLOG_IDX] = s_user_paths[D_LOGS_IDX] + MAIN_LOG;
|
s_user_paths[F_MAINLOG_IDX] = s_user_paths[D_LOGS_IDX] + MAIN_LOG;
|
||||||
s_user_paths[F_MEM1DUMP_IDX] = s_user_paths[D_DUMP_IDX] + MEM1_DUMP;
|
s_user_paths[F_MEM1DUMP_IDX] = s_user_paths[D_DUMP_IDX] + MEM1_DUMP;
|
||||||
s_user_paths[F_MEM2DUMP_IDX] = s_user_paths[D_DUMP_IDX] + MEM2_DUMP;
|
s_user_paths[F_MEM2DUMP_IDX] = s_user_paths[D_DUMP_IDX] + MEM2_DUMP;
|
||||||
|
@ -85,6 +85,7 @@ enum
|
|||||||
F_DUALSHOCKUDPCLIENTCONFIG_IDX,
|
F_DUALSHOCKUDPCLIENTCONFIG_IDX,
|
||||||
F_FREELOOKCONFIG_IDX,
|
F_FREELOOKCONFIG_IDX,
|
||||||
F_GBABIOS_IDX,
|
F_GBABIOS_IDX,
|
||||||
|
F_RETROACHIEVEMENTSCONFIG_IDX,
|
||||||
NUM_PATH_INDICES
|
NUM_PATH_INDICES
|
||||||
};
|
};
|
||||||
|
|
||||||
|
114
Source/Core/Core/AchievementManager.cpp
Normal file
114
Source/Core/Core/AchievementManager.cpp
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
// Copyright 2023 Dolphin Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#ifdef USE_RETRO_ACHIEVEMENTS
|
||||||
|
|
||||||
|
#include "Core/AchievementManager.h"
|
||||||
|
#include "Common/HttpRequest.h"
|
||||||
|
#include "Common/WorkQueueThread.h"
|
||||||
|
#include "Config/AchievementSettings.h"
|
||||||
|
#include "Core/Core.h"
|
||||||
|
|
||||||
|
AchievementManager* AchievementManager::GetInstance()
|
||||||
|
{
|
||||||
|
static AchievementManager s_instance;
|
||||||
|
return &s_instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AchievementManager::Init()
|
||||||
|
{
|
||||||
|
if (!m_is_runtime_initialized && Config::Get(Config::RA_ENABLED))
|
||||||
|
{
|
||||||
|
rc_runtime_init(&m_runtime);
|
||||||
|
m_is_runtime_initialized = true;
|
||||||
|
m_queue.Reset("AchievementManagerQueue", [](const std::function<void()>& func) { func(); });
|
||||||
|
LoginAsync("", [](ResponseType r_type) {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AchievementManager::ResponseType AchievementManager::Login(const std::string& password)
|
||||||
|
{
|
||||||
|
return VerifyCredentials(password);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AchievementManager::LoginAsync(const std::string& password, const LoginCallback& callback)
|
||||||
|
{
|
||||||
|
m_queue.EmplaceItem([this, password, callback] { callback(VerifyCredentials(password)); });
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AchievementManager::IsLoggedIn() const
|
||||||
|
{
|
||||||
|
return m_login_data.response.succeeded;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AchievementManager::Logout()
|
||||||
|
{
|
||||||
|
Config::SetBaseOrCurrent(Config::RA_API_TOKEN, "");
|
||||||
|
rc_api_destroy_login_response(&m_login_data);
|
||||||
|
m_login_data.response.succeeded = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AchievementManager::Shutdown()
|
||||||
|
{
|
||||||
|
m_is_runtime_initialized = false;
|
||||||
|
m_queue.Shutdown();
|
||||||
|
// DON'T log out - keep those credentials for next run.
|
||||||
|
rc_api_destroy_login_response(&m_login_data);
|
||||||
|
m_login_data.response.succeeded = 0;
|
||||||
|
rc_runtime_destroy(&m_runtime);
|
||||||
|
}
|
||||||
|
|
||||||
|
AchievementManager::ResponseType AchievementManager::VerifyCredentials(const std::string& password)
|
||||||
|
{
|
||||||
|
std::string username = Config::Get(Config::RA_USERNAME);
|
||||||
|
std::string api_token = Config::Get(Config::RA_API_TOKEN);
|
||||||
|
rc_api_login_request_t login_request = {
|
||||||
|
.username = username.c_str(), .api_token = api_token.c_str(), .password = password.c_str()};
|
||||||
|
ResponseType r_type = Request<rc_api_login_request_t, rc_api_login_response_t>(
|
||||||
|
login_request, &m_login_data, rc_api_init_login_request, rc_api_process_login_response);
|
||||||
|
if (r_type == ResponseType::SUCCESS)
|
||||||
|
Config::SetBaseOrCurrent(Config::RA_API_TOKEN, m_login_data.api_token);
|
||||||
|
return r_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Every RetroAchievements API call, with only a partial exception for fetch_image, follows
|
||||||
|
// the same design pattern (here, X is the name of the call):
|
||||||
|
// Create a specific rc_api_X_request_t struct and populate with the necessary values
|
||||||
|
// Call rc_api_init_X_request to convert this into a generic rc_api_request_t struct
|
||||||
|
// Perform the HTTP request using the url and post_data in the rc_api_request_t struct
|
||||||
|
// Call rc_api_process_X_response to convert the raw string HTTP response into a
|
||||||
|
// rc_api_X_response_t struct
|
||||||
|
// Use the data in the rc_api_X_response_t struct as needed
|
||||||
|
// Call rc_api_destroy_X_response when finished with the response struct to free memory
|
||||||
|
template <typename RcRequest, typename RcResponse>
|
||||||
|
AchievementManager::ResponseType AchievementManager::Request(
|
||||||
|
RcRequest rc_request, RcResponse* rc_response,
|
||||||
|
const std::function<int(rc_api_request_t*, const RcRequest*)>& init_request,
|
||||||
|
const std::function<int(RcResponse*, const char*)>& process_response)
|
||||||
|
{
|
||||||
|
rc_api_request_t api_request;
|
||||||
|
Common::HttpRequest http_request;
|
||||||
|
init_request(&api_request, &rc_request);
|
||||||
|
auto http_response = http_request.Post(api_request.url, api_request.post_data);
|
||||||
|
rc_api_destroy_request(&api_request);
|
||||||
|
if (http_response.has_value() && http_response->size() > 0)
|
||||||
|
{
|
||||||
|
const std::string response_str(http_response->begin(), http_response->end());
|
||||||
|
process_response(rc_response, response_str.c_str());
|
||||||
|
if (rc_response->response.succeeded)
|
||||||
|
{
|
||||||
|
return ResponseType::SUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logout();
|
||||||
|
return ResponseType::INVALID_CREDENTIALS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return ResponseType::CONNECTION_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // USE_RETRO_ACHIEVEMENTS
|
54
Source/Core/Core/AchievementManager.h
Normal file
54
Source/Core/Core/AchievementManager.h
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
// Copyright 2023 Dolphin Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef USE_RETRO_ACHIEVEMENTS
|
||||||
|
#include <functional>
|
||||||
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
#include <rcheevos/include/rc_api_user.h>
|
||||||
|
#include <rcheevos/include/rc_runtime.h>
|
||||||
|
|
||||||
|
#include "Common/Event.h"
|
||||||
|
#include "Common/WorkQueueThread.h"
|
||||||
|
|
||||||
|
class AchievementManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum class ResponseType
|
||||||
|
{
|
||||||
|
SUCCESS,
|
||||||
|
INVALID_CREDENTIALS,
|
||||||
|
CONNECTION_FAILED,
|
||||||
|
UNKNOWN_FAILURE
|
||||||
|
};
|
||||||
|
using LoginCallback = std::function<void(ResponseType)>;
|
||||||
|
|
||||||
|
static AchievementManager* GetInstance();
|
||||||
|
void Init();
|
||||||
|
ResponseType Login(const std::string& password);
|
||||||
|
void LoginAsync(const std::string& password, const LoginCallback& callback);
|
||||||
|
bool IsLoggedIn() const;
|
||||||
|
void Logout();
|
||||||
|
void Shutdown();
|
||||||
|
|
||||||
|
private:
|
||||||
|
AchievementManager() = default;
|
||||||
|
|
||||||
|
ResponseType VerifyCredentials(const std::string& password);
|
||||||
|
|
||||||
|
template <typename RcRequest, typename RcResponse>
|
||||||
|
ResponseType Request(RcRequest rc_request, RcResponse* rc_response,
|
||||||
|
const std::function<int(rc_api_request_t*, const RcRequest*)>& init_request,
|
||||||
|
const std::function<int(RcResponse*, const char*)>& process_response);
|
||||||
|
|
||||||
|
rc_runtime_t m_runtime{};
|
||||||
|
bool m_is_runtime_initialized = false;
|
||||||
|
rc_api_login_response_t m_login_data{};
|
||||||
|
Common::WorkQueueThread<std::function<void()>> m_queue;
|
||||||
|
}; // class AchievementManager
|
||||||
|
|
||||||
|
#endif // USE_RETRO_ACHIEVEMENTS
|
@ -1,4 +1,6 @@
|
|||||||
add_library(core
|
add_library(core
|
||||||
|
AchievementManager.cpp
|
||||||
|
AchievementManager.h
|
||||||
ActionReplay.cpp
|
ActionReplay.cpp
|
||||||
ActionReplay.h
|
ActionReplay.h
|
||||||
ARDecrypt.cpp
|
ARDecrypt.cpp
|
||||||
@ -21,6 +23,8 @@ add_library(core
|
|||||||
CheatSearch.cpp
|
CheatSearch.cpp
|
||||||
CheatSearch.h
|
CheatSearch.h
|
||||||
CommonTitles.h
|
CommonTitles.h
|
||||||
|
Config/AchievementSettings.cpp
|
||||||
|
Config/AchievementSettings.h
|
||||||
Config/DefaultLocale.cpp
|
Config/DefaultLocale.cpp
|
||||||
Config/DefaultLocale.h
|
Config/DefaultLocale.h
|
||||||
Config/FreeLookSettings.cpp
|
Config/FreeLookSettings.cpp
|
||||||
@ -747,3 +751,8 @@ if(MSVC)
|
|||||||
# Add precompiled header
|
# Add precompiled header
|
||||||
target_link_libraries(core PRIVATE use_pch)
|
target_link_libraries(core PRIVATE use_pch)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(USE_RETRO_ACHIEVEMENTS)
|
||||||
|
target_link_libraries(core PRIVATE rcheevos)
|
||||||
|
target_compile_definitions(core PRIVATE -DUSE_RETRO_ACHIEVEMENTS)
|
||||||
|
endif()
|
16
Source/Core/Core/Config/AchievementSettings.cpp
Normal file
16
Source/Core/Core/Config/AchievementSettings.cpp
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// Copyright 2023 Dolphin Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "Core/Config/AchievementSettings.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "Common/Config/Config.h"
|
||||||
|
|
||||||
|
namespace Config
|
||||||
|
{
|
||||||
|
// Configuration Information
|
||||||
|
const Info<bool> RA_ENABLED{{System::Achievements, "Achievements", "Enabled"}, false};
|
||||||
|
const Info<std::string> RA_USERNAME{{System::Achievements, "Achievements", "Username"}, ""};
|
||||||
|
const Info<std::string> RA_API_TOKEN{{System::Achievements, "Achievements", "ApiToken"}, ""};
|
||||||
|
} // namespace Config
|
14
Source/Core/Core/Config/AchievementSettings.h
Normal file
14
Source/Core/Core/Config/AchievementSettings.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// Copyright 2023 Dolphin Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Common/Config/Config.h"
|
||||||
|
|
||||||
|
namespace Config
|
||||||
|
{
|
||||||
|
// Configuration Information
|
||||||
|
extern const Info<bool> RA_ENABLED;
|
||||||
|
extern const Info<std::string> RA_USERNAME;
|
||||||
|
extern const Info<std::string> RA_API_TOKEN;
|
||||||
|
} // namespace Config
|
@ -94,6 +94,7 @@ const std::map<Config::System, int> system_to_ini = {
|
|||||||
{Config::System::Debugger, F_DEBUGGERCONFIG_IDX},
|
{Config::System::Debugger, F_DEBUGGERCONFIG_IDX},
|
||||||
{Config::System::DualShockUDPClient, F_DUALSHOCKUDPCLIENTCONFIG_IDX},
|
{Config::System::DualShockUDPClient, F_DUALSHOCKUDPCLIENTCONFIG_IDX},
|
||||||
{Config::System::FreeLook, F_FREELOOKCONFIG_IDX},
|
{Config::System::FreeLook, F_FREELOOKCONFIG_IDX},
|
||||||
|
{Config::System::Achievements, F_RETROACHIEVEMENTSCONFIG_IDX},
|
||||||
// Config::System::Session should not be added to this list
|
// Config::System::Session should not be added to this list
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "Common/Config/Config.h"
|
#include "Common/Config/Config.h"
|
||||||
|
#include "Core/Config/AchievementSettings.h"
|
||||||
#include "Core/Config/GraphicsSettings.h"
|
#include "Core/Config/GraphicsSettings.h"
|
||||||
#include "Core/Config/MainSettings.h"
|
#include "Core/Config/MainSettings.h"
|
||||||
#include "Core/Config/UISettings.h"
|
#include "Core/Config/UISettings.h"
|
||||||
@ -37,6 +38,12 @@ bool IsSettingSaveable(const Config::Location& config_location)
|
|||||||
&Config::WIIMOTE_3_SOURCE.GetLocation(),
|
&Config::WIIMOTE_3_SOURCE.GetLocation(),
|
||||||
&Config::WIIMOTE_4_SOURCE.GetLocation(),
|
&Config::WIIMOTE_4_SOURCE.GetLocation(),
|
||||||
&Config::WIIMOTE_BB_SOURCE.GetLocation(),
|
&Config::WIIMOTE_BB_SOURCE.GetLocation(),
|
||||||
|
|
||||||
|
// Achievements
|
||||||
|
|
||||||
|
&Config::RA_ENABLED.GetLocation(),
|
||||||
|
&Config::RA_USERNAME.GetLocation(),
|
||||||
|
&Config::RA_API_TOKEN.GetLocation(),
|
||||||
};
|
};
|
||||||
|
|
||||||
return std::any_of(begin(s_setting_saveable), end(s_setting_saveable),
|
return std::any_of(begin(s_setting_saveable), end(s_setting_saveable),
|
||||||
|
@ -161,6 +161,7 @@
|
|||||||
<ClInclude Include="Common\WindowsRegistry.h" />
|
<ClInclude Include="Common\WindowsRegistry.h" />
|
||||||
<ClInclude Include="Common\WindowSystemInfo.h" />
|
<ClInclude Include="Common\WindowSystemInfo.h" />
|
||||||
<ClInclude Include="Common\WorkQueueThread.h" />
|
<ClInclude Include="Common\WorkQueueThread.h" />
|
||||||
|
<ClInclude Include="Core\AchievementManager.h" />
|
||||||
<ClInclude Include="Core\ActionReplay.h" />
|
<ClInclude Include="Core\ActionReplay.h" />
|
||||||
<ClInclude Include="Core\ARDecrypt.h" />
|
<ClInclude Include="Core\ARDecrypt.h" />
|
||||||
<ClInclude Include="Core\Boot\Boot.h" />
|
<ClInclude Include="Core\Boot\Boot.h" />
|
||||||
@ -172,6 +173,7 @@
|
|||||||
<ClInclude Include="Core\CheatGeneration.h" />
|
<ClInclude Include="Core\CheatGeneration.h" />
|
||||||
<ClInclude Include="Core\CheatSearch.h" />
|
<ClInclude Include="Core\CheatSearch.h" />
|
||||||
<ClInclude Include="Core\CommonTitles.h" />
|
<ClInclude Include="Core\CommonTitles.h" />
|
||||||
|
<ClInclude Include="Core\Config\AchievementSettings.h" />
|
||||||
<ClInclude Include="Core\Config\DefaultLocale.h" />
|
<ClInclude Include="Core\Config\DefaultLocale.h" />
|
||||||
<ClInclude Include="Core\Config\FreeLookSettings.h" />
|
<ClInclude Include="Core\Config\FreeLookSettings.h" />
|
||||||
<ClInclude Include="Core\Config\GraphicsSettings.h" />
|
<ClInclude Include="Core\Config\GraphicsSettings.h" />
|
||||||
@ -795,6 +797,7 @@
|
|||||||
<ClCompile Include="Common\UPnP.cpp" />
|
<ClCompile Include="Common\UPnP.cpp" />
|
||||||
<ClCompile Include="Common\WindowsRegistry.cpp" />
|
<ClCompile Include="Common\WindowsRegistry.cpp" />
|
||||||
<ClCompile Include="Common\Version.cpp" />
|
<ClCompile Include="Common\Version.cpp" />
|
||||||
|
<ClCompile Include="Core\AchievementManager.cpp" />
|
||||||
<ClCompile Include="Core\ActionReplay.cpp" />
|
<ClCompile Include="Core\ActionReplay.cpp" />
|
||||||
<ClCompile Include="Core\ARDecrypt.cpp" />
|
<ClCompile Include="Core\ARDecrypt.cpp" />
|
||||||
<ClCompile Include="Core\Boot\Boot_BS2Emu.cpp" />
|
<ClCompile Include="Core\Boot\Boot_BS2Emu.cpp" />
|
||||||
@ -805,6 +808,7 @@
|
|||||||
<ClCompile Include="Core\BootManager.cpp" />
|
<ClCompile Include="Core\BootManager.cpp" />
|
||||||
<ClCompile Include="Core\CheatGeneration.cpp" />
|
<ClCompile Include="Core\CheatGeneration.cpp" />
|
||||||
<ClCompile Include="Core\CheatSearch.cpp" />
|
<ClCompile Include="Core\CheatSearch.cpp" />
|
||||||
|
<ClCompile Include="Core\Config\AchievementSettings.cpp" />
|
||||||
<ClCompile Include="Core\Config\DefaultLocale.cpp" />
|
<ClCompile Include="Core\Config\DefaultLocale.cpp" />
|
||||||
<ClCompile Include="Core\Config\FreeLookSettings.cpp" />
|
<ClCompile Include="Core\Config\FreeLookSettings.cpp" />
|
||||||
<ClCompile Include="Core\Config\GraphicsSettings.cpp" />
|
<ClCompile Include="Core\Config\GraphicsSettings.cpp" />
|
||||||
|
@ -52,6 +52,7 @@
|
|||||||
<Import Project="$(ExternalsDir)minizip\exports.props" />
|
<Import Project="$(ExternalsDir)minizip\exports.props" />
|
||||||
<Import Project="$(ExternalsDir)picojson\exports.props" />
|
<Import Project="$(ExternalsDir)picojson\exports.props" />
|
||||||
<Import Project="$(ExternalsDir)pugixml\exports.props" />
|
<Import Project="$(ExternalsDir)pugixml\exports.props" />
|
||||||
|
<Import Project="$(ExternalsDir)rcheevos\exports.props" />
|
||||||
<Import Project="$(ExternalsDir)SDL\exports.props" />
|
<Import Project="$(ExternalsDir)SDL\exports.props" />
|
||||||
<Import Project="$(ExternalsDir)SFML\exports.props" />
|
<Import Project="$(ExternalsDir)SFML\exports.props" />
|
||||||
<Import Project="$(ExternalsDir)soundtouch\exports.props" />
|
<Import Project="$(ExternalsDir)soundtouch\exports.props" />
|
||||||
|
@ -686,4 +686,9 @@ endif()
|
|||||||
|
|
||||||
if(USE_DISCORD_PRESENCE)
|
if(USE_DISCORD_PRESENCE)
|
||||||
target_compile_definitions(dolphin-emu PRIVATE -DUSE_DISCORD_PRESENCE)
|
target_compile_definitions(dolphin-emu PRIVATE -DUSE_DISCORD_PRESENCE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(USE_RETRO_ACHIEVEMENTS)
|
||||||
|
target_link_libraries(dolphin-emu PRIVATE rcheevos)
|
||||||
|
target_compile_definitions(dolphin-emu PRIVATE -DUSE_RETRO_ACHIEVEMENTS)
|
||||||
|
endif()
|
||||||
|
@ -436,6 +436,7 @@
|
|||||||
<Import Project="$(ExternalsDir)mbedtls\exports.props" />
|
<Import Project="$(ExternalsDir)mbedtls\exports.props" />
|
||||||
<Import Project="$(ExternalsDir)mGBA\exports.props" />
|
<Import Project="$(ExternalsDir)mGBA\exports.props" />
|
||||||
<Import Project="$(ExternalsDir)picojson\exports.props" />
|
<Import Project="$(ExternalsDir)picojson\exports.props" />
|
||||||
|
<Import Project="$(ExternalsDir)rcheevos\exports.props" />
|
||||||
<Import Project="$(ExternalsDir)SFML\exports.props" />
|
<Import Project="$(ExternalsDir)SFML\exports.props" />
|
||||||
<Import Project="$(ExternalsDir)soundtouch\exports.props" />
|
<Import Project="$(ExternalsDir)soundtouch\exports.props" />
|
||||||
<Import Project="$(ExternalsDir)zstd\exports.props" />
|
<Import Project="$(ExternalsDir)zstd\exports.props" />
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include "Common/Version.h"
|
#include "Common/Version.h"
|
||||||
#include "Common/WindowSystemInfo.h"
|
#include "Common/WindowSystemInfo.h"
|
||||||
|
|
||||||
|
#include "Core/AchievementManager.h"
|
||||||
#include "Core/Boot/Boot.h"
|
#include "Core/Boot/Boot.h"
|
||||||
#include "Core/BootManager.h"
|
#include "Core/BootManager.h"
|
||||||
#include "Core/CommonTitles.h"
|
#include "Core/CommonTitles.h"
|
||||||
@ -222,6 +223,11 @@ MainWindow::MainWindow(std::unique_ptr<BootParameters> boot_parameters,
|
|||||||
|
|
||||||
InitControllers();
|
InitControllers();
|
||||||
|
|
||||||
|
#ifdef USE_RETRO_ACHIEVEMENTS
|
||||||
|
// This has to be done before CreateComponents() so it's initialized.
|
||||||
|
AchievementManager::GetInstance()->Init();
|
||||||
|
#endif // USE_RETRO_ACHIEVEMENTS
|
||||||
|
|
||||||
CreateComponents();
|
CreateComponents();
|
||||||
|
|
||||||
ConnectGameList();
|
ConnectGameList();
|
||||||
@ -301,6 +307,10 @@ MainWindow::~MainWindow()
|
|||||||
Settings::Instance().ResetNetPlayClient();
|
Settings::Instance().ResetNetPlayClient();
|
||||||
Settings::Instance().ResetNetPlayServer();
|
Settings::Instance().ResetNetPlayServer();
|
||||||
|
|
||||||
|
#ifdef USE_RETRO_ACHIEVEMENTS
|
||||||
|
AchievementManager::GetInstance()->Shutdown();
|
||||||
|
#endif // USE_RETRO_ACHIEVEMENTS
|
||||||
|
|
||||||
delete m_render_widget;
|
delete m_render_widget;
|
||||||
delete m_netplay_dialog;
|
delete m_netplay_dialog;
|
||||||
|
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
<PreprocessorDefinitions Condition="'$(AutoUpdate)'!='false'">AUTOUPDATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions Condition="'$(AutoUpdate)'!='false'">AUTOUPDATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<PreprocessorDefinitions>HAVE_SDL2;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>HAVE_SDL2;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<PreprocessorDefinitions Condition="'$(Steam)'=='true'">STEAM;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions Condition="'$(Steam)'=='true'">STEAM;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<PreprocessorDefinitions>USE_RETRO_ACHIEVEMENTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
|
||||||
<!-- Warnings one may want to ignore when using Level4.
|
<!-- Warnings one may want to ignore when using Level4.
|
||||||
4201 nonstandard extension used : nameless struct/union
|
4201 nonstandard extension used : nameless struct/union
|
||||||
|
@ -87,6 +87,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FatFs", "..\Externals\FatFs
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spng", "..\Externals\libspng\spng.vcxproj", "{447B7B1E-1D74-4AEF-B2B9-6EB41C5D5313}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spng", "..\Externals\libspng\spng.vcxproj", "{447B7B1E-1D74-4AEF-B2B9-6EB41C5D5313}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rcheevos", "..\Externals\rcheevos\rcheevos.vcxproj", "{CC99A910-3752-4465-95AA-7DC240D92A99}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|ARM64 = Debug|ARM64
|
Debug|ARM64 = Debug|ARM64
|
||||||
@ -419,6 +421,14 @@ Global
|
|||||||
{447B7B1E-1D74-4AEF-B2B9-6EB41C5D5313}.Release|ARM64.Build.0 = Release|ARM64
|
{447B7B1E-1D74-4AEF-B2B9-6EB41C5D5313}.Release|ARM64.Build.0 = Release|ARM64
|
||||||
{447B7B1E-1D74-4AEF-B2B9-6EB41C5D5313}.Release|x64.ActiveCfg = Release|x64
|
{447B7B1E-1D74-4AEF-B2B9-6EB41C5D5313}.Release|x64.ActiveCfg = Release|x64
|
||||||
{447B7B1E-1D74-4AEF-B2B9-6EB41C5D5313}.Release|x64.Build.0 = Release|x64
|
{447B7B1E-1D74-4AEF-B2B9-6EB41C5D5313}.Release|x64.Build.0 = Release|x64
|
||||||
|
{CC99A910-3752-4465-95AA-7DC240D92A99}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||||
|
{CC99A910-3752-4465-95AA-7DC240D92A99}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||||
|
{CC99A910-3752-4465-95AA-7DC240D92A99}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{CC99A910-3752-4465-95AA-7DC240D92A99}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{CC99A910-3752-4465-95AA-7DC240D92A99}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||||
|
{CC99A910-3752-4465-95AA-7DC240D92A99}.Release|ARM64.Build.0 = Release|ARM64
|
||||||
|
{CC99A910-3752-4465-95AA-7DC240D92A99}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{CC99A910-3752-4465-95AA-7DC240D92A99}.Release|x64.Build.0 = Release|x64
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@ -455,6 +465,7 @@ Global
|
|||||||
{8DC244EE-A0BD-4038-BAF7-CFAFA5EB2BAA} = {87ADDFF9-5768-4DA2-A33B-2477593D6677}
|
{8DC244EE-A0BD-4038-BAF7-CFAFA5EB2BAA} = {87ADDFF9-5768-4DA2-A33B-2477593D6677}
|
||||||
{3F17D282-A77D-4931-B844-903AD0809A5E} = {87ADDFF9-5768-4DA2-A33B-2477593D6677}
|
{3F17D282-A77D-4931-B844-903AD0809A5E} = {87ADDFF9-5768-4DA2-A33B-2477593D6677}
|
||||||
{447B7B1E-1D74-4AEF-B2B9-6EB41C5D5313} = {87ADDFF9-5768-4DA2-A33B-2477593D6677}
|
{447B7B1E-1D74-4AEF-B2B9-6EB41C5D5313} = {87ADDFF9-5768-4DA2-A33B-2477593D6677}
|
||||||
|
{CC99A910-3752-4465-95AA-7DC240D92A99} = {87ADDFF9-5768-4DA2-A33B-2477593D6677}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {64B0A343-3B94-4522-9C24-6937FE5EFB22}
|
SolutionGuid = {64B0A343-3B94-4522-9C24-6937FE5EFB22}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user