Skip to content

Commit

Permalink
【rcheevos】Improved UI and fixed image life cycle management bugs.
Browse files Browse the repository at this point in the history
  • Loading branch information
skylersaleh committed Sep 14, 2023
1 parent f256f95 commit 4e69115
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 51 deletions.
126 changes: 90 additions & 36 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,6 @@ const static char* se_analog_bind_names[]={
//a users settings.
#define SE_NUM_BINDS_ALLOC 64

#define GUI_MAX_IMAGES_PER_FRAME 16
#define SE_NUM_RECENT_PATHS 32
#define SE_FONT_CACHE_PAGE_SIZE 16
#define SE_MAX_UNICODE_CODE_POINT 0xffff
Expand Down Expand Up @@ -258,11 +257,14 @@ typedef struct{
char name[SE_MAX_BIOS_FILES][SE_BIOS_NAME_SIZE];
bool success[SE_MAX_BIOS_FILES];
}se_bios_info_t;
typedef struct se_deferred_image_free_t{
sg_image image;
struct se_deferred_image_free_t * next;
}se_deferred_image_free_t;
typedef struct {
uint64_t laptime;
sg_pass_action pass_action;
sg_image image_stack[GUI_MAX_IMAGES_PER_FRAME];
int current_image;
se_deferred_image_free_t * image_free_list;
int screen_width;
int screen_height;
float dpi_override;
Expand Down Expand Up @@ -413,6 +415,9 @@ void se_load_cheats(const char * filename);
void se_save_cheats(const char* filename);
void se_convert_cheat_code(char * text_code, int cheat_index);
static void se_reset_core();
double se_time();
void se_push_disabled();
void se_pop_disabled();

static const char* se_get_pref_path(){
#if defined(EMSCRIPTEN)
Expand Down Expand Up @@ -483,13 +488,15 @@ static inline bool se_checkbox(const char* label, bool * v){
static void se_text(const char* label,...){
va_list args;
va_start(args, label);
igTextV(se_localize_and_cache(label),args);
igTextWrappedV(se_localize_and_cache(label),args);
va_end(args);
}
static void se_text_disabled(const char* label,...){
va_list args;
va_start(args, label);
igTextDisabledV(se_localize_and_cache(label),args);
se_push_disabled();
igTextWrappedV(se_localize_and_cache(label),args);
se_pop_disabled();
va_end(args);
}
static bool se_combo_str(const char* label,int* current_item,const char* items_separated_by_zeros,int popup_max_height_in_items){
Expand Down Expand Up @@ -1143,17 +1150,24 @@ bool se_key_is_pressed(int keycode){
return gui_state.button_state[keycode];
}
static sg_image* se_get_image(){
if(gui_state.current_image<GUI_MAX_IMAGES_PER_FRAME){
gui_state.current_image++;
return gui_state.image_stack + gui_state.current_image-1;
}
return NULL;
se_deferred_image_free_t * tmp_image = (se_deferred_image_free_t*)calloc(1,sizeof(se_deferred_image_free_t));
tmp_image->next = gui_state.image_free_list;
gui_state.image_free_list = tmp_image;
return &tmp_image->image;
}
static void se_free_image_deferred(sg_image image){
se_deferred_image_free_t * tmp_image = (se_deferred_image_free_t*)calloc(1,sizeof(se_deferred_image_free_t));
tmp_image->next = gui_state.image_free_list;
tmp_image->image=image;
gui_state.image_free_list = tmp_image;
}
static void se_free_all_images(){
for(int i=0;i<gui_state.current_image;++i){
sg_destroy_image(gui_state.image_stack[i]);
while(gui_state.image_free_list){
se_deferred_image_free_t * tmp = gui_state.image_free_list;
sg_destroy_image(tmp->image);
gui_state.image_free_list=tmp->next;
free(tmp);
}
gui_state.current_image=0;
}
typedef uint8_t (*emu_byte_read_t)(uint64_t address);
typedef void (*emu_byte_write_t)(uint64_t address,uint8_t data);
Expand Down Expand Up @@ -1334,8 +1348,8 @@ static void se_ra_load_image_callback(const uint8_t* pixel_data, size_t image_si
.usage= SG_USAGE_IMMUTABLE,
.pixel_format= SG_PIXELFORMAT_RGBA8,
.sample_count= 1,
.min_filter= SG_FILTER_NEAREST,
.mag_filter= SG_FILTER_NEAREST,
.min_filter= SG_FILTER_LINEAR,
.mag_filter= SG_FILTER_LINEAR,
.wrap_u= SG_WRAP_CLAMP_TO_EDGE,
.wrap_v= SG_WRAP_CLAMP_TO_EDGE,
.wrap_w= SG_WRAP_CLAMP_TO_EDGE,
Expand All @@ -1353,7 +1367,7 @@ static void se_ra_load_image_callback(const uint8_t* pixel_data, size_t image_si
}
static void se_ra_game_cleanup(){
if(ra_info.image.id != SG_INVALID_ID){
sg_destroy_image(ra_info.image);
se_free_image_deferred(ra_info.image);
ra_info.image.id = SG_INVALID_ID;
}
if (ra_info.achievement_list){
Expand All @@ -1364,7 +1378,7 @@ static void se_ra_game_cleanup(){
for (int j = 0; j < ra_info.achievement_list->buckets[i].num_achievements; j++)
{
if(ra_info.achievement_images[i][j].id != SG_INVALID_ID)
sg_destroy_image(ra_info.achievement_images[i][j]);
se_free_image_deferred(ra_info.achievement_images[i][j]);
}
free(ra_info.achievement_images[i]);
}
Expand All @@ -1380,15 +1394,10 @@ static void se_ra_load_game_callback(int result, const char* error_message, rc_c
if (result != RC_OK){
// TODO: notification error message?
printf("[rcheevos]: failed to load game: %s\n", error_message);
lock_mutex(ra_info.mutex);
se_ra_game_cleanup();
unlock_mutex(ra_info.mutex);
return;
}

lock_mutex(ra_info.mutex);
se_ra_game_cleanup();

char url[512];
const rc_client_game_t* game = rc_client_get_game_info(ra_get_client());
if (rc_client_game_get_image_url(game, url, sizeof(url)) == RC_OK){
Expand Down Expand Up @@ -2040,6 +2049,7 @@ void se_load_rom_from_emu_state(sb_emu_state_t*emu){
}
}
void se_load_rom(const char *filename){
se_ra_game_cleanup();
se_reset_rewind_buffer(&rewind_buffer);
se_reset_save_states();
se_reset_cheats();
Expand Down Expand Up @@ -3849,6 +3859,49 @@ bool se_selectable_with_box(const char * first_label, const char* second_label,
#endif
return clicked;
}

void se_boxed_image_dual_label(const char * first_label, const char* second_label, const char* box, sg_image* image, int reduce_width){
ImVec2 win_min,win_sz,win_max;
win_min.x=0;
win_min.y=0; // content boundaries min (roughly (0,0)-Scroll), in window coordinates
igGetWindowSize(&win_sz);
win_min.y+=igGetScrollY();
win_max.x = win_min.x+win_sz.x;
win_max.y = win_min.y+win_sz.y;

int item_height = 50;
int padding = 4;

float disp_y_min = igGetCursorPosY();
float disp_y_max = disp_y_min+item_height+padding*2;
//Early out if not visible (helps for long lists)
if(disp_y_max<win_min.y||disp_y_min>win_max.y){
igSetCursorPosY(disp_y_max);
return;
}
int box_h = item_height-padding*2;
int box_w = box_h;
igPushIDStr(second_label);
ImVec2 curr_pos;
igGetCursorPos(&curr_pos);
ImVec2 next_pos=curr_pos;
next_pos.y+=box_h+padding*2;
curr_pos.y+=padding;
igSetCursorPos(curr_pos);

igSetCursorPosX(curr_pos.x+box_w+padding);
igSetCursorPosY(curr_pos.y-padding);
se_text(first_label);
igSetCursorPosX(curr_pos.x+box_w+padding);
igSetCursorPosY(igGetCursorPosY()-5);
se_text_disabled(second_label);
igSetCursorPos(curr_pos);
if(image)igImageButton((ImTextureID)(intptr_t)image->id,(ImVec2){box_w,box_h},(ImVec2){0,0},(ImVec2){1,1},0,(ImVec4){1,1,1,1},(ImVec4){1,1,1,1});
else se_text_centered_in_box((ImVec2){0,0}, (ImVec2){box_w,box_h},box);
igDummy((ImVec2){1,1});
igSetCursorPos(next_pos);
igPopID();
}
#ifdef PLATFORM_ANDROID
#include <android/log.h>

Expand Down Expand Up @@ -5283,32 +5336,33 @@ void se_draw_menu_panel(){
}
}else {
const rc_client_game_t* game = rc_client_get_game_info(ra_get_client());
ImVec2 pos;
sg_image * image = NULL;
const char* play_string = "No Game Loaded";
char line1[256];
char line2[256];
snprintf(line1,256,se_localize_and_cache("Logged in as %s"),user->display_name);
if(game){
if(ra_info.image.id!=SG_INVALID_ID){
igImageButton((ImTextureID)(intptr_t)ra_info.image.id,(ImVec2){32,32},(ImVec2){0,0},(ImVec2){1,1},0,(ImVec4){1,1,1,1},(ImVec4){1,1,1,1});
igSameLine(0,10);
se_text("%s",game->title);
igSeparator();
}
}
se_text("Logged in as %s",user->display_name);
igSameLine(win_w-40,0);
if(se_button("Logout", (ImVec2){0,0})){
if(ra_info.image.id!=SG_INVALID_ID)image=&ra_info.image;
snprintf(line2,256,se_localize_and_cache("Playing: %s"),game->title);
}else snprintf(line2,256,"%s",se_localize_and_cache("No Game Loaded"));
se_boxed_image_dual_label(line1,line2, ICON_FK_TROPHY, image, 0);
if(se_button(ICON_FK_TIMES_CIRCLE " Logout", (ImVec2){0,0})){
char login_info_path[SB_FILE_PATH_SIZE];
snprintf(login_info_path,SB_FILE_PATH_SIZE,"%sra_login_info.txt",se_get_pref_path());
remove(login_info_path);
ra_logout();
}
igSeparator();
if (ra_info.achievement_list){
for (int i = 0; i < ra_info.achievement_list->num_buckets; i++){
se_text(ICON_FK_LOCK " %s",ra_info.achievement_list->buckets[i].label);
for (int j = 0; j < ra_info.achievement_list->buckets[i].num_achievements; j++){
sg_image * image = NULL;
if(ra_info.achievement_images && ra_info.achievement_images[i] && ra_info.achievement_images[i][j].id!=SG_INVALID_ID){
igImageButton((ImTextureID)(intptr_t)ra_info.achievement_images[i][j].id,(ImVec2){32,32},(ImVec2){0,0},(ImVec2){1,1},0,(ImVec4){1,1,1,1},(ImVec4){1,1,1,1});
se_text("%s",ra_info.achievement_list->buckets[i].achievements[j]->title);
se_text("%s",ra_info.achievement_list->buckets[i].achievements[j]->description);
image = &ra_info.achievement_images[i][j];
}
se_boxed_image_dual_label(ra_info.achievement_list->buckets[i].achievements[j]->title,
ra_info.achievement_list->buckets[i].achievements[j]->description, ICON_FK_SPINNER, image, 0);
}
}
}
Expand Down
13 changes: 0 additions & 13 deletions src/retro_achievements.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,19 +194,6 @@ void ra_load_game(const uint8_t *rom, size_t rom_size, int console_id, rc_client
}, rom, rom_size, console_id, callback);
load_game_thread.detach();
}

int ra_get_game_id()
{
const rc_client_game_t* game = rc_client_get_game_info(ra_client);
return game->id;
}

void ra_get_game_title(char* buffer, size_t buffer_size)
{
const rc_client_game_t* game = rc_client_get_game_info(ra_client);
strncpy(buffer, game->title, buffer_size);
}

static void ra_get_image_callback(const rc_api_server_response_t* server_response, void* callback_data)
{
ImageCallbackData* data = (ImageCallbackData*)callback_data;
Expand Down
2 changes: 0 additions & 2 deletions src/retro_achievements.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ void ra_poll_requests();
void ra_shutdown_client();
void ra_logout();
void ra_load_game(const uint8_t* rom, size_t rom_size, int console_id, rc_client_callback_t callback);
int ra_get_game_id();
void ra_get_game_title(char* buffer, size_t buffer_size);
void ra_get_image(const char* url, get_image_callback_t callback, void* userdata);
rc_client_t* ra_get_client();
#endif

0 comments on commit 4e69115

Please sign in to comment.