Mercurial > repos > blastem
diff cue.c @ 2076:3f29e2726522
Added basic support for ISO images for games that only have a data track
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Mon, 31 Jan 2022 22:07:18 -0800 |
parents | c5323c02dde4 |
children | 5a2b759f6b2d |
line wrap: on
line diff
--- a/cue.c Mon Jan 31 19:05:54 2022 -0800 +++ b/cue.c Mon Jan 31 22:07:18 2022 -0800 @@ -43,6 +43,81 @@ } +static void bin_seek(system_media *media, uint32_t sector) +{ + media->cur_sector = sector; + uint32_t lba = sector; + for (uint32_t i = 0; i < media->num_tracks; i++) + { + if (lba < media->tracks[i].fake_pregap) { + media->in_fake_pregap = 1; + break; + } + lba -= media->tracks[i].fake_pregap; + if (lba < media->tracks[i].start_lba) { + media->in_fake_pregap = 1; + break; + } + if (lba < media->tracks[i].end_lba) { + media->in_fake_pregap = 0; + break; + } + } + if (!media->in_fake_pregap) { + fseek(media->f, lba * 2352, SEEK_SET); + } +} + +static uint8_t fake_read(uint32_t sector, uint32_t offset) +{ + if (!offset || (offset >= 16)) { + return 0; + //TODO: error detection and correction bytes + } else if (offset < 12) { + return 0xFF; + } else if (offset == 12) { + uint32_t minute = (sector / 75) / 60; + return (minute % 10) | ((minute / 10 ) << 4); + } else if (offset == 13) { + uint32_t seconds = (sector / 75) % 60; + return (seconds % 10) | ((seconds / 10 ) << 4); + } else if (offset == 14) { + uint32_t frames = sector % 75; + return (frames % 10) | ((frames / 10 ) << 4); + } else { + return 1; + } +} + +static uint8_t bin_read(system_media *media, uint32_t offset) +{ + if (media->in_fake_pregap) { + return fake_read(media->cur_sector, offset); + } else { + return fgetc(media->f); + } +} + +static void iso_seek(system_media *media, uint32_t sector) +{ + media->cur_sector = sector; + if (sector < (2 * 75)) { + media->in_fake_pregap = 1; + } else { + media->in_fake_pregap = 0; + fseek(media->f, (sector - 2 * 75) * 2048, SEEK_SET); + } +} + +static uint8_t iso_read(system_media *media, uint32_t offset) +{ + if (media->in_fake_pregap || offset < 16 || offset > (2048 + 16)) { + return fake_read(media->cur_sector, offset); + } else { + return fgetc(media->f); + } +} + uint8_t parse_cue(system_media *media) { char *line = media->buffer; @@ -153,8 +228,38 @@ fseek(media->f, 16, SEEK_SET); media->size = fread(media->buffer, 1, 2048, media->f); + media->seek = bin_seek; + media->read = bin_read; } uint8_t valid = tracks > 0 && media->f != NULL; media->type = valid ? MEDIA_CDROM : MEDIA_CART; return valid; } + +uint32_t make_iso_media(system_media *media, const char *filename) +{ + media->f = fopen(filename, "rb"); + if (!media->f) { + return 0; + } + media->buffer = calloc(2048, 1); + media->size = fread(media->buffer, 1, 2048, media->f); + media->num_tracks = 2; + media->tracks = calloc(sizeof(track_info), 2); + media->tracks[0] = (track_info){ + .fake_pregap = 2 * 75, + .start_lba = 0, + .end_lba = file_size(media->f), + .type = TRACK_DATA + }; + media->tracks[1] = (track_info){ + .fake_pregap = 2 * 75, + .start_lba = media->tracks[0].end_lba, + .end_lba = media->tracks[0].end_lba + 2 * 75, + .type = TRACK_DATA + }; + media->type = MEDIA_CDROM; + media->seek = iso_seek; + media->read = iso_read; + return media->size; +}