shithub: choc

Download patch

ref: 32803819a07859675b1d95b6aafd1674fe7835d8
parent: a1b066a0eb0d2cf5d17ad68ca833fcdd21f80725
author: Simon Howard <fraggle@gmail.com>
date: Sat Apr 12 12:31:31 EDT 2014

textscreen: Init screen at native bit depth.

Always call SDL_SetVideoMode with bpp=0 to use the desktop's native
bit depth, and instead draw into an intermediate 8-bit screenbuffer
surface. This ensures that we do not encounter any palette mess-ups
as on some systems true 8-bit screen modes are poorly supported.

--- a/textscreen/txt_sdl.c
+++ b/textscreen/txt_sdl.c
@@ -58,6 +58,7 @@
 #define BLINK_PERIOD 250
 
 static SDL_Surface *screen;
+static SDL_Surface *screenbuffer;
 static unsigned char *screendata;
 static int key_mapping = 1;
 
@@ -246,24 +247,29 @@
 
 int TXT_Init(void)
 {
-    int flags;
-
     if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
     {
         return 0;
     }
 
-    flags = SDL_SWSURFACE | SDL_HWPALETTE | SDL_DOUBLEBUF;
-
     ChooseFont();
 
+    // Always create the screen at the native screen depth (bpp=0);
+    // some systems nowadays don't seem to support true 8-bit palettized
+    // screen modes very well and we end up with screwed up colors.
     screen = SDL_SetVideoMode(TXT_SCREEN_W * font->w,
-                              TXT_SCREEN_H * font->h, 8, flags);
+                              TXT_SCREEN_H * font->h, 0, 0);
 
     if (screen == NULL)
         return 0;
 
-    SDL_SetColors(screen, ega_colors, 0, 16);
+    // Instead, we draw everything into an intermediate 8-bit surface
+    // the same dimensions as the screen. SDL then takes care of all the
+    // 8->32 bit (or whatever depth) color conversions for us.
+    screenbuffer = SDL_CreateRGBSurface(0, TXT_SCREEN_W * font->w,
+                                        TXT_SCREEN_H * font->h,
+                                        8, 0, 0, 0, 0);
+    SDL_SetColors(screenbuffer, ega_colors, 0, 16);
     SDL_EnableUNICODE(1);
 
     screendata = malloc(TXT_SCREEN_W * TXT_SCREEN_H * 2);
@@ -285,6 +291,8 @@
 {
     free(screendata);
     screendata = NULL;
+    SDL_FreeSurface(screenbuffer);
+    screenbuffer = NULL;
     SDL_QuitSubSystem(SDL_INIT_VIDEO);
 }
 
@@ -324,8 +332,8 @@
     bytes = (font->w + 7) / 8;
     p = &font->data[character * font->h * bytes];
 
-    s = ((unsigned char *) screen->pixels)
-      + (y * font->h * screen->pitch)
+    s = ((unsigned char *) screenbuffer->pixels)
+      + (y * font->h * screenbuffer->pitch)
       + (x * font->w);
 
     for (y1=0; y1<font->h; ++y1)
@@ -357,7 +365,7 @@
             ++p;
         }
 
-        s += screen->pitch;
+        s += screenbuffer->pitch;
     }
 }
 
@@ -379,6 +387,7 @@
 
 void TXT_UpdateScreenArea(int x, int y, int w, int h)
 {
+    SDL_Rect rect;
     int x1, y1;
     int x_end;
     int y_end;
@@ -396,9 +405,13 @@
         }
     }
 
-    SDL_UpdateRect(screen,
-                   x * font->w, y * font->h,
-                   (x_end - x) * font->w, (y_end - y) * font->h);
+    rect.x = x * font->w;
+    rect.y = y * font->h;
+    rect.w = (x_end - x) * font->w;
+    rect.h = (y_end - y) * font->h;
+
+    SDL_BlitSurface(screenbuffer, &rect, screen, &rect);
+    SDL_UpdateRects(screen, 1, &rect);
 }
 
 void TXT_UpdateScreen(void)