# HG changeset patch # User Michael Pavone # Date 1643695638 28800 # Node ID 3f29e272652286e6930c0736fe8ec838f931a771 # Parent 983f57d08eff052f53d2447d10c0a8d267bd922c Added basic support for ISO images for games that only have a data track diff -r 983f57d08eff -r 3f29e2726522 blastem.c --- a/blastem.c Mon Jan 31 19:05:54 2022 -0800 +++ b/blastem.c Mon Jan 31 22:07:18 2022 -0800 @@ -188,11 +188,18 @@ free(ext); return load_media_zip(filename, dst); } + if (ext && !strcasecmp(ext, "iso")) { + if (stype) { + *stype = SYSTEM_SEGACD; + } + return make_iso_media(dst, filename); + } free(ext); ROMFILE f = romopen(filename, "rb"); if (!f) { return 0; } + if (sizeof(header) != romread(header, 1, sizeof(header), f)) { fatal_error("Error reading from %s\n", filename); } @@ -248,15 +255,8 @@ return ret; } - - int break_on_sync = 0; char *save_state_path; - - - - - char * save_filename; system_header *current_system; system_header *menu_system; diff -r 983f57d08eff -r 3f29e2726522 cdd_mcu.c --- a/cdd_mcu.c Mon Jan 31 19:05:54 2022 -0800 +++ b/cdd_mcu.c Mon Jan 31 22:07:18 2022 -0800 @@ -39,10 +39,12 @@ context->next_int_cycle = CYCLE_NEVER; context->last_subcode_cycle = CYCLE_NEVER; context->last_nibble_cycle = CYCLE_NEVER; + context->last_byte_cycle = CYCLE_NEVER; context->requested_format = SF_NOTREADY; context->media = media; context->current_status_nibble = -1; context->current_cmd_nibble = -1; + context->current_sector_byte = -1; } enum { @@ -111,24 +113,7 @@ handle_seek(context); if (!context->seeking) { context->head_pba++; - uint32_t lba = context->head_pba - LEADIN_SECTORS; - for (uint32_t i = 0; i < context->media->num_tracks; i++) - { - if (lba < context->media->tracks[i].fake_pregap) { - context->in_fake_pregap = 1; - break; - } - lba -= context->media->tracks[i].fake_pregap; - if (lba < context->media->tracks[i].start_lba) { - context->in_fake_pregap = 1; - break; - } - if (lba < context->media->tracks[i].end_lba) { - fseek(context->media->f, lba * 2352, SEEK_SET); - context->in_fake_pregap = 0; - break; - } - } + context->media->seek(context->media, context->head_pba - LEADIN_SECTORS); } break; case DS_PAUSE: @@ -523,28 +508,7 @@ } } if (context->cycle >= next_byte) { - uint8_t byte; - if (context->in_fake_pregap) { - if (!context->current_sector_byte || (context->current_sector_byte >= 16)) { - byte = 0; - //TODO: error detection and correction bytes - } else if (context->current_sector_byte < 12) { - byte = 0xFF; - } else if (context->current_sector_byte == 12) { - uint32_t minute = ((context->head_pba - LEADIN_SECTORS) / 75) / 60; - byte = (minute % 10) | ((minute / 10 ) << 4); - } else if (context->current_sector_byte == 13) { - uint32_t seconds = ((context->head_pba - LEADIN_SECTORS) / 75) % 60; - byte = (seconds % 10) | ((seconds / 10 ) << 4); - } else if (context->current_sector_byte == 14) { - uint32_t frames = (context->head_pba - LEADIN_SECTORS) % 75; - byte = (frames % 10) | ((frames / 10 ) << 4); - } else { - byte = 1; - } - } else { - byte = fgetc(context->media->f); - } + uint8_t byte = context->media->read(context->media, context->current_sector_byte); lc8951_write_byte(cdc, cd_block_to_mclks(context->cycle), context->current_sector_byte++, byte); context->last_byte_cycle = context->cycle; if (context->current_sector_byte == 2352) { diff -r 983f57d08eff -r 3f29e2726522 cue.c --- 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; +} diff -r 983f57d08eff -r 3f29e2726522 cue.h --- a/cue.h Mon Jan 31 19:05:54 2022 -0800 +++ b/cue.h Mon Jan 31 22:07:18 2022 -0800 @@ -2,5 +2,6 @@ #define CUE_H_ uint8_t parse_cue(system_media *media); +uint32_t make_iso_media(system_media *media, const char *filename); #endif //CUE_H_ diff -r 983f57d08eff -r 3f29e2726522 system.h --- a/system.h Mon Jan 31 19:05:54 2022 -0800 +++ b/system.h Mon Jan 31 22:07:18 2022 -0800 @@ -98,6 +98,9 @@ track_type type; } track_info; +typedef void (*seek_fun)(system_media *media, uint32_t sector); +typedef uint8_t (*read_fun)(system_media *media, uint32_t offset); + struct system_media { void *buffer; char *dir; @@ -106,9 +109,13 @@ system_media *chain; track_info *tracks; FILE *f; + seek_fun seek; + read_fun read; uint32_t num_tracks; uint32_t size; + uint32_t cur_sector; media_type type; + uint8_t in_fake_pregap; }; #define OPT_ADDRESS_LOG (1U << 31U)