From 15ca7152281225cb2b0684721a51e75984a91c61 Mon Sep 17 00:00:00 2001 From: kub Date: Thu, 4 Mar 2021 20:48:02 +0100 Subject: [PATCH] core, groundwork for chd support still needs some scrutiny, and build integration is missing --- Makefile | 5 + Makefile.libretro | 2 + pico/cart.c | 200 ++++++++++++++++++++++++++++++++++ pico/cd/cd_image.c | 20 ++-- pico/cd/{cue.c => cd_parse.c} | 124 +++++++++++++++++++-- pico/cd/cd_parse.h | 5 + pico/cd/cdd.c | 12 +- pico/cd/cdd.h | 1 + pico/cd/cue.h | 29 ----- pico/media.c | 39 ++++--- pico/pico.h | 35 +++++- pico/sound/sound.c | 3 +- platform/common/common.mak | 2 +- platform/common/emu.c | 4 +- platform/common/menu_pico.c | 2 +- platform/gizmondo/menu.c | 4 +- platform/libretro/libretro.c | 6 +- platform/psp/emu.c | 18 +-- 18 files changed, 411 insertions(+), 100 deletions(-) rename pico/cd/{cue.c => cd_parse.c} (73%) create mode 100644 pico/cd/cd_parse.h delete mode 100644 pico/cd/cue.h diff --git a/Makefile b/Makefile index 7955305d..99bfc6ac 100644 --- a/Makefile +++ b/Makefile @@ -236,6 +236,11 @@ OBJS += platform/common/mp3_minimp3.o endif endif +ifneq (,$(HAVE_LIBCHDR)) +CFLAGS += -DUSE_LIBCHDR -Iplatform/common/libchdr/include +LDFLAGS += -Lplatform/common/libchdr -lchdr +endif + ifeq "$(PLATFORM_ZLIB)" "1" # zlib OBJS += zlib/gzio.o zlib/inffast.o zlib/inflate.o zlib/inftrees.o zlib/trees.o \ diff --git a/Makefile.libretro b/Makefile.libretro index e1d4414d..a7ef0085 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -564,6 +564,8 @@ asm_32xdraw = 0 asm_32xmemory = 0 endif +#HAVE_LIBCHDR = 1 + CFLAGS += $(fpic) ifeq ($(findstring Haiku,$(shell uname -a)),) diff --git a/pico/cart.c b/pico/cart.c index 9d35c04c..702947c5 100644 --- a/pico/cart.c +++ b/pico/cart.c @@ -16,6 +16,11 @@ #include "file_stream_transforms.h" #endif +#if defined(USE_LIBCHDR) +#include "libchdr/chd.h" +#include "libchdr/cdrom.h" +#endif + static int rom_alloc_size; static const char *rom_exts[] = { "bin", "gen", "smd", "iso", "sms", "gg", "sg" }; @@ -102,6 +107,19 @@ struct zip_file { unsigned int pos; }; +#if defined(USE_LIBCHDR) +struct chd_struct { + pm_file file; + int fpos; + int sectorsize; + chd_file *chd; + int unitbytes; + int hunkunits; + u8 *hunk; + int hunknum; +}; +#endif + pm_file *pm_open(const char *path) { pm_file *file = NULL; @@ -228,6 +246,50 @@ cso_failed: if (f != NULL) fclose(f); return NULL; } +#if defined(USE_LIBCHDR) + else if (strcasecmp(ext, "chd") == 0) + { + struct chd_struct *chd = NULL; + chd_file *cf = NULL; + const chd_header *head; + + if (chd_open(path, CHD_OPEN_READ, NULL, &cf) != CHDERR_NONE) + goto chd_failed; + + // sanity check + head = chd_get_header(cf); + if ((head->hunkbytes == 0) || (head->hunkbytes % CD_FRAME_SIZE)) + goto chd_failed; + + chd = calloc(1, sizeof(*chd)); + if (chd == NULL) + goto chd_failed; + chd->hunk = (u8 *)malloc(head->hunkbytes); + if (!chd->hunk) + goto chd_failed; + + chd->chd = cf; + chd->unitbytes = head->unitbytes; + chd->hunkunits = head->hunkbytes / head->unitbytes; + chd->sectorsize = CD_MAX_SECTOR_DATA; // default to RAW mode + + chd->fpos = 0; + chd->hunknum = -1; + + chd->file.file = chd; + chd->file.type = PMT_CHD; + // subchannel data is skipped, remove it from total size + chd->file.size = chd_get_header(cf)->logicalbytes / CD_FRAME_SIZE * CD_MAX_SECTOR_DATA; + strncpy(chd->file.ext, ext, sizeof(chd->file.ext) - 1); + return &chd->file; + +chd_failed: + /* invalid CHD file */ + if (chd != NULL) free(chd); + if (cf != NULL) chd_close(cf); + return NULL; + } +#endif /* not a zip, treat as uncompressed file */ f = fopen(path, "rb"); @@ -255,6 +317,88 @@ cso_failed: return file; } +void pm_sectorsize(int length, pm_file *stream) +{ + // CHD reading needs to know how much binary data is in one data sector(=unit) +#if defined(USE_LIBCHDR) + if (stream->type == PMT_CHD) { + struct chd_struct *chd = stream->file; + chd->sectorsize = length; + if (chd->sectorsize > chd->unitbytes) + elprintf(EL_STATUS|EL_ANOMALY, "cd: sector size %d too large for unit %d", chd->sectorsize, chd->unitbytes); + } +#endif +} + +#if defined(USE_LIBCHDR) +static size_t _pm_read_chd(void *ptr, size_t bytes, pm_file *stream, int is_audio) +{ + int ret = 0; + + if (stream->type == PMT_CHD) { + struct chd_struct *chd = stream->file; + // calculate sector and offset in sector + int sectsz = is_audio ? CD_MAX_SECTOR_DATA : chd->sectorsize; + int sector = chd->fpos / sectsz; + int offset = chd->fpos - (sector * sectsz); + // calculate hunk and sector offset in hunk + int hunknum = sector / chd->hunkunits; + int hunksec = sector - (hunknum * chd->hunkunits); + int hunkofs = hunksec * chd->unitbytes; + + while (bytes != 0) { + // data left in current sector + int len = sectsz - offset; + + // update hunk cache if needed + if (hunknum != chd->hunknum) { + chd_read(chd->chd, hunknum, chd->hunk); + chd->hunknum = hunknum; + } + if (len > bytes) + len = bytes; + +#ifdef CPU_IS_LE + if (is_audio) { + // convert big endian audio samples + u16 *dst = ptr, v; + u8 *src = chd->hunk + hunkofs + offset; + int i; + + for (i = 0; i < len; i += 4) { + v = *src++ << 8; *dst++ = v | *src++; + v = *src++ << 8; *dst++ = v | *src++; + } + } else +#endif + memcpy(ptr, chd->hunk + hunkofs + offset, len); + + // house keeping + ret += len; + chd->fpos += len; + bytes -= len; + + // no need to advance internals if there's no more data to read + if (bytes) { + ptr += len; + offset = 0; + + sector ++; + hunksec ++; + hunkofs += chd->unitbytes; + if (hunksec >= chd->hunkunits) { + hunksec = 0; + hunkofs = 0; + hunknum ++; + } + } + } + } + + return ret; +} +#endif + size_t pm_read(void *ptr, size_t bytes, pm_file *stream) { int ret; @@ -355,12 +499,46 @@ size_t pm_read(void *ptr, size_t bytes, pm_file *stream) index_end = cso->index[block+1]; } } +#if defined(USE_LIBCHDR) + else if (stream->type == PMT_CHD) + { + ret = _pm_read_chd(ptr, bytes, stream, 0); + } +#endif else ret = 0; return ret; } +size_t pm_read_audio(void *ptr, size_t bytes, pm_file *stream) +{ +#if !(CPU_IS_LE) + if (stream->type == PMT_UNCOMPRESSED) + { + // convert little endian audio samples from WAV file + int ret = pm_read(ptr, bytes, stream); + u16 *dst = ptr, v; + u8 *src = ptr; + int i; + + for (i = 0; i < ret; i += 4) { + v = *src++; *dst++ = v | (*src++ << 8); + v = *src++; *dst++ = v | (*src++ << 8); + } + return ret; + } + else +#endif +#if defined(USE_LIBCHDR) + if (stream->type == PMT_CHD) + { + return _pm_read_chd(ptr, bytes, stream, 1); + } +#endif + return pm_read(ptr, bytes, stream); +} + int pm_seek(pm_file *stream, long offset, int whence) { if (stream->type == PMT_UNCOMPRESSED) @@ -421,6 +599,19 @@ int pm_seek(pm_file *stream, long offset, int whence) } return cso->fpos_out; } +#if defined(USE_LIBCHDR) + else if (stream->type == PMT_CHD) + { + struct chd_struct *chd = stream->file; + switch (whence) + { + case SEEK_CUR: chd->fpos += offset; break; + case SEEK_SET: chd->fpos = offset; break; + case SEEK_END: chd->fpos = stream->size - offset; break; + } + return chd->fpos; + } +#endif else return -1; } @@ -446,6 +637,15 @@ int pm_close(pm_file *fp) free(fp->param); fclose(fp->file); } +#if defined(USE_LIBCHDR) + else if (fp->type == PMT_CHD) + { + struct chd_struct *chd = fp->file; + chd_close(chd->chd); + if (chd->hunk) + free(chd->hunk); + } +#endif else ret = EOF; diff --git a/pico/cd/cd_image.c b/pico/cd/cd_image.c index f328be03..530071a6 100644 --- a/pico/cd/cd_image.c +++ b/pico/cd/cd_image.c @@ -9,7 +9,7 @@ #include "../pico_int.h" #include "genplus_macros.h" #include "cdd.h" -#include "cue.h" +#include "cd_parse.h" #ifdef USE_LIBRETRO_VFS #include "file_stream_transforms.h" @@ -90,7 +90,7 @@ int load_cd_image(const char *cd_img_name, int *type) int iso_name_len, missed, cd_img_sectors; char tmp_name[256], tmp_ext[10], tmp_ext_u[10]; track_t *tracks = cdd.toc.tracks; - cue_data_t *cue_data = NULL; + cd_data_t *cue_data = NULL; pm_file *pmf; if (PicoCDLoadProgressCB != NULL) @@ -103,16 +103,21 @@ int load_cd_image(const char *cd_img_name, int *type) if (cue_data != NULL) { cd_img_name = cue_data->tracks[1].fname; *type = cue_data->tracks[1].type; + } else { + cue_data = chd_parse(cd_img_name); + if (cue_data != NULL) + *type = cue_data->tracks[1].type; } pmf = pm_open(cd_img_name); if (pmf == NULL) { if (cue_data != NULL) - cue_destroy(cue_data); + cdparse_destroy(cue_data); return -1; } tracks[0].fd = pmf; + tracks[0].fname = strdup(cd_img_name); if (*type == CT_ISO) cd_img_sectors = pmf->size >>= 11; // size in sectors @@ -131,7 +136,7 @@ int load_cd_image(const char *cd_img_name, int *type) if (cue_data != NULL) { - if (cue_data->tracks[2].fname == NULL) { + if (cue_data->track_count > 1 && cue_data->tracks[2].fname == NULL) { // NULL fname means track2 is in same file as track1 lba = tracks[0].end = cue_data->tracks[2].sector_offset; } @@ -157,6 +162,7 @@ int load_cd_image(const char *cd_img_name, int *type) { // assume raw, ignore header for wav.. tracks[index].fd = f; + tracks[index].fname = strdup(cue_data->tracks[n].fname); tracks[index].offset = cue_data->tracks[n].sector_offset; length = f->size / 2352; } @@ -189,8 +195,8 @@ int load_cd_image(const char *cd_img_name, int *type) tracks[index].end = lba; sprintf_lba(tmp_ext, sizeof(tmp_ext), tracks[index].start); - elprintf(EL_STATUS, "Track %2i: %s %9i AUDIO %s", - n, tmp_ext, length, cue_data->tracks[n].fname); + elprintf(EL_STATUS, "Track %2i: %s %9i AUDIO %s", n, tmp_ext, length, + cue_data->tracks[n].fname ? cue_data->tracks[n].fname : ""); } goto finish; } @@ -269,7 +275,7 @@ finish: PicoCDLoadProgressCB(cd_img_name, 100); if (cue_data != NULL) - cue_destroy(cue_data); + cdparse_destroy(cue_data); return 0; } diff --git a/pico/cd/cue.c b/pico/cd/cd_parse.c similarity index 73% rename from pico/cd/cue.c rename to pico/cd/cd_parse.c index e8174ce1..6ed6335b 100644 --- a/pico/cd/cue.c +++ b/pico/cd/cd_parse.c @@ -8,15 +8,20 @@ #include #include #include -#include "cue.h" #include "../pico_int.h" +#include "cd_parse.h" // #define elprintf(w,f,...) printf(f "\n",##__VA_ARGS__); #ifdef USE_LIBRETRO_VFS #include "file_stream_transforms.h" #endif +#if defined(USE_LIBCHDR) +#include "libchdr/chd.h" +#include "libchdr/cdrom.h" +#endif + #ifdef _MSC_VER #define snprintf _snprintf #endif @@ -75,7 +80,8 @@ static int get_ext(const char *fname, char ext[4], if (len > 0) pos = len; - strcpy(ext, fname + pos + 1); + strncpy(ext, fname + pos + 1, 4/*sizeof(ext)*/-1); + ext[4/*sizeof(ext)*/-1] = '\0'; if (base != NULL) { if (pos + 1 < base_size) @@ -111,15 +117,110 @@ static int file_openable(const char *fname) #define BEGINS(buff,str) (strncmp(buff,str,sizeof(str)-1) == 0) /* note: tracks[0] is not used */ -cue_data_t *cue_parse(const char *fname) +cd_data_t *chd_parse(const char *fname) +{ + cd_data_t *data = NULL; +#if defined(USE_LIBCHDR) + cd_data_t *tmp; + int count = 0, count_alloc = 2; + int sectors = 0; + char metadata[256]; + chd_file *cf = NULL; + + if (fname == NULL || *fname == '\0') + return NULL; + + if (chd_open(fname, CHD_OPEN_READ, NULL, &cf) != CHDERR_NONE) + goto out; + + data = calloc(1, sizeof(*data) + count_alloc * sizeof(cd_track_t)); + if (data == NULL) + goto out; + + // get track info + while (count < CD_MAX_TRACKS) { + int track = 0, frames = 0, pregap = 0, postgap = 0; + char type[16], subtype[16], pgtype[16], pgsub[16]; + type[0] = subtype[0] = pgtype[0] = pgsub[0] = 0; + + // get metadata for track + if (chd_get_metadata(cf, CDROM_TRACK_METADATA2_TAG, count, + metadata, sizeof(metadata), 0, 0, 0) == CHDERR_NONE) { + if (sscanf(metadata, CDROM_TRACK_METADATA2_FORMAT, + &track, &type[0], &subtype[0], &frames, + &pregap, &pgtype[0], &pgsub[0], &postgap) != 8) + break; + } + else if (chd_get_metadata(cf, CDROM_TRACK_METADATA_TAG, count, + metadata, sizeof(metadata), 0, 0, 0) == CHDERR_NONE) { + if (sscanf(metadata, CDROM_TRACK_METADATA_FORMAT, + &track, &type[0], &subtype[0], &frames) != 4) + break; + } + else break; // all tracks completed + + // metadata sanity check + if (track != count + 1 || frames < 0 || pregap < 0) + break; + + // allocate track structure + count ++; + if (count >= count_alloc) { + count_alloc *= 2; + tmp = realloc(data, sizeof(*data) + count_alloc * sizeof(cd_track_t)); + if (tmp == NULL) { + count--; + break; + } + data = tmp; + } + memset(&data->tracks[count], 0, sizeof(data->tracks[0])); + + if (count == 1) { // binary code + data->tracks[count].fname = strdup(fname); + if (!strcmp(type, "MODE1_RAW") || !strcmp(type, "MODE2_RAW")) { + data->tracks[count].type = CT_BIN; + } else if (!strcmp(type, "MODE1") || !strcmp(type, "MODE2_FORM1")) { + data->tracks[count].type = CT_ISO; + } else + break; + } else { // audio + if (strcmp(type, "AUDIO")) + break; + data->tracks[count].type = CT_CHD; + } + + data->tracks[count].pregap = pregap; + if (pgtype[0] != 'V') // VAUDIO includes pregap in file + pregap = 0; + data->tracks[count].sector_offset = sectors + pregap; + data->tracks[count].sector_xlength = frames - pregap; + sectors += (((frames + CD_TRACK_PADDING - 1) / CD_TRACK_PADDING) * CD_TRACK_PADDING); + } + + // check if image id OK, i.e. there are tracks, and length <= 80 min + if (count && sectors < (80*60*75)) { + data->track_count = count; + } else { + free(data); + data = NULL; + } + +out: + if (cf) + chd_close(cf); +#endif + return data; +} + +cd_data_t *cue_parse(const char *fname) { char current_file[256], *current_filep, cue_base[256]; char buff[256], buff2[32], ext[4], *p; int ret, count = 0, count_alloc = 2, pending_pregap = 0; size_t current_filep_size, fname_len; - cue_data_t *data = NULL; + cd_data_t *data = NULL, *tmp; FILE *f = NULL; - void *tmp; if (fname == NULL || (fname_len = strlen(fname)) == 0) return NULL; @@ -156,14 +257,13 @@ cue_data_t *cue_parse(const char *fname) p = strrchr(cue_base, '.'); if (p) p[1] = '\0'; - data = calloc(1, sizeof(*data) + count_alloc * sizeof(cue_track)); + data = calloc(1, sizeof(*data) + count_alloc * sizeof(cd_track_t)); if (data == NULL) goto out; while (!feof(f)) { - tmp = fgets(buff, sizeof(buff), f); - if (tmp == NULL) + if (fgets(buff, sizeof(buff), f) == NULL) break; mystrip(buff); @@ -180,7 +280,7 @@ cue_data_t *cue_parse(const char *fname) count++; if (count >= count_alloc) { count_alloc *= 2; - tmp = realloc(data, sizeof(*data) + count_alloc * sizeof(cue_track)); + tmp = realloc(data, sizeof(*data) + count_alloc * sizeof(cd_track_t)); if (tmp == NULL) { count--; break; @@ -344,7 +444,7 @@ out: } -void cue_destroy(cue_data_t *data) +void cdparse_destroy(cd_data_t *data) { int c; @@ -360,7 +460,7 @@ void cue_destroy(cue_data_t *data) #if 0 int main(int argc, char *argv[]) { - cue_data_t *data = cue_parse(argv[1]); + cd_data_t *data = cue_parse(argv[1]); int c; if (data == NULL) return 1; @@ -370,7 +470,7 @@ int main(int argc, char *argv[]) data->tracks[c].sector_offset / (75*60), data->tracks[c].sector_offset / 75 % 60, data->tracks[c].sector_offset % 75, data->tracks[c].pregap, data->tracks[c].fname); - cue_destroy(data); + cdparse_destroy(data); return 0; } diff --git a/pico/cd/cd_parse.h b/pico/cd/cd_parse.h new file mode 100644 index 00000000..0e1f59e7 --- /dev/null +++ b/pico/cd/cd_parse.h @@ -0,0 +1,5 @@ + +cd_data_t *chd_parse(const char *fname); +cd_data_t *cue_parse(const char *fname); +void cdparse_destroy(cd_data_t *data); + diff --git a/pico/cd/cdd.c b/pico/cd/cdd.c index 81bc23b6..8fa16e18 100644 --- a/pico/cd/cdd.c +++ b/pico/cd/cdd.c @@ -38,7 +38,7 @@ #include "../pico_int.h" #include "genplus_macros.h" -#include "cue.h" +#include "cd_parse.h" #include "cdd.h" #ifdef USE_LIBTREMOR @@ -321,6 +321,7 @@ int cdd_load(const char *filename, int type) ret = (type == CT_BIN) ? 2352 : 2048; if (ret != cdd.sectorSize) elprintf(EL_STATUS|EL_ANOMALY, "cd: type detection mismatch"); + pm_sectorsize(cdd.sectorSize, cdd.toc.tracks[0].fd); /* read CD image header + security code */ pm_read(header + 0x10, 0x200, cdd.toc.tracks[0].fd); @@ -448,6 +449,9 @@ int cdd_unload(void) { pm_close(cdd.toc.tracks[0].fd); cdd.toc.tracks[0].fd = NULL; + if (cdd.toc.tracks[0].fname) + free(cdd.toc.tracks[0].fd); + cdd.toc.tracks[0].fname = NULL; } for (i = 1; i < cdd.toc.last; i++) @@ -466,7 +470,11 @@ int cdd_unload(void) if (Pico_mcd->cdda_type == CT_MP3) fclose(cdd.toc.tracks[i].fd); else - pm_close(cdd.toc.tracks[0].fd); + pm_close(cdd.toc.tracks[i].fd); + cdd.toc.tracks[i].fd = NULL; + if (cdd.toc.tracks[i].fname) + free(cdd.toc.tracks[i].fd); + cdd.toc.tracks[i].fname = NULL; /* detect single file images */ if (cdd.toc.tracks[i+1].fd == cdd.toc.tracks[i].fd) diff --git a/pico/cd/cdd.h b/pico/cd/cdd.h index 4789cdb4..da5b5108 100644 --- a/pico/cd/cdd.h +++ b/pico/cd/cdd.h @@ -60,6 +60,7 @@ /* CD track */ typedef struct { + char *fname; void *fd; #ifdef USE_LIBTREMOR OggVorbis_File vf; diff --git a/pico/cd/cue.h b/pico/cd/cue.h deleted file mode 100644 index 70ade53d..00000000 --- a/pico/cd/cue.h +++ /dev/null @@ -1,29 +0,0 @@ - -typedef enum -{ - CT_UNKNOWN = 0, - CT_ISO = 1, /* 2048 B/sector */ - CT_BIN = 2, /* 2352 B/sector */ - CT_MP3 = 3, - CT_WAV = 4 -} cue_track_type; - -typedef struct -{ - char *fname; - int pregap; /* pregap for current track */ - int sector_offset; /* in current file */ - int sector_xlength; - cue_track_type type; -} cue_track; - -typedef struct -{ - int track_count; - cue_track tracks[0]; -} cue_data_t; - - -cue_data_t *cue_parse(const char *fname); -void cue_destroy(cue_data_t *data); - diff --git a/pico/media.c b/pico/media.c index f9b053bd..1294243a 100644 --- a/pico/media.c +++ b/pico/media.c @@ -8,7 +8,7 @@ #include #include "pico_int.h" -#include "cd/cue.h" +#include "cd/cd_parse.h" unsigned char media_id_header[0x100]; @@ -49,7 +49,7 @@ static int detect_media(const char *fname) return PM_BAD_DETECT; /* don't believe in extensions, except .cue */ - if (strcasecmp(ext, ".cue") == 0) + if (strcasecmp(ext, ".cue") == 0 || strcasecmp(ext, ".chd") == 0) return PM_CD; pmf = pm_open(fname); @@ -129,26 +129,31 @@ int PicoCdCheck(const char *fname_in, int *pregion) pm_file *cd_f; int region = 4; // 1: Japan, 4: US, 8: Europe char ext[5]; - cue_track_type type = CT_UNKNOWN; - cue_data_t *cue_data = NULL; + enum cd_track_type type = CT_UNKNOWN; + cd_data_t *cd_data = NULL; // opens a cue, or searches for one - cue_data = cue_parse(fname_in); - if (cue_data != NULL) { - fname = cue_data->tracks[1].fname; - type = cue_data->tracks[1].type; - } - else { + if (!cd_data && (cd_data = cue_parse(fname_in)) == NULL) { get_ext(fname_in, ext); if (strcasecmp(ext, ".cue") == 0) return -1; } + // opens a chd + if (!cd_data && (cd_data = chd_parse(fname_in)) == NULL) { + get_ext(fname_in, ext); + if (strcasecmp(ext, ".chd") == 0) + return -1; + } - cd_f = pm_open(fname); - if (cue_data != NULL) - cue_destroy(cue_data); + if (cd_data != NULL) { + // 1st track contains the code + fname = cd_data->tracks[1].fname; + type = cd_data->tracks[1].type; + } - if (cd_f == NULL) return 0; // let the upper level handle this + cd_f = pm_open(fname); + cdparse_destroy(cd_data); + if (cd_f == NULL) return CT_UNKNOWN; // let the upper level handle this if (pm_read(buf, 32, cd_f) != 32) { pm_close(cd_f); @@ -198,7 +203,7 @@ enum media_type_e PicoLoadMedia(const char *filename, { const char *rom_fname = filename; enum media_type_e media_type; - enum cd_img_type cd_img_type = CIT_NOT_CD; + enum cd_track_type cd_img_type = CT_UNKNOWN; unsigned char *rom_data = NULL; unsigned int rom_size = 0; pm_file *rom = NULL; @@ -219,7 +224,7 @@ enum media_type_e PicoLoadMedia(const char *filename, { // check for MegaCD image cd_img_type = PicoCdCheck(filename, &cd_region); - if ((int)cd_img_type >= 0 && cd_img_type != CIT_NOT_CD) + if ((int)cd_img_type >= 0 && cd_img_type != CT_UNKNOWN) { // valid CD image, ask frontend for BIOS.. rom_fname = NULL; @@ -290,7 +295,7 @@ enum media_type_e PicoLoadMedia(const char *filename, Pico.m.ncart_in = 0; // insert CD if it was detected - if (cd_img_type != CIT_NOT_CD) { + if (cd_img_type != CT_UNKNOWN) { ret = cdd_load(filename, cd_img_type); if (ret != 0) { PicoCartUnload(); diff --git a/pico/pico.h b/pico/pico.h index b75a0146..5ec67d40 100644 --- a/pico/pico.h +++ b/pico/pico.h @@ -161,7 +161,8 @@ typedef enum { PMT_UNCOMPRESSED = 0, PMT_ZIP, - PMT_CSO + PMT_CSO, + PMT_CHD } pm_type; typedef struct { @@ -172,7 +173,9 @@ typedef struct char ext[4]; } pm_file; pm_file *pm_open(const char *path); +void pm_sectorsize(int length, pm_file *stream); size_t pm_read(void *ptr, size_t bytes, pm_file *stream); +size_t pm_read_audio(void *ptr, size_t bytes, pm_file *stream); int pm_seek(pm_file *stream, long offset, int whence); int pm_close(pm_file *fp); int PicoCartLoad(pm_file *f,unsigned char **prom,unsigned int *psize,int is_sms); @@ -255,14 +258,34 @@ enum media_type_e { PM_CD, }; -enum cd_img_type +enum cd_track_type { - CIT_NOT_CD = 0, - CIT_ISO, - CIT_BIN, - CIT_CUE + CT_UNKNOWN = 0, + // data tracks + CT_ISO = 1, /* 2048 B/sector */ + CT_BIN = 2, /* 2352 B/sector */ + // audio tracks + CT_MP3 = 3, + CT_WAV = 4, + CT_CHD = 5, }; +typedef struct +{ + char *fname; + int pregap; /* pregap for current track */ + int sector_offset; /* in current file */ + int sector_xlength; + enum cd_track_type type; +} cd_track_t; + +typedef struct +{ + int track_count; + cd_track_t tracks[0]; +} cd_data_t; + + enum media_type_e PicoLoadMedia(const char *filename, const char *carthw_cfg_fname, const char *(*get_bios_filename)(int *region, const char *cd_fname), diff --git a/pico/sound/sound.c b/pico/sound/sound.c index ad748688..0807c030 100644 --- a/pico/sound/sound.c +++ b/pico/sound/sound.c @@ -11,7 +11,6 @@ #include "ym2612.h" #include "sn76496.h" #include "../pico_int.h" -#include "../cd/cue.h" #include "mix.h" #include "emu2413/emu2413.h" @@ -266,7 +265,7 @@ static void cdda_raw_update(int *buffer, int length) if (PicoIn.sndRate < 22050 - 100) mult = 4; cdda_bytes *= mult; - ret = pm_read(cdda_out_buffer, cdda_bytes, Pico_mcd->cdda_stream); + ret = pm_read_audio(cdda_out_buffer, cdda_bytes, Pico_mcd->cdda_stream); if (ret < cdda_bytes) { memset((char *)cdda_out_buffer + ret, 0, cdda_bytes - ret); Pico_mcd->cdda_stream = NULL; diff --git a/platform/common/common.mak b/platform/common/common.mak index de1c3d7c..0aabeab6 100644 --- a/platform/common/common.mak +++ b/platform/common/common.mak @@ -99,7 +99,7 @@ endif # CD SRCS_COMMON += $(R)pico/cd/mcd.c $(R)pico/cd/memory.c $(R)pico/cd/sek.c \ $(R)pico/cd/cdc.c $(R)pico/cd/cdd.c $(R)pico/cd/cd_image.c \ - $(R)pico/cd/cue.c $(R)pico/cd/gfx.c $(R)pico/cd/gfx_dma.c \ + $(R)pico/cd/cd_parse.c $(R)pico/cd/gfx.c $(R)pico/cd/gfx_dma.c \ $(R)pico/cd/misc.c $(R)pico/cd/pcm.c # 32X ifneq "$(no_32x)" "1" diff --git a/platform/common/emu.c b/platform/common/emu.c index 089189d5..151fb531 100644 --- a/platform/common/emu.c +++ b/platform/common/emu.c @@ -539,11 +539,11 @@ out: int emu_swap_cd(const char *fname) { - enum cd_img_type cd_type; + enum cd_track_type cd_type; int ret = -1; cd_type = PicoCdCheck(fname, NULL); - if (cd_type != CIT_NOT_CD) + if (cd_type != CT_UNKNOWN) ret = cdd_load(fname, cd_type); if (ret != 0) { menu_update_msg("Load failed, invalid CD image?"); diff --git a/platform/common/menu_pico.c b/platform/common/menu_pico.c index 38adcc27..fc238c30 100644 --- a/platform/common/menu_pico.c +++ b/platform/common/menu_pico.c @@ -40,7 +40,7 @@ static const char *rom_exts[] = { "zip", "bin", "smd", "gen", "md", - "iso", "cso", "cue", + "iso", "cso", "cue", "chd", "32x", "sms", NULL diff --git a/platform/gizmondo/menu.c b/platform/gizmondo/menu.c index 07a2ce7b..cf1f5b48 100644 --- a/platform/gizmondo/menu.c +++ b/platform/gizmondo/menu.c @@ -1577,9 +1577,9 @@ int menu_loop_tray(void) selfname = romsel_loop(curr_path); if (selfname) { int ret = -1; - cd_img_type cd_type; + cd_track_type cd_type; cd_type = emu_cdCheck(NULL, romFileName); - if (cd_type != CIT_NOT_CD) + if (cd_type >= 0 && cd_type != CT_UNKNOWN) ret = Insert_CD(romFileName, cd_type); if (ret != 0) { sprintf(menuErrorMsg, "Load failed, invalid CD image?"); diff --git a/platform/libretro/libretro.c b/platform/libretro/libretro.c index d889fb20..a6fce3e5 100644 --- a/platform/libretro/libretro.c +++ b/platform/libretro/libretro.c @@ -749,7 +749,7 @@ void retro_get_system_info(struct retro_system_info *info) #define _GIT_VERSION "-" GIT_VERSION #endif info->library_version = VERSION _GIT_VERSION; - info->valid_extensions = "bin|gen|smd|md|32x|cue|iso|sms"; + info->valid_extensions = "bin|gen|smd|md|32x|cue|iso|chd|sms"; info->need_fullpath = true; } @@ -1002,7 +1002,7 @@ static unsigned int disk_get_image_index(void) static bool disk_set_image_index(unsigned int index) { - enum cd_img_type cd_type; + enum cd_track_type cd_type; int ret; if (index >= sizeof(disks) / sizeof(disks[0])) @@ -1024,7 +1024,7 @@ static bool disk_set_image_index(unsigned int index) ret = -1; cd_type = PicoCdCheck(disks[index].fname, NULL); - if (cd_type != CIT_NOT_CD) + if (cd_type >= 0 && cd_type != CT_UNKNOWN) ret = cdd_load(disks[index].fname, cd_type); if (ret != 0) { if (log_cb) diff --git a/platform/psp/emu.c b/platform/psp/emu.c index 080784db..016c44d9 100644 --- a/platform/psp/emu.c +++ b/platform/psp/emu.c @@ -30,7 +30,6 @@ #include #include #include -#include #define OSD_FPS_X 432 @@ -744,23 +743,10 @@ void emu_handle_resume(void) // reopen first CD track if (cdd.toc.tracks[0].fd != NULL) { - const char *fname = rom_fname_reload; - int len = strlen(rom_fname_reload); - cue_data_t *cue_data = NULL; - - if (len > 4 && strcasecmp(fname + len - 4, ".cue") == 0) - { - cue_data = cue_parse(rom_fname_reload); - if (cue_data != NULL) - fname = cue_data->tracks[1].fname; - } - - lprintf("emu_HandleResume: reopen %s\n", fname); + lprintf("emu_HandleResume: reopen %s\n", cdd.toc.tracks[0].fname); pm_close(cdd.toc.tracks[0].fd); - cdd.toc.tracks[0].fd = pm_open(fname); + cdd.toc.tracks[0].fd = pm_open(cdd.toc.tracks[0].fname); lprintf("reopen %s\n", cdd.toc.tracks[0].fd != NULL ? "ok" : "failed"); - - if (cue_data != NULL) cue_destroy(cue_data); } mp3_reopen_file(); -- 2.39.5