diff --git a/cheevos/cheevos.c b/cheevos/cheevos.c index d20f80a9159..9ad7f27caea 100644 --- a/cheevos/cheevos.c +++ b/cheevos/cheevos.c @@ -31,6 +31,7 @@ #include #include #include +#include #ifdef HAVE_CONFIG_H #include "../config.h" @@ -70,9 +71,11 @@ #include "../runtime_file.h" #include "../core.h" #include "../core_option_manager.h" +#include "../version.h" #include "../tasks/tasks_internal.h" +#include "../deps/rcheevos/include/rc_client_raintegration.h" #include "../deps/rcheevos/include/rc_runtime.h" #include "../deps/rcheevos/include/rc_runtime_types.h" #include "../deps/rcheevos/include/rc_hash.h" @@ -3103,6 +3106,104 @@ bool rcheevos_load_aborted(void) #endif /* HAVE_RC_CLIENT */ +#ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION + +static void rc_client_raintegration_hardcore_changed(rc_client_t* client) +{ + const bool hardcore_enabled = rc_client_get_hardcore_enabled(client); + if (hardcore_enabled) + { + if (rcheevos_locals.hardcore_allowed) + { + rcheevos_validate_config_settings(); + if (rcheevos_locals.hardcore_allowed) + { + cheat_manager_apply_cheats(); + if (rcheevos_locals.hardcore_allowed) + rcheevos_enforce_hardcore_settings(); + } + } + + if (!rcheevos_locals.hardcore_allowed) + { + /* local setting prevented hardcore enablement - message should + * have been displayed */ + rc_client_set_hardcore_enabled(client, false); + return; + } + } + + { + settings_t* settings = config_get_ptr(); + settings->bools.cheevos_hardcore_mode_enable = hardcore_enabled; + + bool rewind_enable = settings->bools.rewind_enable; + if (rewind_enable) + { + const enum event_command cmd = hardcore_enabled ? + CMD_EVENT_REWIND_DEINIT : CMD_EVENT_REWIND_INIT; + +#ifdef HAVE_THREADS + if (!task_is_on_main_thread()) + { + /* have to "schedule" this. + * CMD_EVENT_REWIND_DEINIT should + * only be called on the main thread */ + rcheevos_locals.queued_command = cmd; + } + else +#endif + command_event(cmd, NULL); + } + } +} + +static void rcheevos_raintegration_event_handler(const rc_client_raintegration_event_t* event, rc_client_t* client) +{ + switch (event->type) + { + case RC_CLIENT_RAINTEGRATION_EVENT_MENUITEM_CHECKED_CHANGED: + rc_client_raintegration_update_menu_item(client, event->menu_item); + break; + case RC_CLIENT_RAINTEGRATION_EVENT_PAUSE: + command_event(CMD_EVENT_PAUSE, NULL); /* pause the game */ + break; + case RC_CLIENT_RAINTEGRATION_EVENT_HARDCORE_CHANGED: + rc_client_raintegration_hardcore_changed(client); + break; + default: +#ifndef NDEBUG + CHEEVOS_LOG(RCHEEVOS_TAG "Unsupported raintegration event %u\n", event->type); +#endif + break; + } +} + +static void rcheevos_load_raintegration_callback(int result, + const char* error_message, rc_client_t* client, void* userdata) +{ + struct retro_game_info* info = (struct retro_game_info*)userdata; + + rc_client_raintegration_set_event_handler(client, rcheevos_raintegration_event_handler); + + rcheevos_load(info); + + if (info->path) + free((void*)info->path); + if (info->data) + free((void*)info->data); + free(info); + + /* the raintegration initialization process may start before the window is created. + * ensure the handle is correct */ + rc_client_raintegration_update_main_window_handle(rcheevos_locals.client, win32_get_window()); + + /* initialization has finished, the menu can be populated now */ + rcheevos_rebuild_integration_menu(); +} + +#endif + bool rcheevos_load(const void *data) { const struct retro_game_info *info = (const struct retro_game_info*)data; @@ -3183,6 +3284,27 @@ bool rcheevos_load(const void *data) } rcheevos_client_download_placeholder_badge(); + +#ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION + { + struct retro_game_info* info_copy = (struct retro_game_info*) + calloc(1, sizeof(*info)); + info_copy->path = (info->path) ? strdup(info->path) : NULL; + if (info->data) + { + info_copy->data = malloc(info->size); + memcpy((void*)info_copy->data, info->data, info->size); + info_copy->size = info->size; + } + + // TODO: use local path + rc_client_begin_load_raintegration(rcheevos_locals.client, + L"E:\\Source\\RetroAchievements\\RAIntegration\\bin\\x64\\Debug", + (HWND)video_driver_window_get(), "RetroArch", PACKAGE_VERSION, + rcheevos_load_raintegration_callback, info_copy); + return true; + } +#endif } rc_client_set_hardcore_enabled(rcheevos_locals.client, settings->bools.cheevos_hardcore_mode_enable); diff --git a/cheevos/cheevos_menu.c b/cheevos/cheevos_menu.c index 9b59c0635b7..8bad5eab962 100644 --- a/cheevos/cheevos_menu.c +++ b/cheevos/cheevos_menu.c @@ -531,6 +531,36 @@ uintptr_t rcheevos_get_badge_texture(const char* badge, bool locked, bool downlo return tex; } +#ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION + +void rcheevos_update_hwnd(HWND hWnd) +{ + rc_client_raintegration_update_main_window_handle(rcheevos_locals.client, hWnd); +} + +void rcheevos_append_integration_menu(HMENU hMenu) +{ + rc_client_raintegration_rebuild_submenu(rcheevos_locals.client, hMenu); +} + +void rcheevos_rebuild_integration_menu() +{ + if (rcheevos_locals.client->state.raintegration && + rcheevos_locals.client->state.raintegration->hPopupMenu) + { + HWND hWnd = (HWND)video_driver_window_get(); + rc_client_raintegration_rebuild_submenu(rcheevos_locals.client, GetMenu(hWnd)); + //DrawMenuBar(hWnd); + } +} + +bool rcheevos_activate_integration_menu_item(uint32_t nMenuItemId) +{ + return rc_client_raintegration_activate_menu_item(rcheevos_locals.client, nMenuItemId); +} + +#endif /* RC_CLIENT_SUPPORTS_RAINTEGRATION */ + #else /* !HAVE_RC_CLIENT */ enum rcheevos_menuitem_bucket diff --git a/cheevos/cheevos_menu.h b/cheevos/cheevos_menu.h index 9813557299f..205c35cc163 100644 --- a/cheevos/cheevos_menu.h +++ b/cheevos/cheevos_menu.h @@ -35,6 +35,13 @@ bool rcheevos_menu_get_sublabel(unsigned menu_offset, char* buffer, size_t buffe uintptr_t rcheevos_menu_get_badge_texture(unsigned menu_offset); void rcheevos_menu_reset_badges(void); +#ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION +void rcheevos_update_hwnd(HWND hWnd); +void rcheevos_rebuild_integration_menu(); +void rcheevos_append_integration_menu(HMENU hMenu); +bool rcheevos_activate_integration_menu_item(uint32_t nMenuItemId); +#endif + RETRO_END_DECLS #endif /* HAVE_MENU */ diff --git a/deps/rcheevos/include/rc_api_info.h b/deps/rcheevos/include/rc_api_info.h index a9586eeb9a2..93b652bf7ac 100644 --- a/deps/rcheevos/include/rc_api_info.h +++ b/deps/rcheevos/include/rc_api_info.h @@ -6,9 +6,7 @@ #include #include -#ifdef __cplusplus -extern "C" { -#endif +RC_BEGIN_C_DECLS /* --- Fetch Achievement Info --- */ @@ -63,10 +61,10 @@ typedef struct rc_api_fetch_achievement_info_response_t { } rc_api_fetch_achievement_info_response_t; -int rc_api_init_fetch_achievement_info_request(rc_api_request_t* request, const rc_api_fetch_achievement_info_request_t* api_params); -int rc_api_process_fetch_achievement_info_response(rc_api_fetch_achievement_info_response_t* response, const char* server_response); -int rc_api_process_fetch_achievement_info_server_response(rc_api_fetch_achievement_info_response_t* response, const rc_api_server_response_t* server_response); -void rc_api_destroy_fetch_achievement_info_response(rc_api_fetch_achievement_info_response_t* response); +RC_EXPORT int RC_CCONV rc_api_init_fetch_achievement_info_request(rc_api_request_t* request, const rc_api_fetch_achievement_info_request_t* api_params); +RC_EXPORT int RC_CCONV rc_api_process_fetch_achievement_info_response(rc_api_fetch_achievement_info_response_t* response, const char* server_response); +RC_EXPORT int RC_CCONV rc_api_process_fetch_achievement_info_server_response(rc_api_fetch_achievement_info_response_t* response, const rc_api_server_response_t* server_response); +RC_EXPORT void RC_CCONV rc_api_destroy_fetch_achievement_info_response(rc_api_fetch_achievement_info_response_t* response); /* --- Fetch Leaderboard Info --- */ @@ -135,10 +133,10 @@ typedef struct rc_api_fetch_leaderboard_info_response_t { } rc_api_fetch_leaderboard_info_response_t; -int rc_api_init_fetch_leaderboard_info_request(rc_api_request_t* request, const rc_api_fetch_leaderboard_info_request_t* api_params); -int rc_api_process_fetch_leaderboard_info_response(rc_api_fetch_leaderboard_info_response_t* response, const char* server_response); -int rc_api_process_fetch_leaderboard_info_server_response(rc_api_fetch_leaderboard_info_response_t* response, const rc_api_server_response_t* server_response); -void rc_api_destroy_fetch_leaderboard_info_response(rc_api_fetch_leaderboard_info_response_t* response); +RC_EXPORT int RC_CCONV rc_api_init_fetch_leaderboard_info_request(rc_api_request_t* request, const rc_api_fetch_leaderboard_info_request_t* api_params); +RC_EXPORT int RC_CCONV rc_api_process_fetch_leaderboard_info_response(rc_api_fetch_leaderboard_info_response_t* response, const char* server_response); +RC_EXPORT int RC_CCONV rc_api_process_fetch_leaderboard_info_server_response(rc_api_fetch_leaderboard_info_response_t* response, const rc_api_server_response_t* server_response); +RC_EXPORT void RC_CCONV rc_api_destroy_fetch_leaderboard_info_response(rc_api_fetch_leaderboard_info_response_t* response); /* --- Fetch Games List --- */ @@ -174,13 +172,11 @@ typedef struct rc_api_fetch_games_list_response_t { } rc_api_fetch_games_list_response_t; -int rc_api_init_fetch_games_list_request(rc_api_request_t* request, const rc_api_fetch_games_list_request_t* api_params); -int rc_api_process_fetch_games_list_response(rc_api_fetch_games_list_response_t* response, const char* server_response); -int rc_api_process_fetch_games_list_server_response(rc_api_fetch_games_list_response_t* response, const rc_api_server_response_t* server_response); -void rc_api_destroy_fetch_games_list_response(rc_api_fetch_games_list_response_t* response); +RC_EXPORT int RC_CCONV rc_api_init_fetch_games_list_request(rc_api_request_t* request, const rc_api_fetch_games_list_request_t* api_params); +RC_EXPORT int RC_CCONV rc_api_process_fetch_games_list_response(rc_api_fetch_games_list_response_t* response, const char* server_response); +RC_EXPORT int RC_CCONV rc_api_process_fetch_games_list_server_response(rc_api_fetch_games_list_response_t* response, const rc_api_server_response_t* server_response); +RC_EXPORT void RC_CCONV rc_api_destroy_fetch_games_list_response(rc_api_fetch_games_list_response_t* response); -#ifdef __cplusplus -} -#endif +RC_END_C_DECLS #endif /* RC_API_INFO_H */ diff --git a/deps/rcheevos/src/rcheevos/rc_version.h b/deps/rcheevos/src/rcheevos/rc_version.h deleted file mode 100644 index cdf857d5f57..00000000000 --- a/deps/rcheevos/src/rcheevos/rc_version.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef RC_VERSION_H -#define RC_VERSION_H - -#ifdef __cplusplus -extern "C" { -#endif - -#define RCHEEVOS_VERSION_MAJOR 10 -#define RCHEEVOS_VERSION_MINOR 7 -#define RCHEEVOS_VERSION_PATCH 0 - -#define RCHEEVOS_MAKE_VERSION(major, minor, patch) (major * 1000000 + minor * 1000 + patch) -#define RCHEEVOS_VERSION RCHEEVOS_MAKE_VERSION(RCHEEVOS_VERSION_MAJOR, RCHEEVOS_VERSION_MINOR, RCHEEVOS_VERSION_PATCH) - -#define RCHEEVOS_MAKE_STRING(num) #num -#define RCHEEVOS_MAKE_VERSION_STRING(major, minor, patch) RCHEEVOS_MAKE_STRING(major) "." RCHEEVOS_MAKE_STRING(minor) "." RCHEEVOS_MAKE_STRING(patch) -#define RCHEEVOS_MAKE_VERSION_STRING_SHORT(major, minor) RCHEEVOS_MAKE_STRING(major) "." RCHEEVOS_MAKE_STRING(minor) - -#if RCHEEVOS_VERSION_PATCH > 0 - #define RCHEEVOS_VERSION_STRING RCHEEVOS_MAKE_VERSION_STRING(RCHEEVOS_VERSION_MAJOR, RCHEEVOS_VERSION_MINOR, RCHEEVOS_VERSION_PATCH) -#else - #define RCHEEVOS_VERSION_STRING RCHEEVOS_MAKE_VERSION_STRING_SHORT(RCHEEVOS_VERSION_MAJOR, RCHEEVOS_VERSION_MINOR) -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* RC_VERSION_H */ diff --git a/gfx/common/win32_common.c b/gfx/common/win32_common.c index ecf9b9a5569..b29c7992c29 100644 --- a/gfx/common/win32_common.c +++ b/gfx/common/win32_common.c @@ -63,6 +63,10 @@ #include "../../menu/menu_driver.h" #endif +#ifdef HAVE_CHEEVOS +#include "../../cheevos/cheevos_menu.h" +#endif + #include /* Assume W-functions do not work below Win2K and Xbox platforms */ @@ -851,6 +855,13 @@ static LRESULT win32_menu_loop(HWND owner, WPARAM wparam) configuration_set_int( settings, settings->ints.state_slot, idx); } +#ifdef HAVE_CHEEVOS + #ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION + else if (rcheevos_activate_integration_menu_item(mode)) + { + } + #endif +#endif break; } @@ -1833,6 +1844,13 @@ bool win32_window_create(void *data, unsigned style, window_opacity) / 100, LWA_ALPHA); } #endif + +#ifdef HAVE_CHEEVOS + #ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION + rcheevos_update_hwnd(main_window.hwnd); + #endif +#endif + return true; } #endif @@ -2430,6 +2448,12 @@ void win32_set_window(unsigned *width, unsigned *height, { RECT *rect = (RECT*)rect_data; +#ifdef HAVE_CHEEVOS + #ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION + rcheevos_update_hwnd(main_window.hwnd); + #endif +#endif + if (!fullscreen || windowed_full) { settings_t *settings = config_get_ptr(); @@ -2450,6 +2474,12 @@ void win32_set_window(unsigned *width, unsigned *height, win32_localize_menu(menuItem); SetMenu(main_window.hwnd, menuItem); +#ifdef HAVE_CHEEVOS + #ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION + rcheevos_append_integration_menu(menuItem); + #endif +#endif + SendMessage(main_window.hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&rc_temp); g_win32_resize_height = *height += rc_temp.top + rect->top; SetWindowPos(main_window.hwnd, NULL, 0, 0, *width, *height, SWP_NOMOVE); diff --git a/griffin/griffin.c b/griffin/griffin.c index c735128e3da..c5b48c29052 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -195,6 +195,10 @@ ACHIEVEMENTS #define RC_NO_THREADS 1 #endif +#if defined(_WIN32) +#define RC_CLIENT_SUPPORTS_RAINTEGRATION +#endif + #include "../libretro-common/formats/cdfs/cdfs.c" #include "../network/net_http_special.c" @@ -227,6 +231,10 @@ ACHIEVEMENTS #include "../deps/rcheevos/src/rhash/cdreader.c" #include "../deps/rcheevos/src/rhash/hash.c" +#ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION +#include "../deps/rcheevos/src/rc_client_raintegration.c" +#endif + #endif /*============================================================