diff --git a/src/common/image.cpp b/src/common/image.cpp
index b80e10dd5..1fe92feb3 100644
--- a/src/common/image.cpp
+++ b/src/common/image.cpp
@@ -1,4 +1,5 @@
 #include "image.h"
+#include "file_system.h"
 #include "log.h"
 #include "stb_image.h"
 Log_SetChannel(Common::Image);
@@ -6,8 +7,14 @@ Log_SetChannel(Common::Image);
 namespace Common {
 bool LoadImageFromFile(Common::RGBA8Image* image, const char* filename)
 {
+  auto fp = FileSystem::OpenManagedCFile(filename, "rb");
+  if (!fp)
+  {
+    return false;
+  }
+
   int width, height, file_channels;
-  u8* pixel_data = stbi_load(filename, &width, &height, &file_channels, 4);
+  u8* pixel_data = stbi_load_from_file(fp.get(), &width, &height, &file_channels, 4);
   if (!pixel_data)
   {
     const char* error_reason = stbi_failure_reason();
diff --git a/src/core/gpu.cpp b/src/core/gpu.cpp
index 32d36ddcf..086865c83 100644
--- a/src/core/gpu.cpp
+++ b/src/core/gpu.cpp
@@ -1,4 +1,5 @@
 #include "gpu.h"
+#include "common/file_system.h"
 #include "common/heap_array.h"
 #include "common/log.h"
 #include "common/state_wrapper.h"
@@ -1320,10 +1321,17 @@ void GPU::SetTextureWindow(u32 value)
 
 bool GPU::DumpVRAMToFile(const char* filename, u32 width, u32 height, u32 stride, const void* buffer, bool remove_alpha)
 {
-  std::vector<u32> rgba8_buf(width * height);
+  auto fp = FileSystem::OpenManagedCFile(filename, "wb");
+  if (!fp)
+  {
+    Log_ErrorPrintf("Can't open file '%s'", filename);
+    return false;
+  }
+
+  auto rgba8_buf = std::make_unique<u32[]>(width * height);
 
   const char* ptr_in = static_cast<const char*>(buffer);
-  u32* ptr_out = rgba8_buf.data();
+  u32* ptr_out = rgba8_buf.get();
   for (u32 row = 0; row < height; row++)
   {
     const char* row_ptr_in = ptr_in;
@@ -1338,7 +1346,11 @@ bool GPU::DumpVRAMToFile(const char* filename, u32 width, u32 height, u32 stride
 
     ptr_in += stride;
   }
-  return (stbi_write_png(filename, width, height, 4, rgba8_buf.data(), sizeof(u32) * width) != 0);
+
+  const auto write_func = [](void* context, void* data, int size) {
+    std::fwrite(data, 1, size, static_cast<std::FILE*>(context));
+  };
+  return (stbi_write_png_to_func(write_func, fp.get(), width, height, 4, rgba8_buf.get(), sizeof(u32) * width) != 0);
 }
 
 void GPU::DrawDebugStateWindow()
diff --git a/src/core/host_display.cpp b/src/core/host_display.cpp
index 5b81ccb4c..06db6768d 100644
--- a/src/core/host_display.cpp
+++ b/src/core/host_display.cpp
@@ -1,4 +1,5 @@
 #include "host_display.h"
+#include "common/file_system.h"
 #include "common/log.h"
 #include "common/string_util.h"
 #include "stb_image.h"
@@ -31,8 +32,14 @@ bool HostDisplay::SetSoftwareCursor(const void* pixels, u32 width, u32 height, u
 
 bool HostDisplay::SetSoftwareCursor(const char* path, float scale /*= 1.0f*/)
 {
+  auto fp = FileSystem::OpenManagedCFile(path, "rb");
+  if (!fp)
+  {
+    return false;
+  }
+
   int width, height, file_channels;
-  u8* pixel_data = stbi_load(path, &width, &height, &file_channels, 4);
+  u8* pixel_data = stbi_load_from_file(fp.get(), &width, &height, &file_channels, 4);
   if (!pixel_data)
   {
     const char* error_reason = stbi_failure_reason();
@@ -257,32 +264,39 @@ bool HostDisplay::WriteTextureToFile(const void* texture_handle, u32 x, u32 y, u
     texture_data_stride = resized_texture_stride;
   }
 
-  bool result;
+  auto fp = FileSystem::OpenManagedCFile(filename, "wb");
+  if (!fp)
+  {
+    Log_ErrorPrintf("Can't open file '%s'", filename);
+    return false;
+  }
+
+  const auto write_func = [](void* context, void* data, int size) {
+    std::fwrite(data, 1, size, static_cast<std::FILE*>(context));
+  };
+
+  bool result = false;
   if (StringUtil::Strcasecmp(extension, ".png") == 0)
   {
-    result = (stbi_write_png(filename, width, height, 4, texture_data.data(), texture_data_stride) != 0);
+    result =
+      (stbi_write_png_to_func(write_func, fp.get(), width, height, 4, texture_data.data(), texture_data_stride) != 0);
   }
   else if (StringUtil::Strcasecmp(filename, ".jpg") == 0)
   {
-    result = (stbi_write_jpg(filename, width, height, 4, texture_data.data(), 95) != 0);
+    result = (stbi_write_jpg_to_func(write_func, fp.get(), width, height, 4, texture_data.data(), 95) != 0);
   }
   else if (StringUtil::Strcasecmp(filename, ".tga") == 0)
   {
-    result = (stbi_write_tga(filename, width, height, 4, texture_data.data()) != 0);
+    result = (stbi_write_tga_to_func(write_func, fp.get(), width, height, 4, texture_data.data()) != 0);
   }
   else if (StringUtil::Strcasecmp(filename, ".bmp") == 0)
   {
-    result = (stbi_write_bmp(filename, width, height, 4, texture_data.data()) != 0);
-  }
-  else
-  {
-    Log_ErrorPrintf("Unknown extension in filename '%s': '%s'", filename, extension);
-    return false;
+    result = (stbi_write_bmp_to_func(write_func, fp.get(), width, height, 4, texture_data.data()) != 0);
   }
 
   if (!result)
   {
-    Log_ErrorPrintf("Failed to save texture to '%s'", filename);
+    Log_ErrorPrintf("Unknown extension in filename '%s' or save error: '%s'", filename, extension);
     return false;
   }
 
diff --git a/src/frontend-common/game_list.cpp b/src/frontend-common/game_list.cpp
index 0cd9c88f7..d2a3ff126 100644
--- a/src/frontend-common/game_list.cpp
+++ b/src/frontend-common/game_list.cpp
@@ -740,8 +740,12 @@ void GameList::LoadDatabase()
   if (m_database_filename.empty())
     return;
 
+  auto fp = FileSystem::OpenManagedCFile(m_database_filename.c_str(), "rb");
+  if (!fp)
+    return;
+
   tinyxml2::XMLDocument doc;
-  tinyxml2::XMLError error = doc.LoadFile(m_database_filename.c_str());
+  tinyxml2::XMLError error = doc.LoadFile(fp.get());
   if (error != tinyxml2::XML_SUCCESS)
   {
     Log_ErrorPrintf("Failed to parse redump dat '%s': %s", m_database_filename.c_str(),
@@ -858,8 +862,12 @@ void GameList::LoadCompatibilityList()
   if (m_compatibility_list_filename.empty())
     return;
 
+  auto fp = FileSystem::OpenManagedCFile(m_compatibility_list_filename.c_str(), "rb");
+  if (!fp)
+    return;
+
   tinyxml2::XMLDocument doc;
-  tinyxml2::XMLError error = doc.LoadFile(m_compatibility_list_filename.c_str());
+  tinyxml2::XMLError error = doc.LoadFile(fp.get());
   if (error != tinyxml2::XML_SUCCESS)
   {
     Log_ErrorPrintf("Failed to parse compatibility list '%s': %s", m_compatibility_list_filename.c_str(),
@@ -989,11 +997,12 @@ bool GameList::SaveCompatibilityDatabaseForEntry(const GameListCompatibilityEntr
   if (m_compatibility_list_filename.empty())
     return false;
 
-  if (!FileSystem::FileExists(m_compatibility_list_filename.c_str()))
+  auto fp = FileSystem::OpenManagedCFile(m_compatibility_list_filename.c_str(), "rb");
+  if (!fp)
     return SaveCompatibilityDatabase();
 
   tinyxml2::XMLDocument doc;
-  tinyxml2::XMLError error = doc.LoadFile(m_compatibility_list_filename.c_str());
+  tinyxml2::XMLError error = doc.LoadFile(fp.get());
   if (error != tinyxml2::XML_SUCCESS)
   {
     Log_ErrorPrintf("Failed to parse compatibility list '%s': %s", m_compatibility_list_filename.c_str(),