cdrom: adjust a timing hack
[pcsx_rearmed.git] / libpcsxcore / cdrom.c
index 0f1479e..098b77d 100644 (file)
@@ -325,6 +325,7 @@ void cdrLidSeekInterrupt(void)
 
                if (stat.Status & STATUS_SHELLOPEN)
                {
+                       memset(cdr.Prev, 0xff, sizeof(cdr.Prev));
                        cdr.DriveState = DRIVESTATE_LID_OPEN;
                        CDRLID_INT(0x800);
                }
@@ -597,8 +598,14 @@ static u32 cdrAlignTimingHack(u32 cycles)
         * active), but before the game's handler loop reads I_STAT. The time
         * window for this is quite small (~1k cycles of so). Apparently this
         * somehow happens naturally on the real hardware.
+        *
+        * Note: always enforcing this breaks other games like Crash PAL version
+        * (inputs get dropped because bios handler doesn't see interrupts).
         */
-       u32 vint_rel = rcnts[3].cycleStart + 63000 - psxRegs.cycle;
+       u32 vint_rel;
+       if (psxRegs.cycle - rcnts[3].cycleStart > 250000)
+               return cycles;
+       vint_rel = rcnts[3].cycleStart + 63000 - psxRegs.cycle;
        vint_rel += PSXCLK / 60;
        while ((s32)(vint_rel - cycles) < 0)
                vint_rel += PSXCLK / 60;
@@ -1154,7 +1161,8 @@ void cdrInterrupt(void) {
 
                        cycles = (cdr.Mode & 0x80) ? cdReadTime : cdReadTime * 2;
                        cycles += seekTime;
-                       cycles = cdrAlignTimingHack(cycles);
+                       if (Config.hacks.cdr_read_timing)
+                               cycles = cdrAlignTimingHack(cycles);
                        CDRPLAYREAD_INT(cycles, 1);
 
                        SetPlaySeekRead(cdr.StatP, STATUS_SEEK);
@@ -1495,14 +1503,22 @@ void cdrWrite3(unsigned char rt) {
                break; // transfer
        case 1:
                if (cdr.Stat & rt) {
+                       u32 nextCycle = psxRegs.intCycle[PSXINT_CDR].sCycle
+                               + psxRegs.intCycle[PSXINT_CDR].cycle;
 #ifdef CDR_LOG_CMD_IRQ
-                       SysPrintf("%u cdrom: ack %02x (w %02x)\n",
-                               psxRegs.cycle, cdr.Stat & rt, rt);
+                       SysPrintf("%u cdrom: ack %02x (w=%02x p=%d,%d)\n",
+                               psxRegs.cycle, cdr.Stat & rt, rt,
+                               !!(psxRegs.interrupt & (1 << PSXINT_CDR)),
+                               nextCycle - psxRegs.cycle);
 #endif
-                       // note: Croc vs Discworld Noir
+                       // note: Croc, Shadow Tower (more) vs Discworld Noir (<993)
                        if (!(psxRegs.interrupt & (1 << PSXINT_CDR)) &&
                            (cdr.CmdInProgress || cdr.Irq1Pending))
-                               CDR_INT(850); // 711-993
+                       {
+                               s32 c = 2048 - (psxRegs.cycle - nextCycle);
+                               c = MAX_VALUE(c, 512);
+                               CDR_INT(c);
+                       }
                }
                cdr.Stat &= ~rt;