From 4a5b79e03f24ddf9561d10cfad5d018ffd41fb3f Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Mon, 29 Jul 2024 15:44:17 -0400
Subject: [PATCH] SDL_RWFromFile: Deal with Apple-specific quirks removed from
SDL3.
---
include/SDL2/SDL_hints.h | 21 +++++++++++++++++++++
src/sdl2_compat.c | 22 +++++++++++++++++++++-
2 files changed, 42 insertions(+), 1 deletion(-)
diff --git a/include/SDL2/SDL_hints.h b/include/SDL2/SDL_hints.h
index bf5e5b9..24b73b6 100644
--- a/include/SDL2/SDL_hints.h
+++ b/include/SDL2/SDL_hints.h
@@ -3093,6 +3093,27 @@ extern "C" {
*/
#define SDL_HINT_SHUTDOWN_DBUS_ON_QUIT "SDL_SHUTDOWN_DBUS_ON_QUIT"
+/**
+ * Specify if SDL_RWFromFile should use the resource dir on Apple platforms.
+ *
+ * SDL2 has always done this on Apple platforms, but it can be surprising to
+ * try opening a path to discover that SDL adjusts the path to elsewhere, so
+ * this hint allows that behavior to be disabled.
+ *
+ * If running from a App Bundle, this will be MyApp.app/Contents/Resources.
+ * If running as a normal Unix-like process, this will be the directory where
+ * the running binary lives. Setting this hint to 0 avoids this and just
+ * uses the requested path as-is.
+ *
+ * This variable can be set to the following values:
+ *
+ * - "0": SDL will not use the app resource directory.
+ * - "1": SDL will use the app's resource directory (default).
+ *
+ * This hint is available since SDL 2.32.0.
+ */
+#define SDL_HINT_APPLE_RWFROMFILE_USE_RESOURCES "SDL_APPLE_RWFROMFILE_USE_RESOURCES"
+
/**
* An enumeration of hint priorities
diff --git a/src/sdl2_compat.c b/src/sdl2_compat.c
index 1d94968..e8f3f2d 100644
--- a/src/sdl2_compat.c
+++ b/src/sdl2_compat.c
@@ -1999,7 +1999,27 @@ RWops3to2(SDL_IOStream *iostrm3, Uint32 type)
SDL_DECLSPEC SDL2_RWops *SDLCALL
SDL_RWFromFile(const char *file, const char *mode)
{
- SDL2_RWops *rwops2 = RWops3to2(SDL3_IOFromFile(file, mode), SDL_RWOPS_PLATFORM_FILE);
+ SDL2_RWops *rwops2 = NULL;
+
+ /* match some SDL2 Apple-specific quirks that were removed from SDL3. */
+ #if defined(SDL_PLATFORM_APPLE)
+ char *adjusted_path = NULL;
+ /* If the file mode is writable, skip all the bundle stuff because generally the bundle is read-only. */
+ if ((SDL3_strchr(mode, 'r') != NULL) && SDL3_GetHintBoolean(SDL_HINT_APPLE_RWFROMFILE_USE_RESOURCES, SDL_TRUE)) {
+ const char *base = SDL3_GetBasePath();
+ if (!base) {
+ return NULL;
+ } else if (SDL3_asprintf(&adjusted_path, "%s%s", base, file) < 0) {
+ return NULL;
+ }
+ file = adjusted_path;
+ }
+ rwops2 = RWops3to2(SDL3_IOFromFile(file, mode), SDL_RWOPS_PLATFORM_FILE);
+ SDL_free(adjusted_path);
+ #else
+ rwops2 = RWops3to2(SDL3_IOFromFile(file, mode), SDL_RWOPS_PLATFORM_FILE);
+ #endif
+
if (rwops2) {
const SDL_PropertiesID props = SDL3_GetIOProperties(rwops2->hidden.sdl3.iostrm);
if (props) {