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 @@
+
@@ -118,6 +119,7 @@
+
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 @@
+
@@ -93,6 +94,7 @@
+
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((static_cast(m_progress_value) / static_cast(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(m_progress_range),
+ static_cast(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;
+};