mirror of
https://github.com/libretro/RetroArch
synced 2025-04-01 22:20:31 +00:00
proper calculation of offset to track 2 when sector sizes vary
This commit is contained in:
parent
7150d6ef59
commit
3b4e55d0e5
@ -12,8 +12,7 @@
|
|||||||
static void cdfs_determine_sector_size(cdfs_track_t* track)
|
static void cdfs_determine_sector_size(cdfs_track_t* track)
|
||||||
{
|
{
|
||||||
uint8_t buffer[32];
|
uint8_t buffer[32];
|
||||||
int64_t stream_size;
|
const int toc_sector = 16;
|
||||||
const int toc_sector = track->pregap_sectors + 16;
|
|
||||||
|
|
||||||
/* MODE information is normally found in the CUE sheet, but we can try to determine it from the raw data.
|
/* 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 */
|
/* 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))
|
if (intfstream_read(track->stream, buffer, sizeof(buffer)) < sizeof(buffer))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -59,34 +58,12 @@ static void cdfs_determine_sector_size(cdfs_track_t* track)
|
|||||||
track->stream_sector_size = 2352;
|
track->stream_sector_size = 2352;
|
||||||
track->stream_sector_header_size = 16;
|
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)
|
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)
|
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)
|
strncasecmp((const char*)(tmp + 33), path, path_length) == 0)
|
||||||
{
|
{
|
||||||
/* the file size is in bytes 10-13 of the record */
|
/* 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 */
|
/* the file contents are in the sector identified in bytes 2-4 of the record */
|
||||||
sector = tmp[2] | (tmp[3] << 8) | (tmp[4] << 16);
|
sector = tmp[2] | (tmp[3] << 8) | (tmp[4] << 16);
|
||||||
@ -342,7 +318,7 @@ static void cdfs_skip_spaces(const char** ptr)
|
|||||||
++(*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;
|
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 = (cdfs_track_t*)calloc(1, sizeof(*track));
|
||||||
track->stream = stream;
|
track->stream = stream;
|
||||||
track->pregap_sectors = pregap_sectors;
|
track->first_sector_offset = first_sector_offset;
|
||||||
cdfs_determine_sector_size(track);
|
cdfs_determine_sector_size(track);
|
||||||
return track;
|
return track;
|
||||||
}
|
}
|
||||||
@ -363,10 +339,14 @@ static cdfs_track_t* cdfs_open_cue_track(const char* path, unsigned int track_in
|
|||||||
int found_track = 0;
|
int found_track = 0;
|
||||||
char current_track_path[PATH_MAX_LENGTH] = {0};
|
char current_track_path[PATH_MAX_LENGTH] = {0};
|
||||||
char 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);
|
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);
|
int64_t stream_size = intfstream_get_size(cue_stream);
|
||||||
char *cue_contents = (char*)malloc(stream_size + 1);
|
char *cue_contents = (char*)malloc(stream_size + 1);
|
||||||
|
cdfs_track_t* track = NULL;
|
||||||
|
|
||||||
if (!cue_contents)
|
if (!cue_contents)
|
||||||
{
|
{
|
||||||
@ -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);
|
memcpy(current_track_path, file, file_end - file);
|
||||||
current_track_path[file_end - file] = '\0';
|
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))
|
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);
|
cdfs_skip_spaces(&track);
|
||||||
|
|
||||||
sscanf(track, "%d", &track_number);
|
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;
|
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')
|
/* assume AUDIO */
|
||||||
track++;
|
sector_size = 2352;
|
||||||
|
|
||||||
if (track[0])
|
|
||||||
{
|
|
||||||
cdfs_skip_spaces(&track);
|
|
||||||
|
|
||||||
if (!strncasecmp(track, "MODE", 4))
|
|
||||||
found_track = track_number;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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;
|
const char *index = line + 5;
|
||||||
|
|
||||||
|
cdfs_skip_spaces(&index);
|
||||||
|
sscanf(index, "%u", &index_number);
|
||||||
|
while (*index && *index != ' ' && *index != '\n')
|
||||||
|
++index;
|
||||||
cdfs_skip_spaces(&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;
|
if (strstr(current_track_path, "/") || strstr(current_track_path, "\\"))
|
||||||
sscanf(index, "%u", &index_number);
|
|
||||||
|
|
||||||
if (index_number == 1)
|
|
||||||
{
|
{
|
||||||
unsigned min = 0, sec = 0, frame = 0;
|
strncpy(track_path, current_track_path, sizeof(track_path));
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
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))
|
if (string_is_empty(track_path))
|
||||||
return NULL;
|
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
|
#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;
|
intfstream_t* intf_stream;
|
||||||
cdfs_track_t* track;
|
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);
|
intf_stream = intfstream_open_chd_track(path, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE, track_index);
|
||||||
if (!intf_stream)
|
if (!intf_stream)
|
||||||
return NULL;
|
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;
|
return track;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -36,7 +36,7 @@ typedef struct cdfs_track_t
|
|||||||
intfstream_t* stream;
|
intfstream_t* stream;
|
||||||
unsigned int stream_sector_size;
|
unsigned int stream_sector_size;
|
||||||
unsigned int stream_sector_header_size;
|
unsigned int stream_sector_header_size;
|
||||||
unsigned int pregap_sectors;
|
unsigned int first_sector_offset;
|
||||||
} cdfs_track_t;
|
} cdfs_track_t;
|
||||||
|
|
||||||
typedef struct cdfs_file_t
|
typedef struct cdfs_file_t
|
||||||
|
@ -57,7 +57,9 @@ int64_t chdstream_seek(chdstream_t *stream, int64_t offset, int whence);
|
|||||||
|
|
||||||
ssize_t chdstream_get_size(chdstream_t *stream);
|
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
|
RETRO_END_DECLS
|
||||||
|
|
||||||
|
@ -96,7 +96,9 @@ int64_t intfstream_get_size(intfstream_internal_t *intf);
|
|||||||
|
|
||||||
int intfstream_flush(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,
|
intfstream_t* intfstream_open_file(const char *path,
|
||||||
unsigned mode, unsigned hints);
|
unsigned mode, unsigned hints);
|
||||||
|
@ -254,9 +254,8 @@ chdstream_t *chdstream_open(const char *path, int32_t track)
|
|||||||
stream->chd = chd;
|
stream->chd = chd;
|
||||||
stream->frames_per_hunk = hd->hunkbytes / hd->unitbytes;
|
stream->frames_per_hunk = hd->hunkbytes / hd->unitbytes;
|
||||||
stream->track_frame = meta.frame_offset;
|
stream->track_frame = meta.frame_offset;
|
||||||
stream->track_start = (size_t) pregap * stream->frame_size;
|
stream->track_start = (size_t)pregap * stream->frame_size;
|
||||||
stream->track_end = stream->track_start +
|
stream->track_end = stream->track_start + (size_t)meta.frames * stream->frame_size;
|
||||||
(size_t) meta.frames * stream->frame_size;
|
|
||||||
stream->offset = 0;
|
stream->offset = 0;
|
||||||
stream->hunknum = -1;
|
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)
|
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;
|
metadata_t meta;
|
||||||
uint32_t frame_offset = 0;
|
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)
|
for (i = 0; chdstream_get_meta(stream->chd, i, &meta); ++i)
|
||||||
{
|
{
|
||||||
if (stream->track_frame == frame_offset)
|
if (stream->track_frame == frame_offset)
|
||||||
return meta.pregap;
|
return meta.pregap * stream->frame_size;
|
||||||
|
|
||||||
frame_offset += meta.frames + meta.extra;
|
frame_offset += meta.frames + meta.extra;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t chdstream_get_frame_size(chdstream_t *stream)
|
||||||
|
{
|
||||||
|
return stream->frame_size;
|
||||||
|
}
|
||||||
|
@ -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
|
#ifdef HAVE_CHD
|
||||||
if (intf->type == INTFSTREAM_CHD)
|
if (intf->type == INTFSTREAM_CHD)
|
||||||
return chdstream_get_pregap(intf->chd.fp);
|
return chdstream_get_track_start(intf->chd.fp);
|
||||||
#endif
|
#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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user