From f23bcc0faa812c7067147578ca223d24ec93fd0f Mon Sep 17 00:00:00 2001
From: Connor McLaughlin <stenzek@gmail.com>
Date: Fri, 27 Mar 2020 01:42:59 +1000
Subject: [PATCH] SPU: Ignore loop start flag when repeat address is explicitly
 set

Fixes dialog/softlock in Thousand Arms.
---
 src/core/save_state_version.h | 2 +-
 src/core/spu.cpp              | 5 ++++-
 src/core/spu.h                | 1 +
 3 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/src/core/save_state_version.h b/src/core/save_state_version.h
index d8a8f13ba..f45826c4a 100644
--- a/src/core/save_state_version.h
+++ b/src/core/save_state_version.h
@@ -2,4 +2,4 @@
 #include "types.h"
 
 static constexpr u32 SAVE_STATE_MAGIC = 0x43435544;
-static constexpr u32 SAVE_STATE_VERSION = 14;
+static constexpr u32 SAVE_STATE_VERSION = 15;
diff --git a/src/core/spu.cpp b/src/core/spu.cpp
index 7dfd67120..6682d5541 100644
--- a/src/core/spu.cpp
+++ b/src/core/spu.cpp
@@ -130,6 +130,7 @@ bool SPU::DoState(StateWrapper& sw)
     sw.Do(&v.adsr_phase);
     sw.Do(&v.adsr_target);
     sw.Do(&v.has_samples);
+    sw.Do(&v.ignore_loop_address);
   }
 
   sw.DoBytes(m_ram.data(), RAM_SIZE);
@@ -584,6 +585,7 @@ void SPU::WriteVoiceRegister(u32 offset, u16 value)
     {
       Log_DebugPrintf("SPU voice %u ADPCM repeat address <- 0x%04X", voice_index, value);
       voice.regs.adpcm_repeat_address = value;
+      voice.ignore_loop_address = true;
     }
     break;
 
@@ -873,6 +875,7 @@ void SPU::Voice::KeyOn()
   current_address = regs.adpcm_start_address;
   regs.adsr_volume = 0;
   has_samples = false;
+  ignore_loop_address = false;
   SetADSRPhase(ADSRPhase::Attack);
 }
 
@@ -1238,7 +1241,7 @@ std::tuple<s32, s32> SPU::SampleVoice(u32 voice_index)
     voice.DecodeBlock(block);
     voice.has_samples = true;
 
-    if (voice.current_block_flags.loop_start)
+    if (voice.current_block_flags.loop_start && !voice.ignore_loop_address)
     {
       Log_TracePrintf("Voice %u loop start @ 0x%08X", voice_index, ZeroExtend32(voice.current_address));
       voice.regs.adpcm_repeat_address = voice.current_address;
diff --git a/src/core/spu.h b/src/core/spu.h
index b947d59ce..3bdc56b5c 100644
--- a/src/core/spu.h
+++ b/src/core/spu.h
@@ -262,6 +262,7 @@ private:
     ADSRPhase adsr_phase;
     s16 adsr_target;
     bool has_samples;
+    bool ignore_loop_address;
 
     bool IsOn() const { return adsr_phase != ADSRPhase::Off; }