Mercurial > repos > blastem
diff system.c @ 2545:c076a96f1668
Get CD titles sort of working in libretro target
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Thu, 02 Jan 2025 23:02:52 -0800 |
parents | 8cf7cadc17ee |
children | c30f0a288ccf |
line wrap: on
line diff
--- a/system.c Thu Nov 28 23:44:36 2024 -0800 +++ b/system.c Thu Jan 02 23:02:52 2025 -0800 @@ -8,6 +8,250 @@ #include "coleco.h" #include "paths.h" #include "util.h" +#include "cdimage.h" + +#define SMD_HEADER_SIZE 512 +#define SMD_MAGIC1 0x03 +#define SMD_MAGIC2 0xAA +#define SMD_MAGIC3 0xBB +#define SMD_BLOCK_SIZE 0x4000 + +#ifdef DISABLE_ZLIB +#define ROMFILE FILE* +#define romopen fopen +#define romread fread +#define romseek fseek +#define romgetc fgetc +#define romclose fclose +#else +#include "zlib/zlib.h" +#define ROMFILE gzFile +#define romopen gzopen +#define romread gzfread +#define romseek gzseek +#define romgetc gzgetc +#define romclose gzclose +#endif + +uint16_t *process_smd_block(uint16_t *dst, uint8_t *src, size_t bytes) +{ + for (uint8_t *low = src, *high = (src+bytes/2), *end = src+bytes; high < end; high++, low++) { + *(dst++) = *low << 8 | *high; + } + return dst; +} + +int load_smd_rom(ROMFILE f, void **buffer) +{ + uint8_t block[SMD_BLOCK_SIZE]; + romseek(f, SMD_HEADER_SIZE, SEEK_SET); + + size_t filesize = 512 * 1024; + size_t readsize = 0; + uint16_t *dst, *buf; + dst = buf = malloc(filesize); + + + size_t read; + do { + if ((readsize + SMD_BLOCK_SIZE > filesize)) { + filesize *= 2; + buf = realloc(buf, filesize); + dst = buf + readsize/sizeof(uint16_t); + } + read = romread(block, 1, SMD_BLOCK_SIZE, f); + if (read > 0) { + dst = process_smd_block(dst, block, read); + readsize += read; + } + } while(read > 0); + romclose(f); + + *buffer = buf; + + return readsize; +} + +uint8_t is_smd_format(const char *filename, uint8_t *header) +{ + if (header[1] == SMD_MAGIC1 && header[8] == SMD_MAGIC2 && header[9] == SMD_MAGIC3) { + int i; + for (i = 3; i < 8; i++) { + if (header[i] != 0) { + return 0; + } + } + if (i == 8) { + if (header[2]) { + fatal_error("%s is a split SMD ROM which is not currently supported", filename); + } + return 1; + } + } + return 0; +} + +#ifndef IS_LIB +uint32_t load_media_zip(const char *filename, system_media *dst) +{ + static const char *valid_exts[] = {"bin", "md", "gen", "sms", "gg", "rom", "smd", "sg", "sc", "sf7"}; + const uint32_t num_exts = sizeof(valid_exts)/sizeof(*valid_exts); + zip_file *z = zip_open(filename); + if (!z) { + return 0; + } + + for (uint32_t i = 0; i < z->num_entries; i++) + { + char *ext = path_extension(z->entries[i].name); + if (!ext) { + continue; + } + for (uint32_t j = 0; j < num_exts; j++) + { + if (!strcasecmp(ext, valid_exts[j])) { + size_t out_size = nearest_pow2(z->entries[i].size); + dst->buffer = zip_read(z, i, &out_size); + if (dst->buffer) { + if (is_smd_format(z->entries[i].name, dst->buffer)) { + size_t offset; + for (offset = 0; offset + SMD_BLOCK_SIZE + SMD_HEADER_SIZE <= out_size; offset += SMD_BLOCK_SIZE) + { + uint8_t tmp[SMD_BLOCK_SIZE]; + uint8_t *u8dst = dst->buffer; + memcpy(tmp, u8dst + offset + SMD_HEADER_SIZE, SMD_BLOCK_SIZE); + process_smd_block((void *)(u8dst + offset), tmp, SMD_BLOCK_SIZE); + } + out_size = offset; + } + dst->extension = ext; + dst->dir = path_dirname(filename); + if (!dst->dir) { + dst->dir = path_current_dir(); + } + dst->name = basename_no_extension(filename); + dst->size = out_size; + dst->zip = z; + return out_size; + } + } + } + free(ext); + } + zip_close(z); + return 0; +} +#endif + +uint32_t load_media(char * filename, system_media *dst, system_type *stype) +{ + uint8_t header[10]; +#ifndef IS_LIB + if (dst->zip) { + zip_close(dst->zip); + } +#endif + dst->orig_path = filename; + char *ext = path_extension(filename); +#ifndef IS_LIB + if (ext && !strcasecmp(ext, "zip")) { + free(ext); + return load_media_zip(filename, dst); + } +#endif + if (ext && !strcasecmp(ext, "iso")) { + if (stype) { + *stype = SYSTEM_SEGACD; + } + return make_iso_media(dst, filename); + } + + ROMFILE f = romopen(filename, "rb"); + if (!f) { + free(ext); + return 0; + } +#ifndef DISABLE_ZLIB + char *to_free = NULL; + if (!gzdirect(f) && ext && !strcasecmp(ext, "gz")) { + size_t without_gz = strlen(filename) - 2; + to_free = calloc(1, without_gz); + memcpy(to_free, filename, without_gz - 1); + to_free[without_gz - 1] = 0; + free(ext); + filename = to_free; + ext = path_extension(filename); + } +#endif //DISABLE_ZLIB + + if (sizeof(header) != romread(header, 1, sizeof(header), f)) { + fatal_error("Error reading from %s\n", filename); + } + + uint32_t ret = 0; + if (is_smd_format(filename, header)) { + if (stype) { + *stype = SYSTEM_GENESIS; + } + ret = load_smd_rom(f, &dst->buffer); + } + + if (!ret) { + size_t filesize = 512 * 1024; + size_t readsize = sizeof(header); + + char *buf = malloc(filesize); + memcpy(buf, header, readsize); + + size_t read; + do { + read = romread(buf + readsize, 1, filesize - readsize, f); + if (read > 0) { + readsize += read; + if (readsize == filesize) { + int one_more = romgetc(f); + if (one_more >= 0) { + filesize *= 2; + buf = realloc(buf, filesize); + buf[readsize++] = one_more; + } else { + read = 0; + } + } + } + } while (read > 0); + dst->buffer = buf; + ret = (uint32_t)readsize; + } + dst->dir = path_dirname(filename); + if (!dst->dir) { + dst->dir = path_current_dir(); + } + dst->name = basename_no_extension(filename); + dst->extension = ext; + dst->size = ret; + romclose(f); + if (!strcasecmp(dst->extension, "cue")) { + if (parse_cue(dst)) { + if (stype) { + *stype = SYSTEM_SEGACD; + } + } + } else if (!strcasecmp(dst->extension, "toc")) { + if (parse_toc(dst)) { + if (stype) { + *stype = SYSTEM_SEGACD; + } + } + } +#ifndef DISABLE_ZLIB + if (to_free) { + free(to_free); + } +#endif + + return ret; +} uint8_t safe_cmp(char *str, long offset, uint8_t *buffer, long filesize) {