(cheevos) support for identifying Dreamcast CHDs (#13628)

* support for identifying Dreamcast CHDs

* fix copy/paste error
This commit is contained in:
Jamiras 2022-02-15 07:09:43 -07:00 committed by GitHub
parent 0e22b1ec73
commit 5d3654ddbb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 112 additions and 34 deletions

View File

@ -1278,7 +1278,7 @@ static void* rc_hash_handle_chd_open_track(
break; break;
case RC_HASH_CDTRACK_LARGEST: case RC_HASH_CDTRACK_LARGEST:
cdfs_track = cdfs_open_track(path, CHDSTREAM_TRACK_LAST); cdfs_track = cdfs_open_track(path, CHDSTREAM_TRACK_PRIMARY);
break; break;
default: default:
@ -1304,11 +1304,23 @@ static size_t rc_hash_handle_chd_read_sector(
void* buffer, size_t requested_bytes) void* buffer, size_t requested_bytes)
{ {
cdfs_file_t* file = (cdfs_file_t*)track_handle; cdfs_file_t* file = (cdfs_file_t*)track_handle;
uint32_t track_sectors = cdfs_get_num_sectors(file);
sector -= cdfs_get_first_sector(file);
if (sector >= track_sectors)
return 0;
cdfs_seek_sector(file, sector); cdfs_seek_sector(file, sector);
return cdfs_read_file(file, buffer, requested_bytes); return cdfs_read_file(file, buffer, requested_bytes);
} }
static uint32_t rc_hash_handle_chd_first_track_sector(
void* track_handle)
{
cdfs_file_t* file = (cdfs_file_t*)track_handle;
return cdfs_get_first_sector(file);
}
static void rc_hash_handle_chd_close_track(void* track_handle) static void rc_hash_handle_chd_close_track(void* track_handle)
{ {
cdfs_file_t* file = (cdfs_file_t*)track_handle; cdfs_file_t* file = (cdfs_file_t*)track_handle;
@ -1337,6 +1349,7 @@ static void* rc_hash_handle_cd_open_track(
cdreader.open_track = rc_hash_handle_cd_open_track; cdreader.open_track = rc_hash_handle_cd_open_track;
cdreader.read_sector = rc_hash_handle_chd_read_sector; cdreader.read_sector = rc_hash_handle_chd_read_sector;
cdreader.close_track = rc_hash_handle_chd_close_track; cdreader.close_track = rc_hash_handle_chd_close_track;
cdreader.first_track_sector = rc_hash_handle_chd_first_track_sector;
rc_hash_init_custom_cdreader(&cdreader); rc_hash_init_custom_cdreader(&cdreader);
return rc_hash_handle_chd_open_track(path, track); return rc_hash_handle_chd_open_track(path, track);

View File

@ -58,30 +58,31 @@ 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 }
{ }
/* attempt to determine stream_sector_size from file size */
size_t size = intfstream_get_size(track->stream);
if ((size % 2352) == 0) static void cdfs_determine_sector_size_from_file_size(cdfs_track_t* track)
{ {
/* raw tracks use all 2352 bytes and have a 24 byte header */ /* attempt to determine stream_sector_size from file size */
track->stream_sector_size = 2352; size_t size = intfstream_get_size(track->stream);
track->stream_sector_header_size = 24;
} if ((size % 2352) == 0)
else if ((size % 2048) == 0) {
{ /* raw tracks use all 2352 bytes and have a 24 byte header */
/* cooked tracks eliminate all header/footer data */ track->stream_sector_size = 2352;
track->stream_sector_size = 2048; track->stream_sector_header_size = 24;
track->stream_sector_header_size = 0; }
} else if ((size % 2048) == 0)
else if ((size % 2336) == 0) {
{ /* cooked tracks eliminate all header/footer data */
/* MODE 2 format without 16-byte sync data */ track->stream_sector_size = 2048;
track->stream_sector_size = 2336; track->stream_sector_header_size = 0;
track->stream_sector_header_size = 8; }
} else if ((size % 2336) == 0)
} {
/* MODE 2 format without 16-byte sync data */
track->stream_sector_size = 2336;
track->stream_sector_header_size = 8;
} }
} }
@ -109,6 +110,23 @@ void cdfs_seek_sector(cdfs_file_t* file, unsigned int sector)
} }
} }
uint32_t cdfs_get_num_sectors(cdfs_file_t* file)
{
uint32_t frame_size = intfstream_get_frame_size(file->track->stream);
if (frame_size == 0)
{
frame_size = file->track->stream_sector_size;
if (frame_size == 0)
frame_size = 1; /* prevent divide by 0 error if sector size is unknown */
}
return intfstream_get_size(file->track->stream) / frame_size;
}
uint32_t cdfs_get_first_sector(cdfs_file_t* file)
{
return file->track->first_sector_index;
}
static int cdfs_find_file(cdfs_file_t* file, const char* path) static int cdfs_find_file(cdfs_file_t* file, const char* path)
{ {
size_t path_length; size_t path_length;
@ -356,7 +374,7 @@ static void cdfs_skip_spaces(const char** ptr)
} }
static cdfs_track_t* cdfs_wrap_stream( static cdfs_track_t* cdfs_wrap_stream(
intfstream_t* stream, unsigned first_sector_offset) intfstream_t* stream, unsigned first_sector_offset, unsigned first_sector_index)
{ {
cdfs_track_t* track = NULL; cdfs_track_t* track = NULL;
@ -367,6 +385,7 @@ static cdfs_track_t* cdfs_wrap_stream(
calloc(1, sizeof(*track)); calloc(1, sizeof(*track));
track->stream = stream; track->stream = stream;
track->first_sector_offset = first_sector_offset; track->first_sector_offset = first_sector_offset;
track->first_sector_index = first_sector_index;
cdfs_determine_sector_size(track); cdfs_determine_sector_size(track);
@ -507,9 +526,12 @@ static cdfs_track_t* cdfs_open_cue_track(
if (string_is_empty(track_path)) if (string_is_empty(track_path))
return NULL; return NULL;
/* NOTE: previous_index_sector_offset will only be valid if all tracks are in the same BIN file.
* Otherwise, we need to determine how many tracks are in each previous BIN file, which is not
* stored in the CUE file. This will affect cdfs_get_first_sector, which luckily isn't used much. */
track = cdfs_wrap_stream(intfstream_open_file( track = cdfs_wrap_stream(intfstream_open_file(
track_path, RETRO_VFS_FILE_ACCESS_READ, track_path, RETRO_VFS_FILE_ACCESS_READ,
RETRO_VFS_FILE_ACCESS_HINT_NONE), track_offset); RETRO_VFS_FILE_ACCESS_HINT_NONE), track_offset, previous_index_sector_offset);
if (track && track->stream_sector_size == 0) if (track && track->stream_sector_size == 0)
{ {
@ -537,7 +559,8 @@ static cdfs_track_t* cdfs_open_chd_track(const char* path, int32_t track_index)
return NULL; return NULL;
track = cdfs_wrap_stream(intf_stream, track = cdfs_wrap_stream(intf_stream,
intfstream_get_offset_to_start(intf_stream)); intfstream_get_offset_to_start(intf_stream),
intfstream_get_first_sector(intf_stream));
if (track && track->stream_sector_header_size == 0) if (track && track->stream_sector_header_size == 0)
{ {
@ -601,11 +624,15 @@ cdfs_track_t* cdfs_open_raw_track(const char* path)
intfstream_t* file = intfstream_open_file(path, intfstream_t* file = intfstream_open_file(path,
RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE); RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE);
track = cdfs_wrap_stream(file, 0); track = cdfs_wrap_stream(file, 0, 0);
if (track != NULL && track->stream_sector_size == 0) if (track != NULL && track->stream_sector_size == 0)
{ {
cdfs_close_track(track); cdfs_determine_sector_size_from_file_size(track);
track = NULL; if (track->stream_sector_size == 0)
{
cdfs_close_track(track);
track = NULL;
}
} }
} }
else else

View File

@ -37,6 +37,7 @@ typedef struct cdfs_track_t
unsigned int stream_sector_size; unsigned int stream_sector_size;
unsigned int stream_sector_header_size; unsigned int stream_sector_header_size;
unsigned int first_sector_offset; unsigned int first_sector_offset;
unsigned int first_sector_index;
} cdfs_track_t; } cdfs_track_t;
typedef struct cdfs_file_t typedef struct cdfs_file_t
@ -70,6 +71,10 @@ int64_t cdfs_seek(cdfs_file_t* file, int64_t offset, int whence);
void cdfs_seek_sector(cdfs_file_t* file, unsigned int sector); void cdfs_seek_sector(cdfs_file_t* file, unsigned int sector);
uint32_t cdfs_get_num_sectors(cdfs_file_t* file);
uint32_t cdfs_get_first_sector(cdfs_file_t* file);
/* opens the specified track in a CD or virtual CD file - the resulting stream should be passed to /* opens the specified track in a CD or virtual CD file - the resulting stream should be passed to
* cdfs_open_file to get access to a file within the CD. * cdfs_open_file to get access to a file within the CD.
* *

View File

@ -61,6 +61,8 @@ uint32_t chdstream_get_track_start(chdstream_t* stream);
uint32_t chdstream_get_frame_size(chdstream_t* stream); uint32_t chdstream_get_frame_size(chdstream_t* stream);
uint32_t chdstream_get_first_track_sector(chdstream_t* stream);
RETRO_END_DECLS RETRO_END_DECLS
#endif #endif

View File

@ -106,6 +106,8 @@ uint32_t intfstream_get_offset_to_start(intfstream_internal_t *intf);
uint32_t intfstream_get_frame_size(intfstream_internal_t *intf); uint32_t intfstream_get_frame_size(intfstream_internal_t *intf);
uint32_t intfstream_get_first_sector(intfstream_internal_t* intf);
bool intfstream_is_compressed(intfstream_internal_t *intf); bool intfstream_is_compressed(intfstream_internal_t *intf);
bool intfstream_get_crc(intfstream_internal_t *intf, uint32_t *crc); bool intfstream_get_crc(intfstream_internal_t *intf, uint32_t *crc);

View File

@ -163,10 +163,7 @@ chdstream_find_special_track(chd_file *fd, int32_t track, metadata_t *meta)
if (!chdstream_find_track_number(fd, i, &iter)) if (!chdstream_find_track_number(fd, i, &iter))
{ {
if (track == CHDSTREAM_TRACK_LAST && i > 1) if (track == CHDSTREAM_TRACK_LAST && i > 1)
{ return chdstream_find_track_number(fd, i - 1, meta);
*meta = iter;
return true;
}
if (track == CHDSTREAM_TRACK_PRIMARY && largest_track != 0) if (track == CHDSTREAM_TRACK_PRIMARY && largest_track != 0)
return chdstream_find_track_number(fd, largest_track, meta); return chdstream_find_track_number(fd, largest_track, meta);
@ -450,3 +447,22 @@ uint32_t chdstream_get_frame_size(chdstream_t *stream)
{ {
return stream->frame_size; return stream->frame_size;
} }
uint32_t chdstream_get_first_track_sector(chdstream_t* stream)
{
uint32_t i;
metadata_t meta;
uint32_t frame_offset = 0;
uint32_t sector_offset = 0;
for (i = 0; chdstream_get_meta(stream->chd, i, &meta); ++i)
{
if (stream->track_frame == frame_offset)
return sector_offset;
sector_offset += meta.frames;
frame_offset += meta.frames + meta.extra;
}
return 0;
}

View File

@ -604,6 +604,19 @@ uint32_t intfstream_get_frame_size(intfstream_internal_t *intf)
return 0; return 0;
} }
uint32_t intfstream_get_first_sector(intfstream_internal_t* intf)
{
if (intf)
{
#ifdef HAVE_CHD
if (intf->type == INTFSTREAM_CHD)
return chdstream_get_first_track_sector(intf->chd.fp);
#endif
}
return 0;
}
bool intfstream_is_compressed(intfstream_internal_t *intf) bool intfstream_is_compressed(intfstream_internal_t *intf)
{ {
if (!intf) if (!intf)