Revert " add hashing support for PSX cheevos (bin/cue, chd, or real CD)"

This commit is contained in:
Twinaphex 2019-08-30 15:55:07 +02:00 committed by GitHub
parent 6e4f0a03d3
commit 29dc30fa48
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 605 additions and 1545 deletions

View File

@ -177,7 +177,6 @@ OBJ += frontend/frontend_driver.o \
$(LIBRETRO_COMM_DIR)/streams/interface_stream.o \ $(LIBRETRO_COMM_DIR)/streams/interface_stream.o \
$(LIBRETRO_COMM_DIR)/streams/memory_stream.o \ $(LIBRETRO_COMM_DIR)/streams/memory_stream.o \
$(LIBRETRO_COMM_DIR)/vfs/vfs_implementation.o \ $(LIBRETRO_COMM_DIR)/vfs/vfs_implementation.o \
$(LIBRETRO_COMM_DIR)/vfs/vfs_implementation_cdrom.o \
$(LIBRETRO_COMM_DIR)/media/media_detect_cd.o \ $(LIBRETRO_COMM_DIR)/media/media_detect_cd.o \
$(LIBRETRO_COMM_DIR)/lists/string_list.o \ $(LIBRETRO_COMM_DIR)/lists/string_list.o \
$(LIBRETRO_COMM_DIR)/string/stdstring.o \ $(LIBRETRO_COMM_DIR)/string/stdstring.o \
@ -1668,7 +1667,8 @@ ifeq ($(HAVE_CDROM), 1)
endif endif
DEFINES += -DHAVE_CDROM DEFINES += -DHAVE_CDROM
OBJ += $(LIBRETRO_COMM_DIR)/cdrom/cdrom.o OBJ += $(LIBRETRO_COMM_DIR)/cdrom/cdrom.o \
$(LIBRETRO_COMM_DIR)/vfs/vfs_implementation_cdrom.o
endif endif
ifeq ($(HAVE_RTGA), 1) ifeq ($(HAVE_RTGA), 1)

View File

@ -37,7 +37,6 @@ OBJ := ctr/ctr_system.o \
libretro-common/file/config_file.o \ libretro-common/file/config_file.o \
libretro-common/streams/file_stream.o \ libretro-common/streams/file_stream.o \
libretro-common/vfs/vfs_implementation.o \ libretro-common/vfs/vfs_implementation.o \
libretro-common/vfs/vfs_implementation_cdrom.o \
libretro-common/hash/rhash.o \ libretro-common/hash/rhash.o \
file_path_str.o \ file_path_str.o \
verbosity.o verbosity.o

View File

@ -48,7 +48,6 @@ OBJS = frontend/frontend_salamander.o \
libretro-common/file/config_file.o \ libretro-common/file/config_file.o \
libretro-common/streams/file_stream.o \ libretro-common/streams/file_stream.o \
libretro-common/vfs/vfs_implementation.o \ libretro-common/vfs/vfs_implementation.o \
libretro-common/vfs/vfs_implementation_cdrom.o \
libretro-common/hash/rhash.o \ libretro-common/hash/rhash.o \
file_path_str.o \ file_path_str.o \
verbosity.o \ verbosity.o \

View File

@ -48,7 +48,6 @@ OBJS = frontend/frontend_salamander.o \
libretro-common/file/config_file.o \ libretro-common/file/config_file.o \
libretro-common/streams/file_stream.o \ libretro-common/streams/file_stream.o \
libretro-common/vfs/vfs_implementation.o \ libretro-common/vfs/vfs_implementation.o \
libretro-common/vfs/vfs_implementation_cdrom.o \
libretro-common/hash/rhash.o \ libretro-common/hash/rhash.o \
file_path_str.o \ file_path_str.o \
verbosity.o verbosity.o

View File

@ -63,7 +63,6 @@ OBJ = frontend/frontend_salamander.o \
libretro-common/lists/dir_list.o \ libretro-common/lists/dir_list.o \
libretro-common/streams/file_stream.o \ libretro-common/streams/file_stream.o \
libretro-common/vfs/vfs_implementation.o \ libretro-common/vfs/vfs_implementation.o \
libretro-common/vfs/vfs_implementation_cdrom.o \
libretro-common/file/retro_dirent.o \ libretro-common/file/retro_dirent.o \
libretro-common/encodings/encoding_utf.o \ libretro-common/encodings/encoding_utf.o \
libretro-common/compat/compat_strl.o \ libretro-common/compat/compat_strl.o \

View File

@ -66,7 +66,6 @@ ifeq ($(SALAMANDER_BUILD),1)
OBJ += libretro-common/file/config_file.o OBJ += libretro-common/file/config_file.o
OBJ += libretro-common/streams/file_stream.o OBJ += libretro-common/streams/file_stream.o
OBJ += libretro-common/vfs/vfs_implementation.o OBJ += libretro-common/vfs/vfs_implementation.o
OBJ += libretro-common/vfs/vfs_implementation_cdrom.o
OBJ += libretro-common/hash/rhash.o OBJ += libretro-common/hash/rhash.o
OBJ += file_path_str.o OBJ += file_path_str.o
OBJ += verbosity.o OBJ += verbosity.o

View File

@ -1118,8 +1118,6 @@ typedef struct
const char *path; const char *path;
const char *ext; const char *ext;
intfstream_t *stream; intfstream_t *stream;
intfstream_t *cdrom_stream;
intfstream_t *cdrom_track_stream;
rcheevos_cheevo_t *cheevo; rcheevos_cheevo_t *cheevo;
settings_t *settings; settings_t *settings;
struct http_connection_t *conn; struct http_connection_t *conn;
@ -1148,8 +1146,7 @@ enum
RCHEEVOS_HTTP_GET = -13, RCHEEVOS_HTTP_GET = -13,
RCHEEVOS_DEACTIVATE = -14, RCHEEVOS_DEACTIVATE = -14,
RCHEEVOS_PLAYING = -15, RCHEEVOS_PLAYING = -15,
RCHEEVOS_DELAY = -16, RCHEEVOS_DELAY = -16
RCHEEVOS_PSX_MD5 = -17
}; };
static int rcheevos_iterate(rcheevos_coro_t* coro) static int rcheevos_iterate(rcheevos_coro_t* coro)
@ -1158,14 +1155,8 @@ static int rcheevos_iterate(rcheevos_coro_t* coro)
const int lynx_header_len = 0x40; const int lynx_header_len = 0x40;
ssize_t num_read = 0; ssize_t num_read = 0;
size_t to_read = 4096; size_t to_read = 4096;
uint8_t *ptr = NULL; uint8_t *buffer = NULL;
const char *end = NULL; const char *end = NULL;
const char *ext = NULL;
size_t exe_name_size = 0;
char exe_name_buffer[32];
char *exe_name = NULL;
char *scan = NULL;
char buffer[2048];
static const uint32_t genesis_exts[] = static const uint32_t genesis_exts[] =
{ {
@ -1201,24 +1192,12 @@ static int rcheevos_iterate(rcheevos_coro_t* coro)
0 0
}; };
static const uint32_t psx_exts[] =
{
0x0b886782U, /* cue */
0x0b88899aU, /* m3u */
/*0x0b88af0bU,* toc */
/*0x0b88652fU,* ccd */
/*0x0b889c67U,* pbp */
0x0b8865d4U, /* chd */
0
};
static rcheevos_finder_t finders[] = static rcheevos_finder_t finders[] =
{ {
{RCHEEVOS_SNES_MD5, "SNES (discards header)", snes_exts}, {RCHEEVOS_SNES_MD5, "SNES (discards header)", snes_exts},
{RCHEEVOS_GENESIS_MD5, "Genesis (6Mb padding)", genesis_exts}, {RCHEEVOS_GENESIS_MD5, "Genesis (6Mb padding)", genesis_exts},
{RCHEEVOS_LYNX_MD5, "Atari Lynx (discards header)", lynx_exts}, {RCHEEVOS_LYNX_MD5, "Atari Lynx (discards header)", lynx_exts},
{RCHEEVOS_NES_MD5, "NES (discards header)", NULL}, {RCHEEVOS_NES_MD5, "NES (discards header)", NULL},
{RCHEEVOS_PSX_MD5, "Playstation (main executable)", psx_exts},
{RCHEEVOS_GENERIC_MD5, "Generic (plain content)", NULL}, {RCHEEVOS_GENERIC_MD5, "Generic (plain content)", NULL},
{RCHEEVOS_FILENAME_MD5, "Generic (filename)", NULL} {RCHEEVOS_FILENAME_MD5, "Generic (filename)", NULL}
}; };
@ -1264,13 +1243,14 @@ static int rcheevos_iterate(rcheevos_coro_t* coro)
for (;;) for (;;)
{ {
ptr = (uint8_t*)coro->data + coro->len; buffer = (uint8_t*)coro->data + coro->len;
to_read = 4096; to_read = 4096;
if (to_read > coro->count) if (to_read > coro->count)
to_read = coro->count; to_read = coro->count;
num_read = intfstream_read(coro->stream, (void*)ptr, to_read); num_read = intfstream_read(coro->stream,
(void*)buffer, to_read);
if (num_read <= 0) if (num_read <= 0)
break; break;
@ -1565,186 +1545,6 @@ found:
MD5_Final(coro->hash, &coro->md5); MD5_Final(coro->hash, &coro->md5);
CORO_GOTO(RCHEEVOS_GET_GAMEID); CORO_GOTO(RCHEEVOS_GET_GAMEID);
/**************************************************************************
* Info Tries to identify a Playstation game
* Input CHEEVOS_VAR_INFO the content info
* Output CHEEVOS_VAR_GAMEID the Retro Achievements game ID, or 0 if not found
*************************************************************************/
CORO_SUB(RCHEEVOS_PSX_MD5)
{
ext = path_get_extension(coro->path);
MD5_Init(&coro->md5);
/* if we're looking at an m3u file, get the first disc from the playlist */
if (string_is_equal_noncase(ext, "m3u"))
{
coro->cdrom_stream = intfstream_open_file(coro->path, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE);
if (coro->cdrom_stream)
{
char disc_path[PATH_MAX_LENGTH];
char* tmp;
intfstream_read(coro->cdrom_stream, buffer, sizeof(buffer));
intfstream_close(coro->cdrom_stream);
CHEEVOS_FREE(coro->cdrom_stream);
coro->cdrom_stream = NULL;
tmp = buffer;
while (*tmp && *tmp != '\n')
++tmp;
if (tmp > buffer && tmp[-1] == '\r')
--tmp;
*tmp = '\0';
fill_pathname_basedir(disc_path, coro->path, sizeof(disc_path));
strlcat(disc_path, buffer, sizeof(disc_path));
free((void*)coro->path);
coro->path = strdup(disc_path);
ext = path_get_extension(coro->path);
}
}
if (string_is_equal_noncase(ext, "chd"))
{
coro->cdrom_track_stream = intfstream_open_chd_track(coro->path, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE, 1);
}
else
{
coro->cdrom_stream = intfstream_open_file(coro->path, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE);
if (!coro->cdrom_stream)
CORO_STOP();
coro->cdrom_track_stream = intfstream_open_file_child(coro->cdrom_stream, "TRACK 01");
}
if (coro->cdrom_track_stream)
{
coro->stream = intfstream_open_file_child(coro->cdrom_track_stream, "SYSTEM.CNF");
if (coro->stream)
{
intfstream_read(coro->stream, buffer, sizeof(buffer));
intfstream_close(coro->stream);
CHEEVOS_FREE(coro->stream);
coro->stream = NULL;
for (scan = buffer; scan < &buffer[sizeof(buffer)] && *scan; ++scan)
{
if (strncmp(scan, "BOOT", 4) == 0)
{
exe_name = scan + 4;
while (isspace(*exe_name))
++exe_name;
if (*exe_name == '=')
{
++exe_name;
while (isspace(*exe_name))
++exe_name;
if (strncmp(exe_name, "cdrom:", 6) == 0)
exe_name += 6;
if (*exe_name == '\\')
++exe_name;
break;
}
}
while (*scan && *scan != '\n')
++scan;
}
if (exe_name)
{
scan = exe_name;
while (*scan != '\n' && *scan != ';' && *scan != ' ')
++scan;
*scan = '\0';
exe_name_size = scan - exe_name;
if (exe_name_size < sizeof(exe_name_buffer))
{
strcpy(exe_name_buffer, exe_name);
coro->stream = intfstream_open_file_child(coro->cdrom_track_stream, exe_name);
}
if (coro->stream)
{
intfstream_read(coro->stream, buffer, sizeof(buffer));
/* the PSX-E header specifies the executable size as a 4-byte value 28 bytes into the header, which doesn't
* include the header itself. We want to include the header in the hash, so append another 2048 to that value.
* ASSERT: this results in the same value as coro->stream->file.fp->size */
coro->count = 2048 + (((uint8_t)buffer[28 + 3] << 24) | ((uint8_t)buffer[28 + 2] << 16) |
((uint8_t)buffer[28 + 1] << 8) | (uint8_t)buffer[28]);
if (coro->count < CHEEVOS_MB(16)) /* sanity check */
{
/* there's also a few games that are use a singular engine and only differ via their data files.
* luckily, they have unique serial numbers, and use the serial number as the boot file in the
* standard way. include the boot executable name in the hash */
coro->count += exe_name_size;
free(coro->data);
coro->data = (uint8_t*)malloc(coro->count);
memcpy(coro->data, exe_name_buffer, exe_name_size);
coro->len = exe_name_size;
do
{
to_read = coro->count - coro->len;
if (to_read > sizeof(buffer))
to_read = sizeof(buffer);
memcpy((uint8_t*)coro->data + coro->len, buffer, to_read);
coro->len += to_read;
if (coro->len == coro->count)
break;
CORO_YIELD();
intfstream_read(coro->stream, buffer, sizeof(buffer));
} while (true);
CORO_GOSUB(RCHEEVOS_EVAL_MD5);
MD5_Final(coro->hash, &coro->md5);
intfstream_close(coro->stream);
CHEEVOS_FREE(coro->stream);
intfstream_close(coro->cdrom_track_stream);
CHEEVOS_FREE(coro->cdrom_track_stream);
if (coro->cdrom_stream)
{
intfstream_close(coro->cdrom_stream);
CHEEVOS_FREE(coro->cdrom_stream);
}
CORO_GOTO(RCHEEVOS_GET_GAMEID);
}
}
}
intfstream_close(coro->stream);
CHEEVOS_FREE(coro->stream);
}
intfstream_close(coro->cdrom_track_stream);
CHEEVOS_FREE(coro->cdrom_track_stream);
}
if (coro->cdrom_stream)
{
intfstream_close(coro->cdrom_stream);
CHEEVOS_FREE(coro->cdrom_stream);
}
coro->gameid = 0;
CORO_RET();
}
/************************************************************************** /**************************************************************************
* Info Tries to identify a "generic" game * Info Tries to identify a "generic" game
* Input CHEEVOS_VAR_INFO the content info * Input CHEEVOS_VAR_INFO the content info
@ -1840,11 +1640,6 @@ found:
{ {
int size; int size;
CHEEVOS_LOG(RCHEEVOS_TAG "checking hash %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
coro->hash[ 0], coro->hash[ 1], coro->hash[ 2], coro->hash[ 3], coro->hash[ 4], coro->hash[ 5], coro->hash[ 6], coro->hash[ 7],
coro->hash[ 8], coro->hash[ 9], coro->hash[10], coro->hash[11], coro->hash[12], coro->hash[13], coro->hash[14], coro->hash[15]);
size = rc_url_get_gameid(coro->url, sizeof(coro->url), coro->hash); size = rc_url_get_gameid(coro->url, sizeof(coro->url), coro->hash);
if (size < 0) if (size < 0)

View File

@ -550,8 +550,8 @@ Frees the patchdata
void rcheevos_free_patchdata(rcheevos_rapatchdata_t* patchdata) void rcheevos_free_patchdata(rcheevos_rapatchdata_t* patchdata)
{ {
unsigned i = 0, count = 0; unsigned i = 0, count = 0;
rcheevos_racheevo_t* cheevo = NULL; const rcheevos_racheevo_t* cheevo = NULL;
rcheevos_ralboard_t* lboard = NULL; const rcheevos_ralboard_t* lboard = NULL;
cheevo = patchdata->core; cheevo = patchdata->core;

View File

@ -32,12 +32,7 @@ End of setup
*****************************************************************************/ *****************************************************************************/
#define RCHEEVOS_TAG "[RCHEEVOS]: " #define RCHEEVOS_TAG "[RCHEEVOS]: "
#ifdef _DEBUG
#define CHEEVOS_FREE(p) do { void* q = (void*)p; p = NULL; if (q != NULL) free(q); } while (0)
#else
#define CHEEVOS_FREE(p) do { void* q = (void*)p; if (q != NULL) free(q); } while (0) #define CHEEVOS_FREE(p) do { void* q = (void*)p; if (q != NULL) free(q); } while (0)
#endif
#ifdef CHEEVOS_VERBOSE #ifdef CHEEVOS_VERBOSE

View File

@ -973,11 +973,11 @@ FILE
#include "../libretro-common/streams/memory_stream.c" #include "../libretro-common/streams/memory_stream.c"
#ifndef __WINRT__ #ifndef __WINRT__
#include "../libretro-common/vfs/vfs_implementation.c" #include "../libretro-common/vfs/vfs_implementation.c"
#include "../libretro-common/vfs/vfs_implementation_cdrom.c"
#endif #endif
#ifdef HAVE_CDROM #ifdef HAVE_CDROM
#include "../libretro-common/cdrom/cdrom.c" #include "../libretro-common/cdrom/cdrom.c"
#include "../libretro-common/vfs/vfs_implementation_cdrom.c"
#include "../libretro-common/media/media_detect_cd.c" #include "../libretro-common/media/media_detect_cd.c"
#endif #endif

View File

@ -301,7 +301,7 @@ static int cdrom_send_command_win32(const libretro_vfs_implementation_file *stre
memcpy(sptd.s.Cdb, cmd, cmd_len); memcpy(sptd.s.Cdb, cmd, cmd_len);
ioctl_rv = DeviceIoControl(stream->parent ? stream->parent->fh : stream->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 #ifdef CDROM_DEBUG
@ -313,8 +313,7 @@ static int cdrom_send_command_win32(const libretro_vfs_implementation_file *stre
if (cmd[0] == 0xB9) if (cmd[0] == 0xB9)
{ {
double time_taken = (double)(((clock() - t) * 1000) / CLOCKS_PER_SEC); 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", 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);
time_taken, sptd.s.DataTransferLength, len, cmd[3], cmd[4], cmd[5], cmd[6], cmd[7], cmd[8], extra, lba_req, lba_cur, stream->track ? stream->track->cur_lba : -1);
fflush(stdout); fflush(stdout);
} }
@ -360,7 +359,7 @@ static int cdrom_send_command_linux(const libretro_vfs_implementation_file *stre
sgio.mx_sb_len = sense_len; sgio.mx_sb_len = sense_len;
sgio.timeout = 5000; sgio.timeout = 5000;
rv = ioctl(fileno(stream->parent ? stream->parent->fp : stream->fp), 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;
@ -443,7 +442,7 @@ static int cdrom_send_command(libretro_vfs_implementation_file *stream, CDROM_CM
lba_req = cdrom_msf_to_lba(cmd[3], cmd[4], cmd[5]); lba_req = cdrom_msf_to_lba(cmd[3], cmd[4], cmd[5]);
if (lba_req == stream->track->last_frame_lba) if (stream->cdrom.last_frame_valid && lba_req == stream->cdrom.last_frame_lba)
{ {
/* use cached frame */ /* use cached frame */
cached_read = true; cached_read = true;
@ -452,7 +451,7 @@ static int cdrom_send_command(libretro_vfs_implementation_file *stream, CDROM_CM
fflush(stdout); fflush(stdout);
#endif #endif
/* assumes request_len is always equal to the size of last_frame */ /* assumes request_len is always equal to the size of last_frame */
memcpy(xfer_buf_pos, stream->track->last_frame, sizeof(stream->track->last_frame)); memcpy(xfer_buf_pos, stream->cdrom.last_frame, sizeof(stream->cdrom.last_frame));
} }
} }
@ -498,20 +497,18 @@ retry:
memcpy((char*)buf + copied_bytes, xfer_buf_pos + skip, copy_len); memcpy((char*)buf + copied_bytes, xfer_buf_pos + skip, copy_len);
copied_bytes += copy_len; copied_bytes += copy_len;
if (stream->track) if (read_cd && !cached_read && request_len >= 2352)
{ {
if (read_cd && !cached_read && request_len >= 2352) unsigned frame_end = cdrom_msf_to_lba(cmd[6], cmd[7], cmd[8]);
{
unsigned frame_end = cdrom_msf_to_lba(cmd[6], cmd[7], cmd[8]);
/* cache the last received frame */ /* cache the last received frame */
memcpy(stream->track->last_frame, xfer_buf_pos, sizeof(stream->track->last_frame)); memcpy(stream->cdrom.last_frame, xfer_buf_pos, sizeof(stream->cdrom.last_frame));
/* the ending frame is never actually read, so what we really just read is the one right before that */ stream->cdrom.last_frame_valid = true;
stream->track->last_frame_lba = frame_end - 1; /* 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->track->last_frame_lba = (unsigned)-1;
} }
else
stream->cdrom.last_frame_valid = false;
#if 0 #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); 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);
@ -1234,7 +1231,7 @@ int cdrom_read(libretro_vfs_implementation_file *stream, cdrom_group_timeouts_t
if (rv) if (rv)
{ {
stream->track->last_frame_lba = (unsigned)-1; stream->cdrom.last_frame_valid = false;
return 1; return 1;
} }
@ -1431,7 +1428,7 @@ struct string_list* cdrom_get_available_drives(void)
for (i = 0; i < sizeof(DWORD) * 8; i++) for (i = 0; i < sizeof(DWORD) * 8; i++)
{ {
char path[] = {"a:\\"}; char path[] = {"a:\\"};
char cdrom_path[] = {"cdrom://a:/drive.cue"}; char cdrom_path[] = {"cdrom://a:/drive-track01.bin"};
path[0] += i; path[0] += i;
cdrom_path[8] += i; cdrom_path[8] += i;
@ -1447,16 +1444,16 @@ struct string_list* cdrom_get_available_drives(void)
char drive_model[32] = {0}; char drive_model[32] = {0};
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 *cdrom_file = filestream_open(cdrom_path, RETRO_VFS_FILE_ACCESS_READ, 0); RFILE *file = filestream_open(cdrom_path, RETRO_VFS_FILE_ACCESS_READ, 0);
libretro_vfs_implementation_file *stream;
bool is_cdrom = false; bool is_cdrom = false;
if (cdrom_file) if (!file)
{ continue;
libretro_vfs_implementation_file* stream = filestream_get_vfs_handle(cdrom_file);
cdrom_get_inquiry(stream, drive_model, sizeof(drive_model), &is_cdrom);
filestream_close(cdrom_file); stream = filestream_get_vfs_handle(file);
} cdrom_get_inquiry(stream, drive_model, sizeof(drive_model), &is_cdrom);
filestream_close(file);
if (!is_cdrom) if (!is_cdrom)
continue; continue;

View File

@ -1037,10 +1037,6 @@ void chd_close(chd_file *chd)
for (i = 0 ; i < 4 ; i++) for (i = 0 ; i < 4 ; i++)
{ {
void* codec = NULL; void* codec = NULL;
if (!chd->codecintf[i])
continue;
switch (chd->codecintf[i]->compression) switch (chd->codecintf[i]->compression)
{ {
case CHD_CODEC_CD_LZMA: case CHD_CODEC_CD_LZMA:

View File

@ -45,28 +45,16 @@ void chdstream_close(chdstream_t *stream);
ssize_t chdstream_read(chdstream_t *stream, void *data, size_t bytes); ssize_t chdstream_read(chdstream_t *stream, void *data, size_t bytes);
ssize_t chdstream_read_file(chdstream_t *stream, int64_t file_start, void *data, size_t bytes);
int chdstream_getc(chdstream_t *stream); int chdstream_getc(chdstream_t *stream);
int chdstream_getc_file(chdstream_t *stream, int64_t file_start);
char *chdstream_gets(chdstream_t *stream, char *buffer, size_t len); char *chdstream_gets(chdstream_t *stream, char *buffer, size_t len);
char *chdstream_gets_file(chdstream_t *stream, int64_t file_start, char *buffer, size_t len);
uint64_t chdstream_tell(chdstream_t *stream); uint64_t chdstream_tell(chdstream_t *stream);
uint64_t chdstream_tell_file(chdstream_t *stream, int64_t file_start);
void chdstream_rewind(chdstream_t *stream); void chdstream_rewind(chdstream_t *stream);
void chdstream_rewind_file(chdstream_t *stream, int64_t file_start);
int64_t chdstream_seek(chdstream_t *stream, int64_t offset, int whence); int64_t chdstream_seek(chdstream_t *stream, int64_t offset, int whence);
int64_t chdstream_seek_file(chdstream_t* stream, const char* filename);
ssize_t chdstream_get_size(chdstream_t *stream); ssize_t chdstream_get_size(chdstream_t *stream);
RETRO_END_DECLS RETRO_END_DECLS

View File

@ -63,8 +63,6 @@ int64_t filestream_truncate(RFILE *stream, int64_t length);
**/ **/
RFILE* filestream_open(const char *path, unsigned mode, unsigned hints); RFILE* filestream_open(const char *path, unsigned mode, unsigned hints);
RFILE* filestream_open_child(RFILE *stream, const char* path);
int64_t filestream_seek(RFILE *stream, int64_t offset, int seek_position); int64_t filestream_seek(RFILE *stream, int64_t offset, int seek_position);
int64_t filestream_read(RFILE *stream, void *data, int64_t len); int64_t filestream_read(RFILE *stream, void *data, int64_t len);

View File

@ -36,8 +36,7 @@ enum intfstream_type
{ {
INTFSTREAM_FILE = 0, INTFSTREAM_FILE = 0,
INTFSTREAM_MEMORY, INTFSTREAM_MEMORY,
INTFSTREAM_CHD, INTFSTREAM_CHD
INTFSTREAM_CHD_FILE
}; };
typedef struct intfstream_internal intfstream_internal_t, intfstream_t; typedef struct intfstream_internal intfstream_internal_t, intfstream_t;
@ -98,9 +97,6 @@ int intfstream_flush(intfstream_internal_t *intf);
intfstream_t* intfstream_open_file(const char *path, intfstream_t* intfstream_open_file(const char *path,
unsigned mode, unsigned hints); unsigned mode, unsigned hints);
intfstream_t* intfstream_open_file_child(intfstream_internal_t *intf,
const char* path);
intfstream_t *intfstream_open_memory(void *data, intfstream_t *intfstream_open_memory(void *data,
unsigned mode, unsigned hints, uint64_t size); unsigned mode, unsigned hints, uint64_t size);

View File

@ -38,40 +38,28 @@ RETRO_BEGIN_DECLS
typedef void* HANDLE; typedef void* HANDLE;
#endif #endif
#ifdef HAVE_CDROM
typedef struct typedef struct
{ {
char* cue_buf; char *cue_buf;
size_t cue_len; size_t cue_len;
size_t cue_pos;
char drive;
} vfs_cdrom_t;
typedef struct
{
int64_t byte_pos; int64_t byte_pos;
unsigned cur_lba; char drive;
unsigned char cur_track;
unsigned char cur_min; unsigned char cur_min;
unsigned char cur_sec; unsigned char cur_sec;
unsigned char cur_frame; unsigned char cur_frame;
unsigned char cur_track;
unsigned sector_size; unsigned cur_lba;
unsigned char sector_header_size;
unsigned char mode;
unsigned last_frame_lba; unsigned last_frame_lba;
unsigned char last_frame[2352]; unsigned char last_frame[2352];
} vfs_cdrom_track_t; bool last_frame_valid;
} vfs_cdrom_t;
#endif
enum vfs_scheme enum vfs_scheme
{ {
VFS_SCHEME_NONE = 0, VFS_SCHEME_NONE = 0,
VFS_SCHEME_CDROM, VFS_SCHEME_CDROM
VFS_SCHEME_CDROM_TRACK,
VFS_SCHEME_CDROM_FILE,
VFS_SCHEME_CUE,
VFS_SCHEME_CUE_BIN,
VFS_SCHEME_CUE_BIN_FILE
}; };
#ifndef __WINRT__ #ifndef __WINRT__
@ -93,18 +81,10 @@ struct libretro_vfs_implementation_file
uint64_t mappos; uint64_t mappos;
uint64_t mapsize; uint64_t mapsize;
uint8_t *mapped; uint8_t *mapped;
#ifdef VFS_FRONTEND
struct retro_vfs_file_handle* parent;
#else
struct libretro_vfs_implementation_file* parent;
#endif
uint64_t parent_offset;
enum vfs_scheme scheme; enum vfs_scheme scheme;
#ifdef HAVE_CDROM
vfs_cdrom_t cdrom; vfs_cdrom_t cdrom;
vfs_cdrom_track_t* track; #endif
}; };
#endif #endif

View File

@ -24,16 +24,13 @@
#define __LIBRETRO_SDK_VFS_IMPLEMENTATION_CDROM_H #define __LIBRETRO_SDK_VFS_IMPLEMENTATION_CDROM_H
#include <vfs/vfs.h> #include <vfs/vfs.h>
#ifdef HAVE_CDROM
#include <cdrom/cdrom.h> #include <cdrom/cdrom.h>
#endif
RETRO_BEGIN_DECLS RETRO_BEGIN_DECLS
int64_t retro_vfs_file_seek_cdrom(libretro_vfs_implementation_file *stream, int64_t offset, int whence); int64_t retro_vfs_file_seek_cdrom(libretro_vfs_implementation_file *stream, int64_t offset, int whence);
bool retro_vfs_file_open_cdrom( void retro_vfs_file_open_cdrom(
libretro_vfs_implementation_file *stream, libretro_vfs_implementation_file *stream,
const char *path, unsigned mode, unsigned hints); const char *path, unsigned mode, unsigned hints);
@ -46,30 +43,9 @@ int64_t retro_vfs_file_read_cdrom(libretro_vfs_implementation_file *stream,
int retro_vfs_file_error_cdrom(libretro_vfs_implementation_file *stream); int retro_vfs_file_error_cdrom(libretro_vfs_implementation_file *stream);
#ifdef HAVE_CDROM
const cdrom_toc_t* retro_vfs_file_get_cdrom_toc(void); const cdrom_toc_t* retro_vfs_file_get_cdrom_toc(void);
#endif
libretro_vfs_implementation_file* retro_vfs_file_open_cdrom_track( const vfs_cdrom_t* retro_vfs_file_get_cdrom_position(const libretro_vfs_implementation_file *stream);
libretro_vfs_implementation_file* stream, const char* track);
int retro_vfs_file_close_cdrom_track(libretro_vfs_implementation_file *stream);
int64_t retro_vfs_file_seek_cdrom_track(libretro_vfs_implementation_file *stream, int64_t offset, int whence);
int64_t retro_vfs_file_read_cdrom_track(libretro_vfs_implementation_file *stream, void *s, uint64_t len);
int64_t retro_vfs_file_tell_cdrom_track(libretro_vfs_implementation_file *stream);
libretro_vfs_implementation_file* retro_vfs_file_open_cdrom_file(
libretro_vfs_implementation_file* stream, const char* path);
int64_t retro_vfs_file_seek_cdrom_file(libretro_vfs_implementation_file *stream, int64_t offset, int whence);
int64_t retro_vfs_file_read_cdrom_file(libretro_vfs_implementation_file *stream, void *s, uint64_t len);
int64_t retro_vfs_file_tell_cdrom_file(libretro_vfs_implementation_file *stream);
RETRO_END_DECLS RETRO_END_DECLS

View File

@ -26,6 +26,8 @@
#include <file/file_path.h> #include <file/file_path.h>
#include <retro_miscellaneous.h> #include <retro_miscellaneous.h>
/*#define MEDIA_CUE_PARSE_DEBUG*/
static void media_zero_trailing_spaces(char *buf, size_t len) static void media_zero_trailing_spaces(char *buf, size_t len)
{ {
int i; int i;
@ -63,6 +65,203 @@ static bool media_skip_spaces(const char **buf, size_t len)
return false; return false;
} }
/* Fill in "info" with detected CD info. Use this when you have a cue file and want it parsed to find the first data track and any pregap info. */
bool media_detect_cd_info_cue(const char *path, media_detect_cd_info_t *info)
{
RFILE *file = NULL;
char *line = NULL;
char track_path[PATH_MAX_LENGTH] = {0};
char track_abs_path[PATH_MAX_LENGTH] = {0};
char track_mode[11] = {0};
bool found_file = false;
bool found_track = false;
unsigned first_data_track = 0;
uint64_t data_track_pregap_bytes = 0;
if (string_is_empty(path) || !info)
return false;
file = filestream_open(path, RETRO_VFS_FILE_ACCESS_READ, 0);
if (!file)
{
printf("[MEDIA] Could not open cue path for reading: %s\n", path);
fflush(stdout);
return false;
}
while (!filestream_eof(file) && (line = filestream_getline(file)))
{
size_t len = 0;
const char *command = NULL;
if (string_is_empty(line))
{
free(line);
continue;
}
len = strlen(line);
command = line;
media_skip_spaces(&command, len);
if (!found_file && !strncasecmp(command, "FILE", 4))
{
const char *file = command + 4;
media_skip_spaces(&file, len - 4);
if (!string_is_empty(file))
{
const char *file_end = NULL;
size_t file_len = 0;
bool quoted = false;
if (file[0] == '"')
{
quoted = true;
file++;
}
if (quoted)
file_end = strchr(file, '\"');
else
file_end = strchr(file, ' ');
if (file_end)
{
file_len = file_end - file;
memcpy(track_path, file, file_len);
found_file = true;
#ifdef MEDIA_CUE_PARSE_DEBUG
printf("Found file: %s\n", track_path);
fflush(stdout);
#endif
}
}
}
else if (found_file && !found_track && !strncasecmp(command, "TRACK", 5))
{
const char *track = command + 5;
media_skip_spaces(&track, len - 5);
if (!string_is_empty(track))
{
unsigned track_number = 0;
sscanf(track, "%d", &track_number);
#ifdef MEDIA_CUE_PARSE_DEBUG
printf("Found track: %d\n", track_number);
fflush(stdout);
#endif
track++;
if (track[0] && track[0] != ' ' && track[0] != '\t')
track++;
if (!string_is_empty(track))
{
media_skip_spaces(&track, strlen(track));
#ifdef MEDIA_CUE_PARSE_DEBUG
printf("Found track type: %s\n", track);
fflush(stdout);
#endif
if (!strncasecmp(track, "MODE", 4))
{
first_data_track = track_number;
found_track = true;
strlcpy(track_mode, track, sizeof(track_mode));
}
else
found_file = false;
}
}
}
else if (found_file && found_track && first_data_track && !strncasecmp(command, "INDEX", 5))
{
const char *index = command + 5;
media_skip_spaces(&index, len - 5);
if (!string_is_empty(index))
{
unsigned index_number = 0;
sscanf(index, "%d", &index_number);
if (index_number == 1)
{
const char *pregap = index + 1;
if (pregap[0] && pregap[0] != ' ' && pregap[0] != '\t')
pregap++;
if (!string_is_empty(pregap))
{
media_skip_spaces(&pregap, strlen(pregap));
found_file = false;
found_track = false;
if (first_data_track && !string_is_empty(track_mode))
{
unsigned track_sector_size = 0;
unsigned track_mode_number = 0;
if (strlen(track_mode) == 10)
{
sscanf(track_mode, "MODE%d/%d", &track_mode_number, &track_sector_size);
#ifdef MEDIA_CUE_PARSE_DEBUG
printf("Found track mode %d with sector size %d\n", track_mode_number, track_sector_size);
fflush(stdout);
#endif
if ((track_mode_number == 1 || track_mode_number == 2) && track_sector_size)
{
unsigned min = 0;
unsigned sec = 0;
unsigned frame = 0;
sscanf(pregap, "%02d:%02d:%02d", &min, &sec, &frame);
if (min || sec || frame || strstr(pregap, "00:00:00"))
{
data_track_pregap_bytes = ((min * 60 + sec) * 75 + frame) * track_sector_size;
#ifdef MEDIA_CUE_PARSE_DEBUG
printf("Found pregap of %02d:%02d:%02d (bytes: %" PRIu64 ")\n", min, sec, frame, data_track_pregap_bytes);
fflush(stdout);
#endif
break;
}
}
}
}
}
}
}
}
free(line);
}
filestream_close(file);
if (!string_is_empty(track_path))
{
if (strstr(track_path, "/") || strstr(track_path, "\\"))
{
printf("using path %s\n", track_path);
fflush(stdout);
return media_detect_cd_info(track_path, data_track_pregap_bytes, info);
}
else
{
fill_pathname_basedir(track_abs_path, path, sizeof(track_abs_path));
strlcat(track_abs_path, track_path, sizeof(track_abs_path));
printf("using abs path %s\n", track_abs_path);
fflush(stdout);
return media_detect_cd_info(track_abs_path, data_track_pregap_bytes, info);
}
}
return true;
}
/* Fill in "info" with detected CD info. Use this when you want to open a specific track file directly, and the pregap is known. */ /* Fill in "info" with detected CD info. Use this when you want to open a specific track file directly, and the pregap is known. */
bool media_detect_cd_info(const char *path, uint64_t pregap_bytes, media_detect_cd_info_t *info) bool media_detect_cd_info(const char *path, uint64_t pregap_bytes, media_detect_cd_info_t *info)
{ {

View File

@ -43,8 +43,6 @@ struct chdstream
uint32_t frame_size; uint32_t frame_size;
/* Offset of data within frame */ /* Offset of data within frame */
uint32_t frame_offset; uint32_t frame_offset;
/* Size of frame header */
uint32_t frame_header_size;
/* Number of frames per hunk */ /* Number of frames per hunk */
uint32_t frames_per_hunk; uint32_t frames_per_hunk;
/* First frame of track in chd */ /* First frame of track in chd */
@ -362,62 +360,11 @@ ssize_t chdstream_read(chdstream_t *stream, void *data, size_t bytes)
return bytes; return bytes;
} }
ssize_t chdstream_read_file(chdstream_t *stream, int64_t file_start, void *data, size_t bytes)
{
uint8_t buffer[SECTOR_SIZE];
int64_t file_frame = (stream->offset - file_start) / stream->frame_size;
int64_t file_frame_offset = (stream->offset - file_start) - (file_frame * stream->frame_size) - stream->frame_header_size;
ssize_t bytes_read = 0;
if (file_frame_offset >= stream->frame_header_size + 2048)
{
++file_frame;
file_frame_offset = -1;
}
if (file_frame_offset < 0)
{
stream->offset = file_start + (file_frame * stream->frame_size) + stream->frame_header_size;
file_frame_offset = 0;
}
do
{
const int64_t remaining = 2048 - file_frame_offset;
if (bytes < remaining)
{
if (bytes > 0)
{
chdstream_read(stream, data, bytes);
bytes_read += bytes;
}
return bytes_read;
}
chdstream_read(stream, data, remaining);
bytes_read += remaining;
bytes -= remaining;
++file_frame;
stream->offset = file_start + (file_frame * stream->frame_size) + stream->frame_header_size;
file_frame_offset = 0;
} while (true);
}
int chdstream_getc(chdstream_t *stream) int chdstream_getc(chdstream_t *stream)
{ {
char c = 0; char c = 0;
if (chdstream_read(stream, &c, sizeof(c)) != sizeof(c)) if (chdstream_read(stream, &c, sizeof(c) != sizeof(c)))
return EOF;
return c;
}
int chdstream_getc_file(chdstream_t *stream, int64_t file_start)
{
char c = 0;
if (chdstream_read_file(stream, file_start, &c, sizeof(c)) != sizeof(c))
return EOF; return EOF;
return c; return c;
@ -438,43 +385,16 @@ char *chdstream_gets(chdstream_t *stream, char *buffer, size_t len)
return buffer; return buffer;
} }
char *chdstream_gets_file(chdstream_t *stream, int64_t file_start, char *buffer, size_t len)
{
int c;
size_t offset = 0;
while (offset < len && (c = chdstream_getc_file(stream, file_start)) != EOF)
buffer[offset++] = c;
if (offset < len)
buffer[offset] = '\0';
return buffer;
}
uint64_t chdstream_tell(chdstream_t *stream) uint64_t chdstream_tell(chdstream_t *stream)
{ {
return stream->offset; return stream->offset;
} }
uint64_t chdstream_tell_file(chdstream_t *stream, int64_t file_start)
{
const int64_t file_frame = (stream->offset - file_start) / stream->frame_size;
const int64_t file_frame_offset = (stream->offset - file_start) - (file_frame * stream->frame_size) - stream->frame_header_size;
return (file_frame * 2048) + file_frame_offset;
}
void chdstream_rewind(chdstream_t *stream) void chdstream_rewind(chdstream_t *stream)
{ {
stream->offset = 0; stream->offset = 0;
} }
void chdstream_rewind_file(chdstream_t *stream, int64_t file_start)
{
stream->offset = file_start;
}
int64_t chdstream_seek(chdstream_t *stream, int64_t offset, int whence) int64_t chdstream_seek(chdstream_t *stream, int64_t offset, int whence)
{ {
int64_t new_offset; int64_t new_offset;
@ -504,74 +424,6 @@ int64_t chdstream_seek(chdstream_t *stream, int64_t offset, int whence)
return 0; return 0;
} }
int64_t chdstream_seek_file(chdstream_t* stream, const char* path)
{
uint8_t buffer[SECTOR_SIZE], *tmp;
int sector, path_length;
const char* slash = strrchr(path, '\\');
if (slash)
{
/* navigate the path to the directory record for the file */
const int dir_length = (int)(slash - path);
memcpy(buffer, path, dir_length);
buffer[dir_length] = '\0';
if (chdstream_seek_file(stream, (const char*)buffer) < 0)
return -1;
path += dir_length + 1;
}
else
{
/* The boot record or primary volume descriptor is always at sector 16 and will contain a "CD001" marker */
chdstream_seek(stream, 16 * stream->frame_size, SEEK_SET);
chdstream_read(stream, buffer, sizeof(buffer));
if (stream->frame_header_size == 0)
{
if (memcmp(&buffer[25], "CD001", 5) == 0)
stream->frame_header_size = 24;
else
stream->frame_header_size = 16;
}
/* the directory_record starts at 156 bytes into the sector.
* the sector containing the table of contents is a 3 byte value that is 2 bytes into the directory_record. */
{
const int offset = stream->frame_header_size + 156 + 2;
sector = buffer[offset] | (buffer[offset + 1] << 8) | (buffer[offset + 2] << 16);
}
chdstream_seek(stream, sector * stream->frame_size, SEEK_SET);
}
/* process the table of contents */
chdstream_read(stream, buffer, sizeof(buffer));
path_length = strlen(path);
tmp = buffer + stream->frame_header_size;
while (tmp < buffer + sizeof(buffer))
{
/* the first byte of the record is the length of the record - if 0, we reached the end of the data */
if (!*tmp)
break;
/* filename is 33 bytes into the record and the format is "FILENAME;version" or "DIRECTORY" */
if ((tmp[33 + path_length] == ';' || tmp[33 + path_length] == '\0') &&
strncasecmp((const char*)(tmp + 33), path, path_length) == 0)
{
/* the file contents are in the sector identified in bytes 2-4 of the record */
sector = tmp[2] | (tmp[3] << 8) | (tmp[4] << 16);
return chdstream_seek(stream, sector * stream->frame_size, SEEK_SET);
}
/* the first byte of the record is the length of the record */
tmp += tmp[0];
}
return -1;
}
ssize_t chdstream_get_size(chdstream_t *stream) ssize_t chdstream_get_size(chdstream_t *stream)
{ {
return stream->track_end; return stream->track_end;

View File

@ -31,10 +31,9 @@
#include "config.h" #include "config.h"
#endif #endif
#define VFS_FRONTEND
#include <streams/file_stream.h> #include <streams/file_stream.h>
#define VFS_FRONTEND
#include <vfs/vfs_implementation.h> #include <vfs/vfs_implementation.h>
#include <vfs/vfs_implementation_cdrom.h>
static const int64_t vfs_error_return_value = -1; static const int64_t vfs_error_return_value = -1;
@ -177,37 +176,6 @@ RFILE* filestream_open(const char *path, unsigned mode, unsigned hints)
return output; return output;
} }
RFILE* filestream_open_child(RFILE *stream, const char* path)
{
struct retro_vfs_file_handle *fp = NULL;
RFILE* output = NULL;
switch (stream->hfile->scheme)
{
case VFS_SCHEME_CDROM:
case VFS_SCHEME_CUE:
fp = retro_vfs_file_open_cdrom_track(stream->hfile, path);
break;
case VFS_SCHEME_CDROM_TRACK:
case VFS_SCHEME_CUE_BIN:
fp = retro_vfs_file_open_cdrom_file(stream->hfile, path);
break;
default:
return NULL;
}
if (!fp)
return NULL;
output = (RFILE*)malloc(sizeof(RFILE));
output->error_flag = false;
output->eof_flag = false;
output->hfile = fp;
return output;
}
char* filestream_gets(RFILE *stream, char *s, size_t len) char* filestream_gets(RFILE *stream, char *s, size_t len)
{ {
int c = 0; int c = 0;

View File

@ -52,7 +52,6 @@ struct intfstream_internal
struct struct
{ {
int32_t track; int32_t track;
int32_t file_start;
chdstream_t *fp; chdstream_t *fp;
} chd; } chd;
#endif #endif
@ -69,12 +68,12 @@ int64_t intfstream_get_size(intfstream_internal_t *intf)
return filestream_get_size(intf->file.fp); return filestream_get_size(intf->file.fp);
case INTFSTREAM_MEMORY: case INTFSTREAM_MEMORY:
return intf->memory.buf.size; return intf->memory.buf.size;
#ifdef HAVE_CHD
case INTFSTREAM_CHD: case INTFSTREAM_CHD:
return chdstream_get_size(intf->chd.fp); #ifdef HAVE_CHD
return chdstream_get_size(intf->chd.fp);
#else
break;
#endif #endif
default:
break;
} }
return 0; return 0;
@ -96,11 +95,9 @@ bool intfstream_resize(intfstream_internal_t *intf, intfstream_info_t *info)
memstream_set_buffer(intf->memory.buf.data, memstream_set_buffer(intf->memory.buf.data,
intf->memory.buf.size); intf->memory.buf.size);
break; break;
#ifdef HAVE_CHD
case INTFSTREAM_CHD: case INTFSTREAM_CHD:
break; #ifdef HAVE_CHD
#endif #endif
default:
break; break;
} }
@ -125,15 +122,15 @@ bool intfstream_open(intfstream_internal_t *intf, const char *path,
if (!intf->memory.fp) if (!intf->memory.fp)
return false; return false;
break; break;
#ifdef HAVE_CHD
case INTFSTREAM_CHD: case INTFSTREAM_CHD:
#ifdef HAVE_CHD
intf->chd.fp = chdstream_open(path, intf->chd.track); intf->chd.fp = chdstream_open(path, intf->chd.track);
if (!intf->chd.fp) if (!intf->chd.fp)
return false; return false;
break; break;
#endif #else
default:
return false; return false;
#endif
} }
return true; return true;
@ -152,8 +149,6 @@ int intfstream_flush(intfstream_internal_t *intf)
case INTFSTREAM_CHD: case INTFSTREAM_CHD:
/* Should we stub this for these interfaces? */ /* Should we stub this for these interfaces? */
break; break;
default:
break;
} }
return 0; return 0;
@ -174,17 +169,12 @@ int intfstream_close(intfstream_internal_t *intf)
if (intf->memory.fp) if (intf->memory.fp)
memstream_close(intf->memory.fp); memstream_close(intf->memory.fp);
return 0; return 0;
#ifdef HAVE_CHD
case INTFSTREAM_CHD: case INTFSTREAM_CHD:
#ifdef HAVE_CHD
if (intf->chd.fp) if (intf->chd.fp)
chdstream_close(intf->chd.fp); chdstream_close(intf->chd.fp);
return 0;
case INTFSTREAM_CHD_FILE:
/* handle owned by INTFSTREAM_CHD */
return 0;
#endif #endif
default: return 0;
break;
} }
return -1; return -1;
@ -212,13 +202,13 @@ void *intfstream_init(intfstream_info_t *info)
if (!intfstream_resize(intf, info)) if (!intfstream_resize(intf, info))
goto error; goto error;
break; break;
#ifdef HAVE_CHD
case INTFSTREAM_CHD: case INTFSTREAM_CHD:
#ifdef HAVE_CHD
intf->chd.track = info->chd.track; intf->chd.track = info->chd.track;
break; break;
#endif #else
default:
goto error; goto error;
#endif
} }
return intf; return intf;
@ -256,12 +246,12 @@ int64_t intfstream_seek(intfstream_internal_t *intf, int64_t offset, int whence)
} }
case INTFSTREAM_MEMORY: case INTFSTREAM_MEMORY:
return (int64_t)memstream_seek(intf->memory.fp, offset, whence); return (int64_t)memstream_seek(intf->memory.fp, offset, whence);
#ifdef HAVE_CHD
case INTFSTREAM_CHD: case INTFSTREAM_CHD:
#ifdef HAVE_CHD
return (int64_t)chdstream_seek(intf->chd.fp, offset, whence); return (int64_t)chdstream_seek(intf->chd.fp, offset, whence);
#endif #else
default:
break; break;
#endif
} }
return -1; return -1;
@ -278,14 +268,12 @@ int64_t intfstream_read(intfstream_internal_t *intf, void *s, uint64_t len)
return filestream_read(intf->file.fp, s, len); return filestream_read(intf->file.fp, s, len);
case INTFSTREAM_MEMORY: case INTFSTREAM_MEMORY:
return memstream_read(intf->memory.fp, s, len); return memstream_read(intf->memory.fp, s, len);
#ifdef HAVE_CHD
case INTFSTREAM_CHD: case INTFSTREAM_CHD:
#ifdef HAVE_CHD
return chdstream_read(intf->chd.fp, s, len); return chdstream_read(intf->chd.fp, s, len);
case INTFSTREAM_CHD_FILE: #else
return chdstream_read_file(intf->chd.fp, intf->chd.file_start, s, len);
#endif
default:
break; break;
#endif
} }
return -1; return -1;
@ -304,7 +292,6 @@ int64_t intfstream_write(intfstream_internal_t *intf,
case INTFSTREAM_MEMORY: case INTFSTREAM_MEMORY:
return memstream_write(intf->memory.fp, s, len); return memstream_write(intf->memory.fp, s, len);
case INTFSTREAM_CHD: case INTFSTREAM_CHD:
case INTFSTREAM_CHD_FILE:
return -1; return -1;
} }
@ -325,14 +312,12 @@ char *intfstream_gets(intfstream_internal_t *intf,
case INTFSTREAM_MEMORY: case INTFSTREAM_MEMORY:
return memstream_gets(intf->memory.fp, return memstream_gets(intf->memory.fp,
buffer, (size_t)len); buffer, (size_t)len);
#ifdef HAVE_CHD
case INTFSTREAM_CHD: case INTFSTREAM_CHD:
#ifdef HAVE_CHD
return chdstream_gets(intf->chd.fp, buffer, len); return chdstream_gets(intf->chd.fp, buffer, len);
case INTFSTREAM_CHD_FILE: #else
return chdstream_gets_file(intf->chd.fp, intf->chd.file_start, buffer, len);
#endif
default:
break; break;
#endif
} }
return NULL; return NULL;
@ -349,14 +334,12 @@ int intfstream_getc(intfstream_internal_t *intf)
return filestream_getc(intf->file.fp); return filestream_getc(intf->file.fp);
case INTFSTREAM_MEMORY: case INTFSTREAM_MEMORY:
return memstream_getc(intf->memory.fp); return memstream_getc(intf->memory.fp);
#ifdef HAVE_CHD
case INTFSTREAM_CHD: case INTFSTREAM_CHD:
#ifdef HAVE_CHD
return chdstream_getc(intf->chd.fp); return chdstream_getc(intf->chd.fp);
case INTFSTREAM_CHD_FILE: #else
return chdstream_getc_file(intf->chd.fp, intf->chd.file_start);
#endif
default:
break; break;
#endif
} }
return -1; return -1;
@ -373,14 +356,12 @@ int64_t intfstream_tell(intfstream_internal_t *intf)
return (int64_t)filestream_tell(intf->file.fp); return (int64_t)filestream_tell(intf->file.fp);
case INTFSTREAM_MEMORY: case INTFSTREAM_MEMORY:
return (int64_t)memstream_pos(intf->memory.fp); return (int64_t)memstream_pos(intf->memory.fp);
#ifdef HAVE_CHD
case INTFSTREAM_CHD: case INTFSTREAM_CHD:
#ifdef HAVE_CHD
return (int64_t)chdstream_tell(intf->chd.fp); return (int64_t)chdstream_tell(intf->chd.fp);
case INTFSTREAM_CHD_FILE: #else
return (int64_t)chdstream_tell_file(intf->chd.fp, intf->chd.file_start);
#endif
default:
break; break;
#endif
} }
return -1; return -1;
@ -396,15 +377,10 @@ void intfstream_rewind(intfstream_internal_t *intf)
case INTFSTREAM_MEMORY: case INTFSTREAM_MEMORY:
memstream_rewind(intf->memory.fp); memstream_rewind(intf->memory.fp);
break; break;
#ifdef HAVE_CHD
case INTFSTREAM_CHD: case INTFSTREAM_CHD:
#ifdef HAVE_CHD
chdstream_rewind(intf->chd.fp); chdstream_rewind(intf->chd.fp);
break;
case INTFSTREAM_CHD_FILE:
chdstream_rewind_file(intf->chd.fp, intf->chd.file_start);
break;
#endif #endif
default:
break; break;
} }
} }
@ -422,7 +398,7 @@ void intfstream_putc(intfstream_internal_t *intf, int c)
case INTFSTREAM_MEMORY: case INTFSTREAM_MEMORY:
memstream_putc(intf->memory.fp, c); memstream_putc(intf->memory.fp, c);
break; break;
default: case INTFSTREAM_CHD:
break; break;
} }
} }
@ -453,55 +429,6 @@ error:
return NULL; return NULL;
} }
intfstream_t* intfstream_open_file_child(intfstream_internal_t* intf, const char* path)
{
intfstream_info_t info;
intfstream_t *fd = NULL;
if (!intf)
return NULL;
info.type = INTFSTREAM_FILE;
fd = (intfstream_t*)intfstream_init(&info);
if (!fd)
return NULL;
switch (intf->type)
{
case INTFSTREAM_FILE:
fd->file.fp = filestream_open_child(intf->file.fp, path);
break;
case INTFSTREAM_MEMORY:
break;
#ifdef HAVE_CHD
case INTFSTREAM_CHD:
if (chdstream_seek_file(intf->chd.fp, path) < 0)
goto error;
fd->type = INTFSTREAM_CHD_FILE;
fd->chd.fp = intf->chd.fp;
fd->chd.file_start = chdstream_tell(intf->chd.fp);
return fd;
#endif
default:
goto error;
}
if (!fd->file.fp)
goto error;
return fd;
error:
if (fd)
{
intfstream_close(fd);
free(fd);
}
return NULL;
}
intfstream_t *intfstream_open_memory(void *data, intfstream_t *intfstream_open_memory(void *data,
unsigned mode, unsigned hints, uint64_t size) unsigned mode, unsigned hints, uint64_t size)
{ {

View File

@ -179,13 +179,16 @@
#endif #endif
#include <vfs/vfs_implementation.h> #include <vfs/vfs_implementation.h>
#include <vfs/vfs_implementation_cdrom.h>
#include <libretro.h> #include <libretro.h>
#include <memmap.h> #include <memmap.h>
#include <encodings/utf.h> #include <encodings/utf.h>
#include <compat/fopen_utf8.h> #include <compat/fopen_utf8.h>
#include <file/file_path.h> #include <file/file_path.h>
#ifdef HAVE_CDROM
#include <vfs/vfs_implementation_cdrom.h>
#endif
#define RFILE_HINT_UNBUFFERED (1 << 8) #define RFILE_HINT_UNBUFFERED (1 << 8)
int64_t retro_vfs_file_seek_internal(libretro_vfs_implementation_file *stream, int64_t offset, int whence) int64_t retro_vfs_file_seek_internal(libretro_vfs_implementation_file *stream, int64_t offset, int whence)
@ -195,25 +198,10 @@ int64_t retro_vfs_file_seek_internal(libretro_vfs_implementation_file *stream, i
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
{ {
switch (stream->scheme)
{
#ifdef HAVE_CDROM #ifdef HAVE_CDROM
case VFS_SCHEME_CDROM: if (stream->scheme == VFS_SCHEME_CDROM)
return retro_vfs_file_seek_cdrom(stream, offset, whence); return retro_vfs_file_seek_cdrom(stream, offset, whence);
case VFS_SCHEME_CDROM_TRACK:
return retro_vfs_file_seek_cdrom_track(stream, offset, whence);
case VFS_SCHEME_CDROM_FILE:
return retro_vfs_file_seek_cdrom_file(stream, offset, whence);
#endif #endif
case VFS_SCHEME_CUE:
break;
case VFS_SCHEME_CUE_BIN:
return retro_vfs_file_seek_cdrom_track(stream, offset, whence);
case VFS_SCHEME_CUE_BIN_FILE:
return retro_vfs_file_seek_cdrom_file(stream, offset, whence);
default:
break;
}
/* VC2005 and up have a special 64-bit fseek */ /* VC2005 and up have a special 64-bit fseek */
#ifdef ATLEAST_VC2005 #ifdef ATLEAST_VC2005
return _fseeki64(stream->fp, offset, whence); return _fseeki64(stream->fp, offset, whence);
@ -415,28 +403,28 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl(
} }
stream->fd = fd; stream->fd = fd;
#else #else
FILE *fp;
#ifdef HAVE_CDROM #ifdef HAVE_CDROM
if (stream->scheme == VFS_SCHEME_CDROM) if (stream->scheme == VFS_SCHEME_CDROM)
{ {
if (!retro_vfs_file_open_cdrom(stream, path, mode, hints)) retro_vfs_file_open_cdrom(stream, path, mode, hints);
#if defined(_WIN32) && !defined(_XBOX)
if (!stream->fh)
goto error; goto error;
#else
if (!stream->fp)
goto error;
#endif
} }
else else
#endif #endif
{ {
FILE *fp;
const char* ext;
fp = (FILE*)fopen_utf8(path, mode_str); fp = (FILE*)fopen_utf8(path, mode_str);
if (!fp) if (!fp)
goto error; goto error;
stream->fp = fp; stream->fp = fp;
ext = path_get_extension(path);
if (string_is_equal_case_insensitive(ext, "cue"))
stream->scheme = VFS_SCHEME_CUE;
} }
/* Regarding setvbuf: /* Regarding setvbuf:
* *
@ -449,17 +437,11 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl(
*/ */
/* TODO: this is only useful for a few platforms, find which and add ifdef */ /* TODO: this is only useful for a few platforms, find which and add ifdef */
#if !defined(PS2) && !defined(PSP) #if !defined(PS2) && !defined(PSP)
switch (stream->scheme) if (stream->scheme != VFS_SCHEME_CDROM)
{ {
case VFS_SCHEME_CDROM: stream->buf = (char*)calloc(1, 0x4000);
case VFS_SCHEME_CDROM_FILE: if (stream->fp)
case VFS_SCHEME_CDROM_TRACK: setvbuf(stream->fp, stream->buf, _IOFBF, 0x4000);
break;
default:
stream->buf = (char*)calloc(1, 0x4000);
if (stream->fp)
setvbuf(stream->fp, stream->buf, _IOFBF, 0x4000);
break;
} }
#endif #endif
#endif #endif
@ -509,6 +491,18 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl(
stream->size = orbisLseek(stream->fd, 0, SEEK_END); stream->size = orbisLseek(stream->fd, 0, SEEK_END);
orbisLseek(stream->fd, 0, SEEK_SET); orbisLseek(stream->fd, 0, SEEK_SET);
#else #else
#ifdef HAVE_CDROM
if (stream->scheme == VFS_SCHEME_CDROM)
{
retro_vfs_file_seek_cdrom(stream, 0, SEEK_SET);
retro_vfs_file_seek_cdrom(stream, 0, SEEK_END);
stream->size = retro_vfs_file_tell_impl(stream);
retro_vfs_file_seek_cdrom(stream, 0, SEEK_SET);
}
else
#endif
{ {
retro_vfs_file_seek_internal(stream, 0, SEEK_SET); retro_vfs_file_seek_internal(stream, 0, SEEK_SET);
retro_vfs_file_seek_internal(stream, 0, SEEK_END); retro_vfs_file_seek_internal(stream, 0, SEEK_END);
@ -530,27 +524,13 @@ int retro_vfs_file_close_impl(libretro_vfs_implementation_file *stream)
if (!stream) if (!stream)
return -1; return -1;
switch (stream->scheme)
{
#ifdef HAVE_CDROM #ifdef HAVE_CDROM
case VFS_SCHEME_CDROM: if (stream->scheme == VFS_SCHEME_CDROM)
retro_vfs_file_close_cdrom(stream); {
goto end; retro_vfs_file_close_cdrom(stream);
goto end;
case VFS_SCHEME_CDROM_TRACK:
retro_vfs_file_close_cdrom_track(stream);
goto end;
case VFS_SCHEME_CDROM_FILE:
break;
#endif
case VFS_SCHEME_CUE_BIN:
retro_vfs_file_close_cdrom_track(stream);
goto end;
default:
break;
} }
#endif
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
{ {
@ -576,9 +556,8 @@ int retro_vfs_file_close_impl(libretro_vfs_implementation_file *stream)
close(stream->fd); close(stream->fd);
#endif #endif
} }
end:
#ifdef HAVE_CDROM #ifdef HAVE_CDROM
end:
if (stream->cdrom.cue_buf) if (stream->cdrom.cue_buf)
free(stream->cdrom.cue_buf); free(stream->cdrom.cue_buf);
#endif #endif
@ -637,23 +616,10 @@ int64_t retro_vfs_file_tell_impl(libretro_vfs_implementation_file *stream)
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
{ {
switch (stream->scheme)
{
#ifdef HAVE_CDROM #ifdef HAVE_CDROM
case VFS_SCHEME_CDROM: if (stream->scheme == VFS_SCHEME_CDROM)
return retro_vfs_file_tell_cdrom(stream); return retro_vfs_file_tell_cdrom(stream);
case VFS_SCHEME_CDROM_TRACK:
return retro_vfs_file_tell_cdrom_track(stream);
case VFS_SCHEME_CDROM_FILE:
return retro_vfs_file_tell_cdrom_file(stream);
#endif #endif
case VFS_SCHEME_CUE_BIN:
return retro_vfs_file_tell_cdrom_track(stream);
case VFS_SCHEME_CUE_BIN_FILE:
return retro_vfs_file_tell_cdrom_file(stream);
default:
break;
}
#ifdef ORBIS #ifdef ORBIS
{ {
int64_t ret = orbisLseek(stream->fd, 0, SEEK_CUR); int64_t ret = orbisLseek(stream->fd, 0, SEEK_CUR);
@ -710,25 +676,10 @@ int64_t retro_vfs_file_read_impl(libretro_vfs_implementation_file *stream,
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
{ {
switch (stream->scheme)
{
#ifdef HAVE_CDROM #ifdef HAVE_CDROM
case VFS_SCHEME_CDROM: if (stream->scheme == VFS_SCHEME_CDROM)
return retro_vfs_file_read_cdrom(stream, s, len); return retro_vfs_file_read_cdrom(stream, s, len);
case VFS_SCHEME_CDROM_TRACK:
return retro_vfs_file_read_cdrom_track(stream, s, len);
case VFS_SCHEME_CDROM_FILE:
return retro_vfs_file_read_cdrom_file(stream, s, len);
#endif #endif
case VFS_SCHEME_CUE:
break;
case VFS_SCHEME_CUE_BIN:
return retro_vfs_file_read_cdrom_track(stream, s, len);
case VFS_SCHEME_CUE_BIN_FILE:
return retro_vfs_file_read_cdrom_file(stream, s, len);
default:
break;
}
#ifdef ORBIS #ifdef ORBIS
if (orbisRead(stream->fd, s, (size_t)len) < 0) if (orbisRead(stream->fd, s, (size_t)len) < 0)
return -1; return -1;

File diff suppressed because it is too large Load Diff