2000-05-19 08:29:11 +00:00
|
|
|
/*
|
2000-05-22 07:46:47 +00:00
|
|
|
vid_wgl.c
|
2000-05-19 08:29:11 +00:00
|
|
|
|
2000-05-22 07:46:47 +00:00
|
|
|
Win32 WGL vid component
|
2000-05-19 08:29:11 +00:00
|
|
|
|
|
|
|
Copyright (C) 1996-1997 Id Software, Inc.
|
|
|
|
|
|
|
|
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:
|
|
|
|
|
|
|
|
Free Software Foundation, Inc.
|
|
|
|
59 Temple Place - Suite 330
|
|
|
|
Boston, MA 02111-1307, USA
|
|
|
|
|
|
|
|
$Id$
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
|
|
|
#include "quakedef.h"
|
|
|
|
#include "winquake.h"
|
|
|
|
#include "sys.h"
|
|
|
|
#include "resource.h"
|
|
|
|
#include "glquake.h"
|
|
|
|
#include "in_win.h"
|
|
|
|
#include <commctrl.h>
|
2000-05-21 11:32:35 +00:00
|
|
|
#include "screen.h"
|
|
|
|
#include "keys.h"
|
|
|
|
#include "qargs.h"
|
|
|
|
#include "cmd.h"
|
2000-05-21 12:39:18 +00:00
|
|
|
#include "qendian.h"
|
2000-05-22 01:05:57 +00:00
|
|
|
#include "draw.h"
|
2000-05-19 08:29:11 +00:00
|
|
|
|
|
|
|
#define MAX_MODE_LIST 30
|
|
|
|
#define VID_ROW_SIZE 3
|
|
|
|
#define WARP_WIDTH 320
|
|
|
|
#define WARP_HEIGHT 200
|
|
|
|
#define MAXWIDTH 10000
|
|
|
|
#define MAXHEIGHT 10000
|
|
|
|
#define BASEWIDTH 320
|
|
|
|
#define BASEHEIGHT 200
|
|
|
|
|
|
|
|
#define MODE_WINDOWED 0
|
|
|
|
#define NO_MODE (MODE_WINDOWED - 1)
|
|
|
|
#define MODE_FULLSCREEN_DEFAULT (MODE_WINDOWED + 1)
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
modestate_t type;
|
|
|
|
int width;
|
|
|
|
int height;
|
|
|
|
int modenum;
|
|
|
|
int dib;
|
|
|
|
int fullscreen;
|
|
|
|
int bpp;
|
|
|
|
int halfscreen;
|
|
|
|
char modedesc[17];
|
|
|
|
} vmode_t;
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
int width;
|
|
|
|
int height;
|
|
|
|
} lmode_t;
|
|
|
|
|
|
|
|
lmode_t lowresmodes[] = {
|
|
|
|
{320, 200},
|
|
|
|
{320, 240},
|
|
|
|
{400, 300},
|
|
|
|
{512, 384},
|
|
|
|
};
|
|
|
|
|
|
|
|
const char *gl_vendor;
|
|
|
|
const char *gl_renderer;
|
|
|
|
const char *gl_version;
|
|
|
|
const char *gl_extensions;
|
|
|
|
|
|
|
|
qboolean DDActive;
|
|
|
|
qboolean scr_skipupdate;
|
|
|
|
|
|
|
|
static vmode_t modelist[MAX_MODE_LIST];
|
|
|
|
static int nummodes;
|
|
|
|
static vmode_t *pcurrentmode;
|
|
|
|
static vmode_t badmode;
|
|
|
|
|
|
|
|
static DEVMODE gdevmode;
|
|
|
|
static qboolean vid_initialized = false;
|
|
|
|
static qboolean windowed, leavecurrentmode;
|
|
|
|
static qboolean vid_canalttab = false;
|
|
|
|
static qboolean vid_wassuspended = false;
|
|
|
|
static int windowed_mouse;
|
|
|
|
static HICON hIcon;
|
|
|
|
|
|
|
|
int DIBWidth, DIBHeight;
|
|
|
|
RECT WindowRect;
|
|
|
|
DWORD WindowStyle, ExWindowStyle;
|
|
|
|
|
|
|
|
HWND mainwindow, dibwindow;
|
|
|
|
|
|
|
|
int vid_modenum = NO_MODE;
|
|
|
|
int vid_realmode;
|
|
|
|
int vid_default = MODE_WINDOWED;
|
|
|
|
static int windowed_default;
|
|
|
|
unsigned char vid_curpal[256*3];
|
2000-06-04 12:42:38 +00:00
|
|
|
static qboolean fullsbardraw = true;
|
2000-05-19 08:29:11 +00:00
|
|
|
|
|
|
|
HGLRC baseRC;
|
|
|
|
HDC maindc;
|
|
|
|
|
|
|
|
glvert_t glv;
|
|
|
|
|
|
|
|
cvar_t *gl_ztrick;
|
|
|
|
|
|
|
|
HWND WINAPI InitializeWindow (HINSTANCE hInstance, int nCmdShow);
|
|
|
|
|
|
|
|
extern viddef_t vid; // global video state
|
|
|
|
|
|
|
|
unsigned short d_8to16table[256];
|
|
|
|
unsigned d_8to24table[256];
|
|
|
|
unsigned char d_15to8table[65536];
|
|
|
|
|
|
|
|
float gldepthmin, gldepthmax;
|
|
|
|
|
|
|
|
modestate_t modestate = MS_UNINIT;
|
|
|
|
|
|
|
|
void VID_MenuDraw (void);
|
|
|
|
void VID_MenuKey (int key);
|
|
|
|
|
|
|
|
LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
|
|
|
void AppActivate(BOOL fActive, BOOL minimize);
|
|
|
|
char *VID_GetModeDescription (int mode);
|
|
|
|
void ClearAllStates (void);
|
|
|
|
void VID_UpdateWindowStatus (void);
|
|
|
|
void GL_Init (void);
|
|
|
|
|
|
|
|
PROC glArrayElementEXT;
|
|
|
|
PROC glColorPointerEXT;
|
|
|
|
PROC glTexCoordPointerEXT;
|
|
|
|
PROC glVertexPointerEXT;
|
|
|
|
|
|
|
|
typedef void (APIENTRY *lp3DFXFUNC) (int, int, int, int, int, const void*);
|
|
|
|
lp3DFXFUNC glColorTableEXT;
|
|
|
|
qboolean is8bit = false;
|
|
|
|
qboolean isPermedia = false;
|
|
|
|
qboolean gl_mtexable = false;
|
|
|
|
|
|
|
|
//====================================
|
|
|
|
|
|
|
|
cvar_t *vid_mode;
|
|
|
|
cvar_t *_vid_default_mode;
|
|
|
|
cvar_t *_vid_default_mode_win;
|
|
|
|
cvar_t *vid_wait;
|
|
|
|
cvar_t *vid_nopageflip;
|
|
|
|
cvar_t *_vid_wait_override;
|
|
|
|
cvar_t *vid_config_x;
|
|
|
|
cvar_t *vid_config_y;
|
|
|
|
cvar_t *vid_stretch_by_2;
|
|
|
|
cvar_t *_windowed_mouse;
|
|
|
|
|
|
|
|
int window_center_x, window_center_y, window_x, window_y, window_width, window_height;
|
|
|
|
RECT window_rect;
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
VID_InitCvars
|
|
|
|
================
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
VID_InitCvars ()
|
|
|
|
{
|
|
|
|
// It may not look like it, but this is important
|
|
|
|
}
|
|
|
|
|
|
|
|
// direct draw software compatability stuff
|
|
|
|
|
|
|
|
void VID_HandlePause (qboolean pause)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void VID_ForceLockState (int lk)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void VID_LockBuffer (void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void VID_UnlockBuffer (void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
int VID_ForceUnlockedAndReturnState (void)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void D_EndDirectRect (int x, int y, int width, int height)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CenterWindow(HWND hWndCenter, int width, int height, BOOL lefttopjustify)
|
|
|
|
{
|
|
|
|
RECT rect;
|
|
|
|
int CenterX, CenterY;
|
|
|
|
|
|
|
|
CenterX = (GetSystemMetrics(SM_CXSCREEN) - width) / 2;
|
|
|
|
CenterY = (GetSystemMetrics(SM_CYSCREEN) - height) / 2;
|
|
|
|
if (CenterX > CenterY*2)
|
|
|
|
CenterX >>= 1; // dual screens
|
|
|
|
CenterX = (CenterX < 0) ? 0: CenterX;
|
|
|
|
CenterY = (CenterY < 0) ? 0: CenterY;
|
|
|
|
SetWindowPos (hWndCenter, NULL, CenterX, CenterY, 0, 0,
|
|
|
|
SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME);
|
|
|
|
}
|
|
|
|
|
|
|
|
qboolean VID_SetWindowedMode (int modenum)
|
|
|
|
{
|
|
|
|
HDC hdc;
|
|
|
|
int lastmodestate, width, height;
|
|
|
|
RECT rect;
|
|
|
|
|
|
|
|
lastmodestate = modestate;
|
|
|
|
|
|
|
|
WindowRect.top = WindowRect.left = 0;
|
|
|
|
|
|
|
|
WindowRect.right = modelist[modenum].width;
|
|
|
|
WindowRect.bottom = modelist[modenum].height;
|
|
|
|
|
|
|
|
DIBWidth = modelist[modenum].width;
|
|
|
|
DIBHeight = modelist[modenum].height;
|
|
|
|
|
|
|
|
WindowStyle = WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_SYSMENU |
|
|
|
|
WS_MINIMIZEBOX;
|
|
|
|
ExWindowStyle = 0;
|
|
|
|
|
|
|
|
rect = WindowRect;
|
|
|
|
AdjustWindowRectEx(&rect, WindowStyle, FALSE, 0);
|
|
|
|
|
|
|
|
width = rect.right - rect.left;
|
|
|
|
height = rect.bottom - rect.top;
|
|
|
|
|
|
|
|
// Create the DIB window
|
|
|
|
dibwindow = CreateWindowEx (
|
|
|
|
ExWindowStyle,
|
|
|
|
"WinQuake",
|
|
|
|
"GLQuake",
|
|
|
|
WindowStyle,
|
|
|
|
rect.left, rect.top,
|
|
|
|
width,
|
|
|
|
height,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
global_hInstance,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
if (!dibwindow)
|
|
|
|
Sys_Error ("Couldn't create DIB window");
|
|
|
|
|
|
|
|
// Center and show the DIB window
|
|
|
|
CenterWindow(dibwindow, WindowRect.right - WindowRect.left,
|
|
|
|
WindowRect.bottom - WindowRect.top, false);
|
|
|
|
|
|
|
|
ShowWindow (dibwindow, SW_SHOWDEFAULT);
|
|
|
|
UpdateWindow (dibwindow);
|
|
|
|
|
|
|
|
modestate = MS_WINDOWED;
|
|
|
|
|
|
|
|
// because we have set the background brush for the window to NULL
|
|
|
|
// (to avoid flickering when re-sizing the window on the desktop),
|
|
|
|
// we clear the window to black when created, otherwise it will be
|
|
|
|
// empty while Quake starts up.
|
|
|
|
hdc = GetDC(dibwindow);
|
|
|
|
PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS);
|
|
|
|
ReleaseDC(dibwindow, hdc);
|
|
|
|
|
|
|
|
if (vid.conheight > modelist[modenum].height)
|
|
|
|
vid.conheight = modelist[modenum].height;
|
|
|
|
if (vid.conwidth > modelist[modenum].width)
|
|
|
|
vid.conwidth = modelist[modenum].width;
|
|
|
|
vid.width = vid.conwidth;
|
|
|
|
vid.height = vid.conheight;
|
|
|
|
|
|
|
|
vid.numpages = 2;
|
|
|
|
|
|
|
|
mainwindow = dibwindow;
|
|
|
|
|
|
|
|
SendMessage (mainwindow, WM_SETICON, (WPARAM)TRUE, (LPARAM)hIcon);
|
|
|
|
SendMessage (mainwindow, WM_SETICON, (WPARAM)FALSE, (LPARAM)hIcon);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
qboolean VID_SetFullDIBMode (int modenum)
|
|
|
|
{
|
|
|
|
HDC hdc;
|
|
|
|
int lastmodestate, width, height;
|
|
|
|
RECT rect;
|
|
|
|
|
|
|
|
if (!leavecurrentmode)
|
|
|
|
{
|
|
|
|
gdevmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
|
|
|
|
gdevmode.dmBitsPerPel = modelist[modenum].bpp;
|
|
|
|
gdevmode.dmPelsWidth = modelist[modenum].width <<
|
|
|
|
modelist[modenum].halfscreen;
|
|
|
|
gdevmode.dmPelsHeight = modelist[modenum].height;
|
|
|
|
gdevmode.dmSize = sizeof (gdevmode);
|
|
|
|
|
|
|
|
if (ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
|
|
|
|
Sys_Error ("Couldn't set fullscreen DIB mode");
|
|
|
|
}
|
|
|
|
|
|
|
|
lastmodestate = modestate;
|
|
|
|
modestate = MS_FULLDIB;
|
|
|
|
|
|
|
|
WindowRect.top = WindowRect.left = 0;
|
|
|
|
|
|
|
|
WindowRect.right = modelist[modenum].width;
|
|
|
|
WindowRect.bottom = modelist[modenum].height;
|
|
|
|
|
|
|
|
DIBWidth = modelist[modenum].width;
|
|
|
|
DIBHeight = modelist[modenum].height;
|
|
|
|
|
|
|
|
WindowStyle = WS_POPUP;
|
|
|
|
ExWindowStyle = 0;
|
|
|
|
|
|
|
|
rect = WindowRect;
|
|
|
|
AdjustWindowRectEx(&rect, WindowStyle, FALSE, 0);
|
|
|
|
|
|
|
|
width = rect.right - rect.left;
|
|
|
|
height = rect.bottom - rect.top;
|
|
|
|
|
|
|
|
// Create the DIB window
|
|
|
|
dibwindow = CreateWindowEx (
|
|
|
|
ExWindowStyle,
|
|
|
|
"WinQuake",
|
|
|
|
"GLQuake",
|
|
|
|
WindowStyle,
|
|
|
|
rect.left, rect.top,
|
|
|
|
width,
|
|
|
|
height,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
global_hInstance,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
if (!dibwindow)
|
|
|
|
Sys_Error ("Couldn't create DIB window");
|
|
|
|
|
|
|
|
ShowWindow (dibwindow, SW_SHOWDEFAULT);
|
|
|
|
UpdateWindow (dibwindow);
|
|
|
|
|
|
|
|
// Because we have set the background brush for the window to NULL
|
|
|
|
// (to avoid flickering when re-sizing the window on the desktop), we
|
|
|
|
// clear the window to black when created, otherwise it will be
|
|
|
|
// empty while Quake starts up.
|
|
|
|
hdc = GetDC(dibwindow);
|
|
|
|
PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS);
|
|
|
|
ReleaseDC(dibwindow, hdc);
|
|
|
|
|
|
|
|
if (vid.conheight > modelist[modenum].height)
|
|
|
|
vid.conheight = modelist[modenum].height;
|
|
|
|
if (vid.conwidth > modelist[modenum].width)
|
|
|
|
vid.conwidth = modelist[modenum].width;
|
|
|
|
vid.width = vid.conwidth;
|
|
|
|
vid.height = vid.conheight;
|
|
|
|
|
|
|
|
vid.numpages = 2;
|
|
|
|
|
|
|
|
// needed because we're not getting WM_MOVE messages fullscreen on NT
|
|
|
|
window_x = 0;
|
|
|
|
window_y = 0;
|
|
|
|
|
|
|
|
mainwindow = dibwindow;
|
|
|
|
|
|
|
|
SendMessage (mainwindow, WM_SETICON, (WPARAM)TRUE, (LPARAM)hIcon);
|
|
|
|
SendMessage (mainwindow, WM_SETICON, (WPARAM)FALSE, (LPARAM)hIcon);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int VID_SetMode (int modenum, unsigned char *palette)
|
|
|
|
{
|
|
|
|
int original_mode, temp;
|
|
|
|
qboolean stat;
|
|
|
|
MSG msg;
|
|
|
|
HDC hdc;
|
|
|
|
|
|
|
|
if ((windowed && (modenum != 0)) ||
|
|
|
|
(!windowed && (modenum < 1)) ||
|
|
|
|
(!windowed && (modenum >= nummodes)))
|
|
|
|
{
|
|
|
|
Sys_Error ("Bad video mode\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
// so Con_Printfs don't mess us up by forcing vid and snd updates
|
|
|
|
temp = scr_disabled_for_loading;
|
|
|
|
scr_disabled_for_loading = true;
|
|
|
|
|
|
|
|
CDAudio_Pause ();
|
|
|
|
|
|
|
|
if (vid_modenum == NO_MODE)
|
|
|
|
original_mode = windowed_default;
|
|
|
|
else
|
|
|
|
original_mode = vid_modenum;
|
|
|
|
|
|
|
|
// Set either the fullscreen or windowed mode
|
|
|
|
if (modelist[modenum].type == MS_WINDOWED)
|
|
|
|
{
|
|
|
|
if (_windowed_mouse->value && key_dest == key_game)
|
|
|
|
{
|
|
|
|
stat = VID_SetWindowedMode(modenum);
|
|
|
|
IN_ActivateMouse ();
|
|
|
|
IN_HideMouse ();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
IN_DeactivateMouse ();
|
|
|
|
IN_ShowMouse ();
|
|
|
|
stat = VID_SetWindowedMode(modenum);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (modelist[modenum].type == MS_FULLDIB)
|
|
|
|
{
|
|
|
|
stat = VID_SetFullDIBMode(modenum);
|
|
|
|
IN_ActivateMouse ();
|
|
|
|
IN_HideMouse ();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Sys_Error ("VID_SetMode: Bad mode type in modelist");
|
|
|
|
}
|
|
|
|
|
|
|
|
window_width = DIBWidth;
|
|
|
|
window_height = DIBHeight;
|
|
|
|
VID_UpdateWindowStatus ();
|
|
|
|
|
|
|
|
CDAudio_Resume ();
|
|
|
|
scr_disabled_for_loading = temp;
|
|
|
|
|
|
|
|
if (!stat)
|
|
|
|
{
|
|
|
|
Sys_Error ("Couldn't set video mode");
|
|
|
|
}
|
|
|
|
|
|
|
|
// now we try to make sure we get the focus on the mode switch, because
|
|
|
|
// sometimes in some systems we don't. We grab the foreground, then
|
|
|
|
// finish setting up, pump all our messages, and sleep for a little while
|
|
|
|
// to let messages finish bouncing around the system, then we put
|
|
|
|
// ourselves at the top of the z order, then grab the foreground again,
|
|
|
|
// Who knows if it helps, but it probably doesn't hurt
|
|
|
|
SetForegroundWindow (mainwindow);
|
|
|
|
VID_SetPalette (palette);
|
|
|
|
vid_modenum = modenum;
|
|
|
|
Cvar_SetValue (vid_mode, (float)vid_modenum);
|
|
|
|
|
|
|
|
while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
|
|
|
|
{
|
|
|
|
TranslateMessage (&msg);
|
|
|
|
DispatchMessage (&msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
Sleep (100);
|
|
|
|
|
|
|
|
SetWindowPos (mainwindow, HWND_TOP, 0, 0, 0, 0,
|
|
|
|
SWP_DRAWFRAME | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW |
|
|
|
|
SWP_NOCOPYBITS);
|
|
|
|
|
|
|
|
SetForegroundWindow (mainwindow);
|
|
|
|
|
|
|
|
// fix the leftover Alt from any Alt-Tab or the like that switched us away
|
|
|
|
ClearAllStates ();
|
|
|
|
|
|
|
|
if (!msg_suppress_1)
|
|
|
|
Con_SafePrintf ("Video mode %s initialized.\n", VID_GetModeDescription (vid_modenum));
|
|
|
|
|
|
|
|
VID_SetPalette (palette);
|
|
|
|
|
|
|
|
vid.recalc_refdef = 1;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
VID_UpdateWindowStatus
|
|
|
|
================
|
|
|
|
*/
|
|
|
|
void VID_UpdateWindowStatus (void)
|
|
|
|
{
|
|
|
|
|
|
|
|
window_rect.left = window_x;
|
|
|
|
window_rect.top = window_y;
|
|
|
|
window_rect.right = window_x + window_width;
|
|
|
|
window_rect.bottom = window_y + window_height;
|
|
|
|
window_center_x = (window_rect.left + window_rect.right) / 2;
|
|
|
|
window_center_y = (window_rect.top + window_rect.bottom) / 2;
|
|
|
|
|
|
|
|
IN_UpdateClipCursor ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//====================================
|
|
|
|
|
|
|
|
BINDTEXFUNCPTR bindTexFunc;
|
|
|
|
|
|
|
|
#define TEXTURE_EXT_STRING "GL_EXT_texture_object"
|
|
|
|
|
|
|
|
|
|
|
|
void CheckTextureExtensions (void)
|
|
|
|
{
|
|
|
|
char *tmp;
|
|
|
|
qboolean texture_ext;
|
|
|
|
HINSTANCE hInstGL;
|
|
|
|
|
|
|
|
texture_ext = FALSE;
|
|
|
|
/* check for texture extension */
|
|
|
|
tmp = (unsigned char *)glGetString(GL_EXTENSIONS);
|
|
|
|
while (*tmp)
|
|
|
|
{
|
|
|
|
if (strncmp((const char*)tmp, TEXTURE_EXT_STRING, strlen(TEXTURE_EXT_STRING)) == 0)
|
|
|
|
texture_ext = TRUE;
|
|
|
|
tmp++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!texture_ext || COM_CheckParm ("-gl11") )
|
|
|
|
{
|
|
|
|
hInstGL = LoadLibrary("opengl32.dll");
|
|
|
|
|
|
|
|
if (hInstGL == NULL)
|
|
|
|
Sys_Error ("Couldn't load opengl32.dll\n");
|
|
|
|
|
|
|
|
bindTexFunc = (void *)GetProcAddress(hInstGL,"glBindTexture");
|
|
|
|
|
|
|
|
if (!bindTexFunc)
|
|
|
|
Sys_Error ("No texture objects!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* load library and get procedure adresses for texture extension API */
|
|
|
|
if ((bindTexFunc = (BINDTEXFUNCPTR)
|
|
|
|
wglGetProcAddress((LPCSTR) "glBindTextureEXT")) == NULL)
|
|
|
|
{
|
|
|
|
Sys_Error ("GetProcAddress for BindTextureEXT failed");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CheckArrayExtensions (void)
|
|
|
|
{
|
|
|
|
char *tmp;
|
|
|
|
|
|
|
|
/* check for texture extension */
|
|
|
|
tmp = (unsigned char *)glGetString(GL_EXTENSIONS);
|
|
|
|
while (*tmp)
|
|
|
|
{
|
|
|
|
if (strncmp((const char*)tmp, "GL_EXT_vertex_array", strlen("GL_EXT_vertex_array")) == 0)
|
|
|
|
{
|
|
|
|
if (
|
|
|
|
((glArrayElementEXT = wglGetProcAddress("glArrayElementEXT")) == NULL) ||
|
|
|
|
((glColorPointerEXT = wglGetProcAddress("glColorPointerEXT")) == NULL) ||
|
|
|
|
((glTexCoordPointerEXT = wglGetProcAddress("glTexCoordPointerEXT")) == NULL) ||
|
|
|
|
((glVertexPointerEXT = wglGetProcAddress("glVertexPointerEXT")) == NULL) )
|
|
|
|
{
|
|
|
|
Sys_Error ("GetProcAddress for vertex extension failed");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
tmp++;
|
|
|
|
}
|
|
|
|
|
|
|
|
Sys_Error ("Vertex array extension not present");
|
|
|
|
}
|
|
|
|
|
|
|
|
//int texture_mode = GL_NEAREST;
|
|
|
|
//int texture_mode = GL_NEAREST_MIPMAP_NEAREST;
|
|
|
|
//int texture_mode = GL_NEAREST_MIPMAP_LINEAR;
|
|
|
|
int texture_mode = GL_LINEAR;
|
|
|
|
//int texture_mode = GL_LINEAR_MIPMAP_NEAREST;
|
|
|
|
//int texture_mode = GL_LINEAR_MIPMAP_LINEAR;
|
|
|
|
|
|
|
|
int texture_extension_number = 1;
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
void CheckMultiTextureExtensions(void)
|
|
|
|
{
|
2000-06-09 21:34:21 +00:00
|
|
|
Con_Printf("Checking for multitexture... ");
|
|
|
|
if (COM_CheckParm ("-nomtex"))
|
|
|
|
{
|
|
|
|
Con_Printf ("disabled\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (strstr(gl_extensions, "GL_ARB_multitexture "))
|
|
|
|
{
|
|
|
|
Con_Printf ("GL_ARB_multitexture\n");
|
|
|
|
qglMTexCoord2f =
|
|
|
|
(void *)wglGetProcAddress("glMTexCoord2fARB");
|
|
|
|
qglSelectTexture =
|
|
|
|
(void *)wglGetProcAddress("glSelectTextureARB");
|
|
|
|
gl_mtex_enum = GL_TEXTURE0_ARB;
|
|
|
|
gl_mtexable = true;
|
|
|
|
gl_arb_mtex = true;
|
|
|
|
} else if (strstr(gl_extensions, "GL_SGIS_multitexture "))
|
|
|
|
{
|
|
|
|
Con_Printf ("GL_SGIS_multitexture\n");
|
|
|
|
qglMTexCoord2f =
|
|
|
|
(void *)wglGetProcAddress("glMTexCoord2fSGIS");
|
|
|
|
qglSelectTexture =
|
|
|
|
(void *)wglGetProcAddress("glSelectTextureSGIS");
|
|
|
|
gl_mtex_enum = TEXTURE0_SGIS;
|
|
|
|
gl_mtexable = true;
|
|
|
|
gl_arb_mtex = false;
|
|
|
|
} else if (strstr(gl_extensions, "GL_EXT_multitexture "))
|
|
|
|
{
|
|
|
|
Con_Printf ("GL_EXT_multitexture\n");
|
|
|
|
qglMTexCoord2f =
|
|
|
|
(void *)wglGetProcAddress("glMTexCoord2fEXT");
|
|
|
|
qglSelectTexture =
|
|
|
|
(void *)wglGetProcAddress("glSelectTextureEXT");
|
|
|
|
gl_mtex_enum = TEXTURE0_SGIS;
|
2000-05-19 08:29:11 +00:00
|
|
|
gl_mtexable = true;
|
2000-06-09 21:34:21 +00:00
|
|
|
gl_arb_mtex = false;
|
|
|
|
} else {
|
|
|
|
Con_Printf ("none found\n");
|
2000-05-19 08:29:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
void CheckMultiTextureExtensions(void)
|
|
|
|
{
|
|
|
|
gl_mtexable = true;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
GL_Init
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void GL_Init (void)
|
|
|
|
{
|
|
|
|
gl_vendor = glGetString (GL_VENDOR);
|
|
|
|
Con_Printf ("GL_VENDOR: %s\n", gl_vendor);
|
|
|
|
gl_renderer = glGetString (GL_RENDERER);
|
|
|
|
Con_Printf ("GL_RENDERER: %s\n", gl_renderer);
|
|
|
|
|
|
|
|
gl_version = glGetString (GL_VERSION);
|
|
|
|
Con_Printf ("GL_VERSION: %s\n", gl_version);
|
|
|
|
gl_extensions = glGetString (GL_EXTENSIONS);
|
|
|
|
Con_Printf ("GL_EXTENSIONS: %s\n", gl_extensions);
|
|
|
|
|
|
|
|
// Con_Printf ("%s %s\n", gl_renderer, gl_version);
|
|
|
|
|
|
|
|
if (strnicmp(gl_renderer,"PowerVR",7)==0)
|
|
|
|
fullsbardraw = true;
|
|
|
|
|
|
|
|
if (strnicmp(gl_renderer,"Permedia",8)==0)
|
|
|
|
isPermedia = true;
|
|
|
|
|
|
|
|
CheckTextureExtensions ();
|
|
|
|
CheckMultiTextureExtensions ();
|
|
|
|
|
2000-06-03 22:32:53 +00:00
|
|
|
glClearColor (0,0,0,0);
|
2000-05-19 08:29:11 +00:00
|
|
|
glCullFace(GL_FRONT);
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
|
|
|
|
glEnable(GL_ALPHA_TEST);
|
|
|
|
glAlphaFunc(GL_GREATER, 0.666);
|
|
|
|
|
|
|
|
glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
|
|
|
|
glShadeModel (GL_FLAT);
|
|
|
|
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
|
|
|
|
|
|
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
|
This is a NON-TRIVIAL update which took LordHavoc and I about 3 days to
make work properly:
Win32 thing.. If you don't free textures explicitly, you can cause a
problem with nVidia drivers.
Colored lighting is now RGB instead of RGBA. The alpha is kinda pointless
on a lightmap and the effect's not all that great. Plus people stuck with
16 bit OpenGL (any other 3dfx people out there?) will be quite pleased
with the improvement in image quality. This does include LordHavoc's
dynamic light optimization code which takes most of the pain out of having
gl_flashblend off.
All glColor*'s are now half of what they used to be, except where they
aren't. If that doesn't make sense, don't worry. If you see one that's
only half what you'd expect, don't worry---it probably is meant to be like
that.. (More below)
glDisable (GL_BLEND) is now a thing of the GL_PAST. As is GL_REPLACE.
Instead, we _always_ use GL_MODULATE and leave GL_BLEND turned on. This
seems at first like it might be a performance hit, but I swear it's much
more expensive to change blending modes and texture functions 20-30 times
every screen frame!
Win32 issue.. Even though we check for multitexture, we currently don't
use it. Reason is that I am planning to replace SGIS_multitexture with
the preferred ARB_multitexture extension which is supported in most GL 1.1
implementations and is a requirement for GL 1.2 anyway. I also wanted to
get rid of some duplicated code. Since Linux doesn't support multitexture
yet, I just commented out the code keeping me from compiling to get it to
work. Win32 should work without it until it's fixed, which shouldn't be
long since the differences between SGIS and ARB multitextures as far as
Quake is concerned is minimal AT BEST.
LordHavoc and I have been working tirelessly (well not quite, we both did
manage to sleep sometime during this ordeal) to fix the lighting in the GL
renderers! It looks DAMNED CLOSE to software's lighting now, including
the ability to overbright a color. You've gotta see this to know what I'm
talking about. That's why the glColor*'s are halved in most places. The
gamma table code and the general way it works is LordHavoc's design, but
over the course of re-implementing it in QF we did come up with a few more
small optimizations.
A lot of people have noticed that QF's fps count has gone to shit lately.
No promises that this undid whatever the problem was. That means there
could be a huge optimization lurking somewhere in the shadows, waiting for
us to fix it for a massive FPS boost. Even if there's not, the code in
this commit DOUBLED MY FPS COUNT. Granted I was getting pathetic FPS as
it was (around 30, which is pathetic even for a Voodoo3 in Linux) but
still---60 is a big improvement over 30!
Please be sure to "test" this code thuroughly.
2000-06-03 19:56:09 +00:00
|
|
|
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
2000-05-19 08:29:11 +00:00
|
|
|
|
|
|
|
#if 0
|
|
|
|
CheckArrayExtensions ();
|
|
|
|
|
|
|
|
glEnable (GL_VERTEX_ARRAY_EXT);
|
|
|
|
glEnable (GL_TEXTURE_COORD_ARRAY_EXT);
|
|
|
|
glVertexPointerEXT (3, GL_FLOAT, 0, 0, &glv.x);
|
|
|
|
glTexCoordPointerEXT (2, GL_FLOAT, 0, 0, &glv.s);
|
|
|
|
glColorPointerEXT (3, GL_FLOAT, 0, 0, &glv.r);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=================
|
|
|
|
GL_BeginRendering
|
|
|
|
|
|
|
|
=================
|
|
|
|
*/
|
|
|
|
void GL_BeginRendering (int *x, int *y, int *width, int *height)
|
|
|
|
{
|
|
|
|
extern cvar_t *gl_clear;
|
|
|
|
|
|
|
|
*x = *y = 0;
|
|
|
|
*width = WindowRect.right - WindowRect.left;
|
|
|
|
*height = WindowRect.bottom - WindowRect.top;
|
|
|
|
|
|
|
|
// if (!wglMakeCurrent( maindc, baseRC ))
|
|
|
|
// Sys_Error ("wglMakeCurrent failed");
|
|
|
|
|
|
|
|
// glViewport (*x, *y, *width, *height);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GL_EndRendering (void)
|
|
|
|
{
|
|
|
|
if (!scr_skipupdate || block_drawing)
|
|
|
|
SwapBuffers(maindc);
|
|
|
|
|
|
|
|
// handle the mouse state when windowed if that's changed
|
|
|
|
if (modestate == MS_WINDOWED)
|
|
|
|
{
|
|
|
|
if (!_windowed_mouse->value) {
|
|
|
|
if (windowed_mouse) {
|
|
|
|
IN_DeactivateMouse ();
|
|
|
|
IN_ShowMouse ();
|
|
|
|
windowed_mouse = false;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
windowed_mouse = true;
|
|
|
|
if (key_dest == key_game && !mouseactive && ActiveApp) {
|
|
|
|
IN_ActivateMouse ();
|
|
|
|
IN_HideMouse ();
|
|
|
|
} else if (mouseactive && key_dest != key_game) {
|
|
|
|
IN_DeactivateMouse ();
|
|
|
|
IN_ShowMouse ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (fullsbardraw)
|
|
|
|
Sbar_Changed();
|
|
|
|
}
|
|
|
|
|
|
|
|
void VID_SetPalette (unsigned char *palette)
|
|
|
|
{
|
|
|
|
byte *pal;
|
|
|
|
unsigned r,g,b;
|
|
|
|
unsigned v;
|
|
|
|
int r1,g1,b1;
|
|
|
|
int j,k,l,m;
|
|
|
|
unsigned short i;
|
|
|
|
unsigned *table;
|
|
|
|
FILE *f;
|
|
|
|
char s[255];
|
|
|
|
HWND hDlg, hProgress;
|
|
|
|
float gamma;
|
|
|
|
|
|
|
|
//
|
|
|
|
// 8 8 8 encoding
|
|
|
|
//
|
|
|
|
pal = palette;
|
|
|
|
table = d_8to24table;
|
|
|
|
for (i=0 ; i<256 ; i++)
|
|
|
|
{
|
|
|
|
r = pal[0];
|
|
|
|
g = pal[1];
|
|
|
|
b = pal[2];
|
|
|
|
pal += 3;
|
|
|
|
|
|
|
|
// v = (255<<24) + (r<<16) + (g<<8) + (b<<0);
|
|
|
|
// v = (255<<0) + (r<<8) + (g<<16) + (b<<24);
|
|
|
|
v = (255<<24) + (r<<0) + (g<<8) + (b<<16);
|
|
|
|
*table++ = v;
|
|
|
|
}
|
|
|
|
d_8to24table[255] &= 0xffffff; // 255 is transparent
|
|
|
|
|
|
|
|
// JACK: 3D distance calcs - k is last closest, l is the distance.
|
|
|
|
// FIXME: Precalculate this and cache to disk.
|
|
|
|
for (i=0; i < (1<<15); i++) {
|
|
|
|
/* Maps
|
|
|
|
000000000000000
|
|
|
|
000000000011111 = Red = 0x1F
|
|
|
|
000001111100000 = Blue = 0x03E0
|
|
|
|
111110000000000 = Grn = 0x7C00
|
|
|
|
*/
|
|
|
|
r = ((i & 0x1F) << 3)+4;
|
|
|
|
g = ((i & 0x03E0) >> 2)+4;
|
|
|
|
b = ((i & 0x7C00) >> 7)+4;
|
|
|
|
pal = (unsigned char *)d_8to24table;
|
|
|
|
for (v=0,k=0,l=10000*10000; v<256; v++,pal+=4) {
|
|
|
|
r1 = r-pal[0];
|
|
|
|
g1 = g-pal[1];
|
|
|
|
b1 = b-pal[2];
|
|
|
|
j = (r1*r1)+(g1*g1)+(b1*b1);
|
|
|
|
if (j<l) {
|
|
|
|
k=v;
|
|
|
|
l=j;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
d_15to8table[i]=k;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL gammaworks;
|
|
|
|
|
|
|
|
void VID_ShiftPalette (unsigned char *palette)
|
|
|
|
{
|
|
|
|
extern byte ramps[3][256];
|
|
|
|
|
|
|
|
// VID_SetPalette (palette);
|
|
|
|
|
|
|
|
// gammaworks = SetDeviceGammaRamp (maindc, ramps);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void VID_SetDefaultMode (void)
|
|
|
|
{
|
|
|
|
IN_DeactivateMouse ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void VID_Shutdown (void)
|
|
|
|
{
|
|
|
|
HGLRC hRC;
|
|
|
|
HDC hDC;
|
2000-06-04 09:18:48 +00:00
|
|
|
int i,temp[8192];
|
|
|
|
|
2000-05-19 08:29:11 +00:00
|
|
|
|
|
|
|
if (vid_initialized)
|
|
|
|
{
|
|
|
|
vid_canalttab = false;
|
|
|
|
hRC = wglGetCurrentContext();
|
|
|
|
hDC = wglGetCurrentDC();
|
|
|
|
|
|
|
|
wglMakeCurrent(NULL, NULL);
|
|
|
|
|
This is a NON-TRIVIAL update which took LordHavoc and I about 3 days to
make work properly:
Win32 thing.. If you don't free textures explicitly, you can cause a
problem with nVidia drivers.
Colored lighting is now RGB instead of RGBA. The alpha is kinda pointless
on a lightmap and the effect's not all that great. Plus people stuck with
16 bit OpenGL (any other 3dfx people out there?) will be quite pleased
with the improvement in image quality. This does include LordHavoc's
dynamic light optimization code which takes most of the pain out of having
gl_flashblend off.
All glColor*'s are now half of what they used to be, except where they
aren't. If that doesn't make sense, don't worry. If you see one that's
only half what you'd expect, don't worry---it probably is meant to be like
that.. (More below)
glDisable (GL_BLEND) is now a thing of the GL_PAST. As is GL_REPLACE.
Instead, we _always_ use GL_MODULATE and leave GL_BLEND turned on. This
seems at first like it might be a performance hit, but I swear it's much
more expensive to change blending modes and texture functions 20-30 times
every screen frame!
Win32 issue.. Even though we check for multitexture, we currently don't
use it. Reason is that I am planning to replace SGIS_multitexture with
the preferred ARB_multitexture extension which is supported in most GL 1.1
implementations and is a requirement for GL 1.2 anyway. I also wanted to
get rid of some duplicated code. Since Linux doesn't support multitexture
yet, I just commented out the code keeping me from compiling to get it to
work. Win32 should work without it until it's fixed, which shouldn't be
long since the differences between SGIS and ARB multitextures as far as
Quake is concerned is minimal AT BEST.
LordHavoc and I have been working tirelessly (well not quite, we both did
manage to sleep sometime during this ordeal) to fix the lighting in the GL
renderers! It looks DAMNED CLOSE to software's lighting now, including
the ability to overbright a color. You've gotta see this to know what I'm
talking about. That's why the glColor*'s are halved in most places. The
gamma table code and the general way it works is LordHavoc's design, but
over the course of re-implementing it in QF we did come up with a few more
small optimizations.
A lot of people have noticed that QF's fps count has gone to shit lately.
No promises that this undid whatever the problem was. That means there
could be a huge optimization lurking somewhere in the shadows, waiting for
us to fix it for a massive FPS boost. Even if there's not, the code in
this commit DOUBLED MY FPS COUNT. Granted I was getting pathetic FPS as
it was (around 30, which is pathetic even for a Voodoo3 in Linux) but
still---60 is a big improvement over 30!
Please be sure to "test" this code thuroughly.
2000-06-03 19:56:09 +00:00
|
|
|
// LordHavoc: free textures before closing (may help NVIDIA)
|
|
|
|
for (i = 0;i < 8192;i++)
|
|
|
|
temp[i] = i;
|
|
|
|
glDeleteTextures(8192, temp);
|
|
|
|
|
2000-05-19 08:29:11 +00:00
|
|
|
if (hRC)
|
|
|
|
wglDeleteContext(hRC);
|
|
|
|
|
|
|
|
if (hDC && dibwindow)
|
|
|
|
ReleaseDC(dibwindow, hDC);
|
|
|
|
|
|
|
|
if (modestate == MS_FULLDIB)
|
|
|
|
ChangeDisplaySettings (NULL, 0);
|
|
|
|
|
|
|
|
if (maindc && dibwindow)
|
|
|
|
ReleaseDC (dibwindow, maindc);
|
|
|
|
|
|
|
|
AppActivate(false, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
|
|
|
|
BOOL bSetupPixelFormat(HDC hDC)
|
|
|
|
{
|
|
|
|
static PIXELFORMATDESCRIPTOR pfd = {
|
|
|
|
sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
|
|
|
|
1, // version number
|
|
|
|
PFD_DRAW_TO_WINDOW // support window
|
|
|
|
| PFD_SUPPORT_OPENGL // support OpenGL
|
|
|
|
| PFD_DOUBLEBUFFER , // double buffered
|
|
|
|
PFD_TYPE_RGBA, // RGBA type
|
|
|
|
24, // 24-bit color depth
|
|
|
|
0, 0, 0, 0, 0, 0, // color bits ignored
|
|
|
|
0, // no alpha buffer
|
|
|
|
0, // shift bit ignored
|
|
|
|
0, // no accumulation buffer
|
|
|
|
0, 0, 0, 0, // accum bits ignored
|
|
|
|
32, // 32-bit z-buffer
|
|
|
|
0, // no stencil buffer
|
|
|
|
0, // no auxiliary buffer
|
|
|
|
PFD_MAIN_PLANE, // main layer
|
|
|
|
0, // reserved
|
|
|
|
0, 0, 0 // layer masks ignored
|
|
|
|
};
|
|
|
|
int pixelformat;
|
|
|
|
|
|
|
|
if ( (pixelformat = ChoosePixelFormat(hDC, &pfd)) == 0 )
|
|
|
|
{
|
|
|
|
MessageBox(NULL, "ChoosePixelFormat failed", "Error", MB_OK);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (SetPixelFormat(hDC, pixelformat, &pfd) == FALSE)
|
|
|
|
{
|
|
|
|
MessageBox(NULL, "SetPixelFormat failed", "Error", MB_OK);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-05-22 07:59:30 +00:00
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
byte scantokey[128] =
|
|
|
|
{
|
|
|
|
// 0 1 2 3 4 5 6 7
|
|
|
|
// 8 9 A B C D E F
|
|
|
|
0 , 27, '1', '2', '3', '4', '5', '6',
|
|
|
|
'7', '8', '9', '0', '-', '=', K_BACKSPACE, 9, // 0
|
|
|
|
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
|
|
|
|
'o', 'p', '[', ']', 13, K_CTRL, 'a', 's', // 1
|
|
|
|
'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
|
|
|
|
'\'', '`', K_SHIFT,'\\', 'z', 'x', 'c', 'v', // 2
|
|
|
|
'b', 'n', 'm', ',', '.', '/', K_SHIFT,KP_MULTIPLY,
|
|
|
|
K_ALT, ' ', K_CAPSLOCK,K_F1, K_F2, K_F3, K_F4, K_F5, // 3
|
|
|
|
K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE,K_SCRLCK,KP_HOME,
|
|
|
|
KP_UPARROW,KP_PGUP,KP_MINUS,KP_LEFTARROW,KP_5,KP_RIGHTARROW,KP_PLUS,KP_END, // 4
|
|
|
|
KP_DOWNARROW,KP_PGDN,KP_INS,KP_DEL,0, 0, 0, K_F11,
|
|
|
|
K_F12, 0, 0, 0, 0, 0, 0, 0, // 5
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0
|
|
|
|
};
|
|
|
|
|
|
|
|
byte extscantokey[128] =
|
|
|
|
{
|
|
|
|
// 0 1 2 3 4 5 6 7
|
|
|
|
// 8 9 A B C D E F
|
|
|
|
0 , 27, '1', '2', '3', '4', '5', '6',
|
|
|
|
'7', '8', '9', '0', '-', '=', K_BACKSPACE, 9, // 0
|
|
|
|
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
|
|
|
|
'o', 'p', '[', ']', KP_ENTER,K_CTRL,'a', 's', // 1
|
|
|
|
'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
|
|
|
|
'\'', '`', K_SHIFT,'\\', 'z', 'x', 'c', 'v', // 2
|
|
|
|
'b', 'n', 'm', ',', '.', KP_DIVIDE,K_SHIFT,'*',
|
|
|
|
K_ALT, ' ', K_CAPSLOCK,K_F1,K_F2, K_F3, K_F4, K_F5, // 3
|
|
|
|
K_F6, K_F7, K_F8, K_F9, K_F10, KP_NUMLCK,0, K_HOME,
|
|
|
|
K_UPARROW,K_PGUP,'-',K_LEFTARROW,'5',K_RIGHTARROW,'+', K_END, // 4
|
|
|
|
K_DOWNARROW,K_PGDN,K_INS,K_DEL, 0, 0, 0, K_F11,
|
|
|
|
K_F12, 0, 0, 0, 0, 0, 0, 0, // 5
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0
|
|
|
|
};
|
2000-05-19 08:29:11 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======
|
|
|
|
MapKey
|
|
|
|
|
|
|
|
Map from windows to quake keynums
|
|
|
|
=======
|
|
|
|
*/
|
|
|
|
int MapKey (int key)
|
|
|
|
{
|
2000-05-22 07:59:30 +00:00
|
|
|
int extended;
|
|
|
|
|
|
|
|
extended = (key >> 24) & 1;
|
|
|
|
|
2000-05-19 08:29:11 +00:00
|
|
|
key = (key>>16)&255;
|
|
|
|
if (key > 127)
|
|
|
|
return 0;
|
2000-05-22 07:59:30 +00:00
|
|
|
|
|
|
|
if (extended)
|
|
|
|
return extscantokey[key];
|
|
|
|
else
|
|
|
|
return scantokey[key];
|
2000-05-19 08:29:11 +00:00
|
|
|
}
|
|
|
|
|
2000-05-22 07:59:30 +00:00
|
|
|
|
2000-05-19 08:29:11 +00:00
|
|
|
/*
|
|
|
|
===================================================================
|
|
|
|
|
|
|
|
MAIN WINDOW
|
|
|
|
|
|
|
|
===================================================================
|
|
|
|
*/
|
|
|
|
|
2000-05-22 07:59:30 +00:00
|
|
|
extern void CL_ClearStates ();
|
|
|
|
|
2000-05-19 08:29:11 +00:00
|
|
|
/*
|
|
|
|
================
|
|
|
|
ClearAllStates
|
|
|
|
================
|
|
|
|
*/
|
|
|
|
void ClearAllStates (void)
|
|
|
|
{
|
2000-05-22 07:20:00 +00:00
|
|
|
CL_ClearStates ();
|
2000-05-19 08:29:11 +00:00
|
|
|
Key_ClearStates ();
|
|
|
|
IN_ClearStates ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void AppActivate(BOOL fActive, BOOL minimize)
|
|
|
|
/****************************************************************************
|
|
|
|
*
|
|
|
|
* Function: AppActivate
|
|
|
|
* Parameters: fActive - True if app is activating
|
|
|
|
*
|
|
|
|
* Description: If the application is activating, then swap the system
|
|
|
|
* into SYSPAL_NOSTATIC mode so that our palettes will display
|
|
|
|
* correctly.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
{
|
|
|
|
MSG msg;
|
|
|
|
HDC hdc;
|
|
|
|
int i, t;
|
|
|
|
static BOOL sound_active;
|
|
|
|
|
|
|
|
ActiveApp = fActive;
|
|
|
|
Minimized = minimize;
|
|
|
|
|
|
|
|
// enable/disable sound on focus gain/loss
|
|
|
|
if (!ActiveApp && sound_active)
|
|
|
|
{
|
|
|
|
S_BlockSound ();
|
|
|
|
sound_active = false;
|
|
|
|
}
|
|
|
|
else if (ActiveApp && !sound_active)
|
|
|
|
{
|
|
|
|
S_UnblockSound ();
|
|
|
|
sound_active = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fActive)
|
|
|
|
{
|
|
|
|
if (modestate == MS_FULLDIB)
|
|
|
|
{
|
|
|
|
IN_ActivateMouse ();
|
|
|
|
IN_HideMouse ();
|
|
|
|
if (vid_canalttab && vid_wassuspended) {
|
|
|
|
vid_wassuspended = false;
|
|
|
|
ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN);
|
|
|
|
ShowWindow(mainwindow, SW_SHOWNORMAL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ((modestate == MS_WINDOWED) && _windowed_mouse->value && key_dest == key_game)
|
|
|
|
{
|
|
|
|
IN_ActivateMouse ();
|
|
|
|
IN_HideMouse ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!fActive)
|
|
|
|
{
|
|
|
|
if (modestate == MS_FULLDIB)
|
|
|
|
{
|
|
|
|
IN_DeactivateMouse ();
|
|
|
|
IN_ShowMouse ();
|
|
|
|
if (vid_canalttab) {
|
|
|
|
ChangeDisplaySettings (NULL, 0);
|
|
|
|
vid_wassuspended = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ((modestate == MS_WINDOWED) && _windowed_mouse->value)
|
|
|
|
{
|
|
|
|
IN_DeactivateMouse ();
|
|
|
|
IN_ShowMouse ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* main window procedure */
|
|
|
|
LONG WINAPI MainWndProc (
|
|
|
|
HWND hWnd,
|
|
|
|
UINT uMsg,
|
|
|
|
WPARAM wParam,
|
|
|
|
LPARAM lParam)
|
|
|
|
{
|
|
|
|
LONG lRet = 1;
|
|
|
|
int fwKeys, xPos, yPos, fActive, fMinimized, temp;
|
|
|
|
extern unsigned int uiWheelMessage;
|
|
|
|
|
|
|
|
if ( uMsg == uiWheelMessage )
|
|
|
|
uMsg = WM_MOUSEWHEEL;
|
|
|
|
|
|
|
|
switch (uMsg)
|
|
|
|
{
|
|
|
|
case WM_KILLFOCUS:
|
|
|
|
if (modestate == MS_FULLDIB)
|
|
|
|
ShowWindow(mainwindow, SW_SHOWMINNOACTIVE);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_CREATE:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_MOVE:
|
|
|
|
window_x = (int) LOWORD(lParam);
|
|
|
|
window_y = (int) HIWORD(lParam);
|
|
|
|
VID_UpdateWindowStatus ();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_KEYDOWN:
|
|
|
|
case WM_SYSKEYDOWN:
|
|
|
|
Key_Event (MapKey(lParam), true);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_KEYUP:
|
|
|
|
case WM_SYSKEYUP:
|
|
|
|
Key_Event (MapKey(lParam), false);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_SYSCHAR:
|
|
|
|
// keep Alt-Space from happening
|
|
|
|
break;
|
|
|
|
|
|
|
|
// this is complicated because Win32 seems to pack multiple mouse events into
|
|
|
|
// one update sometimes, so we always check all states and look for events
|
|
|
|
case WM_LBUTTONDOWN:
|
|
|
|
case WM_LBUTTONUP:
|
|
|
|
case WM_RBUTTONDOWN:
|
|
|
|
case WM_RBUTTONUP:
|
|
|
|
case WM_MBUTTONDOWN:
|
|
|
|
case WM_MBUTTONUP:
|
|
|
|
case WM_MOUSEMOVE:
|
|
|
|
temp = 0;
|
|
|
|
|
|
|
|
if (wParam & MK_LBUTTON)
|
|
|
|
temp |= 1;
|
|
|
|
|
|
|
|
if (wParam & MK_RBUTTON)
|
|
|
|
temp |= 2;
|
|
|
|
|
|
|
|
if (wParam & MK_MBUTTON)
|
|
|
|
temp |= 4;
|
|
|
|
|
|
|
|
IN_MouseEvent (temp);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
// JACK: This is the mouse wheel with the Intellimouse
|
|
|
|
// Its delta is either positive or neg, and we generate the proper
|
|
|
|
// Event.
|
|
|
|
case WM_MOUSEWHEEL:
|
|
|
|
if ((short) HIWORD(wParam) > 0) {
|
|
|
|
Key_Event(K_MWHEELUP, true);
|
|
|
|
Key_Event(K_MWHEELUP, false);
|
|
|
|
} else {
|
|
|
|
Key_Event(K_MWHEELDOWN, true);
|
|
|
|
Key_Event(K_MWHEELDOWN, false);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_SIZE:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_CLOSE:
|
|
|
|
if (MessageBox (mainwindow, "Are you sure you want to quit?", "Confirm Exit",
|
|
|
|
MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION) == IDYES)
|
|
|
|
{
|
|
|
|
Sys_Quit ();
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_ACTIVATE:
|
|
|
|
fActive = LOWORD(wParam);
|
|
|
|
fMinimized = (BOOL) HIWORD(wParam);
|
|
|
|
AppActivate(!(fActive == WA_INACTIVE), fMinimized);
|
|
|
|
|
|
|
|
// fix the leftover Alt from any Alt-Tab or the like that switched us away
|
|
|
|
ClearAllStates ();
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_DESTROY:
|
|
|
|
{
|
|
|
|
if (dibwindow)
|
|
|
|
DestroyWindow (dibwindow);
|
|
|
|
|
|
|
|
PostQuitMessage (0);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MM_MCINOTIFY:
|
|
|
|
lRet = CDAudio_MessageHandler (hWnd, uMsg, wParam, lParam);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
/* pass all unhandled messages to DefWindowProc */
|
|
|
|
lRet = DefWindowProc (hWnd, uMsg, wParam, lParam);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* return 1 if handled message, 0 if not */
|
|
|
|
return lRet;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
=================
|
|
|
|
VID_NumModes
|
|
|
|
=================
|
|
|
|
*/
|
|
|
|
int VID_NumModes (void)
|
|
|
|
{
|
|
|
|
return nummodes;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
=================
|
|
|
|
VID_GetModePtr
|
|
|
|
=================
|
|
|
|
*/
|
|
|
|
vmode_t *VID_GetModePtr (int modenum)
|
|
|
|
{
|
|
|
|
|
|
|
|
if ((modenum >= 0) && (modenum < nummodes))
|
|
|
|
return &modelist[modenum];
|
|
|
|
else
|
|
|
|
return &badmode;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
=================
|
|
|
|
VID_GetModeDescription
|
|
|
|
=================
|
|
|
|
*/
|
|
|
|
char *VID_GetModeDescription (int mode)
|
|
|
|
{
|
|
|
|
char *pinfo;
|
|
|
|
vmode_t *pv;
|
|
|
|
static char temp[100];
|
|
|
|
|
|
|
|
if ((mode < 0) || (mode >= nummodes))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!leavecurrentmode)
|
|
|
|
{
|
|
|
|
pv = VID_GetModePtr (mode);
|
|
|
|
pinfo = pv->modedesc;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
snprintf (temp, sizeof(temp), "Desktop resolution (%dx%d)",
|
|
|
|
modelist[MODE_FULLSCREEN_DEFAULT].width,
|
|
|
|
modelist[MODE_FULLSCREEN_DEFAULT].height);
|
|
|
|
pinfo = temp;
|
|
|
|
}
|
|
|
|
|
|
|
|
return pinfo;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// KJB: Added this to return the mode driver name in description for console
|
|
|
|
|
|
|
|
char *VID_GetExtModeDescription (int mode)
|
|
|
|
{
|
|
|
|
static char pinfo[40];
|
|
|
|
vmode_t *pv;
|
|
|
|
|
|
|
|
if ((mode < 0) || (mode >= nummodes))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
pv = VID_GetModePtr (mode);
|
|
|
|
if (modelist[mode].type == MS_FULLDIB)
|
|
|
|
{
|
|
|
|
if (!leavecurrentmode)
|
|
|
|
{
|
|
|
|
snprintf (pinfo, sizeof(pinfo), "%s fullscreen", pv->modedesc);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
snprintf (pinfo, sizeof(pinfo), "Desktop resolution (%dx%d)",
|
|
|
|
modelist[MODE_FULLSCREEN_DEFAULT].width,
|
|
|
|
modelist[MODE_FULLSCREEN_DEFAULT].height);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (modestate == MS_WINDOWED)
|
|
|
|
snprintf (pinfo, sizeof(pinfo), "%s windowed", pv->modedesc);
|
|
|
|
else
|
2000-05-20 08:23:41 +00:00
|
|
|
snprintf (pinfo, sizeof(pinfo), "windowed");
|
2000-05-19 08:29:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return pinfo;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
=================
|
|
|
|
VID_DescribeCurrentMode_f
|
|
|
|
=================
|
|
|
|
*/
|
|
|
|
void VID_DescribeCurrentMode_f (void)
|
|
|
|
{
|
|
|
|
Con_Printf ("%s\n", VID_GetExtModeDescription (vid_modenum));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
=================
|
|
|
|
VID_NumModes_f
|
|
|
|
=================
|
|
|
|
*/
|
|
|
|
void VID_NumModes_f (void)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (nummodes == 1)
|
|
|
|
Con_Printf ("%d video mode is available\n", nummodes);
|
|
|
|
else
|
|
|
|
Con_Printf ("%d video modes are available\n", nummodes);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
=================
|
|
|
|
VID_DescribeMode_f
|
|
|
|
=================
|
|
|
|
*/
|
|
|
|
void VID_DescribeMode_f (void)
|
|
|
|
{
|
|
|
|
int t, modenum;
|
|
|
|
|
2000-05-21 11:32:35 +00:00
|
|
|
modenum = atoi (Cmd_Argv(1));
|
2000-05-19 08:29:11 +00:00
|
|
|
|
|
|
|
t = leavecurrentmode;
|
|
|
|
leavecurrentmode = 0;
|
|
|
|
|
|
|
|
Con_Printf ("%s\n", VID_GetExtModeDescription (modenum));
|
|
|
|
|
|
|
|
leavecurrentmode = t;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
=================
|
|
|
|
VID_DescribeModes_f
|
|
|
|
=================
|
|
|
|
*/
|
|
|
|
void VID_DescribeModes_f (void)
|
|
|
|
{
|
|
|
|
int i, lnummodes, t;
|
|
|
|
char *pinfo;
|
|
|
|
vmode_t *pv;
|
|
|
|
|
|
|
|
lnummodes = VID_NumModes ();
|
|
|
|
|
|
|
|
t = leavecurrentmode;
|
|
|
|
leavecurrentmode = 0;
|
|
|
|
|
|
|
|
for (i=1 ; i<lnummodes ; i++)
|
|
|
|
{
|
|
|
|
pv = VID_GetModePtr (i);
|
|
|
|
pinfo = VID_GetExtModeDescription (i);
|
|
|
|
Con_Printf ("%2d: %s\n", i, pinfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
leavecurrentmode = t;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void VID_InitDIB (HINSTANCE hInstance)
|
|
|
|
{
|
|
|
|
WNDCLASS wc;
|
|
|
|
HDC hdc;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* Register the frame class */
|
|
|
|
wc.style = 0;
|
|
|
|
wc.lpfnWndProc = (WNDPROC)MainWndProc;
|
|
|
|
wc.cbClsExtra = 0;
|
|
|
|
wc.cbWndExtra = 0;
|
|
|
|
wc.hInstance = hInstance;
|
|
|
|
wc.hIcon = 0;
|
|
|
|
wc.hCursor = LoadCursor (NULL,IDC_ARROW);
|
|
|
|
wc.hbrBackground = NULL;
|
|
|
|
wc.lpszMenuName = 0;
|
|
|
|
wc.lpszClassName = "WinQuake";
|
|
|
|
|
|
|
|
if (!RegisterClass (&wc) )
|
|
|
|
Sys_Error ("Couldn't register window class");
|
|
|
|
|
|
|
|
modelist[0].type = MS_WINDOWED;
|
|
|
|
|
|
|
|
if (COM_CheckParm("-width"))
|
2000-05-21 11:32:35 +00:00
|
|
|
modelist[0].width = atoi(com_argv[COM_CheckParm("-width")+1]);
|
2000-05-19 08:29:11 +00:00
|
|
|
else
|
|
|
|
modelist[0].width = 640;
|
|
|
|
|
|
|
|
if (modelist[0].width < 320)
|
|
|
|
modelist[0].width = 320;
|
|
|
|
|
|
|
|
if (COM_CheckParm("-height"))
|
2000-05-21 11:32:35 +00:00
|
|
|
modelist[0].height= atoi(com_argv[COM_CheckParm("-height")+1]);
|
2000-05-19 08:29:11 +00:00
|
|
|
else
|
|
|
|
modelist[0].height = modelist[0].width * 240/320;
|
|
|
|
|
|
|
|
if (modelist[0].height < 240)
|
|
|
|
modelist[0].height = 240;
|
|
|
|
|
2000-05-20 08:23:41 +00:00
|
|
|
snprintf (modelist[0].modedesc, sizeof(modelist[0].modedesc), "%dx%d",
|
2000-05-19 08:29:11 +00:00
|
|
|
modelist[0].width, modelist[0].height);
|
|
|
|
|
|
|
|
modelist[0].modenum = MODE_WINDOWED;
|
|
|
|
modelist[0].dib = 1;
|
|
|
|
modelist[0].fullscreen = 0;
|
|
|
|
modelist[0].halfscreen = 0;
|
|
|
|
modelist[0].bpp = 0;
|
|
|
|
|
|
|
|
nummodes = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
=================
|
|
|
|
VID_InitFullDIB
|
|
|
|
=================
|
|
|
|
*/
|
|
|
|
void VID_InitFullDIB (HINSTANCE hInstance)
|
|
|
|
{
|
|
|
|
DEVMODE devmode;
|
|
|
|
int i, modenum, cmodes, originalnummodes, existingmode, numlowresmodes;
|
|
|
|
int j, bpp, done;
|
|
|
|
BOOL stat;
|
|
|
|
|
|
|
|
// enumerate >8 bpp modes
|
|
|
|
originalnummodes = nummodes;
|
|
|
|
modenum = 0;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
stat = EnumDisplaySettings (NULL, modenum, &devmode);
|
|
|
|
|
|
|
|
if ((devmode.dmBitsPerPel >= 15) &&
|
|
|
|
(devmode.dmPelsWidth <= MAXWIDTH) &&
|
|
|
|
(devmode.dmPelsHeight <= MAXHEIGHT) &&
|
|
|
|
(nummodes < MAX_MODE_LIST))
|
|
|
|
{
|
|
|
|
devmode.dmFields = DM_BITSPERPEL |
|
|
|
|
DM_PELSWIDTH |
|
|
|
|
DM_PELSHEIGHT;
|
|
|
|
|
|
|
|
if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) ==
|
|
|
|
DISP_CHANGE_SUCCESSFUL)
|
|
|
|
{
|
|
|
|
modelist[nummodes].type = MS_FULLDIB;
|
|
|
|
modelist[nummodes].width = devmode.dmPelsWidth;
|
|
|
|
modelist[nummodes].height = devmode.dmPelsHeight;
|
|
|
|
modelist[nummodes].modenum = 0;
|
|
|
|
modelist[nummodes].halfscreen = 0;
|
|
|
|
modelist[nummodes].dib = 1;
|
|
|
|
modelist[nummodes].fullscreen = 1;
|
|
|
|
modelist[nummodes].bpp = devmode.dmBitsPerPel;
|
2000-05-20 08:23:41 +00:00
|
|
|
snprintf (modelist[nummodes].modedesc, sizeof(modelist[nummodes].modedesc), "%dx%dx%d",
|
2000-05-19 08:29:11 +00:00
|
|
|
devmode.dmPelsWidth, devmode.dmPelsHeight,
|
|
|
|
devmode.dmBitsPerPel);
|
|
|
|
|
|
|
|
// if the width is more than twice the height, reduce it by half because this
|
|
|
|
// is probably a dual-screen monitor
|
|
|
|
if (!COM_CheckParm("-noadjustaspect"))
|
|
|
|
{
|
|
|
|
if (modelist[nummodes].width > (modelist[nummodes].height << 1))
|
|
|
|
{
|
|
|
|
modelist[nummodes].width >>= 1;
|
|
|
|
modelist[nummodes].halfscreen = 1;
|
2000-05-20 08:23:41 +00:00
|
|
|
snprintf (modelist[nummodes].modedesc, sizeof(modelist[nummodes].modedesc), "%dx%dx%d",
|
2000-05-19 08:29:11 +00:00
|
|
|
modelist[nummodes].width,
|
|
|
|
modelist[nummodes].height,
|
|
|
|
modelist[nummodes].bpp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i=originalnummodes, existingmode = 0 ; i<nummodes ; i++)
|
|
|
|
{
|
|
|
|
if ((modelist[nummodes].width == modelist[i].width) &&
|
|
|
|
(modelist[nummodes].height == modelist[i].height) &&
|
|
|
|
(modelist[nummodes].bpp == modelist[i].bpp))
|
|
|
|
{
|
|
|
|
existingmode = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!existingmode)
|
|
|
|
{
|
|
|
|
nummodes++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
modenum++;
|
|
|
|
} while (stat);
|
|
|
|
|
|
|
|
// see if there are any low-res modes that aren't being reported
|
|
|
|
numlowresmodes = sizeof(lowresmodes) / sizeof(lowresmodes[0]);
|
|
|
|
bpp = 16;
|
|
|
|
done = 0;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
for (j=0 ; (j<numlowresmodes) && (nummodes < MAX_MODE_LIST) ; j++)
|
|
|
|
{
|
|
|
|
devmode.dmBitsPerPel = bpp;
|
|
|
|
devmode.dmPelsWidth = lowresmodes[j].width;
|
|
|
|
devmode.dmPelsHeight = lowresmodes[j].height;
|
|
|
|
devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
|
|
|
|
|
|
|
|
if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) ==
|
|
|
|
DISP_CHANGE_SUCCESSFUL)
|
|
|
|
{
|
|
|
|
modelist[nummodes].type = MS_FULLDIB;
|
|
|
|
modelist[nummodes].width = devmode.dmPelsWidth;
|
|
|
|
modelist[nummodes].height = devmode.dmPelsHeight;
|
|
|
|
modelist[nummodes].modenum = 0;
|
|
|
|
modelist[nummodes].halfscreen = 0;
|
|
|
|
modelist[nummodes].dib = 1;
|
|
|
|
modelist[nummodes].fullscreen = 1;
|
|
|
|
modelist[nummodes].bpp = devmode.dmBitsPerPel;
|
2000-05-20 08:23:41 +00:00
|
|
|
snprintf (modelist[nummodes].modedesc, sizeof(modelist[nummodes].modedesc), "%dx%dx%d",
|
2000-05-19 08:29:11 +00:00
|
|
|
devmode.dmPelsWidth, devmode.dmPelsHeight,
|
|
|
|
devmode.dmBitsPerPel);
|
|
|
|
|
|
|
|
for (i=originalnummodes, existingmode = 0 ; i<nummodes ; i++)
|
|
|
|
{
|
|
|
|
if ((modelist[nummodes].width == modelist[i].width) &&
|
|
|
|
(modelist[nummodes].height == modelist[i].height) &&
|
|
|
|
(modelist[nummodes].bpp == modelist[i].bpp))
|
|
|
|
{
|
|
|
|
existingmode = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!existingmode)
|
|
|
|
{
|
|
|
|
nummodes++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
switch (bpp)
|
|
|
|
{
|
|
|
|
case 16:
|
|
|
|
bpp = 32;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 32:
|
|
|
|
bpp = 24;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 24:
|
|
|
|
done = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} while (!done);
|
|
|
|
|
|
|
|
if (nummodes == originalnummodes)
|
|
|
|
Con_SafePrintf ("No fullscreen DIB modes found\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
qboolean VID_Is8bit() {
|
|
|
|
return is8bit;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define GL_SHARED_TEXTURE_PALETTE_EXT 0x81FB
|
|
|
|
|
|
|
|
void VID_Init8bitPalette()
|
|
|
|
{
|
|
|
|
// Check for 8bit Extensions and initialize them.
|
|
|
|
int i;
|
|
|
|
char thePalette[256*3];
|
|
|
|
char *oldPalette, *newPalette;
|
|
|
|
|
|
|
|
glColorTableEXT = (void *)wglGetProcAddress("glColorTableEXT");
|
|
|
|
if (!glColorTableEXT || strstr(gl_extensions, "GL_EXT_shared_texture_palette") ||
|
|
|
|
COM_CheckParm("-no8bit"))
|
|
|
|
return;
|
|
|
|
|
|
|
|
Con_SafePrintf("8-bit GL extensions enabled.\n");
|
|
|
|
glEnable( GL_SHARED_TEXTURE_PALETTE_EXT );
|
|
|
|
oldPalette = (char *) d_8to24table; //d_8to24table3dfx;
|
|
|
|
newPalette = thePalette;
|
|
|
|
for (i=0;i<256;i++) {
|
|
|
|
*newPalette++ = *oldPalette++;
|
|
|
|
*newPalette++ = *oldPalette++;
|
|
|
|
*newPalette++ = *oldPalette++;
|
|
|
|
oldPalette++;
|
|
|
|
}
|
|
|
|
glColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGB, 256, GL_RGB, GL_UNSIGNED_BYTE,
|
|
|
|
(void *) thePalette);
|
|
|
|
is8bit = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===================
|
|
|
|
VID_Init
|
|
|
|
===================
|
|
|
|
*/
|
|
|
|
void VID_Init (unsigned char *palette)
|
|
|
|
{
|
|
|
|
int i, existingmode;
|
|
|
|
int basenummodes, width, height, bpp, findbpp, done;
|
|
|
|
byte *ptmp;
|
|
|
|
char gldir[MAX_OSPATH];
|
|
|
|
HDC hdc;
|
|
|
|
DEVMODE devmode;
|
|
|
|
|
|
|
|
memset(&devmode, 0, sizeof(devmode));
|
|
|
|
|
2000-05-22 01:05:57 +00:00
|
|
|
// Note that 0 is MODE_WINDOWED
|
2000-05-19 08:29:11 +00:00
|
|
|
vid_mode = Cvar_Get("vid_mode", "0", CVAR_NONE, "None");
|
2000-05-22 01:05:57 +00:00
|
|
|
_vid_default_mode = Cvar_Get("_vid_default_mode", "0", CVAR_ARCHIVE, "None");
|
|
|
|
// Note that 3 is MODE_FULLSCREEN_DEFAULT
|
|
|
|
_vid_default_mode_win = Cvar_Get("_vid_default_mode_win", "3", CVAR_ARCHIVE, "None");
|
|
|
|
|
2000-05-19 08:29:11 +00:00
|
|
|
vid_wait = Cvar_Get("vid_wait", "0", CVAR_NONE, "None");
|
|
|
|
vid_nopageflip = Cvar_Get("vid_nopageflip", "0", CVAR_ARCHIVE, "None");
|
|
|
|
_vid_wait_override = Cvar_Get("_vid_wait_override", "0", CVAR_ARCHIVE, "None");
|
|
|
|
vid_config_x = Cvar_Get("vid_config_x", "800", CVAR_ARCHIVE, "None");
|
|
|
|
vid_config_y = Cvar_Get("vid_config_y", "600", CVAR_ARCHIVE, "None");
|
|
|
|
vid_stretch_by_2 = Cvar_Get("vid_stretch_by_2", "1", CVAR_ARCHIVE, "None");
|
|
|
|
_windowed_mouse = Cvar_Get("_windowed_mouse", "0", CVAR_ARCHIVE, "None");
|
|
|
|
gl_ztrick = Cvar_Get("gl_ztrick", "1", CVAR_NONE, "None");
|
|
|
|
|
|
|
|
Cmd_AddCommand ("vid_nummodes", VID_NumModes_f);
|
|
|
|
Cmd_AddCommand ("vid_describecurrentmode", VID_DescribeCurrentMode_f);
|
|
|
|
Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f);
|
|
|
|
Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f);
|
|
|
|
|
|
|
|
hIcon = LoadIcon (global_hInstance, MAKEINTRESOURCE (IDI_ICON2));
|
|
|
|
|
|
|
|
InitCommonControls();
|
|
|
|
|
|
|
|
VID_InitDIB (global_hInstance);
|
|
|
|
basenummodes = nummodes = 1;
|
|
|
|
|
|
|
|
VID_InitFullDIB (global_hInstance);
|
|
|
|
|
|
|
|
if (COM_CheckParm("-window"))
|
|
|
|
{
|
|
|
|
hdc = GetDC (NULL);
|
|
|
|
|
|
|
|
if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)
|
|
|
|
{
|
|
|
|
Sys_Error ("Can't run in non-RGB mode");
|
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseDC (NULL, hdc);
|
|
|
|
|
|
|
|
windowed = true;
|
|
|
|
|
|
|
|
vid_default = MODE_WINDOWED;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (nummodes == 1)
|
|
|
|
Sys_Error ("No RGB fullscreen modes available");
|
|
|
|
|
|
|
|
windowed = false;
|
|
|
|
|
|
|
|
if (COM_CheckParm("-mode"))
|
|
|
|
{
|
2000-05-21 11:32:35 +00:00
|
|
|
vid_default = atoi(com_argv[COM_CheckParm("-mode")+1]);
|
2000-05-19 08:29:11 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (COM_CheckParm("-current"))
|
|
|
|
{
|
|
|
|
modelist[MODE_FULLSCREEN_DEFAULT].width =
|
|
|
|
GetSystemMetrics (SM_CXSCREEN);
|
|
|
|
modelist[MODE_FULLSCREEN_DEFAULT].height =
|
|
|
|
GetSystemMetrics (SM_CYSCREEN);
|
|
|
|
vid_default = MODE_FULLSCREEN_DEFAULT;
|
|
|
|
leavecurrentmode = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (COM_CheckParm("-width"))
|
|
|
|
{
|
2000-05-21 11:32:35 +00:00
|
|
|
width = atoi(com_argv[COM_CheckParm("-width")+1]);
|
2000-05-19 08:29:11 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
width = 640;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (COM_CheckParm("-bpp"))
|
|
|
|
{
|
2000-05-21 11:32:35 +00:00
|
|
|
bpp = atoi(com_argv[COM_CheckParm("-bpp")+1]);
|
2000-05-19 08:29:11 +00:00
|
|
|
findbpp = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bpp = 15;
|
|
|
|
findbpp = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (COM_CheckParm("-height"))
|
2000-05-21 11:32:35 +00:00
|
|
|
height = atoi(com_argv[COM_CheckParm("-height")+1]);
|
2000-05-19 08:29:11 +00:00
|
|
|
|
|
|
|
// if they want to force it, add the specified mode to the list
|
|
|
|
if (COM_CheckParm("-force") && (nummodes < MAX_MODE_LIST))
|
|
|
|
{
|
|
|
|
modelist[nummodes].type = MS_FULLDIB;
|
|
|
|
modelist[nummodes].width = width;
|
|
|
|
modelist[nummodes].height = height;
|
|
|
|
modelist[nummodes].modenum = 0;
|
|
|
|
modelist[nummodes].halfscreen = 0;
|
|
|
|
modelist[nummodes].dib = 1;
|
|
|
|
modelist[nummodes].fullscreen = 1;
|
|
|
|
modelist[nummodes].bpp = bpp;
|
2000-05-20 08:23:41 +00:00
|
|
|
snprintf (modelist[nummodes].modedesc, sizeof(modelist[nummodes].modedesc), "%dx%dx%d",
|
2000-05-19 08:29:11 +00:00
|
|
|
devmode.dmPelsWidth, devmode.dmPelsHeight,
|
|
|
|
devmode.dmBitsPerPel);
|
|
|
|
|
|
|
|
for (i=nummodes, existingmode = 0 ; i<nummodes ; i++)
|
|
|
|
{
|
|
|
|
if ((modelist[nummodes].width == modelist[i].width) &&
|
|
|
|
(modelist[nummodes].height == modelist[i].height) &&
|
|
|
|
(modelist[nummodes].bpp == modelist[i].bpp))
|
|
|
|
{
|
|
|
|
existingmode = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!existingmode)
|
|
|
|
{
|
|
|
|
nummodes++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
done = 0;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
if (COM_CheckParm("-height"))
|
|
|
|
{
|
2000-05-21 11:32:35 +00:00
|
|
|
height = atoi(com_argv[COM_CheckParm("-height")+1]);
|
2000-05-19 08:29:11 +00:00
|
|
|
|
|
|
|
for (i=1, vid_default=0 ; i<nummodes ; i++)
|
|
|
|
{
|
|
|
|
if ((modelist[i].width == width) &&
|
|
|
|
(modelist[i].height == height) &&
|
|
|
|
(modelist[i].bpp == bpp))
|
|
|
|
{
|
|
|
|
vid_default = i;
|
|
|
|
done = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (i=1, vid_default=0 ; i<nummodes ; i++)
|
|
|
|
{
|
|
|
|
if ((modelist[i].width == width) && (modelist[i].bpp == bpp))
|
|
|
|
{
|
|
|
|
vid_default = i;
|
|
|
|
done = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!done)
|
|
|
|
{
|
|
|
|
if (findbpp)
|
|
|
|
{
|
|
|
|
switch (bpp)
|
|
|
|
{
|
|
|
|
case 15:
|
|
|
|
bpp = 16;
|
|
|
|
break;
|
|
|
|
case 16:
|
|
|
|
bpp = 32;
|
|
|
|
break;
|
|
|
|
case 32:
|
|
|
|
bpp = 24;
|
|
|
|
break;
|
|
|
|
case 24:
|
|
|
|
done = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
done = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} while (!done);
|
|
|
|
|
|
|
|
if (!vid_default)
|
|
|
|
{
|
|
|
|
Sys_Error ("Specified video mode not available");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
vid_initialized = true;
|
|
|
|
|
|
|
|
if ((i = COM_CheckParm("-conwidth")) != 0)
|
2000-05-21 11:32:35 +00:00
|
|
|
vid.conwidth = atoi(com_argv[i+1]);
|
2000-05-19 08:29:11 +00:00
|
|
|
else
|
|
|
|
vid.conwidth = 640;
|
|
|
|
|
|
|
|
vid.conwidth &= 0xfff8; // make it a multiple of eight
|
|
|
|
|
|
|
|
if (vid.conwidth < 320)
|
|
|
|
vid.conwidth = 320;
|
|
|
|
|
|
|
|
// pick a conheight that matches with correct aspect
|
|
|
|
vid.conheight = vid.conwidth*3 / 4;
|
|
|
|
|
|
|
|
if ((i = COM_CheckParm("-conheight")) != 0)
|
2000-05-21 11:32:35 +00:00
|
|
|
vid.conheight = atoi(com_argv[i+1]);
|
2000-05-19 08:29:11 +00:00
|
|
|
if (vid.conheight < 200)
|
|
|
|
vid.conheight = 200;
|
|
|
|
|
|
|
|
vid.maxwarpwidth = WARP_WIDTH;
|
|
|
|
vid.maxwarpheight = WARP_HEIGHT;
|
|
|
|
vid.colormap = host_colormap;
|
|
|
|
vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
|
|
|
|
|
|
|
|
DestroyWindow (hwnd_dialog);
|
|
|
|
|
2000-05-31 17:46:59 +00:00
|
|
|
GL_CheckGamma(palette);
|
2000-05-19 08:29:11 +00:00
|
|
|
VID_SetPalette (palette);
|
|
|
|
|
|
|
|
VID_SetMode (vid_default, palette);
|
|
|
|
|
|
|
|
maindc = GetDC(mainwindow);
|
|
|
|
bSetupPixelFormat(maindc);
|
|
|
|
|
|
|
|
baseRC = wglCreateContext( maindc );
|
|
|
|
if (!baseRC)
|
|
|
|
Sys_Error ("Could not initialize GL (wglCreateContext failed).\n\nMake sure you in are 65535 color mode, and try running -window.");
|
|
|
|
if (!wglMakeCurrent( maindc, baseRC ))
|
|
|
|
Sys_Error ("wglMakeCurrent failed");
|
|
|
|
|
|
|
|
GL_Init ();
|
|
|
|
|
|
|
|
snprintf (gldir, sizeof(gldir), "%s/glquake", com_gamedir);
|
|
|
|
Sys_mkdir (gldir);
|
|
|
|
|
|
|
|
vid_realmode = vid_modenum;
|
|
|
|
|
|
|
|
// Check for 3DFX Extensions and initialize them.
|
|
|
|
VID_Init8bitPalette();
|
|
|
|
|
|
|
|
vid_menudrawfn = VID_MenuDraw;
|
|
|
|
vid_menukeyfn = VID_MenuKey;
|
|
|
|
|
|
|
|
strcpy (badmode.modedesc, "Bad mode");
|
|
|
|
vid_canalttab = true;
|
|
|
|
|
|
|
|
if (COM_CheckParm("-fullsbar"))
|
|
|
|
fullsbardraw = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//========================================================
|
|
|
|
// Video menu stuff
|
|
|
|
//========================================================
|
|
|
|
|
|
|
|
extern void M_Menu_Options_f (void);
|
|
|
|
extern void M_Print (int cx, int cy, char *str);
|
|
|
|
extern void M_PrintWhite (int cx, int cy, char *str);
|
|
|
|
extern void M_DrawCharacter (int cx, int line, int num);
|
|
|
|
extern void M_DrawTransPic (int x, int y, qpic_t *pic);
|
|
|
|
extern void M_DrawPic (int x, int y, qpic_t *pic);
|
|
|
|
|
|
|
|
static int vid_line, vid_wmodes;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
int modenum;
|
|
|
|
char *desc;
|
|
|
|
int iscur;
|
|
|
|
} modedesc_t;
|
|
|
|
|
|
|
|
#define MAX_COLUMN_SIZE 9
|
|
|
|
#define MODE_AREA_HEIGHT (MAX_COLUMN_SIZE + 2)
|
|
|
|
#define MAX_MODEDESCS (MAX_COLUMN_SIZE*3)
|
|
|
|
|
|
|
|
static modedesc_t modedescs[MAX_MODEDESCS];
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
VID_MenuDraw
|
|
|
|
================
|
|
|
|
*/
|
|
|
|
void VID_MenuDraw (void)
|
|
|
|
{
|
|
|
|
qpic_t *p;
|
|
|
|
char *ptr;
|
|
|
|
int lnummodes, i, j, k, column, row, dup, dupmode;
|
|
|
|
char temp[100];
|
|
|
|
vmode_t *pv;
|
|
|
|
|
|
|
|
p = Draw_CachePic ("gfx/vidmodes.lmp");
|
|
|
|
M_DrawPic ( (320-p->width)/2, 4, p);
|
|
|
|
|
|
|
|
vid_wmodes = 0;
|
|
|
|
lnummodes = VID_NumModes ();
|
|
|
|
|
|
|
|
for (i=1 ; (i<lnummodes) && (vid_wmodes < MAX_MODEDESCS) ; i++)
|
|
|
|
{
|
|
|
|
ptr = VID_GetModeDescription (i);
|
|
|
|
pv = VID_GetModePtr (i);
|
|
|
|
|
|
|
|
k = vid_wmodes;
|
|
|
|
|
|
|
|
modedescs[k].modenum = i;
|
|
|
|
modedescs[k].desc = ptr;
|
|
|
|
modedescs[k].iscur = 0;
|
|
|
|
|
|
|
|
if (i == vid_modenum)
|
|
|
|
modedescs[k].iscur = 1;
|
|
|
|
|
|
|
|
vid_wmodes++;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vid_wmodes > 0)
|
|
|
|
{
|
|
|
|
M_Print (2*8, 36+0*8, "Fullscreen Modes (WIDTHxHEIGHTxBPP)");
|
|
|
|
|
|
|
|
column = 8;
|
|
|
|
row = 36+2*8;
|
|
|
|
|
|
|
|
for (i=0 ; i<vid_wmodes ; i++)
|
|
|
|
{
|
|
|
|
if (modedescs[i].iscur)
|
|
|
|
M_PrintWhite (column, row, modedescs[i].desc);
|
|
|
|
else
|
|
|
|
M_Print (column, row, modedescs[i].desc);
|
|
|
|
|
|
|
|
column += 13*8;
|
|
|
|
|
|
|
|
if ((i % VID_ROW_SIZE) == (VID_ROW_SIZE - 1))
|
|
|
|
{
|
|
|
|
column = 8;
|
|
|
|
row += 8;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*2,
|
|
|
|
"Video modes must be set from the");
|
|
|
|
M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*3,
|
|
|
|
"command line with -width <width>");
|
|
|
|
M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*4,
|
|
|
|
"and -bpp <bits-per-pixel>");
|
|
|
|
M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*6,
|
|
|
|
"Select windowed mode with -window");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
VID_MenuKey
|
|
|
|
================
|
|
|
|
*/
|
|
|
|
void VID_MenuKey (int key)
|
|
|
|
{
|
|
|
|
switch (key)
|
|
|
|
{
|
|
|
|
case K_ESCAPE:
|
|
|
|
S_LocalSound ("misc/menu1.wav");
|
|
|
|
M_Menu_Options_f ();
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|