diff options
-rw-r--r-- | libpcsxcore/cdriso.c | 49 |
1 files changed, 42 insertions, 7 deletions
diff --git a/libpcsxcore/cdriso.c b/libpcsxcore/cdriso.c index cf1b363..6df8b67 100644 --- a/libpcsxcore/cdriso.c +++ b/libpcsxcore/cdriso.c @@ -38,6 +38,7 @@ static FILE *subHandle = NULL; static boolean subChanMixed = FALSE; static boolean subChanRaw = FALSE; +static boolean subChanMissing = FALSE; static unsigned char cdbuffer[DATA_SIZE]; static unsigned char subbuffer[SUB_FRAMESIZE]; @@ -56,6 +57,11 @@ static boolean playing = FALSE; static boolean cddaBigEndian = FALSE; static unsigned int cddaCurOffset = 0; static unsigned int cddaStartOffset; +/* Frame offset into CD image where pregap data would be found if it was there. + * If a game seeks there we must *not* return subchannel data since it's + * not in the CD image, so that cdrom code can fake subchannel data instead. + * XXX: there could be multiple pregaps but PSX dumps only have one? */ +static unsigned int pregapOffset; char* CALLBACK CDR__getDriveLetter(void); long CALLBACK CDR__configure(void); @@ -368,6 +374,10 @@ static int parsetoc(const char *isofile) { sscanf(linebuf, "ZERO AUDIO RW_RAW %8s", time); tok2msf((char *)&time, dummy); sector_offs += msf2sec(dummy); + if (numtracks > 1) { + t = ti[numtracks - 1].start_offset; + pregapOffset = t + msf2sec(ti[numtracks - 1].length); + } } } @@ -473,12 +483,15 @@ static int parsecue(const char *isofile) { t = msf2sec(ti[numtracks].start) - msf2sec(ti[numtracks - 1].start); sec2msf(t, ti[numtracks - 1].length); } + if (numtracks > 1 && pregapOffset == -1) + pregapOffset = ti[numtracks].start_offset; } else if (!strcmp(token, "PREGAP")) { if (sscanf(linebuf, " PREGAP %8s", time) == 1) { tok2msf(time, dummy); sector_offs += msf2sec(dummy); } + pregapOffset = -1; // mark to fill track start_offset } else if (!strcmp(token, "FILE")) { sscanf(linebuf, " FILE \"%[^\"]\"", tmpb); @@ -662,21 +675,27 @@ static int parsemds(const char *isofile) { ti[i].start[1] = fgetc(fi); ti[i].start[2] = fgetc(fi); - // get the track length fread(&extra_offset, 1, sizeof(unsigned int), fi); extra_offset = SWAP32(extra_offset); - fseek(fi, extra_offset + 4, SEEK_SET); - fread(&l, 1, sizeof(unsigned int), fi); - l = SWAP32(l); - sec2msf(l, ti[i].length); - // get track start offset (in .mdf) fseek(fi, offset + 0x28, SEEK_SET); fread(&l, 1, sizeof(unsigned int), fi); l = SWAP32(l); ti[i].start_offset = l / CD_FRAMESIZE_RAW; + // get pregap + fseek(fi, extra_offset, SEEK_SET); + fread(&l, 1, sizeof(unsigned int), fi); + l = SWAP32(l); + if (l != 0 && i > 1) + pregapOffset = ti[i].start_offset; + + // get the track length + fread(&l, 1, sizeof(unsigned int), fi); + l = SWAP32(l); + sec2msf(l, ti[i].length); + offset += 0x50; } @@ -753,6 +772,8 @@ static long CALLBACK ISOopen(void) { cddaBigEndian = FALSE; subChanMixed = FALSE; subChanRaw = FALSE; + subChanMixed = FALSE; + pregapOffset = 0; if (parsecue(GetIsoFile()) == 0) { SysPrintf("[+cue]"); @@ -898,6 +919,15 @@ static long CALLBACK ISOreadTrack(unsigned char *time) { return -1; } + if (pregapOffset) { + subChanMissing = FALSE; + if (sector >= pregapOffset) { + sector -= 2 * 75; + if (sector < pregapOffset) + subChanMissing = TRUE; + } + } + if (subChanMixed) { fseek(cdHandle, sector * (CD_FRAMESIZE_RAW + SUB_FRAMESIZE) + 12, SEEK_SET); fread(cdbuffer, 1, DATA_SIZE, cdHandle); @@ -953,6 +983,11 @@ static long CALLBACK ISOplay(unsigned char *time) { cddaStartOffset = abs_sect - file_sect; cddaHandle = ti[i].handle; + if (pregapOffset && (unsigned int)(pregapOffset - file_sect) < 2 * 75) { + // get out of the missing pregap to avoid noise + file_sect = pregapOffset; + } + if (SPU_playCDDAchannel != NULL) { if (subChanMixed) { startCDDA(file_sect * (CD_FRAMESIZE_RAW + SUB_FRAMESIZE)); @@ -974,7 +1009,7 @@ static long CALLBACK ISOstop(void) { // gets subchannel data static unsigned char* CALLBACK ISOgetBufferSub(void) { - if (subHandle != NULL || subChanMixed) { + if ((subHandle != NULL || subChanMixed) && !subChanMissing) { return subbuffer; } |