Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 48 additions & 18 deletions cheevos/cheevos.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,9 @@ static rcheevos_locals_t rcheevos_locals =
true, /* hardcore_allowed */
false,/* hardcore_requires_reload */
false,/* hardcore_being_enabled */
true /* core_supports */
true, /* core_supports */
false,/* badges_loaded */
false /* badges_loading */
};

rcheevos_locals_t* get_rcheevos_locals(void)
Expand Down Expand Up @@ -227,25 +229,24 @@ bool rcheevos_is_pause_allowed(void)
return rc_client_can_pause(rcheevos_locals.client, NULL);
}

static void rcheevos_show_mastery_placard(void)
static void rcheevos_show_completion_placard(const char* title, const char* badge_name)
{
const settings_t* settings = config_get_ptr();
if (settings->bools.cheevos_visibility_mastery)
{
const rc_client_game_t* game = rc_client_get_game_info(rcheevos_locals.client);
char title[256];
size_t _len = snprintf(title, sizeof(title),
char message[256];
size_t _len = snprintf(message, sizeof(message),
msg_hash_to_str(rc_client_get_hardcore_enabled(rcheevos_locals.client)
? MSG_CHEEVOS_MASTERED_GAME
: MSG_CHEEVOS_COMPLETED_GAME),
game->title);
title[sizeof(title) - 1] = '\0';
title);
message[sizeof(message) - 1] = '\0';

#if defined (HAVE_GFX_WIDGETS)
if (gfx_widgets_ready())
{
char msg[128];
char badge_name[32];
char badge[32];
const char* displayname = rc_client_get_user_info(rcheevos_locals.client)->display_name;
const bool content_runtime_log = settings->bools.content_runtime_log;
const bool content_runtime_log_aggr = settings->bools.content_runtime_log_aggregate;
Expand Down Expand Up @@ -276,9 +277,10 @@ static void rcheevos_show_mastery_placard(void)
}
}

__len = strlcpy(badge_name, "i", sizeof(badge_name));
strlcpy(badge_name + __len, game->badge_name, sizeof(badge_name) - __len);
gfx_widgets_push_achievement(title, msg, badge_name);
/* badge image = "iBADGENAME" */
badge[0] = 'i';
strlcpy(&badge[1], badge_name, sizeof(badge) - 1);
gfx_widgets_push_achievement(title, msg, badge);
}
else
#endif
Expand All @@ -287,6 +289,22 @@ static void rcheevos_show_mastery_placard(void)
}
}

static void rcheevos_show_mastery_placard(void)
{
const rc_client_game_t* game = rc_client_get_game_info(rcheevos_locals.client);
rcheevos_show_completion_placard(game->title, game->badge_name);
}

static void rcheevos_show_subset_completion_placard(const rc_client_subset_t* subset)
{
char badge[32];
badge[0] = 'i';
strlcpy(&badge[1], subset->badge_name, sizeof(badge) - 1);
rcheevos_client_download_badge_from_url(subset->badge_url, badge);

rcheevos_show_completion_placard(subset->title, subset->badge_name);
}

static void rcheevos_award_achievement(const rc_client_achievement_t* cheevo)
{
const settings_t* settings = config_get_ptr();
Expand Down Expand Up @@ -588,6 +606,9 @@ static void rcheevos_client_event_handler(const rc_client_event_t* event, rc_cli
case RC_CLIENT_EVENT_GAME_COMPLETED:
rcheevos_show_mastery_placard();
break;
case RC_CLIENT_EVENT_SUBSET_COMPLETED:
rcheevos_show_subset_completion_placard(event->subset);
break;
case RC_CLIENT_EVENT_SERVER_ERROR:
rcheevos_server_error(event->server_error->api, event->server_error->error_message);
break;
Expand Down Expand Up @@ -703,6 +724,8 @@ bool rcheevos_unload(void)

if (was_loaded)
{
rcheevos_locals.badges_loaded = rcheevos_locals.badges_loading = false;

#ifdef HAVE_MENU
rcheevos_menu_reset_badges();

Expand Down Expand Up @@ -1268,9 +1291,8 @@ static void rcheevos_show_game_placard(void)
if (gfx_widgets_ready())
{
char badge_name[32];
size_t __len = strlcpy(badge_name, "i", sizeof(badge_name));
strlcpy(badge_name + __len, game->badge_name,
sizeof(badge_name) - __len);
badge_name[0] = 'i';
strlcpy(&badge_name[1], game->badge_name, sizeof(badge_name) - 1);
gfx_widgets_push_achievement(game->title, msg, badge_name);
}
else
Expand Down Expand Up @@ -1406,13 +1428,21 @@ static void rcheevos_finalize_game_load(rc_client_t* client)
settings_t* settings = config_get_ptr();
bool want_badges = settings->bools.cheevos_badges_enable;
#if !defined(HAVE_GFX_WIDGETS)
/* Then badges are only needed for xmb and ozone menus */
/* Then badges are only needed for xmb, ozone, and rgui menus */
want_badges = want_badges &&
( string_is_equal(settings->arrays.menu_driver, "xmb")
|| string_is_equal(settings->arrays.menu_driver, "ozone"));
|| string_is_equal(settings->arrays.menu_driver, "ozone")
|| string_is_equal(settings->arrays.menu_driver, "rgui"));
#endif
if (want_badges)
rcheevos_client_download_achievement_badges(client);
if (want_badges) /* prefetch the game badge */
{
const rc_client_game_t* game = rc_client_get_game_info(client);
char badge[32];

badge[0] = 'i';
strlcpy(&badge[1], game->badge_name, sizeof(badge) - 1);
rcheevos_client_download_badge_from_url(game->badge_url, badge);
}

if (!rc_client_is_processing_required(client))
{
Expand Down
53 changes: 35 additions & 18 deletions cheevos/cheevos_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@
#include "../network/presence.h"
#endif

#ifdef HAVE_MENU
#include "cheevos_menu.h"
#include "../menu/menu_driver.h"
#endif

#include "../deps/rcheevos/include/rc_api_runtime.h"
#include "../deps/rcheevos/include/rc_api_user.h"

Expand Down Expand Up @@ -405,6 +410,12 @@ static void rcheevos_client_download_task_callback(retro_task_t* task,
{
CHEEVOS_LOG(RCHEEVOS_TAG "Error writing %s\n", callback_data->badge_fullpath);
}
#ifdef HAVE_MENU
else
{
rcheevos_menu_update_badge_references(callback_data->badge_name);
}
#endif

if (callback_data->queue)
{
Expand Down Expand Up @@ -490,7 +501,15 @@ static void rcheevos_client_fetch_next_badge(rc_client_download_queue_t* queue)
#endif
/* if the game is no longer loaded, stop processing the queue */
if (queue->game != rc_client_get_game_info(queue->client))
queue->pass = 2;
queue->pass = 3;

#ifdef HAVE_MENU
if (!(menu_state_get_ptr()->flags & MENU_ST_FLAG_ALIVE))
{
/* menu is no longer open, stop processing the queue so we don't interrupt emulation */
queue->pass = 3;
}
#endif

while (queue->pass < 2)
{
Expand All @@ -514,19 +533,19 @@ static void rcheevos_client_fetch_next_badge(rc_client_download_queue_t* queue)
if (!achievement->badge_name[0])
continue;

if (queue->pass == 0)
if (queue->pass == 1)
{
/* First pass - get all unlocked badges */
/* Second pass - get all unlocked badges */
url = achievement->badge_url;
next_badge = achievement->badge_name;
}
/* Second pass - don't need locked badge for
/* First pass - don't need locked badge for
* achievement player has already unlocked */
else if (achievement->unlock_time)
continue;
else
{
/* Second pass - get locked badge */
/* First pass - get locked badge */
url = achievement->badge_locked_url;
snprintf(badge_name, sizeof(badge_name), "%s_lock", achievement->badge_name);
next_badge = badge_name;
Expand All @@ -538,7 +557,15 @@ static void rcheevos_client_fetch_next_badge(rc_client_download_queue_t* queue)
if (!next_badge)
{
if (--queue->outstanding_requests == 0)
done = true;
{
if (queue->pass == 2)
{
/* all badges successfully loaded */
get_rcheevos_locals()->badges_loaded = true;
}

done = true; /* destroy queue */
}
}

#ifdef HAVE_THREADS
Expand All @@ -564,6 +591,8 @@ static void rcheevos_client_fetch_next_badge(rc_client_download_queue_t* queue)
}
rc_client_destroy_achievement_list(queue->list);

get_rcheevos_locals()->badges_loading = false;

#ifdef HAVE_THREADS
slock_free(queue->lock);
#endif
Expand All @@ -580,18 +609,6 @@ void rcheevos_client_download_placeholder_badge(void)
rcheevos_client_download_badge(NULL, url, "00000");
}

void rcheevos_client_download_game_badge(const rc_client_game_t* game)
{
char url[256] = "";
char badge_name[16];

if (game && rc_client_game_get_image_url(game, url, sizeof(url)) == RC_OK)
{
snprintf(badge_name, sizeof(badge_name), "i%s", game->badge_name);
rcheevos_client_download_badge(NULL, url, badge_name);
}
}

void rcheevos_client_download_achievement_badges(rc_client_t* client)
{
size_t i;
Expand Down
1 change: 0 additions & 1 deletion cheevos/cheevos_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
RETRO_BEGIN_DECLS

void rcheevos_client_download_placeholder_badge(void);
void rcheevos_client_download_game_badge(const rc_client_game_t* game);
void rcheevos_client_download_achievement_badges(rc_client_t* client);
void rcheevos_client_download_badge_from_url(const char* url, const char* badge_name);

Expand Down
2 changes: 2 additions & 0 deletions cheevos/cheevos_locals.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ typedef struct rcheevos_locals_t
bool hardcore_being_enabled; /* allows callers to detect hardcore mode while it's being enabled */

bool core_supports; /* false if core explicitly disables achievements */
bool badges_loaded; /* true once all badges have been loaded */
bool badges_loading; /* true if the download queue is running */
} rcheevos_locals_t;

rcheevos_locals_t* get_rcheevos_locals(void);
Expand Down
67 changes: 57 additions & 10 deletions cheevos/cheevos_menu.c
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,31 @@ uintptr_t rcheevos_menu_get_badge_texture(unsigned menu_offset)
return 0;
}

void rcheevos_menu_update_badge_references(const char* badge_name)
{
rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
unsigned i;
char unlocked_badge_name[8];
const size_t badge_name_len = strlen(badge_name);
if (badge_name_len > 6 && badge_name_len < sizeof(unlocked_badge_name) + 5 &&
strcmp(&badge_name[badge_name_len - 5], "_lock") == 0)
{
memcpy(unlocked_badge_name, badge_name, badge_name_len - 5);
unlocked_badge_name[badge_name_len - 5] = '\0';
badge_name = unlocked_badge_name;
}

for (i = 0; i < rcheevos_locals->menuitem_count; ++i)
{
rcheevos_menuitem_t* menuitem = &rcheevos_locals->menuitems[i];
if (menuitem->menu_badge_grayscale >= 2 && /* using placeholder */
strncmp(menuitem->achievement->badge_name, badge_name, badge_name_len) == 0)
{
rcheevos_menu_update_badge(menuitem, false);
}
}
}

void rcheevos_menu_populate_hardcore_pause_submenu(void* data, bool cheevos_hardcore_mode_enable)
{
const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
Expand Down Expand Up @@ -332,6 +357,11 @@ void rcheevos_menu_populate(void* data, bool cheevos_enable,
MENU_ENUM_LABEL_ACHIEVEMENT_PAUSE_MENU,
MENU_SETTING_ACTION_RESUME_ACHIEVEMENTS, 0, 0, NULL);
}

if (!rcheevos_locals->badges_loaded && !rcheevos_locals->badges_loading) {
rcheevos_locals->badges_loading = true;
rcheevos_client_download_achievement_badges(rcheevos_locals->client);
}
}

for (i = 0; i < list->num_buckets; i++)
Expand Down Expand Up @@ -396,7 +426,7 @@ void rcheevos_menu_populate(void* data, bool cheevos_enable,
break;
}

rcheevos_menu_update_badge(menuitem, true);
rcheevos_menu_update_badge(menuitem, false);
}
}

Expand Down Expand Up @@ -518,6 +548,31 @@ void rcheevos_menu_populate(void* data, bool cheevos_enable,

#endif /* HAVE_MENU */

static void rcheevos_client_download_subset_badge(const char* badge_name)
{
rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();

const rc_client_game_t* game = rc_client_get_game_info(rcheevos_locals->client);
if (game && strcmp(game->badge_name, &badge_name[1]) == 0)
{
rcheevos_client_download_badge_from_url(game->badge_url, badge_name);
}
else
{
rc_client_subset_list_t* subset_list = rc_client_create_subset_list(rcheevos_locals->client);
uint32_t i;
for (i = 0; i < subset_list->num_subsets; ++i)
{
if (strcmp(subset_list->subsets[i]->badge_name, &badge_name[1]) == 0)
{
rcheevos_client_download_badge_from_url(subset_list->subsets[i]->badge_url, badge_name);
break;
}
}
rc_client_destroy_subset_list(subset_list);
}
}

static void rcheevos_client_download_achievement_badge(const char* badge_name, bool locked)
{
/* have to find the achievement associated to badge_name, then fetch either badge_url
Expand Down Expand Up @@ -591,18 +646,10 @@ uintptr_t rcheevos_get_badge_texture(const char* badge, bool locked, bool downlo
{
if (download_if_missing)
{
const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();

if (badge[0] == 'i')
{
const rc_client_game_t* game = rc_client_get_game_info(rcheevos_locals->client);
if (game && strcmp(game->badge_name, &badge[1]) == 0)
rcheevos_client_download_badge_from_url(game->badge_url, badge);
}
rcheevos_client_download_subset_badge(badge);
else
{
rcheevos_client_download_achievement_badge(badge, locked);
}
}
return 0;
}
Expand Down
1 change: 1 addition & 0 deletions cheevos/cheevos_menu.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ size_t rcheevos_menu_get_state(unsigned menu_offset, char *s, size_t len);
size_t rcheevos_menu_get_sublabel(unsigned menu_offset, char *s, size_t len);
uintptr_t rcheevos_menu_get_badge_texture(unsigned menu_offset);
void rcheevos_menu_reset_badges(void);
void rcheevos_menu_update_badge_references(const char* badge_name);

RETRO_END_DECLS

Expand Down
Loading
Loading