Skip to content

Commit

Permalink
[Achievements]Thread safety improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
OFFTKP committed Sep 6, 2023
1 parent 4d02b87 commit b8c6873
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 28 deletions.
4 changes: 3 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,9 @@ add_definitions(-DGIT_COMMIT_HASH=\"${GIT_COMMIT_HASH}\")
add_definitions(-DGIT_BRANCH=\"${GIT_BRANCH}\")
add_definitions(-DGIT_TAG=\"${GIT_TAG}\")

set(SKYEMU_SRC src/main.c src/stb.c src/miniz.c src/res.c src/localization.c)
add_compile_options(-fsanitize=address)
add_link_options(-fsanitize=address)
set(SKYEMU_SRC src/main.c src/stb.c src/miniz.c src/res.c src/localization.c src/recursive_mutex.cpp)

if(ENABLE_HTTP_CONTROL_SERVER)
add_definitions(-DENABLE_HTTP_CONTROL_SERVER=1)
Expand Down
48 changes: 24 additions & 24 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#endif

#ifdef ENABLE_RETRO_ACHIEVEMENTS
#include "retro_achievements.h"
#include "rcheevos/include/rc_client.h"
#include "rcheevos/include/rc_consoles.h"
#endif
Expand All @@ -28,7 +29,7 @@
#include "capstone/include/capstone/capstone.h"
#include "miniz.h"
#include "localization.h"
#include "retro_achievements.h"
#include "recursive_mutex.h"

#if defined(EMSCRIPTEN)
#include <emscripten.h>
Expand Down Expand Up @@ -391,6 +392,7 @@ typedef struct{
sg_image image;
rc_client_achievement_list_t* achievement_list;
sg_image** achievement_images;
recursive_mutex_t mutex;
}se_ra_info_t;
gui_state_t gui_state={ .update_font_atlas=true };

Expand Down Expand Up @@ -1334,6 +1336,7 @@ static void se_ra_login_callback(int result, const char* error_message, rc_clien
}
}
static void se_ra_load_game_image_callback(const uint8_t* pixel_data, size_t image_size, int width, int height, void* user_data){
lock_mutex(ra_info.mutex);
if(pixel_data){
sg_image_data im_data={0};
im_data.subimage[0][0].ptr = pixel_data;
Expand Down Expand Up @@ -1363,8 +1366,10 @@ static void se_ra_load_game_image_callback(const uint8_t* pixel_data, size_t ima
}else{
printf("[rcheevos]: failed to load game image\n");
}
unlock_mutex(ra_info.mutex);
}
static void se_ra_load_achievement_image_callback(const uint8_t* pixel_data, size_t image_size, int width, int height, void* user_data){
lock_mutex(ra_info.mutex);
sg_image* achievement_image=(sg_image*)user_data;
if(pixel_data){
sg_image_data im_data={0};
Expand Down Expand Up @@ -1395,6 +1400,7 @@ static void se_ra_load_achievement_image_callback(const uint8_t* pixel_data, siz
}else{
printf("[rcheevos]: failed to load game image\n");
}
unlock_mutex(ra_info.mutex);
}
static void se_ra_load_game_callback(int result, const char* error_message, rc_client_t* client, void* userdata){
if (result != RC_OK){
Expand All @@ -1407,27 +1413,21 @@ static void se_ra_load_game_callback(int result, const char* error_message, rc_c
return;
}

lock_mutex(ra_info.mutex);
if(ra_info.image.id != SG_INVALID_ID){
sg_destroy_image(ra_info.image);
ra_info.image.id = SG_INVALID_ID;
}

ra_info.game_id = ra_get_game_id();
ra_get_game_title(ra_info.game_title, sizeof(ra_info.game_title));

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)
{
printf("[rcheevos]: could not get game image URL\n");
return;
if (rc_client_game_get_image_url(game, url, sizeof(url)) == RC_OK){
ra_get_image(url, se_ra_load_game_image_callback, NULL);
}
ra_get_image(url, se_ra_load_game_image_callback, NULL);

if (ra_info.achievement_list){
rc_client_destroy_achievement_list(ra_info.achievement_list);
ra_info.achievement_list = NULL;

for (int i = 0; i < ra_info.achievement_list->num_buckets; i++)
{
if(ra_info.achievement_images[i] != NULL)
Expand All @@ -1440,8 +1440,10 @@ static void se_ra_load_game_callback(int result, const char* error_message, rc_c
free(ra_info.achievement_images[i]);
}
}
if(ra_info.achievement_images)
free(ra_info.achievement_images);
free(ra_info.achievement_images);

rc_client_destroy_achievement_list(ra_info.achievement_list);
ra_info.achievement_list = NULL;
}

ra_info.achievement_list = rc_client_create_achievement_list(ra_get_client(),
Expand All @@ -1452,6 +1454,7 @@ static void se_ra_load_game_callback(int result, const char* error_message, rc_c
{
uint32_t num_achievements=ra_info.achievement_list->buckets[i].num_achievements;
ra_info.achievement_images[i] = (sg_image*)malloc(sizeof(sg_image)*num_achievements);
memset(ra_info.achievement_images[i], 0, sizeof(sg_image)*num_achievements);
for (int j = 0; j < num_achievements; j++)
{
char url[512];
Expand All @@ -1470,6 +1473,7 @@ static void se_ra_load_game_callback(int result, const char* error_message, rc_c
printf("locked\n");
}
}
unlock_mutex(ra_info.mutex);
}
static void se_ra_event_handler(const rc_client_event_t* event, rc_client_t* client){
switch (event->type)
Expand All @@ -1490,6 +1494,7 @@ static void se_init_retro_achievements(){
ra_info.image.id = SG_INVALID_ID;
ra_info.achievement_list = NULL;
ra_info.achievement_images = NULL;
ra_info.mutex = create_mutex();
ra_initialize_client(se_ra_read_memory_callback);
rc_client_set_event_handler(ra_get_client(),se_ra_event_handler);

Expand All @@ -1501,19 +1506,10 @@ static void se_init_retro_achievements(){
memset(text, 0, sizeof(text));
if (sb_load_file_data_into_buffer(login_info_path, text, sizeof(text))){
int username_length = strchr(text, '\n') - text;
if(username_length>256){
printf("Saved RetroAchievements username too long\n");
return;
}
memcpy(ra_info.username, text, username_length);
strncpy(ra_info.username, text, username_length);
int password_length = strchr(text + username_length + 1, '\0') - (text + username_length + 1);
char token[256];
memset(token, 0, sizeof(token));
if(password_length>256){
printf("Saved RetroAchievements token too long\n");
return;
}
memcpy(token, text + username_length + 1, password_length);
strncpy(token, text + username_length + 1, password_length);
ra_login_token(ra_info.username, token, se_ra_login_callback);
}
}
Expand Down Expand Up @@ -5334,7 +5330,7 @@ void se_draw_menu_panel(){
for (int j = 0; j < ra_info.achievement_list->buckets[i].num_achievements; j++){
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]->title);
}
}
}
Expand Down Expand Up @@ -5938,6 +5934,7 @@ static void frame(void) {
#ifdef ENABLE_RETRO_ACHIEVEMENTS
ra_poll_requests();
rc_client_do_frame(ra_get_client());
lock_mutex(ra_info.mutex);
#endif
se_reset_html_click_regions();
sb_poll_controller_input(&emu_state.joy);
Expand Down Expand Up @@ -6336,6 +6333,9 @@ static void frame(void) {
se_emscripten_flush_fs();
gui_state.last_saved_settings=gui_state.settings;
}
#ifdef ENABLE_RETRO_ACHIEVEMENTS
unlock_mutex(ra_info.mutex);
#endif
}
void se_load_settings(){
se_load_recent_games_list();
Expand Down
21 changes: 21 additions & 0 deletions src/recursive_mutex.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
extern "C" {
#include "recursive_mutex.h"
}
#include <mutex>

recursive_mutex_t create_mutex() {
recursive_mutex_t mutex = new std::recursive_mutex;
return mutex;
}

void destroy_mutex(recursive_mutex_t mutex) {
delete (std::recursive_mutex*)mutex;
}

void lock_mutex(recursive_mutex_t mutex) {
((std::recursive_mutex*)mutex)->lock();
}

void unlock_mutex(recursive_mutex_t mutex) {
((std::recursive_mutex*)mutex)->unlock();
}
8 changes: 8 additions & 0 deletions src/recursive_mutex.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#ifndef RECURSIVE_MUTEX_WRAPPER
#define RECURSIVE_MUTEX_WRAPPER
typedef void* recursive_mutex_t;
recursive_mutex_t create_mutex();
void destroy_mutex(recursive_mutex_t mutex);
void lock_mutex(recursive_mutex_t mutex);
void unlock_mutex(recursive_mutex_t mutex);
#endif
14 changes: 11 additions & 3 deletions src/retro_achievements.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,12 @@ void ra_poll_requests()

void ra_login_token(const char* username, const char* token, rc_client_callback_t login_callback)
{
rc_client_begin_login_with_token(ra_client, username, token, login_callback, NULL);
std::string username_str = username;
std::string token_str = token;
std::thread login_thread([=](){
rc_client_begin_login_with_token(ra_client, username_str.c_str(), token_str.c_str(), login_callback, NULL);
});
login_thread.detach();
}

void ra_logout()
Expand All @@ -183,8 +188,11 @@ void ra_logout()

void ra_load_game(const uint8_t *rom, size_t rom_size, int console_id, rc_client_callback_t callback)
{
rc_client_begin_identify_and_load_game(ra_client, console_id,
NULL, rom, rom_size, callback, NULL);
std::thread load_thread([=](){
rc_client_begin_identify_and_load_game(ra_client, console_id,
NULL, rom, rom_size, callback, NULL);
});
load_thread.detach();
}

int ra_get_game_id()
Expand Down

0 comments on commit b8c6873

Please sign in to comment.