From 2ad2b969f0dbd466f885a6346cc1af8eb0a35d82 Mon Sep 17 00:00:00 2001
From: LuigiBlood <luigiblood@gmail.com>
Date: Fri, 5 Jun 2020 16:48:19 +0200
Subject: [PATCH] [Disk] Emulate Motor Status & 3779 mSEC disk seek speeds

---
 Source/Project64-core/N64System/Mips/Disk.cpp | 56 ++++++++++++++++++-
 .../N64System/Mips/SystemTiming.cpp           |  2 +-
 Source/Project64-core/N64System/N64Class.cpp  |  4 +-
 3 files changed, 59 insertions(+), 3 deletions(-)

diff --git a/Source/Project64-core/N64System/Mips/Disk.cpp b/Source/Project64-core/N64System/Mips/Disk.cpp
index 5ac125965..b7032f5f7 100644
--- a/Source/Project64-core/N64System/Mips/Disk.cpp
+++ b/Source/Project64-core/N64System/Mips/Disk.cpp
@@ -108,7 +108,61 @@ void DiskCommand()
     if (isSeek)
     {
         //Emulate Seek Times, send interrupt later
-        g_SystemTimer->SetTimer(g_SystemTimer->DDSeekTimer, 0x400000, false);
+        uint32_t seektime = 0x179200;
+        if (g_Reg->ASIC_STATUS & DD_STATUS_MTR_N_SPIN)
+        {
+            seektime += 0x800000;
+            g_Reg->ASIC_STATUS &= ~DD_STATUS_MTR_N_SPIN;
+        }
+
+        //Get Zone
+        uint32_t track = g_Reg->ASIC_CUR_TK >> 16 & 0x0FFF;
+        uint32_t zone = 0;
+        uint32_t zonebound = 0;
+        for (uint8_t i = 0; i < 8; i++)
+        {
+            zonebound += ddZoneTrackSize[i];
+            if (track < zonebound)
+            {
+                zone = i;
+                if (g_Reg->ASIC_CUR_TK & 0x10000000)
+                    zone++;
+                break;
+            }
+        }
+        switch (zone)
+        {
+        case 0:
+        default:
+            break;
+        case 1:
+            seektime += 0x1900;
+            break;
+        case 2:
+            seektime += 0x2A00;
+            break;
+        case 3:
+            seektime += 0x4500;
+            break;
+        case 4:
+            seektime += 0x5E00;
+            break;
+        case 5:
+            seektime += 0x7A00;
+            break;
+        case 6:
+            seektime += 0x9700;
+            break;
+        case 7:
+            seektime += 0xAF00;
+            break;
+        case 8:
+            seektime += 0xCC00;
+            break;
+        }
+
+        g_SystemTimer->SetTimer(g_SystemTimer->DDSeekTimer, seektime, false);
+        g_SystemTimer->SetTimer(g_SystemTimer->DDMotorTimer, 0x6000000, false);
     }
     else
     {
diff --git a/Source/Project64-core/N64System/Mips/SystemTiming.cpp b/Source/Project64-core/N64System/Mips/SystemTiming.cpp
index 4602e16a5..1b0a39d37 100644
--- a/Source/Project64-core/N64System/Mips/SystemTiming.cpp
+++ b/Source/Project64-core/N64System/Mips/SystemTiming.cpp
@@ -229,7 +229,7 @@ void CSystemTimer::TimerDone()
         break;
     case CSystemTimer::DDMotorTimer:
         g_SystemTimer->StopTimer(CSystemTimer::DDMotorTimer);
-        g_Reg->ASIC_STATUS &= ~DD_STATUS_MTR_N_SPIN;
+        g_Reg->ASIC_STATUS |= DD_STATUS_MTR_N_SPIN;
         break;
     case CSystemTimer::ViTimer:
         try
diff --git a/Source/Project64-core/N64System/N64Class.cpp b/Source/Project64-core/N64System/N64Class.cpp
index 5f13bd660..ca7e03741 100644
--- a/Source/Project64-core/N64System/N64Class.cpp
+++ b/Source/Project64-core/N64System/N64Class.cpp
@@ -985,7 +985,9 @@ void CN64System::InitRegisters(bool bPostPif, CMipsMemoryVM & MMU)
     m_Reg.STATUS_REGISTER = 0x34000000;
 
     //64DD Registers
-    m_Reg.ASIC_STATUS = DD_STATUS_RST_STATE;
+
+    //Start 64DD in Reset State and Motor Not Spinning
+    m_Reg.ASIC_STATUS = DD_STATUS_RST_STATE | DD_STATUS_MTR_N_SPIN;
     m_Reg.ASIC_ID_REG = 0x00030000;
     if (g_DDRom && (g_DDRom->CicChipID() == CIC_NUS_DDTL || (g_Disk && g_Disk->GetCountry() == Country::UnknownCountry)))
         m_Reg.ASIC_ID_REG = 0x00040000;