diff --git a/libretro-common/formats/cdfs/cdfs.c b/libretro-common/formats/cdfs/cdfs.c index 2f5ce15001..5f77af6e9e 100644 --- a/libretro-common/formats/cdfs/cdfs.c +++ b/libretro-common/formats/cdfs/cdfs.c @@ -12,8 +12,7 @@ static void cdfs_determine_sector_size(cdfs_track_t* track) { uint8_t buffer[32]; - int64_t stream_size; - const int toc_sector = track->pregap_sectors + 16; + const int toc_sector = 16; /* MODE information is normally found in the CUE sheet, but we can try to determine it from the raw data. * @@ -28,7 +27,7 @@ static void cdfs_determine_sector_size(cdfs_track_t* track) */ /* The boot record or primary volume descriptor is always at sector 16 and will contain a "CD001" marker */ - intfstream_seek(track->stream, toc_sector * 2352, SEEK_SET); + intfstream_seek(track->stream, toc_sector * 2352 + track->first_sector_offset, SEEK_SET); if (intfstream_read(track->stream, buffer, sizeof(buffer)) < sizeof(buffer)) return; @@ -59,34 +58,12 @@ static void cdfs_determine_sector_size(cdfs_track_t* track) track->stream_sector_size = 2352; track->stream_sector_header_size = 16; } - else - { - /* no recognizable header - attempt to determine sector size from stream size */ - stream_size = intfstream_get_size(track->stream); - - if ((stream_size % 2352) == 0) - { - /* audio tracks use all 2352 bytes without a header */ - track->stream_sector_size = 2352; - } - else if ((stream_size % 2048) == 0) - { - /* cooked tracks eliminate all header/footer data */ - track->stream_sector_size = 2048; - } - else if ((stream_size % 2336) == 0) - { - /* MODE 2 format without 16-byte sync data */ - track->stream_sector_size = 2336; - track->stream_sector_header_size = 8; - } - } } } static void cdfs_seek_track_sector(cdfs_track_t* track, unsigned int sector) { - intfstream_seek(track->stream, (sector + track->pregap_sectors) * track->stream_sector_size + track->stream_sector_header_size, SEEK_SET); + intfstream_seek(track->stream, sector * track->stream_sector_size + track->stream_sector_header_size + track->first_sector_offset, SEEK_SET); } void cdfs_seek_sector(cdfs_file_t* file, unsigned int sector) @@ -155,8 +132,7 @@ static int cdfs_find_file(cdfs_file_t* file, const char* path) strncasecmp((const char*)(tmp + 33), path, path_length) == 0) { /* the file size is in bytes 10-13 of the record */ - if (!slash) - file->size = tmp[10] | (tmp[11] << 8) | (tmp[12] << 16) | (tmp[13] << 24); + file->size = tmp[10] | (tmp[11] << 8) | (tmp[12] << 16) | (tmp[13] << 24); /* the file contents are in the sector identified in bytes 2-4 of the record */ sector = tmp[2] | (tmp[3] << 8) | (tmp[4] << 16); @@ -342,7 +318,7 @@ static void cdfs_skip_spaces(const char** ptr) ++(*ptr); } -static cdfs_track_t* cdfs_wrap_stream(intfstream_t* stream, unsigned pregap_sectors) +static cdfs_track_t* cdfs_wrap_stream(intfstream_t* stream, unsigned first_sector_offset) { cdfs_track_t* track; @@ -351,7 +327,7 @@ static cdfs_track_t* cdfs_wrap_stream(intfstream_t* stream, unsigned pregap_sect track = (cdfs_track_t*)calloc(1, sizeof(*track)); track->stream = stream; - track->pregap_sectors = pregap_sectors; + track->first_sector_offset = first_sector_offset; cdfs_determine_sector_size(track); return track; } @@ -363,11 +339,15 @@ static cdfs_track_t* cdfs_open_cue_track(const char* path, unsigned int track_in int found_track = 0; char current_track_path[PATH_MAX_LENGTH] = {0}; char track_path[PATH_MAX_LENGTH] = {0}; - unsigned int pregap_sectors = 0; + unsigned int sector_size = 0; + unsigned int previous_sector_size = 0; + unsigned int previous_index_sector_offset= 0; + unsigned int track_offset = 0; intfstream_t *cue_stream = intfstream_open_file(path, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE); int64_t stream_size = intfstream_get_size(cue_stream); char *cue_contents = (char*)malloc(stream_size + 1); - + cdfs_track_t* track = NULL; + if (!cue_contents) { intfstream_close(cue_stream); @@ -410,6 +390,10 @@ static cdfs_track_t* cdfs_open_cue_track(const char* path, unsigned int track_in memcpy(current_track_path, file, file_end - file); current_track_path[file_end - file] = '\0'; } + + previous_sector_size = 0; + previous_index_sector_offset = 0; + track_offset = 0; } else if (!strncasecmp(line, "TRACK", 5)) { @@ -419,58 +403,60 @@ static cdfs_track_t* cdfs_open_cue_track(const char* path, unsigned int track_in cdfs_skip_spaces(&track); sscanf(track, "%d", &track_number); + while (*track && *track != ' ' && *track != '\n') + ++track; - if (track_index) + previous_sector_size = sector_size; + + cdfs_skip_spaces(&track); + + if (!strncasecmp(track, "MODE", 4)) { - if (track_index == track_number) + /* track_index = 0 means find the first data track */ + if (!track_index || track_index == track_number) found_track = track_number; + + sector_size = atoi(track + 6); } - else /* track_index = 0 means find the first data track */ + else { - while (track[0] && track[0] != ' ' && track[0] != '\t') - track++; - - if (track[0]) - { - cdfs_skip_spaces(&track); - - if (!strncasecmp(track, "MODE", 4)) - found_track = track_number; - } + /* assume AUDIO */ + sector_size = 2352; } } - else if (found_track && !strncasecmp(line, "INDEX", 5)) + else if (!strncasecmp(line, "INDEX", 5)) { + unsigned min = 0, sec = 0, frame = 0; + unsigned index_number = 0; + unsigned sector_offset; const char *index = line + 5; + + cdfs_skip_spaces(&index); + sscanf(index, "%u", &index_number); + while (*index && *index != ' ' && *index != '\n') + ++index; cdfs_skip_spaces(&index); - if (index[0]) + sscanf(index, "%u:%u:%u", &min, &sec, &frame); + sector_offset = ((min * 60) + sec) * 75 + frame; + sector_offset -= previous_index_sector_offset; + track_offset += sector_offset * previous_sector_size; + previous_sector_size = sector_size; + previous_index_sector_offset += sector_offset; + + if (found_track && index_number == 1) { - unsigned index_number = 0; - sscanf(index, "%u", &index_number); - - if (index_number == 1) + if (strstr(current_track_path, "/") || strstr(current_track_path, "\\")) { - unsigned min = 0, sec = 0, frame = 0; - const char* ptr = index; - while (*ptr && *ptr != ' ' && *ptr != '\n') - ++ptr; - cdfs_skip_spaces(&ptr); - sscanf(ptr, "%u:%u:%u", &min, &sec, &frame); - pregap_sectors = ((min * 60) + sec) * 75 + frame; - - if (strstr(current_track_path, "/") || strstr(current_track_path, "\\")) - { - strncpy(track_path, current_track_path, sizeof(track_path)); - } - else - { - fill_pathname_basedir(track_path, path, sizeof(track_path)); - strlcat(track_path, current_track_path, sizeof(track_path)); - } - - break; + strncpy(track_path, current_track_path, sizeof(track_path)); } + else + { + fill_pathname_basedir(track_path, path, sizeof(track_path)); + strlcat(track_path, current_track_path, sizeof(track_path)); + } + + break; } } } @@ -480,7 +466,18 @@ static cdfs_track_t* cdfs_open_cue_track(const char* path, unsigned int track_in if (string_is_empty(track_path)) return NULL; - return cdfs_wrap_stream(intfstream_open_file(track_path, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE), pregap_sectors); + track = cdfs_wrap_stream(intfstream_open_file(track_path, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE), track_offset); + if (track && track->stream_sector_size == 0) + { + track->stream_sector_size = sector_size; + + if (sector_size == 2352) + track->stream_sector_header_size = 16; + else if (sector_size == 2336) + track->stream_sector_header_size = 8; + } + + return track; } #ifdef HAVE_CHD @@ -488,19 +485,23 @@ static cdfs_track_t* cdfs_open_chd_track(const char* path, int32_t track_index) { intfstream_t* intf_stream; cdfs_track_t* track; - unsigned int pregap_sectors; intf_stream = intfstream_open_chd_track(path, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE, track_index); if (!intf_stream) return NULL; - pregap_sectors = intfstream_get_chd_pregap(intf_stream); + track = cdfs_wrap_stream(intf_stream, intfstream_get_offset_to_start(intf_stream)); - track = cdfs_wrap_stream(intf_stream, pregap_sectors); + if (track && track->stream_sector_header_size == 0) + { + track->stream_sector_size = intfstream_get_frame_size(intf_stream); + + if (track->stream_sector_size == 2352) + track->stream_sector_header_size = 16; + else if (track->stream_sector_size == 2336) + track->stream_sector_header_size = 8; + } - /* CHD removes the markers from the header, so we can't detect the header size, just assume its 16 bytes */ - if (track->stream_sector_header_size == 0) - track->stream_sector_header_size = 16; return track; } #endif diff --git a/libretro-common/include/formats/cdfs.h b/libretro-common/include/formats/cdfs.h index b5d7a90f04..7c1df5c268 100644 --- a/libretro-common/include/formats/cdfs.h +++ b/libretro-common/include/formats/cdfs.h @@ -36,7 +36,7 @@ typedef struct cdfs_track_t intfstream_t* stream; unsigned int stream_sector_size; unsigned int stream_sector_header_size; - unsigned int pregap_sectors; + unsigned int first_sector_offset; } cdfs_track_t; typedef struct cdfs_file_t diff --git a/libretro-common/include/streams/chd_stream.h b/libretro-common/include/streams/chd_stream.h index 3b0ac4e131..a14979eedb 100644 --- a/libretro-common/include/streams/chd_stream.h +++ b/libretro-common/include/streams/chd_stream.h @@ -57,7 +57,9 @@ int64_t chdstream_seek(chdstream_t *stream, int64_t offset, int whence); ssize_t chdstream_get_size(chdstream_t *stream); -uint32_t chdstream_get_pregap(chdstream_t* stream); +uint32_t chdstream_get_track_start(chdstream_t* stream); + +uint32_t chdstream_get_frame_size(chdstream_t* stream); RETRO_END_DECLS diff --git a/libretro-common/include/streams/interface_stream.h b/libretro-common/include/streams/interface_stream.h index 58371e2ca0..fcb2c5c767 100644 --- a/libretro-common/include/streams/interface_stream.h +++ b/libretro-common/include/streams/interface_stream.h @@ -96,7 +96,9 @@ int64_t intfstream_get_size(intfstream_internal_t *intf); int intfstream_flush(intfstream_internal_t *intf); -uint32_t intfstream_get_chd_pregap(intfstream_internal_t *intf); +uint32_t intfstream_get_offset_to_start(intfstream_internal_t *intf); + +uint32_t intfstream_get_frame_size(intfstream_internal_t *intf); intfstream_t* intfstream_open_file(const char *path, unsigned mode, unsigned hints); diff --git a/libretro-common/streams/chd_stream.c b/libretro-common/streams/chd_stream.c index 3117b57963..ca7b8ab343 100644 --- a/libretro-common/streams/chd_stream.c +++ b/libretro-common/streams/chd_stream.c @@ -254,9 +254,8 @@ chdstream_t *chdstream_open(const char *path, int32_t track) stream->chd = chd; stream->frames_per_hunk = hd->hunkbytes / hd->unitbytes; stream->track_frame = meta.frame_offset; - stream->track_start = (size_t) pregap * stream->frame_size; - stream->track_end = stream->track_start + - (size_t) meta.frames * stream->frame_size; + stream->track_start = (size_t)pregap * stream->frame_size; + stream->track_end = stream->track_start + (size_t)meta.frames * stream->frame_size; stream->offset = 0; stream->hunknum = -1; @@ -426,10 +425,10 @@ int64_t chdstream_seek(chdstream_t *stream, int64_t offset, int whence) ssize_t chdstream_get_size(chdstream_t *stream) { - return stream->track_end; + return stream->track_end - stream->track_start; } -uint32_t chdstream_get_pregap(chdstream_t *stream) +uint32_t chdstream_get_track_start(chdstream_t *stream) { metadata_t meta; uint32_t frame_offset = 0; @@ -438,10 +437,15 @@ uint32_t chdstream_get_pregap(chdstream_t *stream) for (i = 0; chdstream_get_meta(stream->chd, i, &meta); ++i) { if (stream->track_frame == frame_offset) - return meta.pregap; + return meta.pregap * stream->frame_size; frame_offset += meta.frames + meta.extra; } return 0; } + +uint32_t chdstream_get_frame_size(chdstream_t *stream) +{ + return stream->frame_size; +} diff --git a/libretro-common/streams/interface_stream.c b/libretro-common/streams/interface_stream.c index 752e23b5ee..bddabb2c12 100644 --- a/libretro-common/streams/interface_stream.c +++ b/libretro-common/streams/interface_stream.c @@ -421,12 +421,28 @@ void intfstream_putc(intfstream_internal_t *intf, int c) } } -uint32_t intfstream_get_chd_pregap(intfstream_internal_t *intf) +uint32_t intfstream_get_offset_to_start(intfstream_internal_t *intf) { + if (intf) + { #ifdef HAVE_CHD - if (intf->type == INTFSTREAM_CHD) - return chdstream_get_pregap(intf->chd.fp); + if (intf->type == INTFSTREAM_CHD) + return chdstream_get_track_start(intf->chd.fp); #endif + } + + return 0; +} + +uint32_t intfstream_get_frame_size(intfstream_internal_t *intf) +{ + if (intf) + { +#ifdef HAVE_CHD + if (intf->type == INTFSTREAM_CHD) + return chdstream_get_frame_size(intf->chd.fp); +#endif + } return 0; }