ref: 265c0de3419b5123052a10cef276e1221cd0630c
parent: 136009e7505acc321c2b7f710929cb7d9b88a5b2
author: Simon Howard <fraggle@gmail.com>
date: Fri Dec 15 14:35:46 EST 2006
Split off scaling code into i_scale.c. Add aspect ratio correction stretching (fullscreen 320x240, 640x480, etc)! Subversion-branch: /trunk/chocolate-doom Subversion-revision: 771
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -60,6 +60,7 @@
hu_stuff.c hu_stuff.h \
i_main.c \
info.c info.h \
+i_scale.c i_scale.h \
i_sound.c i_sound.h \
i_system.c i_system.h \
i_timer.c i_timer.h \
--- /dev/null
+++ b/src/i_scale.c
@@ -1,0 +1,404 @@
+
+#include "doomdef.h"
+#include "doomtype.h"
+
+#include "z_zone.h"
+
+// Should be screens[0]
+
+static byte *src_buffer;
+
+// Destination buffer, ie. screen->pixels.
+
+static byte *dest_buffer;
+
+// Pitch of destination buffer, ie. screen->pitch.
+
+static int dest_pitch;
+
+// Lookup tables used for aspect ratio correction stretching code.
+// stretch_tables[0] : 20% / 80%
+// stretch_tables[1] : 40% / 60%
+// All other combinations can be reached from these two tables.
+
+static byte *stretch_tables[2];
+
+void I_InitScale(byte *_src_buffer, byte *_dest_buffer, int _dest_pitch)
+{
+ src_buffer = _src_buffer;
+ dest_buffer = _dest_buffer;
+ dest_pitch = _dest_pitch;
+}
+
+void I_Scale1x(int x1, int y1, int x2, int y2)
+{
+ byte *bufp, *screenp;
+ int y;
+ int w = x2 - x1;
+
+ // Need to byte-copy from buffer into the screen buffer
+
+ bufp = src_buffer + y1 * SCREENWIDTH + x1;
+ screenp = (byte *) dest_buffer + y1 * dest_pitch + x1;
+
+ for (y=y1; y<y2; ++y)
+ {
+ memcpy(screenp, bufp, w);
+ screenp += dest_pitch;
+ bufp += SCREENWIDTH;
+ }
+}
+
+void I_Scale2x(int x1, int y1, int x2, int y2)
+{
+ byte *bufp, *screenp, *screenp2;
+ int x, y;
+ int multi_pitch;
+
+ multi_pitch = dest_pitch * 2;
+ bufp = src_buffer + y1 * SCREENWIDTH + x1;
+ screenp = (byte *) dest_buffer + (y1 * dest_pitch + x1) * 2;
+ screenp2 = screenp + dest_pitch;
+
+ for (y=y1; y<y2; ++y)
+ {
+ byte *sp, *sp2, *bp;
+ sp = screenp;
+ sp2 = screenp2;
+ bp = bufp;
+
+ for (x=x1; x<x2; ++x)
+ {
+ *sp++ = *bp; *sp++ = *bp;
+ *sp2++ = *bp; *sp2++ = *bp;
+ ++bp;
+ }
+ screenp += multi_pitch;
+ screenp2 += multi_pitch;
+ bufp += SCREENWIDTH;
+ }
+}
+
+void I_Scale3x(int x1, int y1, int x2, int y2)
+{
+ byte *bufp, *screenp, *screenp2, *screenp3;
+ int x, y;
+ int multi_pitch;
+
+ multi_pitch = dest_pitch * 3;
+ bufp = src_buffer + y1 * SCREENWIDTH + x1;
+ screenp = (byte *) dest_buffer + (y1 * dest_pitch + x1) * 3;
+ screenp2 = screenp + dest_pitch;
+ screenp3 = screenp + dest_pitch * 2;
+
+ for (y=y1; y<y2; ++y)
+ {
+ byte *sp, *sp2, *sp3, *bp;
+ sp = screenp;
+ sp2 = screenp2;
+ sp3 = screenp3;
+ bp = bufp;
+
+ for (x=x1; x<x2; ++x)
+ {
+ *sp++ = *bp; *sp++ = *bp; *sp++ = *bp;
+ *sp2++ = *bp; *sp2++ = *bp; *sp2++ = *bp;
+ *sp3++ = *bp; *sp3++ = *bp; *sp3++ = *bp;
+ ++bp;
+ }
+ screenp += multi_pitch;
+ screenp2 += multi_pitch;
+ screenp3 += multi_pitch;
+ bufp += SCREENWIDTH;
+ }
+}
+
+void I_Scale4x(int x1, int y1, int x2, int y2)
+{
+ byte *bufp, *screenp, *screenp2, *screenp3, *screenp4;
+ int x, y;
+ int multi_pitch;
+
+ multi_pitch = dest_pitch * 4;
+ bufp = src_buffer + y1 * SCREENWIDTH + x1;
+ screenp = (byte *) dest_buffer + (y1 * dest_pitch + x1) * 4;
+ screenp2 = screenp + dest_pitch;
+ screenp3 = screenp + dest_pitch * 2;
+ screenp4 = screenp + dest_pitch * 3;
+
+ for (y=y1; y<y2; ++y)
+ {
+ byte *sp, *sp2, *sp3, *sp4, *bp;
+ sp = screenp;
+ sp2 = screenp2;
+ sp3 = screenp3;
+ sp4 = screenp4;
+ bp = bufp;
+
+ for (x=x1; x<x2; ++x)
+ {
+ *sp++ = *bp; *sp++ = *bp; *sp++ = *bp; *sp++ = *bp;
+ *sp2++ = *bp; *sp2++ = *bp; *sp2++ = *bp; *sp2++ = *bp;
+ *sp3++ = *bp; *sp3++ = *bp; *sp3++ = *bp; *sp3++ = *bp;
+ *sp4++ = *bp; *sp4++ = *bp; *sp4++ = *bp; *sp4++ = *bp;
+ ++bp;
+ }
+ screenp += multi_pitch;
+ screenp2 += multi_pitch;
+ screenp3 += multi_pitch;
+ screenp4 += multi_pitch;
+ bufp += SCREENWIDTH;
+ }
+}
+
+// Search through the given palette, finding the nearest color that matches
+// the given color.
+
+static int FindNearestColor(byte *palette, int r, int g, int b)
+{
+ byte *col;
+ int best;
+ int best_diff;
+ int diff;
+ int i;
+
+ best = 0;
+ best_diff = INT_MAX;
+
+ for (i=0; i<256; ++i)
+ {
+ col = palette + i * 3;
+ diff = (r - col[0]) * (r - col[0])
+ + (g - col[1]) * (g - col[1])
+ + (b - col[2]) * (b - col[2]);
+
+ if (diff == 0)
+ {
+ return i;
+ }
+ else if (diff < best_diff)
+ {
+ best = i;
+ best_diff = diff;
+ }
+ }
+
+ return best;
+}
+
+// Create a stretch table. This is a lookup table for blending colors.
+// pct specifies the bias between the two colors: 0 = all y, 100 = all x.
+// NB: This is identical to the lookup tables used in other ports for
+// translucency.
+
+static byte *GenerateStretchTable(byte *palette, int pct)
+{
+ byte *result;
+ int x, y;
+ int r, g, b;
+ byte *col1;
+ byte *col2;
+
+ result = Z_Malloc(256 * 256, PU_STATIC, NULL);
+
+ for (x=0; x<256; ++x)
+ {
+ for (y=0; y<256; ++y)
+ {
+ col1 = palette + x * 3;
+ col2 = palette + y * 3;
+ r = (((int) col1[0]) * pct + ((int) col2[0]) * (100 - pct)) / 100;
+ g = (((int) col1[1]) * pct + ((int) col2[1]) * (100 - pct)) / 100;
+ b = (((int) col1[2]) * pct + ((int) col2[2]) * (100 - pct)) / 100;
+ result[x * 256 + y] = FindNearestColor(palette, r, g, b);
+ }
+ }
+
+ return result;
+}
+
+void I_InitStretchTables(byte *palette)
+{
+ // We only actually need two lookup tables:
+ //
+ // mix 0% = just write line 1
+ // mix 20% = stretch_tables[0]
+ // mix 40% = stretch_tables[1]
+ // mix 60% = stretch_tables[1] used backwards
+ // mix 80% = stretch_tables[0] used backwards
+ // mix 100% = just write line 2
+
+ printf("I_InitStretchTables: Generating lookup tables..");
+ fflush(stdout);
+ stretch_tables[0] = GenerateStretchTable(palette, 20);
+ printf(".."); fflush(stdout);
+ stretch_tables[1] = GenerateStretchTable(palette, 40);
+ puts("");
+}
+
+static void WriteBlendedLine1x(byte *dest, byte *src1, byte *src2,
+ byte *stretch_table)
+{
+ int x;
+
+ for (x=0; x<SCREENWIDTH; ++x)
+ {
+ *dest = stretch_table[*src1 * 256 + *src2];
+ ++dest;
+ ++src1;
+ ++src2;
+ }
+}
+
+void I_Stretch1x(int x1, int y1, int x2, int y2)
+{
+ byte *bufp, *screenp;
+ int y;
+
+ // Only works with full screen update
+
+ if (x1 != 0 || y1 != 0 || x2 != SCREENWIDTH || y2 != SCREENHEIGHT)
+ {
+ return;
+ }
+
+ // Need to byte-copy from buffer into the screen buffer
+
+ bufp = src_buffer + y1 * SCREENWIDTH + x1;
+ screenp = (byte *) dest_buffer + y1 * dest_pitch + x1;
+
+ // For every 5 lines of src_buffer, 6 lines are written to dest_buffer
+ // (200 -> 240)
+
+ for (y=0; y<SCREENHEIGHT; y += 5)
+ {
+ // 100% line 0
+ memcpy(screenp, bufp, SCREENWIDTH);
+ screenp += dest_pitch;
+
+ // 20% line 0, 80% line 1
+ WriteBlendedLine1x(screenp, bufp, bufp + SCREENWIDTH, stretch_tables[0]);
+ screenp += dest_pitch; bufp += SCREENWIDTH;
+
+ // 40% line 1, 60% line 2
+ WriteBlendedLine1x(screenp, bufp, bufp + SCREENWIDTH, stretch_tables[1]);
+ screenp += dest_pitch; bufp += SCREENWIDTH;
+
+ // 60% line 2, 40% line 3
+ WriteBlendedLine1x(screenp, bufp + SCREENWIDTH, bufp, stretch_tables[1]);
+ screenp += dest_pitch; bufp += SCREENWIDTH;
+
+ // 80% line 3, 20% line 4
+ WriteBlendedLine1x(screenp, bufp + SCREENWIDTH, bufp, stretch_tables[0]);
+ screenp += dest_pitch; bufp += SCREENWIDTH;
+
+ // 100% line 4
+ memcpy(screenp, bufp, SCREENWIDTH);
+ screenp += dest_pitch; bufp += SCREENWIDTH;
+ }
+}
+
+static void WriteLine2x(byte *dest, byte *src)
+{
+ int x;
+
+ for (x=0; x<SCREENWIDTH; ++x)
+ {
+ dest[0] = *src;
+ dest[1] = *src;
+ dest += 2;
+ ++src;
+ }
+}
+
+static void WriteBlendedLine2x(byte *dest, byte *src1, byte *src2,
+ byte *stretch_table)
+{
+ int x;
+ int val;
+
+ for (x=0; x<SCREENWIDTH; ++x)
+ {
+ val = stretch_table[*src1 * 256 + *src2];
+ dest[0] = val;
+ dest[1] = val;
+ dest += 2;
+ ++src1;
+ ++src2;
+ }
+}
+
+// Scale 2x, correcting aspect ratio in the process
+
+void I_Stretch2x(int x1, int y1, int x2, int y2)
+{
+ byte *bufp, *screenp;
+ int y;
+
+ // Only works with full screen update
+
+ if (x1 != 0 || y1 != 0 || x2 != SCREENWIDTH || y2 != SCREENHEIGHT)
+ {
+ return;
+ }
+
+ // Need to byte-copy from buffer into the screen buffer
+
+ bufp = src_buffer + y1 * SCREENWIDTH + x1;
+ screenp = (byte *) dest_buffer + y1 * dest_pitch + x1;
+
+ // For every 5 lines of src_buffer, 12 lines are written to dest_buffer.
+ // (200 -> 480)
+
+ for (y=0; y<SCREENHEIGHT; y += 5)
+ {
+ // 100% line 0
+ WriteLine2x(screenp, bufp);
+ screenp += dest_pitch;
+
+ // 100% line 0
+ WriteLine2x(screenp, bufp);
+ screenp += dest_pitch;
+
+ // 40% line 0, 60% line 1
+ WriteBlendedLine2x(screenp, bufp, bufp + SCREENWIDTH, stretch_tables[1]);
+ screenp += dest_pitch; bufp += SCREENWIDTH;
+
+ // 100% line 1
+ WriteLine2x(screenp, bufp);
+ screenp += dest_pitch;
+
+ // 80% line 1, 20% line 2
+ WriteBlendedLine2x(screenp, bufp + SCREENWIDTH, bufp, stretch_tables[0]);
+ screenp += dest_pitch; bufp += SCREENWIDTH;
+
+ // 100% line 2
+ WriteLine2x(screenp, bufp);
+ screenp += dest_pitch;
+
+ // 100% line 2
+ WriteLine2x(screenp, bufp);
+ screenp += dest_pitch;
+
+ // 20% line 2, 80% line 3
+ WriteBlendedLine2x(screenp, bufp, bufp + SCREENWIDTH, stretch_tables[0]);
+ screenp += dest_pitch; bufp += SCREENWIDTH;
+
+ // 100% line 3
+ WriteLine2x(screenp, bufp);
+ screenp += dest_pitch;
+
+ // 60% line 3, 40% line 4
+ WriteBlendedLine2x(screenp, bufp + SCREENWIDTH, bufp, stretch_tables[1]);
+ screenp += dest_pitch; bufp += SCREENWIDTH;
+
+ // 100% line 4
+ WriteLine2x(screenp, bufp);
+ screenp += dest_pitch;
+
+ // 100% line 4
+ WriteLine2x(screenp, bufp);
+ screenp += dest_pitch; bufp += SCREENWIDTH;
+ }
+}
+
--- /dev/null
+++ b/src/i_scale.h
@@ -1,0 +1,43 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2006 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// System specific interface stuff.
+//
+//-----------------------------------------------------------------------------
+
+
+#ifndef __I_SCALE__
+#define __I_SCALE__
+
+#include "doomtype.h"
+
+void I_InitScale(byte *_src_buffer, byte *_dest_buffer, int _dest_pitch);
+void I_Scale1x(int x1, int y1, int x2, int y2);
+void I_Scale2x(int x1, int y1, int x2, int y2);
+void I_Scale3x(int x1, int y1, int x2, int y2);
+void I_Scale4x(int x1, int y1, int x2, int y2);
+void I_Stretch1x(int x1, int y1, int x2, int y2);
+void I_Stretch2x(int x1, int y1, int x2, int y2);
+void I_InitStretchTables(byte *palette);
+
+#endif /* #ifndef __I_SCALE__ */
+
--- a/src/i_video.c
+++ b/src/i_video.c
@@ -37,6 +37,7 @@
#include "doomdef.h"
#include "doomstat.h"
#include "d_main.h"
+#include "i_scale.h"
#include "i_system.h"
#include "i_timer.h"
#include "m_argv.h"
@@ -49,15 +50,21 @@
// Alternate screenheight for letterbox mode
-#define LETTERBOX_SCREENHEIGHT 240
+#define SCREENHEIGHT_4_3 240
enum
{
FULLSCREEN_OFF,
FULLSCREEN_ON,
- FULLSCREEN_LETTERBOX,
};
+enum
+{
+ RATIO_CORRECT_NONE,
+ RATIO_CORRECT_LETTERBOX,
+ RATIO_CORRECT_STRETCH,
+};
+
extern void M_QuitDOOM();
static SDL_Surface *screen;
@@ -90,6 +97,10 @@
int fullscreen = FULLSCREEN_ON;
+// Aspect ratio correction mode
+
+int aspect_ratio_correct = RATIO_CORRECT_NONE;
+
// Time to wait for the screen to settle on startup before starting the
// game (ms)
@@ -547,165 +558,77 @@
// Update a small portion of the screen
//
-// Does 2x stretching and buffer blitting if neccessary
+// Does stretching and buffer blitting if neccessary
static void BlitArea(int x1, int y1, int x2, int y2)
{
- int w = x2 - x1;
+ void (*scale_function)(int x1, int y1, int x2, int y2);
int x_offset, y_offset;
- x_offset = ((screen->w / screenmultiply) - SCREENWIDTH) / 2;
- y_offset = ((screen->h / screenmultiply) - SCREENHEIGHT) / 2;
-
- // Need to byte-copy from buffer into the screen buffer
-
- if (screenmultiply == 1 && !native_surface)
+ if (native_surface)
{
- byte *bufp, *screenp;
- int y;
- int pitch;
-
- if (SDL_LockSurface(screen) >= 0)
- {
- pitch = screen->pitch;
- bufp = screens[0] + y1 * SCREENWIDTH + x1;
- screenp = (byte *) screen->pixels + (y1 + y_offset) * pitch
- + x1 + x_offset;
-
- for (y=y1; y<y2; ++y)
- {
- memcpy(screenp, bufp, w);
- screenp += pitch;
- bufp += SCREENWIDTH;
- }
-
- SDL_UnlockSurface(screen);
- }
+ return;
}
- // scales the screen size before blitting it
-
- if (screenmultiply == 2)
+ if (aspect_ratio_correct == RATIO_CORRECT_LETTERBOX)
{
- byte *bufp, *screenp, *screenp2;
- int x, y;
- int pitch;
-
- if (SDL_LockSurface(screen) >= 0)
- {
- pitch = screen->pitch * 2;
- bufp = screens[0] + y1 * SCREENWIDTH + x1;
- screenp = (byte *) screen->pixels
- + (y1 + y_offset) * pitch
- + (x1 + x_offset) * 2;
- screenp2 = screenp + screen->pitch;
-
- for (y=y1; y<y2; ++y)
- {
- byte *sp, *sp2, *bp;
- sp = screenp;
- sp2 = screenp2;
- bp = bufp;
-
- for (x=x1; x<x2; ++x)
- {
- *sp++ = *bp; *sp++ = *bp;
- *sp2++ = *bp; *sp2++ = *bp;
- ++bp;
- }
- screenp += pitch;
- screenp2 += pitch;
- bufp += SCREENWIDTH;
- }
-
- SDL_UnlockSurface(screen);
- }
+ x_offset = (screen->w - SCREENWIDTH * screenmultiply) / 2;
+ y_offset = (screen->h - SCREENHEIGHT * screenmultiply) / 2;
}
-
- if (screenmultiply == 3)
+ else
{
- byte *bufp, *screenp, *screenp2, *screenp3;
- int x, y;
- int pitch;
+ x_offset = 0;
+ y_offset = 0;
+ }
- if (SDL_LockSurface(screen) >= 0)
+ if (aspect_ratio_correct == RATIO_CORRECT_STRETCH)
+ {
+ if (screenmultiply == 1)
{
- pitch = screen->pitch * 3;
- bufp = screens[0] + y1 * SCREENWIDTH + x1;
- screenp = (byte *) screen->pixels
- + (y1 + y_offset) * pitch
- + (x1 + x_offset) * 3;
- screenp2 = screenp + screen->pitch;
- screenp3 = screenp2 + screen->pitch;
-
- for (y=y1; y<y2; ++y)
- {
- byte *sp, *sp2, *sp3, *bp;
- sp = screenp;
- sp2 = screenp2;
- sp3 = screenp3;
- bp = bufp;
-
- for (x=x1; x<x2; ++x)
- {
- *sp++ = *bp; *sp++ = *bp; *sp++ = *bp;
- *sp2++ = *bp; *sp2++ = *bp; *sp2++ = *bp;
- *sp3++ = *bp; *sp3++ = *bp; *sp3++ = *bp;
- ++bp;
- }
- screenp += pitch;
- screenp2 += pitch;
- screenp3 += pitch;
- bufp += SCREENWIDTH;
- }
-
- SDL_UnlockSurface(screen);
+ scale_function = I_Stretch1x;
}
+ else if (screenmultiply == 2)
+ {
+ scale_function = I_Stretch2x;
+ }
+ else
+ {
+ I_Error("No aspect ratio stretching function for screenmultiply=%i",
+ screenmultiply);
+ return;
+ }
+ } else {
+ if (screenmultiply == 1)
+ {
+ scale_function = I_Scale1x;
+ }
+ else if (screenmultiply == 2)
+ {
+ scale_function = I_Scale2x;
+ }
+ else if (screenmultiply == 3)
+ {
+ scale_function = I_Scale3x;
+ }
+ else if (screenmultiply == 4)
+ {
+ scale_function = I_Scale4x;
+ }
+ else
+ {
+ I_Error("No scale function found!");
+ return;
+ }
}
- if (screenmultiply == 4)
+ if (SDL_LockSurface(screen) >= 0)
{
- byte *bufp, *screenp, *screenp2, *screenp3, *screenp4;
- int x, y;
- int pitch;
-
- if (SDL_LockSurface(screen) >= 0)
- {
- pitch = screen->pitch * 4;
- bufp = screens[0] + y1 * SCREENWIDTH + x1;
- screenp = (byte *) screen->pixels
- + (y1 + y_offset) * pitch
- + (x1 + x_offset) * 4;
- screenp2 = screenp + screen->pitch;
- screenp3 = screenp2 + screen->pitch;
- screenp4 = screenp3 + screen->pitch;
-
- for (y=y1; y<y2; ++y)
- {
- byte *sp, *sp2, *sp3, *sp4, *bp;
- sp = screenp;
- sp2 = screenp2;
- sp3 = screenp3;
- sp4 = screenp4;
- bp = bufp;
-
- for (x=x1; x<x2; ++x)
- {
- *sp++ = *bp; *sp++ = *bp; *sp++ = *bp; *sp++ = *bp;
- *sp2++ = *bp; *sp2++ = *bp; *sp2++ = *bp; *sp2++ = *bp;
- *sp3++ = *bp; *sp3++ = *bp; *sp3++ = *bp; *sp3++ = *bp;
- *sp4++ = *bp; *sp4++ = *bp; *sp4++ = *bp; *sp4++ = *bp;
- ++bp;
- }
- screenp += pitch;
- screenp2 += pitch;
- screenp3 += pitch;
- screenp4 += pitch;
- bufp += SCREENWIDTH;
- }
-
- SDL_UnlockSurface(screen);
- }
+ I_InitScale(screens[0],
+ (byte *) screen->pixels + (y_offset * screen->pitch)
+ + x_offset,
+ screen->pitch);
+ scale_function(x1, y1, x2, y2);
+ SDL_UnlockSurface(screen);
}
}
@@ -902,10 +825,10 @@
{
*windowwidth = SCREENWIDTH * screenmultiply;
- if (fullscreen == FULLSCREEN_LETTERBOX)
- *windowheight = LETTERBOX_SCREENHEIGHT * screenmultiply;
- else
+ if (aspect_ratio_correct == RATIO_CORRECT_NONE)
*windowheight = SCREENHEIGHT * screenmultiply;
+ else
+ *windowheight = SCREENHEIGHT_4_3 * screenmultiply;
}
// Check if the screen mode for the current settings is in the list available
@@ -988,14 +911,15 @@
static void AutoAdjustSettings(void)
{
int oldw, oldh;
- int old_fullscreen, old_screenmultiply;
+ int old_ratio, old_screenmultiply;
GetWindowDimensions(&oldw, &oldh);
old_screenmultiply = screenmultiply;
- old_fullscreen = fullscreen;
+ old_ratio = aspect_ratio_correct;
if (!CheckValidFSMode() && screenmultiply == 1
- && fullscreen == FULLSCREEN_ON)
+ && fullscreen == FULLSCREEN_ON
+ && aspect_ratio_correct == RATIO_CORRECT_NONE)
{
// 320x200 is not valid.
@@ -1002,13 +926,13 @@
// Try turning on letterbox mode - avoid doubling up
// the screen if possible
- fullscreen = FULLSCREEN_LETTERBOX;
+ aspect_ratio_correct = RATIO_CORRECT_LETTERBOX;
if (!CheckValidFSMode())
{
// That doesn't work. Change it back.
- fullscreen = FULLSCREEN_ON;
+ aspect_ratio_correct = RATIO_CORRECT_NONE;
}
}
@@ -1019,14 +943,16 @@
screenmultiply = 2;
}
- if (!CheckValidFSMode() && fullscreen == FULLSCREEN_ON)
+ if (!CheckValidFSMode()
+ && fullscreen == FULLSCREEN_ON
+ && aspect_ratio_correct == RATIO_CORRECT_NONE)
{
// This is not a valid mode. Try turning on letterbox mode
- fullscreen = FULLSCREEN_LETTERBOX;
+ aspect_ratio_correct = RATIO_CORRECT_LETTERBOX;
}
- if (old_fullscreen != fullscreen
+ if (old_ratio != aspect_ratio_correct
|| old_screenmultiply != screenmultiply)
{
printf("I_InitGraphics: %ix%i resolution is not supported "
@@ -1034,8 +960,8 @@
printf("I_InitGraphics: Video settings adjusted to "
"compensate:\n");
- if (fullscreen != old_fullscreen)
- printf("\tletterbox mode on (fullscreen=2)\n");
+ if (old_ratio != aspect_ratio_correct)
+ printf("\tletterbox mode on (aspect_ratio_correct=2)\n");
if (screenmultiply != old_screenmultiply)
printf("\tscreenmultiply=%i\n", screenmultiply);
@@ -1102,6 +1028,7 @@
void I_InitGraphics(void)
{
SDL_Event dummy;
+ byte *doompal;
int flags = 0;
char *env;
@@ -1155,6 +1082,13 @@
CheckCommandLine();
+ // Don't allow letterbox mode when windowed
+
+ if (!fullscreen && aspect_ratio_correct == RATIO_CORRECT_LETTERBOX)
+ {
+ aspect_ratio_correct = RATIO_CORRECT_NONE;
+ }
+
if (fullscreen && autoadjust_video_settings)
{
// Check that the fullscreen mode we are trying to use is valid;
@@ -1163,6 +1097,17 @@
AutoAdjustSettings();
}
+ // Generate lookup tables before setting the video mode.
+
+ doompal = W_CacheLumpName (DEH_String("PLAYPAL"),PU_CACHE);
+
+ if (aspect_ratio_correct == RATIO_CORRECT_STRETCH)
+ {
+ I_InitStretchTables(doompal);
+ }
+
+ // Set the video mode.
+
GetWindowDimensions(&windowwidth, &windowheight);
flags |= SDL_SWSURFACE | SDL_HWPALETTE | SDL_DOUBLEBUF;
@@ -1212,7 +1157,7 @@
// Set the palette
- I_SetPalette (W_CacheLumpName (DEH_String("PLAYPAL"),PU_CACHE));
+ I_SetPalette(doompal);
SDL_SetColors(screen, palette, 0, 256);
// Setup title and icon
@@ -1240,7 +1185,9 @@
native_surface = !SDL_MUSTLOCK(screen)
&& screenmultiply == 1
- && screen->pitch == SCREENWIDTH;
+ && screen->pitch == SCREENWIDTH
+ && (aspect_ratio_correct == RATIO_CORRECT_NONE
+ || aspect_ratio_correct == RATIO_CORRECT_LETTERBOX);
// If not, allocate a buffer and copy from that buffer to the
// screen when we do an update
@@ -1249,9 +1196,9 @@
{
screens[0] = (unsigned char *) (screen->pixels);
- if (fullscreen == FULLSCREEN_LETTERBOX)
+ if (aspect_ratio_correct == RATIO_CORRECT_LETTERBOX)
{
- screens[0] += ((LETTERBOX_SCREENHEIGHT - SCREENHEIGHT) * screen->pitch) / 2;
+ screens[0] += ((SCREENHEIGHT_4_3 - SCREENHEIGHT) * screen->pitch) / 2;
}
}
else
--- a/src/i_video.h
+++ b/src/i_video.h
@@ -64,6 +64,7 @@
extern boolean screenvisible;
extern int screenmultiply;
extern int fullscreen;
+extern int aspect_ratio_correct;
extern boolean grabmouse;
extern float mouse_acceleration;
extern int mouse_threshold;
--- a/src/m_misc.c
+++ b/src/m_misc.c
@@ -348,6 +348,7 @@
{
{"autoadjust_video_settings", &autoadjust_video_settings, DEFAULT_INT, 0, 0},
{"fullscreen", &fullscreen, DEFAULT_INT, 0, 0},
+ {"aspect_ratio_correct", &aspect_ratio_correct, DEFAULT_INT, 0, 0},
{"startup_delay", &startup_delay, DEFAULT_INT, 0, 0},
{"screenmultiply", &screenmultiply, DEFAULT_INT, 0, 0},
{"grabmouse", &grabmouse, DEFAULT_INT, 0, 0},