mirror of
https://github.com/libretro/RetroArch
synced 2025-04-10 15:45:19 +00:00
(cheevos) support for identifying Dreamcast CHDs (#13628)
* support for identifying Dreamcast CHDs * fix copy/paste error
This commit is contained in:
parent
0e22b1ec73
commit
5d3654ddbb
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
*
|
*
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
@ -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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user