mirror of
https://github.com/libretro/RetroArch.git
synced 2024-11-27 10:10:57 +00:00
cdrom: always request one sector at a time
This commit is contained in:
parent
cba3eb3968
commit
41b3adc8a4
@ -38,6 +38,7 @@
|
|||||||
#include <lists/string_list.h>
|
#include <lists/string_list.h>
|
||||||
#include <lists/dir_list.h>
|
#include <lists/dir_list.h>
|
||||||
#include <string/stdstring.h>
|
#include <string/stdstring.h>
|
||||||
|
#include <memalign.h>
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@ -253,10 +254,20 @@ static void cdrom_print_sense_data(const unsigned char *sense, size_t len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(_WIN32) && !defined(_XBOX)
|
#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;
|
DWORD ioctl_bytes;
|
||||||
BOOL ioctl_rv;
|
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
|
struct sptd_with_sense
|
||||||
{
|
{
|
||||||
SCSI_PASS_THROUGH_DIRECT s;
|
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);
|
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);
|
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)
|
if (!ioctl_rv || sptd.s.ScsiStatus != 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
@ -301,7 +331,7 @@ static int cdrom_send_command_win32(HANDLE fh, CDROM_CMD_Direction dir, void *bu
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__linux__) && !defined(ANDROID)
|
#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};
|
sg_io_hdr_t sgio = {0};
|
||||||
int rv;
|
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.mx_sb_len = sense_len;
|
||||||
sgio.timeout = 5000;
|
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)
|
if (rv == -1 || sgio.info & SG_INFO_CHECK)
|
||||||
return 1;
|
return 1;
|
||||||
@ -338,108 +368,203 @@ static int cdrom_send_command_linux(int fd, CDROM_CMD_Direction dir, void *buf,
|
|||||||
}
|
}
|
||||||
#endif
|
#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 sense[CDROM_MAX_SENSE_BYTES] = {0};
|
||||||
unsigned char retries_left = CDROM_MAX_RETRIES;
|
unsigned char retries_left = CDROM_MAX_RETRIES;
|
||||||
int rv = 0;
|
int i, rv = 0;
|
||||||
|
int frames = 1;
|
||||||
size_t padded_req_bytes;
|
size_t padded_req_bytes;
|
||||||
|
size_t copied_bytes = 0;
|
||||||
|
bool read_cd = false;
|
||||||
|
|
||||||
if (!cmd || cmd_len == 0)
|
if (!cmd || cmd_len == 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (cmd[0] == 0xBE || cmd[0] == 0xB9)
|
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
|
else
|
||||||
|
{
|
||||||
padded_req_bytes = len + skip;
|
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)
|
if (!xfer_buf)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
memset(xfer_buf, 0, padded_req_bytes);
|
||||||
#ifdef CDROM_DEBUG
|
#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: ");
|
if (read_cd)
|
||||||
|
|
||||||
for (i = 0; i < cmd_len / sizeof(*cmd); i++)
|
|
||||||
{
|
{
|
||||||
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)
|
#ifdef CDROM_DEBUG
|
||||||
printf("(buffer of size %" PRId64 " with skip bytes %" PRId64 " padded to %" PRId64 ")\n", len, skip, padded_req_bytes);
|
if (!cached_read)
|
||||||
else
|
{
|
||||||
printf("\n");
|
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
|
#endif
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
#if defined(__linux__) && !defined(ANDROID)
|
#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
|
#else
|
||||||
#if defined(_WIN32) && !defined(_XBOX)
|
#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
|
||||||
#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:
|
#if 0
|
||||||
case 2:
|
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);
|
||||||
case 3:
|
fflush(stdout);
|
||||||
case 4:
|
|
||||||
case 6:
|
|
||||||
if (retries_left)
|
|
||||||
{
|
|
||||||
#ifdef CDROM_DEBUG
|
|
||||||
printf("[CDROM] Read Retry...\n");
|
|
||||||
fflush(stdout);
|
|
||||||
#endif
|
#endif
|
||||||
retries_left--;
|
memcpy((char*)buf + copied_bytes, xfer_buf_pos + skip, copy_len);
|
||||||
retro_sleep(1000);
|
copied_bytes += copy_len;
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rv = 1;
|
|
||||||
#ifdef CDROM_DEBUG
|
|
||||||
printf("[CDROM] Read retries failed, giving up.\n");
|
|
||||||
fflush(stdout);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
if (read_cd && !cached_read && request_len >= 2352)
|
||||||
default:
|
{
|
||||||
break;
|
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)
|
if (xfer_buf)
|
||||||
free(xfer_buf);
|
memalign_free(xfer_buf);
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@ -533,7 +658,7 @@ static const char* get_profile(unsigned short profile)
|
|||||||
return "Unknown";
|
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 cdb[] = {0x3, 0, 0, 0, 0xFC, 0};
|
||||||
unsigned char buf[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;
|
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 cdb[] = {0x46, 0x2, 0, 0x10, 0, 0, 0, 0, 0x14, 0};
|
||||||
unsigned char buf[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");
|
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 cdb[] = {0x46, 0x2, 0, 0x1D, 0, 0, 0, 0, 0xC, 0};
|
||||||
unsigned char buf[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");
|
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 cdb[] = {0x46, 0x2, 0, 0x1E, 0, 0, 0, 0, 0x10, 0};
|
||||||
unsigned char buf[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");
|
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 cdb[] = {0x46, 0x2, 0, 0x0, 0, 0, 0, 0xFF, 0xFA, 0};
|
||||||
unsigned char buf[0xFFFA] = {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 cdb[] = {0x46, 0x2, 0, 0x1, 0, 0, 0, 0, 0x14, 0};
|
||||||
unsigned char buf[20] = {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 */
|
/* 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 */
|
/* MMC Command: INQUIRY */
|
||||||
unsigned char cdb[] = {0x12, 0, 0, 0, 0xff, 0};
|
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 */
|
/* MMC Command: READ CD MSF */
|
||||||
unsigned char cdb[] = {0xB9, 0, 0, 0, 0, 0, 0, 0, 0, 0xF8, 0, 0};
|
unsigned char cdb[] = {0xB9, 0, 0, 0, 0, 0, 0, 0, 0, 0xF8, 0, 0};
|
||||||
int rv;
|
int rv;
|
||||||
|
double frames = ceil((len + skip) / 2352.0);
|
||||||
|
unsigned frame_end = cdrom_msf_to_lba(min, sec, frame) + frames;
|
||||||
|
|
||||||
cdb[3] = min;
|
cdb[3] = min;
|
||||||
cdb[4] = sec;
|
cdb[4] = sec;
|
||||||
cdb[5] = frame;
|
cdb[5] = frame;
|
||||||
|
|
||||||
if (len + skip <= 2352)
|
if (frames <= 1)
|
||||||
{
|
{
|
||||||
unsigned char next_min = (frame == 74) ? (sec < 59 ? min : min + 1) : min;
|
cdrom_lba_to_msf(frame_end, &cdb[6], &cdb[7], &cdb[8]);
|
||||||
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;
|
|
||||||
|
|
||||||
#ifdef CDROM_DEBUG
|
#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);
|
fflush(stdout);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
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]);
|
cdrom_lba_to_msf(frame_end, &cdb[6], &cdb[7], &cdb[8]);
|
||||||
|
|
||||||
#ifdef CDROM_DEBUG
|
#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);
|
fflush(stdout);
|
||||||
#endif
|
#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);
|
rv = cdrom_send_command(stream, DIRECTION_IN, s, len, cdb, sizeof(cdb), skip);
|
||||||
|
|
||||||
#ifdef CDROM_DEBUG
|
#ifdef CDROM_DEBUG
|
||||||
@ -1119,61 +1230,15 @@ int cdrom_read(libretro_vfs_implementation_file *stream, cdrom_group_timeouts_t
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (rv)
|
if (rv)
|
||||||
|
{
|
||||||
|
stream->cdrom.last_frame_valid = false;
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cdrom_read_lba(libretro_vfs_implementation_file *stream, unsigned lba, void *s, size_t len, size_t skip)
|
int cdrom_stop(libretro_vfs_implementation_file *stream)
|
||||||
{
|
|
||||||
/* 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)
|
|
||||||
{
|
{
|
||||||
/* MMC Command: START STOP UNIT */
|
/* MMC Command: START STOP UNIT */
|
||||||
unsigned char cdb[] = {0x1B, 0, 0, 0, 0x0, 0};
|
unsigned char cdb[] = {0x1B, 0, 0, 0, 0x0, 0};
|
||||||
@ -1190,7 +1255,7 @@ int cdrom_stop(const libretro_vfs_implementation_file *stream)
|
|||||||
return 0;
|
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 */
|
/* MMC Command: PREVENT ALLOW MEDIUM REMOVAL */
|
||||||
unsigned char cdb[] = {0x1E, 0, 0, 0, 0x2, 0};
|
unsigned char cdb[] = {0x1E, 0, 0, 0, 0x2, 0};
|
||||||
@ -1219,7 +1284,7 @@ int cdrom_unlock(const libretro_vfs_implementation_file *stream)
|
|||||||
return 0;
|
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 */
|
/* MMC Command: START STOP UNIT */
|
||||||
unsigned char cdb[] = {0x1B, 0, 0, 0, 0x2, 0};
|
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;
|
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 */
|
/* MMC Command: START STOP UNIT */
|
||||||
unsigned char cdb[] = {0x1B, 0, 0, 0, 0x3, 0};
|
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};
|
union string_list_elem_attr attr = {0};
|
||||||
int dev_index = 0;
|
int dev_index = 0;
|
||||||
RFILE *file = filestream_open(dir_list->elems[i].data, RETRO_VFS_FILE_ACCESS_READ, 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;
|
bool is_cdrom = false;
|
||||||
|
|
||||||
if (!file)
|
if (!file)
|
||||||
@ -1309,7 +1374,6 @@ struct string_list* cdrom_get_available_drives(void)
|
|||||||
#if defined(_WIN32) && !defined(_XBOX)
|
#if defined(_WIN32) && !defined(_XBOX)
|
||||||
DWORD drive_mask = GetLogicalDrives();
|
DWORD drive_mask = GetLogicalDrives();
|
||||||
int i;
|
int i;
|
||||||
int drive_index = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < sizeof(DWORD) * 8; i++)
|
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};
|
char drive_string[33] = {0};
|
||||||
union string_list_elem_attr attr = {0};
|
union string_list_elem_attr attr = {0};
|
||||||
RFILE *file = filestream_open(cdrom_path, RETRO_VFS_FILE_ACCESS_READ, 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;
|
bool is_cdrom = false;
|
||||||
|
|
||||||
if (!file)
|
if (!file)
|
||||||
@ -1358,7 +1422,7 @@ struct string_list* cdrom_get_available_drives(void)
|
|||||||
return list;
|
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 */
|
/* MMC Command: TEST UNIT READY */
|
||||||
unsigned char cdb[] = {0x00, 0, 0, 0, 0, 0};
|
unsigned char cdb[] = {0x00, 0, 0, 0, 0, 0};
|
||||||
@ -1390,7 +1454,7 @@ bool cdrom_drive_has_media(const char drive)
|
|||||||
|
|
||||||
if (file)
|
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;
|
bool has_media = false;
|
||||||
|
|
||||||
has_media = cdrom_is_media_inserted(stream);
|
has_media = cdrom_is_media_inserted(stream);
|
||||||
@ -1403,7 +1467,7 @@ bool cdrom_drive_has_media(const char drive)
|
|||||||
return false;
|
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) */
|
/* MMC Command: MODE SENSE (10) and MODE SELECT (10) */
|
||||||
unsigned char cdb_sense_changeable[] = {0x5A, 0, 0x48, 0, 0, 0, 0, 0, 0x14, 0};
|
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;
|
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 */
|
/* MMC Command: READ TOC/PMA/ATIP */
|
||||||
unsigned char cdb[] = {0x43, 0x2, 0x4, 0, 0, 0, 0, 0x9, 0x30, 0};
|
unsigned char cdb[] = {0x43, 0x2, 0x4, 0, 0, 0, 0, 0x9, 0x30, 0};
|
||||||
|
@ -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);
|
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 */
|
/* 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(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_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 */
|
/* must be freed by the caller */
|
||||||
struct string_list* cdrom_get_available_drives(void);
|
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);
|
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_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);
|
void cdrom_device_fillpath(char *path, size_t len, char drive, unsigned char track, bool is_cue);
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ bool filestream_exists(const char *path);
|
|||||||
|
|
||||||
char *filestream_getline(RFILE *stream);
|
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
|
RETRO_END_DECLS
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#define __LIBRETRO_SDK_VFS_H
|
#define __LIBRETRO_SDK_VFS_H
|
||||||
|
|
||||||
#include <retro_common_api.h>
|
#include <retro_common_api.h>
|
||||||
|
#include <boolean.h>
|
||||||
|
|
||||||
#ifdef RARCH_INTERNAL
|
#ifdef RARCH_INTERNAL
|
||||||
#ifndef VFS_FRONTEND
|
#ifndef VFS_FRONTEND
|
||||||
@ -49,6 +50,9 @@ typedef struct
|
|||||||
unsigned char cur_frame;
|
unsigned char cur_frame;
|
||||||
unsigned char cur_track;
|
unsigned char cur_track;
|
||||||
unsigned cur_lba;
|
unsigned cur_lba;
|
||||||
|
unsigned last_frame_lba;
|
||||||
|
unsigned char last_frame[2352];
|
||||||
|
bool last_frame_valid;
|
||||||
} vfs_cdrom_t;
|
} vfs_cdrom_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -613,7 +613,7 @@ char *filestream_getline(RFILE *stream)
|
|||||||
return newline;
|
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;
|
||||||
}
|
}
|
||||||
|
@ -131,7 +131,7 @@ typedef struct
|
|||||||
{
|
{
|
||||||
RFILE *file;
|
RFILE *file;
|
||||||
RFILE *output_file;
|
RFILE *output_file;
|
||||||
const libretro_vfs_implementation_file *stream;
|
libretro_vfs_implementation_file *stream;
|
||||||
const cdrom_toc_t *toc;
|
const cdrom_toc_t *toc;
|
||||||
char cdrom_path[64];
|
char cdrom_path[64];
|
||||||
char drive_letter[2];
|
char drive_letter[2];
|
||||||
|
Loading…
Reference in New Issue
Block a user