sdl12-compat: audio: Deal with non-seekable rwops in SDL_LoadWAV_RW.

From f52d7787f9f513a5a2ba99d92678af39a9548458 Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Wed, 11 Jan 2023 15:27:00 -0500
Subject: [PATCH] audio: Deal with non-seekable rwops in SDL_LoadWAV_RW.

Fixes #283.
---
 src/SDL12_compat.c | 22 +++++++++++++++++++++-
 src/SDL20_syms.h   |  1 +
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/src/SDL12_compat.c b/src/SDL12_compat.c
index be11e1ef4..219653cb4 100644
--- a/src/SDL12_compat.c
+++ b/src/SDL12_compat.c
@@ -8358,7 +8358,27 @@ SDL_LoadWAV_RW(SDL12_RWops *rwops12, int freerwops12,
                SDL_AudioSpec *spec, Uint8 **buf, Uint32 *len)
 {
     SDL_RWops *rwops20 = RWops12to20(rwops12);
-    SDL_AudioSpec *retval = SDL20_LoadWAV_RW(rwops20, freerwops12, spec, buf, len);
+    SDL_AudioSpec *retval = NULL;
+
+    *buf = NULL;
+
+    /* SDL2's LoadWAV requires a seekable stream, but SDL 1.2 didn't,
+       so if the stream appears unseekable, try to load it into a
+       memory rwops that we _can_ seek in */
+    if (rwops20->seek(rwops20, 0, RW_SEEK_CUR) != -1) {  /* if seekable */
+        retval = SDL20_LoadWAV_RW(rwops20, freerwops12, spec, buf, len);
+    } else {
+        size_t datasize = 0;
+        void *buffer = SDL20_LoadFile_RW(rwops20, &datasize, freerwops12);
+        if (buffer) {
+            SDL_RWops *memrwops20 = SDL20_RWFromConstMem(buffer, (int) datasize);
+            if (memrwops20) {
+                retval = SDL20_LoadWAV_RW(memrwops20, 1, spec, buf, len);
+            }
+            SDL_free(buffer);
+        }
+    }
+
     if (retval && retval->format & 0x20) {
         SDL20_SetError("Unsupported 32-bit PCM data format");
         SDL20_FreeWAV(*buf);
diff --git a/src/SDL20_syms.h b/src/SDL20_syms.h
index cb6f9deee..a2dd92448 100644
--- a/src/SDL20_syms.h
+++ b/src/SDL20_syms.h
@@ -267,6 +267,7 @@ SDL20_SYM(SDL_RWops *,RWFromMem,(void *a, int b),(a,b),return)
 SDL20_SYM(SDL_RWops *,RWFromConstMem,(const void *a, int b),(a,b),return)
 SDL20_SYM(SDL_RWops *,AllocRW,(void),(),return)
 SDL20_SYM(void,FreeRW,(SDL_RWops *a),(a),)
+SDL20_SYM(void *,LoadFile_RW,(SDL_RWops *a, size_t *b, int c),(a,b,c),return)
 
 SDL20_SYM_PASSTHROUGH(void *,malloc,(size_t a),(a),return)
 SDL20_SYM_PASSTHROUGH(void *,calloc,(size_t a, size_t b),(a,b),return)