mirror of
https://github.com/libretro/RetroArch
synced 2025-02-15 18:39:55 +00:00
Add option to automatically backup cores when updating
This commit is contained in:
parent
4b364fa1e1
commit
2782b87267
@ -965,6 +965,14 @@ static const uint16_t network_remote_base_port = 55400;
|
||||
#define DEFAULT_NETWORK_BUILDBOT_AUTO_EXTRACT_ARCHIVE true
|
||||
#define DEFAULT_NETWORK_BUILDBOT_SHOW_EXPERIMENTAL_CORES false
|
||||
|
||||
/* Automatically create a backup whenever a core is
|
||||
* updated via the online updater */
|
||||
#define DEFAULT_CORE_UPDATER_AUTO_BACKUP false
|
||||
/* Number of automatic core backups to retain
|
||||
* (oldest backup will be deleted when creating
|
||||
* a new one) */
|
||||
#define DEFAULT_CORE_UPDATER_AUTO_BACKUP_HISTORY_SIZE 1
|
||||
|
||||
#if defined(ANDROID) || defined(IOS)
|
||||
#define DEFAULT_NETWORK_ON_DEMAND_THUMBNAILS true
|
||||
#else
|
||||
|
@ -1438,6 +1438,7 @@ static struct config_bool_setting *populate_settings_bool(
|
||||
SETTING_BOOL("video_font_enable", &settings->bools.video_font_enable, true, DEFAULT_FONT_ENABLE, false);
|
||||
SETTING_BOOL("core_updater_auto_extract_archive", &settings->bools.network_buildbot_auto_extract_archive, true, DEFAULT_NETWORK_BUILDBOT_AUTO_EXTRACT_ARCHIVE, false);
|
||||
SETTING_BOOL("core_updater_show_experimental_cores", &settings->bools.network_buildbot_show_experimental_cores, true, DEFAULT_NETWORK_BUILDBOT_SHOW_EXPERIMENTAL_CORES, false);
|
||||
SETTING_BOOL("core_updater_auto_backup", &settings->bools.core_updater_auto_backup, true, DEFAULT_CORE_UPDATER_AUTO_BACKUP, false);
|
||||
SETTING_BOOL("camera_allow", &settings->bools.camera_allow, true, false, false);
|
||||
SETTING_BOOL("discord_allow", &settings->bools.discord_enable, true, false, false);
|
||||
#if defined(VITA)
|
||||
@ -1914,6 +1915,8 @@ static struct config_uint_setting *populate_settings_uint(
|
||||
SETTING_UINT("playlist_sublabel_last_played_style", &settings->uints.playlist_sublabel_last_played_style, true, DEFAULT_PLAYLIST_SUBLABEL_LAST_PLAYED_STYLE, false);
|
||||
#endif
|
||||
|
||||
SETTING_UINT("core_updater_auto_backup_history_size", &settings->uints.core_updater_auto_backup_history_size, true, DEFAULT_CORE_UPDATER_AUTO_BACKUP_HISTORY_SIZE, false);
|
||||
|
||||
*size = count;
|
||||
|
||||
return tmp;
|
||||
|
@ -286,6 +286,7 @@ typedef struct settings
|
||||
bool network_buildbot_auto_extract_archive;
|
||||
bool network_buildbot_show_experimental_cores;
|
||||
bool network_on_demand_thumbnails;
|
||||
bool core_updater_auto_backup;
|
||||
|
||||
/* UI */
|
||||
bool ui_menubar_enable;
|
||||
@ -621,6 +622,8 @@ typedef struct settings
|
||||
unsigned ai_service_mode;
|
||||
unsigned ai_service_target_lang;
|
||||
unsigned ai_service_source_lang;
|
||||
|
||||
unsigned core_updater_auto_backup_history_size;
|
||||
} uints;
|
||||
|
||||
struct
|
||||
|
@ -27,7 +27,6 @@
|
||||
|
||||
#include "frontend/frontend_driver.h"
|
||||
#include "file_path_special.h"
|
||||
#include "core_info.h"
|
||||
#include "verbosity.h"
|
||||
|
||||
#include "core_backup.h"
|
||||
@ -532,7 +531,8 @@ core_backup_list_t *core_backup_list_init(
|
||||
if (dir_list->size < 1)
|
||||
goto error;
|
||||
|
||||
/* Ensure list is sorted in alphabetical order */
|
||||
/* Ensure list is sorted in alphabetical order
|
||||
* > This corresponds to 'timestamp' order */
|
||||
dir_list_sort(dir_list, true);
|
||||
|
||||
/* Create core backup list */
|
||||
@ -622,6 +622,30 @@ size_t core_backup_list_size(core_backup_list_t *backup_list)
|
||||
return backup_list->size;
|
||||
}
|
||||
|
||||
/* Returns number of entries of specified 'backup mode'
|
||||
* (manual or automatic) in core backup list */
|
||||
size_t core_backup_list_get_num_backups(
|
||||
core_backup_list_t *backup_list,
|
||||
enum core_backup_mode backup_mode)
|
||||
{
|
||||
size_t i;
|
||||
size_t num_backups = 0;
|
||||
|
||||
if (!backup_list || !backup_list->entries)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < backup_list->size; i++)
|
||||
{
|
||||
core_backup_list_entry_t *current_entry = &backup_list->entries[i];
|
||||
|
||||
if (current_entry &&
|
||||
(current_entry->backup_mode == backup_mode))
|
||||
num_backups++;
|
||||
}
|
||||
|
||||
return num_backups;
|
||||
}
|
||||
|
||||
/* Fetches core backup list entry corresponding
|
||||
* to the specified entry index.
|
||||
* Returns false if index is invalid. */
|
||||
|
@ -132,6 +132,12 @@ void core_backup_list_free(core_backup_list_t *backup_list);
|
||||
/* Returns number of entries in core backup list */
|
||||
size_t core_backup_list_size(core_backup_list_t *backup_list);
|
||||
|
||||
/* Returns number of entries of specified 'backup mode'
|
||||
* (manual or automatic) in core backup list */
|
||||
size_t core_backup_list_get_num_backups(
|
||||
core_backup_list_t *backup_list,
|
||||
enum core_backup_mode backup_mode);
|
||||
|
||||
/* Fetches core backup list entry corresponding
|
||||
* to the specified entry index.
|
||||
* Returns false if index is invalid. */
|
||||
|
@ -516,6 +516,14 @@ MSG_HASH(
|
||||
MENU_ENUM_LABEL_CORE_UPDATER_SHOW_EXPERIMENTAL_CORES,
|
||||
"core_updater_show_experimental_cores"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_CORE_UPDATER_AUTO_BACKUP,
|
||||
"core_updater_auto_backup"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_CORE_UPDATER_AUTO_BACKUP_HISTORY_SIZE,
|
||||
"core_updater_auto_backup_history_size"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_CORE_UPDATER_BUILDBOT_URL,
|
||||
"core_updater_buildbot_url"
|
||||
|
@ -481,6 +481,10 @@ MSG_HASH(
|
||||
MENU_ENUM_SUBLABEL_CORE_DELETE_BACKUP_LIST,
|
||||
"Remove a file from the list of archived backups."
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_CORE_BACKUP_MODE_AUTO,
|
||||
"[Auto]"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_CORE_BACKUP_CRC,
|
||||
"CRC32: "
|
||||
@ -4598,6 +4602,22 @@ MSG_HASH(
|
||||
MENU_ENUM_SUBLABEL_CORE_UPDATER_SHOW_EXPERIMENTAL_CORES,
|
||||
"Include 'experimental' cores in the Core Downloader list. These are typically for development/testing purposes only, and are not recommended for general use."
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_CORE_UPDATER_AUTO_BACKUP,
|
||||
"Backup Cores When Updating"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_SUBLABEL_CORE_UPDATER_AUTO_BACKUP,
|
||||
"Automatically create a backup of any installed cores when performing an online update. Enables easy rollback to a working core if an update introduces a regression."
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_CORE_UPDATER_AUTO_BACKUP_HISTORY_SIZE,
|
||||
"Core Backup History Size"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_SUBLABEL_CORE_UPDATER_AUTO_BACKUP_HISTORY_SIZE,
|
||||
"Specifies how many automatically generated backups to keep for each installed core. When this limit is reached, creating a new backup via an online update will delete the oldest backup. Note: Manual core backups are unaffected by this setting."
|
||||
)
|
||||
|
||||
/* Settings > Playlists */
|
||||
|
||||
@ -10862,6 +10882,10 @@ MSG_HASH(
|
||||
MSG_BACKING_UP_CORE,
|
||||
"Backing up core: "
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_PRUNING_CORE_BACKUP_HISTORY,
|
||||
"Removing obsolete backups: "
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_CORE_BACKUP_COMPLETE,
|
||||
"Core backup complete: "
|
||||
|
@ -4338,16 +4338,20 @@ static int action_ok_core_updater_download(const char *path,
|
||||
const char *label, unsigned type, size_t idx, size_t entry_idx)
|
||||
{
|
||||
#ifdef HAVE_NETWORKING
|
||||
core_updater_list_t *core_list = core_updater_list_get_cached();
|
||||
settings_t *settings = config_get_ptr();
|
||||
const char *path_dir_libretro = settings->paths.directory_libretro;
|
||||
core_updater_list_t *core_list = core_updater_list_get_cached();
|
||||
settings_t *settings = config_get_ptr();
|
||||
bool auto_backup = settings->bools.core_updater_auto_backup;
|
||||
unsigned auto_backup_history_size = settings->uints.core_updater_auto_backup_history_size;
|
||||
const char *path_dir_libretro = settings->paths.directory_libretro;
|
||||
const char *path_dir_core_assets = settings->paths.directory_core_assets;
|
||||
|
||||
if (!core_list)
|
||||
return menu_cbs_exit();
|
||||
|
||||
task_push_core_updater_download(
|
||||
core_list, path, false, true,
|
||||
path_dir_libretro);
|
||||
core_list, path, 0, false,
|
||||
auto_backup, (size_t)auto_backup_history_size,
|
||||
path_dir_libretro, path_dir_core_assets);
|
||||
|
||||
#endif
|
||||
return 0;
|
||||
@ -4357,14 +4361,19 @@ static int action_ok_core_updater_download(const char *path,
|
||||
static int action_ok_update_installed_cores(const char *path,
|
||||
const char *label, unsigned type, size_t idx, size_t entry_idx)
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
const char *path_dir_libretro = settings->paths.directory_libretro;
|
||||
settings_t *settings = config_get_ptr();
|
||||
bool auto_backup = settings->bools.core_updater_auto_backup;
|
||||
unsigned auto_backup_history_size = settings->uints.core_updater_auto_backup_history_size;
|
||||
const char *path_dir_libretro = settings->paths.directory_libretro;
|
||||
const char *path_dir_core_assets = settings->paths.directory_core_assets;
|
||||
|
||||
/* Ensure networking is initialised */
|
||||
generic_action_ok_command(CMD_EVENT_NETWORK_INIT);
|
||||
|
||||
/* Push update task */
|
||||
task_push_update_installed_cores(path_dir_libretro);
|
||||
task_push_update_installed_cores(
|
||||
auto_backup, auto_backup_history_size,
|
||||
path_dir_libretro, path_dir_core_assets);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -6253,15 +6262,16 @@ static int action_ok_netplay_disconnect(const char *path,
|
||||
static int action_ok_core_create_backup(const char *path,
|
||||
const char *label, unsigned type, size_t idx, size_t entry_idx)
|
||||
{
|
||||
const char *core_path = label;
|
||||
settings_t *settings = config_get_ptr();
|
||||
const char *dir_core_assets = settings->paths.directory_core_assets;
|
||||
const char *core_path = label;
|
||||
settings_t *settings = config_get_ptr();
|
||||
unsigned auto_backup_history_size = settings->uints.core_updater_auto_backup_history_size;
|
||||
const char *dir_core_assets = settings->paths.directory_core_assets;
|
||||
|
||||
if (string_is_empty(core_path))
|
||||
return -1;
|
||||
|
||||
task_push_core_backup(core_path, 0, CORE_BACKUP_MODE_MANUAL,
|
||||
dir_core_assets, false);
|
||||
task_push_core_backup(core_path, NULL, 0, CORE_BACKUP_MODE_MANUAL,
|
||||
(size_t)auto_backup_history_size, dir_core_assets, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -525,6 +525,8 @@ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_overlay_show_physical_inputs_p
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_core_updater_buildbot_assets_url, MENU_ENUM_SUBLABEL_BUILDBOT_ASSETS_URL)
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_core_updater_auto_extract_archive, MENU_ENUM_SUBLABEL_CORE_UPDATER_AUTO_EXTRACT_ARCHIVE)
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_core_updater_show_experimental_cores, MENU_ENUM_SUBLABEL_CORE_UPDATER_SHOW_EXPERIMENTAL_CORES)
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_core_updater_auto_backup, MENU_ENUM_SUBLABEL_CORE_UPDATER_AUTO_BACKUP)
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_core_updater_auto_backup_history_size, MENU_ENUM_SUBLABEL_CORE_UPDATER_AUTO_BACKUP_HISTORY_SIZE)
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_netplay_refresh_rooms, MENU_ENUM_SUBLABEL_NETPLAY_REFRESH_ROOMS)
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_rename_entry, MENU_ENUM_SUBLABEL_RENAME_ENTRY)
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_delete_entry, MENU_ENUM_SUBLABEL_DELETE_ENTRY)
|
||||
@ -2375,6 +2377,12 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs,
|
||||
case MENU_ENUM_LABEL_CORE_UPDATER_SHOW_EXPERIMENTAL_CORES:
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_core_updater_show_experimental_cores);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_CORE_UPDATER_AUTO_BACKUP:
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_core_updater_auto_backup);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_CORE_UPDATER_AUTO_BACKUP_HISTORY_SIZE:
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_core_updater_auto_backup_history_size);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_CORE_UPDATER_BUILDBOT_URL:
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_core_updater_buildbot_url);
|
||||
break;
|
||||
|
@ -453,7 +453,7 @@ static unsigned menu_displaylist_parse_core_backup_list(
|
||||
if (core_backup_list_get_index(backup_list, i, &entry) &&
|
||||
entry && !string_is_empty(entry->backup_path))
|
||||
{
|
||||
char timestamp[32];
|
||||
char timestamp[128];
|
||||
char crc[16];
|
||||
|
||||
timestamp[0] = '\0';
|
||||
@ -465,6 +465,14 @@ static unsigned menu_displaylist_parse_core_backup_list(
|
||||
core_backup_list_get_entry_crc_str(
|
||||
entry, crc, sizeof(crc));
|
||||
|
||||
/* Append 'auto backup' tag to timestamp, if required */
|
||||
if (entry->backup_mode == CORE_BACKUP_MODE_AUTO)
|
||||
{
|
||||
strlcat(timestamp, " ", sizeof(timestamp));
|
||||
strlcat(timestamp, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_BACKUP_MODE_AUTO),
|
||||
sizeof(timestamp));
|
||||
}
|
||||
|
||||
/* Add menu entry */
|
||||
if (menu_entries_append_enum(info->list,
|
||||
timestamp,
|
||||
@ -7323,6 +7331,8 @@ unsigned menu_displaylist_build_list(
|
||||
{MENU_ENUM_LABEL_BUILDBOT_ASSETS_URL, PARSE_ONLY_STRING},
|
||||
{MENU_ENUM_LABEL_CORE_UPDATER_AUTO_EXTRACT_ARCHIVE, PARSE_ONLY_BOOL},
|
||||
{MENU_ENUM_LABEL_CORE_UPDATER_SHOW_EXPERIMENTAL_CORES, PARSE_ONLY_BOOL},
|
||||
{MENU_ENUM_LABEL_CORE_UPDATER_AUTO_BACKUP, PARSE_ONLY_BOOL},
|
||||
{MENU_ENUM_LABEL_CORE_UPDATER_AUTO_BACKUP_HISTORY_SIZE, PARSE_ONLY_UINT},
|
||||
};
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(build_list); i++)
|
||||
|
@ -16162,6 +16162,38 @@ static bool setting_append_list(
|
||||
general_read_handler,
|
||||
SD_FLAG_NONE
|
||||
);
|
||||
|
||||
CONFIG_BOOL(
|
||||
list, list_info,
|
||||
&settings->bools.core_updater_auto_backup,
|
||||
MENU_ENUM_LABEL_CORE_UPDATER_AUTO_BACKUP,
|
||||
MENU_ENUM_LABEL_VALUE_CORE_UPDATER_AUTO_BACKUP,
|
||||
DEFAULT_CORE_UPDATER_AUTO_BACKUP,
|
||||
MENU_ENUM_LABEL_VALUE_OFF,
|
||||
MENU_ENUM_LABEL_VALUE_ON,
|
||||
&group_info,
|
||||
&subgroup_info,
|
||||
parent_group,
|
||||
general_write_handler,
|
||||
general_read_handler,
|
||||
SD_FLAG_NONE
|
||||
);
|
||||
|
||||
CONFIG_UINT(
|
||||
list, list_info,
|
||||
&settings->uints.core_updater_auto_backup_history_size,
|
||||
MENU_ENUM_LABEL_CORE_UPDATER_AUTO_BACKUP_HISTORY_SIZE,
|
||||
MENU_ENUM_LABEL_VALUE_CORE_UPDATER_AUTO_BACKUP_HISTORY_SIZE,
|
||||
DEFAULT_CORE_UPDATER_AUTO_BACKUP_HISTORY_SIZE,
|
||||
&group_info,
|
||||
&subgroup_info,
|
||||
parent_group,
|
||||
general_write_handler,
|
||||
general_read_handler);
|
||||
(*list)[list_info->index - 1].ui_type = ST_UI_TYPE_UINT_COMBOBOX;
|
||||
(*list)[list_info->index - 1].action_ok = &setting_action_ok_uint;
|
||||
(*list)[list_info->index - 1].offset_by = 1;
|
||||
menu_settings_list_current_add_range(list, list_info, (*list)[list_info->index - 1].offset_by, 500, 1, true, true);
|
||||
#endif
|
||||
END_SUB_GROUP(list, list_info, parent_group);
|
||||
END_GROUP(list, list_info, parent_group);
|
||||
|
@ -1955,6 +1955,8 @@ enum msg_hash_enums
|
||||
MENU_LABEL(CORE_MANAGER_LIST),
|
||||
MENU_LABEL(CORE_UPDATER_AUTO_EXTRACT_ARCHIVE),
|
||||
MENU_LABEL(CORE_UPDATER_SHOW_EXPERIMENTAL_CORES),
|
||||
MENU_LABEL(CORE_UPDATER_AUTO_BACKUP),
|
||||
MENU_LABEL(CORE_UPDATER_AUTO_BACKUP_HISTORY_SIZE),
|
||||
MENU_LABEL(CORE_UPDATER_BUILDBOT_URL),
|
||||
MENU_LABEL(BUILDBOT_ASSETS_URL),
|
||||
MENU_LABEL(CORE_SET_SUPPORTS_NO_CONTENT_ENABLE),
|
||||
@ -2014,11 +2016,13 @@ enum msg_hash_enums
|
||||
|
||||
MENU_ENUM_LABEL_CORE_RESTORE_BACKUP_ENTRY,
|
||||
MENU_ENUM_LABEL_CORE_DELETE_BACKUP_ENTRY,
|
||||
MENU_ENUM_LABEL_VALUE_CORE_BACKUP_MODE_AUTO,
|
||||
MENU_ENUM_LABEL_VALUE_CORE_BACKUP_CRC,
|
||||
|
||||
MSG_CORE_BACKUP_SCANNING_CORE,
|
||||
MSG_CORE_BACKUP_ALREADY_EXISTS,
|
||||
MSG_BACKING_UP_CORE,
|
||||
MSG_PRUNING_CORE_BACKUP_HISTORY,
|
||||
MSG_CORE_BACKUP_COMPLETE,
|
||||
MSG_CORE_RESTORATION_ALREADY_INSTALLED,
|
||||
MSG_RESTORING_CORE,
|
||||
|
@ -44,6 +44,8 @@ enum core_backup_status
|
||||
CORE_BACKUP_CHECK_CRC,
|
||||
CORE_BACKUP_PRE_ITERATE,
|
||||
CORE_BACKUP_ITERATE,
|
||||
CORE_BACKUP_CHECK_HISTORY,
|
||||
CORE_BACKUP_PRUNE_HISTORY,
|
||||
CORE_BACKUP_END,
|
||||
CORE_RESTORE_GET_CORE_CRC,
|
||||
CORE_RESTORE_GET_BACKUP_CRC,
|
||||
@ -61,6 +63,9 @@ typedef struct core_backup_handle
|
||||
char *backup_path;
|
||||
enum core_backup_type backup_type;
|
||||
enum core_backup_mode backup_mode;
|
||||
size_t auto_backup_history_size;
|
||||
size_t num_auto_backups_to_remove;
|
||||
size_t backup_index;
|
||||
int64_t core_file_size;
|
||||
int64_t backup_file_size;
|
||||
int64_t file_data_read;
|
||||
@ -348,7 +353,13 @@ static void task_core_backup_handler(retro_task_t *task)
|
||||
backup_handle->backup_file = NULL;
|
||||
|
||||
backup_handle->success = true;
|
||||
backup_handle->status = CORE_BACKUP_END;
|
||||
|
||||
/* If this is an automatic backup, check whether
|
||||
* any old backup files should be deleted.
|
||||
* In all other cases, backup is complete */
|
||||
backup_handle->status = (backup_handle->backup_mode ==
|
||||
CORE_BACKUP_MODE_AUTO) ?
|
||||
CORE_BACKUP_CHECK_HISTORY : CORE_BACKUP_END;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -368,6 +379,103 @@ static void task_core_backup_handler(retro_task_t *task)
|
||||
(backup_handle->file_data_read * 100) / backup_handle->core_file_size);
|
||||
}
|
||||
break;
|
||||
case CORE_BACKUP_CHECK_HISTORY:
|
||||
{
|
||||
size_t num_backups;
|
||||
|
||||
/* Sanity check: We can only reach this stage
|
||||
* when performing automatic backups, but verify
|
||||
* that this is true (i.e. don't inadvertently
|
||||
* delete backups of the wrong type if someone
|
||||
* edits the CORE_BACKUP_ITERATE case statement...) */
|
||||
if (backup_handle->backup_mode != CORE_BACKUP_MODE_AUTO)
|
||||
{
|
||||
backup_handle->status = CORE_BACKUP_END;
|
||||
break;
|
||||
}
|
||||
|
||||
/* This is an automated backup
|
||||
* > Fetch number of existing auto backups
|
||||
* in the list
|
||||
* > If we reach this stage then a new backup
|
||||
* has been created successfully -> increment
|
||||
* count by one */
|
||||
num_backups = core_backup_list_get_num_backups(
|
||||
backup_handle->backup_list,
|
||||
CORE_BACKUP_MODE_AUTO);
|
||||
num_backups++;
|
||||
|
||||
/* Check whether we have exceeded the backup
|
||||
* history size limit */
|
||||
if (num_backups > backup_handle->auto_backup_history_size)
|
||||
{
|
||||
char task_title[PATH_MAX_LENGTH];
|
||||
|
||||
task_title[0] = '\0';
|
||||
|
||||
/* Get number of old backups to remove */
|
||||
backup_handle->num_auto_backups_to_remove = num_backups -
|
||||
backup_handle->auto_backup_history_size;
|
||||
|
||||
/* Update task title */
|
||||
task_free_title(task);
|
||||
strlcpy(task_title, msg_hash_to_str(MSG_PRUNING_CORE_BACKUP_HISTORY),
|
||||
sizeof(task_title));
|
||||
strlcat(task_title, backup_handle->core_name, sizeof(task_title));
|
||||
task_set_title(task, strdup(task_title));
|
||||
|
||||
/* Go to history clean-up phase */
|
||||
backup_handle->status = CORE_BACKUP_PRUNE_HISTORY;
|
||||
}
|
||||
/* No backups to remove - task is complete */
|
||||
else
|
||||
backup_handle->status = CORE_BACKUP_END;
|
||||
}
|
||||
break;
|
||||
case CORE_BACKUP_PRUNE_HISTORY:
|
||||
{
|
||||
size_t list_size = core_backup_list_size(backup_handle->backup_list);
|
||||
|
||||
/* The core backup list is automatically sorted
|
||||
* by timestamp - simply loop from start to end
|
||||
* and delete automatic backups until the required
|
||||
* number have been removed */
|
||||
while ((backup_handle->backup_index < list_size) &&
|
||||
(backup_handle->num_auto_backups_to_remove > 0))
|
||||
{
|
||||
const core_backup_list_entry_t *entry = NULL;
|
||||
|
||||
if (core_backup_list_get_index(
|
||||
backup_handle->backup_list,
|
||||
backup_handle->backup_index,
|
||||
&entry) &&
|
||||
entry &&
|
||||
(entry->backup_mode == CORE_BACKUP_MODE_AUTO))
|
||||
{
|
||||
/* Delete backup file (if it exists) */
|
||||
if (path_is_valid(entry->backup_path))
|
||||
filestream_delete(entry->backup_path);
|
||||
|
||||
backup_handle->num_auto_backups_to_remove--;
|
||||
backup_handle->backup_index++;
|
||||
|
||||
/* Break here - only remove one file per
|
||||
* iteration of the task */
|
||||
break;
|
||||
}
|
||||
|
||||
backup_handle->backup_index++;
|
||||
}
|
||||
|
||||
/* Check whether all old backups have been
|
||||
* removed (also handle error conditions by
|
||||
* ensuring we quit if end of backup list is
|
||||
* reached...) */
|
||||
if ((backup_handle->num_auto_backups_to_remove < 1) ||
|
||||
(backup_handle->backup_index >= list_size))
|
||||
backup_handle->status = CORE_BACKUP_END;
|
||||
}
|
||||
break;
|
||||
case CORE_BACKUP_END:
|
||||
{
|
||||
char task_title[PATH_MAX_LENGTH];
|
||||
@ -409,14 +517,20 @@ task_finished:
|
||||
free_core_backup_handle(backup_handle);
|
||||
}
|
||||
|
||||
/* Note: If crc is set to 0, crc of core_path file will
|
||||
* be calculated automatically */
|
||||
void *task_push_core_backup(const char *core_path,
|
||||
/* Note 1: If crc is set to 0, crc of core_path file will
|
||||
* be calculated automatically
|
||||
* Note 2: If core_display_name is set to NULL, display
|
||||
* name will be determined automatically
|
||||
* > core_display_name *must* be set to a non-empty
|
||||
* string if task_push_core_backup() is *not* called
|
||||
* on the main thread */
|
||||
void *task_push_core_backup(
|
||||
const char *core_path, const char *core_display_name,
|
||||
uint32_t crc, enum core_backup_mode backup_mode,
|
||||
size_t auto_backup_history_size,
|
||||
const char *dir_core_assets, bool mute)
|
||||
{
|
||||
task_finder_data_t find_data;
|
||||
core_info_ctx_find_t core_info;
|
||||
const char *core_name = NULL;
|
||||
retro_task_t *task = NULL;
|
||||
core_backup_handle_t *backup_handle = NULL;
|
||||
@ -438,20 +552,27 @@ void *task_push_core_backup(const char *core_path,
|
||||
goto error;
|
||||
|
||||
/* Get core name */
|
||||
core_info.inf = NULL;
|
||||
core_info.path = core_path;
|
||||
|
||||
/* If core is found, use display name */
|
||||
if (core_info_find(&core_info) &&
|
||||
core_info.inf->display_name)
|
||||
core_name = core_info.inf->display_name;
|
||||
if (!string_is_empty(core_display_name))
|
||||
core_name = core_display_name;
|
||||
else
|
||||
{
|
||||
/* If not, use core file name */
|
||||
core_name = path_basename(core_path);
|
||||
core_info_ctx_find_t core_info;
|
||||
|
||||
if (string_is_empty(core_name))
|
||||
goto error;
|
||||
core_info.inf = NULL;
|
||||
core_info.path = core_path;
|
||||
|
||||
/* If core is found, use display name */
|
||||
if (core_info_find(&core_info) &&
|
||||
core_info.inf->display_name)
|
||||
core_name = core_info.inf->display_name;
|
||||
else
|
||||
{
|
||||
/* If not, use core file name */
|
||||
core_name = path_basename(core_path);
|
||||
|
||||
if (string_is_empty(core_name))
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
/* Configure handle */
|
||||
@ -460,23 +581,26 @@ void *task_push_core_backup(const char *core_path,
|
||||
if (!backup_handle)
|
||||
goto error;
|
||||
|
||||
backup_handle->dir_core_assets = string_is_empty(dir_core_assets) ? NULL : strdup(dir_core_assets);
|
||||
backup_handle->core_path = strdup(core_path);
|
||||
backup_handle->core_name = strdup(core_name);
|
||||
backup_handle->backup_path = NULL;
|
||||
backup_handle->backup_type = CORE_BACKUP_TYPE_ARCHIVE;
|
||||
backup_handle->backup_mode = backup_mode;
|
||||
backup_handle->core_file_size = 0;
|
||||
backup_handle->backup_file_size = 0;
|
||||
backup_handle->file_data_read = 0;
|
||||
backup_handle->core_crc = crc;
|
||||
backup_handle->backup_crc = 0;
|
||||
backup_handle->crc_match = false;
|
||||
backup_handle->success = false;
|
||||
backup_handle->core_file = NULL;
|
||||
backup_handle->backup_file = NULL;
|
||||
backup_handle->backup_list = NULL;
|
||||
backup_handle->status = CORE_BACKUP_BEGIN;
|
||||
backup_handle->dir_core_assets = string_is_empty(dir_core_assets) ? NULL : strdup(dir_core_assets);
|
||||
backup_handle->core_path = strdup(core_path);
|
||||
backup_handle->core_name = strdup(core_name);
|
||||
backup_handle->backup_path = NULL;
|
||||
backup_handle->backup_type = CORE_BACKUP_TYPE_ARCHIVE;
|
||||
backup_handle->backup_mode = backup_mode;
|
||||
backup_handle->auto_backup_history_size = auto_backup_history_size;
|
||||
backup_handle->num_auto_backups_to_remove = 0;
|
||||
backup_handle->backup_index = 0;
|
||||
backup_handle->core_file_size = 0;
|
||||
backup_handle->backup_file_size = 0;
|
||||
backup_handle->file_data_read = 0;
|
||||
backup_handle->core_crc = crc;
|
||||
backup_handle->backup_crc = 0;
|
||||
backup_handle->crc_match = false;
|
||||
backup_handle->success = false;
|
||||
backup_handle->core_file = NULL;
|
||||
backup_handle->backup_file = NULL;
|
||||
backup_handle->backup_list = NULL;
|
||||
backup_handle->status = CORE_BACKUP_BEGIN;
|
||||
|
||||
/* Create task */
|
||||
task = task_init();
|
||||
@ -899,23 +1023,26 @@ bool task_push_core_restore(const char *backup_path, const char *dir_libretro,
|
||||
if (!backup_handle)
|
||||
goto error;
|
||||
|
||||
backup_handle->dir_core_assets = NULL;
|
||||
backup_handle->core_path = strdup(core_path);
|
||||
backup_handle->core_name = strdup(core_name);
|
||||
backup_handle->backup_path = strdup(backup_path);
|
||||
backup_handle->backup_type = backup_type;
|
||||
backup_handle->backup_mode = CORE_BACKUP_MODE_MANUAL;
|
||||
backup_handle->core_file_size = 0;
|
||||
backup_handle->backup_file_size = 0;
|
||||
backup_handle->file_data_read = 0;
|
||||
backup_handle->core_crc = 0;
|
||||
backup_handle->backup_crc = 0;
|
||||
backup_handle->crc_match = false;
|
||||
backup_handle->success = false;
|
||||
backup_handle->core_file = NULL;
|
||||
backup_handle->backup_file = NULL;
|
||||
backup_handle->backup_list = NULL;
|
||||
backup_handle->status = CORE_RESTORE_GET_CORE_CRC;
|
||||
backup_handle->dir_core_assets = NULL;
|
||||
backup_handle->core_path = strdup(core_path);
|
||||
backup_handle->core_name = strdup(core_name);
|
||||
backup_handle->backup_path = strdup(backup_path);
|
||||
backup_handle->backup_type = backup_type;
|
||||
backup_handle->backup_mode = CORE_BACKUP_MODE_MANUAL;
|
||||
backup_handle->auto_backup_history_size = 0;
|
||||
backup_handle->num_auto_backups_to_remove = 0;
|
||||
backup_handle->backup_index = 0;
|
||||
backup_handle->core_file_size = 0;
|
||||
backup_handle->backup_file_size = 0;
|
||||
backup_handle->file_data_read = 0;
|
||||
backup_handle->core_crc = 0;
|
||||
backup_handle->backup_crc = 0;
|
||||
backup_handle->crc_match = false;
|
||||
backup_handle->success = false;
|
||||
backup_handle->core_file = NULL;
|
||||
backup_handle->backup_file = NULL;
|
||||
backup_handle->backup_list = NULL;
|
||||
backup_handle->status = CORE_RESTORE_GET_CORE_CRC;
|
||||
|
||||
/* Create task */
|
||||
task = task_init();
|
||||
|
@ -66,6 +66,9 @@ typedef struct core_updater_list_handle
|
||||
enum core_updater_download_status
|
||||
{
|
||||
CORE_UPDATER_DOWNLOAD_BEGIN = 0,
|
||||
CORE_UPDATER_DOWNLOAD_START_BACKUP,
|
||||
CORE_UPDATER_DOWNLOAD_WAIT_BACKUP,
|
||||
CORE_UPDATER_DOWNLOAD_START_TRANSFER,
|
||||
CORE_UPDATER_DOWNLOAD_WAIT_TRANSFER,
|
||||
CORE_UPDATER_DOWNLOAD_WAIT_DECOMPRESS,
|
||||
CORE_UPDATER_DOWNLOAD_END
|
||||
@ -73,14 +76,17 @@ enum core_updater_download_status
|
||||
|
||||
typedef struct core_updater_download_handle
|
||||
{
|
||||
bool auto_backup;
|
||||
size_t auto_backup_history_size;
|
||||
char *path_dir_libretro;
|
||||
char *path_dir_core_assets;
|
||||
char *remote_filename;
|
||||
char *remote_core_path;
|
||||
char *local_download_path;
|
||||
char *local_core_path;
|
||||
char *display_name;
|
||||
uint32_t local_crc;
|
||||
uint32_t remote_crc;
|
||||
bool check_crc;
|
||||
bool crc_match;
|
||||
retro_task_t *http_task;
|
||||
bool http_task_finished;
|
||||
@ -88,6 +94,8 @@ typedef struct core_updater_download_handle
|
||||
retro_task_t *decompress_task;
|
||||
bool decompress_task_finished;
|
||||
bool decompress_task_complete;
|
||||
bool backup_enabled;
|
||||
retro_task_t *backup_task;
|
||||
enum core_updater_download_status status;
|
||||
} core_updater_download_handle_t;
|
||||
|
||||
@ -104,7 +112,10 @@ enum update_installed_cores_status
|
||||
|
||||
typedef struct update_installed_cores_handle
|
||||
{
|
||||
bool auto_backup;
|
||||
size_t auto_backup_history_size;
|
||||
char *path_dir_libretro;
|
||||
char *path_dir_core_assets;
|
||||
core_updater_list_t* core_list;
|
||||
retro_task_t *list_task;
|
||||
retro_task_t *download_task;
|
||||
@ -119,40 +130,37 @@ typedef struct update_installed_cores_handle
|
||||
/* Utility functions */
|
||||
/*********************/
|
||||
|
||||
/* Returns true if local core has the same crc
|
||||
* value as core on buildbot */
|
||||
static bool local_core_matches_remote_crc(
|
||||
const char *local_core_path, uint32_t remote_crc)
|
||||
/* Returns CRC32 of specified core file */
|
||||
static uint32_t task_core_updater_get_core_crc(const char *core_path)
|
||||
{
|
||||
/* Sanity check */
|
||||
if (string_is_empty(local_core_path) || (remote_crc == 0))
|
||||
return false;
|
||||
if (string_is_empty(core_path))
|
||||
return 0;
|
||||
|
||||
if (path_is_valid(local_core_path))
|
||||
if (path_is_valid(core_path))
|
||||
{
|
||||
/* Open core file */
|
||||
intfstream_t *local_core_file = intfstream_open_file(
|
||||
local_core_path, RETRO_VFS_FILE_ACCESS_READ,
|
||||
intfstream_t *core_file = intfstream_open_file(
|
||||
core_path, RETRO_VFS_FILE_ACCESS_READ,
|
||||
RETRO_VFS_FILE_ACCESS_HINT_NONE);
|
||||
|
||||
if (local_core_file)
|
||||
if (core_file)
|
||||
{
|
||||
uint32_t crc = 0;
|
||||
|
||||
/* Get crc value */
|
||||
bool success = intfstream_get_crc(local_core_file, &crc);
|
||||
bool success = intfstream_get_crc(core_file, &crc);
|
||||
|
||||
/* Close core file */
|
||||
intfstream_close(local_core_file);
|
||||
free(local_core_file);
|
||||
local_core_file = NULL;
|
||||
intfstream_close(core_file);
|
||||
free(core_file);
|
||||
core_file = NULL;
|
||||
|
||||
/* Check whether crc matches remote file */
|
||||
if (success && (crc != 0) && (crc == remote_crc))
|
||||
return true;
|
||||
if (success)
|
||||
return crc;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************/
|
||||
@ -184,7 +192,7 @@ finish:
|
||||
|
||||
/* Log any error messages */
|
||||
if (!success)
|
||||
RARCH_ERR("Download of core list '%s' failed: %s\n",
|
||||
RARCH_ERR("[core updater] Download of core list '%s' failed: %s\n",
|
||||
(transf ? transf->path: "unknown"),
|
||||
(err ? err : "unknown"));
|
||||
|
||||
@ -482,7 +490,7 @@ static void cb_decompress_task_core_updater_download(
|
||||
|
||||
/* Log any error messages */
|
||||
if (!string_is_empty(err))
|
||||
RARCH_ERR("%s", err);
|
||||
RARCH_ERR("[core updater] %s", err);
|
||||
}
|
||||
|
||||
void cb_http_task_core_updater_download(
|
||||
@ -576,7 +584,7 @@ finish:
|
||||
|
||||
/* Log any error messages */
|
||||
if (!string_is_empty(err))
|
||||
RARCH_ERR("Download of '%s' failed: %s\n",
|
||||
RARCH_ERR("[core updater] Download of '%s' failed: %s\n",
|
||||
(transf ? transf->path: "unknown"), err);
|
||||
|
||||
if (data)
|
||||
@ -598,6 +606,9 @@ static void free_core_updater_download_handle(core_updater_download_handle_t *do
|
||||
if (download_handle->path_dir_libretro)
|
||||
free(download_handle->path_dir_libretro);
|
||||
|
||||
if (download_handle->path_dir_core_assets)
|
||||
free(download_handle->path_dir_core_assets);
|
||||
|
||||
if (download_handle->remote_filename)
|
||||
free(download_handle->remote_filename);
|
||||
|
||||
@ -636,13 +647,15 @@ static void task_core_updater_download_handler(retro_task_t *task)
|
||||
{
|
||||
case CORE_UPDATER_DOWNLOAD_BEGIN:
|
||||
{
|
||||
file_transfer_t *transf = NULL;
|
||||
/* Get CRC of existing core, if required */
|
||||
if (download_handle->local_crc == 0)
|
||||
download_handle->local_crc = task_core_updater_get_core_crc(
|
||||
download_handle->local_core_path);
|
||||
|
||||
/* Check CRC of existing core, if required */
|
||||
if (download_handle->check_crc)
|
||||
download_handle->crc_match = local_core_matches_remote_crc(
|
||||
download_handle->local_core_path,
|
||||
download_handle->remote_crc);
|
||||
/* Check whether existing core and remote core
|
||||
* have the same CRC */
|
||||
download_handle->crc_match = (download_handle->local_crc != 0) &&
|
||||
(download_handle->local_crc == download_handle->remote_crc);
|
||||
|
||||
/* If CRC matches, end task immediately */
|
||||
if (download_handle->crc_match)
|
||||
@ -651,6 +664,99 @@ static void task_core_updater_download_handler(retro_task_t *task)
|
||||
break;
|
||||
}
|
||||
|
||||
/* If automatic backups are enabled and core is
|
||||
* already installed, trigger a backup - otherwise,
|
||||
* initialise download */
|
||||
download_handle->backup_enabled = download_handle->auto_backup &&
|
||||
path_is_valid(download_handle->local_core_path);
|
||||
|
||||
download_handle->status = download_handle->backup_enabled ?
|
||||
CORE_UPDATER_DOWNLOAD_START_BACKUP :
|
||||
CORE_UPDATER_DOWNLOAD_START_TRANSFER;
|
||||
}
|
||||
break;
|
||||
case CORE_UPDATER_DOWNLOAD_START_BACKUP:
|
||||
{
|
||||
/* Request core backup */
|
||||
download_handle->backup_task = (retro_task_t*)task_push_core_backup(
|
||||
download_handle->local_core_path,
|
||||
download_handle->display_name,
|
||||
download_handle->local_crc, CORE_BACKUP_MODE_AUTO,
|
||||
download_handle->auto_backup_history_size,
|
||||
download_handle->path_dir_core_assets, true);
|
||||
|
||||
if (download_handle->backup_task)
|
||||
{
|
||||
char task_title[PATH_MAX_LENGTH];
|
||||
|
||||
task_title[0] = '\0';
|
||||
|
||||
/* Update task title */
|
||||
task_free_title(task);
|
||||
|
||||
strlcpy(
|
||||
task_title, msg_hash_to_str(MSG_BACKING_UP_CORE),
|
||||
sizeof(task_title));
|
||||
strlcat(task_title, download_handle->display_name, sizeof(task_title));
|
||||
|
||||
task_set_title(task, strdup(task_title));
|
||||
|
||||
/* Start waiting for backup to complete */
|
||||
download_handle->status = CORE_UPDATER_DOWNLOAD_WAIT_BACKUP;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This cannot realistically happen...
|
||||
* > If it does, just log an error and initialise
|
||||
* download */
|
||||
RARCH_ERR("[core updater] Failed to backup core: %s\n",
|
||||
download_handle->local_core_path);
|
||||
download_handle->backup_enabled = false;
|
||||
download_handle->status = CORE_UPDATER_DOWNLOAD_START_TRANSFER;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CORE_UPDATER_DOWNLOAD_WAIT_BACKUP:
|
||||
{
|
||||
bool backup_complete = false;
|
||||
|
||||
/* > If task is running, check 'is finished'
|
||||
* status
|
||||
* > If task is NULL, then it is finished
|
||||
* by definition */
|
||||
if (download_handle->backup_task)
|
||||
{
|
||||
backup_complete = task_get_finished(download_handle->backup_task);
|
||||
|
||||
/* If backup task is running, copy current
|
||||
* progress value to *this* task */
|
||||
if (!backup_complete)
|
||||
{
|
||||
/* Backup accounts for first third of
|
||||
* task progress */
|
||||
int8_t progress = task_get_progress(download_handle->backup_task);
|
||||
|
||||
task_set_progress(task, (int8_t)(((float)progress * (1.0f / 3.0f)) + 0.5f));
|
||||
}
|
||||
}
|
||||
else
|
||||
backup_complete = true;
|
||||
|
||||
/* If backup is complete, initialise download */
|
||||
if (backup_complete)
|
||||
{
|
||||
download_handle->backup_task = NULL;
|
||||
download_handle->status = CORE_UPDATER_DOWNLOAD_START_TRANSFER;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CORE_UPDATER_DOWNLOAD_START_TRANSFER:
|
||||
{
|
||||
file_transfer_t *transf = NULL;
|
||||
char task_title[PATH_MAX_LENGTH];
|
||||
|
||||
task_title[0] = '\0';
|
||||
|
||||
/* Configure file transfer object */
|
||||
transf = (file_transfer_t*)calloc(1, sizeof(file_transfer_t));
|
||||
|
||||
@ -668,16 +774,6 @@ static void task_core_updater_download_handler(retro_task_t *task)
|
||||
download_handle->remote_core_path, true, NULL,
|
||||
cb_http_task_core_updater_download, transf);
|
||||
|
||||
/* Start waiting for HTTP transfer to complete */
|
||||
download_handle->status = CORE_UPDATER_DOWNLOAD_WAIT_TRANSFER;
|
||||
}
|
||||
break;
|
||||
case CORE_UPDATER_DOWNLOAD_WAIT_TRANSFER:
|
||||
{
|
||||
char task_title[PATH_MAX_LENGTH];
|
||||
|
||||
task_title[0] = '\0';
|
||||
|
||||
/* Update task title */
|
||||
task_free_title(task);
|
||||
|
||||
@ -688,6 +784,12 @@ static void task_core_updater_download_handler(retro_task_t *task)
|
||||
|
||||
task_set_title(task, strdup(task_title));
|
||||
|
||||
/* Start waiting for HTTP transfer to complete */
|
||||
download_handle->status = CORE_UPDATER_DOWNLOAD_WAIT_TRANSFER;
|
||||
}
|
||||
break;
|
||||
case CORE_UPDATER_DOWNLOAD_WAIT_TRANSFER:
|
||||
{
|
||||
/* If HTTP task is NULL, then it either finished
|
||||
* or an error occurred - in either case,
|
||||
* just move on to the next state */
|
||||
@ -703,36 +805,46 @@ static void task_core_updater_download_handler(retro_task_t *task)
|
||||
* progress value to *this* task */
|
||||
if (!download_handle->http_task_finished)
|
||||
{
|
||||
/* Download accounts for first half of
|
||||
* task progress */
|
||||
/* > If backups are enabled, download accounts
|
||||
* for second third of task progress
|
||||
* > Otherwise, download accounts for first half
|
||||
* of task progress */
|
||||
int8_t progress = task_get_progress(download_handle->http_task);
|
||||
|
||||
task_set_progress(task, progress >> 1);
|
||||
if (download_handle->backup_enabled)
|
||||
progress = (int8_t)(((float)progress * (1.0f / 3.0f)) + (100.0f / 3.0f) + 0.5f);
|
||||
else
|
||||
progress = progress >> 1;
|
||||
|
||||
task_set_progress(task, progress);
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait for task_push_http_transfer_file()
|
||||
* callback to trigger */
|
||||
if (download_handle->http_task_complete)
|
||||
{
|
||||
char task_title[PATH_MAX_LENGTH];
|
||||
|
||||
task_title[0] = '\0';
|
||||
|
||||
/* Update task title */
|
||||
task_free_title(task);
|
||||
|
||||
strlcpy(
|
||||
task_title, msg_hash_to_str(MSG_EXTRACTING_CORE),
|
||||
sizeof(task_title));
|
||||
strlcat(task_title, download_handle->display_name, sizeof(task_title));
|
||||
|
||||
task_set_title(task, strdup(task_title));
|
||||
|
||||
/* Start waiting for file to be extracted */
|
||||
download_handle->status = CORE_UPDATER_DOWNLOAD_WAIT_DECOMPRESS;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CORE_UPDATER_DOWNLOAD_WAIT_DECOMPRESS:
|
||||
{
|
||||
char task_title[PATH_MAX_LENGTH];
|
||||
|
||||
task_title[0] = '\0';
|
||||
|
||||
/* Update task title */
|
||||
task_free_title(task);
|
||||
|
||||
strlcpy(
|
||||
task_title, msg_hash_to_str(MSG_EXTRACTING_CORE),
|
||||
sizeof(task_title));
|
||||
strlcat(task_title, download_handle->display_name, sizeof(task_title));
|
||||
|
||||
task_set_title(task, strdup(task_title));
|
||||
|
||||
/* If decompression task is NULL, then it either
|
||||
* finished or an error occurred - in either case,
|
||||
* just move on to the next state */
|
||||
@ -749,11 +861,18 @@ static void task_core_updater_download_handler(retro_task_t *task)
|
||||
* current progress value to *this* task */
|
||||
if (!download_handle->decompress_task_finished)
|
||||
{
|
||||
/* Download accounts for second half
|
||||
* of task progress */
|
||||
/* > If backups are enabled, decompression accounts
|
||||
* for last third of task progress
|
||||
* > Otherwise, decompression accounts for second
|
||||
* half of task progress */
|
||||
int8_t progress = task_get_progress(download_handle->decompress_task);
|
||||
|
||||
task_set_progress(task, 50 + (progress >> 1));
|
||||
if (download_handle->backup_enabled)
|
||||
progress = (int8_t)(((float)progress * (1.0f / 3.0f)) + (200.0f / 3.0f) + 0.5f);
|
||||
else
|
||||
progress = 50 + (progress >> 1);
|
||||
|
||||
task_set_progress(task, progress);
|
||||
}
|
||||
}
|
||||
|
||||
@ -816,8 +935,10 @@ static bool task_core_updater_download_finder(retro_task_t *task, void *user_dat
|
||||
|
||||
void *task_push_core_updater_download(
|
||||
core_updater_list_t* core_list,
|
||||
const char *filename, bool mute, bool check_crc,
|
||||
const char *path_dir_libretro)
|
||||
const char *filename, uint32_t crc, bool mute,
|
||||
bool auto_backup, size_t auto_backup_history_size,
|
||||
const char *path_dir_libretro,
|
||||
const char *path_dir_core_assets)
|
||||
{
|
||||
task_finder_data_t find_data;
|
||||
char task_title[PATH_MAX_LENGTH];
|
||||
@ -861,14 +982,17 @@ void *task_push_core_updater_download(
|
||||
sizeof(local_download_path));
|
||||
|
||||
/* Configure handle */
|
||||
download_handle->auto_backup = auto_backup;
|
||||
download_handle->auto_backup_history_size = auto_backup_history_size;
|
||||
download_handle->path_dir_libretro = strdup(path_dir_libretro);
|
||||
download_handle->path_dir_core_assets = string_is_empty(path_dir_core_assets) ? NULL : strdup(path_dir_core_assets);
|
||||
download_handle->remote_filename = strdup(list_entry->remote_filename);
|
||||
download_handle->remote_core_path = strdup(list_entry->remote_core_path);
|
||||
download_handle->local_download_path = strdup(local_download_path);
|
||||
download_handle->local_core_path = strdup(list_entry->local_core_path);
|
||||
download_handle->display_name = strdup(list_entry->display_name);
|
||||
download_handle->local_crc = crc;
|
||||
download_handle->remote_crc = list_entry->crc;
|
||||
download_handle->check_crc = check_crc;
|
||||
download_handle->crc_match = false;
|
||||
download_handle->http_task = NULL;
|
||||
download_handle->http_task_finished = false;
|
||||
@ -876,6 +1000,8 @@ void *task_push_core_updater_download(
|
||||
download_handle->decompress_task = NULL;
|
||||
download_handle->decompress_task_finished = false;
|
||||
download_handle->decompress_task_complete = false;
|
||||
download_handle->backup_enabled = false;
|
||||
download_handle->backup_task = NULL;
|
||||
download_handle->status = CORE_UPDATER_DOWNLOAD_BEGIN;
|
||||
|
||||
/* Concurrent downloads of the same file are not allowed */
|
||||
@ -938,6 +1064,9 @@ static void free_update_installed_cores_handle(
|
||||
if (update_installed_handle->path_dir_libretro)
|
||||
free(update_installed_handle->path_dir_libretro);
|
||||
|
||||
if (update_installed_handle->path_dir_core_assets)
|
||||
free(update_installed_handle->path_dir_core_assets);
|
||||
|
||||
core_updater_list_free(update_installed_handle->core_list);
|
||||
|
||||
free(update_installed_handle);
|
||||
@ -1063,7 +1192,7 @@ static void task_update_installed_cores_handler(retro_task_t *task)
|
||||
case UPDATE_INSTALLED_CORES_UPDATE_CORE:
|
||||
{
|
||||
const core_updater_list_entry_t *list_entry = NULL;
|
||||
bool crc_match;
|
||||
uint32_t local_crc;
|
||||
|
||||
/* Get list entry
|
||||
* > In the event of an error, just return
|
||||
@ -1077,15 +1206,16 @@ static void task_update_installed_cores_handler(retro_task_t *task)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check CRC of existing core */
|
||||
crc_match = local_core_matches_remote_crc(
|
||||
list_entry->local_core_path,
|
||||
list_entry->crc);
|
||||
/* Get CRC of existing core */
|
||||
local_crc = task_core_updater_get_core_crc(
|
||||
list_entry->local_core_path);
|
||||
|
||||
/* If CRC matches, then core is already the most
|
||||
* recent version - just return to
|
||||
* UPDATE_INSTALLED_CORES_ITERATE state */
|
||||
if (crc_match)
|
||||
/* Check whether existing core and remote core
|
||||
* have the same CRC
|
||||
* > If CRC matches, then core is already the most
|
||||
* recent version - just return to
|
||||
* UPDATE_INSTALLED_CORES_ITERATE state */
|
||||
if ((local_crc != 0) && (local_crc == list_entry->crc))
|
||||
{
|
||||
update_installed_handle->status = UPDATE_INSTALLED_CORES_ITERATE;
|
||||
break;
|
||||
@ -1097,8 +1227,11 @@ static void task_update_installed_cores_handler(retro_task_t *task)
|
||||
task_push_core_updater_download(
|
||||
update_installed_handle->core_list,
|
||||
list_entry->remote_filename,
|
||||
true, false,
|
||||
update_installed_handle->path_dir_libretro);
|
||||
local_crc, true,
|
||||
update_installed_handle->auto_backup,
|
||||
update_installed_handle->auto_backup_history_size,
|
||||
update_installed_handle->path_dir_libretro,
|
||||
update_installed_handle->path_dir_core_assets);
|
||||
|
||||
/* Again, if an error occurred, just return to
|
||||
* UPDATE_INSTALLED_CORES_ITERATE state */
|
||||
@ -1208,7 +1341,10 @@ static bool task_update_installed_cores_finder(retro_task_t *task, void *user_da
|
||||
return false;
|
||||
}
|
||||
|
||||
void task_push_update_installed_cores(const char *path_dir_libretro)
|
||||
void task_push_update_installed_cores(
|
||||
bool auto_backup, size_t auto_backup_history_size,
|
||||
const char *path_dir_libretro,
|
||||
const char *path_dir_core_assets)
|
||||
{
|
||||
task_finder_data_t find_data;
|
||||
retro_task_t *task = NULL;
|
||||
@ -1217,20 +1353,24 @@ void task_push_update_installed_cores(const char *path_dir_libretro)
|
||||
calloc(1, sizeof(update_installed_cores_handle_t));
|
||||
|
||||
/* Sanity check */
|
||||
if (!update_installed_handle)
|
||||
if (!update_installed_handle ||
|
||||
string_is_empty(path_dir_libretro))
|
||||
goto error;
|
||||
|
||||
/* Configure handle */
|
||||
update_installed_handle->core_list = core_updater_list_init(
|
||||
CORE_UPDATER_LIST_SIZE);
|
||||
update_installed_handle->list_task = NULL;
|
||||
update_installed_handle->download_task = NULL;
|
||||
update_installed_handle->list_size = 0;
|
||||
update_installed_handle->list_index = 0;
|
||||
update_installed_handle->installed_index = 0;
|
||||
update_installed_handle->num_updated = 0;
|
||||
update_installed_handle->path_dir_libretro = strdup(path_dir_libretro);
|
||||
update_installed_handle->status = UPDATE_INSTALLED_CORES_BEGIN;
|
||||
update_installed_handle->auto_backup = auto_backup;
|
||||
update_installed_handle->auto_backup_history_size = auto_backup_history_size;
|
||||
update_installed_handle->path_dir_libretro = strdup(path_dir_libretro);
|
||||
update_installed_handle->path_dir_core_assets = string_is_empty(path_dir_core_assets) ?
|
||||
NULL : strdup(path_dir_core_assets);
|
||||
update_installed_handle->core_list = core_updater_list_init(CORE_UPDATER_LIST_SIZE);
|
||||
update_installed_handle->list_task = NULL;
|
||||
update_installed_handle->download_task = NULL;
|
||||
update_installed_handle->list_size = 0;
|
||||
update_installed_handle->list_index = 0;
|
||||
update_installed_handle->installed_index = 0;
|
||||
update_installed_handle->num_updated = 0;
|
||||
update_installed_handle->status = UPDATE_INSTALLED_CORES_BEGIN;
|
||||
|
||||
if (!update_installed_handle->core_list)
|
||||
goto error;
|
||||
|
@ -96,13 +96,21 @@ bool task_push_netplay_lan_scan_rooms(retro_task_callback_t cb);
|
||||
bool task_push_netplay_nat_traversal(void *nat_traversal_state, uint16_t port);
|
||||
|
||||
/* Core updater tasks */
|
||||
|
||||
void *task_push_get_core_updater_list(
|
||||
core_updater_list_t* core_list, bool mute, bool refresh_menu);
|
||||
/* Note: If crc is set to 0, crc of local core file
|
||||
* will be calculated automatically */
|
||||
void *task_push_core_updater_download(
|
||||
core_updater_list_t* core_list, const char *filename,
|
||||
bool mute, bool check_crc, const char *path_dir_libretro);
|
||||
void task_push_update_installed_cores(const char *path_dir_libretro);
|
||||
|
||||
core_updater_list_t* core_list,
|
||||
const char *filename, uint32_t crc, bool mute,
|
||||
bool auto_backup, size_t auto_backup_history_size,
|
||||
const char *path_dir_libretro,
|
||||
const char *path_dir_core_assets);
|
||||
void task_push_update_installed_cores(
|
||||
bool auto_backup, size_t auto_backup_history_size,
|
||||
const char *path_dir_libretro,
|
||||
const char *path_dir_core_assets);
|
||||
|
||||
bool task_push_pl_entry_thumbnail_download(
|
||||
const char *system,
|
||||
@ -121,12 +129,18 @@ bool task_push_pl_thumbnail_download(
|
||||
|
||||
/* Core backup/restore tasks */
|
||||
|
||||
/* Note: If crc is set to 0, crc of core_path file will
|
||||
* be calculated automatically */
|
||||
void *task_push_core_backup(const char *core_path,
|
||||
/* Note 1: If crc is set to 0, crc of core_path file will
|
||||
* be calculated automatically
|
||||
* Note 2: If core_display_name is set to NULL, display
|
||||
* name will be determined automatically
|
||||
* > core_display_name *must* be set to a non-empty
|
||||
* string if task_push_core_backup() is *not* called
|
||||
* on the main thread */
|
||||
void *task_push_core_backup(
|
||||
const char *core_path, const char *core_display_name,
|
||||
uint32_t crc, enum core_backup_mode backup_mode,
|
||||
size_t auto_backup_history_size,
|
||||
const char *dir_core_assets, bool mute);
|
||||
|
||||
/* Note: If 'core_loaded' is true, menu stack should be
|
||||
* flushed if task_push_core_restore() returns true */
|
||||
bool task_push_core_restore(const char *backup_path,
|
||||
|
Loading…
x
Reference in New Issue
Block a user