group achievements by category

This commit is contained in:
Jamiras 2021-06-01 11:59:27 -06:00
parent 293e797146
commit e76265e1aa
14 changed files with 576 additions and 307 deletions

View File

@ -2107,7 +2107,6 @@ ifeq ($(HAVE_NETWORKING), 1)
INCLUDE_DIRS += -Ideps/rcheevos/include
OBJ += cheevos/cheevos.o \
cheevos/badges.o \
cheevos/cheevos_menu.o \
cheevos/cheevos_memory.o \
cheevos/cheevos_parser.o \

View File

@ -1,91 +0,0 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2015-2016 - Andre Leiradella
*
* RetroArch is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <file/file_path.h>
#include "../file_path_special.h"
#include "../configuration.h"
#include "../gfx/gfx_display.h"
#include "badges.h"
#ifdef HAVE_MENU
#define CHEEVOS_MENU_BADGE_LIMIT 256
/* TODO/FIXME - public global variables */
static uintptr_t cheevos_badge_menu_texture_list[CHEEVOS_MENU_BADGE_LIMIT] = { 0 };
void cheevos_reset_menu_badges(void)
{
int index;
for (index = 0; index < CHEEVOS_MENU_BADGE_LIMIT; ++index)
{
if (cheevos_badge_menu_texture_list[index])
video_driver_texture_unload(&cheevos_badge_menu_texture_list[index]);
}
memset(&cheevos_badge_menu_texture_list, 0,
sizeof(cheevos_badge_menu_texture_list));
}
void cheevos_set_menu_badge(int index, const char *badge, bool locked)
{
settings_t *settings = config_get_ptr();
if (index >= CHEEVOS_MENU_BADGE_LIMIT)
return;
if (!settings || !settings->bools.cheevos_badges_enable)
cheevos_badge_menu_texture_list[index] = 0;
else
cheevos_badge_menu_texture_list[index] =
cheevos_get_badge_texture(badge, locked);
}
uintptr_t cheevos_get_menu_badge_texture(int index)
{
if (index < CHEEVOS_MENU_BADGE_LIMIT)
return cheevos_badge_menu_texture_list[index];
return 0;
}
#endif
uintptr_t cheevos_get_badge_texture(const char *badge, bool locked)
{
char badge_file[24];
char fullpath[PATH_MAX_LENGTH];
uintptr_t tex = 0;
if (!badge)
return 0;
fullpath[0] = badge_file[0] = '\0';
strlcpy(badge_file, badge, sizeof(badge_file));
if (locked)
strlcat(badge_file, "_lock", sizeof(badge_file));
strlcat(badge_file, FILE_PATH_PNG_EXTENSION, sizeof(badge_file));
fill_pathname_application_special(fullpath, sizeof(fullpath),
APPLICATION_SPECIAL_DIRECTORY_THUMBNAILS_CHEEVOS_BADGES);
if (!gfx_display_reset_textures_list(badge_file, fullpath,
&tex, TEXTURE_FILTER_MIPMAP_LINEAR, NULL, NULL))
tex = 0;
return tex;
}

View File

@ -53,7 +53,6 @@
#include "streams/chd_stream.h"
#endif
#include "badges.h"
#include "cheevos.h"
#include "cheevos_locals.h"
#include "cheevos_memory.h"
@ -139,6 +138,11 @@ static rcheevos_locals_t rcheevos_locals =
{0}, /* token */
"N/A",/* hash */
"", /* user_agent_prefix */
#ifdef HAVE_MENU
NULL, /* menuitems */
0, /* menuitem_capacity */
0, /* menuitem_count */
#endif
false,/* hardcore_active */
false,/* loaded */
true, /* core_supports */
@ -1210,37 +1214,6 @@ void rcheevos_reset_game(bool widgets_ready)
rcheevos_locals.patchdata.console_id);
}
bool rcheevos_get_description(rcheevos_ctx_desc_t* desc)
{
unsigned idx;
const rcheevos_racheevo_t* cheevo;
if (!desc)
return false;
*desc->s = 0;
if (rcheevos_locals.loaded)
{
idx = desc->idx;
if (idx < rcheevos_locals.patchdata.core_count)
cheevo = rcheevos_locals.patchdata.core + idx;
else
{
idx -= rcheevos_locals.patchdata.core_count;
if (idx >= rcheevos_locals.patchdata.unofficial_count)
return true;
cheevo = rcheevos_locals.patchdata.unofficial + idx;
}
strlcpy(desc->s, cheevo->description, desc->len);
}
return true;
}
bool rcheevos_hardcore_active(void)
{
return rcheevos_locals.hardcore_active;
@ -1281,10 +1254,10 @@ bool rcheevos_unload(void)
if (rcheevos_locals.loaded)
{
rcheevos_free_patchdata(&rcheevos_locals.patchdata);
#ifdef HAVE_MENU
cheevos_reset_menu_badges();
rcheevos_menu_reset_badges();
#endif
rcheevos_free_patchdata(&rcheevos_locals.patchdata);
rcheevos_locals.loaded = false;
rcheevos_locals.hardcore_active = false;
@ -2233,7 +2206,7 @@ static int rcheevos_iterate(rcheevos_coro_t* coro)
#endif
#ifdef HAVE_MENU
cheevos_reset_menu_badges();
rcheevos_menu_reset_badges();
#endif
for (coro->i = 0; coro->i < 2; coro->i++)

View File

@ -25,51 +25,35 @@
RETRO_BEGIN_DECLS
typedef struct rcheevos_ctx_desc
{
unsigned idx;
char *s;
size_t len;
} rcheevos_ctx_desc_t;
bool rcheevos_load(const void *data);
size_t rcheevos_get_serialize_size(void);
bool rcheevos_get_serialized_data(void* buffer);
bool rcheevos_set_serialized_data(void* buffer);
void rcheevos_reset_game(bool widgets_ready);
void rcheevos_populate_menu(void* data);
void rcheevos_populate_hardcore_pause_menu(void* data);
void rcheevos_get_achievement_state(unsigned index, char* buffer, size_t buffer_size);
bool rcheevos_get_description(rcheevos_ctx_desc_t *desc);
void rcheevos_pause_hardcore(void);
bool rcheevos_unload(void);
void rcheevos_test(void);
void rcheevos_reset_game(bool widgets_ready);
void rcheevos_pause_hardcore(void);
void rcheevos_hardcore_enabled_changed(void);
void rcheevos_toggle_hardcore_paused(void);
bool rcheevos_hardcore_active(void);
void rcheevos_validate_config_settings(void);
void rcheevos_leaderboards_enabled_changed(void);
void rcheevos_test(void);
void rcheevos_set_support_cheevos(bool state);
bool rcheevos_get_support_cheevos(void);
const char* rcheevos_get_hash(void);
int rcheevos_get_richpresence(char buffer[], int buffer_size);
uintptr_t rcheevos_get_badge_texture(const char *badge, bool locked);
uint8_t* rcheevos_patch_address(unsigned address);
bool rcheevos_hardcore_active(void);
RETRO_END_DECLS
#endif /* __RARCH_CHEEVOS_CHEEVOS_H */

View File

@ -69,9 +69,19 @@ typedef struct rcheevos_racheevo_t
const char* description;
const char* badge;
const char* memaddr;
unsigned points;
unsigned id;
unsigned active;
unsigned points;
retro_time_t unlock_time;
uint8_t active;
#ifdef HAVE_MENU
uint8_t menu_bucket;
uint8_t menu_progress;
uint8_t menu_badge_grayscale;
uintptr_t menu_badge_texture;
#endif
} rcheevos_racheevo_t;
typedef struct rcheevos_ralboard_t
@ -98,6 +108,18 @@ typedef struct rcheevos_rapatchdata_t
unsigned lboard_count;
} rcheevos_rapatchdata_t;
#ifdef HAVE_MENU
typedef struct rcheevos_menuitem_t
{
rcheevos_racheevo_t* cheevo;
enum msg_hash_enums state_label_idx;
} rcheevos_menuitem_t;
void rcheevos_menu_reset_badges(void);
#endif
typedef struct rcheevos_locals_t
{
rc_runtime_t runtime; /* rcheevos runtime state */
@ -114,6 +136,12 @@ typedef struct rcheevos_locals_t
char hash[33]; /* retroachievements hash for current content */
char user_agent_prefix[128]; /* RetroArch/OS version information */
#ifdef HAVE_MENU
rcheevos_menuitem_t* menuitems; /* array of items for the achievements quick menu */
unsigned menuitem_capacity; /* maximum number of items in the menuitems array */
unsigned menuitem_count; /* current number of items in the menuitems array */
#endif
bool hardcore_active; /* hardcore functionality is active */
bool loaded; /* load task has completed */
bool core_supports; /* false if core explicitly disables achievements */

View File

@ -15,103 +15,335 @@
#include "cheevos_locals.h"
#include "badges.h"
#ifdef HAVE_MENU
#include "cheevos.h"
#include "../deps/rcheevos/include/rc_runtime_types.h"
#include "../menu/menu_driver.h"
#include "../menu/menu_entries.h"
#endif
#ifdef HAVE_MENU
void rcheevos_get_achievement_state(unsigned index,
char *buffer, size_t len)
#include <features/features_cpu.h>
enum rcheevos_menuitem_bucket
{
RCHEEVOS_MENUITEM_BUCKET_UNKNOWN = 0,
RCHEEVOS_MENUITEM_BUCKET_LOCKED,
RCHEEVOS_MENUITEM_BUCKET_UNLOCKED,
RCHEEVOS_MENUITEM_BUCKET_UNSUPPORTED,
RCHEEVOS_MENUITEM_BUCKET_RECENTLY_UNLOCKED,
RCHEEVOS_MENUITEM_BUCKET_ACTIVE_CHALLENGE,
RCHEEVOS_MENUITEM_BUCKET_ALMOST_THERE
};
static void rcheevos_menu_update_bucket(rcheevos_racheevo_t* cheevo)
{
if (!cheevo->memaddr)
{
/* non-active unsupported achievement */
cheevo->menu_bucket = RCHEEVOS_MENUITEM_BUCKET_UNSUPPORTED;
}
else if (!(cheevo->active & RCHEEVOS_ACTIVE_HARDCORE))
{
/* non-active unlocked in hardcore achievement */
cheevo->menu_bucket = RCHEEVOS_MENUITEM_BUCKET_UNLOCKED;
}
else
{
const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
rc_trigger_t* trigger;
if (!rcheevos_locals->hardcore_active && !(cheevo->active & RCHEEVOS_ACTIVE_SOFTCORE))
{
/* non-active unlocked in softcore achievement in softcore mode */
cheevo->menu_bucket = RCHEEVOS_MENUITEM_BUCKET_UNLOCKED;
return;
}
/* active achievement */
cheevo->menu_bucket = RCHEEVOS_MENUITEM_BUCKET_LOCKED;
cheevo->menu_progress = 0;
trigger = rc_runtime_get_achievement(&rcheevos_locals->runtime, cheevo->id);
if (trigger)
{
if (trigger->measured_value && trigger->measured_target)
{
const unsigned long clamped_value = (unsigned long)
MIN(trigger->measured_value, trigger->measured_target);
cheevo->menu_progress =
(uint8_t)((clamped_value * 100) / trigger->measured_target);
}
if (trigger->state == RC_TRIGGER_STATE_PRIMED)
cheevo->menu_bucket = RCHEEVOS_MENUITEM_BUCKET_ACTIVE_CHALLENGE;
else if (cheevo->menu_progress >= 80)
cheevo->menu_bucket = RCHEEVOS_MENUITEM_BUCKET_ALMOST_THERE;
}
}
}
static void rcheevos_menu_update_buckets(bool cheevos_test_unofficial)
{
const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
enum msg_hash_enums enum_idx;
rcheevos_racheevo_t *cheevo = NULL;
bool check_measured = false;
if (index < rcheevos_locals->patchdata.core_count)
rcheevos_racheevo_t* cheevo = rcheevos_locals->patchdata.core;
rcheevos_racheevo_t* stop = cheevo + rcheevos_locals->patchdata.core_count;
while (cheevo < stop)
{
enum_idx = MENU_ENUM_LABEL_VALUE_CHEEVOS_LOCKED_ENTRY;
if (rcheevos_locals->patchdata.core)
cheevo = &rcheevos_locals->patchdata.core[index];
}
else
{
enum_idx = MENU_ENUM_LABEL_VALUE_CHEEVOS_UNOFFICIAL_ENTRY;
if (rcheevos_locals->patchdata.unofficial)
cheevo = &rcheevos_locals->patchdata.unofficial[index -
rcheevos_locals->patchdata.core_count];
rcheevos_menu_update_bucket(cheevo);
++cheevo;
}
if (!cheevo || !cheevo->memaddr)
enum_idx = MENU_ENUM_LABEL_VALUE_CHEEVOS_UNSUPPORTED_ENTRY;
else if (!(cheevo->active & RCHEEVOS_ACTIVE_HARDCORE))
enum_idx = MENU_ENUM_LABEL_VALUE_CHEEVOS_UNLOCKED_ENTRY_HARDCORE;
else if (!(cheevo->active & RCHEEVOS_ACTIVE_SOFTCORE))
if (cheevos_test_unofficial)
{
enum_idx = MENU_ENUM_LABEL_VALUE_CHEEVOS_UNLOCKED_ENTRY;
/* if in hardcore mode, track progress towards hardcore unlock */
check_measured = rcheevos_locals->hardcore_active;
}
/* Use either "Locked" for core or "Unofficial"
* for unofficial as set above and track progress */
else
check_measured = true;
cheevo = rcheevos_locals->patchdata.unofficial;
stop = cheevo + rcheevos_locals->patchdata.unofficial_count;
strlcpy(buffer, msg_hash_to_str(enum_idx), len);
if (check_measured)
{
unsigned value, target;
if (rc_runtime_get_achievement_measured(&rcheevos_locals->runtime,
cheevo->id, &value, &target) && target > 0 && value > 0)
while (cheevo < stop)
{
char measured_buffer[12];
const unsigned int clamped_value = MIN(value, target);
const int percent = (int)(((unsigned long)clamped_value) * 100 / target);
snprintf(measured_buffer, sizeof(measured_buffer),
" - %d%%", percent);
strlcat(buffer, measured_buffer, len);
rcheevos_menu_update_bucket(cheevo);
++cheevo;
}
}
}
static void rcheevos_append_menu_achievement(
menu_displaylist_info_t* info, size_t idx,
rcheevos_racheevo_t* cheevo)
bool rcheevos_menu_get_state(unsigned menu_offset, char *buffer, size_t len)
{
bool badge_grayscale;
const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
if (menu_offset < rcheevos_locals->menuitem_count)
{
const rcheevos_menuitem_t* menuitem = &rcheevos_locals->menuitems[menu_offset];
const rcheevos_racheevo_t* cheevo = menuitem->cheevo;
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);
}
menu_entries_append_enum(info->list, cheevo->title,
cheevo->description, MENU_ENUM_LABEL_CHEEVOS_LOCKED_ENTRY,
(unsigned)(MENU_SETTINGS_CHEEVOS_START + idx), 0, 0);
return true;
}
}
/* TODO/FIXME - can we refactor this?
* Make badge_grayscale true by default, then
* have one conditional (second one here) that sets it
* to false */
if (!cheevo->memaddr)
badge_grayscale = true; /* unsupported */
else if (!(cheevo->active & RCHEEVOS_ACTIVE_HARDCORE) ||
!(cheevo->active & RCHEEVOS_ACTIVE_SOFTCORE))
badge_grayscale = false; /* unlocked */
else
badge_grayscale = true; /* locked */
if (buffer)
buffer[0] = '\0';
cheevos_set_menu_badge((int)idx, cheevo->badge, badge_grayscale);
return false;
}
#endif
void rcheevos_populate_hardcore_pause_menu(void* data)
bool rcheevos_menu_get_sublabel(unsigned menu_offset, char *buffer, size_t len)
{
const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
if (menu_offset < rcheevos_locals->menuitem_count)
{
const rcheevos_racheevo_t* cheevo = rcheevos_locals->menuitems[menu_offset].cheevo;
if (cheevo && buffer)
{
strlcpy(buffer, cheevo->description, len);
return true;
}
}
if (buffer)
buffer[0] = '\0';
return false;
}
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)
video_driver_texture_unload(&cheevo->menu_badge_texture);
++cheevo;
}
cheevo = rcheevos_locals->patchdata.unofficial;
stop = cheevo + rcheevos_locals->patchdata.unofficial_count;
while (cheevo < stop)
{
if (cheevo->menu_badge_texture)
video_driver_texture_unload(&cheevo->menu_badge_texture);
++cheevo;
}
}
static rcheevos_menuitem_t* rcheevos_menu_allocate(
rcheevos_locals_t* rcheevos_locals, rcheevos_racheevo_t* cheevo)
{
rcheevos_menuitem_t* menuitem;
if (rcheevos_locals->menuitem_count == rcheevos_locals->menuitem_capacity)
{
if (rcheevos_locals->menuitems)
{
rcheevos_locals->menuitem_capacity += 32;
rcheevos_menuitem_t* new_menuitems = (rcheevos_menuitem_t*)
realloc(rcheevos_locals->menuitems,
rcheevos_locals->menuitem_capacity * sizeof(rcheevos_menuitem_t));
if (new_menuitems)
{
rcheevos_locals->menuitems = new_menuitems;
}
else
{
/* realloc failed */
CHEEVOS_ERR(RCHEEVOS_TAG " could not allocate space for %u menu items",
rcheevos_locals->menuitem_capacity);
rcheevos_locals->menuitem_capacity -= 32;
return NULL;
}
}
else
{
rcheevos_locals->menuitem_capacity = 64;
rcheevos_locals->menuitems = (rcheevos_menuitem_t*)
malloc(rcheevos_locals->menuitem_capacity * sizeof(rcheevos_menuitem_t));
if (!rcheevos_locals->menuitems)
{
/* malloc failed */
CHEEVOS_ERR(RCHEEVOS_TAG " could not allocate space for %u menu items",
rcheevos_locals->menuitem_capacity);
rcheevos_locals->menuitem_capacity = 0;
return NULL;
}
}
}
menuitem = &rcheevos_locals->menuitems[rcheevos_locals->menuitem_count++];
menuitem->cheevo = cheevo;
menuitem->state_label_idx = 0;
return menuitem;
}
static void rcheevos_menu_append_header(rcheevos_locals_t* rcheevos_locals,
enum msg_hash_enums label)
{
rcheevos_menuitem_t* menuitem = rcheevos_menu_allocate(rcheevos_locals, NULL);
if (menuitem)
menuitem->state_label_idx = label;
}
static void rcheevos_menu_append_items(menu_displaylist_info_t* info,
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;
do
{
if (cheevo == stop)
{
if (!cheevos_test_unofficial || processing_unofficial)
break;
processing_unofficial = true;
cheevo = rcheevos_locals->patchdata.unofficial;
stop = cheevo + rcheevos_locals->patchdata.unofficial_count;
continue;
}
if (cheevo->menu_bucket == bucket)
{
rcheevos_menuitem_t* menuitem = rcheevos_menu_allocate(rcheevos_locals, cheevo);
if (!menuitem)
return;
switch (cheevo->menu_bucket)
{
case RCHEEVOS_MENUITEM_BUCKET_UNSUPPORTED:
menuitem->state_label_idx = MENU_ENUM_LABEL_VALUE_CHEEVOS_UNSUPPORTED_ENTRY;
break;
case RCHEEVOS_MENUITEM_BUCKET_UNLOCKED:
case RCHEEVOS_MENUITEM_BUCKET_RECENTLY_UNLOCKED:
if (!(cheevo->active & RCHEEVOS_ACTIVE_HARDCORE))
menuitem->state_label_idx = MENU_ENUM_LABEL_VALUE_CHEEVOS_UNLOCKED_ENTRY_HARDCORE;
else
menuitem->state_label_idx = MENU_ENUM_LABEL_VALUE_CHEEVOS_UNLOCKED_ENTRY;
break;
default:
if (processing_unofficial)
menuitem->state_label_idx = MENU_ENUM_LABEL_VALUE_CHEEVOS_UNOFFICIAL_ENTRY;
else if (!(cheevo->active & RCHEEVOS_ACTIVE_SOFTCORE))
menuitem->state_label_idx = MENU_ENUM_LABEL_VALUE_CHEEVOS_UNLOCKED_ENTRY;
else
menuitem->state_label_idx = MENU_ENUM_LABEL_VALUE_CHEEVOS_LOCKED_ENTRY;
break;
}
if (cheevo->badge && cheevo->badge[0] && settings &&
settings->bools.cheevos_badges_enable)
{
bool badge_grayscale = false;
switch (bucket)
{
case RCHEEVOS_MENUITEM_BUCKET_LOCKED:
case RCHEEVOS_MENUITEM_BUCKET_UNSUPPORTED:
case RCHEEVOS_MENUITEM_BUCKET_ALMOST_THERE:
badge_grayscale = true;
break;
default:
badge_grayscale = false;
break;
}
if (!cheevo->menu_badge_texture || cheevo->menu_badge_grayscale != badge_grayscale)
{
if (cheevo->menu_badge_texture)
video_driver_texture_unload(&cheevo->menu_badge_texture);
cheevo->menu_badge_texture =
rcheevos_get_badge_texture(cheevo->badge, badge_grayscale);
cheevo->menu_badge_grayscale = badge_grayscale;
}
}
}
++cheevo;
} while (true);
}
uintptr_t rcheevos_menu_get_badge_texture(unsigned menu_offset)
{
const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
if (menu_offset < rcheevos_locals->menuitem_count)
{
const rcheevos_racheevo_t* cheevo = rcheevos_locals->menuitems[menu_offset].cheevo;
if (cheevo)
return cheevo->menu_badge_texture;
}
return 0;
}
void rcheevos_menu_populate_hardcore_pause_submenu(void* data)
{
#ifdef HAVE_MENU
const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
menu_displaylist_info_t* info = (menu_displaylist_info_t*)data;
settings_t* settings = config_get_ptr();
bool cheevos_hardcore_mode_enable = settings->bools.cheevos_hardcore_mode_enable;
const settings_t* settings = config_get_ptr();
const bool cheevos_hardcore_mode_enable = settings->bools.cheevos_hardcore_mode_enable;
if (cheevos_hardcore_mode_enable && rcheevos_locals->loaded)
{
@ -142,55 +374,178 @@ void rcheevos_populate_hardcore_pause_menu(void* data)
MENU_SETTING_ACTION_RESUME_ACHIEVEMENTS, 0, 0);
}
}
#endif
}
void rcheevos_populate_menu(void* data)
void rcheevos_menu_populate(void* data)
{
#ifdef HAVE_MENU
int i = 0;
int count = 0;
rcheevos_racheevo_t* cheevo = NULL;
menu_displaylist_info_t* info = (menu_displaylist_info_t*)data;
const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
settings_t* settings = config_get_ptr();
bool cheevos_enable = settings->bools.cheevos_enable;
bool cheevos_hardcore_mode_enable = settings->bools.cheevos_hardcore_mode_enable;
bool cheevos_test_unofficial = settings->bools.cheevos_test_unofficial;
menu_displaylist_info_t* info = (menu_displaylist_info_t*)data;
rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
const settings_t* settings = config_get_ptr();
const bool cheevos_test_unofficial = settings->bools.cheevos_test_unofficial;
unsigned num_locked = 0;
unsigned num_unlocked = 0;
unsigned num_recently_unlocked = 0;
unsigned num_unsupported = 0;
unsigned num_active_challenges = 0;
unsigned num_almost_there = 0;
CHEEVOS_LOG(RCHEEVOS_TAG "populate_menu");
if ( cheevos_enable
&& cheevos_hardcore_mode_enable
&& rcheevos_locals->loaded)
if (rcheevos_locals->loaded)
{
if (rcheevos_locals->hardcore_active)
menu_entries_append_enum(info->list,
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_PAUSE),
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_PAUSE_MENU),
MENU_ENUM_LABEL_ACHIEVEMENT_PAUSE_MENU,
MENU_SETTING_ACTION_PAUSE_ACHIEVEMENTS, 0, 0);
else
menu_entries_append_enum(info->list,
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_RESUME),
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_PAUSE_MENU),
MENU_ENUM_LABEL_ACHIEVEMENT_PAUSE_MENU,
MENU_SETTING_ACTION_RESUME_ACHIEVEMENTS, 0, 0);
const retro_time_t now = cpu_features_get_time_usec();
const retro_time_t recent_unlock_time = now - (10 * 60 * 1000000); /* 10 minutes ago */
bool processing_unofficial = false;
rcheevos_racheevo_t* cheevo = NULL;
rcheevos_racheevo_t* stop = NULL;
/* first menu item is the Pause/Resume Hardcore option (unless hardcore is disabled) */
if (settings->bools.cheevos_enable && settings->bools.cheevos_hardcore_mode_enable)
{
if (rcheevos_locals->hardcore_active)
menu_entries_append_enum(info->list,
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_PAUSE),
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_PAUSE_MENU),
MENU_ENUM_LABEL_ACHIEVEMENT_PAUSE_MENU,
MENU_SETTING_ACTION_PAUSE_ACHIEVEMENTS, 0, 0);
else
menu_entries_append_enum(info->list,
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_RESUME),
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_PAUSE_MENU),
MENU_ENUM_LABEL_ACHIEVEMENT_PAUSE_MENU,
MENU_SETTING_ACTION_RESUME_ACHIEVEMENTS, 0, 0);
}
/* update the bucket for each achievement */
rcheevos_menu_update_buckets(cheevos_test_unofficial);
/* count items in each bucket */
cheevo = rcheevos_locals->patchdata.core;
stop = cheevo + rcheevos_locals->patchdata.core_count;
do
{
if (cheevo == stop)
{
if (!cheevos_test_unofficial || processing_unofficial)
break;
processing_unofficial = true;
cheevo = rcheevos_locals->patchdata.unofficial;
stop = cheevo + rcheevos_locals->patchdata.unofficial_count;
continue;
}
switch (cheevo->menu_bucket)
{
case RCHEEVOS_MENUITEM_BUCKET_UNLOCKED:
if (cheevo->unlock_time && cheevo->unlock_time >= recent_unlock_time)
{
cheevo->menu_bucket = RCHEEVOS_MENUITEM_BUCKET_RECENTLY_UNLOCKED;
++num_recently_unlocked;
}
else
{
++num_unlocked;
}
break;
case RCHEEVOS_MENUITEM_BUCKET_LOCKED:
++num_locked;
break;
case RCHEEVOS_MENUITEM_BUCKET_UNSUPPORTED:
++num_unsupported;
break;
case RCHEEVOS_MENUITEM_BUCKET_ACTIVE_CHALLENGE:
++num_active_challenges;
break;
case RCHEEVOS_MENUITEM_BUCKET_ALMOST_THERE:
++num_almost_there;
break;
}
++cheevo;
} while(true);
}
cheevo = rcheevos_locals->patchdata.core;
for (count = rcheevos_locals->patchdata.core_count; count > 0; count--)
rcheevos_append_menu_achievement(info, i++, cheevo++);
if (cheevos_test_unofficial)
/* active challenges */
if (num_active_challenges)
{
cheevo = rcheevos_locals->patchdata.unofficial;
for (count = rcheevos_locals->patchdata.unofficial_count; count > 0; count--)
rcheevos_append_menu_achievement(info, i++, cheevo++);
}
if (i == 0)
/* recently unlocked */
if (num_recently_unlocked)
{
}
/* almost there */
if (num_almost_there)
{
}
/* locked */
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(info, cheevos_test_unofficial,
RCHEEVOS_MENUITEM_BUCKET_LOCKED);
}
/* unlocked */
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(info, cheevos_test_unofficial,
RCHEEVOS_MENUITEM_BUCKET_UNLOCKED);
}
if (rcheevos_locals->menuitem_count > 0)
{
rcheevos_menuitem_t* menuitem = rcheevos_locals->menuitems;
rcheevos_menuitem_t* stop = menuitem + rcheevos_locals->menuitem_count;
char buffer[128];
unsigned idx = 0;
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 -----",
msg_hash_to_str(menuitem->state_label_idx));
menu_entries_append_enum(info->list, buffer, "",
MENU_ENUM_LABEL_CHEEVOS_LOCKED_ENTRY,
MENU_SETTINGS_CHEEVOS_START + idx, 0, 0);
}
++idx;
++menuitem;
} while (menuitem != stop);
}
else
{
/* no achievements found */
if (!rcheevos_locals->core_supports)
{
menu_entries_append_enum(info->list,
@ -199,7 +554,7 @@ void rcheevos_populate_menu(void* data)
MENU_ENUM_LABEL_CANNOT_ACTIVATE_ACHIEVEMENTS_WITH_THIS_CORE,
FILE_TYPE_NONE, 0, 0);
}
else if (!settings->arrays.cheevos_token[0])
else if (!rcheevos_locals->token[0])
{
menu_entries_append_enum(info->list,
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_LOGGED_IN),
@ -216,6 +571,31 @@ void rcheevos_populate_menu(void* data)
FILE_TYPE_NONE, 0, 0);
}
}
#endif
}
#endif /* HAVE_MENU */
uintptr_t rcheevos_get_badge_texture(const char *badge, bool locked)
{
char badge_file[24];
char fullpath[PATH_MAX_LENGTH];
uintptr_t tex = 0;
if (!badge)
return 0;
snprintf(badge_file, sizeof(badge_file), "%s%s%s", badge,
locked ? "_lock" : "", FILE_PATH_PNG_EXTENSION);
fill_pathname_application_special(fullpath, sizeof(fullpath),
APPLICATION_SPECIAL_DIRECTORY_THUMBNAILS_CHEEVOS_BADGES);
if (!gfx_display_reset_textures_list(badge_file, fullpath,
&tex, TEXTURE_FILTER_MIPMAP_LINEAR, NULL, NULL))
{
tex = 0;
}
return tex;
}

View File

@ -1,5 +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
* of the GNU General Public License as published by the Free Software Found-
@ -13,23 +13,35 @@
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __RARCH_CHEEVOS_BADGE_H
#define __RARCH_CHEEVOS_BADGE_H
#ifndef __RARCH_CHEEVOS_MENU_H
#define __RARCH_CHEEVOS_MENU_H
#ifdef HAVE_MENU
#include <stdint.h>
#include <retro_common_api.h>
#include <stdlib.h>
#include <boolean.h>
#include <retro_common_api.h>
RETRO_BEGIN_DECLS
#ifdef HAVE_MENU
void cheevos_reset_menu_badges(void);
void cheevos_set_menu_badge(int index, const char *badge, bool locked);
uintptr_t cheevos_get_menu_badge_texture(int index);
#endif
typedef struct rcheevos_ctx_desc
{
unsigned idx;
char *s;
size_t len;
} rcheevos_ctx_desc_t;
uintptr_t cheevos_get_badge_texture(const char* badge, bool locked);
void rcheevos_menu_populate(void* data);
void rcheevos_menu_populate_hardcore_pause_submenu(void* data);
bool rcheevos_menu_get_state(unsigned menu_offset, char* buffer, size_t buffer_size);
bool rcheevos_menu_get_sublabel(unsigned menu_offset, char* buffer, size_t buffer_size);
uintptr_t rcheevos_menu_get_badge_texture(unsigned menu_offset);
RETRO_END_DECLS
#endif
#endif /* HAVE_MENU */
#endif /* __RARCH_CHEEVOS_CHEEVOS_H */

View File

@ -18,7 +18,7 @@
#include "../gfx_display.h"
#include "../gfx_widgets.h"
#include "../cheevos/badges.h"
#include "../cheevos/cheevos.h"
#ifdef HAVE_THREADS
#define SLOCK_LOCK(x) slock_lock(x)
@ -391,7 +391,7 @@ void gfx_widgets_push_achievement(const char *title, const char *badge)
/* important - this must be done outside the lock because it has the potential to need to
* lock the video thread, which may be waiting for the popup queue lock to render popups */
uintptr_t badge_id = cheevos_get_badge_texture(badge, 0);
uintptr_t badge_id = rcheevos_get_badge_texture(badge, 0);
if (state->queue_read_index < 0)
{

View File

@ -53,7 +53,7 @@
#endif
#ifdef HAVE_CHEEVOS
#include "../../cheevos/cheevos.h"
#include "../../cheevos/cheevos_menu.h"
#endif
#ifndef BIND_ACTION_GET_VALUE
@ -129,7 +129,7 @@ static void menu_action_setting_disp_set_label_cheevos_entry(
*w = 19;
strlcpy(s2, path, len2);
rcheevos_get_achievement_state(type - MENU_SETTINGS_CHEEVOS_START, s, len);
rcheevos_menu_get_state(type - MENU_SETTINGS_CHEEVOS_START, s, len);
}
#endif

View File

@ -26,7 +26,7 @@
#include "../../core_option_manager.h"
#ifdef HAVE_CHEEVOS
#include "../../cheevos/cheevos.h"
#include "../../cheevos/cheevos_menu.h"
#endif
#include "../../core_info.h"
#include "../../verbosity.h"
@ -1052,20 +1052,8 @@ static int action_bind_sublabel_cheevos_entry(
const char *label, const char *path,
char *s, size_t len)
{
rcheevos_ctx_desc_t desc_info;
unsigned new_id;
char fetched_sublabel[MENU_SUBLABEL_MAX_LENGTH];
fetched_sublabel[0] = '\0';
new_id = type - MENU_SETTINGS_CHEEVOS_START;
desc_info.idx = new_id;
desc_info.s = fetched_sublabel;
desc_info.len = len;
rcheevos_get_description((rcheevos_ctx_desc_t*) &desc_info);
strlcpy(s, desc_info.s, len);
unsigned offset = type - MENU_SETTINGS_CHEEVOS_START;
rcheevos_menu_get_sublabel(offset, s, len);
return 0;
}
#endif

View File

@ -24,7 +24,7 @@
#include <file/file_path.h>
#ifdef HAVE_CHEEVOS
#include "../../../cheevos/badges.h"
#include "../../../cheevos/cheevos_menu.h"
#endif
#include "../../../file_path_special.h"
@ -465,7 +465,7 @@ uintptr_t ozone_entries_icon_get_texture(ozone_handle_t *ozone,
)
{
int index = type - MENU_SETTINGS_CHEEVOS_START;
uintptr_t badge_texture = cheevos_get_menu_badge_texture(index);
uintptr_t badge_texture = rcheevos_menu_get_badge_texture(index);
if (badge_texture)
return badge_texture;
/* Should be replaced with placeholder badge icon. */

View File

@ -59,7 +59,7 @@
#include "../../tasks/tasks_internal.h"
#ifdef HAVE_CHEEVOS
#include "../../cheevos/badges.h"
#include "../../cheevos/cheevos_menu.h"
#endif
#include "../../content.h"
@ -2906,7 +2906,7 @@ static uintptr_t xmb_icon_get_id(xmb_handle_t *xmb,
)
{
int index = type - MENU_SETTINGS_CHEEVOS_START;
uintptr_t badge_texture = cheevos_get_menu_badge_texture(index);
uintptr_t badge_texture = rcheevos_menu_get_badge_texture(index);
if (badge_texture)
return badge_texture;
/* Should be replaced with placeholder badge icon. */

View File

@ -41,6 +41,7 @@
#ifdef HAVE_CHEEVOS
#include "../cheevos/cheevos.h"
#include "../cheevos/cheevos_menu.h"
#endif
#ifdef HAVE_NETWORKING
@ -10982,7 +10983,7 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type,
case DISPLAYLIST_ACHIEVEMENT_PAUSE_MENU:
#ifdef HAVE_CHEEVOS
menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list);
rcheevos_populate_hardcore_pause_menu(info);
rcheevos_menu_populate_hardcore_pause_submenu(info);
#endif
info->need_push = true;
info->need_refresh = true;
@ -10990,7 +10991,7 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type,
case DISPLAYLIST_ACHIEVEMENT_LIST:
#ifdef HAVE_CHEEVOS
menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list);
rcheevos_populate_menu(info);
rcheevos_menu_populate(info);
#endif
info->need_push = true;
info->need_refresh = true;

View File

@ -174,6 +174,7 @@
#ifdef HAVE_CHEEVOS
#include "cheevos/cheevos.h"
#include "cheevos/cheevos_menu.h"
#endif
#ifdef HAVE_TRANSLATE
@ -789,13 +790,7 @@ static int menu_dialog_iterate(
#ifdef HAVE_CHEEVOS
case MENU_DIALOG_HELP_CHEEVOS_DESCRIPTION:
{
rcheevos_ctx_desc_t desc_info;
desc_info.idx = p_dialog->current_id;
desc_info.s = s;
desc_info.len = len;
rcheevos_get_description((rcheevos_ctx_desc_t*) &desc_info);
}
rcheevos_menu_get_sublabel(p_dialog->current_id, s, len);
break;
#endif