aboutsummaryrefslogtreecommitdiff
path: root/libpcsxcore
diff options
context:
space:
mode:
Diffstat (limited to 'libpcsxcore')
-rw-r--r--libpcsxcore/cdriso.c122
1 files changed, 122 insertions, 0 deletions
diff --git a/libpcsxcore/cdriso.c b/libpcsxcore/cdriso.c
index 6f59579..fb074e5 100644
--- a/libpcsxcore/cdriso.c
+++ b/libpcsxcore/cdriso.c
@@ -27,6 +27,7 @@
#include <errno.h>
#include <zlib.h>
+#include <chd.h>
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
@@ -93,6 +94,15 @@ static struct {
unsigned int sector_in_blk;
} *compr_img;
+static struct {
+ unsigned char (*buffer)[CD_FRAMESIZE_RAW + SUB_FRAMESIZE];
+ chd_file* chd;
+ const chd_header* header;
+ unsigned int sectors_per_hunk;
+ unsigned int current_hunk;
+ unsigned int sector_in_hunk;
+} *chd_img;
+
int (*cdimg_read_func)(FILE *f, unsigned int base, void *dest, int sector);
char* CALLBACK CDR__getDriveLetter(void);
@@ -1029,6 +1039,78 @@ fail_io:
return -1;
}
+static int handlechd(const char *isofile) {
+ chd_img = calloc(1, sizeof(*chd_img));
+ if (chd_img == NULL)
+ goto fail_io;
+
+ if(chd_open(isofile, CHD_OPEN_READ, NULL, &chd_img->chd) != CHDERR_NONE)
+ goto fail_io;
+
+ chd_img->header = chd_get_header(chd_img->chd);
+
+ chd_img->buffer = malloc(chd_img->header->hunkbytes);
+ if (chd_img->buffer == NULL)
+ goto fail_io;
+
+ chd_img->sectors_per_hunk = chd_img->header->hunkbytes / (CD_FRAMESIZE_RAW + SUB_FRAMESIZE);
+ chd_img->current_hunk = (unsigned int)-1;
+
+ cddaBigEndian = TRUE;
+
+ numtracks = 0;
+ int frame_offset = 0;
+ memset(ti, 0, sizeof(ti));
+
+ while (1)
+ {
+ struct {
+ char type[64];
+ char subtype[32];
+ char pgtype[32];
+ char pgsub[32];
+ uint32_t track;
+ uint32_t frames;
+ uint32_t pregap;
+ uint32_t postgap;
+ } md = {};
+ char meta[256];
+ uint32_t meta_size = 0;
+
+ if (chd_get_metadata(chd_img->chd, CDROM_TRACK_METADATA2_TAG, numtracks, meta, sizeof(meta), &meta_size, NULL, NULL) == CHDERR_NONE)
+ sscanf(meta, CDROM_TRACK_METADATA2_FORMAT, &md.track, md.type, md.subtype, &md.frames, &md.pregap, md.pgtype, md.pgsub, &md.postgap);
+ else if (chd_get_metadata(chd_img->chd, CDROM_TRACK_METADATA_TAG, numtracks, meta, sizeof(meta), &meta_size, NULL, NULL) == CHDERR_NONE)
+ sscanf(meta, CDROM_TRACK_METADATA_FORMAT, &md.track, md.type, md.subtype, &md.frames);
+ else
+ break;
+
+ ti[md.track].type = !strncmp(md.type, "AUDIO", 5) ? CDDA : DATA;
+
+ sec2msf(frame_offset + md.pregap, ti[md.track].start);
+ sec2msf(md.frames, ti[md.track].length);
+
+ if (!strcmp(md.type, md.pgtype))
+ frame_offset += md.pregap;
+
+ ti[md.track].start_offset = frame_offset * CD_FRAMESIZE_RAW;
+
+ frame_offset += (md.frames + 3) & ~3;
+ frame_offset += md.postgap;
+ numtracks++;
+ }
+
+ if (numtracks)
+ return 0;
+
+fail_io:
+ if (chd_img != NULL) {
+ free(chd_img->buffer);
+ free(chd_img);
+ chd_img = NULL;
+ }
+ return -1;
+}
+
// this function tries to get the .sub file of the given .img
static int opensubfile(const char *isoname) {
char subname[MAXPATHLEN];
@@ -1190,6 +1272,30 @@ finish:
return CD_FRAMESIZE_RAW;
}
+static int cdread_chd(FILE *f, unsigned int base, void *dest, int sector)
+{
+ int hunk;
+
+ if (base)
+ sector += base / CD_FRAMESIZE_RAW;
+
+ hunk = sector / chd_img->sectors_per_hunk;
+ chd_img->sector_in_hunk = sector % chd_img->sectors_per_hunk;
+
+ if (hunk == chd_img->current_hunk)
+ goto finish;
+
+ chd_read(chd_img->chd, hunk, chd_img->buffer);
+
+ chd_img->current_hunk = hunk;
+
+finish:
+ if (dest != cdbuffer) // copy avoid HACK
+ memcpy(dest, chd_img->buffer[chd_img->sector_in_hunk],
+ CD_FRAMESIZE_RAW);
+ return CD_FRAMESIZE_RAW;
+}
+
static int cdread_2048(FILE *f, unsigned int base, void *dest, int sector)
{
int ret;
@@ -1209,6 +1315,10 @@ static unsigned char * CALLBACK ISOgetBuffer_compr(void) {
return compr_img->buff_raw[compr_img->sector_in_blk] + 12;
}
+static unsigned char * CALLBACK ISOgetBuffer_chd(void) {
+ return chd_img->buffer[chd_img->sector_in_hunk] + 12;
+}
+
static unsigned char * CALLBACK ISOgetBuffer(void) {
return cdbuffer + 12;
}
@@ -1276,6 +1386,11 @@ static long CALLBACK ISOopen(void) {
CDR_getBuffer = ISOgetBuffer_compr;
cdimg_read_func = cdread_compressed;
}
+ else if (handlechd(GetIsoFile()) == 0) {
+ SysPrintf("[chd]");
+ CDR_getBuffer = ISOgetBuffer_chd;
+ cdimg_read_func = cdread_chd;
+ }
if (!subChanMixed && opensubfile(GetIsoFile()) == 0) {
SysPrintf("[+sub]");
@@ -1364,6 +1479,13 @@ static long CALLBACK ISOclose(void) {
compr_img = NULL;
}
+ if (chd_img != NULL) {
+ chd_close(chd_img->chd);
+ free(chd_img->buffer);
+ free(chd_img);
+ chd_img = NULL;
+ }
+
for (i = 1; i <= numtracks; i++) {
if (ti[i].handle != NULL) {
fclose(ti[i].handle);