cdrom: try some different seek times
[pcsx_rearmed.git] / libpcsxcore / cdrom.c
index 047172c..fd09c7e 100644 (file)
@@ -106,7 +106,7 @@ static struct {
        u16 CmdInProgress;
        u8 Irq1Pending;
        u8 unused5;
-       u32 LastReadCycles;
+       u32 LastReadSeekCycles;
 
        u8 unused7;
 
@@ -448,11 +448,11 @@ static int ReadTrack(const u8 *time)
        tmp[1] = itob(time[1]);
        tmp[2] = itob(time[2]);
 
+       CDR_LOG("ReadTrack *** %02x:%02x:%02x\n", tmp[0], tmp[1], tmp[2]);
+
        if (memcmp(cdr.Prev, tmp, 3) == 0)
                return 1;
 
-       CDR_LOG("ReadTrack *** %02x:%02x:%02x\n", tmp[0], tmp[1], tmp[2]);
-
        read_ok = CDR_readTrack(tmp);
        if (read_ok)
                memcpy(cdr.Prev, tmp, 3);
@@ -462,12 +462,13 @@ static int ReadTrack(const u8 *time)
 static void UpdateSubq(const u8 *time)
 {
        const struct SubQ *subq;
+       int s = MSF2SECT(time[0], time[1], time[2]);
        u16 crc;
 
-       if (CheckSBI(time))
+       if (CheckSBI(s))
                return;
 
-       subq = (struct SubQ *)CDR_getBufferSub(MSF2SECT(time[0], time[1], time[2]));
+       subq = (struct SubQ *)CDR_getBufferSub(s);
        if (subq != NULL && cdr.CurTrack == 1) {
                crc = calcCrc((u8 *)subq + 12, 10);
                if (crc == (((u16)subq->CRC[0] << 8) | subq->CRC[1])) {
@@ -555,19 +556,25 @@ static void cdrPlayInterrupt_Autopause()
                cdr.ReportDelay--;
 }
 
-// LastReadCycles
 static int cdrSeekTime(unsigned char *target)
 {
        int diff = msf2sec(cdr.SetSectorPlay) - msf2sec(target);
-       int pausePenalty, seekTime = abs(diff) * (cdReadTime / 2000);
+       int seekTime = abs(diff) * (cdReadTime / 2000);
+       int cyclesSinceRS = psxRegs.cycle - cdr.LastReadSeekCycles;
        seekTime = MAX_VALUE(seekTime, 20000);
 
        // need this stupidly long penalty or else Spyro2 intro desyncs
-       pausePenalty = (s32)(psxRegs.cycle - cdr.LastReadCycles) > cdReadTime * 8 ? cdReadTime * 25 : 0;
-       seekTime += pausePenalty;
+       // note: if misapplied this breaks MGS cutscenes among other things
+       if (cyclesSinceRS > cdReadTime * 50)
+               seekTime += cdReadTime * 25;
+       // Transformers Beast Wars Transmetals does Setloc(x),SeekL,Setloc(x),ReadN
+       // and then wants some slack time
+       else if (cyclesSinceRS < cdReadTime *3/2)
+               seekTime += cdReadTime;
 
        seekTime = MIN_VALUE(seekTime, PSXCLK * 2 / 3);
-       CDR_LOG("seek: %.2f %.2f\n", (float)seekTime / PSXCLK, (float)seekTime / cdReadTime);
+       CDR_LOG("seek: %.2f %.2f (%.2f)\n", (float)seekTime / PSXCLK,
+               (float)seekTime / cdReadTime, (float)cyclesSinceRS / cdReadTime);
        return seekTime;
 }
 
@@ -633,7 +640,7 @@ static void msfiSub(u8 *msfi, u32 count)
 
 void cdrPlayReadInterrupt(void)
 {
-       cdr.LastReadCycles = psxRegs.cycle;
+       cdr.LastReadSeekCycles = psxRegs.cycle;
 
        if (cdr.Reading) {
                cdrReadInterrupt();
@@ -1071,6 +1078,7 @@ void cdrInterrupt(void) {
                                memcpy(cdr.LocL, buf, 8);
                        UpdateSubq(cdr.SetSectorPlay);
                        cdr.TrackChanged = FALSE;
+                       cdr.LastReadSeekCycles = psxRegs.cycle;
                        break;
 
                case CdlTest:
@@ -1190,11 +1198,11 @@ void cdrInterrupt(void) {
                        // FALLTHROUGH
 
                set_error:
-                       CDR_LOG_I("cmd %02x error %02x\n", Cmd, error);
                        SetResultSize(2);
                        cdr.Result[0] = cdr.StatP | STATUS_ERROR;
                        cdr.Result[1] = not_ready ? ERROR_NOTREADY : error;
                        cdr.Stat = DiskError;
+                       CDR_LOG_I("cmd %02x error %02x\n", Cmd, cdr.Result[1]);
                        break;
        }