mirror of
https://github.com/libretro/RetroArch
synced 2025-04-17 02:43:03 +00:00
(Cheevos) Style nits:
* single line code blocks - remove brackets * Try to fit lines into 80 chars * Etc
This commit is contained in:
parent
b9df71b9d5
commit
05ca465aab
@ -119,25 +119,29 @@ void rcheevos_log(const char *fmt, ...)
|
||||
#endif
|
||||
|
||||
|
||||
static void rcheevos_achievement_disabled(rcheevos_racheevo_t* cheevo, unsigned address)
|
||||
static void rcheevos_achievement_disabled(
|
||||
rcheevos_racheevo_t* cheevo, unsigned address)
|
||||
{
|
||||
if (!cheevo)
|
||||
return;
|
||||
|
||||
CHEEVOS_ERR(RCHEEVOS_TAG "Achievement %u disabled (invalid address %06X): %s\n",
|
||||
cheevo->id, address, cheevo->title);
|
||||
CHEEVOS_ERR(RCHEEVOS_TAG
|
||||
"Achievement %u disabled (invalid address %06X): %s\n",
|
||||
cheevo->id, address, cheevo->title);
|
||||
CHEEVOS_FREE(cheevo->memaddr);
|
||||
cheevo->memaddr = NULL;
|
||||
cheevo->active |= RCHEEVOS_ACTIVE_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static void rcheevos_lboard_disabled(rcheevos_ralboard_t* lboard, unsigned address)
|
||||
static void rcheevos_lboard_disabled(
|
||||
rcheevos_ralboard_t* lboard, unsigned address)
|
||||
{
|
||||
if (!lboard)
|
||||
return;
|
||||
|
||||
CHEEVOS_ERR(RCHEEVOS_TAG "Leaderboard %u disabled (invalid address %06X): %s\n",
|
||||
lboard->id, address, lboard->title);
|
||||
CHEEVOS_ERR(RCHEEVOS_TAG
|
||||
"Leaderboard %u disabled (invalid address %06X): %s\n",
|
||||
lboard->id, address, lboard->title);
|
||||
CHEEVOS_FREE(lboard->mem);
|
||||
lboard->mem = NULL;
|
||||
}
|
||||
@ -147,7 +151,8 @@ static void rcheevos_handle_log_message(const char* message)
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "%s\n", message);
|
||||
}
|
||||
|
||||
static void rcheevos_get_core_memory_info(unsigned id, rc_libretro_core_memory_info_t* info)
|
||||
static void rcheevos_get_core_memory_info(unsigned id,
|
||||
rc_libretro_core_memory_info_t* info)
|
||||
{
|
||||
retro_ctx_memory_info_t ctx_info;
|
||||
if (!info)
|
||||
@ -180,9 +185,11 @@ static int rcheevos_init_memory(rcheevos_locals_t* locals)
|
||||
mmap.descriptors = &descriptors[0];
|
||||
mmap.num_descriptors = mmaps->num_descriptors;
|
||||
|
||||
/* RetroArch wraps the retro_memory_descriptor's in rarch_memory_descriptor_t's, pull them back out */
|
||||
/* RetroArch wraps the retro_memory_descriptor's
|
||||
* in rarch_memory_descriptor_t's, pull them back out */
|
||||
for (i = 0; i < mmap.num_descriptors; ++i)
|
||||
memcpy(&descriptors[i], &mmaps->descriptors[i].core, sizeof(descriptors[0]));
|
||||
memcpy(&descriptors[i], &mmaps->descriptors[i].core,
|
||||
sizeof(descriptors[0]));
|
||||
|
||||
rc_libretro_init_verbose_message_callback(rcheevos_handle_log_message);
|
||||
result = rc_libretro_memory_init(&locals->memory, &mmap,
|
||||
@ -194,18 +201,19 @@ static int rcheevos_init_memory(rcheevos_locals_t* locals)
|
||||
|
||||
uint8_t* rcheevos_patch_address(unsigned address)
|
||||
{
|
||||
/* Memory map was not previously initialized
|
||||
* (no achievements for this game?), try now */
|
||||
if (rcheevos_locals.memory.count == 0)
|
||||
{
|
||||
/* memory map was not previously initialized (no achievements for this game?) try now */
|
||||
rcheevos_init_memory(&rcheevos_locals);
|
||||
}
|
||||
|
||||
return rc_libretro_memory_find(&rcheevos_locals.memory, address);
|
||||
}
|
||||
|
||||
static unsigned rcheevos_peek(unsigned address, unsigned num_bytes, void* ud)
|
||||
static unsigned rcheevos_peek(unsigned address,
|
||||
unsigned num_bytes, void* ud)
|
||||
{
|
||||
uint8_t* data = rc_libretro_memory_find(&rcheevos_locals.memory, address);
|
||||
uint8_t* data = rc_libretro_memory_find(
|
||||
&rcheevos_locals.memory, address);
|
||||
|
||||
if (data)
|
||||
{
|
||||
switch (num_bytes)
|
||||
@ -227,12 +235,13 @@ static unsigned rcheevos_peek(unsigned address, unsigned num_bytes, void* ud)
|
||||
|
||||
static void rcheevos_activate_achievements(void)
|
||||
{
|
||||
unsigned i;
|
||||
int result;
|
||||
rcheevos_racheevo_t* achievement = rcheevos_locals.game.achievements;
|
||||
settings_t* settings = config_get_ptr();
|
||||
int result;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < rcheevos_locals.game.achievement_count; i++, achievement++)
|
||||
for (i = 0; i < rcheevos_locals.game.achievement_count;
|
||||
i++, achievement++)
|
||||
{
|
||||
if ((achievement->active & (RCHEEVOS_ACTIVE_HARDCORE | RCHEEVOS_ACTIVE_SOFTCORE)) != 0)
|
||||
{
|
||||
@ -265,7 +274,8 @@ static void rcheevos_activate_achievements(void)
|
||||
static rcheevos_racheevo_t* rcheevos_find_cheevo(unsigned id)
|
||||
{
|
||||
rcheevos_racheevo_t* cheevo = rcheevos_locals.game.achievements;
|
||||
rcheevos_racheevo_t* stop = cheevo + rcheevos_locals.game.achievement_count;
|
||||
rcheevos_racheevo_t* stop = cheevo
|
||||
+ rcheevos_locals.game.achievement_count;
|
||||
|
||||
for(; cheevo < stop; ++cheevo)
|
||||
{
|
||||
@ -299,9 +309,7 @@ void rcheevos_award_achievement(rcheevos_locals_t* locals,
|
||||
/* Show the on screen message. */
|
||||
#if defined(HAVE_GFX_WIDGETS)
|
||||
if (widgets_ready)
|
||||
{
|
||||
gfx_widgets_push_achievement(cheevo->title, cheevo->badge);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
@ -314,19 +322,20 @@ void rcheevos_award_achievement(rcheevos_locals_t* locals,
|
||||
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||
}
|
||||
|
||||
/* Start the award task (unofficial achievement unlocks are not submitted). */
|
||||
/* Start the award task (unofficial achievement
|
||||
* unlocks are not submitted). */
|
||||
if (!(cheevo->active & RCHEEVOS_ACTIVE_UNOFFICIAL))
|
||||
rcheevos_client_award_achievement(cheevo->id);
|
||||
|
||||
/* play the unlock sound */
|
||||
#ifdef HAVE_AUDIOMIXER
|
||||
/* Play the unlock sound */
|
||||
if (settings->bools.cheevos_unlock_sound_enable)
|
||||
audio_driver_mixer_play_menu_sound(
|
||||
AUDIO_MIXER_SYSTEM_SLOT_ACHIEVEMENT_UNLOCK);
|
||||
#endif
|
||||
|
||||
/* Take a screenshot of the achievement. */
|
||||
#ifdef HAVE_SCREENSHOTS
|
||||
/* Take a screenshot of the achievement. */
|
||||
if (settings->bools.cheevos_auto_screenshot)
|
||||
{
|
||||
size_t shotname_len = sizeof(char) * 8192;
|
||||
@ -344,10 +353,12 @@ void rcheevos_award_achievement(rcheevos_locals_t* locals,
|
||||
shotname, true,
|
||||
video_driver_cached_frame_has_valid_framebuffer(),
|
||||
false, true))
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "Captured screenshot for achievement %u\n",
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG
|
||||
"Captured screenshot for achievement %u\n",
|
||||
cheevo->id);
|
||||
else
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "Failed to capture screenshot for achievement %u\n",
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG
|
||||
"Failed to capture screenshot for achievement %u\n",
|
||||
cheevo->id);
|
||||
|
||||
free(shotname);
|
||||
@ -359,7 +370,8 @@ void rcheevos_award_achievement(rcheevos_locals_t* locals,
|
||||
static rcheevos_ralboard_t* rcheevos_find_lboard(unsigned id)
|
||||
{
|
||||
rcheevos_ralboard_t* lboard = rcheevos_locals.game.leaderboards;
|
||||
rcheevos_ralboard_t* stop = lboard + rcheevos_locals.game.leaderboard_count;
|
||||
rcheevos_ralboard_t* stop = lboard
|
||||
+ rcheevos_locals.game.leaderboard_count;
|
||||
|
||||
for (; lboard < stop; ++lboard)
|
||||
{
|
||||
@ -376,7 +388,8 @@ static void rcheevos_lboard_submit(rcheevos_locals_t* locals,
|
||||
char buffer[256];
|
||||
char formatted_value[16];
|
||||
|
||||
rc_runtime_format_lboard_value(formatted_value, sizeof(formatted_value),
|
||||
rc_runtime_format_lboard_value(formatted_value,
|
||||
sizeof(formatted_value),
|
||||
value, lboard->format);
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "Submitting %s for leaderboard %u\n",
|
||||
formatted_value, lboard->id);
|
||||
@ -417,11 +430,12 @@ static void rcheevos_lboard_canceled(rcheevos_ralboard_t * lboard,
|
||||
snprintf(buffer, sizeof(buffer),
|
||||
"Leaderboard attempt failed: %s", lboard->title);
|
||||
runloop_msg_queue_push(buffer, 0, 2 * 60, false, NULL,
|
||||
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||
}
|
||||
}
|
||||
|
||||
static void rcheevos_lboard_started(rcheevos_ralboard_t * lboard, int value,
|
||||
static void rcheevos_lboard_started(
|
||||
rcheevos_ralboard_t * lboard, int value,
|
||||
bool widgets_ready)
|
||||
{
|
||||
char buffer[256];
|
||||
@ -434,7 +448,8 @@ static void rcheevos_lboard_started(rcheevos_ralboard_t * lboard, int value,
|
||||
#if defined(HAVE_GFX_WIDGETS)
|
||||
if (widgets_ready && rcheevos_locals.leaderboard_trackers)
|
||||
{
|
||||
rc_runtime_format_lboard_value(buffer, sizeof(buffer), value, lboard->format);
|
||||
rc_runtime_format_lboard_value(buffer,
|
||||
sizeof(buffer), value, lboard->format);
|
||||
gfx_widgets_set_leaderboard_display(lboard->id, buffer);
|
||||
}
|
||||
#endif
|
||||
@ -451,13 +466,13 @@ static void rcheevos_lboard_started(rcheevos_ralboard_t * lboard, int value,
|
||||
lboard->title);
|
||||
|
||||
runloop_msg_queue_push(buffer, 0, 2 * 60, false, NULL,
|
||||
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(HAVE_GFX_WIDGETS)
|
||||
|
||||
static void rcheevos_lboard_updated(rcheevos_ralboard_t* lboard, int value,
|
||||
static void rcheevos_lboard_updated(
|
||||
rcheevos_ralboard_t* lboard, int value,
|
||||
bool widgets_ready)
|
||||
{
|
||||
if (!lboard)
|
||||
@ -466,20 +481,25 @@ static void rcheevos_lboard_updated(rcheevos_ralboard_t* lboard, int value,
|
||||
if (widgets_ready && rcheevos_locals.leaderboard_trackers)
|
||||
{
|
||||
char buffer[32];
|
||||
rc_runtime_format_lboard_value(buffer, sizeof(buffer), value, lboard->format);
|
||||
rc_runtime_format_lboard_value(buffer,
|
||||
sizeof(buffer), value, lboard->format);
|
||||
gfx_widgets_set_leaderboard_display(lboard->id, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
static void rcheevos_challenge_started(rcheevos_racheevo_t* cheevo, int value,
|
||||
static void rcheevos_challenge_started(
|
||||
rcheevos_racheevo_t* cheevo, int value,
|
||||
bool widgets_ready)
|
||||
{
|
||||
settings_t* settings = config_get_ptr();
|
||||
if (cheevo && widgets_ready && settings->bools.cheevos_challenge_indicators)
|
||||
if ( cheevo
|
||||
&& widgets_ready
|
||||
&& settings->bools.cheevos_challenge_indicators)
|
||||
gfx_widgets_set_challenge_display(cheevo->id, cheevo->badge);
|
||||
}
|
||||
|
||||
static void rcheevos_challenge_ended(rcheevos_racheevo_t* cheevo, int value,
|
||||
static void rcheevos_challenge_ended(
|
||||
rcheevos_racheevo_t* cheevo, int value,
|
||||
bool widgets_ready)
|
||||
{
|
||||
if (cheevo && widgets_ready)
|
||||
@ -490,11 +510,12 @@ static void rcheevos_challenge_ended(rcheevos_racheevo_t* cheevo, int value,
|
||||
|
||||
int rcheevos_get_richpresence(char buffer[], int buffer_size)
|
||||
{
|
||||
int ret = rc_runtime_get_richpresence(&rcheevos_locals.runtime, buffer, buffer_size, &rcheevos_peek, NULL, NULL);
|
||||
int ret = rc_runtime_get_richpresence(
|
||||
&rcheevos_locals.runtime, buffer, buffer_size,
|
||||
&rcheevos_peek, NULL, NULL);
|
||||
|
||||
if (ret <= 0 && rcheevos_locals.game.title)
|
||||
ret = snprintf(buffer, buffer_size, "Playing %s", rcheevos_locals.game.title);
|
||||
|
||||
return snprintf(buffer, buffer_size, "Playing %s", rcheevos_locals.game.title);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -504,16 +525,15 @@ void rcheevos_reset_game(bool widgets_ready)
|
||||
/* Hide any visible trackers */
|
||||
if (widgets_ready)
|
||||
{
|
||||
rcheevos_ralboard_t* lboard;
|
||||
rcheevos_racheevo_t* cheevo;
|
||||
unsigned i;
|
||||
|
||||
lboard = rcheevos_locals.game.leaderboards;
|
||||
for (i = 0; i < rcheevos_locals.game.leaderboard_count; ++i, ++lboard)
|
||||
rcheevos_racheevo_t* cheevo;
|
||||
rcheevos_ralboard_t* lboard = rcheevos_locals.game.leaderboards;
|
||||
for (i = 0; i < rcheevos_locals.game.leaderboard_count;
|
||||
++i, ++lboard)
|
||||
gfx_widgets_set_leaderboard_display(lboard->id, NULL);
|
||||
|
||||
cheevo = rcheevos_locals.game.achievements;
|
||||
for (i = 0; i < rcheevos_locals.game.achievement_count; ++i, ++cheevo)
|
||||
for (i = 0; i < rcheevos_locals.game.achievement_count;
|
||||
++i, ++cheevo)
|
||||
gfx_widgets_set_challenge_display(cheevo->id, NULL);
|
||||
}
|
||||
#endif
|
||||
@ -541,8 +561,7 @@ void rcheevos_pause_hardcore(void)
|
||||
static bool rcheevos_timer_check(void* userdata)
|
||||
{
|
||||
retro_time_t stop_time = *(retro_time_t*)userdata;
|
||||
retro_time_t now = cpu_features_get_time_usec();
|
||||
|
||||
retro_time_t now = cpu_features_get_time_usec();
|
||||
return (now < stop_time);
|
||||
}
|
||||
#endif
|
||||
@ -561,8 +580,10 @@ bool rcheevos_unload(void)
|
||||
rcheevos_locals.load_info.state = RCHEEVOS_LOAD_STATE_ABORTED;
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "Asked the load tasks to terminate\n");
|
||||
|
||||
task_queue_wait(rcheevos_timer_check, &stop_time); /* wait for pending tasks to run */
|
||||
task_queue_check(); /* clean up after completed tasks */
|
||||
/* Wait for pending tasks to run */
|
||||
task_queue_wait(rcheevos_timer_check, &stop_time);
|
||||
/* Clean up after completed tasks */
|
||||
task_queue_check();
|
||||
}
|
||||
|
||||
rcheevos_locals.queued_command = CMD_EVENT_NONE;
|
||||
@ -579,15 +600,16 @@ bool rcheevos_unload(void)
|
||||
if (rcheevos_locals.menuitems)
|
||||
{
|
||||
CHEEVOS_FREE(rcheevos_locals.menuitems);
|
||||
rcheevos_locals.menuitems = NULL;
|
||||
rcheevos_locals.menuitem_capacity = rcheevos_locals.menuitem_count = 0;
|
||||
rcheevos_locals.menuitems = NULL;
|
||||
rcheevos_locals.menuitem_capacity =
|
||||
rcheevos_locals.menuitem_count = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (rcheevos_locals.game.title)
|
||||
{
|
||||
CHEEVOS_FREE(rcheevos_locals.game.title);
|
||||
rcheevos_locals.game.title = NULL;
|
||||
rcheevos_locals.game.title = NULL;
|
||||
}
|
||||
|
||||
rcheevos_locals.loaded = false;
|
||||
@ -609,12 +631,13 @@ bool rcheevos_unload(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void rcheevos_toggle_hardcore_achievements(rcheevos_locals_t *locals)
|
||||
static void rcheevos_toggle_hardcore_achievements(
|
||||
rcheevos_locals_t *locals)
|
||||
{
|
||||
const unsigned active_mask =
|
||||
const unsigned active_mask =
|
||||
RCHEEVOS_ACTIVE_SOFTCORE | RCHEEVOS_ACTIVE_HARDCORE | RCHEEVOS_ACTIVE_UNSUPPORTED;
|
||||
rcheevos_racheevo_t* cheevo = locals->game.achievements;
|
||||
rcheevos_racheevo_t* stop = cheevo + locals->game.achievement_count;
|
||||
rcheevos_racheevo_t* stop = cheevo + locals->game.achievement_count;
|
||||
|
||||
while (cheevo < stop)
|
||||
{
|
||||
@ -640,17 +663,20 @@ static void rcheevos_toggle_hardcore_achievements(rcheevos_locals_t *locals)
|
||||
|
||||
static void rcheevos_activate_leaderboards(void)
|
||||
{
|
||||
rcheevos_ralboard_t* leaderboard = rcheevos_locals.game.leaderboards;
|
||||
const settings_t* settings = config_get_ptr();
|
||||
unsigned i;
|
||||
int result;
|
||||
rcheevos_ralboard_t* leaderboard = rcheevos_locals.game.leaderboards;
|
||||
const settings_t *settings = config_get_ptr();
|
||||
|
||||
for (i = 0; i < rcheevos_locals.game.leaderboard_count; ++i, ++leaderboard)
|
||||
for (i = 0; i < rcheevos_locals.game.leaderboard_count;
|
||||
++i, ++leaderboard)
|
||||
{
|
||||
if (!leaderboard->mem)
|
||||
continue;
|
||||
|
||||
result = rc_runtime_activate_lboard(&rcheevos_locals.runtime, leaderboard->id, leaderboard->mem, NULL, 0);
|
||||
result = rc_runtime_activate_lboard(
|
||||
&rcheevos_locals.runtime, leaderboard->id,
|
||||
leaderboard->mem, NULL, 0);
|
||||
if (result != RC_OK)
|
||||
{
|
||||
char buffer[256];
|
||||
@ -673,13 +699,15 @@ static void rcheevos_activate_leaderboards(void)
|
||||
static void rcheevos_deactivate_leaderboards()
|
||||
{
|
||||
rcheevos_ralboard_t* lboard = rcheevos_locals.game.leaderboards;
|
||||
rcheevos_ralboard_t* stop = lboard + rcheevos_locals.game.leaderboard_count;
|
||||
rcheevos_ralboard_t* stop = lboard +
|
||||
rcheevos_locals.game.leaderboard_count;
|
||||
|
||||
for (; lboard < stop; ++lboard)
|
||||
{
|
||||
if (lboard->mem)
|
||||
{
|
||||
rc_runtime_deactivate_lboard(&rcheevos_locals.runtime, lboard->id);
|
||||
rc_runtime_deactivate_lboard(&rcheevos_locals.runtime,
|
||||
lboard->id);
|
||||
|
||||
#if defined(HAVE_GFX_WIDGETS)
|
||||
/* Hide any visible trackers */
|
||||
@ -774,7 +802,8 @@ static void rcheevos_toggle_hardcore_active(rcheevos_locals_t* locals)
|
||||
|
||||
if (locals->loaded)
|
||||
{
|
||||
const char* msg = msg_hash_to_str(MSG_CHEEVOS_HARDCORE_MODE_ENABLE);
|
||||
const char* msg = msg_hash_to_str(
|
||||
MSG_CHEEVOS_HARDCORE_MODE_ENABLE);
|
||||
CHEEVOS_LOG("%s\n", msg);
|
||||
runloop_msg_queue_push(msg, 0, 3 * 60, true, NULL,
|
||||
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||
@ -867,7 +896,8 @@ void rcheevos_validate_config_settings(void)
|
||||
if (!system->library_name || !rcheevos_locals.hardcore_active)
|
||||
return;
|
||||
|
||||
if (!(disallowed_settings = rc_libretro_get_disallowed_settings(system->library_name)))
|
||||
if (!(disallowed_settings
|
||||
= rc_libretro_get_disallowed_settings(system->library_name)))
|
||||
return;
|
||||
|
||||
if (!retroarch_ctl(RARCH_CTL_CORE_OPTIONS_LIST_GET, &coreopts))
|
||||
@ -880,7 +910,8 @@ void rcheevos_validate_config_settings(void)
|
||||
if (!rc_libretro_is_setting_allowed(disallowed_settings, key, val))
|
||||
{
|
||||
char buffer[256];
|
||||
snprintf(buffer, sizeof(buffer), "Hardcore paused. Setting not allowed: %s=%s", key, val);
|
||||
snprintf(buffer, sizeof(buffer),
|
||||
"Hardcore paused. Setting not allowed: %s=%s", key, val);
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "%s\n", buffer);
|
||||
rcheevos_pause_hardcore();
|
||||
|
||||
@ -892,7 +923,8 @@ void rcheevos_validate_config_settings(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void rcheevos_runtime_event_handler(const rc_runtime_event_t* runtime_event)
|
||||
static void rcheevos_runtime_event_handler(
|
||||
const rc_runtime_event_t* runtime_event)
|
||||
{
|
||||
#if defined(HAVE_GFX_WIDGETS)
|
||||
bool widgets_ready = gfx_widgets_ready();
|
||||
@ -904,41 +936,59 @@ static void rcheevos_runtime_event_handler(const rc_runtime_event_t* runtime_eve
|
||||
{
|
||||
#if defined(HAVE_GFX_WIDGETS)
|
||||
case RC_RUNTIME_EVENT_LBOARD_UPDATED:
|
||||
rcheevos_lboard_updated(rcheevos_find_lboard(runtime_event->id), runtime_event->value, widgets_ready);
|
||||
rcheevos_lboard_updated(
|
||||
rcheevos_find_lboard(runtime_event->id),
|
||||
runtime_event->value, widgets_ready);
|
||||
break;
|
||||
|
||||
case RC_RUNTIME_EVENT_ACHIEVEMENT_PRIMED:
|
||||
rcheevos_challenge_started(rcheevos_find_cheevo(runtime_event->id), runtime_event->value, widgets_ready);
|
||||
rcheevos_challenge_started(
|
||||
rcheevos_find_cheevo(runtime_event->id),
|
||||
runtime_event->value, widgets_ready);
|
||||
break;
|
||||
|
||||
case RC_RUNTIME_EVENT_ACHIEVEMENT_UNPRIMED:
|
||||
rcheevos_challenge_ended(rcheevos_find_cheevo(runtime_event->id), runtime_event->value, widgets_ready);
|
||||
rcheevos_challenge_ended(
|
||||
rcheevos_find_cheevo(runtime_event->id),
|
||||
runtime_event->value, widgets_ready);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case RC_RUNTIME_EVENT_ACHIEVEMENT_TRIGGERED:
|
||||
rcheevos_award_achievement(&rcheevos_locals, rcheevos_find_cheevo(runtime_event->id), widgets_ready);
|
||||
rcheevos_award_achievement(
|
||||
&rcheevos_locals,
|
||||
rcheevos_find_cheevo(runtime_event->id), widgets_ready);
|
||||
break;
|
||||
|
||||
case RC_RUNTIME_EVENT_LBOARD_STARTED:
|
||||
rcheevos_lboard_started(rcheevos_find_lboard(runtime_event->id), runtime_event->value, widgets_ready);
|
||||
rcheevos_lboard_started(
|
||||
rcheevos_find_lboard(runtime_event->id),
|
||||
runtime_event->value, widgets_ready);
|
||||
break;
|
||||
|
||||
case RC_RUNTIME_EVENT_LBOARD_CANCELED:
|
||||
rcheevos_lboard_canceled(rcheevos_find_lboard(runtime_event->id),
|
||||
rcheevos_lboard_canceled(
|
||||
rcheevos_find_lboard(runtime_event->id),
|
||||
widgets_ready);
|
||||
break;
|
||||
|
||||
case RC_RUNTIME_EVENT_LBOARD_TRIGGERED:
|
||||
rcheevos_lboard_submit(&rcheevos_locals, rcheevos_find_lboard(runtime_event->id), runtime_event->value, widgets_ready);
|
||||
rcheevos_lboard_submit(
|
||||
&rcheevos_locals,
|
||||
rcheevos_find_lboard(runtime_event->id),
|
||||
runtime_event->value, widgets_ready);
|
||||
break;
|
||||
|
||||
case RC_RUNTIME_EVENT_ACHIEVEMENT_DISABLED:
|
||||
rcheevos_achievement_disabled(rcheevos_find_cheevo(runtime_event->id), runtime_event->value);
|
||||
rcheevos_achievement_disabled(
|
||||
rcheevos_find_cheevo(runtime_event->id),
|
||||
runtime_event->value);
|
||||
break;
|
||||
|
||||
case RC_RUNTIME_EVENT_LBOARD_DISABLED:
|
||||
rcheevos_lboard_disabled(rcheevos_find_lboard(runtime_event->id), runtime_event->value);
|
||||
rcheevos_lboard_disabled(
|
||||
rcheevos_find_lboard(runtime_event->id),
|
||||
runtime_event->value);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -948,7 +998,8 @@ static void rcheevos_runtime_event_handler(const rc_runtime_event_t* runtime_eve
|
||||
|
||||
static int rcheevos_runtime_address_validator(unsigned address)
|
||||
{
|
||||
return (rc_libretro_memory_find(&rcheevos_locals.memory, address) != NULL);
|
||||
return rc_libretro_memory_find(
|
||||
&rcheevos_locals.memory, address) != NULL;
|
||||
}
|
||||
|
||||
static void rcheevos_validate_memrefs(rcheevos_locals_t* locals)
|
||||
@ -959,11 +1010,13 @@ static void rcheevos_validate_memrefs(rcheevos_locals_t* locals)
|
||||
* first call to retro_run. in that case, there will be a total_size
|
||||
* of memory reported by the core, but init will return false, as
|
||||
* all of the pointers were null. if we're still loading the game,
|
||||
* just reset the memory count and we'll re-evaluate in rcheevos_test()
|
||||
* just reset the memory count and we'll re-evaluate in
|
||||
* rcheevos_test()
|
||||
*/
|
||||
if (!locals->loaded)
|
||||
{
|
||||
/* if no memory was exposed, report the error now instead of waiting */
|
||||
/* If no memory was exposed, report the error now
|
||||
* instead of waiting */
|
||||
if (locals->memory.total_size != 0)
|
||||
{
|
||||
locals->memory.count = 0;
|
||||
@ -977,10 +1030,9 @@ static void rcheevos_validate_memrefs(rcheevos_locals_t* locals)
|
||||
CHEEVOS_ERR(RCHEEVOS_TAG "No memory exposed by core\n");
|
||||
|
||||
if (settings && settings->bools.cheevos_verbose_enable)
|
||||
{
|
||||
runloop_msg_queue_push(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CANNOT_ACTIVATE_ACHIEVEMENTS_WITH_THIS_CORE),
|
||||
0, 4 * 60, false, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_WARNING);
|
||||
}
|
||||
0, 4 * 60, false, NULL,
|
||||
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_WARNING);
|
||||
|
||||
rcheevos_unload();
|
||||
rcheevos_pause_hardcore();
|
||||
@ -988,7 +1040,8 @@ static void rcheevos_validate_memrefs(rcheevos_locals_t* locals)
|
||||
}
|
||||
|
||||
rc_runtime_validate_addresses(&locals->runtime,
|
||||
rcheevos_runtime_event_handler, rcheevos_runtime_address_validator);
|
||||
rcheevos_runtime_event_handler,
|
||||
rcheevos_runtime_address_validator);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
@ -1007,13 +1060,12 @@ void rcheevos_test(void)
|
||||
if (!rcheevos_locals.loaded)
|
||||
return;
|
||||
|
||||
/* We were unable to initialize memory earlier, try now */
|
||||
if (rcheevos_locals.memory.count == 0)
|
||||
{
|
||||
/* we were unable to initialize memory earlier, try now */
|
||||
rcheevos_validate_memrefs(&rcheevos_locals);
|
||||
}
|
||||
|
||||
rc_runtime_do_frame(&rcheevos_locals.runtime, &rcheevos_runtime_event_handler, rcheevos_peek, NULL, 0);
|
||||
rc_runtime_do_frame(&rcheevos_locals.runtime,
|
||||
&rcheevos_runtime_event_handler, rcheevos_peek, NULL, 0);
|
||||
}
|
||||
|
||||
size_t rcheevos_get_serialize_size(void)
|
||||
@ -1027,14 +1079,17 @@ bool rcheevos_get_serialized_data(void* buffer)
|
||||
{
|
||||
if (!rcheevos_locals.loaded)
|
||||
return false;
|
||||
return (rc_runtime_serialize_progress(buffer, &rcheevos_locals.runtime, NULL) == RC_OK);
|
||||
return (rc_runtime_serialize_progress(
|
||||
buffer, &rcheevos_locals.runtime, NULL) == RC_OK);
|
||||
}
|
||||
|
||||
bool rcheevos_set_serialized_data(void* buffer)
|
||||
{
|
||||
if (rcheevos_locals.loaded)
|
||||
{
|
||||
if (buffer && rc_runtime_deserialize_progress(&rcheevos_locals.runtime, (const unsigned char*)buffer, NULL) == RC_OK)
|
||||
if (buffer && rc_runtime_deserialize_progress(
|
||||
&rcheevos_locals.runtime,
|
||||
(const unsigned char*)buffer, NULL) == RC_OK)
|
||||
return true;
|
||||
|
||||
rc_runtime_reset(&rcheevos_locals.runtime);
|
||||
@ -1062,10 +1117,12 @@ const char* rcheevos_get_hash(void)
|
||||
|
||||
static void* rc_hash_handle_file_open(const char* path)
|
||||
{
|
||||
return intfstream_open_file(path, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE);
|
||||
return intfstream_open_file(path,
|
||||
RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE);
|
||||
}
|
||||
|
||||
static void rc_hash_handle_file_seek(void* file_handle, int64_t offset, int origin)
|
||||
static void rc_hash_handle_file_seek(
|
||||
void* file_handle, int64_t offset, int origin)
|
||||
{
|
||||
intfstream_seek((intfstream_t*)file_handle, offset, origin);
|
||||
}
|
||||
@ -1075,9 +1132,11 @@ static int64_t rc_hash_handle_file_tell(void* file_handle)
|
||||
return intfstream_tell((intfstream_t*)file_handle);
|
||||
}
|
||||
|
||||
static size_t rc_hash_handle_file_read(void* file_handle, void* buffer, size_t requested_bytes)
|
||||
static size_t rc_hash_handle_file_read(
|
||||
void* file_handle, void* buffer, size_t requested_bytes)
|
||||
{
|
||||
return intfstream_read((intfstream_t*)file_handle, buffer, requested_bytes);
|
||||
return intfstream_read((intfstream_t*)file_handle,
|
||||
buffer, requested_bytes);
|
||||
}
|
||||
|
||||
static void rc_hash_handle_file_close(void* file_handle)
|
||||
@ -1086,7 +1145,8 @@ static void rc_hash_handle_file_close(void* file_handle)
|
||||
CHEEVOS_FREE(file_handle);
|
||||
}
|
||||
|
||||
static void* rc_hash_handle_cd_open_track(const char* path, uint32_t track)
|
||||
static void* rc_hash_handle_cd_open_track(
|
||||
const char* path, uint32_t track)
|
||||
{
|
||||
cdfs_track_t* cdfs_track;
|
||||
|
||||
@ -1138,7 +1198,9 @@ static void* rc_hash_handle_cd_open_track(const char* path, uint32_t track)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static size_t rc_hash_handle_cd_read_sector(void* track_handle, uint32_t sector, void* buffer, size_t requested_bytes)
|
||||
static size_t rc_hash_handle_cd_read_sector(
|
||||
void* track_handle, uint32_t sector,
|
||||
void* buffer, size_t requested_bytes)
|
||||
{
|
||||
cdfs_file_t* file = (cdfs_file_t*)track_handle;
|
||||
|
||||
@ -1161,14 +1223,15 @@ static void rc_hash_handle_cd_close_track(void* track_handle)
|
||||
|
||||
static void rcheevos_show_game_placard()
|
||||
{
|
||||
const settings_t* settings = config_get_ptr();
|
||||
const rcheevos_racheevo_t* cheevo = rcheevos_locals.game.achievements;
|
||||
const rcheevos_racheevo_t* end = cheevo + rcheevos_locals.game.achievement_count;
|
||||
int number_of_active = 0;
|
||||
int number_of_unsupported = 0;
|
||||
int number_of_core = 0;
|
||||
int mode = RCHEEVOS_ACTIVE_SOFTCORE;
|
||||
char msg[256];
|
||||
const settings_t* settings = config_get_ptr();
|
||||
const rcheevos_racheevo_t* cheevo = rcheevos_locals.game.achievements;
|
||||
const rcheevos_racheevo_t* end = cheevo
|
||||
+ rcheevos_locals.game.achievement_count;
|
||||
int number_of_active = 0;
|
||||
int number_of_unsupported = 0;
|
||||
int number_of_core = 0;
|
||||
int mode = RCHEEVOS_ACTIVE_SOFTCORE;
|
||||
|
||||
if (rcheevos_locals.hardcore_active)
|
||||
mode = RCHEEVOS_ACTIVE_HARDCORE;
|
||||
@ -1186,39 +1249,29 @@ static void rcheevos_show_game_placard()
|
||||
}
|
||||
|
||||
if (number_of_core == 0)
|
||||
{
|
||||
snprintf(msg, sizeof(msg), "This game has no achievements.");
|
||||
}
|
||||
else if (!number_of_unsupported)
|
||||
{
|
||||
if (settings->bools.cheevos_start_active)
|
||||
{
|
||||
snprintf(msg, sizeof(msg),
|
||||
"All %d achievements activated for this session.",
|
||||
number_of_core);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(msg, sizeof(msg),
|
||||
"You have %d of %d achievements unlocked.",
|
||||
number_of_core - number_of_active, number_of_core);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (settings->bools.cheevos_start_active)
|
||||
{
|
||||
snprintf(msg, sizeof(msg),
|
||||
"All %d achievements activated for this session (%d unsupported).",
|
||||
number_of_core, number_of_unsupported);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(msg, sizeof(msg),
|
||||
"You have %d of %d achievements unlocked (%d unsupported).",
|
||||
number_of_core - number_of_active - number_of_unsupported,
|
||||
number_of_core, number_of_unsupported);
|
||||
}
|
||||
}
|
||||
|
||||
msg[sizeof(msg) - 1] = 0;
|
||||
@ -1241,7 +1294,8 @@ static void rcheevos_fetch_badges_callback(void* userdata)
|
||||
|
||||
static void rcheevos_fetch_badges(void)
|
||||
{
|
||||
/* this function manages the RCHEEVOS_LOAD_STATE_FETCHING_BADGES state */
|
||||
/* this function manages the
|
||||
* RCHEEVOS_LOAD_STATE_FETCHING_BADGES state */
|
||||
rcheevos_client_fetch_badges(rcheevos_fetch_badges_callback, NULL);
|
||||
}
|
||||
|
||||
@ -1253,12 +1307,13 @@ static void rcheevos_start_session(void)
|
||||
return;
|
||||
}
|
||||
|
||||
if (rcheevos_locals.game.achievement_count == 0 &&
|
||||
rcheevos_locals.game.leaderboard_count == 0)
|
||||
if ( rcheevos_locals.game.achievement_count == 0
|
||||
&& rcheevos_locals.game.leaderboard_count == 0)
|
||||
{
|
||||
if (!rcheevos_locals.runtime.richpresence)
|
||||
{
|
||||
/* nothing for the runtime to process, disable hardcore and bail */
|
||||
/* nothing for the runtime to process,
|
||||
* disable hardcore and bail */
|
||||
rcheevos_show_game_placard();
|
||||
rcheevos_pause_hardcore();
|
||||
return;
|
||||
@ -1267,22 +1322,26 @@ static void rcheevos_start_session(void)
|
||||
|
||||
rcheevos_begin_load_state(RCHEEVOS_LOAD_STATE_STARTING_SESSION);
|
||||
|
||||
/* activate the achievements and leaderboards (rich presence has already been activated) */
|
||||
/* activate the achievements and leaderboards
|
||||
* (rich presence has already been activated) */
|
||||
rcheevos_activate_achievements();
|
||||
|
||||
if (rcheevos_locals.leaderboards_enabled && rcheevos_locals.hardcore_active)
|
||||
if ( rcheevos_locals.leaderboards_enabled
|
||||
&& rcheevos_locals.hardcore_active)
|
||||
rcheevos_activate_leaderboards();
|
||||
|
||||
#if HAVE_REWIND
|
||||
if (!rcheevos_locals.hardcore_active)
|
||||
{
|
||||
/* re-enable rewind. if rcheevos_locals.loaded is true, additional space will be allocated
|
||||
* for the achievement state data */
|
||||
/* Re-enable rewind. If rcheevos_locals.loaded is true,
|
||||
* additional space will be allocated for the achievement
|
||||
* state data */
|
||||
const settings_t* settings = config_get_ptr();
|
||||
if (settings->bools.rewind_enable)
|
||||
{
|
||||
#ifdef HAVE_THREADS
|
||||
/* have to "schedule" this. CMD_EVENT_REWIND_INIT should only be called on the main thread */
|
||||
/* Have to "schedule" this. CMD_EVENT_REWIND_INIT should
|
||||
* only be called on the main thread */
|
||||
rcheevos_locals.queued_command = CMD_EVENT_REWIND_INIT;
|
||||
#else
|
||||
command_event(CMD_EVENT_REWIND_INIT, NULL);
|
||||
@ -1291,12 +1350,13 @@ static void rcheevos_start_session(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* we don't have to wait for this to complete to proceed to the next loading state */
|
||||
/* We don't have to wait for this to complete
|
||||
* to proceed to the next loading state */
|
||||
rcheevos_client_start_session(rcheevos_locals.game.id);
|
||||
|
||||
rcheevos_validate_memrefs(&rcheevos_locals);
|
||||
|
||||
/* let the runtime start processing the achievements */
|
||||
/* Let the runtime start processing the achievements */
|
||||
rcheevos_locals.loaded = true;
|
||||
|
||||
rcheevos_show_game_placard();
|
||||
@ -1312,7 +1372,8 @@ static void rcheevos_initialize_runtime_callback(void* userdata)
|
||||
|
||||
static void rcheevos_fetch_game_data(void)
|
||||
{
|
||||
if (rcheevos_locals.load_info.state == RCHEEVOS_LOAD_STATE_NETWORK_ERROR)
|
||||
if ( rcheevos_locals.load_info.state
|
||||
== RCHEEVOS_LOAD_STATE_NETWORK_ERROR)
|
||||
{
|
||||
strlcpy(rcheevos_locals.game.hash,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE),
|
||||
@ -1325,19 +1386,15 @@ static void rcheevos_fetch_game_data(void)
|
||||
{
|
||||
const settings_t* settings = config_get_ptr();
|
||||
if (settings->bools.cheevos_verbose_enable)
|
||||
{
|
||||
runloop_msg_queue_push(
|
||||
"This game has no achievements.",
|
||||
0, 3 * 60, false, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||
}
|
||||
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "Game could not be identified\n");
|
||||
if (rcheevos_locals.load_info.hashes_tried > 1)
|
||||
{
|
||||
strlcpy(rcheevos_locals.game.hash,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE),
|
||||
sizeof(rcheevos_locals.game.hash));
|
||||
}
|
||||
|
||||
rcheevos_locals.load_info.state = RCHEEVOS_LOAD_STATE_UNKNOWN_GAME;
|
||||
rcheevos_pause_hardcore();
|
||||
@ -1367,9 +1424,7 @@ static void rcheevos_fetch_game_data(void)
|
||||
|
||||
/* wait for rewind to be disabled */
|
||||
while (rcheevos_locals.queued_command != CMD_EVENT_NONE)
|
||||
{
|
||||
retro_sleep(1);
|
||||
}
|
||||
#else
|
||||
command_event(CMD_EVENT_REWIND_DEINIT, NULL);
|
||||
#endif
|
||||
@ -1391,14 +1446,18 @@ struct rcheevos_identify_game_data
|
||||
|
||||
static void rcheevos_identify_game_callback(void* userdata)
|
||||
{
|
||||
struct rcheevos_identify_game_data* data = (struct rcheevos_identify_game_data*)userdata;
|
||||
struct rcheevos_identify_game_data* data =
|
||||
(struct rcheevos_identify_game_data*)userdata;
|
||||
|
||||
if (data)
|
||||
{
|
||||
/* previous hash didn't match, try the next one */
|
||||
char hash[33];
|
||||
if (rcheevos_locals.game.id == 0 && rc_hash_iterate(hash, &data->iterator))
|
||||
if ( rcheevos_locals.game.id == 0
|
||||
&& rc_hash_iterate(hash, &data->iterator))
|
||||
{
|
||||
rcheevos_client_identify_game(hash, rcheevos_identify_game_callback, data);
|
||||
rcheevos_client_identify_game(hash,
|
||||
rcheevos_identify_game_callback, data);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1420,25 +1479,29 @@ static bool rcheevos_identify_game(const struct retro_game_info* info)
|
||||
size_t len;
|
||||
char hash[33];
|
||||
|
||||
rc_hash_initialize_iterator(&iterator, info->path, (uint8_t*)info->data, info->size);
|
||||
rc_hash_initialize_iterator(&iterator,
|
||||
info->path, (uint8_t*)info->data, info->size);
|
||||
if (!rc_hash_iterate(hash, &iterator))
|
||||
{
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "no hashes generated\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
strlcpy(rcheevos_locals.game.hash, hash, sizeof(rcheevos_locals.game.hash));
|
||||
strlcpy(rcheevos_locals.game.hash, hash,
|
||||
sizeof(rcheevos_locals.game.hash));
|
||||
rcheevos_locals.load_info.hashes_tried++;
|
||||
|
||||
if (iterator.consoles[iterator.index] == 0)
|
||||
{
|
||||
/* no more potential matches, just try the one hash */
|
||||
rcheevos_client_identify_game(hash, rcheevos_identify_game_callback, NULL);
|
||||
rcheevos_client_identify_game(hash,
|
||||
rcheevos_identify_game_callback, NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* multiple potential matches, clone the data for the next attempt */
|
||||
data = (struct rcheevos_identify_game_data*)calloc(1, sizeof(struct rcheevos_identify_game_data));
|
||||
data = (struct rcheevos_identify_game_data*)
|
||||
calloc(1, sizeof(struct rcheevos_identify_game_data));
|
||||
if (!data)
|
||||
{
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "allocation failed\n");
|
||||
@ -1463,7 +1526,8 @@ static bool rcheevos_identify_game(const struct retro_game_info* info)
|
||||
}
|
||||
|
||||
memcpy(&data->iterator, &iterator, sizeof(iterator));
|
||||
rcheevos_client_identify_game(hash, rcheevos_identify_game_callback, data);
|
||||
rcheevos_client_identify_game(hash,
|
||||
rcheevos_identify_game_callback, data);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1478,7 +1542,8 @@ static void rcheevos_login_callback(void* userdata)
|
||||
snprintf(msg, sizeof(msg),
|
||||
"RetroAchievements: Logged in as \"%s\".",
|
||||
rcheevos_locals.username);
|
||||
runloop_msg_queue_push(msg, 0, 2 * 60, false, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||
runloop_msg_queue_push(msg, 0, 2 * 60, false, NULL,
|
||||
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1486,7 +1551,7 @@ static void rcheevos_login_callback(void* userdata)
|
||||
rcheevos_fetch_game_data();
|
||||
}
|
||||
|
||||
/* increment the outstanding requests counter and set the load state */
|
||||
/* Increment the outstanding requests counter and set the load state */
|
||||
void rcheevos_begin_load_state(enum rcheevos_load_state state)
|
||||
{
|
||||
CHEEVOS_LOCK(rcheevos_locals.load_info.request_lock);
|
||||
@ -1495,7 +1560,8 @@ void rcheevos_begin_load_state(enum rcheevos_load_state state)
|
||||
CHEEVOS_UNLOCK(rcheevos_locals.load_info.request_lock);
|
||||
}
|
||||
|
||||
/* decrement and return the outstanding requests counter. if non-zero, requests are still outstanding */
|
||||
/* Decrement and return the outstanding requests counter.
|
||||
* If non-zero, requests are still outstanding */
|
||||
int rcheevos_end_load_state(void)
|
||||
{
|
||||
int requests = 0;
|
||||
@ -1513,25 +1579,32 @@ bool rcheevos_load_aborted(void)
|
||||
{
|
||||
switch (rcheevos_locals.load_info.state)
|
||||
{
|
||||
case RCHEEVOS_LOAD_STATE_ABORTED: /* unload has been called */
|
||||
case RCHEEVOS_LOAD_STATE_NONE: /* unload quit waiting and ran to completion */
|
||||
case RCHEEVOS_LOAD_STATE_NETWORK_ERROR: /* login/resolve hash failed after several attempts */
|
||||
/* Unload has been called */
|
||||
case RCHEEVOS_LOAD_STATE_ABORTED:
|
||||
/* Unload quit waiting and ran to completion */
|
||||
case RCHEEVOS_LOAD_STATE_NONE:
|
||||
/* Login/resolve hash failed after several attempts */
|
||||
case RCHEEVOS_LOAD_STATE_NETWORK_ERROR:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool rcheevos_load(const void *data)
|
||||
{
|
||||
const struct retro_game_info *info = (const struct retro_game_info*)data;
|
||||
settings_t *settings = config_get_ptr();
|
||||
bool cheevos_enable = settings && settings->bools.cheevos_enable;
|
||||
struct rc_hash_filereader filereader;
|
||||
struct rc_hash_cdreader cdreader;
|
||||
struct rc_hash_filereader filereader;
|
||||
const struct retro_game_info *info = (const struct retro_game_info*)
|
||||
data;
|
||||
settings_t *settings = config_get_ptr();
|
||||
bool cheevos_enable = settings
|
||||
&& settings->bools.cheevos_enable;
|
||||
|
||||
memset(&rcheevos_locals.load_info, 0,
|
||||
sizeof(rcheevos_locals.load_info));
|
||||
|
||||
memset(&rcheevos_locals.load_info, 0, sizeof(rcheevos_locals.load_info));
|
||||
rcheevos_locals.loaded = false;
|
||||
rcheevos_locals.game.id = -1;
|
||||
#ifdef HAVE_THREADS
|
||||
@ -1539,8 +1612,8 @@ bool rcheevos_load(const void *data)
|
||||
#endif
|
||||
rc_runtime_init(&rcheevos_locals.runtime);
|
||||
|
||||
/* if achievements are not enabled, or the core doesn't support achievements,
|
||||
* disable hardcore and bail */
|
||||
/* If achievements are not enabled, or the core doesn't
|
||||
* support achievements, disable hardcore and bail */
|
||||
if (!cheevos_enable || !rcheevos_locals.core_supports || !data)
|
||||
{
|
||||
rcheevos_pause_hardcore();
|
||||
@ -1575,14 +1648,15 @@ bool rcheevos_load(const void *data)
|
||||
|
||||
rc_hash_init_error_message_callback(rcheevos_handle_log_message);
|
||||
|
||||
#ifndef DEBUG /* in DEBUG mode, always initialize the verbose message handler */
|
||||
#ifndef DEBUG
|
||||
/* in DEBUG mode, always initialize the verbose message handler */
|
||||
if (settings->bools.cheevos_verbose_enable)
|
||||
#endif
|
||||
{
|
||||
rc_hash_init_verbose_message_callback(rcheevos_handle_log_message);
|
||||
}
|
||||
|
||||
/* refresh the user agent in case it's not set or has changed */
|
||||
/* Refresh the user agent in case it's not set or has changed */
|
||||
rcheevos_client_initialize();
|
||||
rcheevos_get_user_agent(&rcheevos_locals,
|
||||
rcheevos_locals.user_agent_core,
|
||||
@ -1614,10 +1688,12 @@ bool rcheevos_load(const void *data)
|
||||
|
||||
*/
|
||||
|
||||
/* identify the game and log the user in. these will run asynchronously. */
|
||||
/* Identify the game and log the user in.
|
||||
* These will run asynchronously. */
|
||||
if (!rcheevos_identify_game(info))
|
||||
{
|
||||
/* no hashes could be generated for the game, disable hardcore and bail */
|
||||
/* No hashes could be generated for the game,
|
||||
* disable hardcore and bail */
|
||||
rcheevos_end_load_state();
|
||||
rcheevos_pause_hardcore();
|
||||
return false;
|
||||
@ -1630,15 +1706,19 @@ bool rcheevos_load(const void *data)
|
||||
{
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "Attempting to login %s (with password)\n",
|
||||
settings->arrays.cheevos_username);
|
||||
rcheevos_client_login_with_password(settings->arrays.cheevos_username,
|
||||
settings->arrays.cheevos_password, rcheevos_login_callback, NULL);
|
||||
rcheevos_client_login_with_password(
|
||||
settings->arrays.cheevos_username,
|
||||
settings->arrays.cheevos_password,
|
||||
rcheevos_login_callback, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "Attempting to login %s (with token)\n",
|
||||
settings->arrays.cheevos_username);
|
||||
rcheevos_client_login_with_token(settings->arrays.cheevos_username,
|
||||
settings->arrays.cheevos_token, rcheevos_login_callback, NULL);
|
||||
rcheevos_client_login_with_token(
|
||||
settings->arrays.cheevos_username,
|
||||
settings->arrays.cheevos_token,
|
||||
rcheevos_login_callback, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -126,9 +126,7 @@ static int append_no_spaces(char* buffer, char* stop, const char* text)
|
||||
++text;
|
||||
}
|
||||
else
|
||||
{
|
||||
*ptr++ = *text++;
|
||||
}
|
||||
}
|
||||
|
||||
*ptr = '\0';
|
||||
@ -156,10 +154,8 @@ void rcheevos_get_user_agent(rcheevos_locals_t *locals,
|
||||
"RetroArch/%s (%s %d.%d)", PACKAGE_VERSION, tmp, major, minor);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(locals->user_agent_prefix, sizeof(locals->user_agent_prefix),
|
||||
"RetroArch/%s", PACKAGE_VERSION);
|
||||
}
|
||||
}
|
||||
|
||||
/* append the non-changing portion */
|
||||
@ -179,9 +175,7 @@ void rcheevos_get_user_agent(rcheevos_locals_t *locals,
|
||||
ptr += strlen(ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr += append_no_spaces(ptr, stop, system->library_name);
|
||||
}
|
||||
|
||||
if (system->library_version)
|
||||
{
|
||||
@ -287,18 +281,14 @@ static void rcheevos_log_post_url(const char* url, const char* post)
|
||||
|
||||
static void rcheevos_async_begin_http_request(rcheevos_async_io_request* request)
|
||||
{
|
||||
if (request->request.post_data == NULL)
|
||||
{
|
||||
task_push_http_transfer_with_user_agent(request->request.url,
|
||||
true, "GET", request->user_agent,
|
||||
rcheevos_async_http_task_callback, request);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (request->request.post_data)
|
||||
task_push_http_post_transfer_with_user_agent(request->request.url,
|
||||
request->request.post_data, true, "POST", request->user_agent,
|
||||
rcheevos_async_http_task_callback, request);
|
||||
}
|
||||
else
|
||||
task_push_http_transfer_with_user_agent(request->request.url,
|
||||
true, "GET", request->user_agent,
|
||||
rcheevos_async_http_task_callback, request);
|
||||
}
|
||||
|
||||
static void rcheevos_async_retry_request(retro_task_t* task)
|
||||
@ -315,8 +305,7 @@ static void rcheevos_async_retry_request(retro_task_t* task)
|
||||
|
||||
static void rcheevos_async_retry_request_after_delay(rcheevos_async_io_request* request, const char* error)
|
||||
{
|
||||
retro_task_t* task = task_init();
|
||||
|
||||
retro_task_t* task = task_init();
|
||||
/* Double the wait between each attempt until we hit
|
||||
* a maximum delay of two minutes.
|
||||
* 250ms -> 500ms -> 1s -> 2s -> 4s -> 8s -> 16s -> 32s -> 64s -> 120s -> 120s... */
|
||||
@ -344,13 +333,16 @@ static bool rcheevos_async_request_failed(rcheevos_async_io_request* request, co
|
||||
/* retry failed, don't retry these requests */
|
||||
switch (request->type)
|
||||
{
|
||||
case CHEEVOS_ASYNC_RICHPRESENCE: /* timer will ping again */
|
||||
case CHEEVOS_ASYNC_FETCH_BADGE: /* fallback to the placeholder image */
|
||||
/* timer will ping again */
|
||||
case CHEEVOS_ASYNC_RICHPRESENCE:
|
||||
/* fallback to the placeholder image */
|
||||
case CHEEVOS_ASYNC_FETCH_BADGE:
|
||||
return false;
|
||||
|
||||
case CHEEVOS_ASYNC_RESOLVE_HASH:
|
||||
case CHEEVOS_ASYNC_LOGIN:
|
||||
/* make a maximum of four attempts (0ms -> 250ms -> 500ms -> 1s) */
|
||||
/* make a maximum of four attempts
|
||||
(0ms -> 250ms -> 500ms -> 1s) */
|
||||
if (request->attempt_count == 3)
|
||||
return false;
|
||||
break;
|
||||
@ -366,7 +358,8 @@ static bool rcheevos_async_request_failed(rcheevos_async_io_request* request, co
|
||||
}
|
||||
|
||||
static void rcheevos_async_http_task_callback(
|
||||
retro_task_t* task, void* task_data, void* user_data, const char* error)
|
||||
retro_task_t* task, void* task_data, void* user_data,
|
||||
const char* error)
|
||||
{
|
||||
rcheevos_async_io_request *request = (rcheevos_async_io_request*)user_data;
|
||||
http_transfer_data_t *data = (http_transfer_data_t*)task_data;
|
||||
@ -383,19 +376,14 @@ static void rcheevos_async_http_task_callback(
|
||||
if (error)
|
||||
{
|
||||
/* there was a communication error */
|
||||
/* automatically requeued, don't process any further */
|
||||
if (rcheevos_async_request_failed(request, error))
|
||||
{
|
||||
/* automatically requeued, don't process any further */
|
||||
return;
|
||||
}
|
||||
|
||||
strlcpy(buffer, error, sizeof(buffer));
|
||||
}
|
||||
else if (!data)
|
||||
{
|
||||
/* Server did not return HTTP headers */
|
||||
else if (!data) /* Server did not return HTTP headers */
|
||||
strlcpy(buffer, "Server communication error", sizeof(buffer));
|
||||
}
|
||||
else if (!data->data || !data->len)
|
||||
{
|
||||
if (data->status <= 0)
|
||||
@ -407,29 +395,22 @@ static void rcheevos_async_http_task_callback(
|
||||
return;
|
||||
}
|
||||
|
||||
if (data->status != 200)
|
||||
{
|
||||
/* Server returned an error via status code. */
|
||||
if (data->status != 200) /* Server returned error via status code. */
|
||||
snprintf(buffer, sizeof(buffer), "HTTP error code %d", data->status);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Server sent an empty response without an error status code */
|
||||
else /* Server sent empty response without error status code */
|
||||
strlcpy(buffer, "No response from server", sizeof(buffer));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer[0] = '\0'; /* indicate success unless handler provides error */
|
||||
/* indicate success unless handler provides error */
|
||||
buffer[0] = '\0';
|
||||
|
||||
/* Call appropriate handler to process the response */
|
||||
/* NOTE: data->data is not null-terminated. Most handlers assume the
|
||||
* response is properly formatted or will encounter a parse failure
|
||||
* before reading past the end of the data */
|
||||
if (request->handler)
|
||||
{
|
||||
/* NOTE: data->data is not null-terminated. Most handlers assume the
|
||||
* response is properly formatted or will encounter a parse failure
|
||||
* before reading past the end of the data */
|
||||
request->handler(request, data, buffer, sizeof(buffer));
|
||||
}
|
||||
}
|
||||
|
||||
if (!buffer[0])
|
||||
@ -469,19 +450,22 @@ static void rcheevos_async_http_task_callback(
|
||||
size_t len = 0;
|
||||
char* ptr;
|
||||
|
||||
if (rcheevos_locals->load_info.state == RCHEEVOS_LOAD_STATE_NETWORK_ERROR)
|
||||
if ( rcheevos_locals->load_info.state
|
||||
== RCHEEVOS_LOAD_STATE_NETWORK_ERROR)
|
||||
break;
|
||||
|
||||
rcheevos_locals->load_info.state = RCHEEVOS_LOAD_STATE_NETWORK_ERROR;
|
||||
rcheevos_locals->load_info.state =
|
||||
RCHEEVOS_LOAD_STATE_NETWORK_ERROR;
|
||||
|
||||
while (request->request.url[len] != '/' || /* find the first single slash */
|
||||
request->request.url[len + 1] == '/' ||
|
||||
request->request.url[len - 1] == '/')
|
||||
{
|
||||
while (
|
||||
/* find the first single slash */
|
||||
request->request.url[len] != '/'
|
||||
|| request->request.url[len + 1] == '/'
|
||||
|| request->request.url[len - 1] == '/')
|
||||
++len;
|
||||
}
|
||||
|
||||
ptr = errbuf + snprintf(errbuf, sizeof(errbuf), "Could not communicate with ");
|
||||
ptr = errbuf + snprintf(errbuf, sizeof(errbuf),
|
||||
"Could not communicate with ");
|
||||
memcpy(ptr, request->request.url, len);
|
||||
ptr[len] = '\0';
|
||||
}
|
||||
@ -509,7 +493,8 @@ static void rcheevos_async_http_task_callback(
|
||||
free(request);
|
||||
}
|
||||
|
||||
static void rcheevos_async_begin_request(rcheevos_async_io_request* request,
|
||||
static void rcheevos_async_begin_request(
|
||||
rcheevos_async_io_request* request,
|
||||
rcheevos_async_handler handler, char type, int id,
|
||||
const char* success_message, const char* failure_message)
|
||||
{
|
||||
@ -528,7 +513,8 @@ static void rcheevos_async_begin_request(rcheevos_async_io_request* request,
|
||||
}
|
||||
|
||||
static bool rcheevos_async_succeeded(int result,
|
||||
const rc_api_response_t* response, char buffer[], size_t buffer_size)
|
||||
const rc_api_response_t* response, char buffer[],
|
||||
size_t buffer_size)
|
||||
{
|
||||
if (result != RC_OK)
|
||||
{
|
||||
@ -555,28 +541,32 @@ void rcheevos_client_initialize(void)
|
||||
* login *
|
||||
****************************/
|
||||
|
||||
static void rcheevos_async_login_callback(struct rcheevos_async_io_request* request,
|
||||
http_transfer_data_t* data, char buffer[], size_t buffer_size)
|
||||
static void rcheevos_async_login_callback(
|
||||
struct rcheevos_async_io_request* request,
|
||||
http_transfer_data_t* data, char buffer[], size_t buffer_size)
|
||||
{
|
||||
rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
|
||||
rc_api_login_response_t api_response;
|
||||
|
||||
int result = rc_api_process_login_response(&api_response, data->data);
|
||||
if (rcheevos_async_succeeded(result, &api_response.response, buffer, buffer_size))
|
||||
if (rcheevos_async_succeeded(result, &api_response.response,
|
||||
buffer, buffer_size))
|
||||
{
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "%s logged in successfully\n", api_response.username);
|
||||
strlcpy(rcheevos_locals->username, api_response.username, sizeof(rcheevos_locals->username));
|
||||
strlcpy(rcheevos_locals->token, api_response.api_token, sizeof(rcheevos_locals->token));
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "%s logged in successfully\n",
|
||||
api_response.username);
|
||||
strlcpy(rcheevos_locals->username, api_response.username,
|
||||
sizeof(rcheevos_locals->username));
|
||||
strlcpy(rcheevos_locals->token, api_response.api_token,
|
||||
sizeof(rcheevos_locals->token));
|
||||
}
|
||||
else
|
||||
{
|
||||
rcheevos_locals->token[0] = '\0';
|
||||
}
|
||||
|
||||
rc_api_destroy_login_response(&api_response);
|
||||
}
|
||||
|
||||
static void rcheevos_client_login(const char* username, const char* password, const char* token,
|
||||
static void rcheevos_client_login(const char* username,
|
||||
const char* password, const char* token,
|
||||
rcheevos_client_callback callback, void* userdata)
|
||||
{
|
||||
rcheevos_async_io_request* request = (rcheevos_async_io_request*)
|
||||
@ -607,14 +597,16 @@ static void rcheevos_client_login(const char* username, const char* password, co
|
||||
}
|
||||
}
|
||||
|
||||
void rcheevos_client_login_with_password(const char* username, const char* password,
|
||||
rcheevos_client_callback callback, void* userdata)
|
||||
void rcheevos_client_login_with_password(const char* username,
|
||||
const char* password,
|
||||
rcheevos_client_callback callback, void* userdata)
|
||||
{
|
||||
rcheevos_client_login(username, password, NULL, callback, userdata);
|
||||
}
|
||||
|
||||
void rcheevos_client_login_with_token(const char* username, const char* token,
|
||||
rcheevos_client_callback callback, void* userdata)
|
||||
void rcheevos_client_login_with_token(const char* username,
|
||||
const char* token,
|
||||
rcheevos_client_callback callback, void* userdata)
|
||||
{
|
||||
rcheevos_client_login(username, NULL, token, callback, userdata);
|
||||
}
|
||||
@ -623,13 +615,16 @@ void rcheevos_client_login_with_token(const char* username, const char* token,
|
||||
* identify game *
|
||||
****************************/
|
||||
|
||||
static void rcheevos_async_resolve_hash_callback(struct rcheevos_async_io_request* request,
|
||||
http_transfer_data_t* data, char buffer[], size_t buffer_size)
|
||||
static void rcheevos_async_resolve_hash_callback(
|
||||
struct rcheevos_async_io_request* request,
|
||||
http_transfer_data_t* data, char buffer[], size_t buffer_size)
|
||||
{
|
||||
rc_api_resolve_hash_response_t api_response;
|
||||
int result = rc_api_process_resolve_hash_response(&api_response,
|
||||
data->data);
|
||||
|
||||
int result = rc_api_process_resolve_hash_response(&api_response, data->data);
|
||||
if (rcheevos_async_succeeded(result, &api_response.response, buffer, buffer_size))
|
||||
if (rcheevos_async_succeeded(result, &api_response.response,
|
||||
buffer, buffer_size))
|
||||
{
|
||||
rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
|
||||
rcheevos_locals->game.id = api_response.game_id;
|
||||
@ -638,7 +633,8 @@ static void rcheevos_async_resolve_hash_callback(struct rcheevos_async_io_reques
|
||||
rc_api_destroy_resolve_hash_response(&api_response);
|
||||
}
|
||||
|
||||
void rcheevos_client_identify_game(const char* hash, rcheevos_client_callback callback, void* userdata)
|
||||
void rcheevos_client_identify_game(const char* hash,
|
||||
rcheevos_client_callback callback, void* userdata)
|
||||
{
|
||||
rcheevos_async_io_request* request = (rcheevos_async_io_request*)
|
||||
calloc(1, sizeof(rcheevos_async_io_request));
|
||||
@ -651,13 +647,13 @@ void rcheevos_client_identify_game(const char* hash, rcheevos_client_callback ca
|
||||
rc_api_resolve_hash_request_t api_params;
|
||||
|
||||
memset(&api_params, 0, sizeof(api_params));
|
||||
api_params.username = "unused"; /* TODO: don't set this after upgrading to rcheevos 10.2 */
|
||||
api_params.username = "unused"; /* TODO: don't set this after upgrading to rcheevos 10.2 */
|
||||
api_params.api_token = "unused"; /* TODO: don't set this after upgrading to rcheevos 10.2 */
|
||||
api_params.game_hash = hash;
|
||||
|
||||
rc_api_init_resolve_hash_request(&request->request, &api_params);
|
||||
|
||||
request->callback = callback;
|
||||
request->callback = callback;
|
||||
request->callback_data = userdata;
|
||||
|
||||
rcheevos_begin_load_state(RCHEEVOS_LOAD_STATE_IDENTIFYING_GAME);
|
||||
@ -683,16 +679,18 @@ typedef struct rcheevos_async_initialize_runtime_data_t
|
||||
void* callback_data;
|
||||
} rcheevos_async_initialize_runtime_data_t;
|
||||
|
||||
static void rcheevos_client_copy_achievements(rcheevos_async_initialize_runtime_data_t* runtime_data)
|
||||
static void rcheevos_client_copy_achievements(
|
||||
rcheevos_async_initialize_runtime_data_t* runtime_data)
|
||||
{
|
||||
const rc_api_achievement_definition_t* definition;
|
||||
rcheevos_racheevo_t* achievement;
|
||||
rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
|
||||
const settings_t* settings = config_get_ptr();
|
||||
unsigned i, j;
|
||||
const rc_api_achievement_definition_t* definition;
|
||||
rcheevos_racheevo_t *achievement;
|
||||
rcheevos_locals_t *rcheevos_locals = get_rcheevos_locals();
|
||||
const settings_t *settings = config_get_ptr();
|
||||
|
||||
rcheevos_locals->game.achievements = (rcheevos_racheevo_t*)
|
||||
calloc(runtime_data->game_data.num_achievements, sizeof(rcheevos_racheevo_t));
|
||||
rcheevos_locals->game.achievements = (rcheevos_racheevo_t*)
|
||||
calloc(runtime_data->game_data.num_achievements,
|
||||
sizeof(rcheevos_racheevo_t));
|
||||
|
||||
achievement = rcheevos_locals->game.achievements;
|
||||
if (!achievement)
|
||||
@ -702,40 +700,50 @@ static void rcheevos_client_copy_achievements(rcheevos_async_initialize_runtime_
|
||||
}
|
||||
|
||||
definition = runtime_data->game_data.achievements;
|
||||
for (i = 0; i < runtime_data->game_data.num_achievements; ++i, ++definition)
|
||||
for (i = 0; i < runtime_data->game_data.num_achievements;
|
||||
++i, ++definition)
|
||||
{
|
||||
if (definition->category == 0 ||
|
||||
!definition->definition || !definition->definition[0] ||
|
||||
!definition->title || !definition->title[0] ||
|
||||
!definition->description || !definition->description[0])
|
||||
{
|
||||
/* invalid definition, ignore */
|
||||
/* invalid definition, ignore */
|
||||
if (
|
||||
definition->category == 0
|
||||
|| !definition->definition
|
||||
|| !definition->definition[0]
|
||||
|| !definition->title
|
||||
|| !definition->title[0]
|
||||
|| !definition->description
|
||||
|| !definition->description[0])
|
||||
continue;
|
||||
}
|
||||
|
||||
if (definition->category != 3)
|
||||
{
|
||||
achievement->active = RCHEEVOS_ACTIVE_UNOFFICIAL;
|
||||
|
||||
if (settings->bools.cheevos_test_unofficial)
|
||||
achievement->active |= RCHEEVOS_ACTIVE_SOFTCORE | RCHEEVOS_ACTIVE_HARDCORE;
|
||||
achievement->active |= RCHEEVOS_ACTIVE_SOFTCORE
|
||||
| RCHEEVOS_ACTIVE_HARDCORE;
|
||||
}
|
||||
else
|
||||
{
|
||||
achievement->active = RCHEEVOS_ACTIVE_SOFTCORE | RCHEEVOS_ACTIVE_HARDCORE;
|
||||
achievement->active = RCHEEVOS_ACTIVE_SOFTCORE
|
||||
| RCHEEVOS_ACTIVE_HARDCORE;
|
||||
|
||||
for (j = 0; j < runtime_data->hardcore_unlocks.num_achievement_ids; ++j)
|
||||
for (j = 0; j <
|
||||
runtime_data->hardcore_unlocks.num_achievement_ids; ++j)
|
||||
{
|
||||
if (runtime_data->hardcore_unlocks.achievement_ids[j] == definition->id)
|
||||
if (runtime_data->hardcore_unlocks.achievement_ids[j]
|
||||
== definition->id)
|
||||
{
|
||||
achievement->active &= ~(RCHEEVOS_ACTIVE_HARDCORE | RCHEEVOS_ACTIVE_SOFTCORE);
|
||||
achievement->active &= ~(RCHEEVOS_ACTIVE_HARDCORE
|
||||
| RCHEEVOS_ACTIVE_SOFTCORE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((achievement->active & RCHEEVOS_ACTIVE_SOFTCORE) != 0)
|
||||
{
|
||||
for (j = 0; j < runtime_data->non_hardcore_unlocks.num_achievement_ids; ++j)
|
||||
for (j = 0; j <
|
||||
runtime_data->non_hardcore_unlocks.num_achievement_ids;
|
||||
++j)
|
||||
{
|
||||
if (runtime_data->non_hardcore_unlocks.achievement_ids[j] == definition->id)
|
||||
{
|
||||
@ -746,33 +754,40 @@ static void rcheevos_client_copy_achievements(rcheevos_async_initialize_runtime_
|
||||
}
|
||||
}
|
||||
|
||||
achievement->id = definition->id;
|
||||
achievement->title = strdup(definition->title);
|
||||
achievement->id = definition->id;
|
||||
achievement->title = strdup(definition->title);
|
||||
achievement->description = strdup(definition->description);
|
||||
achievement->badge = strdup(definition->badge_name);
|
||||
achievement->points = definition->points;
|
||||
achievement->badge = strdup(definition->badge_name);
|
||||
achievement->points = definition->points;
|
||||
|
||||
/* if an achievement has been fully unlocked, we don't need to keep the definition around
|
||||
* as it won't be reactivated. otherwise, we do have to keep a copy of it. */
|
||||
if ((achievement->active & (RCHEEVOS_ACTIVE_HARDCORE | RCHEEVOS_ACTIVE_SOFTCORE)) != 0)
|
||||
/* If an achievement has been fully unlocked,
|
||||
* we don't need to keep the definition around
|
||||
* as it won't be reactivated. Otherwise,
|
||||
* we do have to keep a copy of it. */
|
||||
if ((achievement->active & (RCHEEVOS_ACTIVE_HARDCORE
|
||||
| RCHEEVOS_ACTIVE_SOFTCORE)) != 0)
|
||||
achievement->memaddr = strdup(definition->definition);
|
||||
|
||||
++achievement;
|
||||
}
|
||||
|
||||
rcheevos_locals->game.achievement_count = achievement - rcheevos_locals->game.achievements;
|
||||
rcheevos_locals->game.achievement_count = achievement
|
||||
- rcheevos_locals->game.achievements;
|
||||
}
|
||||
|
||||
static void rcheevos_client_copy_leaderboards(rcheevos_async_initialize_runtime_data_t* runtime_data)
|
||||
static void rcheevos_client_copy_leaderboards(
|
||||
rcheevos_async_initialize_runtime_data_t* runtime_data)
|
||||
{
|
||||
const rc_api_leaderboard_definition_t* definition;
|
||||
rcheevos_ralboard_t* leaderboard;
|
||||
rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
|
||||
unsigned i;
|
||||
rcheevos_ralboard_t *leaderboard;
|
||||
const rc_api_leaderboard_definition_t *definition;
|
||||
rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
|
||||
|
||||
rcheevos_locals->game.leaderboards = (rcheevos_ralboard_t*)
|
||||
calloc(runtime_data->game_data.num_leaderboards, sizeof(rcheevos_ralboard_t));
|
||||
rcheevos_locals->game.leaderboard_count = runtime_data->game_data.num_leaderboards;
|
||||
calloc(runtime_data->game_data.num_leaderboards,
|
||||
sizeof(rcheevos_ralboard_t));
|
||||
rcheevos_locals->game.leaderboard_count =
|
||||
runtime_data->game_data.num_leaderboards;
|
||||
|
||||
leaderboard = rcheevos_locals->game.leaderboards;
|
||||
if (!leaderboard)
|
||||
@ -784,24 +799,28 @@ static void rcheevos_client_copy_leaderboards(rcheevos_async_initialize_runtime_
|
||||
definition = runtime_data->game_data.leaderboards;
|
||||
for (i = 0; i < runtime_data->game_data.num_leaderboards; ++i, ++definition, ++leaderboard)
|
||||
{
|
||||
leaderboard->id = definition->id;
|
||||
leaderboard->title = strdup(definition->title);
|
||||
leaderboard->id = definition->id;
|
||||
leaderboard->title = strdup(definition->title);
|
||||
leaderboard->description = strdup(definition->description);
|
||||
leaderboard->mem = strdup(definition->definition);
|
||||
leaderboard->format = definition->format;
|
||||
leaderboard->mem = strdup(definition->definition);
|
||||
leaderboard->format = definition->format;
|
||||
}
|
||||
}
|
||||
|
||||
static void rcheevos_client_initialize_runtime_rich_presence(rcheevos_async_initialize_runtime_data_t* runtime_data)
|
||||
static void rcheevos_client_initialize_runtime_rich_presence(
|
||||
rcheevos_async_initialize_runtime_data_t* runtime_data)
|
||||
{
|
||||
if (runtime_data->game_data.rich_presence_script && *runtime_data->game_data.rich_presence_script)
|
||||
{
|
||||
rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
|
||||
|
||||
/* just activate the rich presence script now. it can't be toggled on or off,
|
||||
* so there's no reason to keep the unparsed version around any longer than
|
||||
* necessary, and we can avoid making a copy in the process. */
|
||||
int result = rc_runtime_activate_richpresence(&rcheevos_locals->runtime,
|
||||
/* Just activate the rich presence script now.
|
||||
* It can't be toggled on or off,
|
||||
* so there's no reason to keep the unparsed version
|
||||
* around any longer than necessary, and we can avoid
|
||||
* making a copy in the process. */
|
||||
int result = rc_runtime_activate_richpresence(
|
||||
&rcheevos_locals->runtime,
|
||||
runtime_data->game_data.rich_presence_script, NULL, 0);
|
||||
|
||||
if (result != RC_OK)
|
||||
@ -809,11 +828,12 @@ static void rcheevos_client_initialize_runtime_rich_presence(rcheevos_async_init
|
||||
const settings_t* settings = config_get_ptr();
|
||||
char buffer[256];
|
||||
snprintf(buffer, sizeof(buffer),
|
||||
"Could not activate rich presence: %s", rc_error_str(result));
|
||||
"Could not activate rich presence: %s",
|
||||
rc_error_str(result));
|
||||
|
||||
if (settings->bools.cheevos_verbose_enable)
|
||||
runloop_msg_queue_push(buffer, 0, 4 * 60, false, NULL,
|
||||
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||
|
||||
CHEEVOS_ERR(RCHEEVOS_TAG "%s\n", buffer);
|
||||
}
|
||||
@ -844,60 +864,76 @@ static void rcheevos_client_initialize_runtime_callback(void* userdata)
|
||||
free(runtime_data);
|
||||
}
|
||||
|
||||
static void rcheevos_async_fetch_user_unlocks_callback(struct rcheevos_async_io_request* request,
|
||||
http_transfer_data_t* data, char buffer[], size_t buffer_size)
|
||||
static void rcheevos_async_fetch_user_unlocks_callback(
|
||||
struct rcheevos_async_io_request* request,
|
||||
http_transfer_data_t* data, char buffer[], size_t buffer_size)
|
||||
{
|
||||
rcheevos_async_initialize_runtime_data_t* runtime_data = (rcheevos_async_initialize_runtime_data_t*)request->callback_data;
|
||||
rcheevos_async_initialize_runtime_data_t* runtime_data =
|
||||
(rcheevos_async_initialize_runtime_data_t*)request->callback_data;
|
||||
int result;
|
||||
|
||||
if (request->type == CHEEVOS_ASYNC_FETCH_HARDCORE_USER_UNLOCKS)
|
||||
{
|
||||
result = rc_api_process_fetch_user_unlocks_response(&runtime_data->hardcore_unlocks, data->data);
|
||||
rcheevos_async_succeeded(result, &runtime_data->hardcore_unlocks.response, buffer, buffer_size);
|
||||
result = rc_api_process_fetch_user_unlocks_response(
|
||||
&runtime_data->hardcore_unlocks, data->data);
|
||||
rcheevos_async_succeeded(result,
|
||||
&runtime_data->hardcore_unlocks.response,
|
||||
buffer, buffer_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = rc_api_process_fetch_user_unlocks_response(&runtime_data->non_hardcore_unlocks, data->data);
|
||||
rcheevos_async_succeeded(result, &runtime_data->non_hardcore_unlocks.response, buffer, buffer_size);
|
||||
result = rc_api_process_fetch_user_unlocks_response(
|
||||
&runtime_data->non_hardcore_unlocks, data->data);
|
||||
rcheevos_async_succeeded(result,
|
||||
&runtime_data->non_hardcore_unlocks.response,
|
||||
buffer, buffer_size);
|
||||
}
|
||||
}
|
||||
|
||||
static void rcheevos_async_fetch_game_data_callback(struct rcheevos_async_io_request* request,
|
||||
static void rcheevos_async_fetch_game_data_callback(
|
||||
struct rcheevos_async_io_request* request,
|
||||
http_transfer_data_t* data, char buffer[], size_t buffer_size)
|
||||
{
|
||||
rcheevos_async_initialize_runtime_data_t* runtime_data = (rcheevos_async_initialize_runtime_data_t*)request->callback_data;
|
||||
rcheevos_async_initialize_runtime_data_t* runtime_data =
|
||||
(rcheevos_async_initialize_runtime_data_t*)request->callback_data;
|
||||
|
||||
#ifdef CHEEVOS_SAVE_JSON
|
||||
filestream_write_file(CHEEVOS_SAVE_JSON, data->data, data->len);
|
||||
#endif
|
||||
|
||||
int result = rc_api_process_fetch_game_data_response(&runtime_data->game_data, data->data);
|
||||
int result = rc_api_process_fetch_game_data_response(
|
||||
&runtime_data->game_data, data->data);
|
||||
if (rcheevos_async_succeeded(result, &runtime_data->game_data.response, buffer, buffer_size))
|
||||
{
|
||||
rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
|
||||
rcheevos_locals->game.title = strdup(runtime_data->game_data.title);
|
||||
rcheevos_locals->game.console_id = runtime_data->game_data.console_id;
|
||||
rcheevos_locals->game.title = strdup(
|
||||
runtime_data->game_data.title);
|
||||
rcheevos_locals->game.console_id =
|
||||
runtime_data->game_data.console_id;
|
||||
}
|
||||
}
|
||||
|
||||
void rcheevos_client_initialize_runtime(unsigned game_id, rcheevos_client_callback callback, void* userdata)
|
||||
void rcheevos_client_initialize_runtime(unsigned game_id,
|
||||
rcheevos_client_callback callback, void* userdata)
|
||||
{
|
||||
rcheevos_async_io_request* request;
|
||||
const settings_t* settings = config_get_ptr();
|
||||
const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
|
||||
|
||||
rcheevos_async_initialize_runtime_data_t* data = (rcheevos_async_initialize_runtime_data_t*)
|
||||
const settings_t *settings = config_get_ptr();
|
||||
const rcheevos_locals_t *rcheevos_locals = get_rcheevos_locals();
|
||||
rcheevos_async_initialize_runtime_data_t *data =
|
||||
(rcheevos_async_initialize_runtime_data_t*)
|
||||
malloc(sizeof(rcheevos_async_initialize_runtime_data_t));
|
||||
|
||||
if (!data)
|
||||
{
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "Failed to allocate runtime initalization data\n");
|
||||
return;
|
||||
}
|
||||
|
||||
data->callback = callback;
|
||||
data->callback = callback;
|
||||
data->callback_data = userdata;
|
||||
request = (rcheevos_async_io_request*)
|
||||
calloc(1, sizeof(rcheevos_async_io_request));
|
||||
|
||||
request = (rcheevos_async_io_request*)calloc(1, sizeof(rcheevos_async_io_request));
|
||||
if (!request)
|
||||
{
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "Failed to allocate game data fetch request\n");
|
||||
@ -1012,14 +1048,15 @@ void rcheevos_client_initialize_runtime(unsigned game_id, rcheevos_client_callba
|
||||
* ping *
|
||||
****************************/
|
||||
|
||||
static retro_time_t rcheevos_client_prepare_ping(rcheevos_async_io_request* request)
|
||||
static retro_time_t rcheevos_client_prepare_ping(
|
||||
rcheevos_async_io_request* request)
|
||||
{
|
||||
const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
|
||||
const settings_t *settings = config_get_ptr();
|
||||
const bool cheevos_richpresence_enable =
|
||||
settings->bools.cheevos_richpresence_enable;
|
||||
rc_api_ping_request_t api_params;
|
||||
char buffer[256] = "";
|
||||
const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
|
||||
const settings_t *settings = config_get_ptr();
|
||||
const bool cheevos_richpresence_enable =
|
||||
settings->bools.cheevos_richpresence_enable;
|
||||
char buffer[256] = "";
|
||||
|
||||
memset(&api_params, 0, sizeof(api_params));
|
||||
api_params.username = rcheevos_locals->username;
|
||||
@ -1034,7 +1071,8 @@ static retro_time_t rcheevos_client_prepare_ping(rcheevos_async_io_request* requ
|
||||
|
||||
rc_api_init_ping_request(&request->request, &api_params);
|
||||
|
||||
rcheevos_log_post_url(request->request.url, request->request.post_data);
|
||||
rcheevos_log_post_url(request->request.url,
|
||||
request->request.post_data);
|
||||
|
||||
#ifdef HAVE_DISCORD
|
||||
if (settings->bools.discord_enable && discord_is_ready())
|
||||
@ -1060,7 +1098,8 @@ static void rcheevos_async_ping_handler(retro_task_t* task)
|
||||
/* game changed; stop the recurring task - a new one will
|
||||
* be scheduled if a new game is loaded */
|
||||
task_set_finished(task, 1);
|
||||
/* request->request was destroyed in rcheevos_async_http_task_callback */
|
||||
/* request->request was destroyed
|
||||
* in rcheevos_async_http_task_callback */
|
||||
free(request);
|
||||
return;
|
||||
}
|
||||
@ -1075,18 +1114,20 @@ static void rcheevos_async_ping_handler(retro_task_t* task)
|
||||
rcheevos_async_http_task_callback, request);
|
||||
}
|
||||
|
||||
|
||||
/****************************
|
||||
* start session *
|
||||
****************************/
|
||||
|
||||
static void rcheevos_async_start_session_callback(struct rcheevos_async_io_request* request,
|
||||
http_transfer_data_t* data, char buffer[], size_t buffer_size)
|
||||
static void rcheevos_async_start_session_callback(
|
||||
struct rcheevos_async_io_request* request,
|
||||
http_transfer_data_t* data, char buffer[], size_t buffer_size)
|
||||
{
|
||||
rc_api_start_session_response_t api_response;
|
||||
|
||||
int result = rc_api_process_start_session_response(&api_response, data->data);
|
||||
rcheevos_async_succeeded(result, &api_response.response, buffer, buffer_size);
|
||||
int result = rc_api_process_start_session_response(
|
||||
&api_response, data->data);
|
||||
rcheevos_async_succeeded(result,
|
||||
&api_response.response, buffer, buffer_size);
|
||||
rc_api_destroy_start_session_response(&api_response);
|
||||
}
|
||||
|
||||
@ -1106,7 +1147,8 @@ void rcheevos_client_start_session(unsigned game_id)
|
||||
calloc(1, sizeof(rcheevos_async_io_request));
|
||||
if (!request)
|
||||
{
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "Failed to allocate rich presence request\n");
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG
|
||||
"Failed to allocate rich presence request\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1133,7 +1175,8 @@ void rcheevos_client_start_session(unsigned game_id)
|
||||
calloc(1, sizeof(rcheevos_async_io_request));
|
||||
if (!request)
|
||||
{
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "Failed to allocate new session request\n");
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG
|
||||
"Failed to allocate new session request\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1144,7 +1187,8 @@ void rcheevos_client_start_session(unsigned game_id)
|
||||
api_params.api_token = rcheevos_locals->token;
|
||||
api_params.game_id = game_id;
|
||||
|
||||
rc_api_init_start_session_request(&request->request, &api_params);
|
||||
rc_api_init_start_session_request(
|
||||
&request->request, &api_params);
|
||||
|
||||
rcheevos_async_begin_request(request,
|
||||
rcheevos_async_start_session_callback,
|
||||
@ -1173,7 +1217,8 @@ typedef struct rcheevos_fetch_badge_state
|
||||
const char* badge_directory;
|
||||
rcheevos_client_callback callback;
|
||||
void* callback_data;
|
||||
char requested_badges[RCHEEVOS_CONCURRENT_BADGE_DOWNLOADS][32];
|
||||
char requested_badges[
|
||||
RCHEEVOS_CONCURRENT_BADGE_DOWNLOADS][32];
|
||||
} rcheevos_fetch_badge_state;
|
||||
|
||||
typedef struct rcheevos_fetch_badge_data
|
||||
@ -1196,7 +1241,8 @@ static void rcheevos_end_fetch_badges(rcheevos_fetch_badge_state* state)
|
||||
|
||||
static void rcheevos_async_download_next_badge(void* userdata)
|
||||
{
|
||||
rcheevos_fetch_badge_data* badge_data = (rcheevos_fetch_badge_data*)userdata;
|
||||
rcheevos_fetch_badge_data* badge_data =
|
||||
(rcheevos_fetch_badge_data*)userdata;
|
||||
rcheevos_fetch_next_badge(badge_data->state);
|
||||
|
||||
if (rcheevos_end_load_state() == 0)
|
||||
@ -1205,40 +1251,49 @@ static void rcheevos_async_download_next_badge(void* userdata)
|
||||
free(badge_data);
|
||||
}
|
||||
|
||||
static void rcheevos_async_fetch_badge_callback(struct rcheevos_async_io_request* request,
|
||||
http_transfer_data_t* data, char buffer[], size_t buffer_size)
|
||||
static void rcheevos_async_fetch_badge_callback(
|
||||
struct rcheevos_async_io_request* request,
|
||||
http_transfer_data_t* data, char buffer[], size_t buffer_size)
|
||||
{
|
||||
rcheevos_fetch_badge_data* badge_data = (rcheevos_fetch_badge_data*)request->callback_data;
|
||||
const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
|
||||
char badge_fullpath[PATH_MAX_LENGTH];
|
||||
rcheevos_fetch_badge_data* badge_data =
|
||||
(rcheevos_fetch_badge_data*)request->callback_data;
|
||||
const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
|
||||
|
||||
fill_pathname_join(badge_fullpath, badge_data->state->badge_directory,
|
||||
badge_data->state->requested_badges[badge_data->request_index], sizeof(badge_fullpath));
|
||||
badge_data->state->requested_badges[badge_data->request_index],
|
||||
sizeof(badge_fullpath));
|
||||
|
||||
if (!filestream_write_file(badge_fullpath, data->data, data->len))
|
||||
CHEEVOS_ERR(RCHEEVOS_TAG "Error writing badge %s\n", badge_fullpath);
|
||||
CHEEVOS_ERR(RCHEEVOS_TAG "Error writing badge %s\n",
|
||||
badge_fullpath);
|
||||
|
||||
CHEEVOS_LOCK(rcheevos_locals->load_info.request_lock);
|
||||
badge_data->state->requested_badges[badge_data->request_index][0] = '\0';
|
||||
CHEEVOS_UNLOCK(rcheevos_locals->load_info.request_lock);
|
||||
}
|
||||
|
||||
static bool rcheevos_client_fetch_badge(const char* badge_name, int locked, rcheevos_fetch_badge_state* state)
|
||||
static bool rcheevos_client_fetch_badge(
|
||||
const char* badge_name, int locked,
|
||||
rcheevos_fetch_badge_state* state)
|
||||
{
|
||||
char badge_fullpath[PATH_MAX_LENGTH];
|
||||
char* badge_fullname = NULL;
|
||||
char* badge_fullname = NULL;
|
||||
size_t badge_fullname_size = 0;
|
||||
int request_index = -1;
|
||||
int request_index = -1;
|
||||
|
||||
if (!badge_name || !badge_name[0])
|
||||
return false;
|
||||
|
||||
strlcpy(badge_fullpath, state->badge_directory, sizeof(badge_fullpath));
|
||||
strlcpy(badge_fullpath,
|
||||
state->badge_directory, sizeof(badge_fullpath));
|
||||
fill_pathname_slash(badge_fullpath, sizeof(badge_fullpath));
|
||||
badge_fullname = badge_fullpath + strlen(state->badge_directory);
|
||||
badge_fullname_size = sizeof(badge_fullpath) - (badge_fullname - badge_fullpath);
|
||||
badge_fullname = badge_fullpath + strlen(state->badge_directory);
|
||||
badge_fullname_size = sizeof(badge_fullpath) -
|
||||
(badge_fullname - badge_fullpath);
|
||||
|
||||
snprintf(badge_fullname, badge_fullname_size, "%s%s" FILE_PATH_PNG_EXTENSION,
|
||||
snprintf(badge_fullname,
|
||||
badge_fullname_size, "%s%s" FILE_PATH_PNG_EXTENSION,
|
||||
badge_name, locked ? "_lock" : "");
|
||||
|
||||
/* check if it's already available */
|
||||
@ -1255,10 +1310,9 @@ static bool rcheevos_client_fetch_badge(const char* badge_name, int locked, rche
|
||||
for (i = RCHEEVOS_CONCURRENT_BADGE_DOWNLOADS - 1; i >= 0; --i)
|
||||
{
|
||||
if (!state->requested_badges[i][0])
|
||||
{
|
||||
request_index = i;
|
||||
}
|
||||
else if (string_is_equal(badge_fullname, state->requested_badges[i]))
|
||||
else if (string_is_equal(badge_fullname,
|
||||
state->requested_badges[i]))
|
||||
{
|
||||
found_index = i;
|
||||
break;
|
||||
@ -1267,15 +1321,15 @@ static bool rcheevos_client_fetch_badge(const char* badge_name, int locked, rche
|
||||
|
||||
if (found_index == -1)
|
||||
{
|
||||
/* unexpected - but if it happens,
|
||||
* the queue is full. Pretend we found
|
||||
* a match to prevent an exception */
|
||||
if (request_index == -1)
|
||||
{
|
||||
/* unexpected - but if it happens, the queue is full. pretend we found a match to prevent an exception */
|
||||
found_index = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
strlcpy(state->requested_badges[request_index], badge_fullname, sizeof(state->requested_badges[request_index]));
|
||||
}
|
||||
strlcpy(state->requested_badges[request_index],
|
||||
badge_fullname,
|
||||
sizeof(state->requested_badges[request_index]));
|
||||
}
|
||||
CHEEVOS_UNLOCK(rcheevos_locals->load_info.request_lock);
|
||||
|
||||
@ -1296,7 +1350,8 @@ static bool rcheevos_client_fetch_badge(const char* badge_name, int locked, rche
|
||||
|
||||
if (!request || !data)
|
||||
{
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "Failed to allocate fetch badge request\n");
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG
|
||||
"Failed to allocate fetch badge request\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1304,14 +1359,16 @@ static bool rcheevos_client_fetch_badge(const char* badge_name, int locked, rche
|
||||
|
||||
memset(&api_params, 0, sizeof(api_params));
|
||||
api_params.image_name = badge_name;
|
||||
api_params.image_type = locked ? RC_IMAGE_TYPE_ACHIEVEMENT_LOCKED : RC_IMAGE_TYPE_ACHIEVEMENT;
|
||||
api_params.image_type = locked
|
||||
? RC_IMAGE_TYPE_ACHIEVEMENT_LOCKED
|
||||
: RC_IMAGE_TYPE_ACHIEVEMENT;
|
||||
|
||||
rc_api_init_fetch_image_request(&request->request, &api_params);
|
||||
|
||||
data->state = state;
|
||||
data->request_index = request_index;
|
||||
data->state = state;
|
||||
data->request_index = request_index;
|
||||
|
||||
request->callback = rcheevos_async_download_next_badge;
|
||||
request->callback = rcheevos_async_download_next_badge;
|
||||
request->callback_data = data;
|
||||
|
||||
rcheevos_begin_load_state(RCHEEVOS_LOAD_STATE_FETCHING_BADGES);
|
||||
@ -1341,7 +1398,8 @@ static bool rcheevos_fetch_next_badge(rcheevos_fetch_badge_state* state)
|
||||
do
|
||||
{
|
||||
CHEEVOS_LOCK(rcheevos_locals->load_info.request_lock);
|
||||
if (state->locked_badge_fetch_index < rcheevos_locals->game.achievement_count)
|
||||
if ( state->locked_badge_fetch_index
|
||||
< rcheevos_locals->game.achievement_count)
|
||||
cheevo = &rcheevos_locals->game.achievements[state->locked_badge_fetch_index++];
|
||||
else
|
||||
cheevo = NULL;
|
||||
@ -1350,7 +1408,8 @@ static bool rcheevos_fetch_next_badge(rcheevos_fetch_badge_state* state)
|
||||
if (!cheevo)
|
||||
break;
|
||||
|
||||
active = (cheevo->active & (RCHEEVOS_ACTIVE_HARDCORE | RCHEEVOS_ACTIVE_SOFTCORE));
|
||||
active = (cheevo->active
|
||||
& (RCHEEVOS_ACTIVE_HARDCORE | RCHEEVOS_ACTIVE_SOFTCORE));
|
||||
if (rcheevos_client_fetch_badge(cheevo->badge, active, state))
|
||||
return true;
|
||||
|
||||
@ -1364,6 +1423,7 @@ static bool rcheevos_fetch_next_badge(rcheevos_fetch_badge_state* state)
|
||||
cheevo = &rcheevos_locals->game.achievements[state->badge_fetch_index++];
|
||||
else
|
||||
cheevo = NULL;
|
||||
|
||||
CHEEVOS_UNLOCK(rcheevos_locals->load_info.request_lock);
|
||||
|
||||
if (!cheevo)
|
||||
@ -1381,21 +1441,24 @@ static bool rcheevos_fetch_next_badge(rcheevos_fetch_badge_state* state)
|
||||
void rcheevos_client_fetch_badges(rcheevos_client_callback callback, void* userdata)
|
||||
{
|
||||
#if defined(HAVE_MENU) || defined(HAVE_GFX_WIDGETS) /* don't need badges unless menu or widgets are enabled */
|
||||
rcheevos_fetch_badge_state* state = NULL;
|
||||
char badge_fullpath[PATH_MAX_LENGTH] = "";
|
||||
#if !defined(HAVE_GFX_WIDGETS) /* we always want badges if widgets are enabled */
|
||||
settings_t* settings = config_get_ptr();
|
||||
if (!settings->bools.cheevos_badges_enable) /* user has explicitly disabled badges */
|
||||
#if !defined(HAVE_GFX_WIDGETS) /* we always want badges if widgets are enabled */
|
||||
settings_t* settings = config_get_ptr();
|
||||
/* User has explicitly disabled badges */
|
||||
if (!settings->bools.cheevos_badges_enable)
|
||||
return;
|
||||
|
||||
/* badges are only needed for xmb and ozone menus */
|
||||
if (!string_is_equal(settings->arrays.menu_driver, "xmb") &&
|
||||
!string_is_equal(settings->arrays.menu_driver, "ozone"))
|
||||
!string_is_equal(settings->arrays.menu_driver, "ozone"))
|
||||
return;
|
||||
#endif /* !defined(HAVE_GFX_WIDGETS) */
|
||||
#endif /* !defined(HAVE_GFX_WIDGETS) */
|
||||
|
||||
/* make sure the directory exists */
|
||||
fill_pathname_application_special(badge_fullpath, sizeof(badge_fullpath),
|
||||
APPLICATION_SPECIAL_DIRECTORY_THUMBNAILS_CHEEVOS_BADGES);
|
||||
fill_pathname_application_special(badge_fullpath,
|
||||
sizeof(badge_fullpath),
|
||||
APPLICATION_SPECIAL_DIRECTORY_THUMBNAILS_CHEEVOS_BADGES);
|
||||
|
||||
if (!path_is_directory(badge_fullpath))
|
||||
{
|
||||
@ -1404,8 +1467,9 @@ void rcheevos_client_fetch_badges(rcheevos_client_callback callback, void* userd
|
||||
}
|
||||
|
||||
/* start the download task */
|
||||
rcheevos_fetch_badge_state* state = (rcheevos_fetch_badge_state*)
|
||||
state = (rcheevos_fetch_badge_state*)
|
||||
calloc(1, sizeof(rcheevos_fetch_badge_state));
|
||||
|
||||
if (!state)
|
||||
{
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "Failed to allocate fetch badge state\n");
|
||||
@ -1446,19 +1510,20 @@ void rcheevos_client_fetch_badges(rcheevos_client_callback callback, void* userd
|
||||
* award achievement *
|
||||
****************************/
|
||||
|
||||
static void rcheevos_async_award_achievement_callback(struct rcheevos_async_io_request* request,
|
||||
static void rcheevos_async_award_achievement_callback(
|
||||
struct rcheevos_async_io_request* request,
|
||||
http_transfer_data_t *data, char buffer[], size_t buffer_size)
|
||||
{
|
||||
rc_api_award_achievement_response_t api_response;
|
||||
|
||||
int result = rc_api_process_award_achievement_response(&api_response, data->data);
|
||||
if (rcheevos_async_succeeded(result, &api_response.response, buffer, buffer_size))
|
||||
int result = rc_api_process_award_achievement_response(
|
||||
&api_response, data->data);
|
||||
if (rcheevos_async_succeeded(result, &api_response.response,
|
||||
buffer, buffer_size))
|
||||
{
|
||||
if (api_response.awarded_achievement_id != request->id)
|
||||
{
|
||||
snprintf(buffer, buffer_size, "Achievement %u awarded instead",
|
||||
api_response.awarded_achievement_id);
|
||||
}
|
||||
else if (api_response.response.error_message)
|
||||
{
|
||||
/* previously unlocked achievements are returned as a "successful" error */
|
||||
@ -1481,8 +1546,8 @@ void rcheevos_client_award_achievement(unsigned achievement_id)
|
||||
}
|
||||
else
|
||||
{
|
||||
const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
|
||||
rc_api_award_achievement_request_t api_params;
|
||||
const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
|
||||
|
||||
memset(&api_params, 0, sizeof(api_params));
|
||||
api_params.username = rcheevos_locals->username;
|
||||
@ -1491,7 +1556,8 @@ void rcheevos_client_award_achievement(unsigned achievement_id)
|
||||
api_params.hardcore = rcheevos_locals->hardcore_active ? 1 : 0;
|
||||
api_params.game_hash = rcheevos_locals->game.hash;
|
||||
|
||||
rc_api_init_award_achievement_request(&request->request, &api_params);
|
||||
rc_api_init_award_achievement_request(&request->request,
|
||||
&api_params);
|
||||
|
||||
rcheevos_async_begin_request(request,
|
||||
rcheevos_async_award_achievement_callback,
|
||||
@ -1506,28 +1572,30 @@ void rcheevos_client_award_achievement(unsigned achievement_id)
|
||||
* submit leaderboard *
|
||||
****************************/
|
||||
|
||||
static void rcheevos_async_submit_lboard_entry_callback(struct rcheevos_async_io_request* request,
|
||||
static void rcheevos_async_submit_lboard_entry_callback(
|
||||
struct rcheevos_async_io_request* request,
|
||||
http_transfer_data_t* data, char buffer[], size_t buffer_size)
|
||||
{
|
||||
rc_api_submit_lboard_entry_response_t api_response;
|
||||
int result = rc_api_process_submit_lboard_entry_response(
|
||||
&api_response, data->data);
|
||||
|
||||
int result = rc_api_process_submit_lboard_entry_response(&api_response, data->data);
|
||||
|
||||
if (rcheevos_async_succeeded(result, &api_response.response, buffer, buffer_size))
|
||||
{
|
||||
/* not currently doing anything with the response */
|
||||
}
|
||||
/* not currently doing anything with the response */
|
||||
if (rcheevos_async_succeeded(result, &api_response.response, buffer,
|
||||
buffer_size)) { }
|
||||
|
||||
rc_api_destroy_submit_lboard_entry_response(&api_response);
|
||||
}
|
||||
|
||||
void rcheevos_client_submit_lboard_entry(unsigned leaderboard_id, int value)
|
||||
void rcheevos_client_submit_lboard_entry(unsigned leaderboard_id,
|
||||
int value)
|
||||
{
|
||||
rcheevos_async_io_request *request = (rcheevos_async_io_request*)
|
||||
calloc(1, sizeof(rcheevos_async_io_request));
|
||||
if (!request)
|
||||
{
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "Failed to allocate request for lboard %u submit\n",
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG
|
||||
"Failed to allocate request for lboard %u submit\n",
|
||||
leaderboard_id);
|
||||
}
|
||||
else
|
||||
@ -1542,7 +1610,8 @@ void rcheevos_client_submit_lboard_entry(unsigned leaderboard_id, int value)
|
||||
api_params.score = value;
|
||||
api_params.game_hash = rcheevos_locals->game.hash;
|
||||
|
||||
rc_api_init_submit_lboard_entry_request(&request->request, &api_params);
|
||||
rc_api_init_submit_lboard_entry_request(&request->request,
|
||||
&api_params);
|
||||
|
||||
rcheevos_async_begin_request(request,
|
||||
rcheevos_async_submit_lboard_entry_callback,
|
||||
@ -1551,4 +1620,3 @@ void rcheevos_client_submit_lboard_entry(unsigned leaderboard_id, int value)
|
||||
"Error submitting leaderboard");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,15 +115,11 @@ bool rcheevos_menu_get_state(unsigned menu_offset, char *buffer, size_t len)
|
||||
if (cheevo)
|
||||
{
|
||||
if (cheevo->menu_progress)
|
||||
{
|
||||
snprintf(buffer, len, "%s - %d%%",
|
||||
msg_hash_to_str(menuitem->state_label_idx),
|
||||
cheevo->menu_progress);
|
||||
}
|
||||
else
|
||||
{
|
||||
strlcpy(buffer, msg_hash_to_str(menuitem->state_label_idx), len);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -183,9 +179,7 @@ static rcheevos_menuitem_t* rcheevos_menu_allocate(
|
||||
rcheevos_locals->menuitem_capacity * sizeof(rcheevos_menuitem_t));
|
||||
|
||||
if (new_menuitems)
|
||||
{
|
||||
rcheevos_locals->menuitems = new_menuitems;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* realloc failed */
|
||||
@ -353,9 +347,7 @@ static void rcheevos_menu_append_items(rcheevos_locals_t* rcheevos_locals,
|
||||
|
||||
if (cheevo->badge && cheevo->badge[0] && settings &&
|
||||
settings->bools.cheevos_badges_enable)
|
||||
{
|
||||
rcheevos_menu_update_badge(cheevo);
|
||||
}
|
||||
}
|
||||
|
||||
++cheevo;
|
||||
@ -467,7 +459,7 @@ void rcheevos_menu_populate(void* data)
|
||||
|
||||
/* count items in each bucket */
|
||||
cheevo = rcheevos_locals->game.achievements;
|
||||
stop = cheevo + rcheevos_locals->game.achievement_count;
|
||||
stop = cheevo + rcheevos_locals->game.achievement_count;
|
||||
|
||||
while (cheevo < stop)
|
||||
{
|
||||
@ -480,9 +472,7 @@ void rcheevos_menu_populate(void* data)
|
||||
++num_recently_unlocked;
|
||||
}
|
||||
else
|
||||
{
|
||||
++num_unlocked;
|
||||
}
|
||||
break;
|
||||
|
||||
case RCHEEVOS_MENUITEM_BUCKET_LOCKED:
|
||||
@ -555,10 +545,8 @@ void rcheevos_menu_populate(void* data)
|
||||
if (num_locked)
|
||||
{
|
||||
if (rcheevos_locals->menuitem_count > 0)
|
||||
{
|
||||
rcheevos_menu_append_header(rcheevos_locals,
|
||||
MENU_ENUM_LABEL_VALUE_CHEEVOS_LOCKED_ENTRY);
|
||||
}
|
||||
|
||||
rcheevos_menu_append_items(rcheevos_locals,
|
||||
RCHEEVOS_MENUITEM_BUCKET_LOCKED);
|
||||
@ -570,10 +558,8 @@ void rcheevos_menu_populate(void* data)
|
||||
if (num_unsupported)
|
||||
{
|
||||
if (rcheevos_locals->menuitem_count > 0)
|
||||
{
|
||||
rcheevos_menu_append_header(rcheevos_locals,
|
||||
MENU_ENUM_LABEL_VALUE_CHEEVOS_UNSUPPORTED_ENTRY);
|
||||
}
|
||||
|
||||
rcheevos_menu_append_items(rcheevos_locals,
|
||||
RCHEEVOS_MENUITEM_BUCKET_UNSUPPORTED);
|
||||
@ -583,10 +569,8 @@ void rcheevos_menu_populate(void* data)
|
||||
if (num_unlocked)
|
||||
{
|
||||
if (rcheevos_locals->menuitem_count > 0)
|
||||
{
|
||||
rcheevos_menu_append_header(rcheevos_locals,
|
||||
MENU_ENUM_LABEL_VALUE_CHEEVOS_UNLOCKED_ENTRY);
|
||||
}
|
||||
|
||||
rcheevos_menu_append_items(rcheevos_locals,
|
||||
RCHEEVOS_MENUITEM_BUCKET_UNLOCKED);
|
||||
@ -594,21 +578,20 @@ void rcheevos_menu_populate(void* data)
|
||||
|
||||
if (rcheevos_locals->menuitem_count > 0)
|
||||
{
|
||||
/* convert to menu entries */
|
||||
rcheevos_menuitem_t* menuitem = rcheevos_locals->menuitems;
|
||||
rcheevos_menuitem_t* stop = menuitem + rcheevos_locals->menuitem_count;
|
||||
char buffer[128];
|
||||
unsigned idx = 0;
|
||||
/* convert to menu entries */
|
||||
rcheevos_menuitem_t* menuitem = rcheevos_locals->menuitems;
|
||||
rcheevos_menuitem_t* stop = menuitem +
|
||||
rcheevos_locals->menuitem_count;
|
||||
|
||||
do
|
||||
{
|
||||
if (menuitem->cheevo)
|
||||
{
|
||||
menu_entries_append_enum(info->list, menuitem->cheevo->title,
|
||||
menuitem->cheevo->description,
|
||||
MENU_ENUM_LABEL_CHEEVOS_LOCKED_ENTRY,
|
||||
MENU_SETTINGS_CHEEVOS_START + idx, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(buffer, sizeof(buffer), "----- %s -----",
|
||||
@ -627,45 +610,35 @@ void rcheevos_menu_populate(void* data)
|
||||
{
|
||||
/* no achievements found */
|
||||
if (!rcheevos_locals->core_supports)
|
||||
{
|
||||
menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CANNOT_ACTIVATE_ACHIEVEMENTS_WITH_THIS_CORE),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_CANNOT_ACTIVATE_ACHIEVEMENTS_WITH_THIS_CORE),
|
||||
MENU_ENUM_LABEL_CANNOT_ACTIVATE_ACHIEVEMENTS_WITH_THIS_CORE,
|
||||
FILE_TYPE_NONE, 0, 0);
|
||||
}
|
||||
else if (rcheevos_locals->load_info.state == RCHEEVOS_LOAD_STATE_NETWORK_ERROR)
|
||||
{
|
||||
menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NETWORK_ERROR),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_NETWORK_ERROR),
|
||||
MENU_ENUM_LABEL_NETWORK_ERROR,
|
||||
FILE_TYPE_NONE, 0, 0);
|
||||
}
|
||||
else if (!rcheevos_locals->game.id)
|
||||
{
|
||||
menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_UNKNOWN_GAME),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_UNKNOWN_GAME),
|
||||
MENU_ENUM_LABEL_UNKNOWN_GAME,
|
||||
FILE_TYPE_NONE, 0, 0);
|
||||
}
|
||||
else if (!rcheevos_locals->token[0])
|
||||
{
|
||||
menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_LOGGED_IN),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_NOT_LOGGED_IN),
|
||||
MENU_ENUM_LABEL_NOT_LOGGED_IN,
|
||||
FILE_TYPE_NONE, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ACHIEVEMENTS_TO_DISPLAY),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_NO_ACHIEVEMENTS_TO_DISPLAY),
|
||||
MENU_ENUM_LABEL_NO_ACHIEVEMENTS_TO_DISPLAY,
|
||||
FILE_TYPE_NONE, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -688,10 +661,7 @@ uintptr_t rcheevos_get_badge_texture(const char *badge, bool locked)
|
||||
|
||||
if (!gfx_display_reset_textures_list(badge_file, fullpath,
|
||||
&tex, TEXTURE_FILTER_MIPMAP_LINEAR, NULL, NULL))
|
||||
{
|
||||
tex = 0;
|
||||
}
|
||||
return 0;
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user