diff --git a/libretro-common/cdrom/cdrom.c b/libretro-common/cdrom/cdrom.c index a26168b6c4..0d4ad7d6a4 100644 --- a/libretro-common/cdrom/cdrom.c +++ b/libretro-common/cdrom/cdrom.c @@ -34,16 +34,19 @@ #include #include #include +#include +#include +#include #include #include -#ifdef __linux__ +#if defined(__linux__) && !defined(ANDROID) #include #include #endif -#ifdef _WIN32 +#if defined(_WIN32) && !defined(_XBOX) #include #include #endif @@ -86,7 +89,7 @@ void increment_msf(unsigned char *min, unsigned char *sec, unsigned char *frame) *frame = (*frame < 74) ? (*frame + 1) : 0; } -#ifdef _WIN32 +#if defined(_WIN32) && !defined(_XBOX) static int cdrom_send_command_win32(HANDLE fh, CDROM_CMD_Direction dir, void *buf, size_t len, unsigned char *cmd, size_t cmd_len, unsigned char *sense, size_t sense_len) { DWORD ioctl_bytes; @@ -134,7 +137,7 @@ static int cdrom_send_command_win32(HANDLE fh, CDROM_CMD_Direction dir, void *bu } #endif -#ifdef __linux__ +#if defined(__linux__) && !defined(ANDROID) static int cdrom_send_command_linux(int fd, CDROM_CMD_Direction dir, void *buf, size_t len, unsigned char *cmd, size_t cmd_len, unsigned char *sense, size_t sense_len) { sg_io_hdr_t sgio = {0}; @@ -172,7 +175,7 @@ static int cdrom_send_command_linux(int fd, CDROM_CMD_Direction dir, void *buf, } #endif -static int cdrom_send_command(libretro_vfs_implementation_file *stream, CDROM_CMD_Direction dir, void *buf, size_t len, unsigned char *cmd, size_t cmd_len, size_t skip) +static int cdrom_send_command(const libretro_vfs_implementation_file *stream, CDROM_CMD_Direction dir, void *buf, size_t len, unsigned char *cmd, size_t cmd_len, size_t skip) { unsigned char *xfer_buf; unsigned char sense[CDROM_MAX_SENSE_BYTES] = {0}; @@ -204,10 +207,10 @@ static int cdrom_send_command(libretro_vfs_implementation_file *stream, CDROM_CM #endif retry: -#ifdef __linux__ +#if defined(__linux__) && !defined(ANDROID) if (!cdrom_send_command_linux(fileno(stream->fp), dir, xfer_buf, len + skip, cmd, cmd_len, sense, sizeof(sense))) #else -#ifdef _WIN32 +#if defined(_WIN32) && !defined(_XBOX) if (!cdrom_send_command_win32(stream->fh, dir, xfer_buf, len + skip, cmd, cmd_len, sense, sizeof(sense))) #endif #endif @@ -554,7 +557,7 @@ int cdrom_write_cue(libretro_vfs_implementation_file *stream, char **out_buf, si cdrom_read_track_info(stream, point, toc); -#ifdef _WIN32 +#if defined(_WIN32) && !defined(_XBOX) pos += snprintf(*out_buf + pos, len - pos, "FILE \"cdrom://%c://drive-track%02d.bin\" BINARY\n", cdrom_drive, point); #else pos += snprintf(*out_buf + pos, len - pos, "FILE \"cdrom://drive%c-track%02d.bin\" BINARY\n", cdrom_drive, point); @@ -585,7 +588,7 @@ int cdrom_write_cue(libretro_vfs_implementation_file *stream, char **out_buf, si } /* needs 32 bytes for full vendor, product and version */ -int cdrom_get_inquiry(libretro_vfs_implementation_file *stream, char *model, int len) +int cdrom_get_inquiry(const libretro_vfs_implementation_file *stream, char *model, int len, bool *is_cdrom) { /* MMC Command: INQUIRY */ unsigned char cdb[] = {0x12, 0, 0, 0, 0xff, 0}; @@ -613,6 +616,9 @@ int cdrom_get_inquiry(libretro_vfs_implementation_file *stream, char *model, int memcpy(model + 26, buf + 32, 4); } + if (is_cdrom && buf[0] == 5) + *is_cdrom = true; + return 0; } @@ -747,3 +753,61 @@ int cdrom_close_tray(libretro_vfs_implementation_file *stream) return 0; } +struct string_list* cdrom_get_available_drives(void) +{ + struct string_list *list = string_list_new(); + int drive_index = 0; + +#if defined(__linux__) && !defined(ANDROID) + struct string_list *dir_list = dir_list_new("/dev", NULL, false, false, false, false); + int i; + + if (!dir_list) + return list; + + for (i = 0; i < dir_list->size; i++) + { + if (strstr(dir_list->elems[i].data, "/dev/sg")) + { + char drive_model[32] = {0}; + char drive_string[64] = {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); + const libretro_vfs_implementation_file *stream; + bool is_cdrom = false; + + if (!file) + continue; + + stream = filestream_get_vfs_handle(file); + cdrom_get_inquiry(stream, drive_model, sizeof(drive_model), &is_cdrom); + filestream_close(file); + + if (!is_cdrom) + continue; + + sscanf(dir_list->elems[i].data + strlen("/dev/sg"), "%d", &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++; + } + } + + string_list_free(dir_list); +#else + string_list_append(list, "Drive 1", attr); +#endif + + return list; +} + diff --git a/libretro-common/include/cdrom/cdrom.h b/libretro-common/include/cdrom/cdrom.h index 6d0bdac18e..28c27a9090 100644 --- a/libretro-common/include/cdrom/cdrom.h +++ b/libretro-common/include/cdrom/cdrom.h @@ -40,6 +40,8 @@ typedef struct retro_vfs_file_handle libretro_vfs_implementation_file; typedef struct libretro_vfs_implementation_file libretro_vfs_implementation_file; #endif +struct string_list; + RETRO_BEGIN_DECLS typedef struct @@ -73,7 +75,7 @@ int cdrom_read_subq(libretro_vfs_implementation_file *stream, unsigned char *buf int cdrom_write_cue(libretro_vfs_implementation_file *stream, char **out_buf, size_t *out_len, char cdrom_drive, unsigned char *num_tracks, cdrom_toc_t *toc); /* needs 32 bytes for full vendor, product and version */ -int cdrom_get_inquiry(libretro_vfs_implementation_file *stream, char *model, int len); +int cdrom_get_inquiry(const libretro_vfs_implementation_file *stream, char *model, int len, bool *is_cdrom); int cdrom_read(libretro_vfs_implementation_file *stream, unsigned char min, unsigned char sec, unsigned char frame, void *s, size_t len, size_t skip); @@ -87,6 +89,9 @@ int cdrom_open_tray(libretro_vfs_implementation_file *stream); int cdrom_close_tray(libretro_vfs_implementation_file *stream); +/* must be freed by the caller */ +struct string_list* cdrom_get_available_drives(void); + RETRO_END_DECLS #endif diff --git a/libretro-common/lists/string_list.c b/libretro-common/lists/string_list.c index 36e6a2ddca..a9322807e3 100644 --- a/libretro-common/lists/string_list.c +++ b/libretro-common/lists/string_list.c @@ -53,7 +53,7 @@ void string_list_free(struct string_list *list) free(list->elems); } - list->elems = NULL; + list->elems = NULL; free(list); } diff --git a/libretro-common/vfs/vfs_implementation.c b/libretro-common/vfs/vfs_implementation.c index 18dc470676..10e29bab53 100644 --- a/libretro-common/vfs/vfs_implementation.c +++ b/libretro-common/vfs/vfs_implementation.c @@ -410,7 +410,7 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl( if (stream->scheme == VFS_SCHEME_CDROM) { retro_vfs_file_open_cdrom(stream, path, mode, hints); -#ifdef _WIN32 +#if defined(_WIN32) && !defined(_XBOX) if (!stream->fh) goto error; #else diff --git a/libretro-common/vfs/vfs_implementation_cdrom.c b/libretro-common/vfs/vfs_implementation_cdrom.c index 3cea268800..bba5116f9c 100644 --- a/libretro-common/vfs/vfs_implementation_cdrom.c +++ b/libretro-common/vfs/vfs_implementation_cdrom.c @@ -26,7 +26,7 @@ #include #include -#ifdef _WIN32 +#if defined(_WIN32) && !defined(_XBOX) #include #endif @@ -127,7 +127,7 @@ void retro_vfs_file_open_cdrom( libretro_vfs_implementation_file *stream, const char *path, unsigned mode, unsigned hints) { -#ifdef __linux__ +#if defined(__linux__) && !defined(ANDROID) char model[32] = {0}; char cdrom_path[] = "/dev/sg1"; size_t path_len = strlen(path); @@ -176,7 +176,7 @@ void retro_vfs_file_open_cdrom( if (stream->fp) { - if (!cdrom_get_inquiry(stream, model, sizeof(model))) + if (!cdrom_get_inquiry(stream, model, sizeof(model), NULL)) { #ifdef CDROM_DEBUG printf("CDROM Model: %s\n", model); @@ -211,7 +211,7 @@ void retro_vfs_file_open_cdrom( #endif } #endif -#ifdef _WIN32 +#if defined(_WIN32) && !defined(_XBOX) char model[32] = {0}; char cdrom_path[] = "\\\\.\\D:"; size_t path_len = strlen(path); @@ -313,7 +313,7 @@ int retro_vfs_file_close_cdrom(libretro_vfs_implementation_file *stream) fflush(stdout); #endif -#ifdef _WIN32 +#if defined(_WIN32) && !defined(_XBOX) if (!stream->fh || !CloseHandle(stream->fh)) return -1; #else diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index 183f27fe44..93f778c7b2 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -60,6 +60,10 @@ #include "../frontend/drivers/platform_unix.h" #endif +#ifdef HAVE_CDROM +#include +#endif + #include "menu_cbs.h" #include "menu_content.h" #include "menu_driver.h" @@ -4890,23 +4894,40 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, switch (type) { +#ifdef HAVE_CDROM case DISPLAYLIST_DUMP_DISC: + { + int i; + struct string_list *list = cdrom_get_available_drives(); + menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list); count = 0; - - /* TODO/FIXME - remove 'count = 0;' and implement disk list */ - if (count == 0) + for (i = 0; list && i < list->size; i++) + { + menu_entries_append_enum(info->list, + list->elems[i].data, + "", + 0, + MENU_SET_CDROM_LIST, + 0, i); + } + + if (list->size == 0) menu_entries_append_enum(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY), msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY), MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY, FILE_TYPE_NONE, 0, 0); + string_list_free(list); + info->need_push = true; info->need_refresh = true; info->need_clear = true; break; + } +#endif #if defined(HAVE_LAKKA_SWITCH) || defined(HAVE_LIBNX) case DISPLAYLIST_SWITCH_CPU_PROFILE: { diff --git a/menu/menu_driver.h b/menu/menu_driver.h index cbd2261858..f8067980d1 100644 --- a/menu/menu_driver.h +++ b/menu/menu_driver.h @@ -194,6 +194,8 @@ enum menu_settings_type MENU_SET_SWITCH_CPU_PROFILE, #endif + MENU_SET_CDROM_LIST, + MENU_SETTINGS_LAST };