diff options
author | Simon Howard | 2006-12-15 19:35:46 +0000 |
---|---|---|
committer | Simon Howard | 2006-12-15 19:35:46 +0000 |
commit | 265c0de3419b5123052a10cef276e1221cd0630c (patch) | |
tree | 31cc300b13b7b636bec4eebedccf372fc2329eb0 | |
parent | 136009e7505acc321c2b7f710929cb7d9b88a5b2 (diff) | |
download | chocolate-doom-265c0de3419b5123052a10cef276e1221cd0630c.tar.gz chocolate-doom-265c0de3419b5123052a10cef276e1221cd0630c.tar.bz2 chocolate-doom-265c0de3419b5123052a10cef276e1221cd0630c.zip |
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
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/i_scale.c | 404 | ||||
-rw-r--r-- | src/i_scale.h | 43 | ||||
-rw-r--r-- | src/i_video.c | 269 | ||||
-rw-r--r-- | src/i_video.h | 1 | ||||
-rw-r--r-- | src/m_misc.c | 1 |
6 files changed, 558 insertions, 161 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index bb44f207..c27f2c35 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -60,6 +60,7 @@ hu_lib.c hu_lib.h \ 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 \ diff --git a/src/i_scale.c b/src/i_scale.c new file mode 100644 index 00000000..29bc8731 --- /dev/null +++ b/src/i_scale.c @@ -0,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; + } +} + diff --git a/src/i_scale.h b/src/i_scale.h new file mode 100644 index 00000000..6f523039 --- /dev/null +++ b/src/i_scale.h @@ -0,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__ */ + diff --git a/src/i_video.c b/src/i_video.c index dd5cbe9f..53e1272d 100644 --- 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,13 +50,19 @@ // 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(); @@ -90,6 +97,10 @@ int autoadjust_video_settings = 1; 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 @@ static void UpdateGrab(void) // 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 @@ static void GetWindowDimensions(int *windowwidth, int *windowheight) { *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,27 +911,28 @@ static void CheckCommandLine(void) 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. // 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 @@ static void AutoAdjustSettings(void) 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 @@ static void AutoAdjustSettings(void) 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 @@ static void SetBlankCursor(void) void I_InitGraphics(void) { SDL_Event dummy; + byte *doompal; int flags = 0; char *env; @@ -1155,6 +1082,13 @@ void I_InitGraphics(void) 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 @@ void I_InitGraphics(void) 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 @@ void I_InitGraphics(void) // 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 @@ void I_InitGraphics(void) 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 @@ void I_InitGraphics(void) { 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 diff --git a/src/i_video.h b/src/i_video.h index e9904fd8..e4e73041 100644 --- a/src/i_video.h +++ b/src/i_video.h @@ -64,6 +64,7 @@ extern int autoadjust_video_settings; 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; diff --git a/src/m_misc.c b/src/m_misc.c index ca67a03c..5930140c 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -348,6 +348,7 @@ static default_t extra_defaults_list[] = { {"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}, |