Merge branch 'master' of git://github.com/celerizer/RetroArch into celerizer-test

This commit is contained in:
twinaphex 2020-02-14 21:56:14 +01:00
commit 386199e422
14 changed files with 238 additions and 8 deletions

View File

@ -27,6 +27,7 @@
#include <retro_miscellaneous.h>
#include <retro_math.h>
#include <net/net_http.h>
#include <encodings/utf.h>
#include <libretro.h>
#ifdef HAVE_CONFIG_H
@ -45,6 +46,10 @@
#include <rthreads/rthreads.h>
#endif
#ifdef HAVE_DISCORD
#include "../discord/discord.h"
#endif
#include "badges.h"
#include "cheevos.h"
#include "fixup.h"
@ -97,6 +102,10 @@
/* Define this macro to log downloaded badge images. */
#undef CHEEVOS_LOG_BADGES
/* Number of usecs to wait between posting rich presence to the site. */
/* Keep consistent with SERVER_PING_FREQUENCY from RAIntegration. */
#define CHEEVOS_PING_FREQUENCY 2 * 60 * 1000000
typedef struct
{
rc_trigger_t* trigger;
@ -114,6 +123,13 @@ typedef struct
int format;
} rcheevos_lboard_t;
typedef struct
{
rc_richpresence_t* richpresence;
char evaluation[256];
retro_time_t last_update;
} rcheevos_richpresence_t;
typedef struct
{
retro_task_t* task;
@ -128,6 +144,7 @@ typedef struct
rcheevos_cheevo_t* core;
rcheevos_cheevo_t* unofficial;
rcheevos_lboard_t* lboards;
rcheevos_richpresence_t richpresence;
rcheevos_fixups_t fixups;
@ -164,6 +181,7 @@ static rcheevos_locals_t rcheevos_locals =
NULL, /* core */
NULL, /* unofficial */
NULL, /* lboards */
{0}, /* rich presence */
{0}, /* fixups */
{0}, /* token */
"N/A",/* hash */
@ -399,6 +417,7 @@ static int rcheevos_parse(const char* json)
rcheevos_locals.core = NULL;
rcheevos_locals.unofficial = NULL;
rcheevos_locals.lboards = NULL;
rcheevos_locals.richpresence.richpresence = NULL;
rcheevos_free_patchdata(&rcheevos_locals.patchdata);
return 0;
}
@ -551,6 +570,98 @@ static int rcheevos_parse(const char* json)
lboard->format = rc_parse_format(lboard->info->format);
}
if (rcheevos_locals.patchdata.richpresence_script)
{
char *script = rcheevos_locals.patchdata.richpresence_script;
char *buffer_it = &script[0];
const char *script_it = &script[0];
unsigned buffer_size;
while (*script_it != '\0')
{
if (*script_it == '\\')
{
char escaped_char = *(script_it + 1);
switch (escaped_char)
{
/* Ignore carriage return */
case 'r':
script_it += 2;
break;
/* Accept newlines */
case 'n':
*buffer_it = '\n';
buffer_it++;
script_it += 2;
break;
/* Accept UTF-16 unicode characters */
case 'u':
{
uint16_t *utf16;
char *utf8;
uint8_t i, j;
for (i = 1; i < 16; i++)
if (strncmp((script_it + 6 * i), "\\u", 2))
break;
utf16 = (uint16_t*)calloc(i, sizeof(uint16_t));
utf8 = (char*) calloc(i * 4, sizeof(char));
/* Get escaped hex values and add them to the string */
for (j = 0; j < i; j++)
{
char temp[5];
script_it += 2;
memcpy(temp, script_it, 4);
temp[4] = '\0';
utf16[j] = string_hex_to_unsigned(temp);
script_it += 4;
}
if (utf16_to_char_string(utf16, utf8, i * 4))
{
memcpy(buffer_it, utf8, strlen(utf8));
buffer_it += strlen(utf8);
}
free(utf16);
free(utf8);
}
break;
default:
*buffer_it = *script_it;
buffer_it++;
script_it++;
};
}
else
{
*buffer_it = *script_it;
buffer_it++;
script_it++;
}
}
*buffer_it = '\0';
buffer_size = rc_richpresence_size(rcheevos_locals.patchdata.richpresence_script);
if (buffer_size == 0)
{
rcheevos_locals.richpresence.richpresence = NULL;
CHEEVOS_ERR(RCHEEVOS_TAG "Error reading rich presence");
}
else
{
char *buffer = (char*)malloc(buffer_size);
rcheevos_locals.richpresence.richpresence = rc_parse_richpresence(buffer, script, NULL, 0);
rcheevos_locals.richpresence.last_update = cpu_features_get_time_usec();
}
}
return 0;
error:
@ -934,6 +1045,49 @@ static void rcheevos_test_leaderboards(void)
}
}
const char* rcheevos_get_richpresence(void)
{
if (!rcheevos_locals.richpresence.richpresence)
return NULL;
else
return rcheevos_locals.richpresence.evaluation;
}
static void rcheevos_test_richpresence(void)
{
if (!rcheevos_locals.richpresence.richpresence ||
cpu_features_get_time_usec() < rcheevos_locals.richpresence.last_update + CHEEVOS_PING_FREQUENCY)
return;
else
{
settings_t* settings = config_get_ptr();
char url[256], post_data[1024];
rcheevos_locals.richpresence.last_update = cpu_features_get_time_usec();
rc_evaluate_richpresence(rcheevos_locals.richpresence.richpresence,
rcheevos_locals.richpresence.evaluation,
sizeof(rcheevos_locals.richpresence.evaluation), rcheevos_peek, NULL, NULL);
/* Form URL */
snprintf(url, 256, "http://retroachievements.org/dorequest.php?r=ping&u=%s&t=%s",
settings->arrays.cheevos_username,
rcheevos_locals.token);
/* Form POST data */
snprintf(post_data, 1024, "g=%u&m=%s",
rcheevos_locals.patchdata.game_id,
rcheevos_get_richpresence());
#ifdef HAVE_DISCORD
if (settings->bools.discord_enable)
discord_update(DISCORD_PRESENCE_RETROACHIEVEMENTS);
#endif
task_push_http_post_transfer(url, post_data, true, "POST", NULL, NULL);
}
}
void rcheevos_reset_game(void)
{
rcheevos_cheevo_t* cheevo;
@ -971,6 +1125,8 @@ void rcheevos_reset_game(void)
lboard->lboard->submitted = 1;
}
}
rcheevos_locals.richpresence.last_update = cpu_features_get_time_usec();
}
#ifdef HAVE_MENU
@ -1143,12 +1299,14 @@ bool rcheevos_unload(void)
CHEEVOS_FREE(rcheevos_locals.core);
CHEEVOS_FREE(rcheevos_locals.unofficial);
CHEEVOS_FREE(rcheevos_locals.lboards);
CHEEVOS_FREE(rcheevos_locals.richpresence.richpresence);
rcheevos_free_patchdata(&rcheevos_locals.patchdata);
rcheevos_fixup_destroy(&rcheevos_locals.fixups);
rcheevos_locals.core = NULL;
rcheevos_locals.unofficial = NULL;
rcheevos_locals.lboards = NULL;
rcheevos_locals.richpresence.richpresence = NULL;
rcheevos_loaded = false;
rcheevos_hardcore_active = false;
@ -1210,6 +1368,9 @@ void rcheevos_test(void)
settings->bools.cheevos_leaderboards_enable &&
!rcheevos_hardcore_paused)
rcheevos_test_leaderboards();
if (settings->bools.cheevos_richpresence_enable)
rcheevos_test_richpresence();
}
}

View File

@ -66,6 +66,8 @@ int rcheevos_get_console(void);
const char* rcheevos_get_hash(void);
const char *rcheevos_get_richpresence(void);
extern bool rcheevos_loaded;
extern bool rcheevos_hardcore_active;
extern bool rcheevos_hardcore_paused;

View File

@ -23,6 +23,7 @@
#define CHEEVOS_JSON_KEY_TOKEN 0x0e2dbd26U
#define CHEEVOS_JSON_KEY_FLAGS 0x0d2e96b2U
#define CHEEVOS_JSON_KEY_LEADERBOARDS 0xf1247d2dU
#define CHEEVOS_JSON_KEY_RICHPRESENCE 0xf18dd230U
#define CHEEVOS_JSON_KEY_MEM 0x0b8807e4U
#define CHEEVOS_JSON_KEY_FORMAT 0xb341208eU
#define CHEEVOS_JSON_KEY_SUCCESS 0x110461deU
@ -261,7 +262,9 @@ typedef struct
{
int in_cheevos;
int in_lboards;
int is_game_id;
int is_console_id;
int is_richpresence;
unsigned core_count;
unsigned unofficial_count;
unsigned lboard_count;
@ -386,9 +389,14 @@ static int rcheevos_read_key(void* userdata,
case CHEEVOS_JSON_KEY_CONSOLE_ID:
ud->is_console_id = 1;
break;
case CHEEVOS_JSON_KEY_RICHPRESENCE:
ud->is_richpresence = 1;
break;
case CHEEVOS_JSON_KEY_ID:
if (common)
ud->field = &ud->id;
else
ud->is_game_id = 1;
break;
case CHEEVOS_JSON_KEY_MEMADDR:
if (ud->in_cheevos)
@ -451,6 +459,13 @@ static int rcheevos_read_string(void* userdata,
ud->field->string = string;
ud->field->length = length;
}
else if (ud->is_richpresence)
{
ud->patchdata->richpresence_script = (char*)malloc(length + 1);
memcpy(ud->patchdata->richpresence_script, string, length);
ud->patchdata->richpresence_script[length] = '\0';
ud->is_richpresence = 0;
}
return 0;
}
@ -465,6 +480,11 @@ static int rcheevos_read_number(void* userdata,
ud->field->string = number;
ud->field->length = length;
}
else if (ud->is_game_id)
{
ud->patchdata->game_id = (unsigned)strtol(number, NULL, 10);
ud->is_game_id = 0;
}
else if (ud->is_console_id)
{
ud->patchdata->console_id = (unsigned)strtol(number, NULL, 10);
@ -527,7 +547,9 @@ int rcheevos_get_patchdata(const char* json, rcheevos_rapatchdata_t* patchdata)
/* Load the achievements. */
ud.in_cheevos = 0;
ud.in_lboards = 0;
ud.is_game_id = 0;
ud.is_console_id = 0;
ud.is_richpresence = 0;
ud.field = NULL;
ud.core_count = 0;
ud.unofficial_count = 0;
@ -586,7 +608,9 @@ void rcheevos_free_patchdata(rcheevos_rapatchdata_t* patchdata)
CHEEVOS_FREE(patchdata->core);
CHEEVOS_FREE(patchdata->unofficial);
CHEEVOS_FREE(patchdata->lboards);
CHEEVOS_FREE(patchdata->richpresence_script);
patchdata->game_id = 0;
patchdata->console_id = 0;
patchdata->core = NULL;
patchdata->unofficial = NULL;

View File

@ -42,11 +42,13 @@ typedef struct {
} rcheevos_ralboard_t;
typedef struct {
unsigned game_id;
unsigned console_id;
rcheevos_racheevo_t* core;
rcheevos_racheevo_t* unofficial;
rcheevos_ralboard_t* lboards;
char* richpresence_script;
unsigned core_count;
unsigned unofficial_count;

View File

@ -1583,6 +1583,7 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings,
SETTING_BOOL("cheevos_test_unofficial", &settings->bools.cheevos_test_unofficial, true, false, false);
SETTING_BOOL("cheevos_hardcore_mode_enable", &settings->bools.cheevos_hardcore_mode_enable, true, false, false);
SETTING_BOOL("cheevos_leaderboards_enable", &settings->bools.cheevos_leaderboards_enable, true, false, false);
SETTING_BOOL("cheevos_richpresence_enable", &settings->bools.cheevos_richpresence_enable, true, false, false);
SETTING_BOOL("cheevos_verbose_enable", &settings->bools.cheevos_verbose_enable, true, false, false);
SETTING_BOOL("cheevos_auto_screenshot", &settings->bools.cheevos_auto_screenshot, true, false, false);
#ifdef HAVE_XMB

View File

@ -290,6 +290,7 @@ typedef struct settings
bool cheevos_test_unofficial;
bool cheevos_hardcore_mode_enable;
bool cheevos_leaderboards_enable;
bool cheevos_richpresence_enable;
bool cheevos_badges_enable;
bool cheevos_verbose_enable;
bool cheevos_auto_screenshot;

View File

@ -451,6 +451,12 @@ void discord_update(enum discord_presence presence, bool fuzzy_archive_match)
}
}
break;
#ifdef HAVE_CHEEVOS
case DISCORD_PRESENCE_RETROACHIEVEMENTS:
discord_presence.details = rcheevos_get_richpresence();
presence = DISCORD_PRESENCE_GAME;
break;
#endif
case DISCORD_PRESENCE_SHUTDOWN:
discord_presence.partyId = NULL;
discord_presence.partyMax = 0;

View File

@ -33,6 +33,7 @@ enum discord_presence
DISCORD_PRESENCE_NETPLAY_HOSTING,
DISCORD_PRESENCE_NETPLAY_CLIENT,
DISCORD_PRESENCE_NETPLAY_NETPLAY_STOPPED,
DISCORD_PRESENCE_RETROACHIEVEMENTS,
DISCORD_PRESENCE_SHUTDOWN
};

View File

@ -164,6 +164,8 @@ MSG_HASH(MENU_ENUM_LABEL_CHEEVOS_HARDCORE_MODE_ENABLE,
"cheevos_hardcore_mode_enable")
MSG_HASH(MENU_ENUM_LABEL_CHEEVOS_LEADERBOARDS_ENABLE,
"cheevos_leaderboards_enable")
MSG_HASH(MENU_ENUM_LABEL_CHEEVOS_RICHPRESENCE_ENABLE,
"cheevos_richpresence_enable")
MSG_HASH(MENU_ENUM_LABEL_CHEEVOS_BADGES_ENABLE,
"cheevos_badges_enable")
MSG_HASH(MENU_ENUM_LABEL_CHEEVOS_LOCKED_ENTRY,

View File

@ -540,6 +540,10 @@ MSG_HASH(
MENU_ENUM_LABEL_VALUE_CHEEVOS_LEADERBOARDS_ENABLE,
"Leaderboards"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_CHEEVOS_RICHPRESENCE_ENABLE,
"Rich Presence"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_CHEEVOS_BADGES_ENABLE,
"Achievement Badges"
@ -4565,6 +4569,10 @@ MSG_HASH(
"Game specific leaderboards.\n"
"Has no effect if Hardcore Mode is disabled."
)
MSG_HASH(
MENU_ENUM_SUBLABEL_CHEEVOS_RICHPRESENCE_ENABLE,
"Sends detailed play status to the RetroAchievements website."
)
MSG_HASH(
MENU_ENUM_SUBLABEL_CHEEVOS_BADGES_ENABLE,
"Display badges in the Achievement List."

View File

@ -165,6 +165,7 @@ default_sublabel_macro(action_bind_sublabel_cheevos_enable, MENU_
default_sublabel_macro(action_bind_sublabel_cheevos_test_unofficial, MENU_ENUM_SUBLABEL_CHEEVOS_TEST_UNOFFICIAL)
default_sublabel_macro(action_bind_sublabel_cheevos_hardcore_mode_enable, MENU_ENUM_SUBLABEL_CHEEVOS_HARDCORE_MODE_ENABLE)
default_sublabel_macro(action_bind_sublabel_cheevos_leaderboards_enable, MENU_ENUM_SUBLABEL_CHEEVOS_LEADERBOARDS_ENABLE)
default_sublabel_macro(action_bind_sublabel_cheevos_richpresence_enable, MENU_ENUM_SUBLABEL_CHEEVOS_RICHPRESENCE_ENABLE)
default_sublabel_macro(action_bind_sublabel_cheevos_badges_enable, MENU_ENUM_SUBLABEL_CHEEVOS_BADGES_ENABLE)
default_sublabel_macro(action_bind_sublabel_cheevos_verbose_enable, MENU_ENUM_SUBLABEL_CHEEVOS_VERBOSE_ENABLE)
default_sublabel_macro(action_bind_sublabel_cheevos_auto_screenshot, MENU_ENUM_SUBLABEL_CHEEVOS_AUTO_SCREENSHOT)
@ -2632,6 +2633,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs,
case MENU_ENUM_LABEL_CHEEVOS_LEADERBOARDS_ENABLE:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_cheevos_leaderboards_enable);
break;
case MENU_ENUM_LABEL_CHEEVOS_RICHPRESENCE_ENABLE:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_cheevos_richpresence_enable);
break;
case MENU_ENUM_LABEL_CHEEVOS_BADGES_ENABLE:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_cheevos_badges_enable);
break;

View File

@ -5857,6 +5857,7 @@ unsigned menu_displaylist_build_list(file_list_t *list, enum menu_displaylist_ct
{MENU_ENUM_LABEL_CHEEVOS_PASSWORD, PARSE_ONLY_STRING, false },
{MENU_ENUM_LABEL_CHEEVOS_HARDCORE_MODE_ENABLE, PARSE_ONLY_BOOL, false },
{MENU_ENUM_LABEL_CHEEVOS_LEADERBOARDS_ENABLE, PARSE_ONLY_BOOL, false },
{MENU_ENUM_LABEL_CHEEVOS_RICHPRESENCE_ENABLE, PARSE_ONLY_BOOL, false },
{MENU_ENUM_LABEL_CHEEVOS_BADGES_ENABLE, PARSE_ONLY_BOOL, false },
{MENU_ENUM_LABEL_CHEEVOS_TEST_UNOFFICIAL, PARSE_ONLY_BOOL, false },
{MENU_ENUM_LABEL_CHEEVOS_VERBOSE_ENABLE, PARSE_ONLY_BOOL, false },

View File

@ -15414,6 +15414,22 @@ static bool setting_append_list(
SD_FLAG_NONE
);
CONFIG_BOOL(
list, list_info,
&settings->bools.cheevos_richpresence_enable,
MENU_ENUM_LABEL_CHEEVOS_RICHPRESENCE_ENABLE,
MENU_ENUM_LABEL_VALUE_CHEEVOS_RICHPRESENCE_ENABLE,
false,
MENU_ENUM_LABEL_VALUE_OFF,
MENU_ENUM_LABEL_VALUE_ON,
&group_info,
&subgroup_info,
parent_group,
general_write_handler,
general_read_handler,
SD_FLAG_NONE
);
if (string_is_equal(settings->arrays.menu_driver, "xmb") || string_is_equal(settings->arrays.menu_driver, "ozone"))
CONFIG_BOOL(
list, list_info,

View File

@ -1220,6 +1220,7 @@ enum msg_hash_enums
MENU_LABEL(ACCOUNTS_CHEEVOS_USERNAME),
MENU_LABEL(CHEEVOS_HARDCORE_MODE_ENABLE),
MENU_LABEL(CHEEVOS_LEADERBOARDS_ENABLE),
MENU_LABEL(CHEEVOS_RICHPRESENCE_ENABLE),
MENU_LABEL(CHEEVOS_BADGES_ENABLE),
MENU_LABEL(CHEEVOS_TEST_UNOFFICIAL),
MENU_LABEL(CHEEVOS_VERBOSE_ENABLE),