cdrStruct cdr;
static unsigned char *pTransfer;
+static int subq_broken;
/* CD-ROM magic numbers */
#define CdlSync 0
}
}
-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]);
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];
memcpy(cdr.SetSectorPlay, cdr.SetSector, 4);
Find_CurTrack(cdr.SetSectorPlay);
- ReadTrack(cdr.SetSectorPlay);
+ ReadTrack(cdr.SetSectorPlay, 1);
cdr.TrackChanged = FALSE;
}
CDRMISC_INT(cdReadTime);
// update for CdlGetlocP/autopause
- ReadTrack(cdr.SetSectorPlay);
+ ReadTrack(cdr.SetSectorPlay, 0);
}
void cdrInterrupt() {
- plays tracks without retry play
*/
Find_CurTrack(cdr.SetSectorPlay);
- ReadTrack(cdr.SetSectorPlay);
+ ReadTrack(cdr.SetSectorPlay, 1);
cdr.TrackChanged = FALSE;
if (!Config.Cdda)
// 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
cdr.Result[0] = cdr.StatP;
cdr.Seeked = SEEK_DONE;
- ReadTrack( cdr.SetSector );
+ ReadTrack(cdr.SetSector, 0);
buf = CDR_getBuffer();
if (buf == NULL)
}
// update for CdlGetlocP
- ReadTrack(cdr.SetSector);
+ ReadTrack(cdr.SetSector, 0);
Check_Shell(0);
}
static void getCdInfo(void)
{
+ unsigned int i, j, sector;
+ struct SubQ *subq;
+ u8 tmpp[3];
u8 tmp;
CDR_getTN(cdr.ResultTN);
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() {
// read right sub data
memcpy(tmpp, cdr.Prev, 3);
cdr.Prev[0]++;
- ReadTrack(tmpp);
+ ReadTrack(tmpp, 1);
if (cdr.Play) {
Find_CurTrack(cdr.SetSectorPlay);