From 8b91bf5e57c3498df6e8b2786ecc23dc87ca71c4 Mon Sep 17 00:00:00 2001
From: Connor McLaughlin <stenzek@gmail.com>
Date: Wed, 22 Jul 2020 00:03:01 +1000
Subject: [PATCH] Core: Add loading screen based progress callbacks

---
 src/core/CMakeLists.txt                       |  2 +
 src/core/core.vcxproj                         |  2 +
 src/core/core.vcxproj.filters                 |  2 +
 src/core/host_interface_progress_callback.cpp | 99 +++++++++++++++++++
 src/core/host_interface_progress_callback.h   | 32 ++++++
 5 files changed, 137 insertions(+)
 create mode 100644 src/core/host_interface_progress_callback.cpp
 create mode 100644 src/core/host_interface_progress_callback.h

diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 29e7cb093..f678531e6 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -48,6 +48,8 @@ add_library(core
     host_display.h
     host_interface.cpp
     host_interface.h
+    host_interface_progress_callback.cpp
+    host_interface_progress_callback.h
     interrupt_controller.cpp
     interrupt_controller.h
     mdec.cpp
diff --git a/src/core/core.vcxproj b/src/core/core.vcxproj
index 0554a7580..79141511b 100644
--- a/src/core/core.vcxproj
+++ b/src/core/core.vcxproj
@@ -73,6 +73,7 @@
     <ClCompile Include="gpu_hw_opengl.cpp" />
     <ClCompile Include="host_display.cpp" />
     <ClCompile Include="host_interface.cpp" />
+    <ClCompile Include="host_interface_progress_callback.cpp" />
     <ClCompile Include="interrupt_controller.cpp" />
     <ClCompile Include="mdec.cpp" />
     <ClCompile Include="memory_card.cpp" />
@@ -118,6 +119,7 @@
     <ClInclude Include="gte_types.h" />
     <ClInclude Include="host_display.h" />
     <ClInclude Include="host_interface.h" />
+    <ClInclude Include="host_interface_progress_callback.h" />
     <ClInclude Include="interrupt_controller.h" />
     <ClInclude Include="mdec.h" />
     <ClInclude Include="memory_card.h" />
diff --git a/src/core/core.vcxproj.filters b/src/core/core.vcxproj.filters
index 0fee53f5b..b9d17af4c 100644
--- a/src/core/core.vcxproj.filters
+++ b/src/core/core.vcxproj.filters
@@ -46,6 +46,7 @@
     <ClCompile Include="negcon.cpp" />
     <ClCompile Include="gpu_hw_vulkan.cpp" />
     <ClCompile Include="resources.cpp" />
+    <ClCompile Include="host_interface_progress_callback.cpp" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="types.h" />
@@ -93,6 +94,7 @@
     <ClInclude Include="negcon.h" />
     <ClInclude Include="gpu_hw_vulkan.h" />
     <ClInclude Include="resources.h" />
+    <ClInclude Include="host_interface_progress_callback.h" />
   </ItemGroup>
   <ItemGroup>
     <None Include="cpu_core.inl" />
diff --git a/src/core/host_interface_progress_callback.cpp b/src/core/host_interface_progress_callback.cpp
new file mode 100644
index 000000000..01b0e8e17
--- /dev/null
+++ b/src/core/host_interface_progress_callback.cpp
@@ -0,0 +1,99 @@
+#include "host_interface_progress_callback.h"
+#include "common/log.h"
+Log_SetChannel(HostInterfaceProgressCallback);
+
+HostInterfaceProgressCallback::HostInterfaceProgressCallback(HostInterface* intf)
+  : BaseProgressCallback(), m_host_interface(intf)
+{
+}
+
+void HostInterfaceProgressCallback::PushState()
+{
+  BaseProgressCallback::PushState();
+}
+
+void HostInterfaceProgressCallback::PopState()
+{
+  BaseProgressCallback::PopState();
+  Redraw(true);
+}
+
+void HostInterfaceProgressCallback::SetCancellable(bool cancellable)
+{
+  BaseProgressCallback::SetCancellable(cancellable);
+  Redraw(true);
+}
+
+void HostInterfaceProgressCallback::SetStatusText(const char* text)
+{
+  BaseProgressCallback::SetStatusText(text);
+  Redraw(true);
+}
+
+void HostInterfaceProgressCallback::SetProgressRange(u32 range)
+{
+  u32 last_range = m_progress_range;
+
+  BaseProgressCallback::SetProgressRange(range);
+
+  if (m_progress_range != last_range)
+    Redraw(false);
+}
+
+void HostInterfaceProgressCallback::SetProgressValue(u32 value)
+{
+  u32 lastValue = m_progress_value;
+
+  BaseProgressCallback::SetProgressValue(value);
+
+  if (m_progress_value != lastValue)
+    Redraw(false);
+}
+
+void HostInterfaceProgressCallback::Redraw(bool force)
+{
+  const int percent =
+    static_cast<int>((static_cast<float>(m_progress_value) / static_cast<float>(m_progress_range)) * 100.0f);
+  if (percent == m_last_progress_percent && !force)
+    return;
+
+  m_last_progress_percent = percent;
+  m_host_interface->DisplayLoadingScreen(m_status_text, 0, static_cast<int>(m_progress_range),
+                                         static_cast<int>(m_progress_value));
+}
+
+void HostInterfaceProgressCallback::DisplayError(const char* message)
+{
+  Log_ErrorPrint(message);
+}
+
+void HostInterfaceProgressCallback::DisplayWarning(const char* message)
+{
+  Log_WarningPrint(message);
+}
+
+void HostInterfaceProgressCallback::DisplayInformation(const char* message)
+{
+  Log_InfoPrint(message);
+}
+
+void HostInterfaceProgressCallback::DisplayDebugMessage(const char* message)
+{
+  Log_DevPrint(message);
+}
+
+void HostInterfaceProgressCallback::ModalError(const char* message)
+{
+  m_host_interface->ReportError(message);
+}
+
+bool HostInterfaceProgressCallback::ModalConfirmation(const char* message)
+{
+  return m_host_interface->ConfirmMessage(message);
+}
+
+u32 HostInterfaceProgressCallback::ModalPrompt(const char* message, u32 num_options, ...)
+{
+  Log_InfoPrint(message);
+  return 0;
+}
diff --git a/src/core/host_interface_progress_callback.h b/src/core/host_interface_progress_callback.h
new file mode 100644
index 000000000..67192e692
--- /dev/null
+++ b/src/core/host_interface_progress_callback.h
@@ -0,0 +1,32 @@
+#pragma once
+#include "common/progress_callback.h"
+#include "host_interface.h"
+
+class HostInterfaceProgressCallback : public BaseProgressCallback
+{
+public:
+  HostInterfaceProgressCallback(HostInterface* intf);
+
+  void PushState() override;
+  void PopState() override;
+
+  void SetCancellable(bool cancellable) override;
+  void SetStatusText(const char* text) override;
+  void SetProgressRange(u32 range) override;
+  void SetProgressValue(u32 value) override;
+
+  void DisplayError(const char* message) override;
+  void DisplayWarning(const char* message) override;
+  void DisplayInformation(const char* message) override;
+  void DisplayDebugMessage(const char* message) override;
+
+  void ModalError(const char* message) override;
+  bool ModalConfirmation(const char* message) override;
+  u32 ModalPrompt(const char* message, u32 num_options, ...) override;
+  
+private:
+  void Redraw(bool force);
+
+  HostInterface* m_host_interface;
+  int m_last_progress_percent = -1;
+};