mirror of
https://github.com/libretro/RetroArch
synced 2025-04-10 15:45:19 +00:00
Merge pull request #10862 from jdgleaver/core-auto-backup
Add option to automatically backup cores when updating
This commit is contained in:
commit
43a65ec65a
@ -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_AUTO_EXTRACT_ARCHIVE true
|
||||||
#define DEFAULT_NETWORK_BUILDBOT_SHOW_EXPERIMENTAL_CORES false
|
#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)
|
#if defined(ANDROID) || defined(IOS)
|
||||||
#define DEFAULT_NETWORK_ON_DEMAND_THUMBNAILS true
|
#define DEFAULT_NETWORK_ON_DEMAND_THUMBNAILS true
|
||||||
#else
|
#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("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_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_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("camera_allow", &settings->bools.camera_allow, true, false, false);
|
||||||
SETTING_BOOL("discord_allow", &settings->bools.discord_enable, true, false, false);
|
SETTING_BOOL("discord_allow", &settings->bools.discord_enable, true, false, false);
|
||||||
#if defined(VITA)
|
#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);
|
SETTING_UINT("playlist_sublabel_last_played_style", &settings->uints.playlist_sublabel_last_played_style, true, DEFAULT_PLAYLIST_SUBLABEL_LAST_PLAYED_STYLE, false);
|
||||||
#endif
|
#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;
|
*size = count;
|
||||||
|
|
||||||
return tmp;
|
return tmp;
|
||||||
|
@ -286,6 +286,7 @@ typedef struct settings
|
|||||||
bool network_buildbot_auto_extract_archive;
|
bool network_buildbot_auto_extract_archive;
|
||||||
bool network_buildbot_show_experimental_cores;
|
bool network_buildbot_show_experimental_cores;
|
||||||
bool network_on_demand_thumbnails;
|
bool network_on_demand_thumbnails;
|
||||||
|
bool core_updater_auto_backup;
|
||||||
|
|
||||||
/* UI */
|
/* UI */
|
||||||
bool ui_menubar_enable;
|
bool ui_menubar_enable;
|
||||||
@ -621,6 +622,8 @@ typedef struct settings
|
|||||||
unsigned ai_service_mode;
|
unsigned ai_service_mode;
|
||||||
unsigned ai_service_target_lang;
|
unsigned ai_service_target_lang;
|
||||||
unsigned ai_service_source_lang;
|
unsigned ai_service_source_lang;
|
||||||
|
|
||||||
|
unsigned core_updater_auto_backup_history_size;
|
||||||
} uints;
|
} uints;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
|
|
||||||
#include "frontend/frontend_driver.h"
|
#include "frontend/frontend_driver.h"
|
||||||
#include "file_path_special.h"
|
#include "file_path_special.h"
|
||||||
#include "core_info.h"
|
|
||||||
#include "verbosity.h"
|
#include "verbosity.h"
|
||||||
|
|
||||||
#include "core_backup.h"
|
#include "core_backup.h"
|
||||||
@ -532,7 +531,8 @@ core_backup_list_t *core_backup_list_init(
|
|||||||
if (dir_list->size < 1)
|
if (dir_list->size < 1)
|
||||||
goto error;
|
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);
|
dir_list_sort(dir_list, true);
|
||||||
|
|
||||||
/* Create core backup list */
|
/* Create core backup list */
|
||||||
@ -622,6 +622,30 @@ size_t core_backup_list_size(core_backup_list_t *backup_list)
|
|||||||
return backup_list->size;
|
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
|
/* Fetches core backup list entry corresponding
|
||||||
* to the specified entry index.
|
* to the specified entry index.
|
||||||
* Returns false if index is invalid. */
|
* 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 */
|
/* Returns number of entries in core backup list */
|
||||||
size_t core_backup_list_size(core_backup_list_t *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
|
/* Fetches core backup list entry corresponding
|
||||||
* to the specified entry index.
|
* to the specified entry index.
|
||||||
* Returns false if index is invalid. */
|
* Returns false if index is invalid. */
|
||||||
|
@ -516,6 +516,14 @@ MSG_HASH(
|
|||||||
MENU_ENUM_LABEL_CORE_UPDATER_SHOW_EXPERIMENTAL_CORES,
|
MENU_ENUM_LABEL_CORE_UPDATER_SHOW_EXPERIMENTAL_CORES,
|
||||||
"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(
|
MSG_HASH(
|
||||||
MENU_ENUM_LABEL_CORE_UPDATER_BUILDBOT_URL,
|
MENU_ENUM_LABEL_CORE_UPDATER_BUILDBOT_URL,
|
||||||
"core_updater_buildbot_url"
|
"core_updater_buildbot_url"
|
||||||
|
@ -481,6 +481,10 @@ MSG_HASH(
|
|||||||
MENU_ENUM_SUBLABEL_CORE_DELETE_BACKUP_LIST,
|
MENU_ENUM_SUBLABEL_CORE_DELETE_BACKUP_LIST,
|
||||||
"Remove a file from the list of archived backups."
|
"Remove a file from the list of archived backups."
|
||||||
)
|
)
|
||||||
|
MSG_HASH(
|
||||||
|
MENU_ENUM_LABEL_VALUE_CORE_BACKUP_MODE_AUTO,
|
||||||
|
"[Auto]"
|
||||||
|
)
|
||||||
MSG_HASH(
|
MSG_HASH(
|
||||||
MENU_ENUM_LABEL_VALUE_CORE_BACKUP_CRC,
|
MENU_ENUM_LABEL_VALUE_CORE_BACKUP_CRC,
|
||||||
"CRC32: "
|
"CRC32: "
|
||||||
@ -4598,6 +4602,22 @@ MSG_HASH(
|
|||||||
MENU_ENUM_SUBLABEL_CORE_UPDATER_SHOW_EXPERIMENTAL_CORES,
|
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."
|
"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 */
|
/* Settings > Playlists */
|
||||||
|
|
||||||
@ -10862,6 +10882,10 @@ MSG_HASH(
|
|||||||
MSG_BACKING_UP_CORE,
|
MSG_BACKING_UP_CORE,
|
||||||
"Backing up core: "
|
"Backing up core: "
|
||||||
)
|
)
|
||||||
|
MSG_HASH(
|
||||||
|
MSG_PRUNING_CORE_BACKUP_HISTORY,
|
||||||
|
"Removing obsolete backups: "
|
||||||
|
)
|
||||||
MSG_HASH(
|
MSG_HASH(
|
||||||
MSG_CORE_BACKUP_COMPLETE,
|
MSG_CORE_BACKUP_COMPLETE,
|
||||||
"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)
|
const char *label, unsigned type, size_t idx, size_t entry_idx)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_NETWORKING
|
#ifdef HAVE_NETWORKING
|
||||||
core_updater_list_t *core_list = core_updater_list_get_cached();
|
core_updater_list_t *core_list = core_updater_list_get_cached();
|
||||||
settings_t *settings = config_get_ptr();
|
settings_t *settings = config_get_ptr();
|
||||||
const char *path_dir_libretro = settings->paths.directory_libretro;
|
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)
|
if (!core_list)
|
||||||
return menu_cbs_exit();
|
return menu_cbs_exit();
|
||||||
|
|
||||||
task_push_core_updater_download(
|
task_push_core_updater_download(
|
||||||
core_list, path, false, true,
|
core_list, path, 0, false,
|
||||||
path_dir_libretro);
|
auto_backup, (size_t)auto_backup_history_size,
|
||||||
|
path_dir_libretro, path_dir_core_assets);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
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,
|
static int action_ok_update_installed_cores(const char *path,
|
||||||
const char *label, unsigned type, size_t idx, size_t entry_idx)
|
const char *label, unsigned type, size_t idx, size_t entry_idx)
|
||||||
{
|
{
|
||||||
settings_t *settings = config_get_ptr();
|
settings_t *settings = config_get_ptr();
|
||||||
const char *path_dir_libretro = settings->paths.directory_libretro;
|
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 */
|
/* Ensure networking is initialised */
|
||||||
generic_action_ok_command(CMD_EVENT_NETWORK_INIT);
|
generic_action_ok_command(CMD_EVENT_NETWORK_INIT);
|
||||||
|
|
||||||
/* Push update task */
|
/* 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;
|
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,
|
static int action_ok_core_create_backup(const char *path,
|
||||||
const char *label, unsigned type, size_t idx, size_t entry_idx)
|
const char *label, unsigned type, size_t idx, size_t entry_idx)
|
||||||
{
|
{
|
||||||
const char *core_path = label;
|
const char *core_path = label;
|
||||||
settings_t *settings = config_get_ptr();
|
settings_t *settings = config_get_ptr();
|
||||||
const char *dir_core_assets = settings->paths.directory_core_assets;
|
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))
|
if (string_is_empty(core_path))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
task_push_core_backup(core_path, 0, CORE_BACKUP_MODE_MANUAL,
|
task_push_core_backup(core_path, NULL, 0, CORE_BACKUP_MODE_MANUAL,
|
||||||
dir_core_assets, false);
|
(size_t)auto_backup_history_size, dir_core_assets, false);
|
||||||
|
|
||||||
return 0;
|
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_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_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_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_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_rename_entry, MENU_ENUM_SUBLABEL_RENAME_ENTRY)
|
||||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_delete_entry, MENU_ENUM_SUBLABEL_DELETE_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:
|
case MENU_ENUM_LABEL_CORE_UPDATER_SHOW_EXPERIMENTAL_CORES:
|
||||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_core_updater_show_experimental_cores);
|
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_core_updater_show_experimental_cores);
|
||||||
break;
|
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:
|
case MENU_ENUM_LABEL_CORE_UPDATER_BUILDBOT_URL:
|
||||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_core_updater_buildbot_url);
|
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_core_updater_buildbot_url);
|
||||||
break;
|
break;
|
||||||
|
@ -453,7 +453,7 @@ static unsigned menu_displaylist_parse_core_backup_list(
|
|||||||
if (core_backup_list_get_index(backup_list, i, &entry) &&
|
if (core_backup_list_get_index(backup_list, i, &entry) &&
|
||||||
entry && !string_is_empty(entry->backup_path))
|
entry && !string_is_empty(entry->backup_path))
|
||||||
{
|
{
|
||||||
char timestamp[32];
|
char timestamp[128];
|
||||||
char crc[16];
|
char crc[16];
|
||||||
|
|
||||||
timestamp[0] = '\0';
|
timestamp[0] = '\0';
|
||||||
@ -465,6 +465,14 @@ static unsigned menu_displaylist_parse_core_backup_list(
|
|||||||
core_backup_list_get_entry_crc_str(
|
core_backup_list_get_entry_crc_str(
|
||||||
entry, crc, sizeof(crc));
|
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 */
|
/* Add menu entry */
|
||||||
if (menu_entries_append_enum(info->list,
|
if (menu_entries_append_enum(info->list,
|
||||||
timestamp,
|
timestamp,
|
||||||
@ -7323,6 +7331,8 @@ unsigned menu_displaylist_build_list(
|
|||||||
{MENU_ENUM_LABEL_BUILDBOT_ASSETS_URL, PARSE_ONLY_STRING},
|
{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_AUTO_EXTRACT_ARCHIVE, PARSE_ONLY_BOOL},
|
||||||
{MENU_ENUM_LABEL_CORE_UPDATER_SHOW_EXPERIMENTAL_CORES, 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++)
|
for (i = 0; i < ARRAY_SIZE(build_list); i++)
|
||||||
|
@ -16162,6 +16162,38 @@ static bool setting_append_list(
|
|||||||
general_read_handler,
|
general_read_handler,
|
||||||
SD_FLAG_NONE
|
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
|
#endif
|
||||||
END_SUB_GROUP(list, list_info, parent_group);
|
END_SUB_GROUP(list, list_info, parent_group);
|
||||||
END_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_MANAGER_LIST),
|
||||||
MENU_LABEL(CORE_UPDATER_AUTO_EXTRACT_ARCHIVE),
|
MENU_LABEL(CORE_UPDATER_AUTO_EXTRACT_ARCHIVE),
|
||||||
MENU_LABEL(CORE_UPDATER_SHOW_EXPERIMENTAL_CORES),
|
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(CORE_UPDATER_BUILDBOT_URL),
|
||||||
MENU_LABEL(BUILDBOT_ASSETS_URL),
|
MENU_LABEL(BUILDBOT_ASSETS_URL),
|
||||||
MENU_LABEL(CORE_SET_SUPPORTS_NO_CONTENT_ENABLE),
|
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_RESTORE_BACKUP_ENTRY,
|
||||||
MENU_ENUM_LABEL_CORE_DELETE_BACKUP_ENTRY,
|
MENU_ENUM_LABEL_CORE_DELETE_BACKUP_ENTRY,
|
||||||
|
MENU_ENUM_LABEL_VALUE_CORE_BACKUP_MODE_AUTO,
|
||||||
MENU_ENUM_LABEL_VALUE_CORE_BACKUP_CRC,
|
MENU_ENUM_LABEL_VALUE_CORE_BACKUP_CRC,
|
||||||
|
|
||||||
MSG_CORE_BACKUP_SCANNING_CORE,
|
MSG_CORE_BACKUP_SCANNING_CORE,
|
||||||
MSG_CORE_BACKUP_ALREADY_EXISTS,
|
MSG_CORE_BACKUP_ALREADY_EXISTS,
|
||||||
MSG_BACKING_UP_CORE,
|
MSG_BACKING_UP_CORE,
|
||||||
|
MSG_PRUNING_CORE_BACKUP_HISTORY,
|
||||||
MSG_CORE_BACKUP_COMPLETE,
|
MSG_CORE_BACKUP_COMPLETE,
|
||||||
MSG_CORE_RESTORATION_ALREADY_INSTALLED,
|
MSG_CORE_RESTORATION_ALREADY_INSTALLED,
|
||||||
MSG_RESTORING_CORE,
|
MSG_RESTORING_CORE,
|
||||||
|
@ -44,6 +44,8 @@ enum core_backup_status
|
|||||||
CORE_BACKUP_CHECK_CRC,
|
CORE_BACKUP_CHECK_CRC,
|
||||||
CORE_BACKUP_PRE_ITERATE,
|
CORE_BACKUP_PRE_ITERATE,
|
||||||
CORE_BACKUP_ITERATE,
|
CORE_BACKUP_ITERATE,
|
||||||
|
CORE_BACKUP_CHECK_HISTORY,
|
||||||
|
CORE_BACKUP_PRUNE_HISTORY,
|
||||||
CORE_BACKUP_END,
|
CORE_BACKUP_END,
|
||||||
CORE_RESTORE_GET_CORE_CRC,
|
CORE_RESTORE_GET_CORE_CRC,
|
||||||
CORE_RESTORE_GET_BACKUP_CRC,
|
CORE_RESTORE_GET_BACKUP_CRC,
|
||||||
@ -61,6 +63,9 @@ typedef struct core_backup_handle
|
|||||||
char *backup_path;
|
char *backup_path;
|
||||||
enum core_backup_type backup_type;
|
enum core_backup_type backup_type;
|
||||||
enum core_backup_mode backup_mode;
|
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 core_file_size;
|
||||||
int64_t backup_file_size;
|
int64_t backup_file_size;
|
||||||
int64_t file_data_read;
|
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->backup_file = NULL;
|
||||||
|
|
||||||
backup_handle->success = true;
|
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;
|
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);
|
(backup_handle->file_data_read * 100) / backup_handle->core_file_size);
|
||||||
}
|
}
|
||||||
break;
|
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:
|
case CORE_BACKUP_END:
|
||||||
{
|
{
|
||||||
char task_title[PATH_MAX_LENGTH];
|
char task_title[PATH_MAX_LENGTH];
|
||||||
@ -409,14 +517,20 @@ task_finished:
|
|||||||
free_core_backup_handle(backup_handle);
|
free_core_backup_handle(backup_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note: If crc is set to 0, crc of core_path file will
|
/* Note 1: If crc is set to 0, crc of core_path file will
|
||||||
* be calculated automatically */
|
* be calculated automatically
|
||||||
void *task_push_core_backup(const char *core_path,
|
* 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,
|
uint32_t crc, enum core_backup_mode backup_mode,
|
||||||
|
size_t auto_backup_history_size,
|
||||||
const char *dir_core_assets, bool mute)
|
const char *dir_core_assets, bool mute)
|
||||||
{
|
{
|
||||||
task_finder_data_t find_data;
|
task_finder_data_t find_data;
|
||||||
core_info_ctx_find_t core_info;
|
|
||||||
const char *core_name = NULL;
|
const char *core_name = NULL;
|
||||||
retro_task_t *task = NULL;
|
retro_task_t *task = NULL;
|
||||||
core_backup_handle_t *backup_handle = NULL;
|
core_backup_handle_t *backup_handle = NULL;
|
||||||
@ -438,20 +552,27 @@ void *task_push_core_backup(const char *core_path,
|
|||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
/* Get core name */
|
/* Get core name */
|
||||||
core_info.inf = NULL;
|
if (!string_is_empty(core_display_name))
|
||||||
core_info.path = core_path;
|
core_name = core_display_name;
|
||||||
|
|
||||||
/* 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
|
else
|
||||||
{
|
{
|
||||||
/* If not, use core file name */
|
core_info_ctx_find_t core_info;
|
||||||
core_name = path_basename(core_path);
|
|
||||||
|
|
||||||
if (string_is_empty(core_name))
|
core_info.inf = NULL;
|
||||||
goto error;
|
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 */
|
/* Configure handle */
|
||||||
@ -460,23 +581,26 @@ void *task_push_core_backup(const char *core_path,
|
|||||||
if (!backup_handle)
|
if (!backup_handle)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
backup_handle->dir_core_assets = string_is_empty(dir_core_assets) ? NULL : strdup(dir_core_assets);
|
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_path = strdup(core_path);
|
||||||
backup_handle->core_name = strdup(core_name);
|
backup_handle->core_name = strdup(core_name);
|
||||||
backup_handle->backup_path = NULL;
|
backup_handle->backup_path = NULL;
|
||||||
backup_handle->backup_type = CORE_BACKUP_TYPE_ARCHIVE;
|
backup_handle->backup_type = CORE_BACKUP_TYPE_ARCHIVE;
|
||||||
backup_handle->backup_mode = backup_mode;
|
backup_handle->backup_mode = backup_mode;
|
||||||
backup_handle->core_file_size = 0;
|
backup_handle->auto_backup_history_size = auto_backup_history_size;
|
||||||
backup_handle->backup_file_size = 0;
|
backup_handle->num_auto_backups_to_remove = 0;
|
||||||
backup_handle->file_data_read = 0;
|
backup_handle->backup_index = 0;
|
||||||
backup_handle->core_crc = crc;
|
backup_handle->core_file_size = 0;
|
||||||
backup_handle->backup_crc = 0;
|
backup_handle->backup_file_size = 0;
|
||||||
backup_handle->crc_match = false;
|
backup_handle->file_data_read = 0;
|
||||||
backup_handle->success = false;
|
backup_handle->core_crc = crc;
|
||||||
backup_handle->core_file = NULL;
|
backup_handle->backup_crc = 0;
|
||||||
backup_handle->backup_file = NULL;
|
backup_handle->crc_match = false;
|
||||||
backup_handle->backup_list = NULL;
|
backup_handle->success = false;
|
||||||
backup_handle->status = CORE_BACKUP_BEGIN;
|
backup_handle->core_file = NULL;
|
||||||
|
backup_handle->backup_file = NULL;
|
||||||
|
backup_handle->backup_list = NULL;
|
||||||
|
backup_handle->status = CORE_BACKUP_BEGIN;
|
||||||
|
|
||||||
/* Create task */
|
/* Create task */
|
||||||
task = task_init();
|
task = task_init();
|
||||||
@ -899,23 +1023,26 @@ bool task_push_core_restore(const char *backup_path, const char *dir_libretro,
|
|||||||
if (!backup_handle)
|
if (!backup_handle)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
backup_handle->dir_core_assets = NULL;
|
backup_handle->dir_core_assets = NULL;
|
||||||
backup_handle->core_path = strdup(core_path);
|
backup_handle->core_path = strdup(core_path);
|
||||||
backup_handle->core_name = strdup(core_name);
|
backup_handle->core_name = strdup(core_name);
|
||||||
backup_handle->backup_path = strdup(backup_path);
|
backup_handle->backup_path = strdup(backup_path);
|
||||||
backup_handle->backup_type = backup_type;
|
backup_handle->backup_type = backup_type;
|
||||||
backup_handle->backup_mode = CORE_BACKUP_MODE_MANUAL;
|
backup_handle->backup_mode = CORE_BACKUP_MODE_MANUAL;
|
||||||
backup_handle->core_file_size = 0;
|
backup_handle->auto_backup_history_size = 0;
|
||||||
backup_handle->backup_file_size = 0;
|
backup_handle->num_auto_backups_to_remove = 0;
|
||||||
backup_handle->file_data_read = 0;
|
backup_handle->backup_index = 0;
|
||||||
backup_handle->core_crc = 0;
|
backup_handle->core_file_size = 0;
|
||||||
backup_handle->backup_crc = 0;
|
backup_handle->backup_file_size = 0;
|
||||||
backup_handle->crc_match = false;
|
backup_handle->file_data_read = 0;
|
||||||
backup_handle->success = false;
|
backup_handle->core_crc = 0;
|
||||||
backup_handle->core_file = NULL;
|
backup_handle->backup_crc = 0;
|
||||||
backup_handle->backup_file = NULL;
|
backup_handle->crc_match = false;
|
||||||
backup_handle->backup_list = NULL;
|
backup_handle->success = false;
|
||||||
backup_handle->status = CORE_RESTORE_GET_CORE_CRC;
|
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 */
|
/* Create task */
|
||||||
task = task_init();
|
task = task_init();
|
||||||
|
@ -66,6 +66,9 @@ typedef struct core_updater_list_handle
|
|||||||
enum core_updater_download_status
|
enum core_updater_download_status
|
||||||
{
|
{
|
||||||
CORE_UPDATER_DOWNLOAD_BEGIN = 0,
|
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_TRANSFER,
|
||||||
CORE_UPDATER_DOWNLOAD_WAIT_DECOMPRESS,
|
CORE_UPDATER_DOWNLOAD_WAIT_DECOMPRESS,
|
||||||
CORE_UPDATER_DOWNLOAD_END
|
CORE_UPDATER_DOWNLOAD_END
|
||||||
@ -73,14 +76,17 @@ enum core_updater_download_status
|
|||||||
|
|
||||||
typedef struct core_updater_download_handle
|
typedef struct core_updater_download_handle
|
||||||
{
|
{
|
||||||
|
bool auto_backup;
|
||||||
|
size_t auto_backup_history_size;
|
||||||
char *path_dir_libretro;
|
char *path_dir_libretro;
|
||||||
|
char *path_dir_core_assets;
|
||||||
char *remote_filename;
|
char *remote_filename;
|
||||||
char *remote_core_path;
|
char *remote_core_path;
|
||||||
char *local_download_path;
|
char *local_download_path;
|
||||||
char *local_core_path;
|
char *local_core_path;
|
||||||
char *display_name;
|
char *display_name;
|
||||||
|
uint32_t local_crc;
|
||||||
uint32_t remote_crc;
|
uint32_t remote_crc;
|
||||||
bool check_crc;
|
|
||||||
bool crc_match;
|
bool crc_match;
|
||||||
retro_task_t *http_task;
|
retro_task_t *http_task;
|
||||||
bool http_task_finished;
|
bool http_task_finished;
|
||||||
@ -88,6 +94,8 @@ typedef struct core_updater_download_handle
|
|||||||
retro_task_t *decompress_task;
|
retro_task_t *decompress_task;
|
||||||
bool decompress_task_finished;
|
bool decompress_task_finished;
|
||||||
bool decompress_task_complete;
|
bool decompress_task_complete;
|
||||||
|
bool backup_enabled;
|
||||||
|
retro_task_t *backup_task;
|
||||||
enum core_updater_download_status status;
|
enum core_updater_download_status status;
|
||||||
} core_updater_download_handle_t;
|
} core_updater_download_handle_t;
|
||||||
|
|
||||||
@ -104,7 +112,10 @@ enum update_installed_cores_status
|
|||||||
|
|
||||||
typedef struct update_installed_cores_handle
|
typedef struct update_installed_cores_handle
|
||||||
{
|
{
|
||||||
|
bool auto_backup;
|
||||||
|
size_t auto_backup_history_size;
|
||||||
char *path_dir_libretro;
|
char *path_dir_libretro;
|
||||||
|
char *path_dir_core_assets;
|
||||||
core_updater_list_t* core_list;
|
core_updater_list_t* core_list;
|
||||||
retro_task_t *list_task;
|
retro_task_t *list_task;
|
||||||
retro_task_t *download_task;
|
retro_task_t *download_task;
|
||||||
@ -119,40 +130,37 @@ typedef struct update_installed_cores_handle
|
|||||||
/* Utility functions */
|
/* Utility functions */
|
||||||
/*********************/
|
/*********************/
|
||||||
|
|
||||||
/* Returns true if local core has the same crc
|
/* Returns CRC32 of specified core file */
|
||||||
* value as core on buildbot */
|
static uint32_t task_core_updater_get_core_crc(const char *core_path)
|
||||||
static bool local_core_matches_remote_crc(
|
|
||||||
const char *local_core_path, uint32_t remote_crc)
|
|
||||||
{
|
{
|
||||||
/* Sanity check */
|
if (string_is_empty(core_path))
|
||||||
if (string_is_empty(local_core_path) || (remote_crc == 0))
|
return 0;
|
||||||
return false;
|
|
||||||
|
|
||||||
if (path_is_valid(local_core_path))
|
if (path_is_valid(core_path))
|
||||||
{
|
{
|
||||||
/* Open core file */
|
/* Open core file */
|
||||||
intfstream_t *local_core_file = intfstream_open_file(
|
intfstream_t *core_file = intfstream_open_file(
|
||||||
local_core_path, RETRO_VFS_FILE_ACCESS_READ,
|
core_path, RETRO_VFS_FILE_ACCESS_READ,
|
||||||
RETRO_VFS_FILE_ACCESS_HINT_NONE);
|
RETRO_VFS_FILE_ACCESS_HINT_NONE);
|
||||||
|
|
||||||
if (local_core_file)
|
if (core_file)
|
||||||
{
|
{
|
||||||
uint32_t crc = 0;
|
uint32_t crc = 0;
|
||||||
|
|
||||||
/* Get crc value */
|
/* Get crc value */
|
||||||
bool success = intfstream_get_crc(local_core_file, &crc);
|
bool success = intfstream_get_crc(core_file, &crc);
|
||||||
|
|
||||||
/* Close core file */
|
/* Close core file */
|
||||||
intfstream_close(local_core_file);
|
intfstream_close(core_file);
|
||||||
free(local_core_file);
|
free(core_file);
|
||||||
local_core_file = NULL;
|
core_file = NULL;
|
||||||
|
|
||||||
/* Check whether crc matches remote file */
|
if (success)
|
||||||
if (success && (crc != 0) && (crc == remote_crc))
|
return crc;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************************/
|
/*************************/
|
||||||
@ -184,7 +192,7 @@ finish:
|
|||||||
|
|
||||||
/* Log any error messages */
|
/* Log any error messages */
|
||||||
if (!success)
|
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"),
|
(transf ? transf->path: "unknown"),
|
||||||
(err ? err : "unknown"));
|
(err ? err : "unknown"));
|
||||||
|
|
||||||
@ -482,7 +490,7 @@ static void cb_decompress_task_core_updater_download(
|
|||||||
|
|
||||||
/* Log any error messages */
|
/* Log any error messages */
|
||||||
if (!string_is_empty(err))
|
if (!string_is_empty(err))
|
||||||
RARCH_ERR("%s", err);
|
RARCH_ERR("[core updater] %s", err);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cb_http_task_core_updater_download(
|
void cb_http_task_core_updater_download(
|
||||||
@ -576,7 +584,7 @@ finish:
|
|||||||
|
|
||||||
/* Log any error messages */
|
/* Log any error messages */
|
||||||
if (!string_is_empty(err))
|
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);
|
(transf ? transf->path: "unknown"), err);
|
||||||
|
|
||||||
if (data)
|
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)
|
if (download_handle->path_dir_libretro)
|
||||||
free(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)
|
if (download_handle->remote_filename)
|
||||||
free(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:
|
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 */
|
/* Check whether existing core and remote core
|
||||||
if (download_handle->check_crc)
|
* have the same CRC */
|
||||||
download_handle->crc_match = local_core_matches_remote_crc(
|
download_handle->crc_match = (download_handle->local_crc != 0) &&
|
||||||
download_handle->local_core_path,
|
(download_handle->local_crc == download_handle->remote_crc);
|
||||||
download_handle->remote_crc);
|
|
||||||
|
|
||||||
/* If CRC matches, end task immediately */
|
/* If CRC matches, end task immediately */
|
||||||
if (download_handle->crc_match)
|
if (download_handle->crc_match)
|
||||||
@ -651,6 +664,99 @@ static void task_core_updater_download_handler(retro_task_t *task)
|
|||||||
break;
|
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 */
|
/* Configure file transfer object */
|
||||||
transf = (file_transfer_t*)calloc(1, sizeof(file_transfer_t));
|
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,
|
download_handle->remote_core_path, true, NULL,
|
||||||
cb_http_task_core_updater_download, transf);
|
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 */
|
/* Update task title */
|
||||||
task_free_title(task);
|
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));
|
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
|
/* If HTTP task is NULL, then it either finished
|
||||||
* or an error occurred - in either case,
|
* or an error occurred - in either case,
|
||||||
* just move on to the next state */
|
* 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 */
|
* progress value to *this* task */
|
||||||
if (!download_handle->http_task_finished)
|
if (!download_handle->http_task_finished)
|
||||||
{
|
{
|
||||||
/* Download accounts for first half of
|
/* > If backups are enabled, download accounts
|
||||||
* task progress */
|
* 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);
|
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()
|
/* Wait for task_push_http_transfer_file()
|
||||||
* callback to trigger */
|
* callback to trigger */
|
||||||
if (download_handle->http_task_complete)
|
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;
|
download_handle->status = CORE_UPDATER_DOWNLOAD_WAIT_DECOMPRESS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CORE_UPDATER_DOWNLOAD_WAIT_DECOMPRESS:
|
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
|
/* If decompression task is NULL, then it either
|
||||||
* finished or an error occurred - in either case,
|
* finished or an error occurred - in either case,
|
||||||
* just move on to the next state */
|
* 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 */
|
* current progress value to *this* task */
|
||||||
if (!download_handle->decompress_task_finished)
|
if (!download_handle->decompress_task_finished)
|
||||||
{
|
{
|
||||||
/* Download accounts for second half
|
/* > If backups are enabled, decompression accounts
|
||||||
* of task progress */
|
* 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);
|
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(
|
void *task_push_core_updater_download(
|
||||||
core_updater_list_t* core_list,
|
core_updater_list_t* core_list,
|
||||||
const char *filename, bool mute, bool check_crc,
|
const char *filename, uint32_t crc, bool mute,
|
||||||
const char *path_dir_libretro)
|
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;
|
task_finder_data_t find_data;
|
||||||
char task_title[PATH_MAX_LENGTH];
|
char task_title[PATH_MAX_LENGTH];
|
||||||
@ -861,14 +982,17 @@ void *task_push_core_updater_download(
|
|||||||
sizeof(local_download_path));
|
sizeof(local_download_path));
|
||||||
|
|
||||||
/* Configure handle */
|
/* 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_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_filename = strdup(list_entry->remote_filename);
|
||||||
download_handle->remote_core_path = strdup(list_entry->remote_core_path);
|
download_handle->remote_core_path = strdup(list_entry->remote_core_path);
|
||||||
download_handle->local_download_path = strdup(local_download_path);
|
download_handle->local_download_path = strdup(local_download_path);
|
||||||
download_handle->local_core_path = strdup(list_entry->local_core_path);
|
download_handle->local_core_path = strdup(list_entry->local_core_path);
|
||||||
download_handle->display_name = strdup(list_entry->display_name);
|
download_handle->display_name = strdup(list_entry->display_name);
|
||||||
|
download_handle->local_crc = crc;
|
||||||
download_handle->remote_crc = list_entry->crc;
|
download_handle->remote_crc = list_entry->crc;
|
||||||
download_handle->check_crc = check_crc;
|
|
||||||
download_handle->crc_match = false;
|
download_handle->crc_match = false;
|
||||||
download_handle->http_task = NULL;
|
download_handle->http_task = NULL;
|
||||||
download_handle->http_task_finished = false;
|
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 = NULL;
|
||||||
download_handle->decompress_task_finished = false;
|
download_handle->decompress_task_finished = false;
|
||||||
download_handle->decompress_task_complete = false;
|
download_handle->decompress_task_complete = false;
|
||||||
|
download_handle->backup_enabled = false;
|
||||||
|
download_handle->backup_task = NULL;
|
||||||
download_handle->status = CORE_UPDATER_DOWNLOAD_BEGIN;
|
download_handle->status = CORE_UPDATER_DOWNLOAD_BEGIN;
|
||||||
|
|
||||||
/* Concurrent downloads of the same file are not allowed */
|
/* 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)
|
if (update_installed_handle->path_dir_libretro)
|
||||||
free(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);
|
core_updater_list_free(update_installed_handle->core_list);
|
||||||
|
|
||||||
free(update_installed_handle);
|
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:
|
case UPDATE_INSTALLED_CORES_UPDATE_CORE:
|
||||||
{
|
{
|
||||||
const core_updater_list_entry_t *list_entry = NULL;
|
const core_updater_list_entry_t *list_entry = NULL;
|
||||||
bool crc_match;
|
uint32_t local_crc;
|
||||||
|
|
||||||
/* Get list entry
|
/* Get list entry
|
||||||
* > In the event of an error, just return
|
* > In the event of an error, just return
|
||||||
@ -1077,15 +1206,16 @@ static void task_update_installed_cores_handler(retro_task_t *task)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check CRC of existing core */
|
/* Get CRC of existing core */
|
||||||
crc_match = local_core_matches_remote_crc(
|
local_crc = task_core_updater_get_core_crc(
|
||||||
list_entry->local_core_path,
|
list_entry->local_core_path);
|
||||||
list_entry->crc);
|
|
||||||
|
|
||||||
/* If CRC matches, then core is already the most
|
/* Check whether existing core and remote core
|
||||||
* recent version - just return to
|
* have the same CRC
|
||||||
* UPDATE_INSTALLED_CORES_ITERATE state */
|
* > If CRC matches, then core is already the most
|
||||||
if (crc_match)
|
* 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;
|
update_installed_handle->status = UPDATE_INSTALLED_CORES_ITERATE;
|
||||||
break;
|
break;
|
||||||
@ -1097,8 +1227,11 @@ static void task_update_installed_cores_handler(retro_task_t *task)
|
|||||||
task_push_core_updater_download(
|
task_push_core_updater_download(
|
||||||
update_installed_handle->core_list,
|
update_installed_handle->core_list,
|
||||||
list_entry->remote_filename,
|
list_entry->remote_filename,
|
||||||
true, false,
|
local_crc, true,
|
||||||
update_installed_handle->path_dir_libretro);
|
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
|
/* Again, if an error occurred, just return to
|
||||||
* UPDATE_INSTALLED_CORES_ITERATE state */
|
* 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;
|
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;
|
task_finder_data_t find_data;
|
||||||
retro_task_t *task = NULL;
|
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));
|
calloc(1, sizeof(update_installed_cores_handle_t));
|
||||||
|
|
||||||
/* Sanity check */
|
/* Sanity check */
|
||||||
if (!update_installed_handle)
|
if (!update_installed_handle ||
|
||||||
|
string_is_empty(path_dir_libretro))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
/* Configure handle */
|
/* Configure handle */
|
||||||
update_installed_handle->core_list = core_updater_list_init(
|
update_installed_handle->auto_backup = auto_backup;
|
||||||
CORE_UPDATER_LIST_SIZE);
|
update_installed_handle->auto_backup_history_size = auto_backup_history_size;
|
||||||
update_installed_handle->list_task = NULL;
|
update_installed_handle->path_dir_libretro = strdup(path_dir_libretro);
|
||||||
update_installed_handle->download_task = NULL;
|
update_installed_handle->path_dir_core_assets = string_is_empty(path_dir_core_assets) ?
|
||||||
update_installed_handle->list_size = 0;
|
NULL : strdup(path_dir_core_assets);
|
||||||
update_installed_handle->list_index = 0;
|
update_installed_handle->core_list = core_updater_list_init(CORE_UPDATER_LIST_SIZE);
|
||||||
update_installed_handle->installed_index = 0;
|
update_installed_handle->list_task = NULL;
|
||||||
update_installed_handle->num_updated = 0;
|
update_installed_handle->download_task = NULL;
|
||||||
update_installed_handle->path_dir_libretro = strdup(path_dir_libretro);
|
update_installed_handle->list_size = 0;
|
||||||
update_installed_handle->status = UPDATE_INSTALLED_CORES_BEGIN;
|
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)
|
if (!update_installed_handle->core_list)
|
||||||
goto error;
|
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);
|
bool task_push_netplay_nat_traversal(void *nat_traversal_state, uint16_t port);
|
||||||
|
|
||||||
/* Core updater tasks */
|
/* Core updater tasks */
|
||||||
|
|
||||||
void *task_push_get_core_updater_list(
|
void *task_push_get_core_updater_list(
|
||||||
core_updater_list_t* core_list, bool mute, bool refresh_menu);
|
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(
|
void *task_push_core_updater_download(
|
||||||
core_updater_list_t* core_list, const char *filename,
|
core_updater_list_t* core_list,
|
||||||
bool mute, bool check_crc, const char *path_dir_libretro);
|
const char *filename, uint32_t crc, bool mute,
|
||||||
void task_push_update_installed_cores(const char *path_dir_libretro);
|
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(
|
bool task_push_pl_entry_thumbnail_download(
|
||||||
const char *system,
|
const char *system,
|
||||||
@ -121,12 +129,18 @@ bool task_push_pl_thumbnail_download(
|
|||||||
|
|
||||||
/* Core backup/restore tasks */
|
/* Core backup/restore tasks */
|
||||||
|
|
||||||
/* Note: If crc is set to 0, crc of core_path file will
|
/* Note 1: If crc is set to 0, crc of core_path file will
|
||||||
* be calculated automatically */
|
* be calculated automatically
|
||||||
void *task_push_core_backup(const char *core_path,
|
* 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,
|
uint32_t crc, enum core_backup_mode backup_mode,
|
||||||
|
size_t auto_backup_history_size,
|
||||||
const char *dir_core_assets, bool mute);
|
const char *dir_core_assets, bool mute);
|
||||||
|
|
||||||
/* Note: If 'core_loaded' is true, menu stack should be
|
/* Note: If 'core_loaded' is true, menu stack should be
|
||||||
* flushed if task_push_core_restore() returns true */
|
* flushed if task_push_core_restore() returns true */
|
||||||
bool task_push_core_restore(const char *backup_path,
|
bool task_push_core_restore(const char *backup_path,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user