mirror of
https://github.com/libretro/RetroArch
synced 2025-03-28 19:20:35 +00:00
Merge pull request #10122 from Jamiras/rcheevos_rp
default rich presence on; better handling of special characters
This commit is contained in:
commit
8e59430f93
@ -27,7 +27,6 @@
|
||||
#include <retro_miscellaneous.h>
|
||||
#include <retro_math.h>
|
||||
#include <net/net_http.h>
|
||||
#include <encodings/utf.h>
|
||||
#include <libretro.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
@ -572,94 +571,31 @@ static int rcheevos_parse(const char* json)
|
||||
|
||||
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')
|
||||
int buffer_size = rc_richpresence_size(rcheevos_locals.patchdata.richpresence_script);
|
||||
if (buffer_size <= 0)
|
||||
{
|
||||
if (*script_it == '\\')
|
||||
{
|
||||
char escaped_char = *(script_it + 1);
|
||||
snprintf(buffer, sizeof(buffer), "Error in rich presence: %s", rcheevos_rc_error(buffer_size));
|
||||
|
||||
switch (escaped_char)
|
||||
{
|
||||
/* Ignore carriage return */
|
||||
case 'r':
|
||||
script_it += 2;
|
||||
break;
|
||||
if (settings->bools.cheevos_verbose_enable)
|
||||
runloop_msg_queue_push(buffer, 0, 4 * 60, false, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||
|
||||
/* 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)
|
||||
{
|
||||
CHEEVOS_ERR(RCHEEVOS_TAG "%s\n", buffer);
|
||||
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.richpresence = rc_parse_richpresence(buffer, rcheevos_locals.patchdata.richpresence_script, NULL, 0);
|
||||
rcheevos_locals.richpresence.last_update = cpu_features_get_time_usec();
|
||||
}
|
||||
|
||||
rcheevos_locals.richpresence.evaluation[0] = '\0';
|
||||
}
|
||||
|
||||
if (!rcheevos_locals.richpresence.richpresence && rcheevos_locals.patchdata.title)
|
||||
{
|
||||
snprintf(rcheevos_locals.richpresence.evaluation, sizeof(rcheevos_locals.richpresence.evaluation),
|
||||
"Playing %s", rcheevos_locals.patchdata.title);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -1055,37 +991,56 @@ const char* rcheevos_get_richpresence(void)
|
||||
|
||||
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;
|
||||
settings_t* settings = config_get_ptr();
|
||||
retro_time_t now = cpu_features_get_time_usec();
|
||||
|
||||
{
|
||||
settings_t* settings = config_get_ptr();
|
||||
char url[256], post_data[1024];
|
||||
if (settings->bools.cheevos_richpresence_enable)
|
||||
{
|
||||
/* update rich presence every two minutes */
|
||||
if (now < rcheevos_locals.richpresence.last_update + CHEEVOS_PING_FREQUENCY)
|
||||
return;
|
||||
|
||||
rcheevos_locals.richpresence.last_update = cpu_features_get_time_usec();
|
||||
if (rcheevos_locals.richpresence.richpresence)
|
||||
{
|
||||
rc_evaluate_richpresence(rcheevos_locals.richpresence.richpresence,
|
||||
rcheevos_locals.richpresence.evaluation,
|
||||
sizeof(rcheevos_locals.richpresence.evaluation), rcheevos_peek, NULL, NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* send ping every four minutes */
|
||||
if (now < rcheevos_locals.richpresence.last_update + CHEEVOS_PING_FREQUENCY * 2)
|
||||
return;
|
||||
}
|
||||
|
||||
rc_evaluate_richpresence(rcheevos_locals.richpresence.richpresence,
|
||||
rcheevos_locals.richpresence.evaluation,
|
||||
sizeof(rcheevos_locals.richpresence.evaluation), rcheevos_peek, NULL, NULL);
|
||||
rcheevos_locals.richpresence.last_update = now;
|
||||
|
||||
/* Form URL */
|
||||
snprintf(url, 256, "http://retroachievements.org/dorequest.php?r=ping&u=%s&t=%s",
|
||||
settings->arrays.cheevos_username,
|
||||
rcheevos_locals.token);
|
||||
{
|
||||
char user_agent[256], url[256], post_data[1024];
|
||||
|
||||
/* Form POST data */
|
||||
snprintf(post_data, 1024, "g=%u&m=%s",
|
||||
rcheevos_locals.patchdata.game_id,
|
||||
rcheevos_get_richpresence());
|
||||
snprintf(url, sizeof(url), "http://retroachievements.org/dorequest.php?r=ping&u=%s&t=%s",
|
||||
settings->arrays.cheevos_username, rcheevos_locals.token);
|
||||
|
||||
if (rcheevos_locals.richpresence.evaluation[0])
|
||||
{
|
||||
char* tmp = NULL;
|
||||
net_http_urlencode(&tmp, rcheevos_locals.richpresence.evaluation);
|
||||
snprintf(post_data, sizeof(post_data), "g=%u&m=%s", rcheevos_locals.patchdata.game_id, tmp);
|
||||
CHEEVOS_FREE(tmp);
|
||||
|
||||
#ifdef HAVE_DISCORD
|
||||
if (settings->bools.discord_enable)
|
||||
discord_update(DISCORD_PRESENCE_RETROACHIEVEMENTS,
|
||||
false);
|
||||
if (settings->bools.discord_enable)
|
||||
discord_update(DISCORD_PRESENCE_RETROACHIEVEMENTS, false);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(post_data, sizeof(post_data), "g=%u", rcheevos_locals.patchdata.game_id);
|
||||
}
|
||||
|
||||
task_push_http_post_transfer(url, post_data, true, "POST", NULL, NULL);
|
||||
rcheevos_get_user_agent(user_agent);
|
||||
task_push_http_post_transfer_with_user_agent(url, post_data, true, "POST", user_agent, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1370,8 +1325,7 @@ void rcheevos_test(void)
|
||||
!rcheevos_hardcore_paused)
|
||||
rcheevos_test_leaderboards();
|
||||
|
||||
if (settings->bools.cheevos_richpresence_enable)
|
||||
rcheevos_test_richpresence();
|
||||
rcheevos_test_richpresence();
|
||||
}
|
||||
}
|
||||
|
||||
@ -2525,6 +2479,10 @@ found:
|
||||
if (!path_is_directory(coro->badge_fullpath))
|
||||
path_mkdir(coro->badge_fullpath);
|
||||
CORO_YIELD();
|
||||
|
||||
if (!coro->cheevo->info->badge || !coro->cheevo->info->badge[0])
|
||||
continue;
|
||||
|
||||
if (coro->j == 0)
|
||||
snprintf(coro->badge_name,
|
||||
sizeof(coro->badge_name),
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "hash.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <encodings/utf.h>
|
||||
#include <formats/jsonsax.h>
|
||||
#include <string/stdstring.h>
|
||||
#include <compat/strl.h>
|
||||
@ -263,6 +264,7 @@ typedef struct
|
||||
int in_cheevos;
|
||||
int in_lboards;
|
||||
int is_game_id;
|
||||
int is_title;
|
||||
int is_console_id;
|
||||
int is_richpresence;
|
||||
unsigned core_count;
|
||||
@ -276,16 +278,77 @@ typedef struct
|
||||
rcheevos_rapatchdata_t* patchdata;
|
||||
} rcheevos_readud_t;
|
||||
|
||||
static const char* rcheevos_dupstr(const rcheevos_field_t* field)
|
||||
static char* rcheevos_unescape_string(const char* string, size_t length)
|
||||
{
|
||||
char* string = (char*)malloc(field->length + 1);
|
||||
const char* end = string + length;
|
||||
char* buffer = (char*)malloc(length + 1);
|
||||
char* buffer_it = buffer;
|
||||
|
||||
if (!string)
|
||||
if (buffer == NULL)
|
||||
return NULL;
|
||||
|
||||
memcpy((void*)string, (void*)field->string, field->length);
|
||||
string[field->length] = 0;
|
||||
return string;
|
||||
while (string < end)
|
||||
{
|
||||
if (*string == '\\')
|
||||
{
|
||||
char escaped_char = string[1];
|
||||
switch (escaped_char)
|
||||
{
|
||||
case 'r': /* Ignore carriage return */
|
||||
string += 2;
|
||||
break;
|
||||
|
||||
case 'n': /* Accept newlines */
|
||||
*buffer_it++ = '\n';
|
||||
string += 2;
|
||||
break;
|
||||
|
||||
case 'u': /* Accept UTF-16 unicode characters */
|
||||
{
|
||||
#define MAX_SEQUENCES 16
|
||||
uint16_t utf16[MAX_SEQUENCES];
|
||||
char utf8[MAX_SEQUENCES * 4];
|
||||
uint8_t i, j;
|
||||
|
||||
for (i = 1; i < MAX_SEQUENCES - 1; i++)
|
||||
if (strncmp((string + 6 * i), "\\u", 2))
|
||||
break;
|
||||
|
||||
/* Get escaped hex values and add them to the string */
|
||||
for (j = 0; j < i; j++)
|
||||
{
|
||||
char temp[5];
|
||||
|
||||
string += 2;
|
||||
memcpy(temp, string, 4);
|
||||
temp[4] = '\0';
|
||||
utf16[j] = string_hex_to_unsigned(temp);
|
||||
string += 4;
|
||||
}
|
||||
utf16[j] = 0;
|
||||
|
||||
if (utf16_to_char_string(utf16, utf8, sizeof(utf8)))
|
||||
{
|
||||
memcpy(buffer_it, utf8, strlen(utf8));
|
||||
buffer_it += strlen(utf8);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
*buffer_it++ = escaped_char;
|
||||
string += 2;
|
||||
break;
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
*buffer_it++ = *string++;
|
||||
}
|
||||
}
|
||||
*buffer_it = '\0';
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static int rcheevos_new_cheevo(rcheevos_readud_t* ud)
|
||||
@ -300,10 +363,10 @@ static int rcheevos_new_cheevo(rcheevos_readud_t* ud)
|
||||
else
|
||||
return 0;
|
||||
|
||||
cheevo->title = rcheevos_dupstr(&ud->title);
|
||||
cheevo->description = rcheevos_dupstr(&ud->desc);
|
||||
cheevo->badge = rcheevos_dupstr(&ud->badge);
|
||||
cheevo->memaddr = rcheevos_dupstr(&ud->memaddr);
|
||||
cheevo->title = rcheevos_unescape_string(ud->title.string, ud->title.length);
|
||||
cheevo->description = rcheevos_unescape_string(ud->desc.string, ud->desc.length);
|
||||
cheevo->badge = rcheevos_unescape_string(ud->badge.string, ud->badge.length);
|
||||
cheevo->memaddr = rcheevos_unescape_string(ud->memaddr.string, ud->memaddr.length);
|
||||
cheevo->points = (unsigned)strtol(ud->points.string, NULL, 10);
|
||||
cheevo->id = (unsigned)strtol(ud->id.string, NULL, 10);
|
||||
|
||||
@ -326,11 +389,11 @@ static int rcheevos_new_lboard(rcheevos_readud_t* ud)
|
||||
{
|
||||
rcheevos_ralboard_t* lboard = ud->patchdata->lboards + ud->lboard_count++;
|
||||
|
||||
lboard->title = rcheevos_dupstr(&ud->title);
|
||||
lboard->description = rcheevos_dupstr(&ud->desc);
|
||||
lboard->format = rcheevos_dupstr(&ud->format);
|
||||
lboard->mem = rcheevos_dupstr(&ud->memaddr);
|
||||
lboard->id = (unsigned)strtol(ud->id.string, NULL, 10);
|
||||
lboard->title = rcheevos_unescape_string(ud->title.string, ud->title.length);
|
||||
lboard->description = rcheevos_unescape_string(ud->desc.string, ud->desc.length);
|
||||
lboard->format = rcheevos_unescape_string(ud->format.string, ud->format.length);
|
||||
lboard->mem = rcheevos_unescape_string(ud->memaddr.string, ud->memaddr.length);
|
||||
lboard->id = (unsigned)strtol(ud->id.string, NULL, 10);
|
||||
|
||||
if ( !lboard->title
|
||||
|| !lboard->description
|
||||
@ -409,6 +472,8 @@ static int rcheevos_read_key(void* userdata,
|
||||
case CHEEVOS_JSON_KEY_TITLE:
|
||||
if (common)
|
||||
ud->field = &ud->title;
|
||||
else
|
||||
ud->is_title = 1;
|
||||
break;
|
||||
case CHEEVOS_JSON_KEY_DESCRIPTION:
|
||||
if (common)
|
||||
@ -459,11 +524,14 @@ static int rcheevos_read_string(void* userdata,
|
||||
ud->field->string = string;
|
||||
ud->field->length = length;
|
||||
}
|
||||
else if (ud->is_title)
|
||||
{
|
||||
ud->patchdata->title = rcheevos_unescape_string(string, length);
|
||||
ud->is_title = 0;
|
||||
}
|
||||
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->patchdata->richpresence_script = rcheevos_unescape_string(string, length);
|
||||
ud->is_richpresence = 0;
|
||||
}
|
||||
|
||||
@ -544,10 +612,14 @@ int rcheevos_get_patchdata(const char* json, rcheevos_rapatchdata_t* patchdata)
|
||||
return -1;
|
||||
}
|
||||
|
||||
patchdata->richpresence_script = NULL;
|
||||
patchdata->title = NULL;
|
||||
|
||||
/* Load the achievements. */
|
||||
ud.in_cheevos = 0;
|
||||
ud.in_lboards = 0;
|
||||
ud.is_game_id = 0;
|
||||
ud.is_title = 0;
|
||||
ud.is_console_id = 0;
|
||||
ud.is_richpresence = 0;
|
||||
ud.field = NULL;
|
||||
@ -609,6 +681,7 @@ void rcheevos_free_patchdata(rcheevos_rapatchdata_t* patchdata)
|
||||
CHEEVOS_FREE(patchdata->unofficial);
|
||||
CHEEVOS_FREE(patchdata->lboards);
|
||||
CHEEVOS_FREE(patchdata->richpresence_script);
|
||||
CHEEVOS_FREE(patchdata->title);
|
||||
|
||||
patchdata->game_id = 0;
|
||||
patchdata->console_id = 0;
|
||||
|
@ -44,6 +44,7 @@ typedef struct {
|
||||
typedef struct {
|
||||
unsigned game_id;
|
||||
unsigned console_id;
|
||||
char* title;
|
||||
|
||||
rcheevos_racheevo_t* core;
|
||||
rcheevos_racheevo_t* unofficial;
|
||||
|
@ -1583,7 +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_richpresence_enable", &settings->bools.cheevos_richpresence_enable, true, true, 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
|
||||
|
@ -15456,7 +15456,7 @@ static bool setting_append_list(
|
||||
&settings->bools.cheevos_richpresence_enable,
|
||||
MENU_ENUM_LABEL_CHEEVOS_RICHPRESENCE_ENABLE,
|
||||
MENU_ENUM_LABEL_VALUE_CHEEVOS_RICHPRESENCE_ENABLE,
|
||||
false,
|
||||
true,
|
||||
MENU_ENUM_LABEL_VALUE_OFF,
|
||||
MENU_ENUM_LABEL_VALUE_ON,
|
||||
&group_info,
|
||||
|
@ -393,6 +393,27 @@ void* task_push_http_post_transfer(const char *url,
|
||||
url, mute, type, cb, user_data);
|
||||
}
|
||||
|
||||
void* task_push_http_post_transfer_with_user_agent(const char *url,
|
||||
const char *post_data, bool mute,
|
||||
const char *type, const char* user_agent,
|
||||
retro_task_callback_t cb, void *user_data)
|
||||
{
|
||||
struct http_connection_t* conn;
|
||||
|
||||
if (string_is_empty(url))
|
||||
return NULL;
|
||||
|
||||
conn = net_http_connection_new(url, "POST", post_data);
|
||||
if (!conn)
|
||||
return NULL;
|
||||
|
||||
if (user_agent != NULL)
|
||||
net_http_connection_set_user_agent(conn, user_agent);
|
||||
|
||||
/* assert: task_push_http_transfer_generic will free conn on failure */
|
||||
return task_push_http_transfer_generic(conn, url, mute, type, cb, user_data);
|
||||
}
|
||||
|
||||
task_retriever_info_t *http_task_get_transfer_list(void)
|
||||
{
|
||||
task_retriever_data_t retrieve_data;
|
||||
|
@ -76,6 +76,9 @@ void *task_push_http_transfer_with_user_agent(const char *url, bool mute, const
|
||||
void *task_push_http_post_transfer(const char *url, const char *post_data, bool mute, const char *type,
|
||||
retro_task_callback_t cb, void *userdata);
|
||||
|
||||
void *task_push_http_post_transfer_with_user_agent(const char* url, const char* post_data, bool mute,
|
||||
const char* type, const char* user_agent, retro_task_callback_t cb, void* user_data);
|
||||
|
||||
task_retriever_info_t *http_task_get_transfer_list(void);
|
||||
|
||||
bool task_push_wifi_scan(retro_task_callback_t cb);
|
||||
|
Loading…
x
Reference in New Issue
Block a user