sdl12-compat: SDL_AudioCVT may be (or may not be...!) packed differently in SDL2.

From 512fe3bbe78df56d20a4947d623aa590a99bfc4e Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Fri, 18 Jun 2021 00:34:55 -0400
Subject: [PATCH] SDL_AudioCVT may be (or may not be...!) packed differently in
 SDL2.

---
 src/SDL12_compat.c          | 72 +++++++++++++++++++++++++++++++++++++
 src/SDL20_include_wrapper.h |  4 +++
 src/SDL20_syms.h            |  4 +--
 3 files changed, 78 insertions(+), 2 deletions(-)

diff --git a/src/SDL12_compat.c b/src/SDL12_compat.c
index 03b019c..e0b2eac 100644
--- a/src/SDL12_compat.c
+++ b/src/SDL12_compat.c
@@ -800,6 +800,23 @@ typedef struct
     SDL_Joystick *joystick;
 } JoystickOpenedItem;
 
+/* this is identical to SDL2, except SDL2 forced the structure packing in
+   some instances, so we can't passthrough without converting the struct. :( */
+typedef struct
+{
+    int needed;
+    Uint16 src_format;
+    Uint16 dst_format;
+    double rate_incr;
+    Uint8 *buf;
+    int len;
+    int len_cvt;
+    int len_mult;
+    double len_ratio;
+    void (SDLCALL *filters[10])(struct SDL_AudioCVT *cvt, Uint16 format);
+    int filter_index;
+} SDL12_AudioCVT;
+
 #include "SDL_opengl.h"
 #include "SDL_opengl_glext.h"
 
@@ -6902,6 +6919,61 @@ SDL_CloseAudio(void)
 }
 
 
+static SDL_AudioCVT *
+AudioCVT12to20(const SDL12_AudioCVT *cvt12, SDL_AudioCVT *cvt20)
+{
+    SDL_zerop(cvt20);
+    cvt20->needed = cvt12->needed;
+    cvt20->src_format = cvt12->src_format;
+    cvt20->dst_format = cvt12->dst_format;
+    cvt20->rate_incr = cvt12->rate_incr;
+    cvt20->buf = cvt12->buf;
+    cvt20->len = cvt12->len;
+    cvt20->len_cvt = cvt12->len_cvt;
+    cvt20->len_mult = cvt12->len_mult;
+    cvt20->len_ratio = cvt12->len_ratio;
+    SDL20_memcpy(cvt20->filters, cvt12->filters, sizeof (cvt12->filters));
+    cvt20->filter_index = cvt12->filter_index;
+    return cvt20;
+}
+
+static SDL12_AudioCVT *
+AudioCVT20to12(const SDL_AudioCVT *cvt20, SDL12_AudioCVT *cvt12)
+{
+    SDL_zerop(cvt12);
+    cvt12->needed = cvt20->needed;
+    cvt12->src_format = cvt20->src_format;
+    cvt12->dst_format = cvt20->dst_format;
+    cvt12->rate_incr = cvt20->rate_incr;
+    cvt12->buf = cvt20->buf;
+    cvt12->len = cvt20->len;
+    cvt12->len_cvt = cvt20->len_cvt;
+    cvt12->len_mult = cvt20->len_mult;
+    cvt12->len_ratio = cvt20->len_ratio;
+    SDL20_memcpy(cvt12->filters, cvt20->filters, sizeof (cvt20->filters));
+    cvt12->filter_index = cvt20->filter_index;
+    return cvt12;
+}
+
+DECLSPEC int SDLCALL
+SDL_BuildAudioCVT(SDL12_AudioCVT *cvt12, Uint16 src_format, Uint8 src_channels, int src_rate, Uint16 dst_format, Uint8 dst_channels, int dst_rate)
+{
+    SDL_AudioCVT cvt20;
+    const int retval = SDL20_BuildAudioCVT(&cvt20, src_format, src_channels, src_rate, dst_format, dst_channels, dst_rate);
+    AudioCVT20to12(&cvt20, cvt12);  /* SDL 1.2 derefences cvt12 without checking for NULL */
+    return retval;
+}
+
+DECLSPEC int SDLCALL
+SDL_ConvertAudio(SDL12_AudioCVT *cvt12)
+{
+    /* neither SDL 1.2 nor 2.0 makes sure cvt12 isn't NULL here.  :/  */
+    SDL_AudioCVT cvt20;
+    const int retval = SDL20_ConvertAudio(AudioCVT12to20(cvt12, &cvt20));
+    AudioCVT20to12(&cvt20, cvt12);
+    return retval;
+}
+
 
 /* SDL_GL_DisableContext and SDL_GL_EnableContext_Thread are not real SDL 1.2
    APIs, but some idTech4 games shipped with a custom SDL 1.2 build that added
diff --git a/src/SDL20_include_wrapper.h b/src/SDL20_include_wrapper.h
index f9d6c35..5316cda 100644
--- a/src/SDL20_include_wrapper.h
+++ b/src/SDL20_include_wrapper.h
@@ -96,6 +96,8 @@
 #define SDL_UnlockSurface IGNORE_THIS_VERSION_OF_SDL_UnlockSurface
 #define SDL_GetKeyName IGNORE_THIS_VERSION_OF_SDL_GetKeyName
 #define SDL_VideoInit IGNORE_THIS_VERSION_OF_SDL_VideoInit
+#define SDL_BuildAudioCVT IGNORE_THIS_VERSION_OF_SDL_BuildAudioCVT
+#define SDL_ConvertAudio IGNORE_THIS_VERSION_OF_SDL_ConvertAudio
 
 #define BUILD_SDL 1
 
@@ -201,6 +203,8 @@ typedef void (__cdecl *pfnSDL_CurrentEndThread) (unsigned);
 #undef SDL_UnlockSurface
 #undef SDL_GetKeyName
 #undef SDL_VideoInit
+#undef SDL_BuildAudioCVT
+#undef SDL_ConvertAudio
 
 #ifdef SDL_mutexP
 #undef SDL_mutexP
diff --git a/src/SDL20_syms.h b/src/SDL20_syms.h
index 9a8ef5b..baf6a02 100644
--- a/src/SDL20_syms.h
+++ b/src/SDL20_syms.h
@@ -194,8 +194,8 @@ SDL20_SYM(void,CloseAudio,(void),(),)
 SDL20_SYM(SDL_AudioStatus,GetAudioStatus,(void),(),return)
 SDL20_SYM(void,PauseAudio,(int a),(a),)
 SDL20_SYM_PASSTHROUGH(void,FreeWAV,(Uint8 *a),(a),)
-SDL20_SYM_PASSTHROUGH(int,BuildAudioCVT,(SDL_AudioCVT *a, Uint16 b, Uint8 c, int d, Uint16 e, Uint8 f, int g),(a,b,c,d,e,f,g),return)
-SDL20_SYM_PASSTHROUGH(int,ConvertAudio,(SDL_AudioCVT *a),(a),return)
+SDL20_SYM(int,BuildAudioCVT,(SDL_AudioCVT *a, Uint16 b, Uint8 c, int d, Uint16 e, Uint8 f, int g),(a,b,c,d,e,f,g),return)
+SDL20_SYM(int,ConvertAudio,(SDL_AudioCVT *a),(a),return)
 SDL20_SYM_PASSTHROUGH(void,MixAudio,(Uint8 *a, const Uint8 *b, Uint32 c, int d),(a,b,c,d),)
 SDL20_SYM_PASSTHROUGH(void,LockAudio,(void),(),)
 SDL20_SYM_PASSTHROUGH(void,UnlockAudio,(void),(),)