diff --git a/cheevos/cheevos.c b/cheevos/cheevos.c index 966061f6b0..9256f37ef2 100644 --- a/cheevos/cheevos.c +++ b/cheevos/cheevos.c @@ -965,6 +965,8 @@ static void rcheevos_award_achievement(rcheevos_locals_t *locals, if (locals->hardcore_active) cheevo->active &= ~RCHEEVOS_ACTIVE_HARDCORE; + cheevo->unlock_time = cpu_features_get_time_usec(); + /* Show the OSD message. */ { #if defined(HAVE_GFX_WIDGETS) @@ -1256,6 +1258,13 @@ bool rcheevos_unload(void) { #ifdef HAVE_MENU rcheevos_menu_reset_badges(); + + if (rcheevos_locals.menuitems) + { + CHEEVOS_FREE(rcheevos_locals.menuitems); + rcheevos_locals.menuitems = NULL; + rcheevos_locals.menuitem_capacity = rcheevos_locals.menuitem_count = 0; + } #endif rcheevos_free_patchdata(&rcheevos_locals.patchdata); diff --git a/cheevos/cheevos_locals.h b/cheevos/cheevos_locals.h index a9e6ae829d..2ae62ed220 100644 --- a/cheevos/cheevos_locals.h +++ b/cheevos/cheevos_locals.h @@ -1,4 +1,5 @@ /* RetroArch - A frontend for libretro. + * Copyright (C) 2015-2018 - Andre Leiradella * Copyright (C) 2019-2021 - Brian Weiss * * RetroArch is free software: you can redistribute it and/or modify it under the terms @@ -113,7 +114,7 @@ typedef struct rcheevos_rapatchdata_t typedef struct rcheevos_menuitem_t { rcheevos_racheevo_t* cheevo; - enum msg_hash_enums state_label_idx; + enum msg_hash_enums state_label_idx; } rcheevos_menuitem_t; void rcheevos_menu_reset_badges(void); diff --git a/cheevos/cheevos_menu.c b/cheevos/cheevos_menu.c index 87fb4e9554..68f9f3a8da 100644 --- a/cheevos/cheevos_menu.c +++ b/cheevos/cheevos_menu.c @@ -72,7 +72,7 @@ static void rcheevos_menu_update_bucket(rcheevos_racheevo_t* cheevo) { const unsigned long clamped_value = (unsigned long) MIN(trigger->measured_value, trigger->measured_target); - cheevo->menu_progress = + cheevo->menu_progress = (uint8_t)((clamped_value * 100) / trigger->measured_target); } @@ -81,7 +81,7 @@ static void rcheevos_menu_update_bucket(rcheevos_racheevo_t* cheevo) else if (cheevo->menu_progress >= 80) cheevo->menu_bucket = RCHEEVOS_MENUITEM_BUCKET_ALMOST_THERE; } - } + } } static void rcheevos_menu_update_buckets(bool cheevos_test_unofficial) @@ -89,7 +89,7 @@ static void rcheevos_menu_update_buckets(bool cheevos_test_unofficial) const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals(); rcheevos_racheevo_t* cheevo = rcheevos_locals->patchdata.core; rcheevos_racheevo_t* stop = cheevo + rcheevos_locals->patchdata.core_count; - + while (cheevo < stop) { rcheevos_menu_update_bucket(cheevo); @@ -120,7 +120,7 @@ bool rcheevos_menu_get_state(unsigned menu_offset, char *buffer, size_t len) { if (cheevo->menu_progress) { - snprintf(buffer, len, "%s - %d%%", + snprintf(buffer, len, "%s - %d%%", msg_hash_to_str(menuitem->state_label_idx), cheevo->menu_progress); } @@ -163,7 +163,7 @@ void rcheevos_menu_reset_badges(void) const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals(); rcheevos_racheevo_t* cheevo = rcheevos_locals->patchdata.core; rcheevos_racheevo_t* stop = cheevo + rcheevos_locals->patchdata.core_count; - + while (cheevo < stop) { if (cheevo->menu_badge_texture) @@ -193,7 +193,7 @@ static rcheevos_menuitem_t* rcheevos_menu_allocate( { rcheevos_locals->menuitem_capacity += 32; rcheevos_menuitem_t* new_menuitems = (rcheevos_menuitem_t*) - realloc(rcheevos_locals->menuitems, + realloc(rcheevos_locals->menuitems, rcheevos_locals->menuitem_capacity * sizeof(rcheevos_menuitem_t)); if (new_menuitems) @@ -240,15 +240,15 @@ static void rcheevos_menu_append_header(rcheevos_locals_t* rcheevos_locals, menuitem->state_label_idx = label; } -static void rcheevos_menu_append_items(menu_displaylist_info_t* info, +static void rcheevos_menu_append_items(rcheevos_locals_t* rcheevos_locals, bool cheevos_test_unofficial, enum rcheevos_menuitem_bucket bucket) { const settings_t *settings = config_get_ptr(); - rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals(); rcheevos_racheevo_t* cheevo = rcheevos_locals->patchdata.core; rcheevos_racheevo_t* stop = cheevo + rcheevos_locals->patchdata.core_count; bool processing_unofficial = false; - + const unsigned first_index = rcheevos_locals->menuitem_count; + do { if (cheevo == stop) @@ -282,6 +282,25 @@ static void rcheevos_menu_append_items(menu_displaylist_info_t* info, menuitem->state_label_idx = MENU_ENUM_LABEL_VALUE_CHEEVOS_UNLOCKED_ENTRY; break; + case RCHEEVOS_MENUITEM_BUCKET_ALMOST_THERE: + { + /* insert the item such that the progresses are descending */ + unsigned entry_index = rcheevos_locals->menuitem_count - 1; + while (entry_index > first_index) + { + rcheevos_menuitem_t* prev_menuitem = menuitem - 1; + if (prev_menuitem->cheevo->menu_progress >= cheevo->menu_progress) + break; + + memcpy(menuitem, prev_menuitem, sizeof(rcheevos_menuitem_t)); + menuitem = prev_menuitem; + --entry_index; + } + + menuitem->cheevo = cheevo; + } + /* fallthrough to default */ + default: if (processing_unofficial) menuitem->state_label_idx = MENU_ENUM_LABEL_VALUE_CHEEVOS_UNOFFICIAL_ENTRY; @@ -292,7 +311,7 @@ static void rcheevos_menu_append_items(menu_displaylist_info_t* info, break; } - if (cheevo->badge && cheevo->badge[0] && settings && + if (cheevo->badge && cheevo->badge[0] && settings && settings->bools.cheevos_badges_enable) { bool badge_grayscale = false; @@ -301,6 +320,7 @@ static void rcheevos_menu_append_items(menu_displaylist_info_t* info, case RCHEEVOS_MENUITEM_BUCKET_LOCKED: case RCHEEVOS_MENUITEM_BUCKET_UNSUPPORTED: case RCHEEVOS_MENUITEM_BUCKET_ALMOST_THERE: + case RCHEEVOS_MENUITEM_BUCKET_ACTIVE_CHALLENGE: badge_grayscale = true; break; @@ -420,7 +440,7 @@ void rcheevos_menu_populate(void* data) /* count items in each bucket */ cheevo = rcheevos_locals->patchdata.core; stop = cheevo + rcheevos_locals->patchdata.core_count; - + do { if (cheevo == stop) @@ -467,24 +487,52 @@ void rcheevos_menu_populate(void* data) ++cheevo; } while(true); + + if (!rcheevos_locals->menuitems) + { + /* reserve space for all achievements and up to 6 headers before we need to realloc */ + rcheevos_locals->menuitem_capacity = rcheevos_locals->patchdata.core_count + 6; + if (cheevos_test_unofficial) + rcheevos_locals->menuitem_capacity += rcheevos_locals->patchdata.unofficial_count; + + rcheevos_locals->menuitems = (rcheevos_menuitem_t*) + malloc(rcheevos_locals->menuitem_capacity * sizeof(rcheevos_menuitem_t)); + if (!rcheevos_locals->menuitems) + rcheevos_locals->menuitem_capacity = 0; + } } + /* reset menu */ + rcheevos_locals->menuitem_count = 0; + /* active challenges */ if (num_active_challenges) { + rcheevos_menu_append_header(rcheevos_locals, + MENU_ENUM_LABEL_VALUE_CHEEVOS_ACTIVE_CHALLENGES_ENTRY); + rcheevos_menu_append_items(rcheevos_locals, cheevos_test_unofficial, + RCHEEVOS_MENUITEM_BUCKET_ACTIVE_CHALLENGE); } /* recently unlocked */ if (num_recently_unlocked) { + rcheevos_menu_append_header(rcheevos_locals, + MENU_ENUM_LABEL_VALUE_CHEEVOS_RECENTLY_UNLOCKED_ENTRY); + rcheevos_menu_append_items(rcheevos_locals, cheevos_test_unofficial, + RCHEEVOS_MENUITEM_BUCKET_RECENTLY_UNLOCKED); } /* almost there */ if (num_almost_there) { + rcheevos_menu_append_header(rcheevos_locals, + MENU_ENUM_LABEL_VALUE_CHEEVOS_ALMOST_THERE_ENTRY); + rcheevos_menu_append_items(rcheevos_locals, cheevos_test_unofficial, + RCHEEVOS_MENUITEM_BUCKET_ALMOST_THERE); } /* locked */ @@ -496,7 +544,7 @@ void rcheevos_menu_populate(void* data) MENU_ENUM_LABEL_VALUE_CHEEVOS_LOCKED_ENTRY); } - rcheevos_menu_append_items(info, cheevos_test_unofficial, + rcheevos_menu_append_items(rcheevos_locals, cheevos_test_unofficial, RCHEEVOS_MENUITEM_BUCKET_LOCKED); } @@ -509,12 +557,13 @@ void rcheevos_menu_populate(void* data) MENU_ENUM_LABEL_VALUE_CHEEVOS_UNLOCKED_ENTRY); } - rcheevos_menu_append_items(info, cheevos_test_unofficial, + rcheevos_menu_append_items(rcheevos_locals, cheevos_test_unofficial, RCHEEVOS_MENUITEM_BUCKET_UNLOCKED); } 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]; @@ -525,16 +574,16 @@ void rcheevos_menu_populate(void* data) if (menuitem->cheevo) { menu_entries_append_enum(info->list, menuitem->cheevo->title, - menuitem->cheevo->description, + menuitem->cheevo->description, MENU_ENUM_LABEL_CHEEVOS_LOCKED_ENTRY, MENU_SETTINGS_CHEEVOS_START + idx, 0, 0); } else { - snprintf(buffer, sizeof(buffer), "----- %s -----", + snprintf(buffer, sizeof(buffer), "----- %s -----", msg_hash_to_str(menuitem->state_label_idx)); - menu_entries_append_enum(info->list, buffer, "", + menu_entries_append_enum(info->list, buffer, "", MENU_ENUM_LABEL_CHEEVOS_LOCKED_ENTRY, MENU_SETTINGS_CHEEVOS_START + idx, 0, 0); } diff --git a/cheevos/cheevos_menu.h b/cheevos/cheevos_menu.h index 5ccdf58a12..fc6a774e25 100644 --- a/cheevos/cheevos_menu.h +++ b/cheevos/cheevos_menu.h @@ -1,4 +1,5 @@ /* RetroArch - A frontend for libretro. + * Copyright (C) 2015-2018 - Andre Leiradella * Copyright (C) 2019-2021 - Brian Weiss * * RetroArch is free software: you can redistribute it and/or modify it under the terms diff --git a/griffin/griffin.c b/griffin/griffin.c index ec0204448f..d9bc61da3a 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -191,7 +191,7 @@ ACHIEVEMENTS #include "../network/net_http_special.c" #include "../cheevos/cheevos.c" -#include "../cheevos/badges.c" +#include "../cheevos/cheevos_menu.c" #include "../cheevos/cheevos_memory.c" #include "../cheevos/cheevos_parser.c" diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index 4baba81d2e..62b7341727 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -7979,6 +7979,18 @@ MSG_HASH( MENU_ENUM_LABEL_VALUE_CHEEVOS_UNSUPPORTED_ENTRY, "Unsupported" ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CHEEVOS_RECENTLY_UNLOCKED_ENTRY, + "Recently Unlocked" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CHEEVOS_ALMOST_THERE_ENTRY, + "Almost There" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CHEEVOS_ACTIVE_CHALLENGES_ENTRY, + "Active Challenges" + ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CHEEVOS_TRACKERS_ONLY, "Trackers Only" diff --git a/msg_hash.h b/msg_hash.h index e57bfcf90e..8a9ec5d700 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -704,6 +704,9 @@ enum msg_hash_enums MENU_LABEL(CHEEVOS_LOCKED_ENTRY), MENU_LABEL(CHEEVOS_UNSUPPORTED_ENTRY), MENU_LABEL(CHEEVOS_UNOFFICIAL_ENTRY), + MENU_ENUM_LABEL_VALUE_CHEEVOS_RECENTLY_UNLOCKED_ENTRY, + MENU_ENUM_LABEL_VALUE_CHEEVOS_ALMOST_THERE_ENTRY, + MENU_ENUM_LABEL_VALUE_CHEEVOS_ACTIVE_CHALLENGES_ENTRY, MENU_ENUM_LABEL_VALUE_CHEEVOS_TRACKERS_ONLY, MENU_ENUM_LABEL_VALUE_CHEEVOS_NOTIFICATIONS_ONLY, diff --git a/retroarch.c b/retroarch.c index 99891e02f9..efd8e15a08 100644 --- a/retroarch.c +++ b/retroarch.c @@ -790,7 +790,8 @@ static int menu_dialog_iterate( #ifdef HAVE_CHEEVOS case MENU_DIALOG_HELP_CHEEVOS_DESCRIPTION: - rcheevos_menu_get_sublabel(p_dialog->current_id, s, len); + if (!rcheevos_menu_get_sublabel(p_dialog->current_id, s, len)) + return 1; break; #endif