aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libpcsxcore/cdrom.c61
1 files changed, 47 insertions, 14 deletions
diff --git a/libpcsxcore/cdrom.c b/libpcsxcore/cdrom.c
index 78db291..fdb38ba 100644
--- a/libpcsxcore/cdrom.c
+++ b/libpcsxcore/cdrom.c
@@ -45,6 +45,7 @@
cdrStruct cdr;
static unsigned char *pTransfer;
+static int subq_broken;
/* CD-ROM magic numbers */
#define CdlSync 0
@@ -394,9 +395,10 @@ static void Find_CurTrack(const u8 *time)
}
}
-static void ReadTrack(const u8 *time) {
+static void ReadTrack(const u8 *time, int after_seek) {
unsigned char tmp[3];
struct SubQ *subq;
+ int track, old_track;
u16 crc;
tmp[0] = itob(time[0]);
@@ -417,22 +419,30 @@ static void ReadTrack(const u8 *time) {
return;
subq = (struct SubQ *)CDR_getBufferSub();
- if (subq != NULL) {
+ if (subq != NULL && !subq_broken) {
crc = calcCrc((u8 *)subq + 12, 10);
- if (crc == (((u16)subq->CRC[0] << 8) | subq->CRC[1])) {
+ old_track = btoi(cdr.subq.Track);
+ track = btoi(subq->TrackNumber);
+
+ // track checks are probably wrong, but deals with corrupted
+ // subq + good checksum
+ // (how does the real thing handle that?)
+ if (crc == (((u16)subq->CRC[0] << 8) | subq->CRC[1])
+ && (after_seek || track == old_track || track == old_track + 1)) {
cdr.subq.Track = subq->TrackNumber;
cdr.subq.Index = subq->IndexNumber;
memcpy(cdr.subq.Relative, subq->TrackRelativeAddress, 3);
memcpy(cdr.subq.Absolute, subq->AbsoluteAddress, 3);
- // .. + 1 is probably wrong, but deals with corrupted
- // subq + good checksum
- // (how does real thing handle that?)
- if (cdr.CurTrack + 1 == btoi(subq->TrackNumber)) {
+ if (track == cdr.CurTrack + 1) {
cdr.CurTrack++;
cdr.TrackChanged = TRUE;
}
}
+ else {
+ CDR_LOG_I("ignore subq @%02x:%02x:%02x\n",
+ tmp[0], tmp[1], tmp[2]);
+ }
}
else {
unsigned char start[3], next[3];
@@ -562,7 +572,7 @@ void cdrPlayInterrupt()
memcpy(cdr.SetSectorPlay, cdr.SetSector, 4);
Find_CurTrack(cdr.SetSectorPlay);
- ReadTrack(cdr.SetSectorPlay);
+ ReadTrack(cdr.SetSectorPlay, 1);
cdr.TrackChanged = FALSE;
}
@@ -594,7 +604,7 @@ void cdrPlayInterrupt()
CDRMISC_INT(cdReadTime);
// update for CdlGetlocP/autopause
- ReadTrack(cdr.SetSectorPlay);
+ ReadTrack(cdr.SetSectorPlay, 0);
}
void cdrInterrupt() {
@@ -676,7 +686,7 @@ void cdrInterrupt() {
- plays tracks without retry play
*/
Find_CurTrack(cdr.SetSectorPlay);
- ReadTrack(cdr.SetSectorPlay);
+ ReadTrack(cdr.SetSectorPlay, 1);
cdr.TrackChanged = FALSE;
if (!Config.Cdda)
@@ -1016,7 +1026,7 @@ void cdrInterrupt() {
// Fighting Force 2 - update subq time immediately
// - fixes new game
cdr.CurTrack = 1;
- ReadTrack(cdr.SetSector);
+ ReadTrack(cdr.SetSector, 1);
// Crusaders of Might and Magic - update getlocl now
@@ -1094,7 +1104,7 @@ void cdrReadInterrupt() {
cdr.Result[0] = cdr.StatP;
cdr.Seeked = SEEK_DONE;
- ReadTrack( cdr.SetSector );
+ ReadTrack(cdr.SetSector, 0);
buf = CDR_getBuffer();
if (buf == NULL)
@@ -1187,7 +1197,7 @@ void cdrReadInterrupt() {
}
// update for CdlGetlocP
- ReadTrack(cdr.SetSector);
+ ReadTrack(cdr.SetSector, 0);
Check_Shell(0);
}
@@ -1616,6 +1626,9 @@ void cdrDmaInterrupt()
static void getCdInfo(void)
{
+ unsigned int i, j, sector;
+ struct SubQ *subq;
+ u8 tmpp[3];
u8 tmp;
CDR_getTN(cdr.ResultTN);
@@ -1623,6 +1636,26 @@ static void getCdInfo(void)
tmp = cdr.SetSectorEnd[0];
cdr.SetSectorEnd[0] = cdr.SetSectorEnd[2];
cdr.SetSectorEnd[2] = tmp;
+
+ subq_broken = 0;
+ subq = (struct SubQ *)CDR_getBufferSub();
+ if (subq != NULL && cdr.ResultTN[1] >= 2) {
+ CDR_getTD(cdr.ResultTN[1], tmpp);
+ sector = fsm2sec(tmpp) - 33;
+ for (i = 0; i < 5; i++, sector += 2) {
+ sec2msf(sector, tmpp);
+ for (j = 0; j < 3; j++)
+ tmpp[j] = itob(tmpp[j]);
+ CDR_readTrack(tmpp);
+ subq = (struct SubQ *)CDR_getBufferSub();
+ if (subq->IndexNumber == 0)
+ break;
+ }
+ if (i == 5) {
+ SysPrintf("cdrom: subchannel data looks broken, not using it\n");
+ subq_broken = 1;
+ }
+ }
}
void cdrReset() {
@@ -1666,7 +1699,7 @@ int cdrFreeze(void *f, int Mode) {
// read right sub data
memcpy(tmpp, cdr.Prev, 3);
cdr.Prev[0]++;
- ReadTrack(tmpp);
+ ReadTrack(tmpp, 1);
if (cdr.Play) {
Find_CurTrack(cdr.SetSectorPlay);