From 6b68512ac116240e03fedfaaf9cedf3990d9ca98 Mon Sep 17 00:00:00 2001
From: Connor McLaughlin <stenzek@gmail.com>
Date: Mon, 16 Mar 2020 00:03:57 +1000
Subject: [PATCH] HostInterface: Add SaveScreenshot() method

---
 src/core/host_interface.cpp | 42 ++++++++++++++++++++++++++++++++++---
 src/core/host_interface.h   |  3 +++
 2 files changed, 42 insertions(+), 3 deletions(-)

diff --git a/src/core/host_interface.cpp b/src/core/host_interface.cpp
index 2f17baeff..b0917c832 100644
--- a/src/core/host_interface.cpp
+++ b/src/core/host_interface.cpp
@@ -674,10 +674,11 @@ void HostInterface::CreateUserDirectorySubdirectories()
 
   result &= FileSystem::CreateDirectory(GetUserDirectoryRelativePath("bios").c_str(), false);
   result &= FileSystem::CreateDirectory(GetUserDirectoryRelativePath("cache").c_str(), false);
-  result &= FileSystem::CreateDirectory(GetUserDirectoryRelativePath("savestates").c_str(), false);
-  result &= FileSystem::CreateDirectory(GetUserDirectoryRelativePath("memcards").c_str(), false);
   result &= FileSystem::CreateDirectory(GetUserDirectoryRelativePath("dump").c_str(), false);
   result &= FileSystem::CreateDirectory(GetUserDirectoryRelativePath("dump/audio").c_str(), false);
+  result &= FileSystem::CreateDirectory(GetUserDirectoryRelativePath("savestates").c_str(), false);
+  result &= FileSystem::CreateDirectory(GetUserDirectoryRelativePath("screenshots").c_str(), false);
+  result &= FileSystem::CreateDirectory(GetUserDirectoryRelativePath("memcards").c_str(), false);
 
   if (!result)
     ReportError("Failed to create one or more user directories. This may cause issues at runtime.");
@@ -1139,4 +1140,39 @@ void HostInterface::StopDumpingAudio()
     return;
 
   AddOSDMessage("Stopped dumping audio.", 5.0f);
-}
\ No newline at end of file
+}
+
+bool HostInterface::SaveScreenshot(const char* filename /* = nullptr */, bool full_resolution /* = true */,
+                                   bool apply_aspect_ratio /* = true */)
+{
+  if (!m_system)
+    return false;
+
+  std::string auto_filename;
+  if (!filename)
+  {
+    const auto& code = m_system->GetRunningCode();
+    const char* extension = "png";
+    if (code.empty())
+    {
+      auto_filename =
+        GetUserDirectoryRelativePath("screenshots/%s.%s", GetTimestampStringForFileName().GetCharArray(), extension);
+    }
+    else
+    {
+      auto_filename = GetUserDirectoryRelativePath("screenshots/%s_%s.%s", code.c_str(),
+                                                   GetTimestampStringForFileName().GetCharArray(), extension);
+    }
+
+    filename = auto_filename.c_str();
+  }
+
+  if (!m_display->WriteDisplayTextureToFile(filename, full_resolution, apply_aspect_ratio))
+  {
+    AddFormattedOSDMessage(10.0f, "Failed to save screenshot to '%s'", filename);
+    return false;
+  }
+
+  AddFormattedOSDMessage(5.0f, "Screenshot saved to '%s'.", filename);
+  return true;
+}
diff --git a/src/core/host_interface.h b/src/core/host_interface.h
index 210e1dab8..93467c015 100644
--- a/src/core/host_interface.h
+++ b/src/core/host_interface.h
@@ -78,6 +78,9 @@ public:
   /// Stops dumping audio to file if it has been started.
   void StopDumpingAudio();
 
+  /// Saves a screenshot to the specified file. IF no file name is provided, one will be generated automatically.
+  bool SaveScreenshot(const char* filename = nullptr, bool full_resolution = true, bool apply_aspect_ratio = true);
+
   virtual void ReportError(const char* message);
   virtual void ReportMessage(const char* message);
   virtual bool ConfirmMessage(const char* message);