shithub: choc

Download patch

ref: 63624d71c11fe8292466a5c06e6cc71a48bf98bc
parent: e29c27e31acb04e67a715b9a2722c09b9574d374
author: Simon Howard <fraggle@gmail.com>
date: Sun Jan 20 11:18:16 EST 2008

Fix loading disk icon. Add back -1, -2, -3 command line options for
scale. Only allow 320x200, 640x400 special case for aspect ratio correct
when running fullscreen. Clean up "nearest mode" autoadjustment. Fix
crash with autoadjust when running windowed.

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

--- a/src/i_scale.c
+++ b/src/i_scale.c
@@ -72,7 +72,7 @@
 // 1x scale doesn't really do any scaling: it just copies the buffer
 // a line at a time for when pitch != SCREENWIDTH (!native_surface)
 
-static void I_Scale1x(int x1, int y1, int x2, int y2)
+static boolean I_Scale1x(int x1, int y1, int x2, int y2)
 {
     byte *bufp, *screenp;
     int y;
@@ -89,6 +89,8 @@
         screenp += dest_pitch;
         bufp += SCREENWIDTH;
     }
+
+    return true;
 }
 
 screen_mode_t mode_scale_1x = {
@@ -99,7 +101,7 @@
 
 // 2x scale (640x400)
 
-static void I_Scale2x(int x1, int y1, int x2, int y2)
+static boolean I_Scale2x(int x1, int y1, int x2, int y2)
 {
     byte *bufp, *screenp, *screenp2;
     int x, y;
@@ -127,6 +129,8 @@
         screenp2 += multi_pitch;
         bufp += SCREENWIDTH;
     }
+
+    return true;
 }
 
 screen_mode_t mode_scale_2x = {
@@ -137,7 +141,7 @@
 
 // 3x scale (960x600)
 
-static void I_Scale3x(int x1, int y1, int x2, int y2)
+static boolean I_Scale3x(int x1, int y1, int x2, int y2)
 {
     byte *bufp, *screenp, *screenp2, *screenp3;
     int x, y;
@@ -169,6 +173,8 @@
         screenp3 += multi_pitch;
         bufp += SCREENWIDTH;
     }
+
+    return true;
 }
 
 screen_mode_t mode_scale_3x = {
@@ -179,7 +185,7 @@
 
 // 4x scale (1280x800)
 
-static void I_Scale4x(int x1, int y1, int x2, int y2)
+static boolean I_Scale4x(int x1, int y1, int x2, int y2)
 {
     byte *bufp, *screenp, *screenp2, *screenp3, *screenp4;
     int x, y;
@@ -215,6 +221,8 @@
         screenp4 += multi_pitch;
         bufp += SCREENWIDTH;
     }
+
+    return true;
 }
 
 screen_mode_t mode_scale_4x = {
@@ -225,7 +233,7 @@
 
 // 5x scale (1600x1000)
 
-static void I_Scale5x(int x1, int y1, int x2, int y2)
+static boolean I_Scale5x(int x1, int y1, int x2, int y2)
 {
     byte *bufp, *screenp, *screenp2, *screenp3, *screenp4, *screenp5;
     int x, y;
@@ -265,6 +273,8 @@
         screenp5 += multi_pitch;
         bufp += SCREENWIDTH;
     }
+
+    return true;
 }
 
 screen_mode_t mode_scale_5x = {
@@ -396,7 +406,7 @@
 
 // 1x stretch (320x240)
 
-static void I_Stretch1x(int x1, int y1, int x2, int y2)
+static boolean I_Stretch1x(int x1, int y1, int x2, int y2)
 {
     byte *bufp, *screenp;
     int y;
@@ -405,7 +415,7 @@
 
     if (x1 != 0 || y1 != 0 || x2 != SCREENWIDTH || y2 != SCREENHEIGHT)
     {
-        return;
+        return false;
     }    
 
     // Need to byte-copy from buffer into the screen buffer
@@ -442,6 +452,8 @@
         memcpy(screenp, bufp, SCREENWIDTH);
         screenp += dest_pitch; bufp += SCREENWIDTH;
     }
+
+    return true;
 }
 
 screen_mode_t mode_stretch_1x = {
@@ -483,7 +495,7 @@
 
 // 2x stretch (640x480)
 
-static void I_Stretch2x(int x1, int y1, int x2, int y2)
+static boolean I_Stretch2x(int x1, int y1, int x2, int y2)
 {
     byte *bufp, *screenp;
     int y;
@@ -492,7 +504,7 @@
 
     if (x1 != 0 || y1 != 0 || x2 != SCREENWIDTH || y2 != SCREENHEIGHT)
     {
-        return;
+        return false;
     }    
 
     // Need to byte-copy from buffer into the screen buffer
@@ -553,6 +565,8 @@
         WriteLine2x(screenp, bufp);
         screenp += dest_pitch; bufp += SCREENWIDTH;
     }
+
+    return true;
 }
 
 screen_mode_t mode_stretch_2x = {
@@ -595,7 +609,7 @@
 
 // 3x stretch (960x720)
 
-static void I_Stretch3x(int x1, int y1, int x2, int y2)
+static boolean I_Stretch3x(int x1, int y1, int x2, int y2)
 {
     byte *bufp, *screenp;
     int y;
@@ -604,7 +618,7 @@
 
     if (x1 != 0 || y1 != 0 || x2 != SCREENWIDTH || y2 != SCREENHEIGHT)
     {
-        return;
+        return false;
     }    
 
     // Need to byte-copy from buffer into the screen buffer
@@ -689,6 +703,8 @@
         WriteLine3x(screenp, bufp);
         screenp += dest_pitch; bufp += SCREENWIDTH;
     }
+
+    return true;
 }
 
 screen_mode_t mode_stretch_3x = {
@@ -733,7 +749,7 @@
 
 // 4x stretch (1280x960)
 
-static void I_Stretch4x(int x1, int y1, int x2, int y2)
+static boolean I_Stretch4x(int x1, int y1, int x2, int y2)
 {
     byte *bufp, *screenp;
     int y;
@@ -742,7 +758,7 @@
 
     if (x1 != 0 || y1 != 0 || x2 != SCREENWIDTH || y2 != SCREENHEIGHT)
     {
-        return;
+        return false;
     }    
 
     // Need to byte-copy from buffer into the screen buffer
@@ -851,6 +867,8 @@
         WriteLine4x(screenp, bufp);
         screenp += dest_pitch; bufp += SCREENWIDTH;
     }
+
+    return true;
 }
 
 screen_mode_t mode_stretch_4x = {
@@ -877,7 +895,7 @@
 
 // 5x stretch (1600x1200)
 
-static void I_Stretch5x(int x1, int y1, int x2, int y2)
+static boolean I_Stretch5x(int x1, int y1, int x2, int y2)
 {
     byte *bufp, *screenp;
     int y;
@@ -886,7 +904,7 @@
 
     if (x1 != 0 || y1 != 0 || x2 != SCREENWIDTH || y2 != SCREENHEIGHT)
     {
-        return;
+        return false;
     }    
 
     // Need to byte-copy from buffer into the screen buffer
@@ -923,6 +941,8 @@
         WriteLine5x(screenp, bufp);
         screenp += dest_pitch; bufp += SCREENWIDTH;
     }
+
+    return true;
 }
 
 screen_mode_t mode_stretch_5x = {
@@ -978,7 +998,7 @@
 
 // 1x squashed (256x200)
 
-static void I_Squash1x(int x1, int y1, int x2, int y2)
+static boolean I_Squash1x(int x1, int y1, int x2, int y2)
 {
     byte *bufp, *screenp;
     int y;
@@ -987,7 +1007,7 @@
 
     if (x1 != 0 || y1 != 0 || x2 != SCREENWIDTH || y2 != SCREENHEIGHT)
     {
-        return;
+        return false;
     }    
 
     bufp = src_buffer;
@@ -1000,6 +1020,8 @@
         screenp += dest_pitch;
         bufp += SCREENWIDTH;
     }
+
+    return true;
 }
 
 screen_mode_t mode_squash_1x = {
@@ -1075,7 +1097,7 @@
 
 // 2x squash (512x400)
 
-static void I_Squash2x(int x1, int y1, int x2, int y2)
+static boolean I_Squash2x(int x1, int y1, int x2, int y2)
 {
     byte *bufp, *screenp;
     int y;
@@ -1084,7 +1106,7 @@
 
     if (x1 != 0 || y1 != 0 || x2 != SCREENWIDTH || y2 != SCREENHEIGHT)
     {
-        return;
+        return false;
     }    
 
     bufp = src_buffer;
@@ -1097,6 +1119,8 @@
         screenp += dest_pitch * 2;
         bufp += SCREENWIDTH;
     }
+
+    return true;
 }
 
 screen_mode_t mode_squash_2x = {
@@ -1155,7 +1179,7 @@
 // exactly.
 //
 
-static void I_Squash3x(int x1, int y1, int x2, int y2)
+static boolean I_Squash3x(int x1, int y1, int x2, int y2)
 {
     byte *bufp, *screenp;
     int y;
@@ -1164,7 +1188,7 @@
 
     if (x1 != 0 || y1 != 0 || x2 != SCREENWIDTH || y2 != SCREENHEIGHT)
     {
-        return;
+        return false;
     }    
 
     bufp = src_buffer;
@@ -1177,6 +1201,8 @@
         screenp += dest_pitch * 3;
         bufp += SCREENWIDTH;
     }
+
+    return true;
 }
 
 screen_mode_t mode_squash_3x = {
@@ -1263,7 +1289,7 @@
 // 4x squashed (1024x800)
 //
 
-static void I_Squash4x(int x1, int y1, int x2, int y2)
+static boolean I_Squash4x(int x1, int y1, int x2, int y2)
 {
     byte *bufp, *screenp;
     int y;
@@ -1272,7 +1298,7 @@
 
     if (x1 != 0 || y1 != 0 || x2 != SCREENWIDTH || y2 != SCREENHEIGHT)
     {
-        return;
+        return false;
     }    
 
     bufp = src_buffer;
@@ -1285,6 +1311,8 @@
         screenp += dest_pitch * 4;
         bufp += SCREENWIDTH;
     }
+
+    return true;
 }
 
 screen_mode_t mode_squash_4x = {
@@ -1325,7 +1353,7 @@
 // 5x squashed (1280x1000)
 //
 
-static void I_Squash5x(int x1, int y1, int x2, int y2)
+static boolean I_Squash5x(int x1, int y1, int x2, int y2)
 {
     byte *bufp, *screenp;
     int y;
@@ -1334,7 +1362,7 @@
 
     if (x1 != 0 || y1 != 0 || x2 != SCREENWIDTH || y2 != SCREENHEIGHT)
     {
-        return;
+        return false;
     }    
 
     bufp = src_buffer;
@@ -1347,6 +1375,8 @@
         screenp += dest_pitch * 5;
         bufp += SCREENWIDTH;
     }
+
+    return true;
 }
 
 screen_mode_t mode_squash_5x = {
--- a/src/i_video.c
+++ b/src/i_video.c
@@ -635,20 +635,23 @@
 // Update a small portion of the screen
 //
 // Does stretching and buffer blitting if neccessary
+//
+// Return true if blit was successful.
 
-static void BlitArea(int x1, int y1, int x2, int y2)
+static boolean BlitArea(int x1, int y1, int x2, int y2)
 {
-    void (*scale_function)(int x1, int y1, int x2, int y2);
     int x_offset, y_offset;
+    boolean result;
 
+    // No blit needed on native surface
+
     if (native_surface)
     {
-	return;
+	return true;
     }
 
     x_offset = (screen->w - screen_mode->width) / 2;
     y_offset = (screen->h - screen_mode->height) / 2;
-    scale_function = screen_mode->DrawScreen;
 
     if (SDL_LockSurface(screen) >= 0)
     {
@@ -656,28 +659,37 @@
                     (byte *) screen->pixels + (y_offset * screen->pitch)
                                             + x_offset, 
                     screen->pitch);
-        scale_function(x1, y1, x2, y2);
+        result = screen_mode->DrawScreen(x1, y1, x2, y2);
       	SDL_UnlockSurface(screen);
     }
+    else
+    {
+        result = false;
+    }
+
+    return result;
 }
 
 static void UpdateRect(int x1, int y1, int x2, int y2)
 {
+    int x1_scaled, x2_scaled, y1_scaled, y2_scaled;
+
     // Do stretching and blitting
 
-    BlitArea(x1, y1, x2, y2);
+    if (BlitArea(x1, y1, x2, y2))
+    {
+        // Update the area
 
-    // Update the area
+        x1_scaled = (x1 * screen_mode->width) / SCREENWIDTH;
+        y1_scaled = (y1 * screen_mode->height) / SCREENHEIGHT;
+        x2_scaled = (x2 * screen_mode->width) / SCREENWIDTH;
+        y2_scaled = (y2 * screen_mode->height) / SCREENHEIGHT;
 
-/*
-    TODO: fix loading disk
-
-    SDL_UpdateRect(screen, 
-                   x1 * screenmultiply, 
-                   y1 * screenmultiply, 
-                   (x2-x1) * screenmultiply, 
-                   (y2-y1) * screenmultiply);
-*/
+        SDL_UpdateRect(screen,
+                       x1_scaled, y1_scaled,
+                       x2_scaled - x1_scaled,
+                       y2_scaled - y1_scaled);
+    }
 }
 
 void I_BeginRead(void)
@@ -852,92 +864,6 @@
     SDL_FreeSurface(surface);
 }
 
-static void CheckCommandLine(void)
-{
-    int i;
-
-    //!
-    // @category video 
-    //
-    // Grab the mouse when running in windowed mode.
-    //
-
-    if (M_CheckParm("-grabmouse"))
-    {
-        grabmouse = true;
-    }
-
-    //!
-    // @category video 
-    //
-    // Don't grab the mouse when running in windowed mode.
-    //
-
-    if (M_CheckParm("-nograbmouse"))
-    {
-        grabmouse = false;
-    }
-
-    // default to fullscreen mode, allow override with command line
-    // nofullscreen because we love prboom
-
-    //!
-    // @category video 
-    //
-    // Run in a window.
-    //
-
-    if (M_CheckParm("-window") || M_CheckParm("-nofullscreen"))
-    {
-        fullscreen = false;
-    }
-
-    //!
-    // @category video 
-    //
-    // Run in fullscreen mode.
-    //
-
-    if (M_CheckParm("-fullscreen"))
-    {
-        fullscreen = true;
-    }
-
-    //!
-    // @category video 
-    //
-    // Disable the mouse.
-    //
-
-    nomouse = M_CheckParm("-nomouse") > 0;
-
-    //!
-    // @category video
-    //
-    // Specify the screen width, in pixels.
-    //
-
-    i = M_CheckParm("-width");
-
-    if (i > 0)
-    {
-        screen_width = atoi(myargv[i + 1]);
-    }
-
-    //!
-    // @category video
-    //
-    // Specify the screen height, in pixels.
-    //
-
-    i = M_CheckParm("-height");
-
-    if (i > 0)
-    {
-        screen_height = atoi(myargv[i + 1]);
-    }
-}
-
 // Pick the modes list to use:
 
 static void GetScreenModes(screen_mode_t ***modes_list, int *num_modes)
@@ -969,14 +895,17 @@
     // ratio correction is turned on.  These modes have non-square
     // pixels.
 
-    if (w == SCREENWIDTH && h == SCREENHEIGHT)
+    if (fullscreen)
     {
-        return &mode_scale_1x;
+        if (w == SCREENWIDTH && h == SCREENHEIGHT)
+        {
+            return &mode_scale_1x;
+        }
+        else if (w == SCREENWIDTH*2 && h == SCREENHEIGHT*2)
+        {
+            return &mode_scale_2x;
+        }
     }
-    else if (w == SCREENWIDTH*2 && h == SCREENHEIGHT*2)
-    {
-        return &mode_scale_2x;
-    }
 
     GetScreenModes(&modes_list, &modes_list_length);
 
@@ -1019,7 +948,7 @@
         SDL_Rect **modes;
         SDL_Rect *best_mode;
         screen_mode_t *screen_mode;
-        int num_pixels, best_num_pixels;
+        int target_pixels, num_pixels, best_num_pixels;
         int i;
 
         modes = SDL_ListModes(NULL, SDL_FULLSCREEN);
@@ -1029,6 +958,7 @@
 
         best_mode = NULL;
         best_num_pixels = INT_MAX;
+        target_pixels = screen_width * screen_height;
 
         for (i=0; modes[i] != NULL; ++i) 
         {
@@ -1056,19 +986,12 @@
                 return;
             }
 
-            // Only use modes bigger than the specified mode
-
-            if (modes[i]->w < screen_width || modes[i]->h < screen_height)
-            {
-            //    printf("\t< %ix%i\n", screen_width, screen_height);
-                continue;
-            }
-
             // Is this mode better than the current mode?
 
             num_pixels = modes[i]->w * modes[i]->h;
 
-            if (num_pixels < best_num_pixels)
+            if (abs(num_pixels - target_pixels) 
+              < abs(best_num_pixels - target_pixels))
             {
             //    printf("\tA valid mode\n");
                 best_num_pixels = num_pixels;
@@ -1080,20 +1003,7 @@
         {
             // Unable to find a valid mode!
 
-            if (screen_width <= SCREENWIDTH && screen_height <= SCREENHEIGHT)
-            {
-                I_Error("Unable to find any valid video mode at all!");
-            }
-
-            // Reset back to the original defaults and try to find a
-            // mode
-
-            screen_width = SCREENWIDTH;
-            screen_height = SCREENHEIGHT;
-
-            I_AutoAdjustSettings();
-          
-            return;
+            I_Error("Unable to find any valid video mode at all!");
         }
 
         printf("I_InitGraphics: %ix%i mode not supported on this machine.\n",
@@ -1115,6 +1025,14 @@
 
         best_mode = I_FindScreenMode(screen_width, screen_height);
 
+        if (best_mode == NULL) 
+        {
+            // Nothing fits within the current settings.
+            // Pick the closest to 320x200 possible.
+
+            best_mode = I_FindScreenMode(SCREENWIDTH, SCREENHEIGHT_4_3);
+        }
+
         // Do we have the exact mode already?
 
         if (best_mode->width == screen_width 
@@ -1137,6 +1055,208 @@
            "To disable this behavior,\n"
            "set autoadjust_video_settings to 0 in your "
            "configuration file.\n");
+}
+
+// Set video size to a particular scale factor (1x, 2x, 3x, etc.)
+
+static void SetScaleFactor(int factor)
+{
+    if (fullscreen)
+    {
+        // In fullscreen, find a mode that will provide this scale factor
+
+        SDL_Rect **modes;
+        SDL_Rect *best_mode;
+        screen_mode_t *scrmode;
+        int best_num_pixels, num_pixels;
+        int i;
+
+        modes = SDL_ListModes(NULL, SDL_FULLSCREEN);
+
+        best_mode = NULL;
+        best_num_pixels = INT_MAX;
+
+        for (i=0; modes[i] != NULL; ++i)
+        {
+            // What screen_mode_t will this use?
+
+            scrmode = I_FindScreenMode(modes[i]->w, modes[i]->h);
+
+            if (scrmode == NULL)
+            {
+                continue;
+            }
+
+            // Only choose modes that fit the requested scale factor.
+            //
+            // Note that this allows 320x240 as valid for 1x scale, as 
+            // 240/200 is rounded down to 1 by integer division.
+
+            if ((scrmode->width / SCREENWIDTH) != factor
+             || (scrmode->height / SCREENHEIGHT) != factor)
+            {
+                continue;
+            }
+
+            // Is this a better mode than what we currently have?
+
+            num_pixels = modes[i]->w * modes[i]->h;
+
+            if (num_pixels < best_num_pixels)
+            {
+                best_num_pixels = num_pixels;
+                best_mode = modes[i];
+            }
+        }
+
+        if (best_mode == NULL)
+        {
+            I_Error("No fullscreen graphics mode available to support "
+                    "%ix scale factor!", factor);
+        }
+
+        screen_width = best_mode->w;
+        screen_height = best_mode->h;
+    }
+    else
+    {
+        int w, h;
+
+        // Pick 320x200 or 320x240, depending on aspect ratio correct
+
+        if (aspect_ratio_correct)
+        {
+            w = SCREENWIDTH;
+            h = SCREENHEIGHT_4_3;
+        }
+        else 
+        {
+            w = SCREENWIDTH;
+            h = SCREENHEIGHT;
+        }
+
+        screen_width = w * factor;
+        screen_height = h * factor;
+    }
+}
+
+static void CheckCommandLine(void)
+{
+    int i;
+
+    //!
+    // @category video 
+    //
+    // Grab the mouse when running in windowed mode.
+    //
+
+    if (M_CheckParm("-grabmouse"))
+    {
+        grabmouse = true;
+    }
+
+    //!
+    // @category video 
+    //
+    // Don't grab the mouse when running in windowed mode.
+    //
+
+    if (M_CheckParm("-nograbmouse"))
+    {
+        grabmouse = false;
+    }
+
+    // default to fullscreen mode, allow override with command line
+    // nofullscreen because we love prboom
+
+    //!
+    // @category video 
+    //
+    // Run in a window.
+    //
+
+    if (M_CheckParm("-window") || M_CheckParm("-nofullscreen"))
+    {
+        fullscreen = false;
+    }
+
+    //!
+    // @category video 
+    //
+    // Run in fullscreen mode.
+    //
+
+    if (M_CheckParm("-fullscreen"))
+    {
+        fullscreen = true;
+    }
+
+    //!
+    // @category video 
+    //
+    // Disable the mouse.
+    //
+
+    nomouse = M_CheckParm("-nomouse") > 0;
+
+    //!
+    // @category video
+    //
+    // Specify the screen width, in pixels.
+    //
+
+    i = M_CheckParm("-width");
+
+    if (i > 0)
+    {
+        screen_width = atoi(myargv[i + 1]);
+    }
+
+    //!
+    // @category video
+    //
+    // Specify the screen height, in pixels.
+    //
+
+    i = M_CheckParm("-height");
+
+    if (i > 0)
+    {
+        screen_height = atoi(myargv[i + 1]);
+    }
+
+    //!
+    // @category video
+    //
+    // Don't scale up the screen.
+    //
+
+    if (M_CheckParm("-1")) 
+    {
+        SetScaleFactor(1);
+    }
+
+    //!
+    // @category video
+    //
+    // Double up the screen to 2x its normal size.
+    //
+
+    if (M_CheckParm("-2")) 
+    {
+        SetScaleFactor(2);
+    }
+
+    //!
+    // @category video
+    //
+    // Double up the screen to 3x its normal size.
+    //
+
+    if (M_CheckParm("-3")) 
+    {
+        SetScaleFactor(3);
+    }
 }
 
 // Check if we have been invoked as a screensaver by xscreensaver.
--- a/src/i_video.h
+++ b/src/i_video.h
@@ -46,8 +46,9 @@
         void (*InitMode)(byte *palette);
         
         // Function to call to draw the screen from the source buffer.
+        // Return true if draw was successful.
 
-        void (*DrawScreen)(int x1, int y1, int x2, int y2);
+        boolean (*DrawScreen)(int x1, int y1, int x2, int y2);
 
         // If true, this is a "poor quality" mode.  The autoadjust 
         // code should always attempt to use a different mode to this