From ee7cf25126cb25d2754d077b4e16d0595ed03f1e Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Tue, 28 Oct 2025 18:21:23 -0700
Subject: [PATCH] Fixed a crash at startup in Hearts of Iron IV
---
src/sdl2_compat.c | 39 +++++++++++++++++++++++++++++++++++++--
1 file changed, 37 insertions(+), 2 deletions(-)
diff --git a/src/sdl2_compat.c b/src/sdl2_compat.c
index b8d39f8..e67b3aa 100644
--- a/src/sdl2_compat.c
+++ b/src/sdl2_compat.c
@@ -29,7 +29,7 @@
#if defined(DisableScreenSaver)
/*
This breaks the build when creating SDL_ ## DisableScreenSaver
-/usr/include/X11/X.h:#define DisableScreenSaver 0
+/usr/include/X11/X.h:#define DisableScreenSaver 0
*/
#undef DisableScreenSaver
#endif
@@ -532,6 +532,9 @@ static QuirkEntryType quirks[] = {
/* SimCity 3000 tries to call SDL_DestroyMutex after we have been unloaded */
{"sc3u.dynamic", "SDL2COMPAT_NO_UNLOAD", "1"},
+
+ /* Hearts of Iron IV passes a garbage rwops->size pointer to SDL_LoadWAV_RW */
+ {"hoi4", "SDL2COMPAT_BROKEN_LOADWAV_SIZE", "1"},
#endif
};
@@ -3845,6 +3848,33 @@ RWops2to3(SDL2_RWops *rwops2)
return iostrm3;
}
+static Sint64 SDLCALL
+RWops2to3_size_broken(void *userdata)
+{
+ return -1;
+}
+
+static SDL_IOStream *
+RWops2to3_BrokenSize(SDL2_RWops *rwops2)
+{
+ SDL_IOStream *iostrm3 = NULL;
+ if (rwops2) {
+ SDL_IOStreamInterface iface;
+ SDL_INIT_INTERFACE(&iface);
+ iface.size = RWops2to3_size_broken;
+ iface.seek = RWops2to3_seek;
+ iface.read = RWops2to3_read;
+ iface.write = RWops2to3_write;
+ iface.close = RWops2to3_close;
+
+ iostrm3 = SDL3_OpenIO(&iface, rwops2);
+ if (!iostrm3) {
+ return NULL;
+ }
+ }
+ return iostrm3;
+}
+
SDL_DECLSPEC void *SDLCALL
SDL_LoadFile_RW(SDL2_RWops *rwops2, size_t *datasize, int freesrc)
{
@@ -3870,7 +3900,12 @@ SDL_LoadWAV_RW(SDL2_RWops *rwops2, int freesrc, SDL2_AudioSpec *spec2, Uint8 **a
if (spec2 == NULL) {
SDL3_InvalidParamError("spec");
} else {
- SDL_IOStream *iostrm3 = RWops2to3(rwops2);
+ SDL_IOStream *iostrm3;
+ if (SDL3_GetHintBoolean("SDL2COMPAT_BROKEN_LOADWAV_SIZE", false)) {
+ iostrm3 = RWops2to3_BrokenSize(rwops2);
+ } else {
+ iostrm3 = RWops2to3(rwops2);
+ }
if (iostrm3) {
SDL_AudioSpec spec3;
const bool rc = SDL3_LoadWAV_IO(iostrm3, true, &spec3, audio_buf, audio_len); /* always close the iostrm3 bridge object. */