sdl12-compat: audio: SDL_MixAudio has to respect app format, which we might be faking.

From 3c80688bbedb336879619199feac05234f9b97a3 Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Mon, 3 Oct 2022 20:40:22 -0400
Subject: [PATCH] audio: SDL_MixAudio has to respect app format, which we might
 be faking.

Fixes #228.
---
 src/SDL12_compat.c          | 34 ++++++++++++++++++++++++++++++++--
 src/SDL20_include_wrapper.h |  2 ++
 src/SDL20_syms.h            |  2 +-
 3 files changed, 35 insertions(+), 3 deletions(-)

diff --git a/src/SDL12_compat.c b/src/SDL12_compat.c
index f93c6bd60..db151fe1a 100644
--- a/src/SDL12_compat.c
+++ b/src/SDL12_compat.c
@@ -8844,7 +8844,7 @@ FakeCdRomAudioCallback(AudioCallbackWrapperData *data, Uint8 *stream, int len, c
             SDL20_AudioStreamGet(data->cdrom_stream, stream, available);
         } else {
             SDL20_AudioStreamGet(data->cdrom_stream, data->mix_buffer, available);
-            SDL20_MixAudio(stream, data->mix_buffer, available, SDL_MIX_MAXVOLUME);
+            SDL20_MixAudioFormat(stream, data->mix_buffer, audio_cbdata->device_format.format, available, SDL_MIX_MAXVOLUME);
         }
 
         data->cdrom_pcm_frames_written += (int) ((available / ((double) SDL_AUDIO_BITSIZE(data->device_format.format) / 8.0)) / data->device_format.channels);
@@ -9152,6 +9152,37 @@ SDL_GetAudioStatus(void)
     return retval;
 }
 
+DECLSPEC12 void SDLCALL
+SDL_MixAudio(Uint8 *dst, const Uint8 *src, Uint32 len, int volume)
+{
+    SDL_AudioFormat fmt;
+
+    if (volume == 0) {
+        return;  /* nothing to do. */
+    }
+
+    /* in 1.2, if not the subsystem isn't initialized _at all_, it forces
+       format to AUDIO_S16. If it's initialized but the device isn't opened,
+       you get a format of zero and it returns an error without mixing
+       anything. */
+    SDL20_LockAudio();
+    if ((InitializedSubsystems20 & SDL_INIT_AUDIO) != SDL_INIT_AUDIO) {
+        fmt = AUDIO_S16;  /* to quote 1.2: "HACK HACK HACK" */
+    } else if (!audio_cbdata || !audio_cbdata->app_callback_opened) {
+        fmt = 0;  /* this will fail, but drop the lock first. */
+    } else {
+        fmt = audio_cbdata->app_callback_format.format;
+    }
+    SDL20_UnlockAudio();
+
+    if (fmt == 0) {
+        SDL_SetError("SDL_MixAudio(): unknown audio format");  /* this is the exact error 1.2 reports for this. */
+    } else {
+        SDL20_MixAudioFormat(dst, src, fmt, len, volume);
+    }
+}
+
+
 DECLSPEC12 void SDLCALL
 SDL_CloseAudio(void)
 {
@@ -9166,7 +9197,6 @@ SDL_CloseAudio(void)
     CloseSDL2AudioDevice();
 }
 
-
 static SDL_AudioCVT *
 AudioCVT12to20(const SDL12_AudioCVT *cvt12, SDL_AudioCVT *cvt20)
 {
diff --git a/src/SDL20_include_wrapper.h b/src/SDL20_include_wrapper.h
index 4d4be2220..adea80acc 100644
--- a/src/SDL20_include_wrapper.h
+++ b/src/SDL20_include_wrapper.h
@@ -113,6 +113,7 @@
 #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 SDL_MixAudio IGNORE_THIS_VERSION_OF_SDL_MixAudio
 #define SDL_RegisterApp IGNORE_THIS_VERSION_OF_SDL_RegisterApp
 #define SDL_UnregisterApp IGNORE_THIS_VERSION_OF_SDL_UnregisterApp
 
@@ -242,6 +243,7 @@ typedef void (__cdecl *pfnSDL_CurrentEndThread) (unsigned);
 #undef SDL_VideoInit
 #undef SDL_BuildAudioCVT
 #undef SDL_ConvertAudio
+#undef SDL_MixAudio
 #undef SDL_RegisterApp
 #undef SDL_UnregisterApp
 
diff --git a/src/SDL20_syms.h b/src/SDL20_syms.h
index e5469b8b5..cb54bdf0e 100644
--- a/src/SDL20_syms.h
+++ b/src/SDL20_syms.h
@@ -206,7 +206,7 @@ SDL20_SYM(void,PauseAudio,(int a),(a),)
 SDL20_SYM_PASSTHROUGH(void,FreeWAV,(Uint8 *a),(a),)
 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(void,MixAudioFormat,(Uint8 *a, const Uint8 *b, SDL_AudioFormat c, Uint32 d, int e),(a,b,c,d,e),)
 SDL20_SYM_PASSTHROUGH(void,LockAudio,(void),(),)
 SDL20_SYM_PASSTHROUGH(void,UnlockAudio,(void),(),)