sdl12-compat: Support SDL_PHYSPAL

From 6c7eba114e51779dd8562f5834829f2ee591934e Mon Sep 17 00:00:00 2001
From: David Gow <[EMAIL REDACTED]>
Date: Tue, 25 May 2021 14:08:26 +0800
Subject: [PATCH] Support SDL_PHYSPAL

Add a separate SDL_Palette to represent the physical palette, and swap
it in and out in PresentScreen().

Note that we have to manually swap the pointers in
surface20->format->palette, as SDL20_SetSurfacePalette seems to just
update the colours(?), resulting in the logical and physical palettes
ending up the same.
---
 src/SDL12_compat.c | 20 +++++++++++++++++++-
 src/SDL20_syms.h   |  2 ++
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/src/SDL12_compat.c b/src/SDL12_compat.c
index de95d1a..35a922c 100644
--- a/src/SDL12_compat.c
+++ b/src/SDL12_compat.c
@@ -793,6 +793,7 @@ static SDL_Window *VideoWindow20 = NULL;
 static SDL_Renderer *VideoRenderer20 = NULL;
 static SDL_Texture *VideoTexture20 = NULL;
 static SDL12_Surface *VideoSurface12 = NULL;
+static SDL_Palette *VideoPhysicalPalette20 = NULL;
 static Uint32 VideoSurfacePresentTicks = 0;
 static Uint32 VideoSurfaceLastPresentTicks = 0;
 static SDL_Surface *VideoConvertSurface20 = NULL;
@@ -3171,6 +3172,10 @@ EndVidModeCreate(void)
         SDL20_DestroyWindow(VideoWindow20);
         VideoWindow20 = NULL;
     }
+    if (VideoPhysicalPalette20) {
+        SDL20_FreePalette(VideoPhysicalPalette20);
+        VideoPhysicalPalette20 = NULL;
+    }
     if (VideoSurface12) {
         SDL20_free(VideoSurface12->pixels);
         VideoSurface12->pixels = NULL;
@@ -3570,6 +3575,10 @@ SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags12)
                 { const int x = (i & 0x3) | ((i & 0x3) << 2); color->b = x | x << 4; }
                 color->a = 255;
             }
+            if (!VideoPhysicalPalette20) {
+                VideoPhysicalPalette20 = SDL20_AllocPalette(256);
+            }
+            SDL20_SetPaletteColors(VideoPhysicalPalette20, VideoSurface12->format->palette->colors, 0, 256);
         }
     }
 
@@ -3838,6 +3847,9 @@ PresentScreen(void)
 
     SDL_assert(VideoSurface12 != NULL);
 
+    SDL_Palette *logicalPal = VideoSurface12->surface20->format->palette;
+    VideoSurface12->surface20->format->palette = VideoPhysicalPalette20;
+
     if (SDL20_LockTexture(VideoTexture20, NULL, &pixels, &pitch) < 0) {
         return;  /* oh well */
     }
@@ -3878,6 +3890,7 @@ PresentScreen(void)
     }
 
     SDL20_RenderPresent(VideoRenderer20);
+    VideoSurface12->surface20->format->palette = logicalPal;
     VideoSurfaceLastPresentTicks = SDL20_GetTicks();
     VideoSurfacePresentTicks = 0;
 }
@@ -4237,13 +4250,18 @@ SDL_SetPalette(SDL12_Surface *surface12, int flags, const SDL_Color *colors,
             retval = -1;
         }
     }
+    
+    if (flags & SDL12_PHYSPAL) {
+        if (SDL20_SetPaletteColors(VideoPhysicalPalette20, opaquecolors, firstcolor, ncolors) < 0) {
+            retval = -1;
+        }
+    }
 
     SDL20_free(opaquecolors);
 
     /* in case this pointer changed... */
     palette12->colors = palette20->colors;
 
-    FIXME("We need to store the physical palette somewhere");  /* it might be different that logical palette and it will be needed for future blits. */
     if ((surface12 == VideoSurface12) && (flags & SDL12_PHYSPAL)) {
         SDL_UpdateRect(surface12, 0, 0, 0, 0);   /* force screen to reblit with new palette. */
     }
diff --git a/src/SDL20_syms.h b/src/SDL20_syms.h
index 9246835..dcddbe2 100644
--- a/src/SDL20_syms.h
+++ b/src/SDL20_syms.h
@@ -115,6 +115,8 @@ SDL20_SYM(int,SetSurfaceBlendMode,(SDL_Surface *a, SDL_BlendMode b),(a,b),return
 SDL20_SYM(int,GetSurfaceBlendMode,(SDL_Surface *a, SDL_BlendMode *b),(a,b),return)
 SDL20_SYM(SDL_Surface*,LoadBMP_RW,(SDL_RWops *a, int b),(a,b),return)
 SDL20_SYM(int,SaveBMP_RW,(SDL_Surface *a, SDL_RWops *b, int c),(a,b,c),return)
+SDL20_SYM(SDL_Palette*,AllocPalette,(int a),(a),return)
+SDL20_SYM(void,FreePalette,(SDL_Palette *a),(a),)
 SDL20_SYM(int,SetPaletteColors,(SDL_Palette *a, const SDL_Color *b, int c, int d),(a,b,c,d),return)
 SDL20_SYM(SDL_bool,GL_ExtensionSupported,(const char *a),(a),return)
 SDL20_SYM(int,GL_LoadLibrary,(const char *a),(a),return)