diff --git a/libretro-common/cdrom/cdrom.c b/libretro-common/cdrom/cdrom.c index 23dfa89b3b..55fa67368f 100644 --- a/libretro-common/cdrom/cdrom.c +++ b/libretro-common/cdrom/cdrom.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #ifdef _WIN32 @@ -253,10 +254,20 @@ static void cdrom_print_sense_data(const unsigned char *sense, size_t len) } #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) +static int cdrom_send_command_win32(const libretro_vfs_implementation_file *stream, 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; BOOL ioctl_rv; +#ifdef CDROM_DEBUG + clock_t t = clock(); + const char *extra = " "; + static unsigned char last_min = 0; + static unsigned char last_sec = 0; + static unsigned char last_frame = 0; + + unsigned lba_cur = cdrom_msf_to_lba(last_min, last_sec, last_frame); + unsigned lba_req = cdrom_msf_to_lba(cmd[3], cmd[4], cmd[5]); +#endif struct sptd_with_sense { SCSI_PASS_THROUGH_DIRECT s; @@ -290,9 +301,28 @@ static int cdrom_send_command_win32(HANDLE fh, CDROM_CMD_Direction dir, void *bu memcpy(sptd.s.Cdb, cmd, cmd_len); - ioctl_rv = DeviceIoControl(fh, IOCTL_SCSI_PASS_THROUGH_DIRECT, &sptd, + ioctl_rv = DeviceIoControl(stream->fh, IOCTL_SCSI_PASS_THROUGH_DIRECT, &sptd, sizeof(sptd), &sptd, sizeof(sptd), &ioctl_bytes, NULL); +#ifdef CDROM_DEBUG + if (lba_req < lba_cur) + extra = " BACKWARDS SECTOR READ"; + else if (lba_req > lba_cur) + extra = " SKIPPED SECTOR READ"; + + if (cmd[0] == 0xB9) + { + double time_taken = (double)(((clock() - t) * 1000) / CLOCKS_PER_SEC); + printf("time taken %f ms for DT received length %ld of %" PRId64 " for %02d:%02d:%02d to %02d:%02d:%02d%s req %d cur %d cur_lba %d\n", time_taken, sptd.s.DataTransferLength, len, cmd[3], cmd[4], cmd[5], cmd[6], cmd[7], cmd[8], extra, lba_req, lba_cur, stream->cdrom.cur_lba); + fflush(stdout); + } + + last_min = cmd[3]; + last_sec = cmd[4]; + last_frame = cmd[5]; + increment_msf(&last_min, &last_sec, &last_frame); +#endif + if (!ioctl_rv || sptd.s.ScsiStatus != 0) return 1; @@ -301,7 +331,7 @@ static int cdrom_send_command_win32(HANDLE fh, CDROM_CMD_Direction dir, void *bu #endif #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) +static int cdrom_send_command_linux(const libretro_vfs_implementation_file *stream, 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}; int rv; @@ -329,7 +359,7 @@ static int cdrom_send_command_linux(int fd, CDROM_CMD_Direction dir, void *buf, sgio.mx_sb_len = sense_len; sgio.timeout = 5000; - rv = ioctl(fd, SG_IO, &sgio); + rv = ioctl(fileno(stream->fp), SG_IO, &sgio); if (rv == -1 || sgio.info & SG_INFO_CHECK) return 1; @@ -338,108 +368,203 @@ static int cdrom_send_command_linux(int fd, CDROM_CMD_Direction dir, void *buf, } #endif -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) +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) { - unsigned char *xfer_buf; + unsigned char *xfer_buf = NULL; + unsigned char *xfer_buf_pos = xfer_buf; unsigned char sense[CDROM_MAX_SENSE_BYTES] = {0}; unsigned char retries_left = CDROM_MAX_RETRIES; - int rv = 0; + int i, rv = 0; + int frames = 1; size_t padded_req_bytes; + size_t copied_bytes = 0; + bool read_cd = false; if (!cmd || cmd_len == 0) return 1; if (cmd[0] == 0xBE || cmd[0] == 0xB9) - padded_req_bytes = 2352 * ceil((len + skip) / 2352.0); + { + frames = ceil((len + skip) / 2352.0); + padded_req_bytes = 2352 * frames; + read_cd = true; + /* these will be incremented below */ + cmd[6] = cmd[3]; + cmd[7] = cmd[4]; + cmd[8] = cmd[5]; + } else + { padded_req_bytes = len + skip; + } - xfer_buf = (unsigned char*)calloc(1, padded_req_bytes); + xfer_buf = (unsigned char*)memalign_alloc(4096, padded_req_bytes); + xfer_buf_pos = xfer_buf; if (!xfer_buf) return 1; + memset(xfer_buf, 0, padded_req_bytes); #ifdef CDROM_DEBUG + printf("Number of frames to read: %d\n", frames); + fflush(stdout); +#endif + for (i = 0; i < frames; i++) { - unsigned i; + size_t request_len = padded_req_bytes; + size_t copy_len = request_len; + bool cached_read = false; - printf("[CDROM] Send Command: "); - - for (i = 0; i < cmd_len / sizeof(*cmd); i++) + if (read_cd) { - printf("%02X ", cmd[i]); + unsigned lba_req = 0; + + request_len = 2352; + copy_len = request_len; + + increment_msf(&cmd[6], &cmd[7], &cmd[8]); + + if (i > 0) + { + skip = 0; + increment_msf(&cmd[3], &cmd[4], &cmd[5]); + } + else + { + if (skip) + copy_len -= skip; + } + + if (i == frames - 1) + { + copy_len = len - copied_bytes; + } + + lba_req = cdrom_msf_to_lba(cmd[3], cmd[4], cmd[5]); + + if (stream->cdrom.last_frame_valid && lba_req == stream->cdrom.last_frame_lba) + { + /* use cached frame */ + cached_read = true; +#ifdef CDROM_DEBUG + printf("[CDROM] Using cached frame\n"); + fflush(stdout); +#endif + /* assumes request_len is always equal to the size of last_frame */ + memcpy(xfer_buf_pos, stream->cdrom.last_frame, sizeof(stream->cdrom.last_frame)); + } + } - if (len) - printf("(buffer of size %" PRId64 " with skip bytes %" PRId64 " padded to %" PRId64 ")\n", len, skip, padded_req_bytes); - else - printf("\n"); +#ifdef CDROM_DEBUG + if (!cached_read) + { + unsigned j; - fflush(stdout); - } + printf("[CDROM] Send Command: "); + + for (j = 0; j < cmd_len / sizeof(*cmd); j++) + { + printf("%02X ", cmd[j]); + } + + if (len) + printf("(buffer of size %" PRId64 " with skip bytes %" PRId64 " padded to %" PRId64 "), frame %d\n", len, skip, padded_req_bytes, i); + else + printf("\n"); + + fflush(stdout); + } #endif retry: #if defined(__linux__) && !defined(ANDROID) - if (!cdrom_send_command_linux(fileno(stream->fp), dir, xfer_buf, padded_req_bytes, cmd, cmd_len, sense, sizeof(sense))) + if (cached_read || !cdrom_send_command_linux(stream, dir, xfer_buf_pos, request_len, cmd, cmd_len, sense, sizeof(sense))) #else #if defined(_WIN32) && !defined(_XBOX) - if (!cdrom_send_command_win32(stream->fh, dir, xfer_buf, padded_req_bytes, cmd, cmd_len, sense, sizeof(sense))) + if (cached_read || !cdrom_send_command_win32(stream, dir, xfer_buf_pos, request_len, cmd, cmd_len, sense, sizeof(sense))) #endif #endif - { - rv = 0; - - if (buf) - memcpy(buf, xfer_buf + skip, len); - } - else - { - cdrom_print_sense_data(sense, sizeof(sense)); - - /* INQUIRY/TEST/SENSE should never fail, don't retry. */ - /* READ ATIP seems to fail outright on some drives (BW-16D1HT) with pressed discs, skip retries. */ - if (cmd[0] != 0x0 && cmd[0] != 0x12 && cmd[0] != 0x5A && !(cmd[0] == 0x43 && cmd[2] == 0x4)) { - unsigned char key = sense[2] & 0xF; + rv = 0; - switch (key) + if (buf) { - case 0: - case 2: - case 3: - case 4: - case 6: - if (retries_left) - { -#ifdef CDROM_DEBUG - printf("[CDROM] Read Retry...\n"); - fflush(stdout); +#if 0 + printf("offsetting %" PRId64 " from buf, copying at xfer_buf offset %" PRId64 ", copying %" PRId64 " bytes\n", copied_bytes, (xfer_buf_pos + skip) - xfer_buf, copy_len); + fflush(stdout); #endif - retries_left--; - retro_sleep(1000); - goto retry; - } - else - { - rv = 1; -#ifdef CDROM_DEBUG - printf("[CDROM] Read retries failed, giving up.\n"); - fflush(stdout); -#endif - } + memcpy((char*)buf + copied_bytes, xfer_buf_pos + skip, copy_len); + copied_bytes += copy_len; - break; - default: - break; + if (read_cd && !cached_read && request_len >= 2352) + { + unsigned frame_end = cdrom_msf_to_lba(cmd[6], cmd[7], cmd[8]); + + /* cache the last received frame */ + memcpy(stream->cdrom.last_frame, xfer_buf_pos, sizeof(stream->cdrom.last_frame)); + stream->cdrom.last_frame_valid = true; + /* the ending frame is never actually read, so what we really just read is the one right before that */ + stream->cdrom.last_frame_lba = frame_end - 1; + } + else + stream->cdrom.last_frame_valid = false; + +#if 0 + printf("Frame %d, adding %" PRId64 " to buf_pos, is now %" PRId64 ". skip is %" PRId64 "\n", i, request_len, (xfer_buf_pos + request_len) - xfer_buf, skip); + fflush(stdout); +#endif + xfer_buf_pos += request_len; } } + else + { + cdrom_print_sense_data(sense, sizeof(sense)); - rv = 1; + /* INQUIRY/TEST/SENSE should never fail, don't retry. */ + /* READ ATIP seems to fail outright on some drives with pressed discs, skip retries. */ + if (cmd[0] != 0x0 && cmd[0] != 0x12 && cmd[0] != 0x5A && !(cmd[0] == 0x43 && cmd[2] == 0x4)) + { + unsigned char key = sense[2] & 0xF; + + switch (key) + { + case 0: + case 2: + case 3: + case 4: + case 6: + if (retries_left) + { + #ifdef CDROM_DEBUG + printf("[CDROM] Read Retry...\n"); + fflush(stdout); + #endif + retries_left--; + retro_sleep(1000); + goto retry; + } + else + { + rv = 1; + #ifdef CDROM_DEBUG + printf("[CDROM] Read retries failed, giving up.\n"); + fflush(stdout); + #endif + } + + break; + default: + break; + } + } + + rv = 1; + } } if (xfer_buf) - free(xfer_buf); + memalign_free(xfer_buf); return rv; } @@ -533,7 +658,7 @@ static const char* get_profile(unsigned short profile) return "Unknown"; } -int cdrom_get_sense(const libretro_vfs_implementation_file *stream, unsigned char *sense, size_t len) +int cdrom_get_sense(libretro_vfs_implementation_file *stream, unsigned char *sense, size_t len) { unsigned char cdb[] = {0x3, 0, 0, 0, 0xFC, 0}; unsigned char buf[0xFC] = {0}; @@ -552,7 +677,7 @@ int cdrom_get_sense(const libretro_vfs_implementation_file *stream, unsigned cha return 0; } -void cdrom_get_current_config_random_readable(const libretro_vfs_implementation_file *stream) +void cdrom_get_current_config_random_readable(libretro_vfs_implementation_file *stream) { unsigned char cdb[] = {0x46, 0x2, 0, 0x10, 0, 0, 0, 0, 0x14, 0}; unsigned char buf[0x14] = {0}; @@ -585,7 +710,7 @@ void cdrom_get_current_config_random_readable(const libretro_vfs_implementation_ printf("[CDROM] Supported commands: READ CAPACITY, READ (10)\n"); } -void cdrom_get_current_config_multiread(const libretro_vfs_implementation_file *stream) +void cdrom_get_current_config_multiread(libretro_vfs_implementation_file *stream) { unsigned char cdb[] = {0x46, 0x2, 0, 0x1D, 0, 0, 0, 0, 0xC, 0}; unsigned char buf[0xC] = {0}; @@ -618,7 +743,7 @@ void cdrom_get_current_config_multiread(const libretro_vfs_implementation_file * printf("[CDROM] Supported commands: READ (10), READ CD, READ DISC INFORMATION, READ TRACK INFORMATION\n"); } -void cdrom_get_current_config_cdread(const libretro_vfs_implementation_file *stream) +void cdrom_get_current_config_cdread(libretro_vfs_implementation_file *stream) { unsigned char cdb[] = {0x46, 0x2, 0, 0x1E, 0, 0, 0, 0, 0x10, 0}; unsigned char buf[0x10] = {0}; @@ -652,7 +777,7 @@ void cdrom_get_current_config_cdread(const libretro_vfs_implementation_file *str printf("[CDROM] Supported commands: READ CD, READ CD MSF, READ TOC/PMA/ATIP\n"); } -void cdrom_get_current_config_profiles(const libretro_vfs_implementation_file *stream) +void cdrom_get_current_config_profiles(libretro_vfs_implementation_file *stream) { unsigned char cdb[] = {0x46, 0x2, 0, 0x0, 0, 0, 0, 0xFF, 0xFA, 0}; unsigned char buf[0xFFFA] = {0}; @@ -697,7 +822,7 @@ void cdrom_get_current_config_profiles(const libretro_vfs_implementation_file *s } } -void cdrom_get_current_config_core(const libretro_vfs_implementation_file *stream) +void cdrom_get_current_config_core(libretro_vfs_implementation_file *stream) { unsigned char cdb[] = {0x46, 0x2, 0, 0x1, 0, 0, 0, 0, 0x14, 0}; unsigned char buf[20] = {0}; @@ -1026,7 +1151,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(const libretro_vfs_implementation_file *stream, char *model, int len, bool *is_cdrom) +int cdrom_get_inquiry(libretro_vfs_implementation_file *stream, char *model, int len, bool *is_cdrom) { /* MMC Command: INQUIRY */ unsigned char cdb[] = {0x12, 0, 0, 0, 0xff, 0}; @@ -1071,46 +1196,32 @@ int cdrom_read(libretro_vfs_implementation_file *stream, cdrom_group_timeouts_t /* MMC Command: READ CD MSF */ unsigned char cdb[] = {0xB9, 0, 0, 0, 0, 0, 0, 0, 0, 0xF8, 0, 0}; int rv; + double frames = ceil((len + skip) / 2352.0); + unsigned frame_end = cdrom_msf_to_lba(min, sec, frame) + frames; cdb[3] = min; cdb[4] = sec; cdb[5] = frame; - if (len + skip <= 2352) + if (frames <= 1) { - unsigned char next_min = (frame == 74) ? (sec < 59 ? min : min + 1) : min; - unsigned char next_sec = (frame == 74) ? (sec < 59 ? (sec + 1) : 0) : sec; - unsigned char next_frame = (frame < 74) ? (frame + 1) : 0; - - cdb[6] = next_min; - cdb[7] = next_sec; - cdb[8] = next_frame; - + cdrom_lba_to_msf(frame_end, &cdb[6], &cdb[7], &cdb[8]); #ifdef CDROM_DEBUG - printf("[CDROM] single-frame read: from %d %d %d to %d %d %d skip %" PRId64 "\n", cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], cdb[8], skip); + printf("[CDROM] single-frame read: %d %d %d skip %" PRId64 "\n", cdb[3], cdb[4], cdb[5], skip); fflush(stdout); #endif } else { - double frames = (len + skip) / 2352.0; - unsigned frame_end = cdrom_msf_to_lba(min, sec, frame) + ceil(frames); - - if (timeouts->g1_timeout && (frames / 75) > timeouts->g1_timeout) - { - printf("[CDROM] multi-frame read of %d seconds is longer than group 1 timeout of %d seconds\n", (int)frames, timeouts->g1_timeout); - fflush(stdout); - return 1; - } - cdrom_lba_to_msf(frame_end, &cdb[6], &cdb[7], &cdb[8]); #ifdef CDROM_DEBUG - printf("[CDROM] multi-frame read: from %d %d %d to %d %d %d skip %" PRId64 "\n", cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], cdb[8], skip); + printf("[CDROM] multi-frame read: %d sectors starting from %02d:%02d:%02d skip %" PRId64 "\n", (int)frames, cdb[3], cdb[4], cdb[5], skip); fflush(stdout); #endif } + /* regardless of the length specified here, a new buffer will be allocated and padded to a sector multiple inside cdrom_send_command */ rv = cdrom_send_command(stream, DIRECTION_IN, s, len, cdb, sizeof(cdb), skip); #ifdef CDROM_DEBUG @@ -1119,61 +1230,15 @@ int cdrom_read(libretro_vfs_implementation_file *stream, cdrom_group_timeouts_t #endif if (rv) + { + stream->cdrom.last_frame_valid = false; return 1; + } return 0; } -int cdrom_read_lba(libretro_vfs_implementation_file *stream, unsigned lba, void *s, size_t len, size_t skip) -{ - /* MMC Command: READ CD */ - unsigned char cdb[] = {0xBE, 0, 0, 0, 0, 0, 0, 0, 0, 0xF8, 0, 0}; - unsigned lba_orig = lba; - int rv; - - cdb[2] = (lba >> 24) & 0xFF; - cdb[3] = (lba >> 16) & 0xFF; - cdb[4] = (lba >> 8) & 0xFF; - cdb[5] = (lba >> 0) & 0xFF; - - if (len + skip <= 2352) - { - cdb[8] = 1; - -#ifdef CDROM_DEBUG - printf("[CDROM] single-frame read: from %d count %d skip %" PRId64 "\n", lba_orig, 1, skip); - fflush(stdout); -#endif - } - else - { - unsigned frames = lba_orig + ceil((len + skip) / 2352.0); - unsigned lba_count = frames - lba_orig; - - cdb[6] = (lba_count >> 16) & 0xFF; - cdb[7] = (lba_count >> 8) & 0xFF; - cdb[8] = (lba_count >> 0) & 0xFF; - -#ifdef CDROM_DEBUG - printf("[CDROM] multi-frame read: from %d to %d len %d skip %" PRId64 "\n", lba_orig, frames, frames - lba_orig, skip); - fflush(stdout); -#endif - } - - rv = cdrom_send_command(stream, DIRECTION_IN, s, len, cdb, sizeof(cdb), skip); - -#ifdef CDROM_DEBUG - printf("[CDROM] read status code %d\n", rv); - fflush(stdout); -#endif - - if (rv) - return 1; - - return 0; -} - -int cdrom_stop(const libretro_vfs_implementation_file *stream) +int cdrom_stop(libretro_vfs_implementation_file *stream) { /* MMC Command: START STOP UNIT */ unsigned char cdb[] = {0x1B, 0, 0, 0, 0x0, 0}; @@ -1190,7 +1255,7 @@ int cdrom_stop(const libretro_vfs_implementation_file *stream) return 0; } -int cdrom_unlock(const libretro_vfs_implementation_file *stream) +int cdrom_unlock(libretro_vfs_implementation_file *stream) { /* MMC Command: PREVENT ALLOW MEDIUM REMOVAL */ unsigned char cdb[] = {0x1E, 0, 0, 0, 0x2, 0}; @@ -1219,7 +1284,7 @@ int cdrom_unlock(const libretro_vfs_implementation_file *stream) return 0; } -int cdrom_open_tray(const libretro_vfs_implementation_file *stream) +int cdrom_open_tray(libretro_vfs_implementation_file *stream) { /* MMC Command: START STOP UNIT */ unsigned char cdb[] = {0x1B, 0, 0, 0, 0x2, 0}; @@ -1241,7 +1306,7 @@ int cdrom_open_tray(const libretro_vfs_implementation_file *stream) return 0; } -int cdrom_close_tray(const libretro_vfs_implementation_file *stream) +int cdrom_close_tray(libretro_vfs_implementation_file *stream) { /* MMC Command: START STOP UNIT */ unsigned char cdb[] = {0x1B, 0, 0, 0, 0x3, 0}; @@ -1277,7 +1342,7 @@ struct string_list* cdrom_get_available_drives(void) 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; + libretro_vfs_implementation_file *stream; bool is_cdrom = false; if (!file) @@ -1309,7 +1374,6 @@ struct string_list* cdrom_get_available_drives(void) #if defined(_WIN32) && !defined(_XBOX) DWORD drive_mask = GetLogicalDrives(); int i; - int drive_index = 0; for (i = 0; i < sizeof(DWORD) * 8; i++) { @@ -1331,7 +1395,7 @@ struct string_list* cdrom_get_available_drives(void) char drive_string[33] = {0}; union string_list_elem_attr attr = {0}; RFILE *file = filestream_open(cdrom_path, RETRO_VFS_FILE_ACCESS_READ, 0); - const libretro_vfs_implementation_file *stream; + libretro_vfs_implementation_file *stream; bool is_cdrom = false; if (!file) @@ -1358,7 +1422,7 @@ struct string_list* cdrom_get_available_drives(void) return list; } -bool cdrom_is_media_inserted(const libretro_vfs_implementation_file *stream) +bool cdrom_is_media_inserted(libretro_vfs_implementation_file *stream) { /* MMC Command: TEST UNIT READY */ unsigned char cdb[] = {0x00, 0, 0, 0, 0, 0}; @@ -1390,7 +1454,7 @@ bool cdrom_drive_has_media(const char drive) if (file) { - const libretro_vfs_implementation_file *stream = filestream_get_vfs_handle(file); + libretro_vfs_implementation_file *stream = filestream_get_vfs_handle(file); bool has_media = false; has_media = cdrom_is_media_inserted(stream); @@ -1403,7 +1467,7 @@ bool cdrom_drive_has_media(const char drive) return false; } -bool cdrom_set_read_cache(const libretro_vfs_implementation_file *stream, bool enabled) +bool cdrom_set_read_cache(libretro_vfs_implementation_file *stream, bool enabled) { /* MMC Command: MODE SENSE (10) and MODE SELECT (10) */ unsigned char cdb_sense_changeable[] = {0x5A, 0, 0x48, 0, 0, 0, 0, 0, 0x14, 0}; @@ -1533,7 +1597,7 @@ bool cdrom_get_timeouts(libretro_vfs_implementation_file *stream, cdrom_group_ti return true; } -bool cdrom_has_atip(const libretro_vfs_implementation_file *stream) +bool cdrom_has_atip(libretro_vfs_implementation_file *stream) { /* MMC Command: READ TOC/PMA/ATIP */ unsigned char cdb[] = {0x43, 0x2, 0x4, 0, 0, 0, 0, 0x9, 0x30, 0}; diff --git a/libretro-common/include/cdrom/cdrom.h b/libretro-common/include/cdrom/cdrom.h index 0cf7f804a2..d455602fa7 100644 --- a/libretro-common/include/cdrom/cdrom.h +++ b/libretro-common/include/cdrom/cdrom.h @@ -79,46 +79,44 @@ 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(const libretro_vfs_implementation_file *stream, char *model, int len, bool *is_cdrom); +int cdrom_get_inquiry(libretro_vfs_implementation_file *stream, char *model, int len, bool *is_cdrom); int cdrom_read(libretro_vfs_implementation_file *stream, cdrom_group_timeouts_t *timeouts, unsigned char min, unsigned char sec, unsigned char frame, void *s, size_t len, size_t skip); -int cdrom_read_lba(libretro_vfs_implementation_file *stream, unsigned lba, void *s, size_t len, size_t skip); - int cdrom_set_read_speed(libretro_vfs_implementation_file *stream, unsigned speed); -int cdrom_stop(const libretro_vfs_implementation_file *stream); +int cdrom_stop(libretro_vfs_implementation_file *stream); -int cdrom_unlock(const libretro_vfs_implementation_file *stream); +int cdrom_unlock(libretro_vfs_implementation_file *stream); -int cdrom_open_tray(const libretro_vfs_implementation_file *stream); +int cdrom_open_tray(libretro_vfs_implementation_file *stream); -int cdrom_close_tray(const 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); -bool cdrom_is_media_inserted(const libretro_vfs_implementation_file *stream); +bool cdrom_is_media_inserted(libretro_vfs_implementation_file *stream); bool cdrom_drive_has_media(const char drive); -void cdrom_get_current_config_core(const libretro_vfs_implementation_file *stream); +void cdrom_get_current_config_core(libretro_vfs_implementation_file *stream); -void cdrom_get_current_config_profiles(const libretro_vfs_implementation_file *stream); +void cdrom_get_current_config_profiles(libretro_vfs_implementation_file *stream); -void cdrom_get_current_config_cdread(const libretro_vfs_implementation_file *stream); +void cdrom_get_current_config_cdread(libretro_vfs_implementation_file *stream); -void cdrom_get_current_config_multiread(const libretro_vfs_implementation_file *stream); +void cdrom_get_current_config_multiread(libretro_vfs_implementation_file *stream); -void cdrom_get_current_config_random_readable(const libretro_vfs_implementation_file *stream); +void cdrom_get_current_config_random_readable(libretro_vfs_implementation_file *stream); -int cdrom_get_sense(const libretro_vfs_implementation_file *stream, unsigned char *sense, size_t len); +int cdrom_get_sense(libretro_vfs_implementation_file *stream, unsigned char *sense, size_t len); -bool cdrom_set_read_cache(const libretro_vfs_implementation_file *stream, bool enabled); +bool cdrom_set_read_cache(libretro_vfs_implementation_file *stream, bool enabled); bool cdrom_get_timeouts(libretro_vfs_implementation_file *stream, cdrom_group_timeouts_t *timeouts); -bool cdrom_has_atip(const libretro_vfs_implementation_file *stream); +bool cdrom_has_atip(libretro_vfs_implementation_file *stream); void cdrom_device_fillpath(char *path, size_t len, char drive, unsigned char track, bool is_cue); diff --git a/libretro-common/include/streams/file_stream.h b/libretro-common/include/streams/file_stream.h index c25dfe78b5..063983a4a1 100644 --- a/libretro-common/include/streams/file_stream.h +++ b/libretro-common/include/streams/file_stream.h @@ -107,7 +107,7 @@ bool filestream_exists(const char *path); char *filestream_getline(RFILE *stream); -const libretro_vfs_implementation_file* filestream_get_vfs_handle(RFILE *stream); +libretro_vfs_implementation_file* filestream_get_vfs_handle(RFILE *stream); RETRO_END_DECLS diff --git a/libretro-common/include/vfs/vfs.h b/libretro-common/include/vfs/vfs.h index 5f046fec6e..b876f438b6 100644 --- a/libretro-common/include/vfs/vfs.h +++ b/libretro-common/include/vfs/vfs.h @@ -24,6 +24,7 @@ #define __LIBRETRO_SDK_VFS_H #include +#include #ifdef RARCH_INTERNAL #ifndef VFS_FRONTEND @@ -49,6 +50,9 @@ typedef struct unsigned char cur_frame; unsigned char cur_track; unsigned cur_lba; + unsigned last_frame_lba; + unsigned char last_frame[2352]; + bool last_frame_valid; } vfs_cdrom_t; #endif diff --git a/libretro-common/streams/file_stream.c b/libretro-common/streams/file_stream.c index 1579c15068..4d537cda43 100644 --- a/libretro-common/streams/file_stream.c +++ b/libretro-common/streams/file_stream.c @@ -613,7 +613,7 @@ char *filestream_getline(RFILE *stream) return newline; } -const libretro_vfs_implementation_file* filestream_get_vfs_handle(RFILE *stream) +libretro_vfs_implementation_file* filestream_get_vfs_handle(RFILE *stream) { - return (const libretro_vfs_implementation_file*)stream->hfile; + return (libretro_vfs_implementation_file*)stream->hfile; } diff --git a/tasks/task_content.c b/tasks/task_content.c index b6b6b3ffdf..ca53d4ffe1 100644 --- a/tasks/task_content.c +++ b/tasks/task_content.c @@ -131,7 +131,7 @@ typedef struct { RFILE *file; RFILE *output_file; - const libretro_vfs_implementation_file *stream; + libretro_vfs_implementation_file *stream; const cdrom_toc_t *toc; char cdrom_path[64]; char drive_letter[2];