From ea429a1b8d04b53c0e0d9c33bdba8e613de0e88d Mon Sep 17 00:00:00 2001
From: Jaklyy <102590697+Jaklyy@users.noreply.github.com>
Date: Thu, 4 Jul 2024 12:58:58 -0400
Subject: [PATCH] improve interlock emulation

add cycles to the instruction execution time rather than the timestamp directly.
---
 src/ARM.cpp |  9 +++++----
 src/ARM.h   | 10 ++++++----
 2 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/src/ARM.cpp b/src/ARM.cpp
index f667e0f6..7d5a02c7 100644
--- a/src/ARM.cpp
+++ b/src/ARM.cpp
@@ -696,6 +696,7 @@ void ARMv5::Execute()
 
         NDS.ARM9Timestamp += Cycles;
         Cycles = 0;
+        CyclesILed = 0;
     }
 
     if (Halted == 2)
@@ -1262,7 +1263,7 @@ bool ARMv4::DataWrite32S(u32 addr, u32 val, bool dataabort)
 void ARMv5::AddCycles_CD_STR()
 {
     s32 numC = (R[15] & 0x2) ? 0 : CodeCycles;
-    s32 numD = DataCycles;
+    s32 numD = DataCycles + CyclesILed;
 
     s32 early;
     if (DataRegion == Mem9_ITCM)
@@ -1287,7 +1288,7 @@ void ARMv5::AddCycles_CD_STR()
 void ARMv5::AddCycles_CD_STM()
 {
     s32 numC = (R[15] & 0x2) ? 0 : CodeCycles;
-    s32 numD = DataCycles;
+    s32 numD = DataCycles + CyclesILed;
 
     s32 early;
     if (DataRegion == Mem9_ITCM)
@@ -1313,7 +1314,7 @@ void ARMv5::AddCycles_CDI_LDR()
 {
     // LDR cycles. ARM9 seems to skip the internal cycle here.
     s32 numC = (R[15] & 0x2) ? 0 : CodeCycles;
-    s32 numD = DataCycles;
+    s32 numD = DataCycles + CyclesILed;
 
     // if a 32 bit bus, start 2 cycles early; else, start 4 cycles early
     s32 early;
@@ -1340,7 +1341,7 @@ void ARMv5::AddCycles_CDI_LDM()
 {
     // LDM cycles. ARM9 seems to skip the internal cycle here.
     s32 numC = (R[15] & 0x2) ? 0 : CodeCycles;
-    s32 numD = DataCycles;
+    s32 numD = DataCycles + CyclesILed;
 
     // if a 32 bit bus, start 2 cycles early; else, start 4 cycles early
     s32 early;
diff --git a/src/ARM.h b/src/ARM.h
index 20d11ad2..a76a6d09 100644
--- a/src/ARM.h
+++ b/src/ARM.h
@@ -30,7 +30,7 @@
 #include "debug/GdbStub.h"
 #endif
 
-//#define INTERLOCK
+#define INTERLOCK
 
 namespace melonDS
 {
@@ -318,14 +318,14 @@ public:
     {
         // code only. always nonseq 32-bit for ARM9.
         s32 numC = CodeCycles;
-        Cycles += numC;
+        Cycles += std::max(numC, CyclesILed + 1);
     }
 
     void AddCycles_CI(s32 numI) override
     {
         // code+internal
         s32 numC = CodeCycles;
-        numI += 1;
+        numI += 1 + CyclesILed;
         Cycles += std::max(numC, numI);
     }
 
@@ -340,7 +340,7 @@ public:
     inline u32 GetReg(const u32 reg, const u32 delay = 0) override
     {
         if (InterlockTimestamp[reg] > (Timestamp() + delay))
-            Timestamp() = InterlockTimestamp[reg] - delay;
+            CyclesILed = InterlockTimestamp[reg] - (Timestamp() + delay);
         return R[reg];
     }
 
@@ -417,6 +417,8 @@ public:
 
     bool (*GetMemRegion)(u32 addr, bool write, MemRegion* region);
 
+    s32 CyclesILed;
+
 #ifdef GDBSTUB_ENABLED
     u32 ReadMem(u32 addr, int size) override;
     void WriteMem(u32 addr, int size, u32 v) override;