diff --git a/src/core/mdec.cpp b/src/core/mdec.cpp
index 022ba781d..8fc133442 100644
--- a/src/core/mdec.cpp
+++ b/src/core/mdec.cpp
@@ -106,6 +106,8 @@ static void CopyOutBlock(void* param, TickCount ticks, TickCount ticks_late);
 // from nocash spec
 static bool rl_decode_block(s16* blk, const u8* qt);
 static void IDCT(s16* blk);
+static void IDCT_New(s16* blk);
+static void IDCT_Old(s16* blk);
 static void yuv_to_rgb(u32 xx, u32 yy, const std::array<s16, 64>& Crblk, const std::array<s16, 64>& Cbblk,
                        const std::array<s16, 64>& Yblk);
 static void y_to_mono(const std::array<s16, 64>& Yblk);
@@ -627,9 +629,7 @@ void MDEC::CopyOutBlock(void* param, TickCount ticks, TickCount ticks_late)
 
     case DataOutputDepth_15Bit:
     {
-      // people have made texture packs using the old conversion routines.. best to just leave them be.
-      if (g_settings.texture_replacements.enable_vram_write_replacements ||
-          g_settings.texture_replacements.dump_vram_writes)
+      if (UNLIKELY(g_settings.use_old_mdec_routines))
       {
         const u16 a = ZeroExtend16(s_status.data_output_bit15.GetValue()) << 15;
         for (u32 i = 0; i < static_cast<u32>(s_block_rgb.size());)
@@ -762,6 +762,15 @@ bool MDEC::rl_decode_block(s16* blk, const u8* qt)
 }
 
 void MDEC::IDCT(s16* blk)
+{
+  // people have made texture packs using the old conversion routines.. best to just leave them be.
+  if (UNLIKELY(g_settings.use_old_mdec_routines))
+    IDCT_Old(blk);
+  else
+    IDCT_New(blk);
+}
+
+void MDEC::IDCT_New(s16* blk)
 {
   std::array<s32, 64> temp;
   for (u32 x = 0; x < 8; x++)
@@ -788,6 +797,33 @@ void MDEC::IDCT(s16* blk)
   }
 }
 
+void MDEC::IDCT_Old(s16* blk)
+{
+  std::array<s64, 64> temp_buffer;
+  for (u32 x = 0; x < 8; x++)
+  {
+    for (u32 y = 0; y < 8; y++)
+    {
+      s64 sum = 0;
+      for (u32 u = 0; u < 8; u++)
+        sum += s32(blk[u * 8 + x]) * s32(s_scale_table[u * 8 + y]);
+      temp_buffer[x + y * 8] = sum;
+    }
+  }
+  for (u32 x = 0; x < 8; x++)
+  {
+    for (u32 y = 0; y < 8; y++)
+    {
+      s64 sum = 0;
+      for (u32 u = 0; u < 8; u++)
+        sum += s64(temp_buffer[u + y * 8]) * s32(s_scale_table[u * 8 + x]);
+
+      blk[x + y * 8] =
+        static_cast<s16>(std::clamp<s32>(SignExtendN<9, s32>((sum >> 32) + ((sum >> 31) & 1)), -128, 127));
+    }
+  }
+}
+
 void MDEC::yuv_to_rgb(u32 xx, u32 yy, const std::array<s16, 64>& Crblk, const std::array<s16, 64>& Cbblk,
                       const std::array<s16, 64>& Yblk)
 {
diff --git a/src/core/settings.cpp b/src/core/settings.cpp
index 496166d9a..47aee5e96 100644
--- a/src/core/settings.cpp
+++ b/src/core/settings.cpp
@@ -301,6 +301,8 @@ void Settings::Load(SettingsInterface& si)
   audio_output_muted = si.GetBoolValue("Audio", "OutputMuted", false);
   audio_dump_on_boot = si.GetBoolValue("Audio", "DumpOnBoot", false);
 
+  use_old_mdec_routines = si.GetBoolValue("Hacks", "UseOldMDECRoutines", false);
+
   dma_max_slice_ticks = si.GetIntValue("Hacks", "DMAMaxSliceTicks", DEFAULT_DMA_MAX_SLICE_TICKS);
   dma_halt_ticks = si.GetIntValue("Hacks", "DMAHaltTicks", DEFAULT_DMA_HALT_TICKS);
   gpu_fifo_size = static_cast<u32>(si.GetIntValue("Hacks", "GPUFIFOSize", DEFAULT_GPU_FIFO_SIZE));
@@ -512,6 +514,7 @@ void Settings::Save(SettingsInterface& si) const
   si.SetBoolValue("Audio", "OutputMuted", audio_output_muted);
   si.SetBoolValue("Audio", "DumpOnBoot", audio_dump_on_boot);
 
+  si.SetBoolValue("Hacks", "UseOldMDECRoutines", use_old_mdec_routines);
   si.SetIntValue("Hacks", "DMAMaxSliceTicks", dma_max_slice_ticks);
   si.SetIntValue("Hacks", "DMAHaltTicks", dma_halt_ticks);
   si.SetIntValue("Hacks", "GPUFIFOSize", gpu_fifo_size);
diff --git a/src/core/settings.h b/src/core/settings.h
index d1bc2b7a8..64b9ed0d7 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -168,6 +168,8 @@ struct Settings
   bool audio_output_muted = false;
   bool audio_dump_on_boot = false;
 
+  bool use_old_mdec_routines = false;
+
   // timing hacks section
   TickCount dma_max_slice_ticks = DEFAULT_DMA_MAX_SLICE_TICKS;
   TickCount dma_halt_ticks = DEFAULT_DMA_HALT_TICKS;
diff --git a/src/duckstation-qt/advancedsettingswidget.cpp b/src/duckstation-qt/advancedsettingswidget.cpp
index 5a8ca72ff..dd5333f60 100644
--- a/src/duckstation-qt/advancedsettingswidget.cpp
+++ b/src/duckstation-qt/advancedsettingswidget.cpp
@@ -226,8 +226,7 @@ void AdvancedSettingsWidget::addTweakOptions()
                         "DisableAllEnhancements", false);
   addBooleanTweakOption(m_dialog, m_ui.tweakOptionTable, tr("Show Status Indicators"), "Display",
                         "ShowStatusIndicators", true);
-  addBooleanTweakOption(m_dialog, m_ui.tweakOptionTable, tr("Show Frame Times"), "Display",
-                        "ShowFrameTimes", false);
+  addBooleanTweakOption(m_dialog, m_ui.tweakOptionTable, tr("Show Frame Times"), "Display", "ShowFrameTimes", false);
   addBooleanTweakOption(m_dialog, m_ui.tweakOptionTable, tr("Apply Compatibility Settings"), "Main",
                         "ApplyCompatibilitySettings", true);
   addIntRangeTweakOption(m_dialog, m_ui.tweakOptionTable, tr("Display FPS Limit"), "Display", "MaxFPS", 0, 1000, 0);
@@ -261,6 +260,8 @@ void AdvancedSettingsWidget::addTweakOptions()
                        Settings::GetCPUFastmemModeDisplayName, "CPUFastmemMode",
                        static_cast<u32>(CPUFastmemMode::Count), Settings::DEFAULT_CPU_FASTMEM_MODE);
 
+  addBooleanTweakOption(m_dialog, m_ui.tweakOptionTable, tr("Use Old MDEC Routines"), "Hacks", "UseOldMDECRoutines",
+                        false);
   addBooleanTweakOption(m_dialog, m_ui.tweakOptionTable, tr("Enable VRAM Write Texture Replacement"),
                         "TextureReplacements", "EnableVRAMWriteReplacements", false);
   addBooleanTweakOption(m_dialog, m_ui.tweakOptionTable, tr("Preload Texture Replacements"), "TextureReplacements",
@@ -305,7 +306,7 @@ void AdvancedSettingsWidget::onResetToDefaultClicked()
 
     setBooleanTweakOption(m_ui.tweakOptionTable, i++, false);    // Disable all enhancements
     setBooleanTweakOption(m_ui.tweakOptionTable, i++, true);     // Show status indicators
-    setBooleanTweakOption(m_ui.tweakOptionTable, i++, false);     // Show frame times
+    setBooleanTweakOption(m_ui.tweakOptionTable, i++, false);    // Show frame times
     setBooleanTweakOption(m_ui.tweakOptionTable, i++, true);     // Apply compatibility settings
     setIntRangeTweakOption(m_ui.tweakOptionTable, i++, 0);       // Display FPS limit
     setChoiceTweakOption(m_ui.tweakOptionTable, i++, 0);         // Multisample antialiasing
@@ -316,6 +317,7 @@ void AdvancedSettingsWidget::onResetToDefaultClicked()
     setBooleanTweakOption(m_ui.tweakOptionTable, i++, false);             // Recompiler memory exceptions
     setBooleanTweakOption(m_ui.tweakOptionTable, i++, true);              // Recompiler block linking
     setChoiceTweakOption(m_ui.tweakOptionTable, i++, Settings::DEFAULT_CPU_FASTMEM_MODE); // Recompiler fastmem mode
+    setBooleanTweakOption(m_ui.tweakOptionTable, i++, false);                             // Use Old MDEC Routines
     setBooleanTweakOption(m_ui.tweakOptionTable, i++, false); // VRAM write texture replacement
     setBooleanTweakOption(m_ui.tweakOptionTable, i++, false); // Preload texture replacements
     setBooleanTweakOption(m_ui.tweakOptionTable, i++, false); // Dump replacable VRAM writes
@@ -345,6 +347,7 @@ void AdvancedSettingsWidget::onResetToDefaultClicked()
   sif->DeleteValue("Main", "DisableAllEnhancements");
   sif->DeleteValue("Display", "ShowEnhancements");
   sif->DeleteValue("Display", "ShowStatusIndicators");
+  sif->DeleteValue("Display", "ShowFrameTimes");
   sif->DeleteValue("Main", "ApplyCompatibilitySettings");
   sif->DeleteValue("Display", "MaxFPS");
   sif->DeleteValue("Display", "ActiveStartOffset");
@@ -365,6 +368,7 @@ void AdvancedSettingsWidget::onResetToDefaultClicked()
   sif->DeleteValue("TextureReplacements", "DumpVRAMWriteForceAlphaChannel");
   sif->DeleteValue("TextureReplacements", "DumpVRAMWriteWidthThreshold");
   sif->DeleteValue("TextureReplacements", "DumpVRAMWriteHeightThreshold");
+  sif->DeleteValue("Hacks", "UseOldMDECRoutines");
   sif->DeleteValue("Hacks", "DMAMaxSliceTicks");
   sif->DeleteValue("Hacks", "DMAHaltTicks");
   sif->DeleteValue("Hacks", "GPUFIFOSize");