shithub: choc

Download patch

ref: b03de59700f80c75308849ac5f89310d010af066
parent: 167d4df40b55f2e8b559a797bb93b09554a871d0
author: Simon Howard <fraggle@gmail.com>
date: Sun Nov 21 10:44:43 EST 2010

Add -8in32 command line parameter to make the game run in 32-bit color
mode, scaling up into an intermediate 8-bit buffer first. This should
help with the palette problems experienced by Windows Vista/7 users.

Subversion-branch: /trunk/chocolate-doom
Subversion-revision: 2164

--- a/src/i_video.c
+++ b/src/i_video.c
@@ -93,6 +93,12 @@
 
 static SDL_Surface *screen;
 
+// Intermediate 8-bit buffer that we draw to instead of 'screen'.
+// This is used when we are rendering in 32-bit screen mode.
+// When in a real 8-bit screen mode, screenbuffer == screen.
+
+static SDL_Surface *screenbuffer;
+
 // palette
 
 static SDL_Color palette[256];
@@ -750,17 +756,18 @@
 	return true;
     }
 
-    x_offset = (screen->w - screen_mode->width) / 2;
-    y_offset = (screen->h - screen_mode->height) / 2;
+    x_offset = (screenbuffer->w - screen_mode->width) / 2;
+    y_offset = (screenbuffer->h - screen_mode->height) / 2;
 
-    if (SDL_LockSurface(screen) >= 0)
+    if (SDL_LockSurface(screenbuffer) >= 0)
     {
-        I_InitScale(screens[0], 
-                    (byte *) screen->pixels + (y_offset * screen->pitch)
-                                            + x_offset, 
-                    screen->pitch);
+        I_InitScale(screens[0],
+                    (byte *) screenbuffer->pixels
+                                + (y_offset * screenbuffer->pitch)
+                                + x_offset,
+                    screenbuffer->pitch);
         result = screen_mode->DrawScreen(x1, y1, x2, y2);
-      	SDL_UnlockSurface(screen);
+      	SDL_UnlockSurface(screenbuffer);
     }
     else
     {
@@ -895,19 +902,30 @@
     // draw to screen
 
     BlitArea(0, 0, SCREENWIDTH, SCREENHEIGHT);
-    
-    // If we have a palette to set, the act of setting the palette
-    // updates the screen
 
     if (palette_to_set)
     {
-        SDL_SetColors(screen, palette, 0, 256);
+        SDL_SetColors(screenbuffer, palette, 0, 256);
         palette_to_set = false;
+
+        // In native 8-bit mode, if we have a palette to set, the act
+        // of setting the palette updates the screen
+
+        if (screenbuffer == screen)
+        {
+            return;
+        }
     }
-    else
+
+    // In 8in32 mode, we must blit from the fake 8-bit screen buffer
+    // to the real screen before doing a screen flip.
+
+    if (screenbuffer != screen)
     {
-        SDL_Flip(screen);
+        SDL_BlitSurface(screenbuffer, NULL, screen, NULL);
     }
+
+    SDL_Flip(screen);
 }
 
 
@@ -1540,6 +1558,7 @@
 {
     byte *doompal;
     int flags = 0;
+    int bpp = 8;
 
     doompal = W_CacheLumpName(DEH_String("PLAYPAL"), PU_CACHE);
 
@@ -1552,8 +1571,17 @@
 
     // Set the video mode.
 
-    flags |= SDL_SWSURFACE | SDL_HWPALETTE | SDL_DOUBLEBUF;
+    flags |= SDL_SWSURFACE;
 
+    if (M_CheckParm("-8in32"))
+    {
+        bpp = 32;
+    }
+    else
+    {
+        flags |= SDL_HWPALETTE | SDL_DOUBLEBUF;
+    }
+
     if (fullscreen)
     {
         flags |= SDL_FULLSCREEN;
@@ -1563,13 +1591,25 @@
         flags |= SDL_RESIZABLE;
     }
 
-    screen = SDL_SetVideoMode(w, h, 8, flags);
+    screen = SDL_SetVideoMode(w, h, bpp, flags);
 
     if (screen == NULL)
     {
-        I_Error("Error setting video mode: %s\n", SDL_GetError());
+        I_Error("Error setting video mode %ix%ix%ibpp: %s\n",
+                w, h, bpp, SDL_GetError());
     }
 
+    if (screen->format->BitsPerPixel == 8)
+    {
+        screenbuffer = screen;
+    }
+    else
+    {
+        screenbuffer = SDL_CreateRGBSurface(SDL_SWSURFACE,
+                                            screen->w, screen->h, 8,
+                                            0, 0, 0, 0);
+    }
+
     // If mode was not set, it must be set now that we know the
     // screen size.
 
@@ -1708,25 +1748,20 @@
     // Start with a clear black screen
     // (screen will be flipped after we set the palette)
 
-    if (SDL_LockSurface(screen) >= 0)
-    {
-        byte *screenpixels;
-        int y;
+    SDL_FillRect(screenbuffer, NULL, 0);
 
-        screenpixels = (byte *) screen->pixels;
-
-        for (y=0; y<screen->h; ++y)
-            memset(screenpixels + screen->pitch * y, 0, screen->w);
-
-        SDL_UnlockSurface(screen);
-    }
-
     // Set the palette
 
     doompal = W_CacheLumpName(DEH_String("PLAYPAL"), PU_CACHE);
     I_SetPalette(doompal);
-    SDL_SetColors(screen, palette, 0, 256);
+    SDL_SetColors(screenbuffer, palette, 0, 256);
 
+    if (screen != screenbuffer)
+    {
+        SDL_BlitSurface(screenbuffer, NULL, screen, NULL);
+        SDL_Flip(screen);
+    }
+
     CreateCursors();
 
     UpdateFocus();
@@ -1747,7 +1782,8 @@
     // Likewise if the screen pitch is not the same as the width
     // If we have to multiply, drawing is done to a separate 320x200 buf
 
-    native_surface = !SDL_MUSTLOCK(screen)
+    native_surface = screen == screenbuffer
+                  && !SDL_MUSTLOCK(screen)
                   && screen_mode == &mode_scale_1x
                   && screen->pitch == SCREENWIDTH
                   && aspect_ratio_correct;