summaryrefslogtreecommitdiff
path: root/src/i_video.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/i_video.c')
-rw-r--r--src/i_video.c384
1 files changed, 308 insertions, 76 deletions
diff --git a/src/i_video.c b/src/i_video.c
index 0ed4d716..8360ab9e 100644
--- a/src/i_video.c
+++ b/src/i_video.c
@@ -29,14 +29,14 @@
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
+#include <string.h>
#include "icon.c"
#include "config.h"
-#include "deh_main.h"
-#include "doomdef.h"
-#include "doomstat.h"
-#include "d_main.h"
+#include "deh_str.h"
+#include "doomtype.h"
+#include "doomkeys.h"
#include "i_joystick.h"
#include "i_system.h"
#include "i_swap.h"
@@ -44,12 +44,55 @@
#include "i_video.h"
#include "i_scale.h"
#include "m_argv.h"
-#include "s_sound.h"
-#include "sounds.h"
+#include "m_config.h"
+#include "tables.h"
#include "v_video.h"
#include "w_wad.h"
#include "z_zone.h"
+// Lookup table for mapping ASCII characters to their equivalent when
+// shift is pressed on an American layout keyboard:
+
+static const char shiftxform[] =
+{
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 31, ' ', '!', '"', '#', '$', '%', '&',
+ '"', // shift-'
+ '(', ')', '*', '+',
+ '<', // shift-,
+ '_', // shift--
+ '>', // shift-.
+ '?', // shift-/
+ ')', // shift-0
+ '!', // shift-1
+ '@', // shift-2
+ '#', // shift-3
+ '$', // shift-4
+ '%', // shift-5
+ '^', // shift-6
+ '&', // shift-7
+ '*', // shift-8
+ '(', // shift-9
+ ':',
+ ':', // shift-;
+ '<',
+ '+', // shift-=
+ '>', '?', '@',
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
+ 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+ '[', // shift-[
+ '!', // shift-backslash - OH MY GOD DOES WATCOM SUCK
+ ']', // shift-]
+ '"', '_',
+ '\'', // shift-`
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
+ 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+ '{', '|', '}', '~', 127
+};
+
+
// Non aspect ratio-corrected modes (direct multiples of 320x200)
static screen_mode_t *screen_modes[] = {
@@ -81,14 +124,18 @@ static screen_mode_t *screen_modes_corrected[] = {
&mode_squash_5x,
};
-extern void M_QuitDOOM();
-
// SDL video driver name
char *video_driver = "";
+// SDL surface for the screen.
+
static SDL_Surface *screen;
+// Window title
+
+static char *window_title = "";
+
// palette
static SDL_Color palette[256];
@@ -103,44 +150,73 @@ static boolean initialised = false;
// disable mouse?
static boolean nomouse = false;
-extern int usemouse;
+int usemouse = 1;
+
+// Disallow mouse and joystick movement to cause forward/backward
+// motion. Specified with the '-novert' command line parameter.
+// This is an int to allow saving to config file
-// if true, screens[0] is screen->pixel
+int novert = 0;
+
+// if true, I_VideoBuffer is screen->pixels
static boolean native_surface;
// Screen width and height, from configuration file.
-int screen_width = SCREENWIDTH;
-int screen_height = SCREENHEIGHT;
+static int screen_width = SCREENWIDTH;
+static int screen_height = SCREENHEIGHT;
// Automatically adjust video settings if the selected mode is
// not a valid video mode.
-int autoadjust_video_settings = 1;
+static int autoadjust_video_settings = 1;
// Run in full screen mode? (int type for config code)
-int fullscreen = true;
+static int fullscreen = true;
// Aspect ratio correction mode
-int aspect_ratio_correct = true;
+static int aspect_ratio_correct = true;
// Time to wait for the screen to settle on startup before starting the
// game (ms)
-int startup_delay = 1000;
+static int startup_delay = 1000;
// Grab the mouse? (int type for config code)
-int grabmouse = true;
+static int grabmouse = true;
+
+// The screen buffer; this is modified to draw things to the screen
+
+byte *I_VideoBuffer = NULL;
+
+// If true, game is running as a screensaver
+
+boolean screensaver_mode = false;
// Flag indicating whether the screen is currently visible:
// when the screen isnt visible, don't render the screen
boolean screenvisible;
+// If true, we display dots at the bottom of the screen to
+// indicate FPS.
+
+static boolean display_fps_dots;
+
+// If this is true, the screen is rendered but not blitted to the
+// video buffer.
+
+static boolean noblit;
+
+// Callback function to invoke to determine whether to grab the
+// mouse pointer.
+
+static grabmouse_callback_t grabmouse_callback = NULL;
+
// disk image data and background overwritten by the disk to be
// restored by EndRead
@@ -163,6 +239,10 @@ static screen_mode_t *screen_mode;
int vanilla_keyboard_mapping = true;
+// Is the shift key currently down?
+
+static int shiftdown = 0;
+
// Mouse acceleration
//
// This emulates some of the behavior of DOS mouse drivers by increasing
@@ -175,6 +255,10 @@ int vanilla_keyboard_mapping = true;
float mouse_acceleration = 2.0;
int mouse_threshold = 10;
+// Gamma correction level to use
+
+int usegamma = 0;
+
static boolean MouseShouldBeGrabbed()
{
// never grab the mouse when in screensaver mode
@@ -198,24 +282,34 @@ static boolean MouseShouldBeGrabbed()
if (!usemouse || nomouse)
return false;
- // Drone players don't need mouse focus
-
- if (drone)
- return false;
-
// if we specify not to grab the mouse, never grab
if (!grabmouse)
return false;
- // when menu is active or game is paused, release the mouse
-
- if (menuactive || paused)
- return false;
+ // Invoke the grabmouse callback function to determine whether
+ // the mouse should be grabbed
- // only grab mouse when playing levels (but not demos)
+ if (grabmouse_callback != NULL)
+ {
+ return grabmouse_callback();
+ }
+ else
+ {
+ return true;
+ }
+}
+
+void I_SetGrabMouseCallback(grabmouse_callback_t func)
+{
+ grabmouse_callback = func;
+}
- return (gamestate == GS_LEVEL) && !demoplayback;
+// Set the variable controlling FPS dots.
+
+void I_DisplayFPSDots(boolean dots_on)
+{
+ display_fps_dots = dots_on;
}
// Update the value of window_focused when we get a focus event
@@ -240,9 +334,10 @@ static void UpdateFocus(void)
screenvisible = (state & SDL_APPACTIVE) != 0;
}
-static void LoadDiskImage(void)
+void I_EnableLoadingDisk(void)
{
patch_t *disk;
+ byte *tmpbuf;
char *disk_name;
int y;
char buf[20];
@@ -265,9 +360,16 @@ static void LoadDiskImage(void)
disk = W_CacheLumpName(disk_name, PU_STATIC);
- V_DrawPatch(0, 0, 0, disk);
+ // Draw the patch into a temporary buffer
+
+ tmpbuf = Z_Malloc(SCREENWIDTH * (disk->height + 1), PU_STATIC, NULL);
+ V_UseBuffer(tmpbuf);
+
disk_image_w = SHORT(disk->width);
disk_image_h = SHORT(disk->height);
+ V_DrawPatch(0, 0, disk);
+
+ // Copy the disk into the disk_image buffer.
disk_image = Z_Malloc(disk_image_w * disk_image_h, PU_STATIC, NULL);
saved_background = Z_Malloc(disk_image_w * disk_image_h, PU_STATIC, NULL);
@@ -275,12 +377,16 @@ static void LoadDiskImage(void)
for (y=0; y<disk_image_h; ++y)
{
memcpy(disk_image + disk_image_w * y,
- screens[0] + SCREENWIDTH * y,
+ tmpbuf + SCREENWIDTH * y,
disk_image_w);
- memset(screens[0] + SCREENWIDTH * y, 0, disk_image_w);
}
+ // All done - free the screen buffer and restore the normal
+ // video buffer.
+
W_ReleaseLumpName(disk_name);
+ V_RestoreBuffer();
+ Z_Free(tmpbuf);
}
//
@@ -425,6 +531,74 @@ static int AccelerateMouse(int val)
}
}
+// Get the equivalent ASCII (Unicode?) character for a keypress.
+
+static int GetTypedChar(SDL_Event *event)
+{
+ int key;
+
+ // If Vanilla keyboard mapping enabled, the keyboard
+ // scan code is used to give the character typed.
+ // This does not change depending on keyboard layout.
+ // If you have a German keyboard, pressing 'z' will
+ // give 'y', for example. It is desirable to be able
+ // to fix this so that people with non-standard
+ // keyboard mappings can type properly. If vanilla
+ // mode is disabled, use the properly translated
+ // version.
+
+ if (vanilla_keyboard_mapping)
+ {
+ key = TranslateKey(&event->key.keysym);
+
+ // Is shift held down? If so, perform a translation.
+
+ if (shiftdown > 0)
+ {
+ if (key >= 0 && key < arrlen(shiftxform))
+ {
+ key = shiftxform[key];
+ }
+ else
+ {
+ key = 0;
+ }
+ }
+
+ return key;
+ }
+ else
+ {
+ // Unicode value, from key layout.
+
+ return event->key.keysym.unicode;
+ }
+}
+
+static void UpdateShiftStatus(SDL_Event *event)
+{
+ int change;
+
+ if (event->type == SDL_KEYDOWN)
+ {
+ change = 1;
+ }
+ else if (event->type == SDL_KEYUP)
+ {
+ change = -1;
+ }
+ else
+ {
+ return;
+ }
+
+ if (event->key.keysym.sym == SDLK_LSHIFT
+ || event->key.keysym.sym == SDLK_RSHIFT)
+ {
+ shiftdown += change;
+ }
+}
+
void I_GetEvent(void)
{
SDL_Event sdlevent;
@@ -453,32 +627,18 @@ void I_GetEvent(void)
I_Quit();
}
+ UpdateShiftStatus(&sdlevent);
+
// process event
switch (sdlevent.type)
{
case SDL_KEYDOWN:
+ // data1 has the key pressed, data2 has the character
+ // (shift-translated, etc)
event.type = ev_keydown;
event.data1 = TranslateKey(&sdlevent.key.keysym);
-
- // If Vanilla keyboard mapping enabled, the keyboard
- // scan code is used to give the character typed.
- // This does not change depending on keyboard layout.
- // If you have a German keyboard, pressing 'z' will
- // give 'y', for example. It is desirable to be able
- // to fix this so that people with non-standard
- // keyboard mappings can type properly. If vanilla
- // mode is disabled, use the properly translated
- // version.
-
- if (vanilla_keyboard_mapping)
- {
- event.data2 = event.data1;
- }
- else
- {
- event.data2 = sdlevent.key.keysym.unicode;
- }
+ event.data2 = GetTypedChar(&sdlevent);
D_PostEvent(&event);
break;
@@ -519,11 +679,13 @@ void I_GetEvent(void)
}
break;
+/* TODO
case SDL_QUIT:
// bring up the "quit doom?" prompt
S_StartSound(NULL,sfx_swtchn);
M_QuitDOOM(0);
break;
+ */
case SDL_ACTIVEEVENT:
// need to update our focus state
@@ -572,7 +734,15 @@ static void I_ReadMouse(void)
ev.type = ev_mouse;
ev.data1 = MouseButtonState();
ev.data2 = AccelerateMouse(x);
- ev.data3 = -AccelerateMouse(y);
+
+ if (!novert)
+ {
+ ev.data3 = -AccelerateMouse(y);
+ }
+ else
+ {
+ ev.data3 = 0;
+ }
D_PostEvent(&ev);
}
@@ -663,7 +833,7 @@ static boolean BlitArea(int x1, int y1, int x2, int y2)
if (SDL_LockSurface(screen) >= 0)
{
- I_InitScale(screens[0],
+ I_InitScale(I_VideoBuffer,
(byte *) screen->pixels + (y_offset * screen->pitch)
+ x_offset,
screen->pitch);
@@ -712,7 +882,7 @@ void I_BeginRead(void)
for (y=0; y<disk_image_h; ++y)
{
byte *screenloc =
- screens[0]
+ I_VideoBuffer
+ (SCREENHEIGHT - 1 - disk_image_h + y) * SCREENWIDTH
+ (SCREENWIDTH - 1 - disk_image_w);
@@ -738,7 +908,7 @@ void I_EndRead(void)
for (y=0; y<disk_image_h; ++y)
{
byte *screenloc =
- screens[0]
+ I_VideoBuffer
+ (SCREENHEIGHT - 1 - disk_image_h + y) * SCREENWIDTH
+ (SCREENWIDTH - 1 - disk_image_w);
@@ -775,19 +945,18 @@ void I_FinishUpdate (void)
return;
// draws little dots on the bottom of the screen
- if (devparm)
- {
+ if (display_fps_dots)
+ {
i = I_GetTime();
tics = i - lasttic;
lasttic = i;
if (tics > 20) tics = 20;
for (i=0 ; i<tics*2 ; i+=4)
- screens[0][ (SCREENHEIGHT-1)*SCREENWIDTH + i] = 0xff;
+ I_VideoBuffer[ (SCREENHEIGHT-1)*SCREENWIDTH + i] = 0xff;
for ( ; i<20*4 ; i+=4)
- screens[0][ (SCREENHEIGHT-1)*SCREENWIDTH + i] = 0x0;
-
+ I_VideoBuffer[ (SCREENHEIGHT-1)*SCREENWIDTH + i] = 0x0;
}
// draw to screen
@@ -814,7 +983,7 @@ void I_FinishUpdate (void)
//
void I_ReadScreen (byte* scr)
{
- memcpy (scr, screens[0], SCREENWIDTH*SCREENHEIGHT);
+ memcpy(scr, I_VideoBuffer, SCREENWIDTH*SCREENHEIGHT);
}
@@ -836,16 +1005,26 @@ void I_SetPalette (byte *doompalette)
}
//
-// Set the window caption
+// Set the window title
+//
+
+void I_SetWindowTitle(char *title)
+{
+ window_title = title;
+}
+
+//
+// Call the SDL function to set the window title, based on
+// the title set with I_SetWindowTitle.
//
-void I_SetWindowCaption(void)
+static void I_InitWindowTitle(void)
{
char *buf;
- buf = Z_Malloc(strlen(gamedescription) + strlen(PACKAGE_STRING) + 10,
+ buf = Z_Malloc(strlen(window_title) + strlen(PACKAGE_STRING) + 5,
PU_STATIC, NULL);
- sprintf(buf, "%s - %s", gamedescription, PACKAGE_STRING);
+ sprintf(buf, "%s - %s", window_title, PACKAGE_STRING);
SDL_WM_SetCaption(buf, NULL);
@@ -854,7 +1033,7 @@ void I_SetWindowCaption(void)
// Set the application icon
-void I_SetWindowIcon(void)
+static void I_InitWindowIcon(void)
{
SDL_Surface *surface;
Uint8 *mask;
@@ -1173,6 +1352,14 @@ static void CheckCommandLine(void)
int i;
//!
+ // @vanilla
+ //
+ // Disable blitting the screen.
+ //
+
+ noblit = M_CheckParm ("-noblit");
+
+ //!
// @category video
//
// Grab the mouse when running in windowed mode.
@@ -1307,6 +1494,28 @@ static void CheckCommandLine(void)
{
SetScaleFactor(3);
}
+
+ //!
+ // @category video
+ //
+ // Disable vertical mouse movement.
+ //
+
+ if (M_CheckParm("-novert"))
+ {
+ novert = true;
+ }
+
+ //!
+ // @category video
+ //
+ // Enable vertical mouse movement.
+ //
+
+ if (M_CheckParm("-nonovert"))
+ {
+ novert = false;
+ }
}
// Check if we have been invoked as a screensaver by xscreensaver.
@@ -1484,8 +1693,8 @@ void I_InitGraphics(void)
// Set up title and icon. Windows cares about the ordering; this
// has to be done before the call to SDL_SetVideoMode.
- I_SetWindowCaption();
- I_SetWindowIcon();
+ I_InitWindowTitle();
+ I_InitWindowIcon();
// Set the video mode.
@@ -1574,23 +1783,21 @@ void I_InitGraphics(void)
if (native_surface)
{
- screens[0] = (unsigned char *) screen->pixels;
+ I_VideoBuffer = (unsigned char *) screen->pixels;
- screens[0] += (screen->h - SCREENHEIGHT) / 2;
+ I_VideoBuffer += (screen->h - SCREENHEIGHT) / 2;
}
else
{
- screens[0] = (unsigned char *) Z_Malloc (SCREENWIDTH * SCREENHEIGHT,
- PU_STATIC, NULL);
+ I_VideoBuffer = (unsigned char *) Z_Malloc (SCREENWIDTH * SCREENHEIGHT,
+ PU_STATIC, NULL);
}
- // "Loading from disk" icon
-
- LoadDiskImage();
+ V_RestoreBuffer();
// Clear the screen to black.
- memset(screens[0], 0, SCREENWIDTH * SCREENHEIGHT);
+ memset(I_VideoBuffer, 0, SCREENWIDTH * SCREENHEIGHT);
// We need SDL to give us translated versions of keys as well
@@ -1612,5 +1819,30 @@ void I_InitGraphics(void)
}
initialised = true;
+
+ // Call I_ShutdownGraphics on quit
+
+ I_AtExit(I_ShutdownGraphics, true);
+}
+
+// Bind all variables controlling video options into the configuration
+// file system.
+
+void I_BindVideoVariables(void)
+{
+ M_BindVariable("use_mouse", &usemouse);
+ M_BindVariable("autoadjust_video_settings", &autoadjust_video_settings);
+ M_BindVariable("fullscreen", &fullscreen);
+ M_BindVariable("aspect_ratio_correct", &aspect_ratio_correct);
+ M_BindVariable("startup_delay", &startup_delay);
+ M_BindVariable("screen_width", &screen_width);
+ M_BindVariable("screen_height", &screen_height);
+ M_BindVariable("grabmouse", &grabmouse);
+ M_BindVariable("mouse_acceleration", &mouse_acceleration);
+ M_BindVariable("mouse_threshold", &mouse_threshold);
+ M_BindVariable("video_driver", &video_driver);
+ M_BindVariable("usegamma", &usegamma);
+ M_BindVariable("vanilla_keyboard_mapping", &vanilla_keyboard_mapping);
+ M_BindVariable("novert", &novert);
}