From 32803819a07859675b1d95b6aafd1674fe7835d8 Mon Sep 17 00:00:00 2001 From: Simon Howard Date: Sat, 12 Apr 2014 16:31:31 -0400 Subject: 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. --- textscreen/txt_sdl.c | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) (limited to 'textscreen/txt_sdl.c') diff --git a/textscreen/txt_sdl.c b/textscreen/txt_sdl.c index 984a2e75..26b4a361 100644 --- a/textscreen/txt_sdl.c +++ b/textscreen/txt_sdl.c @@ -58,6 +58,7 @@ typedef struct #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 @@ static void ChooseFont(void) 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 @@ void TXT_Shutdown(void) { free(screendata); screendata = NULL; + SDL_FreeSurface(screenbuffer); + screenbuffer = NULL; SDL_QuitSubSystem(SDL_INIT_VIDEO); } @@ -324,8 +332,8 @@ static inline void UpdateCharacter(int x, int y) 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; y1h; ++y1) @@ -357,7 +365,7 @@ static inline void UpdateCharacter(int x, int y) ++p; } - s += screen->pitch; + s += screenbuffer->pitch; } } @@ -379,6 +387,7 @@ static int LimitToRange(int val, int min, int max) 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 @@ void TXT_UpdateScreenArea(int x, int y, int w, int h) } } - 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) -- cgit v1.2.3