diff --git a/Makefile.common b/Makefile.common index e53c3b7c23..0b2889f0b2 100644 --- a/Makefile.common +++ b/Makefile.common @@ -177,7 +177,6 @@ OBJ += frontend/frontend_driver.o \ $(LIBRETRO_COMM_DIR)/streams/interface_stream.o \ $(LIBRETRO_COMM_DIR)/streams/memory_stream.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)/lists/string_list.o \ $(LIBRETRO_COMM_DIR)/string/stdstring.o \ @@ -1668,7 +1667,8 @@ ifeq ($(HAVE_CDROM), 1) endif 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 ifeq ($(HAVE_RTGA), 1) diff --git a/Makefile.ctr.salamander b/Makefile.ctr.salamander index dafb2d1c2c..44987e81d6 100644 --- a/Makefile.ctr.salamander +++ b/Makefile.ctr.salamander @@ -37,7 +37,6 @@ OBJ := ctr/ctr_system.o \ libretro-common/file/config_file.o \ libretro-common/streams/file_stream.o \ libretro-common/vfs/vfs_implementation.o \ - libretro-common/vfs/vfs_implementation_cdrom.o \ libretro-common/hash/rhash.o \ file_path_str.o \ verbosity.o diff --git a/Makefile.psp1.salamander b/Makefile.psp1.salamander index 24a8e2e0d7..7c08c5222c 100644 --- a/Makefile.psp1.salamander +++ b/Makefile.psp1.salamander @@ -48,7 +48,6 @@ OBJS = frontend/frontend_salamander.o \ libretro-common/file/config_file.o \ libretro-common/streams/file_stream.o \ libretro-common/vfs/vfs_implementation.o \ - libretro-common/vfs/vfs_implementation_cdrom.o \ libretro-common/hash/rhash.o \ file_path_str.o \ verbosity.o \ diff --git a/Makefile.vita.salamander b/Makefile.vita.salamander index fa24ee75ec..f479726e6d 100644 --- a/Makefile.vita.salamander +++ b/Makefile.vita.salamander @@ -48,7 +48,6 @@ OBJS = frontend/frontend_salamander.o \ libretro-common/file/config_file.o \ libretro-common/streams/file_stream.o \ libretro-common/vfs/vfs_implementation.o \ - libretro-common/vfs/vfs_implementation_cdrom.o \ libretro-common/hash/rhash.o \ file_path_str.o \ verbosity.o diff --git a/Makefile.wii.salamander b/Makefile.wii.salamander index fa662d53f9..8dc4e027c6 100644 --- a/Makefile.wii.salamander +++ b/Makefile.wii.salamander @@ -63,7 +63,6 @@ OBJ = frontend/frontend_salamander.o \ libretro-common/lists/dir_list.o \ libretro-common/streams/file_stream.o \ libretro-common/vfs/vfs_implementation.o \ - libretro-common/vfs/vfs_implementation_cdrom.o \ libretro-common/file/retro_dirent.o \ libretro-common/encodings/encoding_utf.o \ libretro-common/compat/compat_strl.o \ diff --git a/Makefile.wiiu b/Makefile.wiiu index b62811b6e3..3b6dea4468 100644 --- a/Makefile.wiiu +++ b/Makefile.wiiu @@ -66,7 +66,6 @@ ifeq ($(SALAMANDER_BUILD),1) OBJ += libretro-common/file/config_file.o OBJ += libretro-common/streams/file_stream.o OBJ += libretro-common/vfs/vfs_implementation.o - OBJ += libretro-common/vfs/vfs_implementation_cdrom.o OBJ += libretro-common/hash/rhash.o OBJ += file_path_str.o OBJ += verbosity.o diff --git a/cheevos-new/cheevos.c b/cheevos-new/cheevos.c index 927ce8735a..caf85fbc94 100644 --- a/cheevos-new/cheevos.c +++ b/cheevos-new/cheevos.c @@ -1118,8 +1118,6 @@ typedef struct const char *path; const char *ext; intfstream_t *stream; - intfstream_t *cdrom_stream; - intfstream_t *cdrom_track_stream; rcheevos_cheevo_t *cheevo; settings_t *settings; struct http_connection_t *conn; @@ -1148,8 +1146,7 @@ enum RCHEEVOS_HTTP_GET = -13, RCHEEVOS_DEACTIVATE = -14, RCHEEVOS_PLAYING = -15, - RCHEEVOS_DELAY = -16, - RCHEEVOS_PSX_MD5 = -17 + RCHEEVOS_DELAY = -16 }; 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; ssize_t num_read = 0; size_t to_read = 4096; - uint8_t *ptr = NULL; + uint8_t *buffer = 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[] = { @@ -1201,24 +1192,12 @@ static int rcheevos_iterate(rcheevos_coro_t* coro) 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[] = { {RCHEEVOS_SNES_MD5, "SNES (discards header)", snes_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_PSX_MD5, "Playstation (main executable)", psx_exts}, {RCHEEVOS_GENERIC_MD5, "Generic (plain content)", NULL}, {RCHEEVOS_FILENAME_MD5, "Generic (filename)", NULL} }; @@ -1264,13 +1243,14 @@ static int rcheevos_iterate(rcheevos_coro_t* coro) for (;;) { - ptr = (uint8_t*)coro->data + coro->len; + buffer = (uint8_t*)coro->data + coro->len; to_read = 4096; if (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) break; @@ -1565,186 +1545,6 @@ found: MD5_Final(coro->hash, &coro->md5); 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 * Input CHEEVOS_VAR_INFO the content info @@ -1840,11 +1640,6 @@ found: { 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); if (size < 0) diff --git a/cheevos-new/parser.c b/cheevos-new/parser.c index b28ac7b20e..eed9a88ecb 100644 --- a/cheevos-new/parser.c +++ b/cheevos-new/parser.c @@ -550,8 +550,8 @@ Frees the patchdata void rcheevos_free_patchdata(rcheevos_rapatchdata_t* patchdata) { unsigned i = 0, count = 0; - rcheevos_racheevo_t* cheevo = NULL; - rcheevos_ralboard_t* lboard = NULL; + const rcheevos_racheevo_t* cheevo = NULL; + const rcheevos_ralboard_t* lboard = NULL; cheevo = patchdata->core; diff --git a/cheevos-new/util.h b/cheevos-new/util.h index fbd882b66a..1794ef3ebb 100644 --- a/cheevos-new/util.h +++ b/cheevos-new/util.h @@ -32,12 +32,7 @@ End of setup *****************************************************************************/ #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) -#endif #ifdef CHEEVOS_VERBOSE diff --git a/griffin/griffin.c b/griffin/griffin.c index 40e59a643a..dd834caebd 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -973,11 +973,11 @@ FILE #include "../libretro-common/streams/memory_stream.c" #ifndef __WINRT__ #include "../libretro-common/vfs/vfs_implementation.c" -#include "../libretro-common/vfs/vfs_implementation_cdrom.c" #endif #ifdef HAVE_CDROM #include "../libretro-common/cdrom/cdrom.c" +#include "../libretro-common/vfs/vfs_implementation_cdrom.c" #include "../libretro-common/media/media_detect_cd.c" #endif diff --git a/libretro-common/cdrom/cdrom.c b/libretro-common/cdrom/cdrom.c index 1909fb6556..cb5ff8c110 100644 --- a/libretro-common/cdrom/cdrom.c +++ b/libretro-common/cdrom/cdrom.c @@ -301,7 +301,7 @@ static int cdrom_send_command_win32(const libretro_vfs_implementation_file *stre 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); #ifdef CDROM_DEBUG @@ -313,8 +313,7 @@ static int cdrom_send_command_win32(const libretro_vfs_implementation_file *stre 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->track ? stream->track->cur_lba : -1); + 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); } @@ -360,7 +359,7 @@ static int cdrom_send_command_linux(const libretro_vfs_implementation_file *stre sgio.mx_sb_len = sense_len; 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) 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]); - if (lba_req == stream->track->last_frame_lba) + if (stream->cdrom.last_frame_valid && lba_req == stream->cdrom.last_frame_lba) { /* use cached frame */ cached_read = true; @@ -452,7 +451,7 @@ static int cdrom_send_command(libretro_vfs_implementation_file *stream, CDROM_CM fflush(stdout); #endif /* 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); 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 */ - memcpy(stream->track->last_frame, xfer_buf_pos, sizeof(stream->track->last_frame)); - /* the ending frame is never actually read, so what we really just read is the one right before that */ - stream->track->last_frame_lba = frame_end - 1; - } - else - stream->track->last_frame_lba = (unsigned)-1; + /* 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); @@ -1234,7 +1231,7 @@ int cdrom_read(libretro_vfs_implementation_file *stream, cdrom_group_timeouts_t if (rv) { - stream->track->last_frame_lba = (unsigned)-1; + stream->cdrom.last_frame_valid = false; return 1; } @@ -1431,7 +1428,7 @@ struct string_list* cdrom_get_available_drives(void) for (i = 0; i < sizeof(DWORD) * 8; i++) { char path[] = {"a:\\"}; - char cdrom_path[] = {"cdrom://a:/drive.cue"}; + char cdrom_path[] = {"cdrom://a:/drive-track01.bin"}; path[0] += i; cdrom_path[8] += i; @@ -1447,16 +1444,16 @@ struct string_list* cdrom_get_available_drives(void) char drive_model[32] = {0}; char drive_string[33] = {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; - if (cdrom_file) - { - libretro_vfs_implementation_file* stream = filestream_get_vfs_handle(cdrom_file); - cdrom_get_inquiry(stream, drive_model, sizeof(drive_model), &is_cdrom); + if (!file) + continue; - 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) continue; diff --git a/libretro-common/formats/libchdr/libchdr_chd.c b/libretro-common/formats/libchdr/libchdr_chd.c index fd48b9e87d..3e3de49c26 100644 --- a/libretro-common/formats/libchdr/libchdr_chd.c +++ b/libretro-common/formats/libchdr/libchdr_chd.c @@ -1037,10 +1037,6 @@ void chd_close(chd_file *chd) for (i = 0 ; i < 4 ; i++) { void* codec = NULL; - - if (!chd->codecintf[i]) - continue; - switch (chd->codecintf[i]->compression) { case CHD_CODEC_CD_LZMA: diff --git a/libretro-common/include/streams/chd_stream.h b/libretro-common/include/streams/chd_stream.h index 7fde65b386..246a2dcfc9 100644 --- a/libretro-common/include/streams/chd_stream.h +++ b/libretro-common/include/streams/chd_stream.h @@ -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_file(chdstream_t *stream, int64_t file_start, void *data, size_t bytes); - 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_file(chdstream_t *stream, int64_t file_start, char *buffer, size_t len); - 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_file(chdstream_t *stream, int64_t file_start); - 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); RETRO_END_DECLS diff --git a/libretro-common/include/streams/file_stream.h b/libretro-common/include/streams/file_stream.h index 64b7afbb25..0cfadad83c 100644 --- a/libretro-common/include/streams/file_stream.h +++ b/libretro-common/include/streams/file_stream.h @@ -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_child(RFILE *stream, const char* path); - int64_t filestream_seek(RFILE *stream, int64_t offset, int seek_position); int64_t filestream_read(RFILE *stream, void *data, int64_t len); diff --git a/libretro-common/include/streams/interface_stream.h b/libretro-common/include/streams/interface_stream.h index aeec984272..ec480c6624 100644 --- a/libretro-common/include/streams/interface_stream.h +++ b/libretro-common/include/streams/interface_stream.h @@ -36,8 +36,7 @@ enum intfstream_type { INTFSTREAM_FILE = 0, INTFSTREAM_MEMORY, - INTFSTREAM_CHD, - INTFSTREAM_CHD_FILE + INTFSTREAM_CHD }; 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, unsigned mode, unsigned hints); -intfstream_t* intfstream_open_file_child(intfstream_internal_t *intf, - const char* path); - intfstream_t *intfstream_open_memory(void *data, unsigned mode, unsigned hints, uint64_t size); diff --git a/libretro-common/include/vfs/vfs.h b/libretro-common/include/vfs/vfs.h index 2f24597c82..b876f438b6 100644 --- a/libretro-common/include/vfs/vfs.h +++ b/libretro-common/include/vfs/vfs.h @@ -38,40 +38,28 @@ RETRO_BEGIN_DECLS typedef void* HANDLE; #endif +#ifdef HAVE_CDROM typedef struct { - char* cue_buf; + char *cue_buf; size_t cue_len; - size_t cue_pos; - char drive; -} vfs_cdrom_t; - -typedef struct -{ int64_t byte_pos; - unsigned cur_lba; - unsigned char cur_track; + char drive; unsigned char cur_min; unsigned char cur_sec; unsigned char cur_frame; - - unsigned sector_size; - unsigned char sector_header_size; - unsigned char mode; - + unsigned char cur_track; + unsigned cur_lba; unsigned last_frame_lba; unsigned char last_frame[2352]; -} vfs_cdrom_track_t; + bool last_frame_valid; +} vfs_cdrom_t; +#endif enum vfs_scheme { VFS_SCHEME_NONE = 0, - VFS_SCHEME_CDROM, - VFS_SCHEME_CDROM_TRACK, - VFS_SCHEME_CDROM_FILE, - VFS_SCHEME_CUE, - VFS_SCHEME_CUE_BIN, - VFS_SCHEME_CUE_BIN_FILE + VFS_SCHEME_CDROM }; #ifndef __WINRT__ @@ -93,18 +81,10 @@ struct libretro_vfs_implementation_file uint64_t mappos; uint64_t mapsize; 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; - +#ifdef HAVE_CDROM vfs_cdrom_t cdrom; - vfs_cdrom_track_t* track; +#endif }; #endif diff --git a/libretro-common/include/vfs/vfs_implementation_cdrom.h b/libretro-common/include/vfs/vfs_implementation_cdrom.h index 43d1ace50e..3996fbe877 100644 --- a/libretro-common/include/vfs/vfs_implementation_cdrom.h +++ b/libretro-common/include/vfs/vfs_implementation_cdrom.h @@ -24,16 +24,13 @@ #define __LIBRETRO_SDK_VFS_IMPLEMENTATION_CDROM_H #include - -#ifdef HAVE_CDROM #include -#endif RETRO_BEGIN_DECLS 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, 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); -#ifdef HAVE_CDROM const cdrom_toc_t* retro_vfs_file_get_cdrom_toc(void); -#endif -libretro_vfs_implementation_file* retro_vfs_file_open_cdrom_track( - 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); +const vfs_cdrom_t* retro_vfs_file_get_cdrom_position(const libretro_vfs_implementation_file *stream); RETRO_END_DECLS diff --git a/libretro-common/media/media_detect_cd.c b/libretro-common/media/media_detect_cd.c index 8d06d59dfa..9faa747a5a 100644 --- a/libretro-common/media/media_detect_cd.c +++ b/libretro-common/media/media_detect_cd.c @@ -26,6 +26,8 @@ #include #include +/*#define MEDIA_CUE_PARSE_DEBUG*/ + static void media_zero_trailing_spaces(char *buf, size_t len) { int i; @@ -63,6 +65,203 @@ static bool media_skip_spaces(const char **buf, size_t len) 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. */ bool media_detect_cd_info(const char *path, uint64_t pregap_bytes, media_detect_cd_info_t *info) { diff --git a/libretro-common/streams/chd_stream.c b/libretro-common/streams/chd_stream.c index af0dbe070d..97d3eb4699 100644 --- a/libretro-common/streams/chd_stream.c +++ b/libretro-common/streams/chd_stream.c @@ -43,8 +43,6 @@ struct chdstream uint32_t frame_size; /* Offset of data within frame */ uint32_t frame_offset; - /* Size of frame header */ - uint32_t frame_header_size; /* Number of frames per hunk */ uint32_t frames_per_hunk; /* First frame of track in chd */ @@ -362,62 +360,11 @@ ssize_t chdstream_read(chdstream_t *stream, void *data, size_t 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) { char c = 0; - 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)) + if (chdstream_read(stream, &c, sizeof(c) != sizeof(c))) return EOF; return c; @@ -438,43 +385,16 @@ char *chdstream_gets(chdstream_t *stream, char *buffer, size_t len) 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) { 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) { 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 new_offset; @@ -504,74 +424,6 @@ int64_t chdstream_seek(chdstream_t *stream, int64_t offset, int whence) 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) { return stream->track_end; diff --git a/libretro-common/streams/file_stream.c b/libretro-common/streams/file_stream.c index f8bd88e852..e3e4590752 100644 --- a/libretro-common/streams/file_stream.c +++ b/libretro-common/streams/file_stream.c @@ -31,10 +31,9 @@ #include "config.h" #endif -#define VFS_FRONTEND #include +#define VFS_FRONTEND #include -#include 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; } -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) { int c = 0; diff --git a/libretro-common/streams/interface_stream.c b/libretro-common/streams/interface_stream.c index d6a85c738b..0207823ce2 100644 --- a/libretro-common/streams/interface_stream.c +++ b/libretro-common/streams/interface_stream.c @@ -52,7 +52,6 @@ struct intfstream_internal struct { int32_t track; - int32_t file_start; chdstream_t *fp; } chd; #endif @@ -69,12 +68,12 @@ int64_t intfstream_get_size(intfstream_internal_t *intf) return filestream_get_size(intf->file.fp); case INTFSTREAM_MEMORY: return intf->memory.buf.size; -#ifdef HAVE_CHD case INTFSTREAM_CHD: - return chdstream_get_size(intf->chd.fp); +#ifdef HAVE_CHD + return chdstream_get_size(intf->chd.fp); +#else + break; #endif - default: - break; } return 0; @@ -96,11 +95,9 @@ bool intfstream_resize(intfstream_internal_t *intf, intfstream_info_t *info) memstream_set_buffer(intf->memory.buf.data, intf->memory.buf.size); break; -#ifdef HAVE_CHD case INTFSTREAM_CHD: - break; +#ifdef HAVE_CHD #endif - default: break; } @@ -125,15 +122,15 @@ bool intfstream_open(intfstream_internal_t *intf, const char *path, if (!intf->memory.fp) return false; break; -#ifdef HAVE_CHD case INTFSTREAM_CHD: +#ifdef HAVE_CHD intf->chd.fp = chdstream_open(path, intf->chd.track); if (!intf->chd.fp) return false; break; -#endif - default: +#else return false; +#endif } return true; @@ -152,8 +149,6 @@ int intfstream_flush(intfstream_internal_t *intf) case INTFSTREAM_CHD: /* Should we stub this for these interfaces? */ break; - default: - break; } return 0; @@ -174,17 +169,12 @@ int intfstream_close(intfstream_internal_t *intf) if (intf->memory.fp) memstream_close(intf->memory.fp); return 0; -#ifdef HAVE_CHD case INTFSTREAM_CHD: +#ifdef HAVE_CHD if (intf->chd.fp) chdstream_close(intf->chd.fp); - return 0; - case INTFSTREAM_CHD_FILE: - /* handle owned by INTFSTREAM_CHD */ - return 0; #endif - default: - break; + return 0; } return -1; @@ -212,13 +202,13 @@ void *intfstream_init(intfstream_info_t *info) if (!intfstream_resize(intf, info)) goto error; break; -#ifdef HAVE_CHD case INTFSTREAM_CHD: +#ifdef HAVE_CHD intf->chd.track = info->chd.track; break; -#endif - default: +#else goto error; +#endif } return intf; @@ -256,12 +246,12 @@ int64_t intfstream_seek(intfstream_internal_t *intf, int64_t offset, int whence) } case INTFSTREAM_MEMORY: return (int64_t)memstream_seek(intf->memory.fp, offset, whence); -#ifdef HAVE_CHD case INTFSTREAM_CHD: +#ifdef HAVE_CHD return (int64_t)chdstream_seek(intf->chd.fp, offset, whence); -#endif - default: +#else break; +#endif } 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); case INTFSTREAM_MEMORY: return memstream_read(intf->memory.fp, s, len); -#ifdef HAVE_CHD case INTFSTREAM_CHD: +#ifdef HAVE_CHD return chdstream_read(intf->chd.fp, s, len); - case INTFSTREAM_CHD_FILE: - return chdstream_read_file(intf->chd.fp, intf->chd.file_start, s, len); -#endif - default: +#else break; +#endif } return -1; @@ -304,7 +292,6 @@ int64_t intfstream_write(intfstream_internal_t *intf, case INTFSTREAM_MEMORY: return memstream_write(intf->memory.fp, s, len); case INTFSTREAM_CHD: - case INTFSTREAM_CHD_FILE: return -1; } @@ -325,14 +312,12 @@ char *intfstream_gets(intfstream_internal_t *intf, case INTFSTREAM_MEMORY: return memstream_gets(intf->memory.fp, buffer, (size_t)len); -#ifdef HAVE_CHD case INTFSTREAM_CHD: +#ifdef HAVE_CHD return chdstream_gets(intf->chd.fp, buffer, len); - case INTFSTREAM_CHD_FILE: - return chdstream_gets_file(intf->chd.fp, intf->chd.file_start, buffer, len); -#endif - default: +#else break; +#endif } return NULL; @@ -349,14 +334,12 @@ int intfstream_getc(intfstream_internal_t *intf) return filestream_getc(intf->file.fp); case INTFSTREAM_MEMORY: return memstream_getc(intf->memory.fp); -#ifdef HAVE_CHD case INTFSTREAM_CHD: +#ifdef HAVE_CHD return chdstream_getc(intf->chd.fp); - case INTFSTREAM_CHD_FILE: - return chdstream_getc_file(intf->chd.fp, intf->chd.file_start); -#endif - default: +#else break; +#endif } return -1; @@ -373,14 +356,12 @@ int64_t intfstream_tell(intfstream_internal_t *intf) return (int64_t)filestream_tell(intf->file.fp); case INTFSTREAM_MEMORY: return (int64_t)memstream_pos(intf->memory.fp); -#ifdef HAVE_CHD case INTFSTREAM_CHD: +#ifdef HAVE_CHD return (int64_t)chdstream_tell(intf->chd.fp); - case INTFSTREAM_CHD_FILE: - return (int64_t)chdstream_tell_file(intf->chd.fp, intf->chd.file_start); -#endif - default: +#else break; +#endif } return -1; @@ -396,15 +377,10 @@ void intfstream_rewind(intfstream_internal_t *intf) case INTFSTREAM_MEMORY: memstream_rewind(intf->memory.fp); break; -#ifdef HAVE_CHD case INTFSTREAM_CHD: +#ifdef HAVE_CHD chdstream_rewind(intf->chd.fp); - break; - case INTFSTREAM_CHD_FILE: - chdstream_rewind_file(intf->chd.fp, intf->chd.file_start); - break; #endif - default: break; } } @@ -422,7 +398,7 @@ void intfstream_putc(intfstream_internal_t *intf, int c) case INTFSTREAM_MEMORY: memstream_putc(intf->memory.fp, c); break; - default: + case INTFSTREAM_CHD: break; } } @@ -453,55 +429,6 @@ error: 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, unsigned mode, unsigned hints, uint64_t size) { diff --git a/libretro-common/vfs/vfs_implementation.c b/libretro-common/vfs/vfs_implementation.c index 535501aeb4..d92566e0f0 100644 --- a/libretro-common/vfs/vfs_implementation.c +++ b/libretro-common/vfs/vfs_implementation.c @@ -179,13 +179,16 @@ #endif #include -#include #include #include #include #include #include +#ifdef HAVE_CDROM +#include +#endif + #define RFILE_HINT_UNBUFFERED (1 << 8) 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) { - switch (stream->scheme) - { #ifdef HAVE_CDROM - case VFS_SCHEME_CDROM: - 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); + if (stream->scheme == VFS_SCHEME_CDROM) + return retro_vfs_file_seek_cdrom(stream, offset, whence); #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 */ #ifdef ATLEAST_VC2005 return _fseeki64(stream->fp, offset, whence); @@ -415,28 +403,28 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl( } stream->fd = fd; #else + FILE *fp; #ifdef HAVE_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; +#else + if (!stream->fp) + goto error; +#endif } else #endif { - FILE *fp; - const char* ext; - fp = (FILE*)fopen_utf8(path, mode_str); if (!fp) goto error; stream->fp = fp; - - ext = path_get_extension(path); - if (string_is_equal_case_insensitive(ext, "cue")) - stream->scheme = VFS_SCHEME_CUE; } /* 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 */ #if !defined(PS2) && !defined(PSP) - switch (stream->scheme) + if (stream->scheme != VFS_SCHEME_CDROM) { - case VFS_SCHEME_CDROM: - case VFS_SCHEME_CDROM_FILE: - case VFS_SCHEME_CDROM_TRACK: - break; - default: - stream->buf = (char*)calloc(1, 0x4000); - if (stream->fp) - setvbuf(stream->fp, stream->buf, _IOFBF, 0x4000); - break; + stream->buf = (char*)calloc(1, 0x4000); + if (stream->fp) + setvbuf(stream->fp, stream->buf, _IOFBF, 0x4000); } #endif #endif @@ -509,6 +491,18 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl( stream->size = orbisLseek(stream->fd, 0, SEEK_END); orbisLseek(stream->fd, 0, SEEK_SET); #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_END); @@ -530,27 +524,13 @@ int retro_vfs_file_close_impl(libretro_vfs_implementation_file *stream) if (!stream) return -1; - switch (stream->scheme) - { #ifdef HAVE_CDROM - case VFS_SCHEME_CDROM: - 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; + if (stream->scheme == VFS_SCHEME_CDROM) + { + retro_vfs_file_close_cdrom(stream); + goto end; } +#endif 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); #endif } - -end: #ifdef HAVE_CDROM +end: if (stream->cdrom.cue_buf) free(stream->cdrom.cue_buf); #endif @@ -637,23 +616,10 @@ int64_t retro_vfs_file_tell_impl(libretro_vfs_implementation_file *stream) if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) { - switch (stream->scheme) - { #ifdef HAVE_CDROM - case VFS_SCHEME_CDROM: - 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); + if (stream->scheme == VFS_SCHEME_CDROM) + return retro_vfs_file_tell_cdrom(stream); #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 { 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) { - switch (stream->scheme) - { #ifdef HAVE_CDROM - case VFS_SCHEME_CDROM: - 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); + if (stream->scheme == VFS_SCHEME_CDROM) + return retro_vfs_file_read_cdrom(stream, s, len); #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 if (orbisRead(stream->fd, s, (size_t)len) < 0) return -1; diff --git a/libretro-common/vfs/vfs_implementation_cdrom.c b/libretro-common/vfs/vfs_implementation_cdrom.c index 17bb2e1d9e..537dc7acac 100644 --- a/libretro-common/vfs/vfs_implementation_cdrom.c +++ b/libretro-common/vfs/vfs_implementation_cdrom.c @@ -21,698 +21,370 @@ */ #include -#include #include #include #include -#include - -#ifdef HAVE_CDROM #include -#endif #if defined(_WIN32) && !defined(_XBOX) #include #endif -/*#define CDROM_CUE_PARSE_DEBUG*/ - -#ifdef HAVE_CDROM static cdrom_toc_t vfs_cdrom_toc = {0}; const cdrom_toc_t* retro_vfs_file_get_cdrom_toc(void) { return &vfs_cdrom_toc; } -#endif -static void retro_vfs_file_seek_cdrom_track_sector(libretro_vfs_implementation_file* stream, unsigned sector) +int64_t retro_vfs_file_seek_cdrom(libretro_vfs_implementation_file *stream, int64_t offset, int whence) { - retro_vfs_file_seek_cdrom_track(stream, sector * stream->track->sector_size, SEEK_SET); -} - -static unsigned char retro_vs_file_get_sector_header_size(libretro_vfs_implementation_file* track_stream) -{ - unsigned char buffer[32]; - unsigned char sector_header_size = 0; - - if (!track_stream || !track_stream->track) - return 0; - - /* MODE information is normally found in the CUE sheet, but we can try to determine it from the raw data. - * - * MODE1/2048 - CDROM Mode1 Data (cooked) [no header, no footer] - * MODE1/2352 - CDROM Mode1 Data (raw) [16 byte header, 288 byte footer] - * MODE2/2336 - CDROM-XA Mode2 Data [8 byte header, 280 byte footer] - * MODE2/2352 - CDROM-XA Mode2 Data [24 byte header, 280 byte footer] - * - * Note that MODE is actually a property on each sector and can change between 1 and 2 depending on how much error - * correction the author desired. To support that, the data format must be "/2352" to include the full header and - * data without error correction information, at which point the CUE sheet information becomes just a hint. - * For simplicitly, we currently only handle "/2352" modes - */ - - /* The boot record or primary volume descriptor is always at sector 16 and will contain a "CD001" marker */ - retro_vfs_file_seek_cdrom_track_sector(track_stream, 16); - if (retro_vfs_file_read_cdrom_track(track_stream, buffer, sizeof(buffer)) == 0) - return 0; - - /* ISO-9660 says the first twelve bytes of a sector should be the sync pattern 00 FF FF FF FF FF FF FF FF FF FF 00 - * if it's not, then assume the track is audio data and has no header or MODE2/2336 which we don't support */ - if (buffer[0] == 0 && buffer[1] == 0xFF && buffer[2] == 0xFF && buffer[3] == 0xFF && - buffer[4] == 0xFF && buffer[5] == 0xFF && buffer[6] == 0xFF && buffer[7] == 0xFF && - buffer[8] == 0xFF && buffer[9] == 0xFF && buffer[10] == 0xFF && buffer[11] == 0) - { - /* after the 12 byte sync pattern is three bytes identifying the sector and then one byte for the mode (total 16 bytes) */ - sector_header_size = 16; - track_stream->track->mode = buffer[15]; - - /* if this is a CDROM-XA data source, the "CD001" tag will be offset by an additional 8 bytes */ - if (buffer[25] == 0x43 && buffer[26] == 0x44 && - buffer[27] == 0x30 && buffer[28] == 0x30 && buffer[29] == 0x31) - { - sector_header_size = 24; - } - } - - return sector_header_size; -} - -#ifdef HAVE_CDROM - -static bool retro_vfs_file_open_cdrom_handle(libretro_vfs_implementation_file* stream, const char* path, char drive) -{ -#ifdef CDROM_DEBUG - printf("[CDROM] Open: Path %s\n", path); - fflush(stdout); -#endif - -#if defined(__linux__) && !defined(ANDROID) - char cdrom_path[] = "/dev/sg1"; - cdrom_path[7] = drive; - - stream->fp = (FILE*)fopen_utf8(cdrom_path, "r+b"); - - if (!stream->fp) - return false; -#elif defined(_WIN32) && !defined(_XBOX) - char cdrom_path[] = "\\\\.\\D:"; - cdrom_path[4] = drive; - - stream->fh = CreateFile(cdrom_path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - - if (stream->fh == INVALID_HANDLE_VALUE) - { - stream->fh = NULL; - return false; - } -#endif - - stream->orig_path = strdup(path); - - if (cdrom_is_media_inserted(stream)) - { - cdrom_write_cue(stream, &stream->cdrom.cue_buf, &stream->cdrom.cue_len, stream->cdrom.drive, &vfs_cdrom_toc.num_tracks, &vfs_cdrom_toc); - cdrom_get_timeouts(stream, &vfs_cdrom_toc.timeouts); - } - - return true; -} - -#endif - -bool retro_vfs_file_open_cdrom( - libretro_vfs_implementation_file* stream, - const char* path, unsigned mode, unsigned hints) -{ - size_t path_len = strlen(path); - const char* ext = path_get_extension(path); + const char *ext = path_get_extension(stream->orig_path); if (string_is_equal_noncase(ext, "cue")) { - stream->cdrom.drive = '\0'; - -#ifdef HAVE_CDROM -#if defined(__linux__) && !defined(ANDROID) - if (path_len >= strlen("drive1.cue")) + switch (whence) { - if (!memcmp(path, "drive", strlen("drive"))) - { - if (path[5] >= '0' && path[5] <= '9') - { - stream->cdrom.drive = path[5]; - vfs_cdrom_toc.drive = stream->cdrom.drive; - - return retro_vfs_file_open_cdrom_handle(stream, path, stream->cdrom.drive); - } - } + case SEEK_SET: + stream->cdrom.byte_pos = offset; + break; + case SEEK_CUR: + stream->cdrom.byte_pos += offset; + break; + case SEEK_END: + stream->cdrom.byte_pos = (stream->cdrom.cue_len - 1) + offset; + break; } -#elif defined(_WIN32) && !defined(_XBOX) - if (path_len >= strlen("d:/drive.cue")) - { - if (!memcmp(path + 1, ":/drive", strlen(":/drive"))) - { - if ((path[0] >= 'A' && path[0] <= 'Z') || (path[0] >= 'a' && path[0] <= 'z')) - { - stream->cdrom.drive = path[0]; - vfs_cdrom_toc.drive = stream->cdrom.drive; - return retro_vfs_file_open_cdrom_handle(stream, path, stream->cdrom.drive); - } - } - } +#ifdef CDROM_DEBUG + printf("[CDROM] Seek: Path %s Offset %" PRIu64 " is now at %" PRIu64 "\n", stream->orig_path, offset, stream->cdrom.byte_pos); + fflush(stdout); #endif -#endif - - stream->fp = (FILE*)fopen_utf8(path, "r+b"); - if (stream->fp) - { - stream->scheme = VFS_SCHEME_CUE; - return true; - } } -#ifdef HAVE_CDROM else if (string_is_equal_noncase(ext, "bin")) { - unsigned track = 0; + int lba = (offset / 2352); + unsigned char min = 0; + unsigned char sec = 0; + unsigned char frame = 0; + const char *seek_type = "SEEK_SET"; -#if defined(__linux__) && !defined(ANDROID) - if (path_len >= strlen("drive1-track01.bin")) + (void)seek_type; + + switch (whence) { - if (!memcmp(path, "drive", strlen("drive"))) + case SEEK_CUR: { - if (!memcmp(path + 6, "-track", strlen("-track"))) - sscanf(path + 12, "%02u", (unsigned*)& track); + unsigned new_lba; - stream->cdrom.drive = path[5]; - if (!retro_vfs_file_open_cdrom_handle(stream, path, stream->cdrom.drive)) - return false; + stream->cdrom.byte_pos += offset; + new_lba = vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba + (stream->cdrom.byte_pos / 2352); + seek_type = "SEEK_CUR"; + + cdrom_lba_to_msf(new_lba, &min, &sec, &frame); + + break; + } + case SEEK_END: + { + ssize_t pregap_lba_len = (vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].audio ? 0 : (vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba - vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba_start)); + ssize_t lba_len = vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].track_size - pregap_lba_len; + + cdrom_lba_to_msf(lba_len + lba, &min, &sec, &frame); + + stream->cdrom.byte_pos = lba_len * 2352; + seek_type = "SEEK_END"; + + break; + } + case SEEK_SET: + default: + { + seek_type = "SEEK_SET"; + stream->cdrom.byte_pos = offset; + cdrom_lba_to_msf(vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba + (stream->cdrom.byte_pos / 2352), &min, &sec, &frame); + break; } } -#elif defined(_WIN32) && !defined(_XBOX) - if (path_len >= strlen("d:/drive-track01.bin")) - { - if (!memcmp(path + 1, ":/drive-track", strlen(":/drive-track"))) - { - sscanf(path + 14, "%02u", (unsigned*)& track); - stream->cdrom.drive = path[0]; - vfs_cdrom_toc.drive = stream->cdrom.drive; + stream->cdrom.cur_min = min; + stream->cdrom.cur_sec = sec; + stream->cdrom.cur_frame = frame; + stream->cdrom.cur_lba = cdrom_msf_to_lba(min, sec, frame); - if (!retro_vfs_file_open_cdrom_handle(stream, path, stream->cdrom.drive)) - return false; - } - } -#endif - - if (track) - { #ifdef CDROM_DEBUG - printf("[CDROM] Opening track %u\n", track); - fflush(stdout); + printf("[CDROM] Seek %s: Path %s Offset %" PRIu64 " is now at %" PRIu64 " (MSF %02u:%02u:%02u) (LBA %u)...\n", seek_type, stream->orig_path, offset, stream->cdrom.byte_pos, (unsigned)stream->cdrom.cur_min, (unsigned)stream->cdrom.cur_sec, (unsigned)stream->cdrom.cur_frame, stream->cdrom.cur_lba); + fflush(stdout); #endif + } + else + return -1; - if (track > vfs_cdrom_toc.num_tracks) - track = 1; + return 0; +} - stream->scheme = VFS_SCHEME_CDROM_TRACK; - stream->parent = stream; - stream->size = vfs_cdrom_toc.track[track - 1].track_bytes; - stream->track = (vfs_cdrom_track_t*)calloc(1, sizeof(*stream->track)); - stream->track->sector_size = 2352; - stream->track->cur_track = track; - stream->track->cur_min = vfs_cdrom_toc.track[track - 1].min; - stream->track->cur_sec = vfs_cdrom_toc.track[track - 1].sec; - stream->track->cur_frame = vfs_cdrom_toc.track[track - 1].frame; - stream->track->cur_lba = cdrom_msf_to_lba(stream->track->cur_min, stream->track->cur_sec, stream->track->cur_frame); - stream->track->last_frame_lba = (unsigned)-1; - return true; +void retro_vfs_file_open_cdrom( + libretro_vfs_implementation_file *stream, + const char *path, unsigned mode, unsigned hints) +{ +#if defined(__linux__) && !defined(ANDROID) + char cdrom_path[] = "/dev/sg1"; + size_t path_len = strlen(path); + const char *ext = path_get_extension(path); + + stream->cdrom.cur_track = 1; + + if (!string_is_equal_noncase(ext, "cue") && !string_is_equal_noncase(ext, "bin")) + return; + + if (path_len >= strlen("drive1-track01.bin")) + { + if (!memcmp(path, "drive", strlen("drive"))) + { + if (!memcmp(path + 6, "-track", strlen("-track"))) + { + if (sscanf(path + 12, "%02u", (unsigned*)&stream->cdrom.cur_track)) + { +#ifdef CDROM_DEBUG + printf("[CDROM] Opening track %d\n", stream->cdrom.cur_track); + fflush(stdout); +#endif + } + } } } -#endif - return false; + if (path_len >= strlen("drive1.cue")) + { + if (!memcmp(path, "drive", strlen("drive"))) + { + if (path[5] >= '0' && path[5] <= '9') + { + cdrom_path[7] = path[5]; + stream->cdrom.drive = path[5]; + vfs_cdrom_toc.drive = stream->cdrom.drive; + } + } + } + +#ifdef CDROM_DEBUG + printf("[CDROM] Open: Path %s URI %s\n", cdrom_path, path); + fflush(stdout); +#endif + stream->fp = (FILE*)fopen_utf8(cdrom_path, "r+b"); + + if (!stream->fp) + return; + + if (string_is_equal_noncase(ext, "cue")) + { + if (stream->cdrom.cue_buf) + { + free(stream->cdrom.cue_buf); + stream->cdrom.cue_buf = NULL; + } + + cdrom_write_cue(stream, &stream->cdrom.cue_buf, &stream->cdrom.cue_len, stream->cdrom.drive, &vfs_cdrom_toc.num_tracks, &vfs_cdrom_toc); + cdrom_get_timeouts(stream, &vfs_cdrom_toc.timeouts); + +#ifdef CDROM_DEBUG + if (string_is_empty(stream->cdrom.cue_buf)) + { + printf("[CDROM] Error writing cue sheet.\n"); + fflush(stdout); + } + else + { + printf("[CDROM] CUE Sheet:\n%s\n", stream->cdrom.cue_buf); + fflush(stdout); + } +#endif + } +#endif +#if defined(_WIN32) && !defined(_XBOX) + char cdrom_path[] = "\\\\.\\D:"; + size_t path_len = strlen(path); + const char *ext = path_get_extension(path); + + if (!string_is_equal_noncase(ext, "cue") && !string_is_equal_noncase(ext, "bin")) + return; + + if (path_len >= strlen("d:/drive-track01.bin")) + { + if (!memcmp(path + 1, ":/drive-track", strlen(":/drive-track"))) + { + if (sscanf(path + 14, "%02u", (unsigned*)&stream->cdrom.cur_track)) + { +#ifdef CDROM_DEBUG + printf("[CDROM] Opening track %d\n", stream->cdrom.cur_track); + fflush(stdout); +#endif + } + } + } + + if (path_len >= strlen("d:/drive.cue")) + { + if (!memcmp(path + 1, ":/drive", strlen(":/drive"))) + { + if ((path[0] >= 'A' && path[0] <= 'Z') || (path[0] >= 'a' && path[0] <= 'z')) + { + cdrom_path[4] = path[0]; + stream->cdrom.drive = path[0]; + vfs_cdrom_toc.drive = stream->cdrom.drive; + } + } + } + +#ifdef CDROM_DEBUG + printf("[CDROM] Open: Path %s URI %s\n", cdrom_path, path); + fflush(stdout); +#endif + stream->fh = CreateFile(cdrom_path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + + if (stream->fh == INVALID_HANDLE_VALUE) + return; + + if (string_is_equal_noncase(ext, "cue")) + { + if (stream->cdrom.cue_buf) + { + free(stream->cdrom.cue_buf); + stream->cdrom.cue_buf = NULL; + } + + cdrom_write_cue(stream, &stream->cdrom.cue_buf, &stream->cdrom.cue_len, stream->cdrom.drive, &vfs_cdrom_toc.num_tracks, &vfs_cdrom_toc); + cdrom_get_timeouts(stream, &vfs_cdrom_toc.timeouts); + +#ifdef CDROM_DEBUG + if (string_is_empty(stream->cdrom.cue_buf)) + { + printf("[CDROM] Error writing cue sheet.\n"); + fflush(stdout); + } + else + { + printf("[CDROM] CUE Sheet:\n%s\n", stream->cdrom.cue_buf); + fflush(stdout); + } +#endif + } +#endif + if (vfs_cdrom_toc.num_tracks > 1 && stream->cdrom.cur_track) + { + stream->cdrom.cur_min = vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].min; + stream->cdrom.cur_sec = vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].sec; + stream->cdrom.cur_frame = vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].frame; + stream->cdrom.cur_lba = cdrom_msf_to_lba(stream->cdrom.cur_min, stream->cdrom.cur_sec, stream->cdrom.cur_frame); + } + else + { + stream->cdrom.cur_min = vfs_cdrom_toc.track[0].min; + stream->cdrom.cur_sec = vfs_cdrom_toc.track[0].sec; + stream->cdrom.cur_frame = vfs_cdrom_toc.track[0].frame; + stream->cdrom.cur_lba = cdrom_msf_to_lba(stream->cdrom.cur_min, stream->cdrom.cur_sec, stream->cdrom.cur_frame); + } } int retro_vfs_file_close_cdrom(libretro_vfs_implementation_file *stream) { -#ifdef HAVE_CDROM #ifdef CDROM_DEBUG printf("[CDROM] Close: Path %s\n", stream->orig_path); fflush(stdout); #endif #if defined(_WIN32) && !defined(_XBOX) - if (stream->fh && !CloseHandle(stream->fh)) + if (!stream->fh || !CloseHandle(stream->fh)) return -1; #else if (!stream->fp || fclose(stream->fp)) return -1; #endif -#endif - - return 0; -} - -int64_t retro_vfs_file_seek_cdrom(libretro_vfs_implementation_file *stream, int64_t offset, int whence) -{ - switch (whence) - { - case SEEK_SET: - stream->cdrom.cue_pos = offset; - break; - - case SEEK_CUR: - stream->cdrom.cue_pos += offset; - break; - - case SEEK_END: - stream->cdrom.cue_pos = stream->cdrom.cue_len - offset; - break; - } - - if (stream->cdrom.cue_pos > stream->cdrom.cue_len) - stream->cdrom.cue_pos = stream->cdrom.cue_len; - if (stream->cdrom.cue_pos < 0) - stream->cdrom.cue_pos = 0; return 0; } int64_t retro_vfs_file_tell_cdrom(libretro_vfs_implementation_file *stream) { - return stream->cdrom.cue_pos; -} - -int64_t retro_vfs_file_read_cdrom(libretro_vfs_implementation_file* stream, - void* s, uint64_t len) -{ - size_t bytes_to_copy; - - if (!stream->cdrom.cue_buf) - return 0; - - bytes_to_copy = stream->cdrom.cue_len - stream->cdrom.cue_pos; - if (bytes_to_copy > len) - bytes_to_copy = len; - if (bytes_to_copy > 0) - { - memcpy(s, &stream->cdrom.cue_buf[stream->cdrom.cue_pos], bytes_to_copy); - stream->cdrom.cue_pos += bytes_to_copy; - } - - return bytes_to_copy; -} - -int retro_vfs_file_error_cdrom(libretro_vfs_implementation_file *stream) -{ - return 0; -} - -static void retro_vfs_skip_spaces(const char **buf, size_t len) -{ - if (!buf || !*buf) - return; - - while (len-- && (**buf == ' ' || **buf == '\t')) - ++(*buf); -} - -static bool retro_vfs_file_get_cue_track_path(const char* cue_contents, const char* cue_path, unsigned track, char* track_path, size_t max_track_path, int* track_pregap_bytes, int* sector_size) -{ - const char *line = NULL; - const char* cue = cue_contents; - char current_track_path[PATH_MAX_LENGTH] = {0}; - char track_mode[11] = {0}; - bool found_file = false; - unsigned found_track = 0; - - if (!cue_contents) - return false; - - track_path[0] = '\0'; - - while (*cue) - { - size_t len = 0; - - while (*cue && (*cue == ' ' || *cue == '\t')) - ++cue; - line = cue; - while (*cue && *cue != '\n') - ++cue; - len = cue - line; - if (*cue) - ++cue; - if (len == 0) - continue; - - if (!found_file && !strncasecmp(line, "FILE", 4)) - { - const char *file = line + 4; - retro_vfs_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(current_track_path, file, file_len); - found_file = true; -#ifdef CDROM_CUE_PARSE_DEBUG - printf("Found file: %s\n", current_track_path); - fflush(stdout); -#endif - } - } - } - else if (found_file && !found_track && !strncasecmp(line, "TRACK", 5)) - { - const char *track = line + 5; - retro_vfs_skip_spaces(&track, len - 5); - - if (!string_is_empty(track)) - { - unsigned track_number = 0; - sscanf(track, "%u", &track_number); -#ifdef CDROM_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)) - { - retro_vfs_skip_spaces(&track, strlen(track)); -#ifdef CDROM_CUE_PARSE_DEBUG - printf("Found track type: %s\n", track); - fflush(stdout); -#endif - if (!strncasecmp(track, "MODE", 4)) - { - found_track = track_number; - strlcpy(track_mode, track, sizeof(track_mode)); - } - else - found_track = 0; - } - } - } - else if (found_file && found_track == track && !strncasecmp(line, "INDEX", 5)) - { - const char *index = line + 5; - retro_vfs_skip_spaces(&index, len - 5); - - if (!string_is_empty(index)) - { - unsigned index_number = 0; - sscanf(index, "%u", &index_number); - - if (index_number == 1) - { - const char *pregap = index + 1; - if (pregap[0] && pregap[0] != ' ' && pregap[0] != '\t') - pregap++; - - if (strstr(current_track_path, "/") || strstr(current_track_path, "\\")) - { - strncpy(track_path, current_track_path, max_track_path); -#ifdef CDROM_CUE_PARSE_DEBUG - printf("using path %s\n", track_path); - fflush(stdout); -#endif - } - else - { - fill_pathname_basedir(track_path, cue_path, max_track_path); - strlcat(track_path, current_track_path, max_track_path); -#ifdef CDROM_CUE_PARSE_DEBUG - printf("using absolute path %s\n", track_path); - fflush(stdout); -#endif - } - - if (!string_is_empty(pregap)) - { - retro_vfs_skip_spaces(&pregap, strlen(pregap)); - found_file = false; - found_track = false; - - if (!string_is_empty(track_mode)) - { - unsigned track_sector_size = 0; - unsigned track_mode_number = 0; - - if (strlen(track_mode) == 10) - { - sscanf(track_mode, "MODE%u/%u", &track_mode_number, &track_sector_size); -#ifdef CDROM_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, "%02u:%02u:%02u", &min, &sec, &frame); - - if (min || sec || frame || strstr(pregap, "00:00:00")) - { - if (sector_size) - *sector_size = track_sector_size; - if (track_pregap_bytes) - *track_pregap_bytes = ((min * 60 + sec) * 75 + frame) * track_sector_size; -#ifdef CDROM_CUE_PARSE_DEBUG - printf("Found pregap of %02u:%02u:%02u (bytes: %" PRIu64 ")\n", min, sec, frame, data_track_pregap_bytes); - fflush(stdout); -#endif - break; - } - } - } - } - } - } - } - } - } - - return !string_is_empty(track_path); -} - -libretro_vfs_implementation_file* retro_vfs_file_open_cdrom_track(libretro_vfs_implementation_file* stream, const char* track) -{ - char track_path[PATH_MAX_LENGTH]; - unsigned track_index = 0; - - if (!stream->cdrom.cue_buf) - { - switch (stream->scheme) - { - case VFS_SCHEME_CUE: - stream->cdrom.cue_len = stream->size; - stream->cdrom.cue_buf = (char*)malloc(stream->size + 1); - if (stream->cdrom.cue_buf) - { - retro_vfs_file_seek_impl(stream, 0, RETRO_VFS_SEEK_POSITION_START); - retro_vfs_file_read_impl(stream, stream->cdrom.cue_buf, stream->cdrom.cue_len); - stream->cdrom.cue_buf[stream->cdrom.cue_len] = '\0'; - } - break; - -#ifdef HAVE_CDROM - case VFS_SCHEME_CDROM: - cdrom_write_cue(stream, &stream->cdrom.cue_buf, &stream->cdrom.cue_len, stream->cdrom.drive, &vfs_cdrom_toc.num_tracks, &vfs_cdrom_toc); - cdrom_get_timeouts(stream, &vfs_cdrom_toc.timeouts); - -#ifdef CDROM_DEBUG - if (string_is_empty(stream->cdrom.cue_buf)) - { - printf("[CDROM] Error writing cue sheet.\n"); - fflush(stdout); - } - else - { - printf("[CDROM] CUE Sheet:\n%s\n", stream->cdrom.cue_buf); - fflush(stdout); - } -#endif - break; -#endif - - default: - return NULL; - } - - if (!stream->cdrom.cue_buf) - return NULL; - } - - while (*track && (*track < '0' || *track > '9')) - ++track; - - sscanf(track, "%u", &track_index); - - if (track_index > 0) - { - int pregap_bytes = 0; - int sector_size = 2352; - if (retro_vfs_file_get_cue_track_path(stream->cdrom.cue_buf, stream->orig_path, track_index, track_path, PATH_MAX_LENGTH, &pregap_bytes, §or_size)) - { - libretro_vfs_implementation_file* track_stream; - if (stream->scheme == VFS_SCHEME_CDROM) - { -#ifdef HAVE_CDROM - track_stream = (libretro_vfs_implementation_file*)calloc(1, sizeof(*stream)); - track_stream->size = vfs_cdrom_toc.track[track_index - 1].track_bytes; -#endif - } - else - { - track_stream = retro_vfs_file_open_impl(track_path, RETRO_VFS_FILE_ACCESS_READ, stream->hints); - } - - if (track_stream) - { - track_stream->scheme = VFS_SCHEME_CDROM_TRACK; - track_stream->cdrom.drive = stream->cdrom.drive; - track_stream->parent = stream; - track_stream->parent_offset = pregap_bytes; - - track_stream->track = (vfs_cdrom_track_t*)calloc(1, sizeof(*track_stream->track)); - track_stream->track->cur_track = track_index; - track_stream->track->last_frame_lba = (unsigned)-1; - track_stream->track->sector_size = sector_size; - track_stream->track->sector_header_size = retro_vs_file_get_sector_header_size(track_stream); - - return track_stream; - } - } - } - - return NULL; -} - -int retro_vfs_file_close_cdrom_track(libretro_vfs_implementation_file* stream) -{ - if (stream->track) - free(stream->track); - - if (stream->parent == stream) - retro_vfs_file_close_cdrom(stream); - - return 0; -} - -int64_t retro_vfs_file_seek_cdrom_track(libretro_vfs_implementation_file* stream, int64_t offset, int whence) -{ - if (!stream->parent) + const char *ext = NULL; + if (!stream) return -1; - switch (whence) + ext = path_get_extension(stream->orig_path); + + if (string_is_equal_noncase(ext, "cue")) { - case SEEK_SET: - stream->track->byte_pos = offset; - break; - - case SEEK_CUR: - stream->track->byte_pos += offset; - break; - - case SEEK_END: - stream->track->byte_pos = stream->size - offset; - break; - } - - if (stream->track->byte_pos >= stream->size) - stream->track->byte_pos = stream->size - 1; - if (stream->track->byte_pos < 0) - stream->track->byte_pos = 0; - - if (stream->parent->scheme == VFS_SCHEME_CUE) - { - int64_t rv; - - /* temporarily change scheme to prevent infinite recusion */ - stream->scheme = VFS_SCHEME_NONE; - rv = retro_vfs_file_seek_impl(stream, stream->track->byte_pos + stream->parent_offset, SEEK_SET); - stream->scheme = VFS_SCHEME_CUE_BIN; - - if (rv >= 0) - stream->track->cur_lba = stream->track->byte_pos / stream->track->sector_size; - - return rv; - } - -#ifdef HAVE_CDROM - stream->track->cur_lba = vfs_cdrom_toc.track[stream->track->cur_track - 1].lba + (stream->track->byte_pos / stream->track->sector_size); - cdrom_lba_to_msf(stream->track->cur_lba, &stream->track->cur_min, &stream->track->cur_sec, &stream->track->cur_frame); - #ifdef CDROM_DEBUG - printf("[CDROM] Seek: Path %s Offset %" PRIu64 " is now at %" PRIu64 " (MSF %02u:%02u:%02u) (LBA %u)...\n", - stream->orig_path, offset, stream->track->byte_pos, (unsigned)stream->track->cur_min, (unsigned)stream->track->cur_sec, (unsigned)stream->track->cur_frame, stream->track->cur_lba); - fflush(stdout); + printf("[CDROM] (cue) Tell: Path %s Position %" PRIu64 "\n", stream->orig_path, stream->cdrom.byte_pos); + fflush(stdout); #endif + return stream->cdrom.byte_pos; + } + else if (string_is_equal_noncase(ext, "bin")) + { +#ifdef CDROM_DEBUG + printf("[CDROM] (bin) Tell: Path %s Position %" PRId64 "\n", stream->orig_path, stream->cdrom.byte_pos); + fflush(stdout); #endif + return stream->cdrom.byte_pos; + } - return 0; + return -1; } -static void retro_vfs_file_read_cdrom_track_sector(libretro_vfs_implementation_file* stream, void* s, uint64_t len) +int64_t retro_vfs_file_read_cdrom(libretro_vfs_implementation_file *stream, + void *s, uint64_t len) { - if (stream->parent->scheme == VFS_SCHEME_CUE) + int rv; + const char *ext = path_get_extension(stream->orig_path); + + if (string_is_equal_noncase(ext, "cue")) { - /* temporarily change the scheme to prevent recursion */ - stream->scheme = VFS_SCHEME_NONE; - retro_vfs_file_read_impl(stream, s, len); - stream->scheme = VFS_SCHEME_CUE_BIN; + if ((int64_t)len < (int64_t)stream->cdrom.cue_len - stream->cdrom.byte_pos) + { +#ifdef CDROM_DEBUG + printf("[CDROM] Read: Reading %" PRIu64 " bytes from cuesheet starting at %" PRIu64 "...\n", len, stream->cdrom.byte_pos); + fflush(stdout); +#endif + memcpy(s, stream->cdrom.cue_buf + stream->cdrom.byte_pos, len); + stream->cdrom.byte_pos += len; + + return len; + } + else + { +#ifdef CDROM_DEBUG + printf("[CDROM] Read: Reading %" PRIu64 " bytes from cuesheet starting at %" PRIu64 " failed.\n", len, stream->cdrom.byte_pos); + fflush(stdout); +#endif + return 0; + } } -#ifdef HAVE_CDROM - else + else if (string_is_equal_noncase(ext, "bin")) { - int rv; + size_t skip = stream->cdrom.byte_pos % 2352; unsigned char min = 0; unsigned char sec = 0; unsigned char frame = 0; unsigned char rmin = 0; unsigned char rsec = 0; unsigned char rframe = 0; - uint64_t byte_pos = stream->track->cur_lba * stream->track->sector_size; - if (byte_pos >= vfs_cdrom_toc.track[stream->track->cur_track - 1].track_bytes) - return; + if (stream->cdrom.byte_pos >= vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].track_bytes) + return 0; - if (byte_pos + len > vfs_cdrom_toc.track[stream->track->cur_track - 1].track_bytes) - len -= (byte_pos + len) - vfs_cdrom_toc.track[stream->track->cur_track - 1].track_bytes; + if (stream->cdrom.byte_pos + len > vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].track_bytes) + len -= (stream->cdrom.byte_pos + len) - vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].track_bytes; - cdrom_lba_to_msf(stream->track->cur_lba, &min, &sec, &frame); - cdrom_lba_to_msf(stream->track->cur_lba - vfs_cdrom_toc.track[stream->track->cur_track - 1].lba, &rmin, &rsec, &rframe); + cdrom_lba_to_msf(stream->cdrom.cur_lba, &min, &sec, &frame); + cdrom_lba_to_msf(stream->cdrom.cur_lba - vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba, &rmin, &rsec, &rframe); #ifdef CDROM_DEBUG - printf("[CDROM] Read: Reading %" PRIu64 " bytes from %s starting at byte offset %" PRIu64 " (rMSF %02u:%02u:%02u aMSF %02u:%02u:%02u) (LBA %u)...\n", len, stream->orig_path, byte_pos, (unsigned)rmin, (unsigned)rsec, (unsigned)rframe, (unsigned)min, (unsigned)sec, (unsigned)frame, stream->track->cur_lba); + printf("[CDROM] Read: Reading %" PRIu64 " bytes from %s starting at byte offset %" PRIu64 " (rMSF %02u:%02u:%02u aMSF %02u:%02u:%02u) (LBA %u) skip %" PRIu64 "...\n", len, stream->orig_path, stream->cdrom.byte_pos, (unsigned)rmin, (unsigned)rsec, (unsigned)rframe, (unsigned)min, (unsigned)sec, (unsigned)frame, stream->cdrom.cur_lba, skip); fflush(stdout); #endif - rv = cdrom_read(stream, &vfs_cdrom_toc.timeouts, min, sec, frame, s, (size_t)len, 0); + rv = cdrom_read(stream, &vfs_cdrom_toc.timeouts, min, sec, frame, s, (size_t)len, skip); /*rv = cdrom_read_lba(stream, stream->cdrom.cur_lba, s, (size_t)len, skip);*/ if (rv) @@ -721,256 +393,31 @@ static void retro_vfs_file_read_cdrom_track_sector(libretro_vfs_implementation_f printf("[CDROM] Failed to read %" PRIu64 " bytes from CD.\n", len); fflush(stdout); #endif - } - } -#endif -} - -int64_t retro_vfs_file_read_cdrom_track(libretro_vfs_implementation_file *stream, void *s, uint64_t len) -{ - uint64_t bytes_read = 0; - - if (!stream->parent) - return -1; - - if (stream->track->last_frame_lba == stream->track->cur_lba) - { - const int used = stream->track->byte_pos % stream->track->sector_size; - int remaining = stream->track->sector_size - used; - if (remaining > len) - { - memcpy(s, stream->track->last_frame + used, len); - stream->track->byte_pos += len; - return len; + return 0; } - memcpy(s, stream->track->last_frame + used, remaining); - s = (char*)s + remaining; - len -= remaining; - bytes_read += remaining; + stream->cdrom.byte_pos += len; + stream->cdrom.cur_lba = vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba + (stream->cdrom.byte_pos / 2352); - stream->track->cur_lba++; - retro_vfs_file_seek_cdrom_track_sector(stream, stream->track->cur_lba); - } - - while (len >= stream->track->sector_size) - { - retro_vfs_file_read_cdrom_track_sector(stream, s, stream->track->sector_size); - s = (char*)s + 2352; - - stream->track->cur_lba++; - - bytes_read += 2352; - len -= 2352; - } - - stream->track->byte_pos = stream->track->cur_lba * stream->track->sector_size; - - if (len > 0) - { - retro_vfs_file_read_cdrom_track_sector(stream, stream->track->last_frame, stream->track->sector_size); - memcpy(s, stream->track->last_frame, len); - bytes_read += len; - - stream->track->byte_pos += len; - stream->track->last_frame_lba = stream->track->cur_lba; - -#ifdef HAVE_CDROM - cdrom_lba_to_msf(stream->track->cur_lba, &stream->track->cur_min, &stream->track->cur_sec, &stream->track->cur_frame); -#endif - } - - return bytes_read; -} - -int64_t retro_vfs_file_tell_cdrom_track(libretro_vfs_implementation_file* stream) -{ - return stream->track->byte_pos; -} - -static int retro_vfs_file_find_cdrom_file_sector(libretro_vfs_implementation_file* track_stream, const char* path, unsigned* file_size) -{ - uint8_t buffer[2352], *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'; - - sector = retro_vfs_file_find_cdrom_file_sector(track_stream, (const char*)buffer, NULL); - if (sector < 0) - return sector; - - path += dir_length + 1; - } - else - { - int offset; - - /* find the cd information (always 16 frames in) */ - retro_vfs_file_seek_cdrom_track_sector(track_stream, 16); - retro_vfs_file_read_cdrom_track(track_stream, buffer, sizeof(buffer)); - - /* 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. */ - offset = track_stream->track->sector_header_size + 156 + 2; - sector = buffer[offset] | (buffer[offset + 1] << 8) | (buffer[offset + 2] << 16); - } - - /* process the table of contents */ - retro_vfs_file_seek_cdrom_track_sector(track_stream, sector); - retro_vfs_file_read_cdrom_track(track_stream, buffer, sizeof(buffer)); - - path_length = strlen(path); - tmp = buffer + track_stream->track->sector_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); - retro_vfs_file_seek_cdrom_track_sector(track_stream, sector); - - /* the file size is in bytes 10-13 of the record */ - if (file_size) - *file_size = tmp[10] | (tmp[11] << 8) | (tmp[12] << 16) | (tmp[13] << 24); + cdrom_lba_to_msf(stream->cdrom.cur_lba, &stream->cdrom.cur_min, &stream->cdrom.cur_sec, &stream->cdrom.cur_frame); #ifdef CDROM_DEBUG - { - unsigned char min, sec, frame; - cdrom_lba_to_msf(sector, &min, &sec, &frame); - printf("[CDROM] found %s (MSF %02u:%02u:%02u) (LBA %u)\n", path, (unsigned)min, (unsigned)sec, (unsigned)frame, sector); - fflush(stdout); - } + printf("[CDROM] read %" PRIu64 " bytes, position is now: %" PRIu64 " (MSF %02u:%02u:%02u) (LBA %u)\n", len, stream->cdrom.byte_pos, (unsigned)stream->cdrom.cur_min, (unsigned)stream->cdrom.cur_sec, (unsigned)stream->cdrom.cur_frame, cdrom_msf_to_lba(stream->cdrom.cur_min, stream->cdrom.cur_sec, stream->cdrom.cur_frame)); + fflush(stdout); #endif - return sector; - } - - /* the first byte of the record is the length of the record */ - tmp += tmp[0]; + return len; } -#ifdef CDROM_DEBUG - printf("[CDROM] did not find %s\n", path); - fflush(stdout); -#endif - - return -1; + return 0; } -libretro_vfs_implementation_file* retro_vfs_file_open_cdrom_file(libretro_vfs_implementation_file* track_stream, const char* path) +int retro_vfs_file_error_cdrom(libretro_vfs_implementation_file *stream) { - libretro_vfs_implementation_file* file_stream; - unsigned file_size = 0; - - int sector = retro_vfs_file_find_cdrom_file_sector(track_stream, path, &file_size); - if (sector < 0) - return NULL; - - file_stream = (libretro_vfs_implementation_file*)calloc(1, sizeof(*file_stream)); - file_stream->scheme = (track_stream->scheme == VFS_SCHEME_CDROM_TRACK) ? VFS_SCHEME_CDROM_FILE : VFS_SCHEME_CUE_BIN_FILE; - file_stream->parent = track_stream; - file_stream->parent_offset = sector * 2352 + track_stream->track->sector_header_size; - file_stream->orig_path = strdup(path); - file_stream->size = file_size; - - return file_stream; + return 0; } -int64_t retro_vfs_file_tell_cdrom_file(libretro_vfs_implementation_file* stream) +const vfs_cdrom_t* retro_vfs_file_get_cdrom_position(const libretro_vfs_implementation_file *stream) { - if (stream->parent != NULL && stream->parent->track) - { - const int64_t current_offset_raw = stream->parent->track->byte_pos - stream->parent_offset; - return (current_offset_raw / stream->parent->track->sector_size) * 2048 + (current_offset_raw % stream->parent->track->sector_size); - } - - return -1; -} - -int64_t retro_vfs_file_seek_cdrom_file(libretro_vfs_implementation_file* stream, int64_t offset, int whence) -{ - int64_t offset_raw; - switch (whence) - { - case SEEK_CUR: - { - const int64_t current_offset_raw = stream->parent->track->byte_pos - stream->parent_offset; - const int64_t current_offset = (current_offset_raw / stream->parent->track->sector_size) * 2048 + (current_offset_raw % stream->parent->track->sector_size); - offset = current_offset + offset; - break; - } - - case SEEK_END: - offset = stream->size - offset; - break; - } - - offset_raw = (offset / 2048) * stream->parent->track->sector_size + (offset % 2048); - - return retro_vfs_file_seek_cdrom_track(stream->parent, offset_raw, SEEK_SET); -} - -int64_t retro_vfs_file_read_cdrom_file(libretro_vfs_implementation_file* stream, void* s, uint64_t len) -{ - uint8_t buffer[2352]; - int64_t bytes_read = 0; - - if (!stream || !stream->parent || !stream->parent->track) - return 0; - - if (stream->parent->track->last_frame_lba == stream->parent->track->cur_lba) - { - const int used = stream->parent->track->byte_pos % stream->parent->track->sector_size - stream->parent->track->sector_header_size; - int remaining = 2048 - used; - if (remaining > 0) - { - if (remaining > len) - { - retro_vfs_file_read_cdrom_track(stream->parent, s, len); - return len; - } - - retro_vfs_file_read_cdrom_track(stream->parent, s, remaining); - s = (char*)s + remaining; - bytes_read += remaining; - } - - stream->parent->track->cur_lba = stream->parent->track->last_frame_lba + 1; - } - - while (len >= 2048) - { - retro_vfs_file_read_cdrom_track_sector(stream->parent, buffer, stream->parent->track->sector_size); - stream->parent->track->cur_lba++; - - memcpy(s, buffer + stream->parent->track->sector_header_size, 2048); - s = (char*)s + 2048; - bytes_read += 2048; - len -= 2048; - } - - stream->parent->track->byte_pos = stream->parent->track->cur_lba * stream->parent->track->sector_size; - - if (len > 0) - { - retro_vfs_file_read_cdrom_track(stream->parent, buffer, len + stream->parent->track->sector_header_size); - memcpy(s, buffer + stream->parent->track->sector_header_size, len); - - stream->parent->track->byte_pos += len; - bytes_read += len; - } - - return bytes_read; + return &stream->cdrom; }