mirror of
https://github.com/libretro/RetroArch
synced 2025-04-02 16:20:39 +00:00
validate hashes for secondary discs in multi-disc games (#13283)
This commit is contained in:
parent
339feab15b
commit
99a1ffdb89
@ -29,6 +29,7 @@
|
|||||||
#include <retro_timers.h>
|
#include <retro_timers.h>
|
||||||
#include <net/net_http.h>
|
#include <net/net_http.h>
|
||||||
#include <libretro.h>
|
#include <libretro.h>
|
||||||
|
#include <lrc_hash.h>
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "../config.h"
|
#include "../config.h"
|
||||||
@ -570,6 +571,8 @@ bool rcheevos_unload(void)
|
|||||||
|
|
||||||
/* immediately mark the game as unloaded so the ping thread will terminate normally */
|
/* immediately mark the game as unloaded so the ping thread will terminate normally */
|
||||||
rcheevos_locals.game.id = -1;
|
rcheevos_locals.game.id = -1;
|
||||||
|
rcheevos_locals.game.console_id = 0;
|
||||||
|
rcheevos_locals.game.hash = NULL;
|
||||||
|
|
||||||
#ifdef HAVE_THREADS
|
#ifdef HAVE_THREADS
|
||||||
if (rcheevos_locals.load_info.state < RCHEEVOS_LOAD_STATE_DONE &&
|
if (rcheevos_locals.load_info.state < RCHEEVOS_LOAD_STATE_DONE &&
|
||||||
@ -617,6 +620,13 @@ bool rcheevos_unload(void)
|
|||||||
rcheevos_locals.hardcore_active = false;
|
rcheevos_locals.hardcore_active = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (rcheevos_locals.game.hashes != NULL)
|
||||||
|
{
|
||||||
|
rcheevos_hash_entry_t* hash_entry = rcheevos_locals.game.hashes;
|
||||||
|
rcheevos_locals.game.hashes = hash_entry->next;
|
||||||
|
free(hash_entry);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAVE_THREADS
|
#ifdef HAVE_THREADS
|
||||||
rcheevos_locals.queued_command = CMD_EVENT_NONE;
|
rcheevos_locals.queued_command = CMD_EVENT_NONE;
|
||||||
#endif
|
#endif
|
||||||
@ -1117,7 +1127,9 @@ bool rcheevos_get_support_cheevos(void)
|
|||||||
|
|
||||||
const char* rcheevos_get_hash(void)
|
const char* rcheevos_get_hash(void)
|
||||||
{
|
{
|
||||||
return rcheevos_locals.game.hash;
|
return (rcheevos_locals.game.hash != NULL) ?
|
||||||
|
rcheevos_locals.game.hash :
|
||||||
|
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* hooks for rc_hash library */
|
/* hooks for rc_hash library */
|
||||||
@ -1315,6 +1327,11 @@ static void rcheevos_fetch_badges(void)
|
|||||||
|
|
||||||
static void rcheevos_start_session_async(retro_task_t* task)
|
static void rcheevos_start_session_async(retro_task_t* task)
|
||||||
{
|
{
|
||||||
|
const bool needs_runtime =
|
||||||
|
( rcheevos_locals.game.achievement_count > 0
|
||||||
|
|| rcheevos_locals.game.leaderboard_count > 0
|
||||||
|
|| rcheevos_locals.runtime.richpresence);
|
||||||
|
|
||||||
if (rcheevos_load_aborted())
|
if (rcheevos_load_aborted())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -1322,22 +1339,10 @@ static void rcheevos_start_session_async(retro_task_t* task)
|
|||||||
* to proceed to the next loading state */
|
* to proceed to the next loading state */
|
||||||
rcheevos_client_start_session(rcheevos_locals.game.id);
|
rcheevos_client_start_session(rcheevos_locals.game.id);
|
||||||
|
|
||||||
/* if there's nothing for the runtime to process,
|
|
||||||
* disable hardcore and bail. */
|
|
||||||
if (rcheevos_locals.game.achievement_count == 0
|
|
||||||
&& rcheevos_locals.game.leaderboard_count == 0)
|
|
||||||
{
|
|
||||||
if (!rcheevos_locals.runtime.richpresence)
|
|
||||||
{
|
|
||||||
rcheevos_pause_hardcore();
|
|
||||||
task_set_finished(task, true);
|
|
||||||
rcheevos_end_load();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rcheevos_begin_load_state(RCHEEVOS_LOAD_STATE_STARTING_SESSION);
|
rcheevos_begin_load_state(RCHEEVOS_LOAD_STATE_STARTING_SESSION);
|
||||||
|
|
||||||
|
if (needs_runtime)
|
||||||
|
{
|
||||||
/* activate the achievements and leaderboards
|
/* activate the achievements and leaderboards
|
||||||
* (rich presence has already been activated) */
|
* (rich presence has already been activated) */
|
||||||
rcheevos_activate_achievements();
|
rcheevos_activate_achievements();
|
||||||
@ -1346,10 +1351,12 @@ static void rcheevos_start_session_async(retro_task_t* task)
|
|||||||
&& rcheevos_locals.hardcore_active)
|
&& rcheevos_locals.hardcore_active)
|
||||||
rcheevos_activate_leaderboards();
|
rcheevos_activate_leaderboards();
|
||||||
|
|
||||||
|
/* disable any unsupported achievements */
|
||||||
rcheevos_validate_memrefs(&rcheevos_locals);
|
rcheevos_validate_memrefs(&rcheevos_locals);
|
||||||
|
|
||||||
/* Let the runtime start processing the achievements */
|
/* Let the runtime start processing the achievements */
|
||||||
rcheevos_locals.loaded = true;
|
rcheevos_locals.loaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
#if HAVE_REWIND
|
#if HAVE_REWIND
|
||||||
if (!rcheevos_locals.hardcore_active)
|
if (!rcheevos_locals.hardcore_active)
|
||||||
@ -1374,6 +1381,11 @@ static void rcheevos_start_session_async(retro_task_t* task)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* if there's nothing for the runtime to process,
|
||||||
|
* disable hardcore. */
|
||||||
|
if (!needs_runtime)
|
||||||
|
rcheevos_pause_hardcore();
|
||||||
|
|
||||||
task_set_finished(task, true);
|
task_set_finished(task, true);
|
||||||
|
|
||||||
if (rcheevos_end_load_state() == 0)
|
if (rcheevos_end_load_state() == 0)
|
||||||
@ -1417,9 +1429,7 @@ static void rcheevos_fetch_game_data(void)
|
|||||||
if ( rcheevos_locals.load_info.state
|
if ( rcheevos_locals.load_info.state
|
||||||
== RCHEEVOS_LOAD_STATE_NETWORK_ERROR)
|
== RCHEEVOS_LOAD_STATE_NETWORK_ERROR)
|
||||||
{
|
{
|
||||||
strlcpy(rcheevos_locals.game.hash,
|
rcheevos_locals.game.hash = NULL;
|
||||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE),
|
|
||||||
sizeof(rcheevos_locals.game.hash));
|
|
||||||
rcheevos_pause_hardcore();
|
rcheevos_pause_hardcore();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1434,9 +1444,7 @@ static void rcheevos_fetch_game_data(void)
|
|||||||
|
|
||||||
CHEEVOS_LOG(RCHEEVOS_TAG "Game could not be identified\n");
|
CHEEVOS_LOG(RCHEEVOS_TAG "Game could not be identified\n");
|
||||||
if (rcheevos_locals.load_info.hashes_tried > 1)
|
if (rcheevos_locals.load_info.hashes_tried > 1)
|
||||||
strlcpy(rcheevos_locals.game.hash,
|
rcheevos_locals.game.hash = NULL;
|
||||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE),
|
|
||||||
sizeof(rcheevos_locals.game.hash));
|
|
||||||
|
|
||||||
rcheevos_locals.load_info.state = RCHEEVOS_LOAD_STATE_UNKNOWN_GAME;
|
rcheevos_locals.load_info.state = RCHEEVOS_LOAD_STATE_UNKNOWN_GAME;
|
||||||
rcheevos_pause_hardcore();
|
rcheevos_pause_hardcore();
|
||||||
@ -1495,16 +1503,21 @@ static void rcheevos_identify_game_callback(void* userdata)
|
|||||||
(struct rcheevos_identify_game_data*)userdata;
|
(struct rcheevos_identify_game_data*)userdata;
|
||||||
|
|
||||||
if (data)
|
if (data)
|
||||||
|
{
|
||||||
|
if (rcheevos_locals.game.id == 0)
|
||||||
{
|
{
|
||||||
/* previous hash didn't match, try the next one */
|
/* previous hash didn't match, try the next one */
|
||||||
char hash[33];
|
char hash[33];
|
||||||
if ( rcheevos_locals.game.id == 0
|
if (rc_hash_iterate(hash, &data->iterator))
|
||||||
&& rc_hash_iterate(hash, &data->iterator))
|
|
||||||
{
|
{
|
||||||
|
memcpy(rcheevos_locals.game.hashes->hash, hash, sizeof(hash));
|
||||||
|
rcheevos_locals.load_info.hashes_tried++;
|
||||||
|
|
||||||
rcheevos_client_identify_game(hash,
|
rcheevos_client_identify_game(hash,
|
||||||
rcheevos_identify_game_callback, data);
|
rcheevos_identify_game_callback, data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* no more hashes generated, free the iterator data */
|
/* no more hashes generated, free the iterator data */
|
||||||
if (data->datacopy)
|
if (data->datacopy)
|
||||||
@ -1512,6 +1525,8 @@ static void rcheevos_identify_game_callback(void* userdata)
|
|||||||
free(data);
|
free(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rcheevos_locals.game.hashes->game_id = rcheevos_locals.game.id;
|
||||||
|
|
||||||
/* hash resolution complete, proceed to fetching game data */
|
/* hash resolution complete, proceed to fetching game data */
|
||||||
if (rcheevos_end_load_state() == 0)
|
if (rcheevos_end_load_state() == 0)
|
||||||
rcheevos_fetch_game_data();
|
rcheevos_fetch_game_data();
|
||||||
@ -1532,8 +1547,10 @@ static bool rcheevos_identify_game(const struct retro_game_info* info)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
strlcpy(rcheevos_locals.game.hash, hash,
|
rcheevos_locals.game.hashes = (rcheevos_hash_entry_t*)calloc(1, sizeof(rcheevos_hash_entry_t));
|
||||||
sizeof(rcheevos_locals.game.hash));
|
rcheevos_locals.game.hashes->path_djb2 = djb2_calculate(info->path);
|
||||||
|
rcheevos_locals.game.hash = rcheevos_locals.game.hashes->hash;
|
||||||
|
memcpy(rcheevos_locals.game.hashes->hash, hash, sizeof(hash));
|
||||||
rcheevos_locals.load_info.hashes_tried++;
|
rcheevos_locals.load_info.hashes_tried++;
|
||||||
|
|
||||||
if (iterator.consoles[iterator.index] == 0)
|
if (iterator.consoles[iterator.index] == 0)
|
||||||
@ -1652,6 +1669,7 @@ bool rcheevos_load(const void *data)
|
|||||||
|
|
||||||
rcheevos_locals.loaded = false;
|
rcheevos_locals.loaded = false;
|
||||||
rcheevos_locals.game.id = -1;
|
rcheevos_locals.game.id = -1;
|
||||||
|
rcheevos_locals.game.console_id = 0;
|
||||||
#ifdef HAVE_THREADS
|
#ifdef HAVE_THREADS
|
||||||
rcheevos_locals.queued_command = CMD_EVENT_NONE;
|
rcheevos_locals.queued_command = CMD_EVENT_NONE;
|
||||||
#endif
|
#endif
|
||||||
@ -1661,6 +1679,7 @@ bool rcheevos_load(const void *data)
|
|||||||
* support achievements, disable hardcore and bail */
|
* support achievements, disable hardcore and bail */
|
||||||
if (!cheevos_enable || !rcheevos_locals.core_supports || !data)
|
if (!cheevos_enable || !rcheevos_locals.core_supports || !data)
|
||||||
{
|
{
|
||||||
|
rcheevos_locals.game.id = 0;
|
||||||
rcheevos_pause_hardcore();
|
rcheevos_pause_hardcore();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1783,3 +1802,172 @@ bool rcheevos_load(const void *data)
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void rcheevos_add_hash(rcheevos_hash_entry_t* hash_entry)
|
||||||
|
{
|
||||||
|
hash_entry->next = rcheevos_locals.game.hashes;
|
||||||
|
rcheevos_locals.game.hashes = hash_entry;
|
||||||
|
rcheevos_locals.game.hash = hash_entry->hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rcheevos_identify_game_disc_callback(void* userdata)
|
||||||
|
{
|
||||||
|
rcheevos_hash_entry_t* hash_entry = (rcheevos_hash_entry_t*)userdata;
|
||||||
|
|
||||||
|
/* rcheevos_client_identify_game will update rcheevos_locals.game.id */
|
||||||
|
if (rcheevos_locals.game.id == hash_entry->game_id)
|
||||||
|
{
|
||||||
|
CHEEVOS_LOG(RCHEEVOS_TAG "Hash valid for current game\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* rcheevos_locals.game.id has the game id for the new hash, swap it with the old game id */
|
||||||
|
const int hash_game_id = rcheevos_locals.game.id;
|
||||||
|
rcheevos_locals.game.id = hash_entry->game_id;
|
||||||
|
hash_entry->game_id = hash_game_id;
|
||||||
|
|
||||||
|
if (hash_game_id != 0)
|
||||||
|
{
|
||||||
|
/* when changing discs, if the disc is recognized but belongs to another game, allow it.
|
||||||
|
* this allows loading known game discs for games that leverage user-provided discs. */
|
||||||
|
CHEEVOS_LOG(RCHEEVOS_TAG "Hash identified for game %d\n", hash_game_id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CHEEVOS_LOG(RCHEEVOS_TAG "Disc not recognized\n");
|
||||||
|
if (rcheevos_hardcore_active())
|
||||||
|
{
|
||||||
|
/* don't allow unknown game discs in hardcore.
|
||||||
|
* assume it's a modified version of the base game. */
|
||||||
|
runloop_msg_queue_push("Hardcore paused. Game disc unrecognized.", 0, 5 * 60, false, NULL,
|
||||||
|
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_ERROR);
|
||||||
|
rcheevos_pause_hardcore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* disc is valid, add it to the known disk list */
|
||||||
|
rcheevos_add_hash(hash_entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rcheevos_identify_initial_disc_callback(void* userdata)
|
||||||
|
{
|
||||||
|
rcheevos_hash_entry_t* hash_entry = (rcheevos_hash_entry_t*)userdata;
|
||||||
|
|
||||||
|
/* rcheevos_client_identify_game will update rcheevos_locals.game.id */
|
||||||
|
if (rcheevos_locals.game.id != hash_entry->game_id)
|
||||||
|
{
|
||||||
|
if (rcheevos_locals.game.id == 0)
|
||||||
|
{
|
||||||
|
CHEEVOS_LOG(RCHEEVOS_TAG "Disc not recognized\n");
|
||||||
|
runloop_msg_queue_push("Disabling achievements. Game disc unrecognized.", 0, 5 * 60, false, NULL,
|
||||||
|
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_ERROR);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CHEEVOS_LOG(RCHEEVOS_TAG "Initial disc for game %d\n", rcheevos_locals.game.id);
|
||||||
|
runloop_msg_queue_push("Disabling achievements. Not for loaded game.", 0, 5 * 60, false, NULL,
|
||||||
|
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
rcheevos_unload();
|
||||||
|
|
||||||
|
free(hash_entry);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* disc is valid, add it to the known disk list */
|
||||||
|
CHEEVOS_LOG(RCHEEVOS_TAG "Hash valid for current game\n");
|
||||||
|
rcheevos_add_hash(hash_entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rcheevos_validate_initial_disc_handler(retro_task_t* task)
|
||||||
|
{
|
||||||
|
char* new_disc_path = (char*)task->user_data;
|
||||||
|
|
||||||
|
if (rcheevos_locals.game.id == 0)
|
||||||
|
{
|
||||||
|
/* could not identify game. don't bother identifying initial disc */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (rcheevos_locals.game.console_id == 0)
|
||||||
|
{
|
||||||
|
/* not ready yet. try again in another 500ms */
|
||||||
|
task->when = cpu_features_get_time_usec() + 500 * 1000;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* game ready. attempt to validate the initial disc */
|
||||||
|
rcheevos_change_disc(new_disc_path, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(new_disc_path);
|
||||||
|
task_set_finished(task, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rcheevos_change_disc(const char* new_disc_path, bool initial_disc)
|
||||||
|
{
|
||||||
|
rcheevos_hash_entry_t* hash_entry = rcheevos_locals.game.hashes;
|
||||||
|
rcheevos_hash_entry_t* hash_entry2;
|
||||||
|
const uint32_t path_djb2 = djb2_calculate(new_disc_path);
|
||||||
|
|
||||||
|
/* no game loaded */
|
||||||
|
if (rcheevos_locals.game.id == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* see if we've already identified this file */
|
||||||
|
for (; hash_entry; hash_entry = hash_entry->next)
|
||||||
|
{
|
||||||
|
if (hash_entry->path_djb2 == path_djb2)
|
||||||
|
{
|
||||||
|
rcheevos_locals.game.hash = hash_entry->hash;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* don't check the disc until the game is done loading */
|
||||||
|
if (rcheevos_locals.game.console_id == 0)
|
||||||
|
{
|
||||||
|
retro_task_t* task = task_init();
|
||||||
|
task->handler = rcheevos_validate_initial_disc_handler;
|
||||||
|
task->user_data = strdup(new_disc_path);
|
||||||
|
task->progress = -1;
|
||||||
|
task->when = cpu_features_get_time_usec() + 500 * 1000; /* 500ms */
|
||||||
|
task_queue_push(task);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* attempt to identify the file */
|
||||||
|
hash_entry = (rcheevos_hash_entry_t*)calloc(1, sizeof(rcheevos_hash_entry_t));
|
||||||
|
hash_entry->path_djb2 = path_djb2;
|
||||||
|
|
||||||
|
if (!rc_hash_generate_from_file(hash_entry->hash, rcheevos_locals.game.console_id, new_disc_path))
|
||||||
|
{
|
||||||
|
/* when changing discs, if the disc is not supported by the system, allow it. this is
|
||||||
|
* primarily for games that support user-provided audio CDs, but does allow using discs
|
||||||
|
* from other systems for games that leverage user-provided discs. */
|
||||||
|
CHEEVOS_LOG(RCHEEVOS_TAG "No hash generated\n");
|
||||||
|
rcheevos_add_hash(hash_entry);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* assume it's for the same game. we'll validate in the callback */
|
||||||
|
hash_entry->game_id = rcheevos_locals.game.id;
|
||||||
|
|
||||||
|
/* check to see if the hash is already known - may have generated it for the m3u */
|
||||||
|
for (hash_entry2 = rcheevos_locals.game.hashes; hash_entry2; hash_entry2 = hash_entry2->next)
|
||||||
|
{
|
||||||
|
if (string_is_equal(hash_entry->hash, hash_entry2->hash))
|
||||||
|
{
|
||||||
|
CHEEVOS_LOG(RCHEEVOS_TAG "Hash valid for current game\n");
|
||||||
|
rcheevos_add_hash(hash_entry);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* call the server to make sure the hash is valid for the loaded game */
|
||||||
|
rcheevos_client_identify_game(hash_entry->hash,
|
||||||
|
initial_disc ? rcheevos_identify_initial_disc_callback :
|
||||||
|
rcheevos_identify_game_disc_callback, hash_entry);
|
||||||
|
}
|
||||||
|
@ -26,6 +26,8 @@
|
|||||||
RETRO_BEGIN_DECLS
|
RETRO_BEGIN_DECLS
|
||||||
|
|
||||||
bool rcheevos_load(const void *data);
|
bool rcheevos_load(const void *data);
|
||||||
|
void rcheevos_change_disc(const char* new_disc_path, bool initial_disc);
|
||||||
|
|
||||||
size_t rcheevos_get_serialize_size(void);
|
size_t rcheevos_get_serialize_size(void);
|
||||||
bool rcheevos_get_serialized_data(void* buffer);
|
bool rcheevos_get_serialized_data(void* buffer);
|
||||||
bool rcheevos_set_serialized_data(void* buffer);
|
bool rcheevos_set_serialized_data(void* buffer);
|
||||||
|
@ -627,6 +627,12 @@ static void rcheevos_async_login_callback(
|
|||||||
if (rcheevos_async_succeeded(result, &api_response.response,
|
if (rcheevos_async_succeeded(result, &api_response.response,
|
||||||
buffer, buffer_size))
|
buffer, buffer_size))
|
||||||
{
|
{
|
||||||
|
/* save the token to the config and clear the password on success */
|
||||||
|
settings_t* settings = config_get_ptr();
|
||||||
|
strlcpy(settings->arrays.cheevos_token, api_response.api_token,
|
||||||
|
sizeof(settings->arrays.cheevos_token));
|
||||||
|
settings->arrays.cheevos_password[0] = '\0';
|
||||||
|
|
||||||
CHEEVOS_LOG(RCHEEVOS_TAG "%s logged in successfully\n",
|
CHEEVOS_LOG(RCHEEVOS_TAG "%s logged in successfully\n",
|
||||||
api_response.username);
|
api_response.username);
|
||||||
strlcpy(rcheevos_locals->username, api_response.username,
|
strlcpy(rcheevos_locals->username, api_response.username,
|
||||||
|
@ -120,13 +120,23 @@ typedef struct rcheevos_load_info_t
|
|||||||
#endif
|
#endif
|
||||||
} rcheevos_load_info_t;
|
} rcheevos_load_info_t;
|
||||||
|
|
||||||
|
typedef struct rcheevos_hash_entry_t
|
||||||
|
{
|
||||||
|
uint32_t path_djb2;
|
||||||
|
int game_id;
|
||||||
|
struct rcheevos_hash_entry_t* next;
|
||||||
|
char hash[33];
|
||||||
|
} rcheevos_hash_entry_t;
|
||||||
|
|
||||||
typedef struct rcheevos_game_info_t
|
typedef struct rcheevos_game_info_t
|
||||||
{
|
{
|
||||||
int id;
|
int id;
|
||||||
int console_id;
|
int console_id;
|
||||||
char* title;
|
char* title;
|
||||||
char badge_name[16];
|
char badge_name[16];
|
||||||
char hash[33];
|
char* hash;
|
||||||
|
|
||||||
|
rcheevos_hash_entry_t* hashes;
|
||||||
|
|
||||||
rcheevos_racheevo_t* achievements;
|
rcheevos_racheevo_t* achievements;
|
||||||
rcheevos_ralboard_t* leaderboards;
|
rcheevos_ralboard_t* leaderboards;
|
||||||
|
@ -30,6 +30,10 @@
|
|||||||
|
|
||||||
#include "disk_control_interface.h"
|
#include "disk_control_interface.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_CHEEVOS
|
||||||
|
#include "cheevos/cheevos.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
/*****************/
|
/*****************/
|
||||||
/* Configuration */
|
/* Configuration */
|
||||||
/*****************/
|
/*****************/
|
||||||
@ -325,6 +329,11 @@ bool disk_control_set_eject_state(
|
|||||||
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_CHEEVOS
|
||||||
|
if (!error && !eject)
|
||||||
|
rcheevos_change_disc(disk_control->index_record.image_path, false);
|
||||||
|
#endif
|
||||||
|
|
||||||
return !error;
|
return !error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -773,6 +782,11 @@ bool disk_control_verify_initial_index(
|
|||||||
0, msg_duration,
|
0, msg_duration,
|
||||||
false, NULL,
|
false, NULL,
|
||||||
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||||
|
|
||||||
|
#ifdef HAVE_CHEEVOS
|
||||||
|
if (image_index > 0)
|
||||||
|
rcheevos_change_disc(disk_control->index_record.image_path, true);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user