cdrom: change GetlocP handling
[pcsx_rearmed.git] / libpcsxcore / cdriso.c
index 2a31950..a755a23 100644 (file)
@@ -54,7 +54,6 @@ static FILE *subHandle = NULL;
 
 static boolean subChanMixed = FALSE;
 static boolean subChanRaw = FALSE;
-static boolean subChanMissing = FALSE;
 
 static boolean multifile = FALSE;
 
@@ -93,7 +92,8 @@ static struct {
 } *chd_img;
 #endif
 
-int (*cdimg_read_func)(FILE *f, unsigned int base, void *dest, int sector);
+static int (*cdimg_read_func)(FILE *f, unsigned int base, void *dest, int sector);
+static int (*cdimg_read_sub_func)(FILE *f, int sector);
 
 char* CALLBACK CDR__getDriveLetter(void);
 long CALLBACK CDR__configure(void);
@@ -1070,29 +1070,48 @@ static int opensbifile(const char *isoname) {
 
 static int cdread_normal(FILE *f, unsigned int base, void *dest, int sector)
 {
-       fseek(f, base + sector * CD_FRAMESIZE_RAW, SEEK_SET);
-       return fread(dest, 1, CD_FRAMESIZE_RAW, f);
+       int ret;
+       if (fseek(f, base + sector * CD_FRAMESIZE_RAW, SEEK_SET))
+               goto fail_io;
+       ret = fread(dest, 1, CD_FRAMESIZE_RAW, f);
+       if (ret <= 0)
+               goto fail_io;
+       return ret;
+
+fail_io:
+       // often happens in cdda gaps of a split cue/bin, so not logged
+       //SysPrintf("File IO error %d, base %u, sector %u\n", errno, base, sector);
+       return -1;
 }
 
 static int cdread_sub_mixed(FILE *f, unsigned int base, void *dest, int sector)
 {
        int ret;
 
-       fseek(f, base + sector * (CD_FRAMESIZE_RAW + SUB_FRAMESIZE), SEEK_SET);
+       if (fseek(f, base + sector * (CD_FRAMESIZE_RAW + SUB_FRAMESIZE), SEEK_SET))
+               goto fail_io;
        ret = fread(dest, 1, CD_FRAMESIZE_RAW, f);
+       if (ret <= 0)
+               goto fail_io;
+       return ret;
+
+fail_io:
+       //SysPrintf("File IO error %d, base %u, sector %u\n", errno, base, sector);
+       return -1;
+}
+
+static int cdread_sub_sub_mixed(FILE *f, int sector)
+{
+       if (fseek(f, sector * (CD_FRAMESIZE_RAW + SUB_FRAMESIZE) + CD_FRAMESIZE_RAW, SEEK_SET))
+               goto fail_io;
        if (fread(subbuffer, 1, SUB_FRAMESIZE, f) != SUB_FRAMESIZE)
                goto fail_io;
 
-       if (subChanRaw) DecodeRawSubData();
-       goto done;
+       return SUB_FRAMESIZE;
 
 fail_io:
-#ifndef NDEBUG
-       SysPrintf(_("File IO error in <%s:%s>.\n"), __FILE__, __func__);
-#endif
-
-done:
-       return ret;
+       SysPrintf("subchannel: file IO error %d, sector %u\n", errno, sector);
+       return -1;
 }
 
 static int uncompress2_pcsx(void *out, unsigned long *out_size, void *in, unsigned long in_size)
@@ -1201,8 +1220,7 @@ static int cdread_chd(FILE *f, unsigned int base, void *dest, int sector)
 {
        int hunk;
 
-       if (base)
-               sector += base;
+       sector += base;
 
        hunk = sector / chd_img->sectors_per_hunk;
        chd_img->sector_in_hunk = sector % chd_img->sectors_per_hunk;
@@ -1216,14 +1234,28 @@ static int cdread_chd(FILE *f, unsigned int base, void *dest, int sector)
        if (dest != cdbuffer) // copy avoid HACK
                memcpy(dest, chd_img->buffer[chd_img->sector_in_hunk],
                        CD_FRAMESIZE_RAW);
-       if (subChanMixed) {
-               memcpy(subbuffer, chd_img->buffer[chd_img->sector_in_hunk] + CD_FRAMESIZE_RAW,
-                       SUB_FRAMESIZE);
-               if (subChanRaw)
-                       DecodeRawSubData();
-       }
        return CD_FRAMESIZE_RAW;
 }
+
+static int cdread_sub_chd(FILE *f, int sector)
+{
+       int hunk;
+
+       if (!subChanMixed)
+               return -1;
+
+       hunk = sector / chd_img->sectors_per_hunk;
+       chd_img->sector_in_hunk = sector % chd_img->sectors_per_hunk;
+
+       if (hunk != chd_img->current_hunk)
+       {
+               chd_read(chd_img->chd, hunk, chd_img->buffer);
+               chd_img->current_hunk = hunk;
+       }
+
+       memcpy(subbuffer, chd_img->buffer[chd_img->sector_in_hunk] + CD_FRAMESIZE_RAW, SUB_FRAMESIZE);
+       return SUB_FRAMESIZE;
+}
 #endif
 
 static int cdread_2048(FILE *f, unsigned int base, void *dest, int sector)
@@ -1298,6 +1330,7 @@ static long CALLBACK ISOopen(void) {
 
        CDR_getBuffer = ISOgetBuffer;
        cdimg_read_func = cdread_normal;
+       cdimg_read_sub_func = NULL;
 
        if (parsetoc(GetIsoFile()) == 0) {
                strcat(image_str, "[+toc]");
@@ -1326,6 +1359,7 @@ static long CALLBACK ISOopen(void) {
                strcat(image_str, "[+chd]");
                CDR_getBuffer = ISOgetBuffer_chd;
                cdimg_read_func = cdread_chd;
+               cdimg_read_sub_func = cdread_sub_chd;
                is_chd = 1;
        }
 #endif
@@ -1387,10 +1421,14 @@ static long CALLBACK ISOopen(void) {
 
        PrintTracks();
 
-       if (subChanMixed && !is_chd)
+       if (subChanMixed && !is_chd) {
                cdimg_read_func = cdread_sub_mixed;
-       else if (isMode1ISO)
+               cdimg_read_sub_func = cdread_sub_sub_mixed;
+       }
+       else if (isMode1ISO) {
                cdimg_read_func = cdread_2048;
+               cdimg_read_sub_func = NULL;
+       }
 
        // make sure we have another handle open for cdda
        if (numtracks > 1 && ti[1].handle == NULL) {
@@ -1530,28 +1568,13 @@ static boolean CALLBACK ISOreadTrack(unsigned char *time) {
                return 0;
        }
 
-       if (pregapOffset) {
-               subChanMissing = FALSE;
-               if (sector >= pregapOffset) {
-                       sector -= 2 * 75;
-                       if (sector < pregapOffset)
-                               subChanMissing = TRUE;
-               }
-       }
+       if (pregapOffset && sector >= pregapOffset)
+               sector -= 2 * 75;
 
        ret = cdimg_read_func(cdHandle, 0, cdbuffer, sector);
        if (ret < 12*2 + 2048)
                return 0;
 
-       if (subHandle != NULL) {
-               fseek(subHandle, sector * SUB_FRAMESIZE, SEEK_SET);
-               if (fread(subbuffer, 1, SUB_FRAMESIZE, subHandle) != SUB_FRAMESIZE)
-                       /* Faulty subchannel data shouldn't cause a read failure */
-                       return 1;
-
-               if (subChanRaw) DecodeRawSubData();
-       }
-
        return 1;
 }
 
@@ -1570,12 +1593,29 @@ static long CALLBACK ISOstop(void) {
 }
 
 // gets subchannel data
-static unsigned char* CALLBACK ISOgetBufferSub(void) {
-       if ((subHandle != NULL || subChanMixed) && !subChanMissing) {
-               return subbuffer;
+static unsigned char* CALLBACK ISOgetBufferSub(int sector) {
+       if (pregapOffset && sector >= pregapOffset) {
+               sector -= 2 * 75;
+               if (sector < pregapOffset) // ?
+                       return NULL;
        }
 
-       return NULL;
+       if (cdimg_read_sub_func != NULL) {
+               if (cdimg_read_sub_func(cdHandle, sector) != SUB_FRAMESIZE)
+                       return NULL;
+       }
+       else if (subHandle != NULL) {
+               if (fseek(subHandle, sector * SUB_FRAMESIZE, SEEK_SET))
+                       return NULL;
+               if (fread(subbuffer, 1, SUB_FRAMESIZE, subHandle) != SUB_FRAMESIZE)
+                       return NULL;
+       }
+       else {
+               return NULL;
+       }
+
+       if (subChanRaw) DecodeRawSubData();
+       return subbuffer;
 }
 
 static long CALLBACK ISOgetStatus(struct CdrStat *stat) {