mirror of
https://github.com/libretro/RetroArch.git
synced 2024-11-26 17:50:56 +00:00
update to rcheevos 11.6 (#17088)
This commit is contained in:
parent
228426880b
commit
ec314b9e43
11
deps/rcheevos/CHANGELOG.md
vendored
11
deps/rcheevos/CHANGELOG.md
vendored
@ -1,3 +1,14 @@
|
||||
# v11.6.0
|
||||
* backdate retried unlocks in rc_client
|
||||
* add memory map and hash method for RC_CONSOLE_ZX_SPECTRUM
|
||||
* add RC_CONSOLE_GAMECUBE to supported consoles for iso file extension
|
||||
* add DTCM to RC_CONSOLE_NINTENDO_DS and RC_CONSOLE_NINTENDO_DSI memory maps
|
||||
* don't report conflict if last conditions of OrNext chain conflict
|
||||
* don't report conflict if last conditions of AddSource chain conflict
|
||||
* fix hits not being reset on leaderboard value when start and submit are both true in a single frame
|
||||
* fix crash when multiple items in a CSV lookup overlap
|
||||
* fix crash if game is unloaded while activating achievements
|
||||
|
||||
# v11.5.0
|
||||
* add total_entries to rc_api_fetch_leaderboard_info_response_t
|
||||
* add RC_CLIENT_RAINTEGRATION_EVENT_MENU_CHANGED event
|
||||
|
4
deps/rcheevos/include/rc_api_runtime.h
vendored
4
deps/rcheevos/include/rc_api_runtime.h
vendored
@ -220,6 +220,8 @@ typedef struct rc_api_award_achievement_request_t {
|
||||
uint32_t hardcore;
|
||||
/* The hash associated to the game being played */
|
||||
const char* game_hash;
|
||||
/* The number of seconds since the achievement was unlocked */
|
||||
uint32_t seconds_since_unlock;
|
||||
}
|
||||
rc_api_award_achievement_request_t;
|
||||
|
||||
@ -263,6 +265,8 @@ typedef struct rc_api_submit_lboard_entry_request_t {
|
||||
int32_t score;
|
||||
/* The hash associated to the game being played */
|
||||
const char* game_hash;
|
||||
/* The number of seconds since the leaderboard attempt was completed */
|
||||
uint32_t seconds_since_completion;
|
||||
}
|
||||
rc_api_submit_lboard_entry_request_t;
|
||||
|
||||
|
17
deps/rcheevos/src/rapi/rc_api_runtime.c
vendored
17
deps/rcheevos/src/rapi/rc_api_runtime.c
vendored
@ -412,6 +412,8 @@ int rc_api_init_award_achievement_request(rc_api_request_t* request, const rc_ap
|
||||
rc_url_builder_append_unum_param(&builder, "h", api_params->hardcore ? 1 : 0);
|
||||
if (api_params->game_hash && *api_params->game_hash)
|
||||
rc_url_builder_append_str_param(&builder, "m", api_params->game_hash);
|
||||
if (api_params->seconds_since_unlock)
|
||||
rc_url_builder_append_unum_param(&builder, "o", api_params->seconds_since_unlock);
|
||||
|
||||
/* Evaluate the signature. */
|
||||
md5_init(&md5);
|
||||
@ -420,6 +422,14 @@ int rc_api_init_award_achievement_request(rc_api_request_t* request, const rc_ap
|
||||
md5_append(&md5, (md5_byte_t*)api_params->username, (int)strlen(api_params->username));
|
||||
snprintf(buffer, sizeof(buffer), "%d", api_params->hardcore ? 1 : 0);
|
||||
md5_append(&md5, (md5_byte_t*)buffer, (int)strlen(buffer));
|
||||
if (api_params->seconds_since_unlock) {
|
||||
/* second achievement id is needed by delegated unlock. including it here allows overloading
|
||||
* the hash generating code on the server */
|
||||
snprintf(buffer, sizeof(buffer), "%u", api_params->achievement_id);
|
||||
md5_append(&md5, (md5_byte_t*)buffer, (int)strlen(buffer));
|
||||
snprintf(buffer, sizeof(buffer), "%u", api_params->seconds_since_unlock);
|
||||
md5_append(&md5, (md5_byte_t*)buffer, (int)strlen(buffer));
|
||||
}
|
||||
md5_finish(&md5, digest);
|
||||
rc_format_md5(buffer, digest);
|
||||
rc_url_builder_append_str_param(&builder, "v", buffer);
|
||||
@ -505,6 +515,9 @@ int rc_api_init_submit_lboard_entry_request(rc_api_request_t* request, const rc_
|
||||
if (api_params->game_hash && *api_params->game_hash)
|
||||
rc_url_builder_append_str_param(&builder, "m", api_params->game_hash);
|
||||
|
||||
if (api_params->seconds_since_completion)
|
||||
rc_url_builder_append_unum_param(&builder, "o", api_params->seconds_since_completion);
|
||||
|
||||
/* Evaluate the signature. */
|
||||
md5_init(&md5);
|
||||
snprintf(buffer, sizeof(buffer), "%u", api_params->leaderboard_id);
|
||||
@ -512,6 +525,10 @@ int rc_api_init_submit_lboard_entry_request(rc_api_request_t* request, const rc_
|
||||
md5_append(&md5, (md5_byte_t*)api_params->username, (int)strlen(api_params->username));
|
||||
snprintf(buffer, sizeof(buffer), "%d", api_params->score);
|
||||
md5_append(&md5, (md5_byte_t*)buffer, (int)strlen(buffer));
|
||||
if (api_params->seconds_since_completion) {
|
||||
snprintf(buffer, sizeof(buffer), "%u", api_params->seconds_since_completion);
|
||||
md5_append(&md5, (md5_byte_t*)buffer, (int)strlen(buffer));
|
||||
}
|
||||
md5_finish(&md5, digest);
|
||||
rc_format_md5(buffer, digest);
|
||||
rc_url_builder_append_str_param(&builder, "v", buffer);
|
||||
|
117
deps/rcheevos/src/rc_client.c
vendored
117
deps/rcheevos/src/rc_client.c
vendored
@ -1434,7 +1434,6 @@ static void rc_client_activate_game(rc_client_load_state_t* load_state, rc_api_s
|
||||
rc_mutex_lock(&client->state.mutex);
|
||||
load_state->progress = (client->state.load == load_state) ?
|
||||
RC_CLIENT_LOAD_GAME_STATE_DONE : RC_CLIENT_LOAD_GAME_STATE_ABORTED;
|
||||
client->state.load = NULL;
|
||||
rc_mutex_unlock(&client->state.mutex);
|
||||
|
||||
if (load_state->progress != RC_CLIENT_LOAD_GAME_STATE_DONE) {
|
||||
@ -1455,17 +1454,15 @@ static void rc_client_activate_game(rc_client_load_state_t* load_state, rc_api_s
|
||||
start_session_response->num_unlocks, RC_CLIENT_ACHIEVEMENT_UNLOCKED_SOFTCORE);
|
||||
}
|
||||
|
||||
/* make the loaded game active if another game is not aleady being loaded. */
|
||||
rc_mutex_lock(&client->state.mutex);
|
||||
if (client->state.load == NULL)
|
||||
if (client->state.load == load_state)
|
||||
client->game = load_state->game;
|
||||
else
|
||||
load_state->progress = RC_CLIENT_LOAD_GAME_STATE_ABORTED;
|
||||
rc_mutex_unlock(&client->state.mutex);
|
||||
|
||||
if (client->game != load_state->game) {
|
||||
/* previous load state was aborted */
|
||||
if (load_state->callback)
|
||||
load_state->callback(RC_ABORTED, "The requested game is no longer active", client, load_state->callback_userdata);
|
||||
}
|
||||
else {
|
||||
if (load_state->progress != RC_CLIENT_LOAD_GAME_STATE_ABORTED) {
|
||||
/* if a change media request is pending, kick it off */
|
||||
rc_client_pending_media_t* pending_media;
|
||||
|
||||
@ -1475,6 +1472,9 @@ static void rc_client_activate_game(rc_client_load_state_t* load_state, rc_api_s
|
||||
rc_mutex_unlock(&load_state->client->state.mutex);
|
||||
|
||||
if (pending_media) {
|
||||
/* rc_client_check_pending_media will fail if it can't find the game in client->game or
|
||||
* client->state.load->game. since we've detached the load_state, this has to occur after
|
||||
* we've made the game active. */
|
||||
if (pending_media->hash) {
|
||||
rc_client_begin_change_media_from_hash(client, pending_media->hash,
|
||||
pending_media->callback, pending_media->callback_userdata);
|
||||
@ -1488,12 +1488,50 @@ static void rc_client_activate_game(rc_client_load_state_t* load_state, rc_api_s
|
||||
rc_client_free_pending_media(pending_media);
|
||||
}
|
||||
|
||||
/* client->game must be set before calling this function so it can query the console_id */
|
||||
rc_mutex_lock(&client->state.mutex);
|
||||
if (client->state.load != load_state)
|
||||
load_state->progress = RC_CLIENT_LOAD_GAME_STATE_ABORTED;
|
||||
rc_mutex_unlock(&client->state.mutex);
|
||||
}
|
||||
|
||||
/* if the game is still being loaded, make sure all the required memory addresses are accessible
|
||||
* so we can mark achievements as unsupported before loading them into the runtime. */
|
||||
if (load_state->progress != RC_CLIENT_LOAD_GAME_STATE_ABORTED) {
|
||||
/* TODO: it is desirable to not do memory reads from a background thread. Some emulators (like Dolphin) don't
|
||||
* allow it. Dolphin's solution is to use a dummy read function that says all addresses are valid and
|
||||
* switches to the actual read function after the callback is called. latter invalid reads will
|
||||
* mark achievements as unsupported. */
|
||||
|
||||
/* ASSERT: client->game must be set before calling this function so the read_memory callback can query the console_id */
|
||||
rc_client_validate_addresses(load_state->game, client);
|
||||
|
||||
rc_mutex_lock(&client->state.mutex);
|
||||
if (client->state.load != load_state)
|
||||
load_state->progress = RC_CLIENT_LOAD_GAME_STATE_ABORTED;
|
||||
rc_mutex_unlock(&client->state.mutex);
|
||||
}
|
||||
|
||||
/* if the game is still being loaded, load any active acheivements/leaderboards into the runtime */
|
||||
if (load_state->progress != RC_CLIENT_LOAD_GAME_STATE_ABORTED) {
|
||||
rc_client_activate_achievements(load_state->game, client);
|
||||
rc_client_activate_leaderboards(load_state->game, client);
|
||||
|
||||
/* detach the load state to indicate that loading is fully complete */
|
||||
rc_mutex_lock(&client->state.mutex);
|
||||
if (client->state.load == load_state)
|
||||
client->state.load = NULL;
|
||||
else
|
||||
load_state->progress = RC_CLIENT_LOAD_GAME_STATE_ABORTED;
|
||||
rc_mutex_unlock(&client->state.mutex);
|
||||
}
|
||||
|
||||
/* one last sanity check to make sure the game is still being loaded. */
|
||||
if (load_state->progress == RC_CLIENT_LOAD_GAME_STATE_ABORTED) {
|
||||
/* game has been unloaded, or another game is being loaded over the top of this game */
|
||||
if (load_state->callback)
|
||||
load_state->callback(RC_ABORTED, "The requested game is no longer active", client, load_state->callback_userdata);
|
||||
}
|
||||
else {
|
||||
if (load_state->hash->hash[0] != '[') {
|
||||
if (load_state->client->state.spectator_mode != RC_CLIENT_SPECTATOR_MODE_LOCKED) {
|
||||
/* schedule the periodic ping */
|
||||
@ -2001,7 +2039,6 @@ static int rc_client_attach_load_state(rc_client_t* client, rc_client_load_state
|
||||
{
|
||||
if (client->state.load == NULL) {
|
||||
rc_client_unload_game(client);
|
||||
client->state.load = load_state;
|
||||
|
||||
if (load_state->game == NULL) {
|
||||
load_state->game = rc_client_allocate_game();
|
||||
@ -2012,6 +2049,10 @@ static int rc_client_attach_load_state(rc_client_t* client, rc_client_load_state
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
rc_mutex_lock(&client->state.mutex);
|
||||
client->state.load = load_state;
|
||||
rc_mutex_unlock(&client->state.mutex);
|
||||
}
|
||||
else if (client->state.load != load_state) {
|
||||
/* previous load was aborted */
|
||||
@ -2615,8 +2656,6 @@ static void rc_client_game_mark_ui_to_be_hidden(rc_client_t* client, rc_client_g
|
||||
void rc_client_unload_game(rc_client_t* client)
|
||||
{
|
||||
rc_client_game_info_t* game;
|
||||
rc_client_scheduled_callback_data_t** last;
|
||||
rc_client_scheduled_callback_data_t* next;
|
||||
|
||||
if (!client)
|
||||
return;
|
||||
@ -2643,29 +2682,38 @@ void rc_client_unload_game(rc_client_t* client)
|
||||
if (client->state.load) {
|
||||
/* this mimics rc_client_abort_async without nesting the lock */
|
||||
client->state.load->async_handle.aborted = RC_CLIENT_ASYNC_ABORTED;
|
||||
|
||||
/* if the game is still being loaded, let the load process clean it up */
|
||||
if (client->state.load->game == game)
|
||||
game = NULL;
|
||||
|
||||
client->state.load = NULL;
|
||||
}
|
||||
|
||||
if (client->state.spectator_mode == RC_CLIENT_SPECTATOR_MODE_LOCKED)
|
||||
client->state.spectator_mode = RC_CLIENT_SPECTATOR_MODE_ON;
|
||||
|
||||
if (game != NULL)
|
||||
if (game != NULL) {
|
||||
rc_client_scheduled_callback_data_t** last;
|
||||
rc_client_scheduled_callback_data_t* next;
|
||||
|
||||
rc_client_game_mark_ui_to_be_hidden(client, game);
|
||||
|
||||
last = &client->state.scheduled_callbacks;
|
||||
do {
|
||||
next = *last;
|
||||
if (!next)
|
||||
break;
|
||||
last = &client->state.scheduled_callbacks;
|
||||
do {
|
||||
next = *last;
|
||||
if (!next)
|
||||
break;
|
||||
|
||||
/* remove rich presence ping scheduled event for game */
|
||||
if (next->callback == rc_client_ping && game && next->related_id == game->public_.id) {
|
||||
*last = next->next;
|
||||
continue;
|
||||
}
|
||||
/* remove rich presence ping scheduled event for game */
|
||||
if (next->callback == rc_client_ping && next->related_id == game->public_.id) {
|
||||
*last = next->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
last = &next->next;
|
||||
} while (1);
|
||||
last = &next->next;
|
||||
} while (1);
|
||||
}
|
||||
|
||||
rc_mutex_unlock(&client->state.mutex);
|
||||
|
||||
@ -3528,7 +3576,7 @@ typedef struct rc_client_award_achievement_callback_data_t
|
||||
uint32_t retry_count;
|
||||
uint8_t hardcore;
|
||||
const char* game_hash;
|
||||
time_t unlock_time;
|
||||
rc_clock_t unlock_time;
|
||||
rc_client_t* client;
|
||||
rc_client_scheduled_callback_data_t* scheduled_callback_data;
|
||||
} rc_client_award_achievement_callback_data_t;
|
||||
@ -3679,6 +3727,11 @@ static void rc_client_award_achievement_server_call(rc_client_award_achievement_
|
||||
api_params.hardcore = ach_data->hardcore;
|
||||
api_params.game_hash = ach_data->game_hash;
|
||||
|
||||
if (ach_data->retry_count) {
|
||||
const rc_clock_t now = ach_data->client->callbacks.get_time_millisecs(ach_data->client);
|
||||
api_params.seconds_since_unlock = (uint32_t)((now - ach_data->unlock_time) / 1000);
|
||||
}
|
||||
|
||||
result = rc_api_init_award_achievement_request(&request, &api_params);
|
||||
if (result != RC_OK) {
|
||||
RC_CLIENT_LOG_ERR_FORMATTED(ach_data->client, "Error constructing unlock request for achievement %u: %s", ach_data->id, rc_error_str(result));
|
||||
@ -3745,7 +3798,8 @@ static void rc_client_award_achievement(rc_client_t* client, rc_client_achieveme
|
||||
callback_data->client = client;
|
||||
callback_data->id = achievement->public_.id;
|
||||
callback_data->hardcore = client->state.hardcore;
|
||||
callback_data->unlock_time = achievement->public_.unlock_time;
|
||||
callback_data->game_hash = client->game->public_.hash;
|
||||
callback_data->unlock_time = client->callbacks.get_time_millisecs(client);
|
||||
|
||||
if (client->game) /* may be NULL if this gets called while unloading the game (from another thread - events are raised outside the lock) */
|
||||
callback_data->game_hash = client->game->public_.hash;
|
||||
@ -4179,7 +4233,7 @@ typedef struct rc_client_submit_leaderboard_entry_callback_data_t
|
||||
int32_t score;
|
||||
uint32_t retry_count;
|
||||
const char* game_hash;
|
||||
time_t submit_time;
|
||||
rc_clock_t submit_time;
|
||||
rc_client_t* client;
|
||||
rc_client_scheduled_callback_data_t* scheduled_callback_data;
|
||||
} rc_client_submit_leaderboard_entry_callback_data_t;
|
||||
@ -4334,6 +4388,11 @@ static void rc_client_submit_leaderboard_entry_server_call(rc_client_submit_lead
|
||||
api_params.score = lboard_data->score;
|
||||
api_params.game_hash = lboard_data->game_hash;
|
||||
|
||||
if (lboard_data->retry_count) {
|
||||
const rc_clock_t now = lboard_data->client->callbacks.get_time_millisecs(lboard_data->client);
|
||||
api_params.seconds_since_completion = (uint32_t)((now - lboard_data->submit_time) / 1000);
|
||||
}
|
||||
|
||||
result = rc_api_init_submit_lboard_entry_request(&request, &api_params);
|
||||
if (result != RC_OK) {
|
||||
RC_CLIENT_LOG_ERR_FORMATTED(lboard_data->client, "Error constructing submit leaderboard entry for leaderboard %u: %s", lboard_data->id, rc_error_str(result));
|
||||
@ -4377,7 +4436,7 @@ static void rc_client_submit_leaderboard_entry(rc_client_t* client, rc_client_le
|
||||
callback_data->id = leaderboard->public_.id;
|
||||
callback_data->score = leaderboard->value;
|
||||
callback_data->game_hash = client->game->public_.hash;
|
||||
callback_data->submit_time = time(NULL);
|
||||
callback_data->submit_time = client->callbacks.get_time_millisecs(client);
|
||||
|
||||
RC_CLIENT_LOG_INFO_FORMATTED(client, "Submitting %s (%d) for leaderboard %u: %s",
|
||||
leaderboard->public_.tracker_value, leaderboard->value, leaderboard->public_.id, leaderboard->public_.title);
|
||||
|
36
deps/rcheevos/src/rc_libretro.c
vendored
36
deps/rcheevos/src/rc_libretro.c
vendored
@ -36,6 +36,17 @@ typedef struct rc_disallowed_core_settings_t
|
||||
const rc_disallowed_setting_t* disallowed_settings;
|
||||
} rc_disallowed_core_settings_t;
|
||||
|
||||
|
||||
static const rc_disallowed_setting_t _rc_disallowed_beetle_psx_settings[] = {
|
||||
{ "beetle_psx_cpu_freq_scale", "<100" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static const rc_disallowed_setting_t _rc_disallowed_beetle_psx_hw_settings[] = {
|
||||
{ "beetle_psx_hw_cpu_freq_scale", "<100" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static const rc_disallowed_setting_t _rc_disallowed_bsnes_settings[] = {
|
||||
{ "bsnes_region", "pal" },
|
||||
{ NULL, NULL }
|
||||
@ -80,6 +91,11 @@ static const rc_disallowed_setting_t _rc_disallowed_fceumm_settings[] = {
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static const rc_disallowed_setting_t _rc_disallowed_flycast_settings[] = {
|
||||
{ "reicast_sh4clock", "<200" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static const rc_disallowed_setting_t _rc_disallowed_gpgx_settings[] = {
|
||||
{ "genesis_plus_gx_lock_on", ",action replay (pro),game genie" },
|
||||
{ "genesis_plus_gx_region_detect", "pal" },
|
||||
@ -108,6 +124,7 @@ static const rc_disallowed_setting_t _rc_disallowed_neocd_settings[] = {
|
||||
};
|
||||
|
||||
static const rc_disallowed_setting_t _rc_disallowed_pcsx_rearmed_settings[] = {
|
||||
{ "pcsx_rearmed_psxclock", "<55" },
|
||||
{ "pcsx_rearmed_region", "pal" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
@ -140,6 +157,11 @@ static const rc_disallowed_setting_t _rc_disallowed_snes9x_settings[] = {
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static const rc_disallowed_setting_t _rc_disallowed_swanstation_settings[] = {
|
||||
{ "swanstation_CPU_Overclock", "<100" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static const rc_disallowed_setting_t _rc_disallowed_vice_settings[] = {
|
||||
{ "vice_autostart", "disabled" }, /* autostart dictates initial load and reset from menu */
|
||||
{ "vice_reset", "!autostart" }, /* reset dictates behavior when pressing reset button (END) */
|
||||
@ -152,6 +174,8 @@ static const rc_disallowed_setting_t _rc_disallowed_virtual_jaguar_settings[] =
|
||||
};
|
||||
|
||||
static const rc_disallowed_core_settings_t rc_disallowed_core_settings[] = {
|
||||
{ "Beetle PSX", _rc_disallowed_beetle_psx_settings },
|
||||
{ "Beetle PSX HW", _rc_disallowed_beetle_psx_hw_settings },
|
||||
{ "bsnes-mercury", _rc_disallowed_bsnes_settings },
|
||||
{ "cap32", _rc_disallowed_cap32_settings },
|
||||
{ "dolphin-emu", _rc_disallowed_dolphin_settings },
|
||||
@ -160,6 +184,7 @@ static const rc_disallowed_core_settings_t rc_disallowed_core_settings[] = {
|
||||
{ "ecwolf", _rc_disallowed_ecwolf_settings },
|
||||
{ "FCEUmm", _rc_disallowed_fceumm_settings },
|
||||
{ "FinalBurn Neo", _rc_disallowed_fbneo_settings },
|
||||
{ "Flycast", _rc_disallowed_flycast_settings },
|
||||
{ "Genesis Plus GX", _rc_disallowed_gpgx_settings },
|
||||
{ "Genesis Plus GX Wide", _rc_disallowed_gpgx_wide_settings },
|
||||
{ "Mesen", _rc_disallowed_mesen_settings },
|
||||
@ -171,6 +196,7 @@ static const rc_disallowed_core_settings_t rc_disallowed_core_settings[] = {
|
||||
{ "QUASI88", _rc_disallowed_quasi88_settings },
|
||||
{ "SMS Plus GX", _rc_disallowed_smsplus_settings },
|
||||
{ "Snes9x", _rc_disallowed_snes9x_settings },
|
||||
{ "SwanStation", _rc_disallowed_swanstation_settings },
|
||||
{ "VICE x64", _rc_disallowed_vice_settings },
|
||||
{ "Virtual Jaguar", _rc_disallowed_virtual_jaguar_settings },
|
||||
{ NULL, NULL }
|
||||
@ -186,6 +212,12 @@ static int rc_libretro_string_equal_nocase_wildcard(const char* test, const char
|
||||
return (*value == '\0');
|
||||
}
|
||||
|
||||
static int rc_libretro_numeric_less_than(const char* test, const char* value) {
|
||||
int test_num = atoi(test);
|
||||
int value_num = atoi(value);
|
||||
return (test_num < value_num);
|
||||
}
|
||||
|
||||
static int rc_libretro_match_value(const char* val, const char* match) {
|
||||
/* if value starts with a comma, it's a CSV list of potential matches */
|
||||
if (*match == ',') {
|
||||
@ -218,6 +250,10 @@ static int rc_libretro_match_value(const char* val, const char* match) {
|
||||
if (*match == '!')
|
||||
return !rc_libretro_match_value(val, &match[1]);
|
||||
|
||||
/* a leading less tahn means the provided value is the minimum allowed */
|
||||
if (*match == '<')
|
||||
return rc_libretro_numeric_less_than(val, &match[1]);
|
||||
|
||||
/* just a single value, attempt to match it */
|
||||
return rc_libretro_string_equal_nocase_wildcard(val, match);
|
||||
}
|
||||
|
2
deps/rcheevos/src/rc_version.h
vendored
2
deps/rcheevos/src/rc_version.h
vendored
@ -8,7 +8,7 @@
|
||||
RC_BEGIN_C_DECLS
|
||||
|
||||
#define RCHEEVOS_VERSION_MAJOR 11
|
||||
#define RCHEEVOS_VERSION_MINOR 5
|
||||
#define RCHEEVOS_VERSION_MINOR 6
|
||||
#define RCHEEVOS_VERSION_PATCH 0
|
||||
|
||||
#define RCHEEVOS_MAKE_VERSION(major, minor, patch) (major * 1000000 + minor * 1000 + patch)
|
||||
|
49
deps/rcheevos/src/rcheevos/consoleinfo.c
vendored
49
deps/rcheevos/src/rcheevos/consoleinfo.c
vendored
@ -721,16 +721,29 @@ static const rc_memory_regions_t rc_memory_regions_n64 = { _rc_memory_regions_n6
|
||||
/* ===== Nintendo DS ===== */
|
||||
/* https://www.akkit.org/info/gbatek.htm#dsmemorymaps */
|
||||
static const rc_memory_region_t _rc_memory_regions_nintendo_ds[] = {
|
||||
{ 0x000000U, 0x3FFFFFU, 0x02000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }
|
||||
{ 0x0000000U, 0x03FFFFFU, 0x02000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" },
|
||||
/* To keep DS/DSi memory maps aligned, padding is set here for the DSi's extra RAM */
|
||||
{ 0x0400000U, 0x0FFFFFFU, 0x02400000U, RC_MEMORY_TYPE_UNUSED, "Unused (DSi exclusive)" },
|
||||
/* The DS/DSi have "tightly coupled memory": very fast memory directly connected to the CPU.
|
||||
* This memory has an instruction variant (ITCM) and a data variant (DTCM).
|
||||
* For achievement purposes it is useful to be able to access the data variant.
|
||||
* This memory does not have a fixed address on console, being able to be moved to any $0xxxx000 region.
|
||||
* While normally this kind of memory is addressed outside of the possible native addressing space, this is simply not possible,
|
||||
* as the DS/DSi's address space covers all possible uint32_t values.
|
||||
* $0E000000 is used here as a "pseudo-end," as this is nearly the end of all the memory actually mapped to addresses
|
||||
* This means that (with the exception of $FFFF0000 onwards, which has the ARM9 BIOS mapped) $0E000000 onwards has nothing mapped to it
|
||||
*/
|
||||
{ 0x1000000U, 0x1003FFFU, 0x0E000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Data TCM" }
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_nintendo_ds = { _rc_memory_regions_nintendo_ds, 1 };
|
||||
static const rc_memory_regions_t rc_memory_regions_nintendo_ds = { _rc_memory_regions_nintendo_ds, 3 };
|
||||
|
||||
/* ===== Nintendo DSi ===== */
|
||||
/* https://problemkaputt.de/gbatek.htm#dsiiomap */
|
||||
static const rc_memory_region_t _rc_memory_regions_nintendo_dsi[] = {
|
||||
{ 0x000000U, 0xFFFFFFU, 0x02000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }
|
||||
{ 0x0000000U, 0x0FFFFFFU, 0x02000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" },
|
||||
{ 0x1000000U, 0x1003FFFU, 0x0E000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Data TCM" }
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_nintendo_dsi = { _rc_memory_regions_nintendo_dsi, 1 };
|
||||
static const rc_memory_regions_t rc_memory_regions_nintendo_dsi = { _rc_memory_regions_nintendo_dsi, 2 };
|
||||
|
||||
/* ===== Oric ===== */
|
||||
static const rc_memory_region_t _rc_memory_regions_oric[] = {
|
||||
@ -956,6 +969,31 @@ static const rc_memory_region_t _rc_memory_regions_wonderswan[] = {
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_wonderswan = { _rc_memory_regions_wonderswan, 2 };
|
||||
|
||||
/* ===== ZX Spectrum ===== */
|
||||
/* https://github.com/TASEmulators/BizHawk/blob/3a3b22c/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum16K/ZX16.cs
|
||||
* https://github.com/TASEmulators/BizHawk/blob/3a3b22c/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum48K/ZX48.Memory.cs
|
||||
* https://worldofspectrum.org/faq/reference/128kreference.htm */
|
||||
static const rc_memory_region_t _rc_memory_regions_zx_spectrum[] = {
|
||||
/* ZX Spectrum is complicated as multiple models exist with varying amounts of memory.
|
||||
* In practice, this can be reduced to two categories: 16K/48K units, and 128K units.
|
||||
* 16K/48K units have RAM starting at $4000 onwards, 16K ending at $7FFF, 48K ending at $FFFF.
|
||||
* 128K units have banked memory, with $4000-$7FFF normally having RAM bank 5, and $8000-$BFFF normally having RAM bank 2.
|
||||
* $C000-$FFFF is normally reserved for banked RAM, having any of banks 0-7.
|
||||
* For the purposes of the RAM map, $C000-$FFFF is assumed to be bank 0, and $10000 onwards has the other banks in order (1, 3, 4, 6, 7)
|
||||
* Doing it this way always for 16K/48K games to have the same memory map on the 128K, and thus avoid issues due to the model selected.
|
||||
* Later 128K units also have a special banking mode that changes up banking completely, but for 16K/48K compatibility purposes this doesn't matter, and so is irrelevant.
|
||||
*/
|
||||
{ 0x00000U, 0x03FFFU, 0x04000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Screen RAM" }, /* RAM bank 5 on 128K units */
|
||||
{ 0x04000U, 0x07FFFU, 0x08000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, /* RAM bank 2 on 128K units */
|
||||
{ 0x08000U, 0x0BFFFU, 0x0C000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, /* RAM bank 0-7 on 128K units, assumed to be bank 0 here */
|
||||
{ 0x0C000U, 0x0FFFFU, 0x10000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, /* RAM bank 1 on 128K units */
|
||||
{ 0x10000U, 0x13FFFU, 0x14000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, /* RAM bank 3 on 128K units */
|
||||
{ 0x14000U, 0x17FFFU, 0x18000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, /* RAM bank 4 on 128K units */
|
||||
{ 0x18000U, 0x1BFFFU, 0x1C000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, /* RAM bank 6 on 128K units */
|
||||
{ 0x1C000U, 0x1FFFFU, 0x20000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Screen RAM" } /* RAM bank 7 on 128K units */
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_zx_spectrum = { _rc_memory_regions_zx_spectrum, 8 };
|
||||
|
||||
/* ===== default ===== */
|
||||
static const rc_memory_regions_t rc_memory_regions_none = { 0, 0 };
|
||||
|
||||
@ -1141,6 +1179,9 @@ const rc_memory_regions_t* rc_console_memory_regions(uint32_t console_id)
|
||||
case RC_CONSOLE_WONDERSWAN:
|
||||
return &rc_memory_regions_wonderswan;
|
||||
|
||||
case RC_CONSOLE_ZX_SPECTRUM:
|
||||
return &rc_memory_regions_zx_spectrum;
|
||||
|
||||
default:
|
||||
return &rc_memory_regions_none;
|
||||
}
|
||||
|
16
deps/rcheevos/src/rcheevos/lboard.c
vendored
16
deps/rcheevos/src/rcheevos/lboard.c
vendored
@ -199,19 +199,19 @@ int rc_evaluate_lboard(rc_lboard_t* self, int32_t* value, rc_peek_t peek, void*
|
||||
/* start and submit are both true in the same frame, just submit without announcing the leaderboard is available */
|
||||
self->state = RC_LBOARD_STATE_TRIGGERED;
|
||||
}
|
||||
else if (self->start.requirement == 0 && self->start.alternative == 0) {
|
||||
/* start condition is empty - this leaderboard is submit-only with no measured progress */
|
||||
else if (!self->start.requirement && !self->start.alternative) {
|
||||
/* start trigger is empty. assume the leaderboard is in development and ignore */
|
||||
}
|
||||
else {
|
||||
/* start the leaderboard attempt */
|
||||
self->state = RC_LBOARD_STATE_STARTED;
|
||||
|
||||
/* reset any hit counts in the value */
|
||||
if (self->progress)
|
||||
rc_reset_value(self->progress);
|
||||
|
||||
rc_reset_value(&self->value);
|
||||
}
|
||||
|
||||
/* reset any hit counts in the value */
|
||||
if (self->progress)
|
||||
rc_reset_value(self->progress);
|
||||
|
||||
rc_reset_value(&self->value);
|
||||
}
|
||||
break;
|
||||
|
||||
|
29
deps/rcheevos/src/rcheevos/rc_version.h
vendored
29
deps/rcheevos/src/rcheevos/rc_version.h
vendored
@ -1,29 +0,0 @@
|
||||
#ifndef RC_VERSION_H
|
||||
#define RC_VERSION_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define RCHEEVOS_VERSION_MAJOR 10
|
||||
#define RCHEEVOS_VERSION_MINOR 7
|
||||
#define RCHEEVOS_VERSION_PATCH 0
|
||||
|
||||
#define RCHEEVOS_MAKE_VERSION(major, minor, patch) (major * 1000000 + minor * 1000 + patch)
|
||||
#define RCHEEVOS_VERSION RCHEEVOS_MAKE_VERSION(RCHEEVOS_VERSION_MAJOR, RCHEEVOS_VERSION_MINOR, RCHEEVOS_VERSION_PATCH)
|
||||
|
||||
#define RCHEEVOS_MAKE_STRING(num) #num
|
||||
#define RCHEEVOS_MAKE_VERSION_STRING(major, minor, patch) RCHEEVOS_MAKE_STRING(major) "." RCHEEVOS_MAKE_STRING(minor) "." RCHEEVOS_MAKE_STRING(patch)
|
||||
#define RCHEEVOS_MAKE_VERSION_STRING_SHORT(major, minor) RCHEEVOS_MAKE_STRING(major) "." RCHEEVOS_MAKE_STRING(minor)
|
||||
|
||||
#if RCHEEVOS_VERSION_PATCH > 0
|
||||
#define RCHEEVOS_VERSION_STRING RCHEEVOS_MAKE_VERSION_STRING(RCHEEVOS_VERSION_MAJOR, RCHEEVOS_VERSION_MINOR, RCHEEVOS_VERSION_PATCH)
|
||||
#else
|
||||
#define RCHEEVOS_VERSION_STRING RCHEEVOS_MAKE_VERSION_STRING_SHORT(RCHEEVOS_VERSION_MAJOR, RCHEEVOS_VERSION_MINOR)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* RC_VERSION_H */
|
6
deps/rcheevos/src/rcheevos/richpresence.c
vendored
6
deps/rcheevos/src/rcheevos/richpresence.c
vendored
@ -360,6 +360,9 @@ static const char* rc_parse_richpresence_lookup(rc_richpresence_lookup_t* lookup
|
||||
do
|
||||
{
|
||||
line = nextline;
|
||||
if (line == NULL)
|
||||
break;
|
||||
|
||||
nextline = rc_parse_line(line, &endline, parse);
|
||||
|
||||
if (endline - line < 2) {
|
||||
@ -438,6 +441,9 @@ static const char* rc_parse_richpresence_lookup(rc_richpresence_lookup_t* lookup
|
||||
|
||||
/* insert the current item and continue scanning the next one */
|
||||
rc_insert_richpresence_lookup_item(lookup, first, last, label, (int)(endline - label), parse);
|
||||
if (parse->offset < 0)
|
||||
break;
|
||||
|
||||
line = endptr + 1;
|
||||
} while (line < endline);
|
||||
|
||||
|
4
deps/rcheevos/src/rcheevos/runtime.c
vendored
4
deps/rcheevos/src/rcheevos/runtime.c
vendored
@ -316,7 +316,7 @@ int rc_runtime_activate_lboard(rc_runtime_t* self, uint32_t id, const char* mema
|
||||
rc_lboard_t* lboard;
|
||||
rc_parse_state_t parse;
|
||||
rc_runtime_lboard_t* runtime_lboard;
|
||||
int32_t size;
|
||||
int size;
|
||||
uint32_t i;
|
||||
|
||||
if (memaddr == 0)
|
||||
@ -834,7 +834,7 @@ void rc_runtime_invalidate_address(rc_runtime_t* self, uint32_t address) {
|
||||
}
|
||||
}
|
||||
|
||||
void rc_runtime_validate_addresses(rc_runtime_t* self, rc_runtime_event_handler_t event_handler,
|
||||
void rc_runtime_validate_addresses(rc_runtime_t* self, rc_runtime_event_handler_t event_handler,
|
||||
rc_runtime_validate_address_t validate_handler) {
|
||||
rc_memref_t** last_memref = &self->memrefs;
|
||||
rc_memref_t* memref = self->memrefs;
|
||||
|
22
deps/rcheevos/src/rhash/hash.c
vendored
22
deps/rcheevos/src/rhash/hash.c
vendored
@ -3129,6 +3129,7 @@ int rc_hash_generate_from_buffer(char hash[33], uint32_t console_id, const uint8
|
||||
case RC_CONSOLE_VIRTUAL_BOY:
|
||||
case RC_CONSOLE_WASM4:
|
||||
case RC_CONSOLE_WONDERSWAN:
|
||||
case RC_CONSOLE_ZX_SPECTRUM:
|
||||
return rc_hash_buffer(hash, buffer, buffer_size);
|
||||
|
||||
case RC_CONSOLE_ARDUBOY:
|
||||
@ -3427,6 +3428,7 @@ int rc_hash_generate_from_file(char hash[33], uint32_t console_id, const char* p
|
||||
case RC_CONSOLE_VIRTUAL_BOY:
|
||||
case RC_CONSOLE_WASM4:
|
||||
case RC_CONSOLE_WONDERSWAN:
|
||||
case RC_CONSOLE_ZX_SPECTRUM:
|
||||
/* generic whole-file hash - don't buffer */
|
||||
return rc_hash_whole_file(hash, path);
|
||||
|
||||
@ -3592,6 +3594,7 @@ static void rc_hash_initialize_dsk_iterator(struct rc_hash_iterator* iterator, c
|
||||
/* check MSX first, as Apple II isn't supported by RetroArch, and RAppleWin won't use the iterator */
|
||||
rc_hash_iterator_append_console(iterator, RC_CONSOLE_MSX);
|
||||
rc_hash_iterator_append_console(iterator, RC_CONSOLE_AMSTRAD_PC);
|
||||
rc_hash_iterator_append_console(iterator, RC_CONSOLE_ZX_SPECTRUM);
|
||||
rc_hash_iterator_append_console(iterator, RC_CONSOLE_APPLE_II);
|
||||
}
|
||||
|
||||
@ -3744,6 +3747,10 @@ void rc_hash_initialize_iterator(struct rc_hash_iterator* iterator, const char*
|
||||
{
|
||||
iterator->consoles[0] = RC_CONSOLE_NINTENDO_3DS;
|
||||
}
|
||||
else if (rc_path_compare_extension(ext, "csw"))
|
||||
{
|
||||
iterator->consoles[0] = RC_CONSOLE_ZX_SPECTRUM;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
@ -3827,6 +3834,7 @@ void rc_hash_initialize_iterator(struct rc_hash_iterator* iterator, const char*
|
||||
iterator->consoles[1] = RC_CONSOLE_PSP;
|
||||
iterator->consoles[2] = RC_CONSOLE_3DO;
|
||||
iterator->consoles[3] = RC_CONSOLE_SEGA_CD; /* ASSERT: handles both Sega CD and Saturn */
|
||||
iterator->consoles[4] = RC_CONSOLE_GAMECUBE;
|
||||
need_path = 1;
|
||||
}
|
||||
break;
|
||||
@ -3928,6 +3936,10 @@ void rc_hash_initialize_iterator(struct rc_hash_iterator* iterator, const char*
|
||||
{
|
||||
iterator->consoles[0] = RC_CONSOLE_ELEKTOR_TV_GAMES_COMPUTER;
|
||||
}
|
||||
else if (rc_path_compare_extension(ext, "pzx"))
|
||||
{
|
||||
iterator->consoles[0] = RC_CONSOLE_ZX_SPECTRUM;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
@ -3966,11 +3978,16 @@ void rc_hash_initialize_iterator(struct rc_hash_iterator* iterator, const char*
|
||||
{
|
||||
iterator->consoles[0] = RC_CONSOLE_THOMSONTO8; /* disk */
|
||||
}
|
||||
else if (rc_path_compare_extension(ext, "scl"))
|
||||
{
|
||||
iterator->consoles[0] = RC_CONSOLE_ZX_SPECTRUM;
|
||||
}
|
||||
break;
|
||||
|
||||
case 't':
|
||||
if (rc_path_compare_extension(ext, "tap"))
|
||||
{
|
||||
/* also Commodore 64 and ZX Spectrum, but all are full file hashes */
|
||||
iterator->consoles[0] = RC_CONSOLE_ORIC;
|
||||
}
|
||||
else if (rc_path_compare_extension(ext, "tic"))
|
||||
@ -3981,6 +3998,11 @@ void rc_hash_initialize_iterator(struct rc_hash_iterator* iterator, const char*
|
||||
{
|
||||
iterator->consoles[0] = RC_CONSOLE_ELEKTOR_TV_GAMES_COMPUTER;
|
||||
}
|
||||
else if (rc_path_compare_extension(ext, "trd") ||
|
||||
rc_path_compare_extension(ext, "tzx"))
|
||||
{
|
||||
iterator->consoles[0] = RC_CONSOLE_ZX_SPECTRUM;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
|
Loading…
Reference in New Issue
Block a user