ref: 32803819a07859675b1d95b6aafd1674fe7835d8
parent: a1b066a0eb0d2cf5d17ad68ca833fcdd21f80725
author: Simon Howard <[email protected]>
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)