diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index 151f93dcf1..2de7564b4c 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -8939,3 +8939,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_XMB_ANIMATION_OPENING_MAIN_MENU, "Animation Main Menu Opens/Closes") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_GPU_INDEX, "GPU Index") +MSG_HASH(MSG_DUMPING_DISC, + "Dumping disc...") +MSG_HASH(MSG_DRIVE_NUMBER, + "Drive %d") diff --git a/libretro-common/cdrom/cdrom.c b/libretro-common/cdrom/cdrom.c index 61e4c0473e..db9e542446 100644 --- a/libretro-common/cdrom/cdrom.c +++ b/libretro-common/cdrom/cdrom.c @@ -835,6 +835,7 @@ static int cdrom_read_track_info(libretro_vfs_implementation_file *stream, unsig unsigned lba = 0; unsigned track_size = 0; int rv = cdrom_send_command(stream, DIRECTION_IN, buf, sizeof(buf), cdb, sizeof(cdb), 0); + ssize_t pregap_lba_len; if (rv) return 1; @@ -848,6 +849,10 @@ static int cdrom_read_track_info(libretro_vfs_implementation_file *stream, unsig /* lba_start may be earlier than the MSF start times seen in read_subq */ toc->track[track - 1].lba_start = lba; toc->track[track - 1].track_size = track_size; + + pregap_lba_len = (toc->track[track - 1].audio ? 0 : (toc->track[track - 1].lba - toc->track[track - 1].lba_start)); + + toc->track[track - 1].track_bytes = (track_size - pregap_lba_len) * 2352; toc->track[track - 1].mode = buf[6] & 0xF; #ifdef CDROM_DEBUG @@ -1239,7 +1244,6 @@ struct string_list* cdrom_get_available_drives(void) struct string_list *list = string_list_new(); #if defined(__linux__) && !defined(ANDROID) struct string_list *dir_list = dir_list_new("/dev", NULL, false, false, false, false); - int drive_index = 0; int i; if (!dir_list) @@ -1250,7 +1254,7 @@ struct string_list* cdrom_get_available_drives(void) if (strstr(dir_list->elems[i].data, "/dev/sg")) { char drive_model[32] = {0}; - char drive_string[64] = {0}; + char drive_string[32] = {0}; union string_list_elem_attr attr = {0}; int dev_index = 0; RFILE *file = filestream_open(dir_list->elems[i].data, RETRO_VFS_FILE_ACCESS_READ, 0); @@ -1272,15 +1276,12 @@ struct string_list* cdrom_get_available_drives(void) dev_index = '0' + dev_index; attr.i = dev_index; - snprintf(drive_string, sizeof(drive_string), "Drive %d: ", drive_index + 1); - if (!string_is_empty(drive_model)) strlcat(drive_string, drive_model, sizeof(drive_string)); else strlcat(drive_string, "Unknown Drive", sizeof(drive_string)); string_list_append(list, drive_string, attr); - drive_index++; } } @@ -1326,15 +1327,12 @@ struct string_list* cdrom_get_available_drives(void) attr.i = path[0]; - snprintf(drive_string, sizeof(drive_string), "Drive %d: ", drive_index + 1); - if (!string_is_empty(drive_model)) strlcat(drive_string, drive_model, sizeof(drive_string)); else strlcat(drive_string, "Unknown Drive", sizeof(drive_string)); string_list_append(list, drive_string, attr); - drive_index++; } } #endif @@ -1507,3 +1505,52 @@ bool cdrom_has_atip(const libretro_vfs_implementation_file *stream) return true; } + +void cdrom_device_fillpath(char *path, size_t len, char drive, unsigned char track, bool is_cue) +{ + size_t pos = 0; + + if (!path || len == 0) + return; + + if (is_cue) + { +#ifdef _WIN32 + pos = strlcpy(path, "cdrom://", len); + + if (len > pos) + path[pos++] = drive; + + pos = strlcat(path, ":/drive.cue", len); +#else +#ifdef __linux__ + pos = strlcpy(path, "cdrom://drive", len); + + if (len > pos) + path[pos++] = drive; + + pos = strlcat(path, ".cue", len); +#endif +#endif + } + else + { +#ifdef _WIN32 + pos = strlcpy(path, "cdrom://", len); + + if (len > pos) + path[pos++] = drive; + + pos += snprintf(path + pos, len - pos, ":/drive-track%02d.bin", track); +#else +#ifdef __linux__ + pos = strlcpy(path, "cdrom://drive", len); + + if (len > pos) + path[pos++] = drive; + + pos += snprintf(path + pos, len - pos, "-track%02d.bin", track); +#endif +#endif + } +} diff --git a/libretro-common/file/file_path.c b/libretro-common/file/file_path.c index bae812756d..9b85d76855 100644 --- a/libretro-common/file/file_path.c +++ b/libretro-common/file/file_path.c @@ -629,11 +629,20 @@ void fill_str_dated_filename(char *out_filename, const struct tm* tm_ = localtime(&cur_time); format[0] = '\0'; - strftime(format, sizeof(format), "-%y%m%d-%H%M%S.", tm_); - fill_pathname_join_concat_noext(out_filename, - in_str, format, ext, - size); + if (string_is_empty(ext)) + { + strftime(format, sizeof(format), "-%y%m%d-%H%M%S", tm_); + fill_pathname_noext(out_filename, in_str, format, size); + } + else + { + strftime(format, sizeof(format), "-%y%m%d-%H%M%S.", tm_); + + fill_pathname_join_concat_noext(out_filename, + in_str, format, ext, + size); + } } /** @@ -885,8 +894,7 @@ void fill_pathname_join_special_ext(char *out_path, strlcat(out_path, ext, size); } -void fill_pathname_join_concat_noext( - char *out_path, +void fill_pathname_join_concat_noext(char *out_path, const char *dir, const char *path, const char *concat, size_t size) diff --git a/libretro-common/include/cdrom/cdrom.h b/libretro-common/include/cdrom/cdrom.h index 78abec532e..cc25db7623 100644 --- a/libretro-common/include/cdrom/cdrom.h +++ b/libretro-common/include/cdrom/cdrom.h @@ -50,7 +50,8 @@ typedef struct { unsigned lba_start; /* start of pregap */ unsigned lba; /* start of data */ - unsigned track_size; + unsigned track_size; /* in LBAs */ + unsigned track_bytes; unsigned char track_num; unsigned char min; /* start of data */ unsigned char sec; @@ -117,6 +118,8 @@ bool cdrom_get_timeouts(libretro_vfs_implementation_file *stream, cdrom_group_ti bool cdrom_has_atip(const libretro_vfs_implementation_file *stream); +void cdrom_device_fillpath(char *path, size_t len, char drive, unsigned char track, bool is_cue); + RETRO_END_DECLS #endif diff --git a/libretro-common/include/file/file_path.h b/libretro-common/include/file/file_path.h index 0dcb7c1c80..31b3ce8aef 100644 --- a/libretro-common/include/file/file_path.h +++ b/libretro-common/include/file/file_path.h @@ -376,8 +376,7 @@ void fill_pathname_join_special_ext(char *out_path, const char *last, const char *ext, size_t size); -void fill_pathname_join_concat_noext( - char *out_path, +void fill_pathname_join_concat_noext(char *out_path, const char *dir, const char *path, const char *concat, size_t size); diff --git a/libretro-common/vfs/vfs_implementation_cdrom.c b/libretro-common/vfs/vfs_implementation_cdrom.c index 347db2fc31..7bb0e5c1a2 100644 --- a/libretro-common/vfs/vfs_implementation_cdrom.c +++ b/libretro-common/vfs/vfs_implementation_cdrom.c @@ -369,6 +369,12 @@ int64_t retro_vfs_file_read_cdrom(libretro_vfs_implementation_file *stream, unsigned char rsec = 0; unsigned char rframe = 0; + if (stream->cdrom.byte_pos >= vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].track_bytes) + return 0; + + if (stream->cdrom.byte_pos + len > vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].track_bytes) + len -= (stream->cdrom.byte_pos + len) - vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].track_bytes; + cdrom_lba_to_msf(stream->cdrom.cur_lba, &min, &sec, &frame); cdrom_lba_to_msf(stream->cdrom.cur_lba - vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba, &rmin, &rsec, &rframe); diff --git a/menu/cbs/menu_cbs_ok.c b/menu/cbs/menu_cbs_ok.c index 143b2c8719..f76e287133 100644 --- a/menu/cbs/menu_cbs_ok.c +++ b/menu/cbs/menu_cbs_ok.c @@ -2141,7 +2141,11 @@ static int action_ok_load_cdrom(const char *path, static int action_ok_dump_cdrom(const char *path, const char *label, unsigned type, size_t idx, size_t entry_idx) { - /* TODO/FIXME - implement */ + if (string_is_empty(label)) + return -1; +#ifdef HAVE_CDROM + task_push_cdrom_dump(label); +#endif return 0; } diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index 6d429e71c3..e46393153e 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -168,7 +168,7 @@ static int menu_displaylist_parse_core_info(menu_displaylist_info_t *info) if (!info_list[i].name) continue; - fill_pathname_join_concat_noext(tmp, + fill_pathname_join_concat(tmp, msg_hash_to_str(info_list[i].msg), ": ", info_list[i].name, @@ -345,7 +345,7 @@ static unsigned menu_displaylist_parse_system_info(menu_displaylist_info_t *info (void)tmp_string; #ifdef HAVE_GIT_VERSION - fill_pathname_join_concat_noext( + fill_pathname_join_concat( tmp, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_GIT_VERSION), ": ", @@ -493,7 +493,7 @@ static unsigned menu_displaylist_parse_system_info(menu_displaylist_info_t *info tmp2[0] = '\0'; - fill_pathname_join_concat_noext( + fill_pathname_join_concat( tmp, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_FRONTEND_IDENTIFIER), ": ", @@ -509,7 +509,7 @@ static unsigned menu_displaylist_parse_system_info(menu_displaylist_info_t *info { frontend->get_lakka_version(tmp2, sizeof(tmp2)); - fill_pathname_join_concat_noext(tmp, + fill_pathname_join_concat(tmp, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_LAKKA_VERSION), ": ", tmp2, @@ -525,7 +525,7 @@ static unsigned menu_displaylist_parse_system_info(menu_displaylist_info_t *info { frontend->get_name(tmp2, sizeof(tmp2)); - fill_pathname_join_concat_noext(tmp, + fill_pathname_join_concat(tmp, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_FRONTEND_NAME), ": ", tmp2, @@ -661,7 +661,7 @@ static unsigned menu_displaylist_parse_system_info(menu_displaylist_info_t *info break; } - fill_pathname_join_concat_noext(tmp, + fill_pathname_join_concat(tmp, msg_hash_to_str( MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_POWER_SOURCE), ": ", @@ -678,7 +678,7 @@ static unsigned menu_displaylist_parse_system_info(menu_displaylist_info_t *info video_context_driver_get_ident(&ident_info); tmp_string = ident_info.ident; - fill_pathname_join_concat_noext(tmp, + fill_pathname_join_concat(tmp, msg_hash_to_str( MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_VIDEO_CONTEXT_DRIVER), ": ", @@ -809,7 +809,7 @@ static unsigned menu_displaylist_parse_system_info(menu_displaylist_info_t *info for (i = 0; i < ARRAY_SIZE(info_list); i++) { - fill_pathname_join_concat_noext(feat_str, + fill_pathname_join_concat(feat_str, msg_hash_to_str( info_list[i].msg), ": ", @@ -987,7 +987,7 @@ static int create_string_list_rdb_entry_string( string_list_join_concat(output_label, str_len, str_list, "|"); string_list_free(str_list); - fill_pathname_join_concat_noext(tmp, desc, ": ", + fill_pathname_join_concat(tmp, desc, ": ", actual_string, path_size); menu_entries_append_enum(list, tmp, output_label, enum_idx, @@ -1181,7 +1181,7 @@ static int menu_displaylist_parse_database_entry(menu_handle_t *menu, if (db_info_entry->name) { - fill_pathname_join_concat_noext(tmp, + fill_pathname_join_concat(tmp, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_NAME), ": ", db_info_entry->name, @@ -1193,7 +1193,7 @@ static int menu_displaylist_parse_database_entry(menu_handle_t *menu, } if (db_info_entry->description) { - fill_pathname_join_concat_noext(tmp, + fill_pathname_join_concat(tmp, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_DESCRIPTION), ": ", db_info_entry->description, @@ -1205,7 +1205,7 @@ static int menu_displaylist_parse_database_entry(menu_handle_t *menu, } if (db_info_entry->genre) { - fill_pathname_join_concat_noext(tmp, + fill_pathname_join_concat(tmp, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_GENRE), ": ", db_info_entry->genre, @@ -4906,9 +4906,18 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, for (i = 0; list && i < list->size; i++) { + char drive_string[32] = {0}; + char drive[2] = {0}; + size_t pos = 0; + + drive[0] = list->elems[i].attr.i; + + pos += snprintf(drive_string + pos, sizeof(drive_string) - pos, msg_hash_to_str(MSG_DRIVE_NUMBER), i + 1); + pos += snprintf(drive_string + pos, sizeof(drive_string) - pos, ": %s", list->elems[i].data); + menu_entries_append_enum(info->list, - list->elems[i].data, - "", + drive_string, + drive, 0, MENU_SET_CDROM_LIST, 0, i); diff --git a/msg_hash.h b/msg_hash.h index ce4cd8f982..2d89df82fe 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -2435,6 +2435,9 @@ enum msg_hash_enums MENU_LABEL(ENABLE_DEVICE_VIBRATION), MENU_LABEL(VIDEO_GPU_INDEX), + MSG_DUMPING_DISC, + MSG_DRIVE_NUMBER, + MSG_LAST }; diff --git a/retroarch.c b/retroarch.c index 66ade31ff8..df61e7145a 100644 --- a/retroarch.c +++ b/retroarch.c @@ -10328,7 +10328,7 @@ void video_driver_set_title_buf(void) struct retro_system_info info; core_get_system_info(&info); - fill_pathname_join_concat_noext( + fill_pathname_join_concat( video_driver_title_buf, msg_hash_to_str(MSG_PROGRAM), " ", diff --git a/tasks/task_content.c b/tasks/task_content.c index 5c87463491..8d4f933a48 100644 --- a/tasks/task_content.c +++ b/tasks/task_content.c @@ -66,6 +66,9 @@ #ifdef HAVE_MENU #include "../menu/menu_driver.h" +#ifdef HAVE_MENU_WIDGETS +#include "../../menu/widgets/menu_widgets.h" +#endif #endif #include "../menu/menu_shader.h" @@ -108,6 +111,34 @@ extern bool discord_is_inited; typedef struct content_stream content_stream_t; typedef struct content_information_ctx content_information_ctx_t; +#ifdef HAVE_CDROM +enum cdrom_dump_state +{ + DUMP_STATE_TOC_PENDING, + DUMP_STATE_WRITE_CUE, + DUMP_STATE_NEXT_TRACK, + DUMP_STATE_READ_TRACK +}; + +typedef struct +{ + RFILE *file; + RFILE *output_file; + const libretro_vfs_implementation_file *stream; + const cdrom_toc_t *toc; + char cdrom_path[64]; + char drive_letter[2]; + char title[512]; + unsigned char cur_track; + int64_t cur_track_bytes; + int64_t track_written_bytes; + int64_t disc_total_bytes; + int64_t disc_read_bytes; + bool next; + enum cdrom_dump_state state; +} task_cdrom_dump_state_t; +#endif + struct content_stream { uint32_t a; @@ -166,6 +197,301 @@ static char pending_subsystem_extensions[PATH_MAX_LENGTH]; #endif static char *pending_subsystem_roms[RARCH_MAX_SUBSYSTEM_ROMS]; +#ifdef HAVE_CDROM +static void task_cdrom_dump_handler(retro_task_t *task) +{ + task_cdrom_dump_state_t *state = (task_cdrom_dump_state_t*)task->state; + + if (task_get_progress(task) == 100) + { + if (state->file) + { + filestream_close(state->file); + state->file = NULL; + } + if (state->output_file) + { + filestream_close(state->output_file); + state->file = NULL; + } + + task_set_finished(task, true); + + RARCH_LOG("[CDROM] Dump finished.\n"); + + return; + } + + switch (state->state) + { + case DUMP_STATE_TOC_PENDING: + { + /* open cuesheet file from drive */ + char cue_path[PATH_MAX_LENGTH]; + + cue_path[0] = '\0'; + + cdrom_device_fillpath(cue_path, sizeof(cue_path), state->drive_letter[0], 0, true); + + state->file = filestream_open(cue_path, RETRO_VFS_FILE_ACCESS_READ, 0); + + if (!state->file) + { + RARCH_ERR("[CDROM]: Error opening file for reading: %s\n", cue_path); + task_set_progress(task, 100); + task_free_title(task); + task_set_title(task, strdup(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_FILE_READ_OPEN_FAILED))); + return; + } + + state->state = DUMP_STATE_WRITE_CUE; + + break; + } + case DUMP_STATE_WRITE_CUE: + { + /* write cuesheet to a file */ + int64_t cue_size = filestream_get_size(state->file); + char *cue_data = (char*)calloc(1, cue_size); + settings_t *settings = config_get_ptr(); + char output_file[PATH_MAX_LENGTH]; + char cue_filename[PATH_MAX_LENGTH]; + + output_file[0] = cue_filename[0] = '\0'; + + filestream_read(state->file, cue_data, cue_size); + + state->stream = filestream_get_vfs_handle(state->file); + state->toc = retro_vfs_file_get_cdrom_toc(); + + if (cdrom_has_atip(state->stream)) + RARCH_LOG("[CDROM] This disc is not genuine.\n"); + + filestream_close(state->file); + + output_file[0] = cue_filename[0] = '\0'; + + snprintf(cue_filename, sizeof(cue_filename), "%s.cue", state->title); + + fill_pathname_join(output_file, settings->paths.directory_core_assets, + cue_filename, sizeof(output_file)); + + { + RFILE *file = filestream_open(output_file, RETRO_VFS_FILE_ACCESS_WRITE, 0); + unsigned char point = 0; + + if (!file) + { + RARCH_ERR("[CDROM]: Error opening file for writing: %s\n", output_file); + task_set_progress(task, 100); + task_free_title(task); + task_set_title(task, strdup(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_FILE_WRITE_OPEN_FAILED))); + return; + } + + for (point = 1; point <= state->toc->num_tracks; point++) + { + const char *track_type = "MODE1/2352"; + char track_filename[PATH_MAX_LENGTH]; + + state->disc_total_bytes += state->toc->track[point - 1].track_bytes; + + track_filename[0] = '\0'; + + if (state->toc->track[point - 1].audio) + track_type = "AUDIO"; + else if (state->toc->track[point - 1].mode == 1) + track_type = "MODE1/2352"; + else if (state->toc->track[point - 1].mode == 2) + track_type = "MODE2/2352"; + + snprintf(track_filename, sizeof(track_filename), "%s (Track %02d).bin", state->title, point); + + filestream_printf(file, "FILE \"%s\" BINARY\n", track_filename); + filestream_printf(file, " TRACK %02d %s\n", point, track_type); + + { + unsigned pregap_lba_len = state->toc->track[point - 1].lba - state->toc->track[point - 1].lba_start; + + if (state->toc->track[point - 1].audio && pregap_lba_len > 0) + { + unsigned char min = 0; + unsigned char sec = 0; + unsigned char frame = 0; + + cdrom_lba_to_msf(pregap_lba_len, &min, &sec, &frame); + + filestream_printf(file, " INDEX 00 00:00:00\n"); + filestream_printf(file, " INDEX 01 %02u:%02u:%02u\n", (unsigned)min, (unsigned)sec, (unsigned)frame); + } + else + filestream_printf(file, " INDEX 01 00:00:00\n"); + } + } + + filestream_close(file); + } + + state->file = NULL; + state->state = DUMP_STATE_NEXT_TRACK; + + free(cue_data); + + return; + } + case DUMP_STATE_NEXT_TRACK: + { + /* no file is open as we either just started or just finished a track, need to start dumping the next track */ + state->cur_track++; + + /* no more tracks to dump, we're done */ + if (state->toc && state->cur_track > state->toc->num_tracks) + { + task_set_progress(task, 100); + return; + } + + RARCH_LOG("[CDROM] Dumping track %d...\n", state->cur_track); + + memset(state->cdrom_path, 0, sizeof(state->cdrom_path)); + + cdrom_device_fillpath(state->cdrom_path, sizeof(state->cdrom_path), state->drive_letter[0], state->cur_track, false); + + state->track_written_bytes = 0; + state->file = filestream_open(state->cdrom_path, RETRO_VFS_FILE_ACCESS_READ, 0); + + /* open a new file for writing for this next track */ + if (state->file) + { + settings_t *settings = config_get_ptr(); + char output_path[PATH_MAX_LENGTH]; + char track_filename[PATH_MAX_LENGTH]; + + output_path[0] = track_filename[0] = '\0'; + + snprintf(track_filename, sizeof(track_filename), "%s (Track %02d).bin", state->title, state->cur_track); + + state->cur_track_bytes = filestream_get_size(state->file); + + fill_pathname_join(output_path, settings->paths.directory_core_assets, + track_filename, sizeof(output_path)); + + state->output_file = filestream_open(output_path, RETRO_VFS_FILE_ACCESS_WRITE, 0); + + if (!state->output_file) + { + RARCH_ERR("[CDROM]: Error opening file for writing: %s\n", output_path); + task_set_progress(task, 100); + task_free_title(task); + task_set_title(task, strdup(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_FILE_WRITE_OPEN_FAILED))); + return; + } + } + else + { + RARCH_ERR("[CDROM]: Error opening file for writing: %s\n", state->cdrom_path); + task_set_progress(task, 100); + task_free_title(task); + task_set_title(task, strdup(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_FILE_WRITE_OPEN_FAILED))); + return; + } + + state->state = DUMP_STATE_READ_TRACK; + return; + } + case DUMP_STATE_READ_TRACK: + { + /* read data from track and write it to a file in chunks */ + if (state->cur_track_bytes > state->track_written_bytes) + { + char data[2352 * 2] = {0}; + int64_t read_bytes = filestream_read(state->file, data, sizeof(data)); + int progress = 0; + + if (read_bytes <= 0) + { + task_set_progress(task, 100); + task_free_title(task); + task_set_title(task, strdup("Failed to read from drive. Dump aborted.")); + return; + } + + state->track_written_bytes += read_bytes; + state->disc_read_bytes += read_bytes; + progress = (state->disc_read_bytes / (double)state->disc_total_bytes) * 100.0; + +#ifdef CDROM_DEBUG + RARCH_LOG("[CDROM] Read %" PRId64 " bytes, totalling %" PRId64 " of %" PRId64 " bytes. Progress: %d%%\n", read_bytes, state->track_written_bytes, state->cur_track_bytes, progress); +#endif + + if (filestream_write(state->output_file, data, read_bytes) <= 0) + { + task_set_progress(task, 100); + task_free_title(task); + task_set_title(task, strdup("Failed to write to disk. Dump aborted.")); + return; + } + + task_set_progress(task, progress); + + return; + } + else if (state->cur_track_bytes == state->track_written_bytes) + { + /* TODO: FIXME: this stops after only the first track */ + if (state->file) + { + filestream_close(state->file); + state->file = NULL; + } + if (state->output_file) + { + filestream_close(state->output_file); + state->file = NULL; + } + + state->state = DUMP_STATE_NEXT_TRACK; + return; + } + + break; + } + } +} + +static void task_cdrom_dump_callback(retro_task_t *task, + void *task_data, + void *user_data, const char *error) +{ + task_cdrom_dump_state_t *state = (task_cdrom_dump_state_t*)task->state; + + if (state) + free(state); +} + +void task_push_cdrom_dump(const char *drive) +{ + retro_task_t *task = task_init(); + task_cdrom_dump_state_t *state = (task_cdrom_dump_state_t*)calloc(1, sizeof(*state)); + + state->drive_letter[0] = drive[0]; + state->next = true; + state->cur_track = 0; + state->state = DUMP_STATE_TOC_PENDING; + + fill_str_dated_filename(state->title, "cdrom", NULL, sizeof(state->title)); + + task->state = state; + task->handler = task_cdrom_dump_handler; + task->callback = task_cdrom_dump_callback; + task->title = strdup(msg_hash_to_str(MSG_DUMPING_DISC)); + + RARCH_LOG("[CDROM] Starting disc dump...\n"); + + task_queue_push(task); +} +#endif + static int64_t content_file_read(const char *path, void **buf, int64_t *length) { #ifdef HAVE_COMPRESSION diff --git a/tasks/task_screenshot.c b/tasks/task_screenshot.c index 59f10fbe61..931802c30e 100644 --- a/tasks/task_screenshot.c +++ b/tasks/task_screenshot.c @@ -310,7 +310,7 @@ static bool screenshot_dump( if (use_thread) { - retro_task_t *task= task_init(); + retro_task_t *task = task_init(); task->type = TASK_TYPE_BLOCKING; task->state = state; diff --git a/tasks/tasks_internal.h b/tasks/tasks_internal.h index 1de890b9c9..f4ae943036 100644 --- a/tasks/tasks_internal.h +++ b/tasks/tasks_internal.h @@ -150,6 +150,10 @@ void input_autoconfigure_joypad_reindex_devices(void); void set_save_state_in_background(bool state); +#ifdef HAVE_CDROM +void task_push_cdrom_dump(const char *drive); +#endif + extern const char* const input_builtin_autoconfs[]; RETRO_END_DECLS