mirror of
https://github.com/libretro/RetroArch.git
synced 2024-11-23 16:09:47 +00:00
cdrom: add disc dump option
This commit is contained in:
parent
2ef16de941
commit
15d97dbaf3
@ -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")
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
@ -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),
|
||||
" ",
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user