diff options
| author | wyatt8740 <wyatt8740@yahoo.com> | 2014-01-06 12:02:16 -0500 |
|---|---|---|
| committer | wyatt8740 <wyatt8740@yahoo.com> | 2014-01-06 12:02:16 -0500 |
| commit | a8f828a066773a59fdf646299359d35ae0e845af (patch) | |
| tree | 86123409fc6f231cf4136e81159b63cb1e9ec102 /WinQuake/vid_win.c | |
| parent | b2951690415054ae8705c07f8df7a4ba7cde382a (diff) | |
| download | quake-pum-a8f828a066773a59fdf646299359d35ae0e845af.tar.gz | |
Removed accidental upload of copyrighted map files
Diffstat (limited to 'WinQuake/vid_win.c')
| -rw-r--r-- | WinQuake/vid_win.c | 6686 |
1 files changed, 3343 insertions, 3343 deletions
diff --git a/WinQuake/vid_win.c b/WinQuake/vid_win.c index db90689..6347669 100644 --- a/WinQuake/vid_win.c +++ b/WinQuake/vid_win.c @@ -1,3343 +1,3343 @@ -/* -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 the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// vid_win.c -- Win32 video driver - -#include "quakedef.h" -#include "winquake.h" -#include "d_local.h" -#include "resource.h" - -#define MAX_MODE_LIST 30 -#define VID_ROW_SIZE 3 - -qboolean dibonly; - -extern int Minimized; - -HWND mainwindow; - -HWND WINAPI InitializeWindow (HINSTANCE hInstance, int nCmdShow); - -int DIBWidth, DIBHeight; -qboolean DDActive; -RECT WindowRect; -DWORD WindowStyle, ExWindowStyle; - -int window_center_x, window_center_y, window_x, window_y, window_width, window_height; -RECT window_rect; - -static DEVMODE gdevmode; -static qboolean startwindowed = 0, windowed_mode_set; -static int firstupdate = 1; -static qboolean vid_initialized = false, vid_palettized; -static int lockcount; -static int vid_fulldib_on_focus_mode; -static qboolean force_minimized, in_mode_set, is_mode0x13, force_mode_set; -static int vid_stretched, windowed_mouse; -static qboolean palette_changed, syscolchg, vid_mode_set, hide_window, pal_is_nostatic; -static HICON hIcon; - -viddef_t vid; // global video state - -#define MODE_WINDOWED 0 -#define MODE_SETTABLE_WINDOW 2 -#define NO_MODE (MODE_WINDOWED - 1) -#define MODE_FULLSCREEN_DEFAULT (MODE_WINDOWED + 3) - -// Note that 0 is MODE_WINDOWED -cvar_t vid_mode = {"vid_mode","0", false}; -// Note that 0 is MODE_WINDOWED -cvar_t _vid_default_mode = {"_vid_default_mode","0", true}; -// Note that 3 is MODE_FULLSCREEN_DEFAULT -cvar_t _vid_default_mode_win = {"_vid_default_mode_win","3", true}; -cvar_t vid_wait = {"vid_wait","0"}; -cvar_t vid_nopageflip = {"vid_nopageflip","0", true}; -cvar_t _vid_wait_override = {"_vid_wait_override", "0", true}; -cvar_t vid_config_x = {"vid_config_x","800", true}; -cvar_t vid_config_y = {"vid_config_y","600", true}; -cvar_t vid_stretch_by_2 = {"vid_stretch_by_2","1", true}; -cvar_t _windowed_mouse = {"_windowed_mouse","0", true}; -cvar_t vid_fullscreen_mode = {"vid_fullscreen_mode","3", true}; -cvar_t vid_windowed_mode = {"vid_windowed_mode","0", true}; -cvar_t block_switch = {"block_switch","0", true}; -cvar_t vid_window_x = {"vid_window_x", "0", true}; -cvar_t vid_window_y = {"vid_window_y", "0", true}; - -typedef struct { - int width; - int height; -} lmode_t; - -lmode_t lowresmodes[] = { - {320, 200}, - {320, 240}, - {400, 300}, - {512, 384}, -}; - -int vid_modenum = NO_MODE; -int vid_testingmode, vid_realmode; -double vid_testendtime; -int vid_default = MODE_WINDOWED; -static int windowed_default; - -modestate_t modestate = MS_UNINIT; - -static byte *vid_surfcache; -static int vid_surfcachesize; -static int VID_highhunkmark; - -unsigned char vid_curpal[256*3]; - -unsigned short d_8to16table[256]; -unsigned d_8to24table[256]; - -int driver = grDETECT,mode; -bool useWinDirect = true, useDirectDraw = true; -MGLDC *mgldc = NULL,*memdc = NULL,*dibdc = NULL,*windc = NULL; - -typedef struct { - modestate_t type; - int width; - int height; - int modenum; - int mode13; - int stretched; - int dib; - int fullscreen; - int bpp; - int halfscreen; - char modedesc[13]; -} vmode_t; - -static vmode_t modelist[MAX_MODE_LIST]; -static int nummodes; -static vmode_t *pcurrentmode; - -int aPage; // Current active display page -int vPage; // Current visible display page -int waitVRT = true; // True to wait for retrace on flip - -static vmode_t badmode; - -static byte backingbuf[48*24]; - -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); - - -/* -================ -VID_RememberWindowPos -================ -*/ -void VID_RememberWindowPos (void) -{ - RECT rect; - - if (GetWindowRect (mainwindow, &rect)) - { - if ((rect.left < GetSystemMetrics (SM_CXSCREEN)) && - (rect.top < GetSystemMetrics (SM_CYSCREEN)) && - (rect.right > 0) && - (rect.bottom > 0)) - { - Cvar_SetValue ("vid_window_x", (float)rect.left); - Cvar_SetValue ("vid_window_y", (float)rect.top); - } - } -} - - -/* -================ -VID_CheckWindowXY -================ -*/ -void VID_CheckWindowXY (void) -{ - - if (((int)vid_window_x.value > (GetSystemMetrics (SM_CXSCREEN) - 160)) || - ((int)vid_window_y.value > (GetSystemMetrics (SM_CYSCREEN) - 120)) || - ((int)vid_window_x.value < 0) || - ((int)vid_window_y.value < 0)) - { - Cvar_SetValue ("vid_window_x", 0.0); - Cvar_SetValue ("vid_window_y", 0.0 ); - } -} - - -/* -================ -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 (); -} - - -/* -================ -ClearAllStates -================ -*/ -void ClearAllStates (void) -{ - int i; - -// send an up event for each key, to make sure the server clears them all - for (i=0 ; i<256 ; i++) - { - Key_Event (i, false); - } - - Key_ClearStates (); - IN_ClearStates (); -} - - -/* -================ -VID_CheckAdequateMem -================ -*/ -qboolean VID_CheckAdequateMem (int width, int height) -{ - int tbuffersize; - - tbuffersize = width * height * sizeof (*d_pzbuffer); - - tbuffersize += D_SurfaceCacheForRes (width, height); - -// see if there's enough memory, allowing for the normal mode 0x13 pixel, -// z, and surface buffers - if ((host_parms.memsize - tbuffersize + SURFCACHE_SIZE_AT_320X200 + - 0x10000 * 3) < minimum_memory) - { - return false; // not enough memory for mode - } - - return true; -} - - -/* -================ -VID_AllocBuffers -================ -*/ -qboolean VID_AllocBuffers (int width, int height) -{ - int tsize, tbuffersize; - - tbuffersize = width * height * sizeof (*d_pzbuffer); - - tsize = D_SurfaceCacheForRes (width, height); - - tbuffersize += tsize; - -// see if there's enough memory, allowing for the normal mode 0x13 pixel, -// z, and surface buffers - if ((host_parms.memsize - tbuffersize + SURFCACHE_SIZE_AT_320X200 + - 0x10000 * 3) < minimum_memory) - { - Con_SafePrintf ("Not enough memory for video mode\n"); - return false; // not enough memory for mode - } - - vid_surfcachesize = tsize; - - if (d_pzbuffer) - { - D_FlushCaches (); - Hunk_FreeToHighMark (VID_highhunkmark); - d_pzbuffer = NULL; - } - - VID_highhunkmark = Hunk_HighMark (); - - d_pzbuffer = Hunk_HighAllocName (tbuffersize, "video"); - - vid_surfcache = (byte *)d_pzbuffer + - width * height * sizeof (*d_pzbuffer); - - return true; -} - - -void initFatalError(void) -{ - MGL_exit(); - MGL_fatalError(MGL_errorMsg(MGL_result())); - exit(EXIT_FAILURE); -} - - -int VID_Suspend (MGLDC *dc,m_int flags) -{ - - if (flags & MGL_DEACTIVATE) - { - // FIXME: this doesn't currently work on NT - if (block_switch.value && !WinNT) - { - return MGL_NO_DEACTIVATE; - } - - S_BlockSound (); - S_ClearBuffer (); - - IN_RestoreOriginalMouseState (); - CDAudio_Pause (); - - // keep WM_PAINT from trying to redraw - in_mode_set = true; - - block_drawing = true; // so we don't try to draw while switched away - - return MGL_NO_SUSPEND_APP; - } - else if (flags & MGL_REACTIVATE) - { - IN_SetQuakeMouseState (); - // fix the leftover Alt from any Alt-Tab or the like that switched us away - ClearAllStates (); - CDAudio_Resume (); - S_UnblockSound (); - - in_mode_set = false; - - vid.recalc_refdef = 1; - - block_drawing = false; - - return MGL_NO_SUSPEND_APP; - } - -} - - -void registerAllDispDrivers(void) -{ - /* Event though these driver require WinDirect, we register - * them so that they will still be available even if DirectDraw - * is present and the user has disable the high performance - * WinDirect modes. - */ - MGL_registerDriver(MGL_VGA8NAME,VGA8_driver); -// MGL_registerDriver(MGL_VGAXNAME,VGAX_driver); - - /* Register display drivers */ - if (useWinDirect) - { -//we don't want VESA 1.X drivers MGL_registerDriver(MGL_SVGA8NAME,SVGA8_driver); - MGL_registerDriver(MGL_LINEAR8NAME,LINEAR8_driver); - - if (!COM_CheckParm ("-novbeaf")) - MGL_registerDriver(MGL_ACCEL8NAME,ACCEL8_driver); - } - - if (useDirectDraw) - { - MGL_registerDriver(MGL_DDRAW8NAME,DDRAW8_driver); - } -} - - -void registerAllMemDrivers(void) -{ - /* Register memory context drivers */ - MGL_registerDriver(MGL_PACKED8NAME,PACKED8_driver); -} - - -void VID_InitMGLFull (HINSTANCE hInstance) -{ - int i, xRes, yRes, bits, vMode, lowres, curmode, temp; - int lowstretchedres, stretchedmode, lowstretched; - uchar *m; - -// FIXME: NT is checked for because MGL currently has a bug that causes it -// to try to use WinDirect modes even on NT - if (COM_CheckParm("-nowindirect") || - COM_CheckParm("-nowd") || - COM_CheckParm("-novesa") || - WinNT) - { - useWinDirect = false; - } - - if (COM_CheckParm("-nodirectdraw") || COM_CheckParm("-noddraw") || COM_CheckParm("-nodd")) - useDirectDraw = false; - - // Initialise the MGL - MGL_unregisterAllDrivers(); - registerAllDispDrivers(); - registerAllMemDrivers(); - MGL_detectGraph(&driver,&mode); - m = MGL_availableModes(); - - if (m[0] != 0xFF) - { - lowres = lowstretchedres = 99999; - lowstretched = 0; - curmode = 0; - - // find the lowest-res mode, or a mode we can stretch up to and get - // lowest-res that way - for (i = 0; m[i] != 0xFF; i++) - { - MGL_modeResolution(m[i], &xRes, &yRes,&bits); - - if ((bits == 8) && - (xRes <= MAXWIDTH) && - (yRes <= MAXHEIGHT) && - (curmode < MAX_MODE_LIST)) - { - if (m[i] == grVGA_320x200x256) - is_mode0x13 = true; - - if (!COM_CheckParm("-noforcevga")) - { - if (m[i] == grVGA_320x200x256) - { - mode = i; - break; - } - } - - if (xRes < lowres) - { - lowres = xRes; - mode = i; - } - - if ((xRes < lowstretchedres) && ((xRes >> 1) >= 320)) - { - lowstretchedres = xRes >> 1; - stretchedmode = i; - } - } - - curmode++; - } - - // if there's a mode we can stretch by 2 up to, thereby effectively getting - // a lower-res mode than the lowest-res real but still at least 320x200, that - // will be our default mode - if (lowstretchedres < lowres) - { - mode = stretchedmode; - lowres = lowstretchedres; - lowstretched = 1; - } - - // build the mode list, leaving room for the low-res stretched mode, if any - nummodes++; // leave room for default mode - - for (i = 0; m[i] != 0xFF; i++) - { - MGL_modeResolution(m[i], &xRes, &yRes,&bits); - - if ((bits == 8) && - (xRes <= MAXWIDTH) && - (yRes <= MAXHEIGHT) && - (nummodes < MAX_MODE_LIST)) - { - if (i == mode) - { - if (lowstretched) - { - stretchedmode = nummodes; - curmode = nummodes++; - } - else - { - curmode = MODE_FULLSCREEN_DEFAULT; - } - } - else - { - curmode = nummodes++; - } - - modelist[curmode].type = MS_FULLSCREEN; - modelist[curmode].width = xRes; - modelist[curmode].height = yRes; - sprintf (modelist[curmode].modedesc, "%dx%d", xRes, yRes); - - if (m[i] == grVGA_320x200x256) - modelist[curmode].mode13 = 1; - else - modelist[curmode].mode13 = 0; - - modelist[curmode].modenum = m[i]; - modelist[curmode].stretched = 0; - modelist[curmode].dib = 0; - modelist[curmode].fullscreen = 1; - modelist[curmode].halfscreen = 0; - modelist[curmode].bpp = 8; - } - } - - if (lowstretched) - { - modelist[MODE_FULLSCREEN_DEFAULT] = modelist[stretchedmode]; - modelist[MODE_FULLSCREEN_DEFAULT].stretched = 1; - modelist[MODE_FULLSCREEN_DEFAULT].width >>= 1; - modelist[MODE_FULLSCREEN_DEFAULT].height >>= 1; - sprintf (modelist[MODE_FULLSCREEN_DEFAULT].modedesc, "%dx%d", - modelist[MODE_FULLSCREEN_DEFAULT].width, - modelist[MODE_FULLSCREEN_DEFAULT].height); - } - - vid_default = MODE_FULLSCREEN_DEFAULT; - - temp = m[0]; - - if (!MGL_init(&driver, &temp, "")) - { - initFatalError(); - } - } - - MGL_setSuspendAppCallback(VID_Suspend); -} - - -MGLDC *createDisplayDC(int forcemem) -/**************************************************************************** -* -* Function: createDisplayDC -* Returns: Pointer to the MGL device context to use for the application -* -* Description: Initialises the MGL and creates an appropriate display -* device context to be used by the GUI. This creates and -* apropriate device context depending on the system being -* compile for, and should be the only place where system -* specific code is required. -* -****************************************************************************/ -{ - MGLDC *dc; - pixel_format_t pf; - int npages; - - // Start the specified video mode - if (!MGL_changeDisplayMode(mode)) - initFatalError(); - - npages = MGL_availablePages(mode); - - if (npages > 3) - npages = 3; - - if (!COM_CheckParm ("-notriplebuf")) - { - if (npages > 2) - { - npages = 2; - } - } - - if ((dc = MGL_createDisplayDC(npages)) == NULL) - return NULL; - - if (!forcemem && (MGL_surfaceAccessType(dc)) == MGL_LINEAR_ACCESS && (dc->mi.maxPage > 0)) - { - MGL_makeCurrentDC(dc); - memdc = NULL; - } - else - { - // Set up for blitting from a memory buffer - memdc = MGL_createMemoryDC(MGL_sizex(dc)+1,MGL_sizey(dc)+1,8,&pf); - MGL_makeCurrentDC(memdc); - } - - // Enable page flipping even for even for blitted surfaces - if (forcemem) - { - vid.numpages = 1; - } - else - { - vid.numpages = dc->mi.maxPage + 1; - - if (vid.numpages > 1) - { - // Set up for page flipping - MGL_setActivePage(dc, aPage = 1); - MGL_setVisualPage(dc, vPage = 0, false); - } - - if (vid.numpages > 3) - vid.numpages = 3; - } - - if (vid.numpages == 2) - waitVRT = true; - else - waitVRT = false; - - return dc; -} - - -void VID_InitMGLDIB (HINSTANCE hInstance) -{ - WNDCLASS wc; - HDC hdc; - int i; - - hIcon = LoadIcon (hInstance, MAKEINTRESOURCE (IDI_ICON2)); - - /* 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"); - - /* Find the size for the DIB window */ - /* Initialise the MGL for windowed operation */ - MGL_setAppInstance(hInstance); - registerAllMemDrivers(); - MGL_initWindowed(""); - - modelist[0].type = MS_WINDOWED; - modelist[0].width = 320; - modelist[0].height = 240; - strcpy (modelist[0].modedesc, "320x240"); - modelist[0].mode13 = 0; - modelist[0].modenum = MODE_WINDOWED; - modelist[0].stretched = 0; - modelist[0].dib = 1; - modelist[0].fullscreen = 0; - modelist[0].halfscreen = 0; - modelist[0].bpp = 8; - - modelist[1].type = MS_WINDOWED; - modelist[1].width = 640; - modelist[1].height = 480; - strcpy (modelist[1].modedesc, "640x480"); - modelist[1].mode13 = 0; - modelist[1].modenum = MODE_WINDOWED + 1; - modelist[1].stretched = 1; - modelist[1].dib = 1; - modelist[1].fullscreen = 0; - modelist[1].halfscreen = 0; - modelist[1].bpp = 8; - - modelist[2].type = MS_WINDOWED; - modelist[2].width = 800; - modelist[2].height = 600; - strcpy (modelist[2].modedesc, "800x600"); - modelist[2].mode13 = 0; - modelist[2].modenum = MODE_WINDOWED + 2; - modelist[2].stretched = 1; - modelist[2].dib = 1; - modelist[2].fullscreen = 0; - modelist[2].halfscreen = 0; - modelist[2].bpp = 8; - -// automatically stretch the default mode up if > 640x480 desktop resolution - hdc = GetDC(NULL); - - if ((GetDeviceCaps(hdc, HORZRES) > 640) && !COM_CheckParm("-noautostretch")) - { - vid_default = MODE_WINDOWED + 1; - } - else - { - vid_default = MODE_WINDOWED; - } - - windowed_default = vid_default; - - ReleaseDC(NULL,hdc); - - nummodes = 3; // reserve space for windowed mode - - DDActive = 0; -} - - -/* -================= -VID_InitFullDIB -================= -*/ -void VID_InitFullDIB (HINSTANCE hInstance) -{ - DEVMODE devmode; - int i, j, modenum, cmodes, existingmode, originalnummodes, lowestres; - int numlowresmodes, bpp, done; - int cstretch, istretch, mstretch; - BOOL stat; - -// enumerate 8 bpp modes - originalnummodes = nummodes; - modenum = 0; - lowestres = 99999; - - do - { - stat = EnumDisplaySettings (NULL, modenum, &devmode); - - if ((devmode.dmBitsPerPel == 8) && - (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].mode13 = 0; - modelist[nummodes].stretched = 0; - modelist[nummodes].halfscreen = 0; - modelist[nummodes].dib = 1; - modelist[nummodes].fullscreen = 1; - modelist[nummodes].bpp = devmode.dmBitsPerPel; - sprintf (modelist[nummodes].modedesc, "%dx%d", - devmode.dmPelsWidth, devmode.dmPelsHeight); - - // 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; - sprintf (modelist[nummodes].modedesc, "%dx%d", - modelist[nummodes].width, - modelist[nummodes].height); - } - } - - for (i=originalnummodes, existingmode = 0 ; i<nummodes ; i++) - { - if ((modelist[nummodes].width == modelist[i].width) && - (modelist[nummodes].height == modelist[i].height)) - { - existingmode = 1; - break; - } - } - - if (!existingmode) - { - if (modelist[nummodes].width < lowestres) - lowestres = modelist[nummodes].width; - - nummodes++; - } - } - } - - modenum++; - } while (stat); - -// see if any of them were actually settable; if so, this is our mode list, -// else enumerate all modes; our mode list is whichever ones are settable -// with > 8 bpp - if (nummodes == originalnummodes) - { - modenum = 0; - lowestres = 99999; - - Con_SafePrintf ("No 8-bpp fullscreen DIB modes found\n"); - - do - { - stat = EnumDisplaySettings (NULL, modenum, &devmode); - - if ((((devmode.dmPelsWidth <= MAXWIDTH) && - (devmode.dmPelsHeight <= MAXHEIGHT)) || - (!COM_CheckParm("-noadjustaspect") && - (devmode.dmPelsWidth <= (MAXWIDTH*2)) && - (devmode.dmPelsWidth > (devmode.dmPelsHeight*2)))) && - (nummodes < MAX_MODE_LIST) && - (devmode.dmBitsPerPel > 8)) - { - 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].mode13 = 0; - modelist[nummodes].stretched = 0; - modelist[nummodes].halfscreen = 0; - modelist[nummodes].dib = 1; - modelist[nummodes].fullscreen = 1; - modelist[nummodes].bpp = devmode.dmBitsPerPel; - sprintf (modelist[nummodes].modedesc, "%dx%d", - devmode.dmPelsWidth, devmode.dmPelsHeight); - - // 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*2)) - { - modelist[nummodes].width >>= 1; - modelist[nummodes].halfscreen = 1; - sprintf (modelist[nummodes].modedesc, "%dx%d", - modelist[nummodes].width, - modelist[nummodes].height); - } - } - - for (i=originalnummodes, existingmode = 0 ; i<nummodes ; i++) - { - if ((modelist[nummodes].width == modelist[i].width) && - (modelist[nummodes].height == modelist[i].height)) - { - // pick the lowest available bpp - if (modelist[nummodes].bpp < modelist[i].bpp) - modelist[i] = modelist[nummodes]; - - existingmode = 1; - break; - } - } - - if (!existingmode) - { - if (modelist[nummodes].width < lowestres) - lowestres = modelist[nummodes].width; - - nummodes++; - } - } - } - - modenum++; - } while (stat); - } - -// see if there are any low-res modes that aren't being reported - numlowresmodes = sizeof(lowresmodes) / sizeof(lowresmodes[0]); - bpp = 8; - done = 0; - -// first make sure the driver doesn't just answer yes to all tests - devmode.dmBitsPerPel = 8; - devmode.dmPelsWidth = 42; - devmode.dmPelsHeight = 37; - devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; - - if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) == - DISP_CHANGE_SUCCESSFUL) - { - done = 1; - } - - while (!done) - { - 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].mode13 = 0; - modelist[nummodes].stretched = 0; - modelist[nummodes].halfscreen = 0; - modelist[nummodes].dib = 1; - modelist[nummodes].fullscreen = 1; - modelist[nummodes].bpp = devmode.dmBitsPerPel; - sprintf (modelist[nummodes].modedesc, "%dx%d", - devmode.dmPelsWidth, devmode.dmPelsHeight); - - // we only want the lowest-bpp version of each mode - 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) - { - if (modelist[nummodes].width < lowestres) - lowestres = modelist[nummodes].width; - - nummodes++; - } - } - } - - switch (bpp) - { - case 8: - bpp = 16; - break; - - case 16: - bpp = 32; - break; - - case 32: - done = 1; - break; - } - } - -// now add the lowest stretch-by-2 pseudo-modes between 320-wide -// (inclusive) and lowest real res (not inclusive) -// don't bother if we have a real VGA mode 0x13 mode - if (!is_mode0x13) - { - for (i=originalnummodes, cstretch=0 ; i<nummodes ; i++) - { - if (((modelist[i].width >> 1) < lowestres) && - ((modelist[i].width >> 1) >= 320)) - { - lowestres = modelist[i].width >> 1; - cstretch = 1; - mstretch = i; - } - } - - if ((nummodes + cstretch) > MAX_MODE_LIST) - cstretch = MAX_MODE_LIST - nummodes; - - if (cstretch > 0) - { - for (i=(nummodes-1) ; i>=originalnummodes ; i--) - modelist[i+cstretch] = modelist[i]; - - nummodes += cstretch; - istretch = originalnummodes; - - modelist[istretch] = modelist[mstretch]; - modelist[istretch].width >>= 1; - modelist[istretch].height >>= 1; - modelist[istretch].stretched = 1; - sprintf (modelist[istretch].modedesc, "%dx%d", - modelist[istretch].width, modelist[istretch].height); - } - } - - if (nummodes != originalnummodes) - vid_default = MODE_FULLSCREEN_DEFAULT; - else - Con_SafePrintf ("No fullscreen DIB modes found\n"); -} - - -/* -================= -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_CheckModedescFixup -================= -*/ -void VID_CheckModedescFixup (int mode) -{ - int x, y, stretch; - - if (mode == MODE_SETTABLE_WINDOW) - { - modelist[mode].stretched = (int)vid_stretch_by_2.value; - stretch = modelist[mode].stretched; - - if (vid_config_x.value < (320 << stretch)) - vid_config_x.value = 320 << stretch; - - if (vid_config_y.value < (200 << stretch)) - vid_config_y.value = 200 << stretch; - - x = (int)vid_config_x.value; - y = (int)vid_config_y.value; - sprintf (modelist[mode].modedesc, "%dx%d", x, y); - modelist[mode].width = x; - modelist[mode].height = y; - } -} - - -/* -================= -VID_GetModeDescriptionMemCheck -================= -*/ -char *VID_GetModeDescriptionMemCheck (int mode) -{ - char *pinfo; - vmode_t *pv; - - if ((mode < 0) || (mode >= nummodes)) - return NULL; - - VID_CheckModedescFixup (mode); - - pv = VID_GetModePtr (mode); - pinfo = pv->modedesc; - - if (VID_CheckAdequateMem (pv->width, pv->height)) - { - return pinfo; - } - else - { - return NULL; - } -} - - -/* -================= -VID_GetModeDescription -================= -*/ -char *VID_GetModeDescription (int mode) -{ - char *pinfo; - vmode_t *pv; - - if ((mode < 0) || (mode >= nummodes)) - return NULL; - - VID_CheckModedescFixup (mode); - - pv = VID_GetModePtr (mode); - pinfo = pv->modedesc; - return pinfo; -} - - -/* -================= -VID_GetModeDescription2 - -Tacks on "windowed" or "fullscreen" -================= -*/ -char *VID_GetModeDescription2 (int mode) -{ - static char pinfo[40]; - vmode_t *pv; - - if ((mode < 0) || (mode >= nummodes)) - return NULL; - - VID_CheckModedescFixup (mode); - - pv = VID_GetModePtr (mode); - - if (modelist[mode].type == MS_FULLSCREEN) - { - sprintf(pinfo,"%s fullscreen", pv->modedesc); - } - else if (modelist[mode].type == MS_FULLDIB) - { - sprintf(pinfo,"%s fullscreen", pv->modedesc); - } - else - { - sprintf(pinfo, "%s windowed", pv->modedesc); - } - - 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; - - VID_CheckModedescFixup (mode); - - pv = VID_GetModePtr (mode); - if (modelist[mode].type == MS_FULLSCREEN) - { - sprintf(pinfo,"%s fullscreen %s",pv->modedesc, - MGL_modeDriverName(pv->modenum)); - } - else if (modelist[mode].type == MS_FULLDIB) - { - sprintf(pinfo,"%s fullscreen DIB", pv->modedesc); - } - else - { - sprintf(pinfo, "%s windowed", pv->modedesc); - } - - return pinfo; -} - - -void DestroyDIBWindow (void) -{ - - if (modestate == MS_WINDOWED) - { - // destroy the associated MGL DC's; the window gets reused - if (windc) - MGL_destroyDC(windc); - if (dibdc) - MGL_destroyDC(dibdc); - windc = dibdc = NULL; - } -} - - -void DestroyFullscreenWindow (void) -{ - - if (modestate == MS_FULLSCREEN) - { - // destroy the existing fullscreen mode and DC's - if (mgldc) - MGL_destroyDC (mgldc); - if (memdc) - MGL_destroyDC (memdc); - mgldc = memdc = NULL; - } -} - - - -void DestroyFullDIBWindow (void) -{ - if (modestate == MS_FULLDIB) - { - ChangeDisplaySettings (NULL, CDS_FULLSCREEN); - - // Destroy the fullscreen DIB window and associated MGL DC's - if (windc) - MGL_destroyDC(windc); - if (dibdc) - MGL_destroyDC(dibdc); - windc = dibdc = NULL; - } -} - - -qboolean VID_SetWindowedMode (int modenum) -{ - HDC hdc; - pixel_format_t pf; - qboolean stretched; - int lastmodestate; - LONG wlong; - - if (!windowed_mode_set) - { - if (COM_CheckParm ("-resetwinpos")) - { - Cvar_SetValue ("vid_window_x", 0.0); - Cvar_SetValue ("vid_window_y", 0.0); - } - - windowed_mode_set; - } - - VID_CheckModedescFixup (modenum); - - DDActive = 0; - lastmodestate = modestate; - - DestroyFullscreenWindow (); - DestroyFullDIBWindow (); - - if (windc) - MGL_destroyDC(windc); - if (dibdc) - MGL_destroyDC(dibdc); - windc = dibdc = NULL; - -// KJB: Signal to the MGL that we are going back to windowed mode - if (!MGL_changeDisplayMode(grWINDOWED)) - initFatalError(); - - WindowRect.top = WindowRect.left = 0; - - WindowRect.right = modelist[modenum].width; - WindowRect.bottom = modelist[modenum].height; - stretched = modelist[modenum].stretched; - - DIBWidth = modelist[modenum].width; - DIBHeight = modelist[modenum].height; - - if (stretched) - { - DIBWidth >>= 1; - DIBHeight >>= 1; - } - - WindowStyle = WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_SYSMENU | - WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CLIPSIBLINGS | - WS_CLIPCHILDREN; - ExWindowStyle = 0; - AdjustWindowRectEx(&WindowRect, WindowStyle, FALSE, 0); - -// the first time we're called to set the mode, create the window we'll use -// for the rest of the session - if (!vid_mode_set) - { - mainwindow = CreateWindowEx ( - ExWindowStyle, - "WinQuake", - "WinQuake", - WindowStyle, - 0, 0, - WindowRect.right - WindowRect.left, - WindowRect.bottom - WindowRect.top, - NULL, - NULL, - global_hInstance, - NULL); - - if (!mainwindow) - Sys_Error ("Couldn't create DIB window"); - - // tell MGL to use this window for fullscreen modes - MGL_registerFullScreenWindow (mainwindow); - - vid_mode_set = true; - } - else - { - SetWindowLong(mainwindow, GWL_STYLE, WindowStyle | WS_VISIBLE); - SetWindowLong(mainwindow, GWL_EXSTYLE, ExWindowStyle); - } - - if (!SetWindowPos (mainwindow, - NULL, - 0, 0, - WindowRect.right - WindowRect.left, - WindowRect.bottom - WindowRect.top, - SWP_NOCOPYBITS | SWP_NOZORDER | - SWP_HIDEWINDOW)) - { - Sys_Error ("Couldn't resize DIB window"); - } - - if (hide_window) - return true; - -// position and show the DIB window - VID_CheckWindowXY (); - SetWindowPos (mainwindow, NULL, (int)vid_window_x.value, - (int)vid_window_y.value, 0, 0, - SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME); - - if (force_minimized) - ShowWindow (mainwindow, SW_MINIMIZE); - else - ShowWindow (mainwindow, SW_SHOWDEFAULT); - - UpdateWindow (mainwindow); - - modestate = MS_WINDOWED; - vid_fulldib_on_focus_mode = 0; - -// 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(mainwindow); - PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS); - ReleaseDC(mainwindow, hdc); - - /* Create the MGL window DC and the MGL memory DC */ - if ((windc = MGL_createWindowedDC(mainwindow)) == NULL) - MGL_fatalError("Unable to create Windowed DC!"); - - if ((dibdc = MGL_createMemoryDC(DIBWidth,DIBHeight,8,&pf)) == NULL) - MGL_fatalError("Unable to create Memory DC!"); - - MGL_makeCurrentDC(dibdc); - - vid.buffer = vid.conbuffer = vid.direct = dibdc->surface; - vid.rowbytes = vid.conrowbytes = dibdc->mi.bytesPerLine; - vid.numpages = 1; - vid.maxwarpwidth = WARP_WIDTH; - vid.maxwarpheight = WARP_HEIGHT; - vid.height = vid.conheight = DIBHeight; - vid.width = vid.conwidth = DIBWidth; - vid.aspect = ((float)vid.height / (float)vid.width) * - (320.0 / 240.0); - - vid_stretched = stretched; - - SendMessage (mainwindow, WM_SETICON, (WPARAM)TRUE, (LPARAM)hIcon); - SendMessage (mainwindow, WM_SETICON, (WPARAM)FALSE, (LPARAM)hIcon); - - return true; -} - - -qboolean VID_SetFullscreenMode (int modenum) -{ - - DDActive = 1; - - DestroyDIBWindow (); - DestroyFullDIBWindow (); - - mode = modelist[modenum].modenum; - - // Destroy old DC's, resetting back to fullscreen mode - if (mgldc) - MGL_destroyDC (mgldc); - if (memdc) - MGL_destroyDC (memdc); - mgldc = memdc = NULL; - - if ((mgldc = createDisplayDC (modelist[modenum].stretched || - (int)vid_nopageflip.value)) == NULL) - { - return false; - } - - modestate = MS_FULLSCREEN; - vid_fulldib_on_focus_mode = 0; - - vid.buffer = vid.conbuffer = vid.direct = NULL; - vid.maxwarpwidth = WARP_WIDTH; - vid.maxwarpheight = WARP_HEIGHT; - DIBHeight = vid.height = vid.conheight = modelist[modenum].height; - DIBWidth = vid.width = vid.conwidth = modelist[modenum].width; - vid.aspect = ((float)vid.height / (float)vid.width) * - (320.0 / 240.0); - - vid_stretched = modelist[modenum].stretched; - -// needed because we're not getting WM_MOVE messages fullscreen on NT - window_x = 0; - window_y = 0; - -// set the large icon, so the Quake icon will show up in the taskbar - SendMessage (mainwindow, WM_SETICON, (WPARAM)1, (LPARAM)hIcon); - SendMessage (mainwindow, WM_SETICON, (WPARAM)0, (LPARAM)hIcon); - -// shouldn't be needed, but Kendall needs to let us get the activation -// message for this not to be needed on NT - AppActivate (true, false); - - return true; -} - - -qboolean VID_SetFullDIBMode (int modenum) -{ - HDC hdc; - pixel_format_t pf; - int lastmodestate; - - DDActive = 0; - - DestroyFullscreenWindow (); - DestroyDIBWindow (); - - if (windc) - MGL_destroyDC(windc); - if (dibdc) - MGL_destroyDC(dibdc); - windc = dibdc = NULL; - -// KJB: Signal to the MGL that we are going back to windowed mode - if (!MGL_changeDisplayMode(grWINDOWED)) - initFatalError(); - - gdevmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; - gdevmode.dmBitsPerPel = modelist[modenum].bpp; - gdevmode.dmPelsWidth = modelist[modenum].width << modelist[modenum].stretched << - modelist[modenum].halfscreen; - gdevmode.dmPelsHeight = modelist[modenum].height << modelist[modenum].stretched; - 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; - vid_fulldib_on_focus_mode = modenum; - - WindowRect.top = WindowRect.left = 0; - - hdc = GetDC(NULL); - - WindowRect.right = modelist[modenum].width << modelist[modenum].stretched; - WindowRect.bottom = modelist[modenum].height << modelist[modenum].stretched; - - ReleaseDC(NULL,hdc); - - DIBWidth = modelist[modenum].width; - DIBHeight = modelist[modenum].height; - - WindowStyle = WS_POPUP | WS_SYSMENU | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; - ExWindowStyle = 0; - AdjustWindowRectEx(&WindowRect, WindowStyle, FALSE, 0); - - SetWindowLong(mainwindow, GWL_STYLE, WindowStyle | WS_VISIBLE); - SetWindowLong(mainwindow, GWL_EXSTYLE, ExWindowStyle); - - if (!SetWindowPos (mainwindow, - NULL, - 0, 0, - WindowRect.right - WindowRect.left, - WindowRect.bottom - WindowRect.top, - SWP_NOCOPYBITS | SWP_NOZORDER)) - { - Sys_Error ("Couldn't resize DIB window"); - } - -// position and show the DIB window - SetWindowPos (mainwindow, HWND_TOPMOST, 0, 0, 0, 0, - SWP_NOSIZE | SWP_SHOWWINDOW | SWP_DRAWFRAME); - ShowWindow (mainwindow, SW_SHOWDEFAULT); - UpdateWindow (mainwindow); - - // 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(mainwindow); - PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS); - ReleaseDC(mainwindow, hdc); - - /* Create the MGL window DC and the MGL memory DC */ - if ((windc = MGL_createWindowedDC(mainwindow)) == NULL) - MGL_fatalError("Unable to create Fullscreen DIB DC!"); - - if ((dibdc = MGL_createMemoryDC(DIBWidth,DIBHeight,8,&pf)) == NULL) - MGL_fatalError("Unable to create Memory DC!"); - - MGL_makeCurrentDC(dibdc); - - vid.buffer = vid.conbuffer = vid.direct = dibdc->surface; - vid.rowbytes = vid.conrowbytes = dibdc->mi.bytesPerLine; - vid.numpages = 1; - vid.maxwarpwidth = WARP_WIDTH; - vid.maxwarpheight = WARP_HEIGHT; - vid.height = vid.conheight = DIBHeight; - vid.width = vid.conwidth = DIBWidth; - vid.aspect = ((float)vid.height / (float)vid.width) * - (320.0 / 240.0); - - vid_stretched = modelist[modenum].stretched; - -// needed because we're not getting WM_MOVE messages fullscreen on NT - window_x = 0; - window_y = 0; - - return true; -} - - -void VID_RestoreOldMode (int original_mode) -{ - static qboolean inerror = false; - - if (inerror) - return; - - in_mode_set = false; - inerror = true; - -// make sure mode set happens (video mode changes) - vid_modenum = original_mode - 1; - - if (!VID_SetMode (original_mode, vid_curpal)) - { - vid_modenum = MODE_WINDOWED - 1; - - if (!VID_SetMode (windowed_default, vid_curpal)) - Sys_Error ("Can't set any video mode"); - } - - inerror = false; -} - - -void VID_SetDefaultMode (void) -{ - - if (vid_initialized) - VID_SetMode (0, vid_curpal); - - IN_DeactivateMouse (); -} - - -int VID_SetMode (int modenum, unsigned char *palette) -{ - int original_mode, temp, dummy; - qboolean stat; - MSG msg; - HDC hdc; - - while ((modenum >= nummodes) || (modenum < 0)) - { - if (vid_modenum == NO_MODE) - { - if (modenum == vid_default) - { - modenum = windowed_default; - } - else - { - modenum = vid_default; - } - - Cvar_SetValue ("vid_mode", (float)modenum); - } - else - { - Cvar_SetValue ("vid_mode", (float)vid_modenum); - return 0; - } - } - - if (!force_mode_set && (modenum == vid_modenum)) - return true; - -// so Con_Printfs don't mess us up by forcing vid and snd updates - temp = scr_disabled_for_loading; - scr_disabled_for_loading = true; - in_mode_set = true; - - CDAudio_Pause (); - S_ClearBuffer (); - - 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) - { - 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 - { - stat = VID_SetFullscreenMode(modenum); - IN_ActivateMouse (); - IN_HideMouse (); - } - - window_width = vid.width << vid_stretched; - window_height = vid.height << vid_stretched; - VID_UpdateWindowStatus (); - - CDAudio_Resume (); - scr_disabled_for_loading = temp; - - if (!stat) - { - VID_RestoreOldMode (original_mode); - return false; - } - - if (hide_window) - return true; - -// 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 - if (!force_minimized) - SetForegroundWindow (mainwindow); - - hdc = GetDC(NULL); - - if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) - vid_palettized = true; - else - vid_palettized = false; - - VID_SetPalette (palette); - - ReleaseDC(NULL,hdc); - - vid_modenum = modenum; - Cvar_SetValue ("vid_mode", (float)vid_modenum); - - if (!VID_AllocBuffers (vid.width, vid.height)) - { - // couldn't get memory for this mode; try to fall back to previous mode - VID_RestoreOldMode (original_mode); - return false; - } - - D_InitCaches (vid_surfcache, vid_surfcachesize); - - while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) - { - TranslateMessage (&msg); - DispatchMessage (&msg); - } - - Sleep (100); - - if (!force_minimized) - { - 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 ("%s\n", VID_GetModeDescription (vid_modenum)); - - VID_SetPalette (palette); - - in_mode_set = false; - vid.recalc_refdef = 1; - - return true; -} - -void VID_LockBuffer (void) -{ - - if (dibdc) - return; - - lockcount++; - - if (lockcount > 1) - return; - - MGL_beginDirectAccess(); - - if (memdc) - { - // Update surface pointer for linear access modes - vid.buffer = vid.conbuffer = vid.direct = memdc->surface; - vid.rowbytes = vid.conrowbytes = memdc->mi.bytesPerLine; - } - else if (mgldc) - { - // Update surface pointer for linear access modes - vid.buffer = vid.conbuffer = vid.direct = mgldc->surface; - vid.rowbytes = vid.conrowbytes = mgldc->mi.bytesPerLine; - } - - if (r_dowarp) - d_viewbuffer = r_warpbuffer; - else - d_viewbuffer = (void *)(byte *)vid.buffer; - - if (r_dowarp) - screenwidth = WARP_WIDTH; - else - screenwidth = vid.rowbytes; - - if (lcd_x.value) - screenwidth <<= 1; -} - - -void VID_UnlockBuffer (void) -{ - if (dibdc) - return; - - lockcount--; - - if (lockcount > 0) - return; - - if (lockcount < 0) - Sys_Error ("Unbalanced unlock"); - - MGL_endDirectAccess(); - -// to turn up any unlocked accesses - vid.buffer = vid.conbuffer = vid.direct = d_viewbuffer = NULL; - -} - - -int VID_ForceUnlockedAndReturnState (void) -{ - int lk; - - if (!lockcount) - return 0; - - lk = lockcount; - - if (dibdc) - { - lockcount = 0; - } - else - { - lockcount = 1; - VID_UnlockBuffer (); - } - - return lk; -} - - -void VID_ForceLockState (int lk) -{ - - if (!dibdc && lk) - { - lockcount = 0; - VID_LockBuffer (); - } - - lockcount = lk; -} - - -void VID_SetPalette (unsigned char *palette) -{ - INT i; - palette_t pal[256]; - HDC hdc; - - if (!Minimized) - { - palette_changed = true; - - // make sure we have the static colors if we're the active app - hdc = GetDC(NULL); - - if (vid_palettized && ActiveApp) - { - if (GetSystemPaletteUse(hdc) == SYSPAL_STATIC) - { - // switch to SYSPAL_NOSTATIC and remap the colors - SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC); - syscolchg = true; - pal_is_nostatic = true; - } - } - - ReleaseDC(NULL,hdc); - - // Translate the palette values to an MGL palette array and - // set the values. - for (i = 0; i < 256; i++) - { - pal[i].red = palette[i*3]; - pal[i].green = palette[i*3+1]; - pal[i].blue = palette[i*3+2]; - } - - if (DDActive) - { - if (!mgldc) - return; - - MGL_setPalette(mgldc,pal,256,0); - MGL_realizePalette(mgldc,256,0,false); - if (memdc) - MGL_setPalette(memdc,pal,256,0); - } - else - { - if (!windc) - return; - - MGL_setPalette(windc,pal,256,0); - MGL_realizePalette(windc,256,0,false); - if (dibdc) - { - MGL_setPalette(dibdc,pal,256,0); - MGL_realizePalette(dibdc,256,0,false); - } - } - } - - memcpy (vid_curpal, palette, sizeof(vid_curpal)); - - if (syscolchg) - { - PostMessage (HWND_BROADCAST, WM_SYSCOLORCHANGE, (WPARAM)0, (LPARAM)0); - syscolchg = false; - } -} - - -void VID_ShiftPalette (unsigned char *palette) -{ - VID_SetPalette (palette); -} - - -/* -================= -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 modenum; - - modenum = Q_atoi (Cmd_Argv(1)); - - Con_Printf ("%s\n", VID_GetExtModeDescription (modenum)); -} - - -/* -================= -VID_DescribeModes_f -================= -*/ -void VID_DescribeModes_f (void) -{ - int i, lnummodes; - char *pinfo; - qboolean na; - vmode_t *pv; - - na = false; - - lnummodes = VID_NumModes (); - - for (i=0 ; i<lnummodes ; i++) - { - pv = VID_GetModePtr (i); - pinfo = VID_GetExtModeDescription (i); - - if (VID_CheckAdequateMem (pv->width, pv->height)) - { - Con_Printf ("%2d: %s\n", i, pinfo); - } - else - { - Con_Printf ("**: %s\n", pinfo); - na = true; - } - } - - if (na) - { - Con_Printf ("\n[**: not enough system RAM for mode]\n"); - } -} - - -/* -================= -VID_TestMode_f -================= -*/ -void VID_TestMode_f (void) -{ - int modenum; - double testduration; - - if (!vid_testingmode) - { - modenum = Q_atoi (Cmd_Argv(1)); - - if (VID_SetMode (modenum, vid_curpal)) - { - vid_testingmode = 1; - testduration = Q_atof (Cmd_Argv(2)); - if (testduration == 0) - testduration = 5.0; - vid_testendtime = realtime + testduration; - } - } -} - - -/* -================= -VID_Windowed_f -================= -*/ -void VID_Windowed_f (void) -{ - - VID_SetMode ((int)vid_windowed_mode.value, vid_curpal); -} - - -/* -================= -VID_Fullscreen_f -================= -*/ -void VID_Fullscreen_f (void) -{ - - VID_SetMode ((int)vid_fullscreen_mode.value, vid_curpal); -} - - -/* -================= -VID_Minimize_f -================= -*/ -void VID_Minimize_f (void) -{ - -// we only support minimizing windows; if you're fullscreen, -// switch to windowed first - if (modestate == MS_WINDOWED) - ShowWindow (mainwindow, SW_MINIMIZE); -} - - - -/* -================= -VID_ForceMode_f -================= -*/ -void VID_ForceMode_f (void) -{ - int modenum; - double testduration; - - if (!vid_testingmode) - { - modenum = Q_atoi (Cmd_Argv(1)); - - force_mode_set = 1; - VID_SetMode (modenum, vid_curpal); - force_mode_set = 0; - } -} - - -void VID_Init (unsigned char *palette) -{ - int i, bestmatch, bestmatchmetric, t, dr, dg, db; - int basenummodes; - byte *ptmp; - - Cvar_RegisterVariable (&vid_mode); - Cvar_RegisterVariable (&vid_wait); - Cvar_RegisterVariable (&vid_nopageflip); - Cvar_RegisterVariable (&_vid_wait_override); - Cvar_RegisterVariable (&_vid_default_mode); - Cvar_RegisterVariable (&_vid_default_mode_win); - Cvar_RegisterVariable (&vid_config_x); - Cvar_RegisterVariable (&vid_config_y); - Cvar_RegisterVariable (&vid_stretch_by_2); - Cvar_RegisterVariable (&_windowed_mouse); - Cvar_RegisterVariable (&vid_fullscreen_mode); - Cvar_RegisterVariable (&vid_windowed_mode); - Cvar_RegisterVariable (&block_switch); - Cvar_RegisterVariable (&vid_window_x); - Cvar_RegisterVariable (&vid_window_y); - - Cmd_AddCommand ("vid_testmode", VID_TestMode_f); - 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); - Cmd_AddCommand ("vid_forcemode", VID_ForceMode_f); - Cmd_AddCommand ("vid_windowed", VID_Windowed_f); - Cmd_AddCommand ("vid_fullscreen", VID_Fullscreen_f); - Cmd_AddCommand ("vid_minimize", VID_Minimize_f); - - if (COM_CheckParm ("-dibonly")) - dibonly = true; - - VID_InitMGLDIB (global_hInstance); - - basenummodes = nummodes; - - if (!dibonly) - VID_InitMGLFull (global_hInstance); - -// if there are no non-windowed modes, or only windowed and mode 0x13, then use -// fullscreen DIBs as well - if (((nummodes == basenummodes) || - ((nummodes == (basenummodes + 1)) && is_mode0x13)) && - !COM_CheckParm ("-nofulldib")) - - { - VID_InitFullDIB (global_hInstance); - } - - vid.maxwarpwidth = WARP_WIDTH; - vid.maxwarpheight = WARP_HEIGHT; - vid.colormap = host_colormap; - vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048)); - vid_testingmode = 0; - -// GDI doesn't let us remap palette index 0, so we'll remap color -// mappings from that black to another one - bestmatchmetric = 256*256*3; - - for (i=1 ; i<256 ; i++) - { - dr = palette[0] - palette[i*3]; - dg = palette[1] - palette[i*3+1]; - db = palette[2] - palette[i*3+2]; - - t = (dr * dr) + (dg * dg) + (db * db); - - if (t < bestmatchmetric) - { - bestmatchmetric = t; - bestmatch = i; - - if (t == 0) - break; - } - } - - for (i=0, ptmp = vid.colormap ; i<(1<<(VID_CBITS+8)) ; i++, ptmp++) - { - if (*ptmp == 0) - *ptmp = bestmatch; - } - - if (COM_CheckParm("-startwindowed")) - { - startwindowed = 1; - vid_default = windowed_default; - } - - if (hwnd_dialog) - DestroyWindow (hwnd_dialog); - -// sound initialization has to go here, preceded by a windowed mode set, -// so there's a window for DirectSound to work with but we're not yet -// fullscreen so the "hardware already in use" dialog is visible if it -// gets displayed - -// keep the window minimized until we're ready for the first real mode set - hide_window = true; - VID_SetMode (MODE_WINDOWED, palette); - hide_window = false; - S_Init (); - - vid_initialized = true; - - force_mode_set = true; - VID_SetMode (vid_default, palette); - force_mode_set = false; - - vid_realmode = vid_modenum; - - VID_SetPalette (palette); - - vid_menudrawfn = VID_MenuDraw; - vid_menukeyfn = VID_MenuKey; - - strcpy (badmode.modedesc, "Bad mode"); -} - - -void VID_Shutdown (void) -{ - HDC hdc; - int dummy; - - if (vid_initialized) - { - if (modestate == MS_FULLDIB) - ChangeDisplaySettings (NULL, CDS_FULLSCREEN); - - PostMessage (HWND_BROADCAST, WM_PALETTECHANGED, (WPARAM)mainwindow, (LPARAM)0); - PostMessage (HWND_BROADCAST, WM_SYSCOLORCHANGE, (WPARAM)0, (LPARAM)0); - - AppActivate(false, false); - DestroyDIBWindow (); - DestroyFullscreenWindow (); - DestroyFullDIBWindow (); - - if (hwnd_dialog) - DestroyWindow (hwnd_dialog); - - if (mainwindow) - DestroyWindow(mainwindow); - - MGL_exit(); - - vid_testingmode = 0; - vid_initialized = 0; - } -} - - -/* -================ -FlipScreen -================ -*/ -void FlipScreen(vrect_t *rects) -{ - HRESULT ddrval; - - // Flip the surfaces - - if (DDActive) - { - if (mgldc) - { - if (memdc) - { - while (rects) - { - if (vid_stretched) - { - MGL_stretchBltCoord(mgldc, memdc, - rects->x, - rects->y, - rects->x + rects->width, - rects->y + rects->height, - rects->x << 1, - rects->y << 1, - (rects->x + rects->width) << 1, - (rects->y + rects->height) << 1); - } - else - { - MGL_bitBltCoord(mgldc, memdc, - rects->x, rects->y, - (rects->x + rects->width), - (rects->y + rects->height), - rects->x, rects->y, MGL_REPLACE_MODE); - } - - rects = rects->pnext; - } - } - - if (vid.numpages > 1) - { - // We have a flipping surface, so do a hard page flip - aPage = (aPage+1) % vid.numpages; - vPage = (vPage+1) % vid.numpages; - MGL_setActivePage(mgldc,aPage); - MGL_setVisualPage(mgldc,vPage,waitVRT); - } - } - } - else - { - HDC hdcScreen; - - hdcScreen = GetDC(mainwindow); - - if (windc && dibdc) - { - MGL_setWinDC(windc,hdcScreen); - - while (rects) - { - if (vid_stretched) - { - MGL_stretchBltCoord(windc,dibdc, - rects->x, rects->y, - rects->x + rects->width, rects->y + rects->height, - rects->x << 1, rects->y << 1, - (rects->x + rects->width) << 1, - (rects->y + rects->height) << 1); - } - else - { - MGL_bitBltCoord(windc,dibdc, - rects->x, rects->y, - rects->x + rects->width, rects->y + rects->height, - rects->x, rects->y, MGL_REPLACE_MODE); - } - - rects = rects->pnext; - } - } - - ReleaseDC(mainwindow, hdcScreen); - } -} - - -void VID_Update (vrect_t *rects) -{ - vrect_t rect; - RECT trect; - - if (!vid_palettized && palette_changed) - { - palette_changed = false; - rect.x = 0; - rect.y = 0; - rect.width = vid.width; - rect.height = vid.height; - rect.pnext = NULL; - rects = ▭ - } - - if (firstupdate) - { - if (modestate == MS_WINDOWED) - { - GetWindowRect (mainwindow, &trect); - - if ((trect.left != (int)vid_window_x.value) || - (trect.top != (int)vid_window_y.value)) - { - if (COM_CheckParm ("-resetwinpos")) - { - Cvar_SetValue ("vid_window_x", 0.0); - Cvar_SetValue ("vid_window_y", 0.0); - } - - VID_CheckWindowXY (); - SetWindowPos (mainwindow, NULL, (int)vid_window_x.value, - (int)vid_window_y.value, 0, 0, - SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME); - } - } - - if ((_vid_default_mode_win.value != vid_default) && - (!startwindowed || (_vid_default_mode_win.value < MODE_FULLSCREEN_DEFAULT))) - { - firstupdate = 0; - - if (COM_CheckParm ("-resetwinpos")) - { - Cvar_SetValue ("vid_window_x", 0.0); - Cvar_SetValue ("vid_window_y", 0.0); - } - - if ((_vid_default_mode_win.value < 0) || - (_vid_default_mode_win.value >= nummodes)) - { - Cvar_SetValue ("_vid_default_mode_win", windowed_default); - } - - Cvar_SetValue ("vid_mode", _vid_default_mode_win.value); - } - } - - // We've drawn the frame; copy it to the screen - FlipScreen (rects); - - if (vid_testingmode) - { - if (realtime >= vid_testendtime) - { - VID_SetMode (vid_realmode, vid_curpal); - vid_testingmode = 0; - } - } - else - { - if ((int)vid_mode.value != vid_realmode) - { - VID_SetMode ((int)vid_mode.value, vid_curpal); - Cvar_SetValue ("vid_mode", (float)vid_modenum); - // so if mode set fails, we don't keep on - // trying to set that mode - vid_realmode = vid_modenum; - } - } - -// handle the mouse state when windowed if that's changed - if (modestate == MS_WINDOWED) - { - if ((int)_windowed_mouse.value != windowed_mouse) - { - if (_windowed_mouse.value) - { - IN_ActivateMouse (); - IN_HideMouse (); - } - else - { - IN_DeactivateMouse (); - IN_ShowMouse (); - } - - windowed_mouse = (int)_windowed_mouse.value; - } - } -} - - -/* -================ -D_BeginDirectRect -================ -*/ -void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) -{ - int i, j, reps, repshift; - vrect_t rect; - - if (!vid_initialized) - return; - - if (vid.aspect > 1.5) - { - reps = 2; - repshift = 1; - } - else - { - reps = 1; - repshift = 0; - } - - if (vid.numpages == 1) - { - VID_LockBuffer (); - - if (!vid.direct) - Sys_Error ("NULL vid.direct pointer"); - - for (i=0 ; i<(height << repshift) ; i += reps) - { - for (j=0 ; j<reps ; j++) - { - memcpy (&backingbuf[(i + j) * 24], - vid.direct + x + ((y << repshift) + i + j) * vid.rowbytes, - width); - memcpy (vid.direct + x + ((y << repshift) + i + j) * vid.rowbytes, - &pbitmap[(i >> repshift) * width], - width); - } - } - - VID_UnlockBuffer (); - - rect.x = x; - rect.y = y; - rect.width = width; - rect.height = height << repshift; - rect.pnext = NULL; - - FlipScreen (&rect); - } - else - { - // unlock if locked - if (lockcount > 0) - MGL_endDirectAccess(); - - // set the active page to the displayed page - MGL_setActivePage (mgldc, vPage); - - // lock the screen - MGL_beginDirectAccess (); - - // save from and draw to screen - for (i=0 ; i<(height << repshift) ; i += reps) - { - for (j=0 ; j<reps ; j++) - { - memcpy (&backingbuf[(i + j) * 24], - (byte *)mgldc->surface + x + - ((y << repshift) + i + j) * mgldc->mi.bytesPerLine, - width); - memcpy ((byte *)mgldc->surface + x + - ((y << repshift) + i + j) * mgldc->mi.bytesPerLine, - &pbitmap[(i >> repshift) * width], - width); - } - } - - // unlock the screen - MGL_endDirectAccess (); - - // restore the original active page - MGL_setActivePage (mgldc, aPage); - - // relock the screen if it was locked - if (lockcount > 0) - MGL_beginDirectAccess(); - } -} - - -/* -================ -D_EndDirectRect -================ -*/ -void D_EndDirectRect (int x, int y, int width, int height) -{ - int i, j, reps, repshift; - vrect_t rect; - - if (!vid_initialized) - return; - - if (vid.aspect > 1.5) - { - reps = 2; - repshift = 1; - } - else - { - reps = 1; - repshift = 0; - } - - if (vid.numpages == 1) - { - VID_LockBuffer (); - - if (!vid.direct) - Sys_Error ("NULL vid.direct pointer"); - - for (i=0 ; i<(height << repshift) ; i += reps) - { - for (j=0 ; j<reps ; j++) - { - memcpy (vid.direct + x + ((y << repshift) + i + j) * vid.rowbytes, - &backingbuf[(i + j) * 24], - width); - } - } - - VID_UnlockBuffer (); - - rect.x = x; - rect.y = y; - rect.width = width; - rect.height = height << repshift; - rect.pnext = NULL; - - FlipScreen (&rect); - } - else - { - // unlock if locked - if (lockcount > 0) - MGL_endDirectAccess(); - - // set the active page to the displayed page - MGL_setActivePage (mgldc, vPage); - - // lock the screen - MGL_beginDirectAccess (); - - // restore to the screen - for (i=0 ; i<(height << repshift) ; i += reps) - { - for (j=0 ; j<reps ; j++) - { - memcpy ((byte *)mgldc->surface + x + - ((y << repshift) + i + j) * mgldc->mi.bytesPerLine, - &backingbuf[(i + j) * 24], - width); - } - } - - // unlock the screen - MGL_endDirectAccess (); - - // restore the original active page - MGL_setActivePage (mgldc, aPage); - - // relock the screen if it was locked - if (lockcount > 0) - MGL_beginDirectAccess(); - } -} - - -//========================================================================== - -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,'*', - K_ALT,' ', 0 , K_F1, K_F2, K_F3, K_F4, K_F5, // 3 - K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE, 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, // 6 - 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, - 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 // 7 -}; - -/* -======= -MapKey - -Map from windows to quake keynums -======= -*/ -int MapKey (int key) -{ - key = (key>>16)&255; - if (key > 127) - return 0; - - return scantokey[key]; -} - -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. -* -****************************************************************************/ -{ - HDC hdc; - int i, t; - static BOOL sound_active; - - ActiveApp = fActive; - -// messy, but it seems to work - if (vid_fulldib_on_focus_mode) - { - Minimized = minimize; - - if (Minimized) - ActiveApp = false; - } - - MGL_appActivate(windc, ActiveApp); - - if (vid_initialized) - { - // yield the palette if we're losing the focus - hdc = GetDC(NULL); - - if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) - { - if (ActiveApp) - { - if ((modestate == MS_WINDOWED) || (modestate == MS_FULLDIB)) - { - if (GetSystemPaletteUse(hdc) == SYSPAL_STATIC) - { - // switch to SYSPAL_NOSTATIC and remap the colors - SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC); - syscolchg = true; - pal_is_nostatic = true; - } - } - } - else if (pal_is_nostatic) - { - if (GetSystemPaletteUse(hdc) == SYSPAL_NOSTATIC) - { - // switch back to SYSPAL_STATIC and the old mapping - SetSystemPaletteUse(hdc, SYSPAL_STATIC); - syscolchg = true; - } - - pal_is_nostatic = false; - } - } - - if (!Minimized) - VID_SetPalette (vid_curpal); - - scr_fullupdate = 0; - - ReleaseDC(NULL,hdc); - } - -// enable/disable sound on focus gain/loss - if (!ActiveApp && sound_active) - { - S_BlockSound (); - S_ClearBuffer (); - sound_active = false; - } - else if (ActiveApp && !sound_active) - { - S_UnblockSound (); - S_ClearBuffer (); - sound_active = true; - } - -// minimize/restore fulldib windows/mouse-capture normal windows on demand - if (!in_mode_set) - { - if (ActiveApp) - { - if (vid_fulldib_on_focus_mode) - { - if (vid_initialized) - { - msg_suppress_1 = true; // don't want to see normal mode set message - VID_SetMode (vid_fulldib_on_focus_mode, vid_curpal); - msg_suppress_1 = false; - - t = in_mode_set; - in_mode_set = true; - AppActivate (true, false); - in_mode_set = t; - } - - IN_ActivateMouse (); - IN_HideMouse (); - } - else if ((modestate == MS_WINDOWED) && _windowed_mouse.value) - { - IN_ActivateMouse (); - IN_HideMouse (); - } - } - - if (!ActiveApp) - { - if (modestate == MS_FULLDIB) - { - if (vid_initialized) - { - force_minimized = true; - i = vid_fulldib_on_focus_mode; - msg_suppress_1 = true; // don't want to see normal mode set message - VID_SetMode (windowed_default, vid_curpal); - msg_suppress_1 = false; - vid_fulldib_on_focus_mode = i; - force_minimized = false; - - // we never seem to get WM_ACTIVATE inactive from this mode set, so we'll - // do it manually - t = in_mode_set; - in_mode_set = true; - AppActivate (false, true); - in_mode_set = t; - } - - IN_DeactivateMouse (); - IN_ShowMouse (); - } - else if ((modestate == MS_WINDOWED) && _windowed_mouse.value) - { - IN_DeactivateMouse (); - IN_ShowMouse (); - } - } - } -} - - -/* -================ -VID_HandlePause -================ -*/ -void VID_HandlePause (qboolean pause) -{ - - if ((modestate == MS_WINDOWED) && _windowed_mouse.value) - { - if (pause) - { - IN_DeactivateMouse (); - IN_ShowMouse (); - } - else - { - IN_ActivateMouse (); - IN_HideMouse (); - } - } -} - - -/* -=================================================================== - -MAIN WINDOW - -=================================================================== -*/ - -LONG CDAudio_MessageHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - -/* main window procedure */ -LONG WINAPI MainWndProc ( - HWND hWnd, - UINT uMsg, - WPARAM wParam, - LPARAM lParam) -{ - LONG lRet = 0; - int fwKeys, xPos, yPos, fActive, fMinimized, temp; - HDC hdc; - PAINTSTRUCT ps; - static int recursiveflag; - - switch (uMsg) - { - case WM_CREATE: - break; - - case WM_SYSCOMMAND: - - // Check for maximize being hit - switch (wParam & ~0x0F) - { - case SC_MAXIMIZE: - // if minimized, bring up as a window before going fullscreen, - // so MGL will have the right state to restore - if (Minimized) - { - force_mode_set = true; - VID_SetMode (vid_modenum, vid_curpal); - force_mode_set = false; - } - - VID_SetMode ((int)vid_fullscreen_mode.value, vid_curpal); - break; - - case SC_SCREENSAVE: - case SC_MONITORPOWER: - if (modestate != MS_WINDOWED) - { - // don't call DefWindowProc() because we don't want to start - // the screen saver fullscreen - break; - } - - // fall through windowed and allow the screen saver to start - - default: - if (!in_mode_set) - { - S_BlockSound (); - S_ClearBuffer (); - } - - lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); - - if (!in_mode_set) - { - S_UnblockSound (); - } - } - break; - - case WM_MOVE: - window_x = (int) LOWORD(lParam); - window_y = (int) HIWORD(lParam); - VID_UpdateWindowStatus (); - - if ((modestate == MS_WINDOWED) && !in_mode_set && !Minimized) - VID_RememberWindowPos (); - - break; - - case WM_SIZE: - Minimized = false; - - if (!(wParam & SIZE_RESTORED)) - { - if (wParam & SIZE_MINIMIZED) - Minimized = true; - } - break; - - case WM_SYSCHAR: - // keep Alt-Space from happening - 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 (); - - if (!in_mode_set) - { - if (windc) - MGL_activatePalette(windc,true); - - VID_SetPalette(vid_curpal); - } - - break; - - case WM_PAINT: - hdc = BeginPaint(hWnd, &ps); - - if (!in_mode_set && host_initialized) - SCR_UpdateWholeScreen (); - - EndPaint(hWnd, &ps); - break; - - case WM_KEYDOWN: - case WM_SYSKEYDOWN: - if (!in_mode_set) - Key_Event (MapKey(lParam), true); - break; - - case WM_KEYUP: - case WM_SYSKEYUP: - if (!in_mode_set) - Key_Event (MapKey(lParam), false); - 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: - if (!in_mode_set) - { - 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; - // KJB: Added these new palette functions - case WM_PALETTECHANGED: - if ((HWND)wParam == hWnd) - break; - /* Fall through to WM_QUERYNEWPALETTE */ - case WM_QUERYNEWPALETTE: - hdc = GetDC(NULL); - - if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) - vid_palettized = true; - else - vid_palettized = false; - - ReleaseDC(NULL,hdc); - - scr_fullupdate = 0; - - if (vid_initialized && !in_mode_set && windc && MGL_activatePalette(windc,false) && !Minimized) - { - VID_SetPalette (vid_curpal); - InvalidateRect (mainwindow, NULL, false); - - // specifically required if WM_QUERYNEWPALETTE realizes a new palette - lRet = TRUE; - } - break; - - case WM_DISPLAYCHANGE: - if (!in_mode_set && (modestate == MS_WINDOWED) && !vid_fulldib_on_focus_mode) - { - force_mode_set = true; - VID_SetMode (vid_modenum, vid_curpal); - force_mode_set = false; - } - break; - - case WM_CLOSE: - // this causes Close in the right-click task bar menu not to work, but right - // now bad things happen if Close is handled in that case (garbage and a - // crash on Win95) - if (!in_mode_set) - { - if (MessageBox (mainwindow, "Are you sure you want to quit?", "Confirm Exit", - MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION) == IDYES) - { - Sys_Quit (); - } - } - 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 0 if handled message, 1 if not */ - return lRet; -} - - -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; - int ismode13; - int width; -} modedesc_t; - -#define MAX_COLUMN_SIZE 5 -#define MODE_AREA_HEIGHT (MAX_COLUMN_SIZE + 6) -#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; - modedesc_t tmodedesc; - - p = Draw_CachePic ("gfx/vidmodes.lmp"); - M_DrawPic ( (320-p->width)/2, 4, p); - - for (i=0 ; i<3 ; i++) - { - ptr = VID_GetModeDescriptionMemCheck (i); - modedescs[i].modenum = modelist[i].modenum; - modedescs[i].desc = ptr; - modedescs[i].ismode13 = 0; - modedescs[i].iscur = 0; - - if (vid_modenum == i) - modedescs[i].iscur = 1; - } - - vid_wmodes = 3; - lnummodes = VID_NumModes (); - - for (i=3 ; i<lnummodes ; i++) - { - ptr = VID_GetModeDescriptionMemCheck (i); - pv = VID_GetModePtr (i); - - // we only have room for 15 fullscreen modes, so don't allow - // 360-wide modes, because if there are 5 320-wide modes and - // 5 360-wide modes, we'll run out of space - if (ptr && ((pv->width != 360) || COM_CheckParm("-allow360"))) - { - dup = 0; - - for (j=3 ; j<vid_wmodes ; j++) - { - if (!strcmp (modedescs[j].desc, ptr)) - { - dup = 1; - dupmode = j; - break; - } - } - - if (dup || (vid_wmodes < MAX_MODEDESCS)) - { - if (!dup || !modedescs[dupmode].ismode13 || COM_CheckParm("-noforcevga")) - { - if (dup) - { - k = dupmode; - } - else - { - k = vid_wmodes; - } - - modedescs[k].modenum = i; - modedescs[k].desc = ptr; - modedescs[k].ismode13 = pv->mode13; - modedescs[k].iscur = 0; - modedescs[k].width = pv->width; - - if (i == vid_modenum) - modedescs[k].iscur = 1; - - if (!dup) - vid_wmodes++; - } - } - } - } - -// sort the modes on width (to handle picking up oddball dibonly modes -// after all the others) - for (i=3 ; i<(vid_wmodes-1) ; i++) - { - for (j=(i+1) ; j<vid_wmodes ; j++) - { - if (modedescs[i].width > modedescs[j].width) - { - tmodedesc = modedescs[i]; - modedescs[i] = modedescs[j]; - modedescs[j] = tmodedesc; - } - } - } - - - M_Print (13*8, 36, "Windowed Modes"); - - column = 16; - row = 36+2*8; - - for (i=0 ; i<3; i++) - { - if (modedescs[i].iscur) - M_PrintWhite (column, row, modedescs[i].desc); - else - M_Print (column, row, modedescs[i].desc); - - column += 13*8; - } - - if (vid_wmodes > 3) - { - M_Print (12*8, 36+4*8, "Fullscreen Modes"); - - column = 16; - row = 36+6*8; - - for (i=3 ; 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 - 3) % VID_ROW_SIZE) == (VID_ROW_SIZE - 1)) - { - column = 16; - row += 8; - } - } - } - -// line cursor - if (vid_testingmode) - { - sprintf (temp, "TESTING %s", - modedescs[vid_line].desc); - M_Print (13*8, 36 + MODE_AREA_HEIGHT * 8 + 8*4, temp); - M_Print (9*8, 36 + MODE_AREA_HEIGHT * 8 + 8*6, - "Please wait 5 seconds..."); - } - else - { - M_Print (9*8, 36 + MODE_AREA_HEIGHT * 8 + 8, - "Press Enter to set mode"); - M_Print (6*8, 36 + MODE_AREA_HEIGHT * 8 + 8*3, - "T to test mode for 5 seconds"); - ptr = VID_GetModeDescription2 (vid_modenum); - - if (ptr) - { - sprintf (temp, "D to set default: %s", ptr); - M_Print (2*8, 36 + MODE_AREA_HEIGHT * 8 + 8*5, temp); - } - - ptr = VID_GetModeDescription2 ((int)_vid_default_mode_win.value); - - if (ptr) - { - sprintf (temp, "Current default: %s", ptr); - M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*6, temp); - } - - M_Print (15*8, 36 + MODE_AREA_HEIGHT * 8 + 8*8, - "Esc to exit"); - - row = 36 + 2*8 + (vid_line / VID_ROW_SIZE) * 8; - column = 8 + (vid_line % VID_ROW_SIZE) * 13*8; - - if (vid_line >= 3) - row += 3*8; - - M_DrawCharacter (column, row, 12+((int)(realtime*4)&1)); - } -} - - -/* -================ -VID_MenuKey -================ -*/ -void VID_MenuKey (int key) -{ - if (vid_testingmode) - return; - - switch (key) - { - case K_ESCAPE: - S_LocalSound ("misc/menu1.wav"); - M_Menu_Options_f (); - break; - - case K_LEFTARROW: - S_LocalSound ("misc/menu1.wav"); - vid_line = ((vid_line / VID_ROW_SIZE) * VID_ROW_SIZE) + - ((vid_line + 2) % VID_ROW_SIZE); - - if (vid_line >= vid_wmodes) - vid_line = vid_wmodes - 1; - break; - - case K_RIGHTARROW: - S_LocalSound ("misc/menu1.wav"); - vid_line = ((vid_line / VID_ROW_SIZE) * VID_ROW_SIZE) + - ((vid_line + 4) % VID_ROW_SIZE); - - if (vid_line >= vid_wmodes) - vid_line = (vid_line / VID_ROW_SIZE) * VID_ROW_SIZE; - break; - - case K_UPARROW: - S_LocalSound ("misc/menu1.wav"); - vid_line -= VID_ROW_SIZE; - - if (vid_line < 0) - { - vid_line += ((vid_wmodes + (VID_ROW_SIZE - 1)) / - VID_ROW_SIZE) * VID_ROW_SIZE; - - while (vid_line >= vid_wmodes) - vid_line -= VID_ROW_SIZE; - } - break; - - case K_DOWNARROW: - S_LocalSound ("misc/menu1.wav"); - vid_line += VID_ROW_SIZE; - - if (vid_line >= vid_wmodes) - { - vid_line -= ((vid_wmodes + (VID_ROW_SIZE - 1)) / - VID_ROW_SIZE) * VID_ROW_SIZE; - - while (vid_line < 0) - vid_line += VID_ROW_SIZE; - } - break; - - case K_ENTER: - S_LocalSound ("misc/menu1.wav"); - VID_SetMode (modedescs[vid_line].modenum, vid_curpal); - break; - - case 'T': - case 't': - S_LocalSound ("misc/menu1.wav"); - // have to set this before setting the mode because WM_PAINT - // happens during the mode set and does a VID_Update, which - // checks vid_testingmode - vid_testingmode = 1; - vid_testendtime = realtime + 5.0; - - if (!VID_SetMode (modedescs[vid_line].modenum, vid_curpal)) - { - vid_testingmode = 0; - } - break; - - case 'D': - case 'd': - S_LocalSound ("misc/menu1.wav"); - firstupdate = 0; - Cvar_SetValue ("_vid_default_mode_win", vid_modenum); - break; - - default: - break; - } -} +/*
+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 the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+// vid_win.c -- Win32 video driver
+
+#include "quakedef.h"
+#include "winquake.h"
+#include "d_local.h"
+#include "resource.h"
+
+#define MAX_MODE_LIST 30
+#define VID_ROW_SIZE 3
+
+qboolean dibonly;
+
+extern int Minimized;
+
+HWND mainwindow;
+
+HWND WINAPI InitializeWindow (HINSTANCE hInstance, int nCmdShow);
+
+int DIBWidth, DIBHeight;
+qboolean DDActive;
+RECT WindowRect;
+DWORD WindowStyle, ExWindowStyle;
+
+int window_center_x, window_center_y, window_x, window_y, window_width, window_height;
+RECT window_rect;
+
+static DEVMODE gdevmode;
+static qboolean startwindowed = 0, windowed_mode_set;
+static int firstupdate = 1;
+static qboolean vid_initialized = false, vid_palettized;
+static int lockcount;
+static int vid_fulldib_on_focus_mode;
+static qboolean force_minimized, in_mode_set, is_mode0x13, force_mode_set;
+static int vid_stretched, windowed_mouse;
+static qboolean palette_changed, syscolchg, vid_mode_set, hide_window, pal_is_nostatic;
+static HICON hIcon;
+
+viddef_t vid; // global video state
+
+#define MODE_WINDOWED 0
+#define MODE_SETTABLE_WINDOW 2
+#define NO_MODE (MODE_WINDOWED - 1)
+#define MODE_FULLSCREEN_DEFAULT (MODE_WINDOWED + 3)
+
+// Note that 0 is MODE_WINDOWED
+cvar_t vid_mode = {"vid_mode","0", false};
+// Note that 0 is MODE_WINDOWED
+cvar_t _vid_default_mode = {"_vid_default_mode","0", true};
+// Note that 3 is MODE_FULLSCREEN_DEFAULT
+cvar_t _vid_default_mode_win = {"_vid_default_mode_win","3", true};
+cvar_t vid_wait = {"vid_wait","0"};
+cvar_t vid_nopageflip = {"vid_nopageflip","0", true};
+cvar_t _vid_wait_override = {"_vid_wait_override", "0", true};
+cvar_t vid_config_x = {"vid_config_x","800", true};
+cvar_t vid_config_y = {"vid_config_y","600", true};
+cvar_t vid_stretch_by_2 = {"vid_stretch_by_2","1", true};
+cvar_t _windowed_mouse = {"_windowed_mouse","0", true};
+cvar_t vid_fullscreen_mode = {"vid_fullscreen_mode","3", true};
+cvar_t vid_windowed_mode = {"vid_windowed_mode","0", true};
+cvar_t block_switch = {"block_switch","0", true};
+cvar_t vid_window_x = {"vid_window_x", "0", true};
+cvar_t vid_window_y = {"vid_window_y", "0", true};
+
+typedef struct {
+ int width;
+ int height;
+} lmode_t;
+
+lmode_t lowresmodes[] = {
+ {320, 200},
+ {320, 240},
+ {400, 300},
+ {512, 384},
+};
+
+int vid_modenum = NO_MODE;
+int vid_testingmode, vid_realmode;
+double vid_testendtime;
+int vid_default = MODE_WINDOWED;
+static int windowed_default;
+
+modestate_t modestate = MS_UNINIT;
+
+static byte *vid_surfcache;
+static int vid_surfcachesize;
+static int VID_highhunkmark;
+
+unsigned char vid_curpal[256*3];
+
+unsigned short d_8to16table[256];
+unsigned d_8to24table[256];
+
+int driver = grDETECT,mode;
+bool useWinDirect = true, useDirectDraw = true;
+MGLDC *mgldc = NULL,*memdc = NULL,*dibdc = NULL,*windc = NULL;
+
+typedef struct {
+ modestate_t type;
+ int width;
+ int height;
+ int modenum;
+ int mode13;
+ int stretched;
+ int dib;
+ int fullscreen;
+ int bpp;
+ int halfscreen;
+ char modedesc[13];
+} vmode_t;
+
+static vmode_t modelist[MAX_MODE_LIST];
+static int nummodes;
+static vmode_t *pcurrentmode;
+
+int aPage; // Current active display page
+int vPage; // Current visible display page
+int waitVRT = true; // True to wait for retrace on flip
+
+static vmode_t badmode;
+
+static byte backingbuf[48*24];
+
+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);
+
+
+/*
+================
+VID_RememberWindowPos
+================
+*/
+void VID_RememberWindowPos (void)
+{
+ RECT rect;
+
+ if (GetWindowRect (mainwindow, &rect))
+ {
+ if ((rect.left < GetSystemMetrics (SM_CXSCREEN)) &&
+ (rect.top < GetSystemMetrics (SM_CYSCREEN)) &&
+ (rect.right > 0) &&
+ (rect.bottom > 0))
+ {
+ Cvar_SetValue ("vid_window_x", (float)rect.left);
+ Cvar_SetValue ("vid_window_y", (float)rect.top);
+ }
+ }
+}
+
+
+/*
+================
+VID_CheckWindowXY
+================
+*/
+void VID_CheckWindowXY (void)
+{
+
+ if (((int)vid_window_x.value > (GetSystemMetrics (SM_CXSCREEN) - 160)) ||
+ ((int)vid_window_y.value > (GetSystemMetrics (SM_CYSCREEN) - 120)) ||
+ ((int)vid_window_x.value < 0) ||
+ ((int)vid_window_y.value < 0))
+ {
+ Cvar_SetValue ("vid_window_x", 0.0);
+ Cvar_SetValue ("vid_window_y", 0.0 );
+ }
+}
+
+
+/*
+================
+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 ();
+}
+
+
+/*
+================
+ClearAllStates
+================
+*/
+void ClearAllStates (void)
+{
+ int i;
+
+// send an up event for each key, to make sure the server clears them all
+ for (i=0 ; i<256 ; i++)
+ {
+ Key_Event (i, false);
+ }
+
+ Key_ClearStates ();
+ IN_ClearStates ();
+}
+
+
+/*
+================
+VID_CheckAdequateMem
+================
+*/
+qboolean VID_CheckAdequateMem (int width, int height)
+{
+ int tbuffersize;
+
+ tbuffersize = width * height * sizeof (*d_pzbuffer);
+
+ tbuffersize += D_SurfaceCacheForRes (width, height);
+
+// see if there's enough memory, allowing for the normal mode 0x13 pixel,
+// z, and surface buffers
+ if ((host_parms.memsize - tbuffersize + SURFCACHE_SIZE_AT_320X200 +
+ 0x10000 * 3) < minimum_memory)
+ {
+ return false; // not enough memory for mode
+ }
+
+ return true;
+}
+
+
+/*
+================
+VID_AllocBuffers
+================
+*/
+qboolean VID_AllocBuffers (int width, int height)
+{
+ int tsize, tbuffersize;
+
+ tbuffersize = width * height * sizeof (*d_pzbuffer);
+
+ tsize = D_SurfaceCacheForRes (width, height);
+
+ tbuffersize += tsize;
+
+// see if there's enough memory, allowing for the normal mode 0x13 pixel,
+// z, and surface buffers
+ if ((host_parms.memsize - tbuffersize + SURFCACHE_SIZE_AT_320X200 +
+ 0x10000 * 3) < minimum_memory)
+ {
+ Con_SafePrintf ("Not enough memory for video mode\n");
+ return false; // not enough memory for mode
+ }
+
+ vid_surfcachesize = tsize;
+
+ if (d_pzbuffer)
+ {
+ D_FlushCaches ();
+ Hunk_FreeToHighMark (VID_highhunkmark);
+ d_pzbuffer = NULL;
+ }
+
+ VID_highhunkmark = Hunk_HighMark ();
+
+ d_pzbuffer = Hunk_HighAllocName (tbuffersize, "video");
+
+ vid_surfcache = (byte *)d_pzbuffer +
+ width * height * sizeof (*d_pzbuffer);
+
+ return true;
+}
+
+
+void initFatalError(void)
+{
+ MGL_exit();
+ MGL_fatalError(MGL_errorMsg(MGL_result()));
+ exit(EXIT_FAILURE);
+}
+
+
+int VID_Suspend (MGLDC *dc,m_int flags)
+{
+
+ if (flags & MGL_DEACTIVATE)
+ {
+ // FIXME: this doesn't currently work on NT
+ if (block_switch.value && !WinNT)
+ {
+ return MGL_NO_DEACTIVATE;
+ }
+
+ S_BlockSound ();
+ S_ClearBuffer ();
+
+ IN_RestoreOriginalMouseState ();
+ CDAudio_Pause ();
+
+ // keep WM_PAINT from trying to redraw
+ in_mode_set = true;
+
+ block_drawing = true; // so we don't try to draw while switched away
+
+ return MGL_NO_SUSPEND_APP;
+ }
+ else if (flags & MGL_REACTIVATE)
+ {
+ IN_SetQuakeMouseState ();
+ // fix the leftover Alt from any Alt-Tab or the like that switched us away
+ ClearAllStates ();
+ CDAudio_Resume ();
+ S_UnblockSound ();
+
+ in_mode_set = false;
+
+ vid.recalc_refdef = 1;
+
+ block_drawing = false;
+
+ return MGL_NO_SUSPEND_APP;
+ }
+
+}
+
+
+void registerAllDispDrivers(void)
+{
+ /* Event though these driver require WinDirect, we register
+ * them so that they will still be available even if DirectDraw
+ * is present and the user has disable the high performance
+ * WinDirect modes.
+ */
+ MGL_registerDriver(MGL_VGA8NAME,VGA8_driver);
+// MGL_registerDriver(MGL_VGAXNAME,VGAX_driver);
+
+ /* Register display drivers */
+ if (useWinDirect)
+ {
+//we don't want VESA 1.X drivers MGL_registerDriver(MGL_SVGA8NAME,SVGA8_driver);
+ MGL_registerDriver(MGL_LINEAR8NAME,LINEAR8_driver);
+
+ if (!COM_CheckParm ("-novbeaf"))
+ MGL_registerDriver(MGL_ACCEL8NAME,ACCEL8_driver);
+ }
+
+ if (useDirectDraw)
+ {
+ MGL_registerDriver(MGL_DDRAW8NAME,DDRAW8_driver);
+ }
+}
+
+
+void registerAllMemDrivers(void)
+{
+ /* Register memory context drivers */
+ MGL_registerDriver(MGL_PACKED8NAME,PACKED8_driver);
+}
+
+
+void VID_InitMGLFull (HINSTANCE hInstance)
+{
+ int i, xRes, yRes, bits, vMode, lowres, curmode, temp;
+ int lowstretchedres, stretchedmode, lowstretched;
+ uchar *m;
+
+// FIXME: NT is checked for because MGL currently has a bug that causes it
+// to try to use WinDirect modes even on NT
+ if (COM_CheckParm("-nowindirect") ||
+ COM_CheckParm("-nowd") ||
+ COM_CheckParm("-novesa") ||
+ WinNT)
+ {
+ useWinDirect = false;
+ }
+
+ if (COM_CheckParm("-nodirectdraw") || COM_CheckParm("-noddraw") || COM_CheckParm("-nodd"))
+ useDirectDraw = false;
+
+ // Initialise the MGL
+ MGL_unregisterAllDrivers();
+ registerAllDispDrivers();
+ registerAllMemDrivers();
+ MGL_detectGraph(&driver,&mode);
+ m = MGL_availableModes();
+
+ if (m[0] != 0xFF)
+ {
+ lowres = lowstretchedres = 99999;
+ lowstretched = 0;
+ curmode = 0;
+
+ // find the lowest-res mode, or a mode we can stretch up to and get
+ // lowest-res that way
+ for (i = 0; m[i] != 0xFF; i++)
+ {
+ MGL_modeResolution(m[i], &xRes, &yRes,&bits);
+
+ if ((bits == 8) &&
+ (xRes <= MAXWIDTH) &&
+ (yRes <= MAXHEIGHT) &&
+ (curmode < MAX_MODE_LIST))
+ {
+ if (m[i] == grVGA_320x200x256)
+ is_mode0x13 = true;
+
+ if (!COM_CheckParm("-noforcevga"))
+ {
+ if (m[i] == grVGA_320x200x256)
+ {
+ mode = i;
+ break;
+ }
+ }
+
+ if (xRes < lowres)
+ {
+ lowres = xRes;
+ mode = i;
+ }
+
+ if ((xRes < lowstretchedres) && ((xRes >> 1) >= 320))
+ {
+ lowstretchedres = xRes >> 1;
+ stretchedmode = i;
+ }
+ }
+
+ curmode++;
+ }
+
+ // if there's a mode we can stretch by 2 up to, thereby effectively getting
+ // a lower-res mode than the lowest-res real but still at least 320x200, that
+ // will be our default mode
+ if (lowstretchedres < lowres)
+ {
+ mode = stretchedmode;
+ lowres = lowstretchedres;
+ lowstretched = 1;
+ }
+
+ // build the mode list, leaving room for the low-res stretched mode, if any
+ nummodes++; // leave room for default mode
+
+ for (i = 0; m[i] != 0xFF; i++)
+ {
+ MGL_modeResolution(m[i], &xRes, &yRes,&bits);
+
+ if ((bits == 8) &&
+ (xRes <= MAXWIDTH) &&
+ (yRes <= MAXHEIGHT) &&
+ (nummodes < MAX_MODE_LIST))
+ {
+ if (i == mode)
+ {
+ if (lowstretched)
+ {
+ stretchedmode = nummodes;
+ curmode = nummodes++;
+ }
+ else
+ {
+ curmode = MODE_FULLSCREEN_DEFAULT;
+ }
+ }
+ else
+ {
+ curmode = nummodes++;
+ }
+
+ modelist[curmode].type = MS_FULLSCREEN;
+ modelist[curmode].width = xRes;
+ modelist[curmode].height = yRes;
+ sprintf (modelist[curmode].modedesc, "%dx%d", xRes, yRes);
+
+ if (m[i] == grVGA_320x200x256)
+ modelist[curmode].mode13 = 1;
+ else
+ modelist[curmode].mode13 = 0;
+
+ modelist[curmode].modenum = m[i];
+ modelist[curmode].stretched = 0;
+ modelist[curmode].dib = 0;
+ modelist[curmode].fullscreen = 1;
+ modelist[curmode].halfscreen = 0;
+ modelist[curmode].bpp = 8;
+ }
+ }
+
+ if (lowstretched)
+ {
+ modelist[MODE_FULLSCREEN_DEFAULT] = modelist[stretchedmode];
+ modelist[MODE_FULLSCREEN_DEFAULT].stretched = 1;
+ modelist[MODE_FULLSCREEN_DEFAULT].width >>= 1;
+ modelist[MODE_FULLSCREEN_DEFAULT].height >>= 1;
+ sprintf (modelist[MODE_FULLSCREEN_DEFAULT].modedesc, "%dx%d",
+ modelist[MODE_FULLSCREEN_DEFAULT].width,
+ modelist[MODE_FULLSCREEN_DEFAULT].height);
+ }
+
+ vid_default = MODE_FULLSCREEN_DEFAULT;
+
+ temp = m[0];
+
+ if (!MGL_init(&driver, &temp, ""))
+ {
+ initFatalError();
+ }
+ }
+
+ MGL_setSuspendAppCallback(VID_Suspend);
+}
+
+
+MGLDC *createDisplayDC(int forcemem)
+/****************************************************************************
+*
+* Function: createDisplayDC
+* Returns: Pointer to the MGL device context to use for the application
+*
+* Description: Initialises the MGL and creates an appropriate display
+* device context to be used by the GUI. This creates and
+* apropriate device context depending on the system being
+* compile for, and should be the only place where system
+* specific code is required.
+*
+****************************************************************************/
+{
+ MGLDC *dc;
+ pixel_format_t pf;
+ int npages;
+
+ // Start the specified video mode
+ if (!MGL_changeDisplayMode(mode))
+ initFatalError();
+
+ npages = MGL_availablePages(mode);
+
+ if (npages > 3)
+ npages = 3;
+
+ if (!COM_CheckParm ("-notriplebuf"))
+ {
+ if (npages > 2)
+ {
+ npages = 2;
+ }
+ }
+
+ if ((dc = MGL_createDisplayDC(npages)) == NULL)
+ return NULL;
+
+ if (!forcemem && (MGL_surfaceAccessType(dc)) == MGL_LINEAR_ACCESS && (dc->mi.maxPage > 0))
+ {
+ MGL_makeCurrentDC(dc);
+ memdc = NULL;
+ }
+ else
+ {
+ // Set up for blitting from a memory buffer
+ memdc = MGL_createMemoryDC(MGL_sizex(dc)+1,MGL_sizey(dc)+1,8,&pf);
+ MGL_makeCurrentDC(memdc);
+ }
+
+ // Enable page flipping even for even for blitted surfaces
+ if (forcemem)
+ {
+ vid.numpages = 1;
+ }
+ else
+ {
+ vid.numpages = dc->mi.maxPage + 1;
+
+ if (vid.numpages > 1)
+ {
+ // Set up for page flipping
+ MGL_setActivePage(dc, aPage = 1);
+ MGL_setVisualPage(dc, vPage = 0, false);
+ }
+
+ if (vid.numpages > 3)
+ vid.numpages = 3;
+ }
+
+ if (vid.numpages == 2)
+ waitVRT = true;
+ else
+ waitVRT = false;
+
+ return dc;
+}
+
+
+void VID_InitMGLDIB (HINSTANCE hInstance)
+{
+ WNDCLASS wc;
+ HDC hdc;
+ int i;
+
+ hIcon = LoadIcon (hInstance, MAKEINTRESOURCE (IDI_ICON2));
+
+ /* 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");
+
+ /* Find the size for the DIB window */
+ /* Initialise the MGL for windowed operation */
+ MGL_setAppInstance(hInstance);
+ registerAllMemDrivers();
+ MGL_initWindowed("");
+
+ modelist[0].type = MS_WINDOWED;
+ modelist[0].width = 320;
+ modelist[0].height = 240;
+ strcpy (modelist[0].modedesc, "320x240");
+ modelist[0].mode13 = 0;
+ modelist[0].modenum = MODE_WINDOWED;
+ modelist[0].stretched = 0;
+ modelist[0].dib = 1;
+ modelist[0].fullscreen = 0;
+ modelist[0].halfscreen = 0;
+ modelist[0].bpp = 8;
+
+ modelist[1].type = MS_WINDOWED;
+ modelist[1].width = 640;
+ modelist[1].height = 480;
+ strcpy (modelist[1].modedesc, "640x480");
+ modelist[1].mode13 = 0;
+ modelist[1].modenum = MODE_WINDOWED + 1;
+ modelist[1].stretched = 1;
+ modelist[1].dib = 1;
+ modelist[1].fullscreen = 0;
+ modelist[1].halfscreen = 0;
+ modelist[1].bpp = 8;
+
+ modelist[2].type = MS_WINDOWED;
+ modelist[2].width = 800;
+ modelist[2].height = 600;
+ strcpy (modelist[2].modedesc, "800x600");
+ modelist[2].mode13 = 0;
+ modelist[2].modenum = MODE_WINDOWED + 2;
+ modelist[2].stretched = 1;
+ modelist[2].dib = 1;
+ modelist[2].fullscreen = 0;
+ modelist[2].halfscreen = 0;
+ modelist[2].bpp = 8;
+
+// automatically stretch the default mode up if > 640x480 desktop resolution
+ hdc = GetDC(NULL);
+
+ if ((GetDeviceCaps(hdc, HORZRES) > 640) && !COM_CheckParm("-noautostretch"))
+ {
+ vid_default = MODE_WINDOWED + 1;
+ }
+ else
+ {
+ vid_default = MODE_WINDOWED;
+ }
+
+ windowed_default = vid_default;
+
+ ReleaseDC(NULL,hdc);
+
+ nummodes = 3; // reserve space for windowed mode
+
+ DDActive = 0;
+}
+
+
+/*
+=================
+VID_InitFullDIB
+=================
+*/
+void VID_InitFullDIB (HINSTANCE hInstance)
+{
+ DEVMODE devmode;
+ int i, j, modenum, cmodes, existingmode, originalnummodes, lowestres;
+ int numlowresmodes, bpp, done;
+ int cstretch, istretch, mstretch;
+ BOOL stat;
+
+// enumerate 8 bpp modes
+ originalnummodes = nummodes;
+ modenum = 0;
+ lowestres = 99999;
+
+ do
+ {
+ stat = EnumDisplaySettings (NULL, modenum, &devmode);
+
+ if ((devmode.dmBitsPerPel == 8) &&
+ (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].mode13 = 0;
+ modelist[nummodes].stretched = 0;
+ modelist[nummodes].halfscreen = 0;
+ modelist[nummodes].dib = 1;
+ modelist[nummodes].fullscreen = 1;
+ modelist[nummodes].bpp = devmode.dmBitsPerPel;
+ sprintf (modelist[nummodes].modedesc, "%dx%d",
+ devmode.dmPelsWidth, devmode.dmPelsHeight);
+
+ // 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;
+ sprintf (modelist[nummodes].modedesc, "%dx%d",
+ modelist[nummodes].width,
+ modelist[nummodes].height);
+ }
+ }
+
+ for (i=originalnummodes, existingmode = 0 ; i<nummodes ; i++)
+ {
+ if ((modelist[nummodes].width == modelist[i].width) &&
+ (modelist[nummodes].height == modelist[i].height))
+ {
+ existingmode = 1;
+ break;
+ }
+ }
+
+ if (!existingmode)
+ {
+ if (modelist[nummodes].width < lowestres)
+ lowestres = modelist[nummodes].width;
+
+ nummodes++;
+ }
+ }
+ }
+
+ modenum++;
+ } while (stat);
+
+// see if any of them were actually settable; if so, this is our mode list,
+// else enumerate all modes; our mode list is whichever ones are settable
+// with > 8 bpp
+ if (nummodes == originalnummodes)
+ {
+ modenum = 0;
+ lowestres = 99999;
+
+ Con_SafePrintf ("No 8-bpp fullscreen DIB modes found\n");
+
+ do
+ {
+ stat = EnumDisplaySettings (NULL, modenum, &devmode);
+
+ if ((((devmode.dmPelsWidth <= MAXWIDTH) &&
+ (devmode.dmPelsHeight <= MAXHEIGHT)) ||
+ (!COM_CheckParm("-noadjustaspect") &&
+ (devmode.dmPelsWidth <= (MAXWIDTH*2)) &&
+ (devmode.dmPelsWidth > (devmode.dmPelsHeight*2)))) &&
+ (nummodes < MAX_MODE_LIST) &&
+ (devmode.dmBitsPerPel > 8))
+ {
+ 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].mode13 = 0;
+ modelist[nummodes].stretched = 0;
+ modelist[nummodes].halfscreen = 0;
+ modelist[nummodes].dib = 1;
+ modelist[nummodes].fullscreen = 1;
+ modelist[nummodes].bpp = devmode.dmBitsPerPel;
+ sprintf (modelist[nummodes].modedesc, "%dx%d",
+ devmode.dmPelsWidth, devmode.dmPelsHeight);
+
+ // 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*2))
+ {
+ modelist[nummodes].width >>= 1;
+ modelist[nummodes].halfscreen = 1;
+ sprintf (modelist[nummodes].modedesc, "%dx%d",
+ modelist[nummodes].width,
+ modelist[nummodes].height);
+ }
+ }
+
+ for (i=originalnummodes, existingmode = 0 ; i<nummodes ; i++)
+ {
+ if ((modelist[nummodes].width == modelist[i].width) &&
+ (modelist[nummodes].height == modelist[i].height))
+ {
+ // pick the lowest available bpp
+ if (modelist[nummodes].bpp < modelist[i].bpp)
+ modelist[i] = modelist[nummodes];
+
+ existingmode = 1;
+ break;
+ }
+ }
+
+ if (!existingmode)
+ {
+ if (modelist[nummodes].width < lowestres)
+ lowestres = modelist[nummodes].width;
+
+ nummodes++;
+ }
+ }
+ }
+
+ modenum++;
+ } while (stat);
+ }
+
+// see if there are any low-res modes that aren't being reported
+ numlowresmodes = sizeof(lowresmodes) / sizeof(lowresmodes[0]);
+ bpp = 8;
+ done = 0;
+
+// first make sure the driver doesn't just answer yes to all tests
+ devmode.dmBitsPerPel = 8;
+ devmode.dmPelsWidth = 42;
+ devmode.dmPelsHeight = 37;
+ devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
+
+ if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) ==
+ DISP_CHANGE_SUCCESSFUL)
+ {
+ done = 1;
+ }
+
+ while (!done)
+ {
+ 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].mode13 = 0;
+ modelist[nummodes].stretched = 0;
+ modelist[nummodes].halfscreen = 0;
+ modelist[nummodes].dib = 1;
+ modelist[nummodes].fullscreen = 1;
+ modelist[nummodes].bpp = devmode.dmBitsPerPel;
+ sprintf (modelist[nummodes].modedesc, "%dx%d",
+ devmode.dmPelsWidth, devmode.dmPelsHeight);
+
+ // we only want the lowest-bpp version of each mode
+ 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)
+ {
+ if (modelist[nummodes].width < lowestres)
+ lowestres = modelist[nummodes].width;
+
+ nummodes++;
+ }
+ }
+ }
+
+ switch (bpp)
+ {
+ case 8:
+ bpp = 16;
+ break;
+
+ case 16:
+ bpp = 32;
+ break;
+
+ case 32:
+ done = 1;
+ break;
+ }
+ }
+
+// now add the lowest stretch-by-2 pseudo-modes between 320-wide
+// (inclusive) and lowest real res (not inclusive)
+// don't bother if we have a real VGA mode 0x13 mode
+ if (!is_mode0x13)
+ {
+ for (i=originalnummodes, cstretch=0 ; i<nummodes ; i++)
+ {
+ if (((modelist[i].width >> 1) < lowestres) &&
+ ((modelist[i].width >> 1) >= 320))
+ {
+ lowestres = modelist[i].width >> 1;
+ cstretch = 1;
+ mstretch = i;
+ }
+ }
+
+ if ((nummodes + cstretch) > MAX_MODE_LIST)
+ cstretch = MAX_MODE_LIST - nummodes;
+
+ if (cstretch > 0)
+ {
+ for (i=(nummodes-1) ; i>=originalnummodes ; i--)
+ modelist[i+cstretch] = modelist[i];
+
+ nummodes += cstretch;
+ istretch = originalnummodes;
+
+ modelist[istretch] = modelist[mstretch];
+ modelist[istretch].width >>= 1;
+ modelist[istretch].height >>= 1;
+ modelist[istretch].stretched = 1;
+ sprintf (modelist[istretch].modedesc, "%dx%d",
+ modelist[istretch].width, modelist[istretch].height);
+ }
+ }
+
+ if (nummodes != originalnummodes)
+ vid_default = MODE_FULLSCREEN_DEFAULT;
+ else
+ Con_SafePrintf ("No fullscreen DIB modes found\n");
+}
+
+
+/*
+=================
+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_CheckModedescFixup
+=================
+*/
+void VID_CheckModedescFixup (int mode)
+{
+ int x, y, stretch;
+
+ if (mode == MODE_SETTABLE_WINDOW)
+ {
+ modelist[mode].stretched = (int)vid_stretch_by_2.value;
+ stretch = modelist[mode].stretched;
+
+ if (vid_config_x.value < (320 << stretch))
+ vid_config_x.value = 320 << stretch;
+
+ if (vid_config_y.value < (200 << stretch))
+ vid_config_y.value = 200 << stretch;
+
+ x = (int)vid_config_x.value;
+ y = (int)vid_config_y.value;
+ sprintf (modelist[mode].modedesc, "%dx%d", x, y);
+ modelist[mode].width = x;
+ modelist[mode].height = y;
+ }
+}
+
+
+/*
+=================
+VID_GetModeDescriptionMemCheck
+=================
+*/
+char *VID_GetModeDescriptionMemCheck (int mode)
+{
+ char *pinfo;
+ vmode_t *pv;
+
+ if ((mode < 0) || (mode >= nummodes))
+ return NULL;
+
+ VID_CheckModedescFixup (mode);
+
+ pv = VID_GetModePtr (mode);
+ pinfo = pv->modedesc;
+
+ if (VID_CheckAdequateMem (pv->width, pv->height))
+ {
+ return pinfo;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+
+/*
+=================
+VID_GetModeDescription
+=================
+*/
+char *VID_GetModeDescription (int mode)
+{
+ char *pinfo;
+ vmode_t *pv;
+
+ if ((mode < 0) || (mode >= nummodes))
+ return NULL;
+
+ VID_CheckModedescFixup (mode);
+
+ pv = VID_GetModePtr (mode);
+ pinfo = pv->modedesc;
+ return pinfo;
+}
+
+
+/*
+=================
+VID_GetModeDescription2
+
+Tacks on "windowed" or "fullscreen"
+=================
+*/
+char *VID_GetModeDescription2 (int mode)
+{
+ static char pinfo[40];
+ vmode_t *pv;
+
+ if ((mode < 0) || (mode >= nummodes))
+ return NULL;
+
+ VID_CheckModedescFixup (mode);
+
+ pv = VID_GetModePtr (mode);
+
+ if (modelist[mode].type == MS_FULLSCREEN)
+ {
+ sprintf(pinfo,"%s fullscreen", pv->modedesc);
+ }
+ else if (modelist[mode].type == MS_FULLDIB)
+ {
+ sprintf(pinfo,"%s fullscreen", pv->modedesc);
+ }
+ else
+ {
+ sprintf(pinfo, "%s windowed", pv->modedesc);
+ }
+
+ 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;
+
+ VID_CheckModedescFixup (mode);
+
+ pv = VID_GetModePtr (mode);
+ if (modelist[mode].type == MS_FULLSCREEN)
+ {
+ sprintf(pinfo,"%s fullscreen %s",pv->modedesc,
+ MGL_modeDriverName(pv->modenum));
+ }
+ else if (modelist[mode].type == MS_FULLDIB)
+ {
+ sprintf(pinfo,"%s fullscreen DIB", pv->modedesc);
+ }
+ else
+ {
+ sprintf(pinfo, "%s windowed", pv->modedesc);
+ }
+
+ return pinfo;
+}
+
+
+void DestroyDIBWindow (void)
+{
+
+ if (modestate == MS_WINDOWED)
+ {
+ // destroy the associated MGL DC's; the window gets reused
+ if (windc)
+ MGL_destroyDC(windc);
+ if (dibdc)
+ MGL_destroyDC(dibdc);
+ windc = dibdc = NULL;
+ }
+}
+
+
+void DestroyFullscreenWindow (void)
+{
+
+ if (modestate == MS_FULLSCREEN)
+ {
+ // destroy the existing fullscreen mode and DC's
+ if (mgldc)
+ MGL_destroyDC (mgldc);
+ if (memdc)
+ MGL_destroyDC (memdc);
+ mgldc = memdc = NULL;
+ }
+}
+
+
+
+void DestroyFullDIBWindow (void)
+{
+ if (modestate == MS_FULLDIB)
+ {
+ ChangeDisplaySettings (NULL, CDS_FULLSCREEN);
+
+ // Destroy the fullscreen DIB window and associated MGL DC's
+ if (windc)
+ MGL_destroyDC(windc);
+ if (dibdc)
+ MGL_destroyDC(dibdc);
+ windc = dibdc = NULL;
+ }
+}
+
+
+qboolean VID_SetWindowedMode (int modenum)
+{
+ HDC hdc;
+ pixel_format_t pf;
+ qboolean stretched;
+ int lastmodestate;
+ LONG wlong;
+
+ if (!windowed_mode_set)
+ {
+ if (COM_CheckParm ("-resetwinpos"))
+ {
+ Cvar_SetValue ("vid_window_x", 0.0);
+ Cvar_SetValue ("vid_window_y", 0.0);
+ }
+
+ windowed_mode_set;
+ }
+
+ VID_CheckModedescFixup (modenum);
+
+ DDActive = 0;
+ lastmodestate = modestate;
+
+ DestroyFullscreenWindow ();
+ DestroyFullDIBWindow ();
+
+ if (windc)
+ MGL_destroyDC(windc);
+ if (dibdc)
+ MGL_destroyDC(dibdc);
+ windc = dibdc = NULL;
+
+// KJB: Signal to the MGL that we are going back to windowed mode
+ if (!MGL_changeDisplayMode(grWINDOWED))
+ initFatalError();
+
+ WindowRect.top = WindowRect.left = 0;
+
+ WindowRect.right = modelist[modenum].width;
+ WindowRect.bottom = modelist[modenum].height;
+ stretched = modelist[modenum].stretched;
+
+ DIBWidth = modelist[modenum].width;
+ DIBHeight = modelist[modenum].height;
+
+ if (stretched)
+ {
+ DIBWidth >>= 1;
+ DIBHeight >>= 1;
+ }
+
+ WindowStyle = WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_SYSMENU |
+ WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CLIPSIBLINGS |
+ WS_CLIPCHILDREN;
+ ExWindowStyle = 0;
+ AdjustWindowRectEx(&WindowRect, WindowStyle, FALSE, 0);
+
+// the first time we're called to set the mode, create the window we'll use
+// for the rest of the session
+ if (!vid_mode_set)
+ {
+ mainwindow = CreateWindowEx (
+ ExWindowStyle,
+ "WinQuake",
+ "WinQuake",
+ WindowStyle,
+ 0, 0,
+ WindowRect.right - WindowRect.left,
+ WindowRect.bottom - WindowRect.top,
+ NULL,
+ NULL,
+ global_hInstance,
+ NULL);
+
+ if (!mainwindow)
+ Sys_Error ("Couldn't create DIB window");
+
+ // tell MGL to use this window for fullscreen modes
+ MGL_registerFullScreenWindow (mainwindow);
+
+ vid_mode_set = true;
+ }
+ else
+ {
+ SetWindowLong(mainwindow, GWL_STYLE, WindowStyle | WS_VISIBLE);
+ SetWindowLong(mainwindow, GWL_EXSTYLE, ExWindowStyle);
+ }
+
+ if (!SetWindowPos (mainwindow,
+ NULL,
+ 0, 0,
+ WindowRect.right - WindowRect.left,
+ WindowRect.bottom - WindowRect.top,
+ SWP_NOCOPYBITS | SWP_NOZORDER |
+ SWP_HIDEWINDOW))
+ {
+ Sys_Error ("Couldn't resize DIB window");
+ }
+
+ if (hide_window)
+ return true;
+
+// position and show the DIB window
+ VID_CheckWindowXY ();
+ SetWindowPos (mainwindow, NULL, (int)vid_window_x.value,
+ (int)vid_window_y.value, 0, 0,
+ SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME);
+
+ if (force_minimized)
+ ShowWindow (mainwindow, SW_MINIMIZE);
+ else
+ ShowWindow (mainwindow, SW_SHOWDEFAULT);
+
+ UpdateWindow (mainwindow);
+
+ modestate = MS_WINDOWED;
+ vid_fulldib_on_focus_mode = 0;
+
+// 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(mainwindow);
+ PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS);
+ ReleaseDC(mainwindow, hdc);
+
+ /* Create the MGL window DC and the MGL memory DC */
+ if ((windc = MGL_createWindowedDC(mainwindow)) == NULL)
+ MGL_fatalError("Unable to create Windowed DC!");
+
+ if ((dibdc = MGL_createMemoryDC(DIBWidth,DIBHeight,8,&pf)) == NULL)
+ MGL_fatalError("Unable to create Memory DC!");
+
+ MGL_makeCurrentDC(dibdc);
+
+ vid.buffer = vid.conbuffer = vid.direct = dibdc->surface;
+ vid.rowbytes = vid.conrowbytes = dibdc->mi.bytesPerLine;
+ vid.numpages = 1;
+ vid.maxwarpwidth = WARP_WIDTH;
+ vid.maxwarpheight = WARP_HEIGHT;
+ vid.height = vid.conheight = DIBHeight;
+ vid.width = vid.conwidth = DIBWidth;
+ vid.aspect = ((float)vid.height / (float)vid.width) *
+ (320.0 / 240.0);
+
+ vid_stretched = stretched;
+
+ SendMessage (mainwindow, WM_SETICON, (WPARAM)TRUE, (LPARAM)hIcon);
+ SendMessage (mainwindow, WM_SETICON, (WPARAM)FALSE, (LPARAM)hIcon);
+
+ return true;
+}
+
+
+qboolean VID_SetFullscreenMode (int modenum)
+{
+
+ DDActive = 1;
+
+ DestroyDIBWindow ();
+ DestroyFullDIBWindow ();
+
+ mode = modelist[modenum].modenum;
+
+ // Destroy old DC's, resetting back to fullscreen mode
+ if (mgldc)
+ MGL_destroyDC (mgldc);
+ if (memdc)
+ MGL_destroyDC (memdc);
+ mgldc = memdc = NULL;
+
+ if ((mgldc = createDisplayDC (modelist[modenum].stretched ||
+ (int)vid_nopageflip.value)) == NULL)
+ {
+ return false;
+ }
+
+ modestate = MS_FULLSCREEN;
+ vid_fulldib_on_focus_mode = 0;
+
+ vid.buffer = vid.conbuffer = vid.direct = NULL;
+ vid.maxwarpwidth = WARP_WIDTH;
+ vid.maxwarpheight = WARP_HEIGHT;
+ DIBHeight = vid.height = vid.conheight = modelist[modenum].height;
+ DIBWidth = vid.width = vid.conwidth = modelist[modenum].width;
+ vid.aspect = ((float)vid.height / (float)vid.width) *
+ (320.0 / 240.0);
+
+ vid_stretched = modelist[modenum].stretched;
+
+// needed because we're not getting WM_MOVE messages fullscreen on NT
+ window_x = 0;
+ window_y = 0;
+
+// set the large icon, so the Quake icon will show up in the taskbar
+ SendMessage (mainwindow, WM_SETICON, (WPARAM)1, (LPARAM)hIcon);
+ SendMessage (mainwindow, WM_SETICON, (WPARAM)0, (LPARAM)hIcon);
+
+// shouldn't be needed, but Kendall needs to let us get the activation
+// message for this not to be needed on NT
+ AppActivate (true, false);
+
+ return true;
+}
+
+
+qboolean VID_SetFullDIBMode (int modenum)
+{
+ HDC hdc;
+ pixel_format_t pf;
+ int lastmodestate;
+
+ DDActive = 0;
+
+ DestroyFullscreenWindow ();
+ DestroyDIBWindow ();
+
+ if (windc)
+ MGL_destroyDC(windc);
+ if (dibdc)
+ MGL_destroyDC(dibdc);
+ windc = dibdc = NULL;
+
+// KJB: Signal to the MGL that we are going back to windowed mode
+ if (!MGL_changeDisplayMode(grWINDOWED))
+ initFatalError();
+
+ gdevmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
+ gdevmode.dmBitsPerPel = modelist[modenum].bpp;
+ gdevmode.dmPelsWidth = modelist[modenum].width << modelist[modenum].stretched <<
+ modelist[modenum].halfscreen;
+ gdevmode.dmPelsHeight = modelist[modenum].height << modelist[modenum].stretched;
+ 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;
+ vid_fulldib_on_focus_mode = modenum;
+
+ WindowRect.top = WindowRect.left = 0;
+
+ hdc = GetDC(NULL);
+
+ WindowRect.right = modelist[modenum].width << modelist[modenum].stretched;
+ WindowRect.bottom = modelist[modenum].height << modelist[modenum].stretched;
+
+ ReleaseDC(NULL,hdc);
+
+ DIBWidth = modelist[modenum].width;
+ DIBHeight = modelist[modenum].height;
+
+ WindowStyle = WS_POPUP | WS_SYSMENU | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
+ ExWindowStyle = 0;
+ AdjustWindowRectEx(&WindowRect, WindowStyle, FALSE, 0);
+
+ SetWindowLong(mainwindow, GWL_STYLE, WindowStyle | WS_VISIBLE);
+ SetWindowLong(mainwindow, GWL_EXSTYLE, ExWindowStyle);
+
+ if (!SetWindowPos (mainwindow,
+ NULL,
+ 0, 0,
+ WindowRect.right - WindowRect.left,
+ WindowRect.bottom - WindowRect.top,
+ SWP_NOCOPYBITS | SWP_NOZORDER))
+ {
+ Sys_Error ("Couldn't resize DIB window");
+ }
+
+// position and show the DIB window
+ SetWindowPos (mainwindow, HWND_TOPMOST, 0, 0, 0, 0,
+ SWP_NOSIZE | SWP_SHOWWINDOW | SWP_DRAWFRAME);
+ ShowWindow (mainwindow, SW_SHOWDEFAULT);
+ UpdateWindow (mainwindow);
+
+ // 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(mainwindow);
+ PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS);
+ ReleaseDC(mainwindow, hdc);
+
+ /* Create the MGL window DC and the MGL memory DC */
+ if ((windc = MGL_createWindowedDC(mainwindow)) == NULL)
+ MGL_fatalError("Unable to create Fullscreen DIB DC!");
+
+ if ((dibdc = MGL_createMemoryDC(DIBWidth,DIBHeight,8,&pf)) == NULL)
+ MGL_fatalError("Unable to create Memory DC!");
+
+ MGL_makeCurrentDC(dibdc);
+
+ vid.buffer = vid.conbuffer = vid.direct = dibdc->surface;
+ vid.rowbytes = vid.conrowbytes = dibdc->mi.bytesPerLine;
+ vid.numpages = 1;
+ vid.maxwarpwidth = WARP_WIDTH;
+ vid.maxwarpheight = WARP_HEIGHT;
+ vid.height = vid.conheight = DIBHeight;
+ vid.width = vid.conwidth = DIBWidth;
+ vid.aspect = ((float)vid.height / (float)vid.width) *
+ (320.0 / 240.0);
+
+ vid_stretched = modelist[modenum].stretched;
+
+// needed because we're not getting WM_MOVE messages fullscreen on NT
+ window_x = 0;
+ window_y = 0;
+
+ return true;
+}
+
+
+void VID_RestoreOldMode (int original_mode)
+{
+ static qboolean inerror = false;
+
+ if (inerror)
+ return;
+
+ in_mode_set = false;
+ inerror = true;
+
+// make sure mode set happens (video mode changes)
+ vid_modenum = original_mode - 1;
+
+ if (!VID_SetMode (original_mode, vid_curpal))
+ {
+ vid_modenum = MODE_WINDOWED - 1;
+
+ if (!VID_SetMode (windowed_default, vid_curpal))
+ Sys_Error ("Can't set any video mode");
+ }
+
+ inerror = false;
+}
+
+
+void VID_SetDefaultMode (void)
+{
+
+ if (vid_initialized)
+ VID_SetMode (0, vid_curpal);
+
+ IN_DeactivateMouse ();
+}
+
+
+int VID_SetMode (int modenum, unsigned char *palette)
+{
+ int original_mode, temp, dummy;
+ qboolean stat;
+ MSG msg;
+ HDC hdc;
+
+ while ((modenum >= nummodes) || (modenum < 0))
+ {
+ if (vid_modenum == NO_MODE)
+ {
+ if (modenum == vid_default)
+ {
+ modenum = windowed_default;
+ }
+ else
+ {
+ modenum = vid_default;
+ }
+
+ Cvar_SetValue ("vid_mode", (float)modenum);
+ }
+ else
+ {
+ Cvar_SetValue ("vid_mode", (float)vid_modenum);
+ return 0;
+ }
+ }
+
+ if (!force_mode_set && (modenum == vid_modenum))
+ return true;
+
+// so Con_Printfs don't mess us up by forcing vid and snd updates
+ temp = scr_disabled_for_loading;
+ scr_disabled_for_loading = true;
+ in_mode_set = true;
+
+ CDAudio_Pause ();
+ S_ClearBuffer ();
+
+ 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)
+ {
+ 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
+ {
+ stat = VID_SetFullscreenMode(modenum);
+ IN_ActivateMouse ();
+ IN_HideMouse ();
+ }
+
+ window_width = vid.width << vid_stretched;
+ window_height = vid.height << vid_stretched;
+ VID_UpdateWindowStatus ();
+
+ CDAudio_Resume ();
+ scr_disabled_for_loading = temp;
+
+ if (!stat)
+ {
+ VID_RestoreOldMode (original_mode);
+ return false;
+ }
+
+ if (hide_window)
+ return true;
+
+// 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
+ if (!force_minimized)
+ SetForegroundWindow (mainwindow);
+
+ hdc = GetDC(NULL);
+
+ if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)
+ vid_palettized = true;
+ else
+ vid_palettized = false;
+
+ VID_SetPalette (palette);
+
+ ReleaseDC(NULL,hdc);
+
+ vid_modenum = modenum;
+ Cvar_SetValue ("vid_mode", (float)vid_modenum);
+
+ if (!VID_AllocBuffers (vid.width, vid.height))
+ {
+ // couldn't get memory for this mode; try to fall back to previous mode
+ VID_RestoreOldMode (original_mode);
+ return false;
+ }
+
+ D_InitCaches (vid_surfcache, vid_surfcachesize);
+
+ while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
+ {
+ TranslateMessage (&msg);
+ DispatchMessage (&msg);
+ }
+
+ Sleep (100);
+
+ if (!force_minimized)
+ {
+ 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 ("%s\n", VID_GetModeDescription (vid_modenum));
+
+ VID_SetPalette (palette);
+
+ in_mode_set = false;
+ vid.recalc_refdef = 1;
+
+ return true;
+}
+
+void VID_LockBuffer (void)
+{
+
+ if (dibdc)
+ return;
+
+ lockcount++;
+
+ if (lockcount > 1)
+ return;
+
+ MGL_beginDirectAccess();
+
+ if (memdc)
+ {
+ // Update surface pointer for linear access modes
+ vid.buffer = vid.conbuffer = vid.direct = memdc->surface;
+ vid.rowbytes = vid.conrowbytes = memdc->mi.bytesPerLine;
+ }
+ else if (mgldc)
+ {
+ // Update surface pointer for linear access modes
+ vid.buffer = vid.conbuffer = vid.direct = mgldc->surface;
+ vid.rowbytes = vid.conrowbytes = mgldc->mi.bytesPerLine;
+ }
+
+ if (r_dowarp)
+ d_viewbuffer = r_warpbuffer;
+ else
+ d_viewbuffer = (void *)(byte *)vid.buffer;
+
+ if (r_dowarp)
+ screenwidth = WARP_WIDTH;
+ else
+ screenwidth = vid.rowbytes;
+
+ if (lcd_x.value)
+ screenwidth <<= 1;
+}
+
+
+void VID_UnlockBuffer (void)
+{
+ if (dibdc)
+ return;
+
+ lockcount--;
+
+ if (lockcount > 0)
+ return;
+
+ if (lockcount < 0)
+ Sys_Error ("Unbalanced unlock");
+
+ MGL_endDirectAccess();
+
+// to turn up any unlocked accesses
+ vid.buffer = vid.conbuffer = vid.direct = d_viewbuffer = NULL;
+
+}
+
+
+int VID_ForceUnlockedAndReturnState (void)
+{
+ int lk;
+
+ if (!lockcount)
+ return 0;
+
+ lk = lockcount;
+
+ if (dibdc)
+ {
+ lockcount = 0;
+ }
+ else
+ {
+ lockcount = 1;
+ VID_UnlockBuffer ();
+ }
+
+ return lk;
+}
+
+
+void VID_ForceLockState (int lk)
+{
+
+ if (!dibdc && lk)
+ {
+ lockcount = 0;
+ VID_LockBuffer ();
+ }
+
+ lockcount = lk;
+}
+
+
+void VID_SetPalette (unsigned char *palette)
+{
+ INT i;
+ palette_t pal[256];
+ HDC hdc;
+
+ if (!Minimized)
+ {
+ palette_changed = true;
+
+ // make sure we have the static colors if we're the active app
+ hdc = GetDC(NULL);
+
+ if (vid_palettized && ActiveApp)
+ {
+ if (GetSystemPaletteUse(hdc) == SYSPAL_STATIC)
+ {
+ // switch to SYSPAL_NOSTATIC and remap the colors
+ SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC);
+ syscolchg = true;
+ pal_is_nostatic = true;
+ }
+ }
+
+ ReleaseDC(NULL,hdc);
+
+ // Translate the palette values to an MGL palette array and
+ // set the values.
+ for (i = 0; i < 256; i++)
+ {
+ pal[i].red = palette[i*3];
+ pal[i].green = palette[i*3+1];
+ pal[i].blue = palette[i*3+2];
+ }
+
+ if (DDActive)
+ {
+ if (!mgldc)
+ return;
+
+ MGL_setPalette(mgldc,pal,256,0);
+ MGL_realizePalette(mgldc,256,0,false);
+ if (memdc)
+ MGL_setPalette(memdc,pal,256,0);
+ }
+ else
+ {
+ if (!windc)
+ return;
+
+ MGL_setPalette(windc,pal,256,0);
+ MGL_realizePalette(windc,256,0,false);
+ if (dibdc)
+ {
+ MGL_setPalette(dibdc,pal,256,0);
+ MGL_realizePalette(dibdc,256,0,false);
+ }
+ }
+ }
+
+ memcpy (vid_curpal, palette, sizeof(vid_curpal));
+
+ if (syscolchg)
+ {
+ PostMessage (HWND_BROADCAST, WM_SYSCOLORCHANGE, (WPARAM)0, (LPARAM)0);
+ syscolchg = false;
+ }
+}
+
+
+void VID_ShiftPalette (unsigned char *palette)
+{
+ VID_SetPalette (palette);
+}
+
+
+/*
+=================
+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 modenum;
+
+ modenum = Q_atoi (Cmd_Argv(1));
+
+ Con_Printf ("%s\n", VID_GetExtModeDescription (modenum));
+}
+
+
+/*
+=================
+VID_DescribeModes_f
+=================
+*/
+void VID_DescribeModes_f (void)
+{
+ int i, lnummodes;
+ char *pinfo;
+ qboolean na;
+ vmode_t *pv;
+
+ na = false;
+
+ lnummodes = VID_NumModes ();
+
+ for (i=0 ; i<lnummodes ; i++)
+ {
+ pv = VID_GetModePtr (i);
+ pinfo = VID_GetExtModeDescription (i);
+
+ if (VID_CheckAdequateMem (pv->width, pv->height))
+ {
+ Con_Printf ("%2d: %s\n", i, pinfo);
+ }
+ else
+ {
+ Con_Printf ("**: %s\n", pinfo);
+ na = true;
+ }
+ }
+
+ if (na)
+ {
+ Con_Printf ("\n[**: not enough system RAM for mode]\n");
+ }
+}
+
+
+/*
+=================
+VID_TestMode_f
+=================
+*/
+void VID_TestMode_f (void)
+{
+ int modenum;
+ double testduration;
+
+ if (!vid_testingmode)
+ {
+ modenum = Q_atoi (Cmd_Argv(1));
+
+ if (VID_SetMode (modenum, vid_curpal))
+ {
+ vid_testingmode = 1;
+ testduration = Q_atof (Cmd_Argv(2));
+ if (testduration == 0)
+ testduration = 5.0;
+ vid_testendtime = realtime + testduration;
+ }
+ }
+}
+
+
+/*
+=================
+VID_Windowed_f
+=================
+*/
+void VID_Windowed_f (void)
+{
+
+ VID_SetMode ((int)vid_windowed_mode.value, vid_curpal);
+}
+
+
+/*
+=================
+VID_Fullscreen_f
+=================
+*/
+void VID_Fullscreen_f (void)
+{
+
+ VID_SetMode ((int)vid_fullscreen_mode.value, vid_curpal);
+}
+
+
+/*
+=================
+VID_Minimize_f
+=================
+*/
+void VID_Minimize_f (void)
+{
+
+// we only support minimizing windows; if you're fullscreen,
+// switch to windowed first
+ if (modestate == MS_WINDOWED)
+ ShowWindow (mainwindow, SW_MINIMIZE);
+}
+
+
+
+/*
+=================
+VID_ForceMode_f
+=================
+*/
+void VID_ForceMode_f (void)
+{
+ int modenum;
+ double testduration;
+
+ if (!vid_testingmode)
+ {
+ modenum = Q_atoi (Cmd_Argv(1));
+
+ force_mode_set = 1;
+ VID_SetMode (modenum, vid_curpal);
+ force_mode_set = 0;
+ }
+}
+
+
+void VID_Init (unsigned char *palette)
+{
+ int i, bestmatch, bestmatchmetric, t, dr, dg, db;
+ int basenummodes;
+ byte *ptmp;
+
+ Cvar_RegisterVariable (&vid_mode);
+ Cvar_RegisterVariable (&vid_wait);
+ Cvar_RegisterVariable (&vid_nopageflip);
+ Cvar_RegisterVariable (&_vid_wait_override);
+ Cvar_RegisterVariable (&_vid_default_mode);
+ Cvar_RegisterVariable (&_vid_default_mode_win);
+ Cvar_RegisterVariable (&vid_config_x);
+ Cvar_RegisterVariable (&vid_config_y);
+ Cvar_RegisterVariable (&vid_stretch_by_2);
+ Cvar_RegisterVariable (&_windowed_mouse);
+ Cvar_RegisterVariable (&vid_fullscreen_mode);
+ Cvar_RegisterVariable (&vid_windowed_mode);
+ Cvar_RegisterVariable (&block_switch);
+ Cvar_RegisterVariable (&vid_window_x);
+ Cvar_RegisterVariable (&vid_window_y);
+
+ Cmd_AddCommand ("vid_testmode", VID_TestMode_f);
+ 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);
+ Cmd_AddCommand ("vid_forcemode", VID_ForceMode_f);
+ Cmd_AddCommand ("vid_windowed", VID_Windowed_f);
+ Cmd_AddCommand ("vid_fullscreen", VID_Fullscreen_f);
+ Cmd_AddCommand ("vid_minimize", VID_Minimize_f);
+
+ if (COM_CheckParm ("-dibonly"))
+ dibonly = true;
+
+ VID_InitMGLDIB (global_hInstance);
+
+ basenummodes = nummodes;
+
+ if (!dibonly)
+ VID_InitMGLFull (global_hInstance);
+
+// if there are no non-windowed modes, or only windowed and mode 0x13, then use
+// fullscreen DIBs as well
+ if (((nummodes == basenummodes) ||
+ ((nummodes == (basenummodes + 1)) && is_mode0x13)) &&
+ !COM_CheckParm ("-nofulldib"))
+
+ {
+ VID_InitFullDIB (global_hInstance);
+ }
+
+ vid.maxwarpwidth = WARP_WIDTH;
+ vid.maxwarpheight = WARP_HEIGHT;
+ vid.colormap = host_colormap;
+ vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
+ vid_testingmode = 0;
+
+// GDI doesn't let us remap palette index 0, so we'll remap color
+// mappings from that black to another one
+ bestmatchmetric = 256*256*3;
+
+ for (i=1 ; i<256 ; i++)
+ {
+ dr = palette[0] - palette[i*3];
+ dg = palette[1] - palette[i*3+1];
+ db = palette[2] - palette[i*3+2];
+
+ t = (dr * dr) + (dg * dg) + (db * db);
+
+ if (t < bestmatchmetric)
+ {
+ bestmatchmetric = t;
+ bestmatch = i;
+
+ if (t == 0)
+ break;
+ }
+ }
+
+ for (i=0, ptmp = vid.colormap ; i<(1<<(VID_CBITS+8)) ; i++, ptmp++)
+ {
+ if (*ptmp == 0)
+ *ptmp = bestmatch;
+ }
+
+ if (COM_CheckParm("-startwindowed"))
+ {
+ startwindowed = 1;
+ vid_default = windowed_default;
+ }
+
+ if (hwnd_dialog)
+ DestroyWindow (hwnd_dialog);
+
+// sound initialization has to go here, preceded by a windowed mode set,
+// so there's a window for DirectSound to work with but we're not yet
+// fullscreen so the "hardware already in use" dialog is visible if it
+// gets displayed
+
+// keep the window minimized until we're ready for the first real mode set
+ hide_window = true;
+ VID_SetMode (MODE_WINDOWED, palette);
+ hide_window = false;
+ S_Init ();
+
+ vid_initialized = true;
+
+ force_mode_set = true;
+ VID_SetMode (vid_default, palette);
+ force_mode_set = false;
+
+ vid_realmode = vid_modenum;
+
+ VID_SetPalette (palette);
+
+ vid_menudrawfn = VID_MenuDraw;
+ vid_menukeyfn = VID_MenuKey;
+
+ strcpy (badmode.modedesc, "Bad mode");
+}
+
+
+void VID_Shutdown (void)
+{
+ HDC hdc;
+ int dummy;
+
+ if (vid_initialized)
+ {
+ if (modestate == MS_FULLDIB)
+ ChangeDisplaySettings (NULL, CDS_FULLSCREEN);
+
+ PostMessage (HWND_BROADCAST, WM_PALETTECHANGED, (WPARAM)mainwindow, (LPARAM)0);
+ PostMessage (HWND_BROADCAST, WM_SYSCOLORCHANGE, (WPARAM)0, (LPARAM)0);
+
+ AppActivate(false, false);
+ DestroyDIBWindow ();
+ DestroyFullscreenWindow ();
+ DestroyFullDIBWindow ();
+
+ if (hwnd_dialog)
+ DestroyWindow (hwnd_dialog);
+
+ if (mainwindow)
+ DestroyWindow(mainwindow);
+
+ MGL_exit();
+
+ vid_testingmode = 0;
+ vid_initialized = 0;
+ }
+}
+
+
+/*
+================
+FlipScreen
+================
+*/
+void FlipScreen(vrect_t *rects)
+{
+ HRESULT ddrval;
+
+ // Flip the surfaces
+
+ if (DDActive)
+ {
+ if (mgldc)
+ {
+ if (memdc)
+ {
+ while (rects)
+ {
+ if (vid_stretched)
+ {
+ MGL_stretchBltCoord(mgldc, memdc,
+ rects->x,
+ rects->y,
+ rects->x + rects->width,
+ rects->y + rects->height,
+ rects->x << 1,
+ rects->y << 1,
+ (rects->x + rects->width) << 1,
+ (rects->y + rects->height) << 1);
+ }
+ else
+ {
+ MGL_bitBltCoord(mgldc, memdc,
+ rects->x, rects->y,
+ (rects->x + rects->width),
+ (rects->y + rects->height),
+ rects->x, rects->y, MGL_REPLACE_MODE);
+ }
+
+ rects = rects->pnext;
+ }
+ }
+
+ if (vid.numpages > 1)
+ {
+ // We have a flipping surface, so do a hard page flip
+ aPage = (aPage+1) % vid.numpages;
+ vPage = (vPage+1) % vid.numpages;
+ MGL_setActivePage(mgldc,aPage);
+ MGL_setVisualPage(mgldc,vPage,waitVRT);
+ }
+ }
+ }
+ else
+ {
+ HDC hdcScreen;
+
+ hdcScreen = GetDC(mainwindow);
+
+ if (windc && dibdc)
+ {
+ MGL_setWinDC(windc,hdcScreen);
+
+ while (rects)
+ {
+ if (vid_stretched)
+ {
+ MGL_stretchBltCoord(windc,dibdc,
+ rects->x, rects->y,
+ rects->x + rects->width, rects->y + rects->height,
+ rects->x << 1, rects->y << 1,
+ (rects->x + rects->width) << 1,
+ (rects->y + rects->height) << 1);
+ }
+ else
+ {
+ MGL_bitBltCoord(windc,dibdc,
+ rects->x, rects->y,
+ rects->x + rects->width, rects->y + rects->height,
+ rects->x, rects->y, MGL_REPLACE_MODE);
+ }
+
+ rects = rects->pnext;
+ }
+ }
+
+ ReleaseDC(mainwindow, hdcScreen);
+ }
+}
+
+
+void VID_Update (vrect_t *rects)
+{
+ vrect_t rect;
+ RECT trect;
+
+ if (!vid_palettized && palette_changed)
+ {
+ palette_changed = false;
+ rect.x = 0;
+ rect.y = 0;
+ rect.width = vid.width;
+ rect.height = vid.height;
+ rect.pnext = NULL;
+ rects = ▭
+ }
+
+ if (firstupdate)
+ {
+ if (modestate == MS_WINDOWED)
+ {
+ GetWindowRect (mainwindow, &trect);
+
+ if ((trect.left != (int)vid_window_x.value) ||
+ (trect.top != (int)vid_window_y.value))
+ {
+ if (COM_CheckParm ("-resetwinpos"))
+ {
+ Cvar_SetValue ("vid_window_x", 0.0);
+ Cvar_SetValue ("vid_window_y", 0.0);
+ }
+
+ VID_CheckWindowXY ();
+ SetWindowPos (mainwindow, NULL, (int)vid_window_x.value,
+ (int)vid_window_y.value, 0, 0,
+ SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME);
+ }
+ }
+
+ if ((_vid_default_mode_win.value != vid_default) &&
+ (!startwindowed || (_vid_default_mode_win.value < MODE_FULLSCREEN_DEFAULT)))
+ {
+ firstupdate = 0;
+
+ if (COM_CheckParm ("-resetwinpos"))
+ {
+ Cvar_SetValue ("vid_window_x", 0.0);
+ Cvar_SetValue ("vid_window_y", 0.0);
+ }
+
+ if ((_vid_default_mode_win.value < 0) ||
+ (_vid_default_mode_win.value >= nummodes))
+ {
+ Cvar_SetValue ("_vid_default_mode_win", windowed_default);
+ }
+
+ Cvar_SetValue ("vid_mode", _vid_default_mode_win.value);
+ }
+ }
+
+ // We've drawn the frame; copy it to the screen
+ FlipScreen (rects);
+
+ if (vid_testingmode)
+ {
+ if (realtime >= vid_testendtime)
+ {
+ VID_SetMode (vid_realmode, vid_curpal);
+ vid_testingmode = 0;
+ }
+ }
+ else
+ {
+ if ((int)vid_mode.value != vid_realmode)
+ {
+ VID_SetMode ((int)vid_mode.value, vid_curpal);
+ Cvar_SetValue ("vid_mode", (float)vid_modenum);
+ // so if mode set fails, we don't keep on
+ // trying to set that mode
+ vid_realmode = vid_modenum;
+ }
+ }
+
+// handle the mouse state when windowed if that's changed
+ if (modestate == MS_WINDOWED)
+ {
+ if ((int)_windowed_mouse.value != windowed_mouse)
+ {
+ if (_windowed_mouse.value)
+ {
+ IN_ActivateMouse ();
+ IN_HideMouse ();
+ }
+ else
+ {
+ IN_DeactivateMouse ();
+ IN_ShowMouse ();
+ }
+
+ windowed_mouse = (int)_windowed_mouse.value;
+ }
+ }
+}
+
+
+/*
+================
+D_BeginDirectRect
+================
+*/
+void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
+{
+ int i, j, reps, repshift;
+ vrect_t rect;
+
+ if (!vid_initialized)
+ return;
+
+ if (vid.aspect > 1.5)
+ {
+ reps = 2;
+ repshift = 1;
+ }
+ else
+ {
+ reps = 1;
+ repshift = 0;
+ }
+
+ if (vid.numpages == 1)
+ {
+ VID_LockBuffer ();
+
+ if (!vid.direct)
+ Sys_Error ("NULL vid.direct pointer");
+
+ for (i=0 ; i<(height << repshift) ; i += reps)
+ {
+ for (j=0 ; j<reps ; j++)
+ {
+ memcpy (&backingbuf[(i + j) * 24],
+ vid.direct + x + ((y << repshift) + i + j) * vid.rowbytes,
+ width);
+ memcpy (vid.direct + x + ((y << repshift) + i + j) * vid.rowbytes,
+ &pbitmap[(i >> repshift) * width],
+ width);
+ }
+ }
+
+ VID_UnlockBuffer ();
+
+ rect.x = x;
+ rect.y = y;
+ rect.width = width;
+ rect.height = height << repshift;
+ rect.pnext = NULL;
+
+ FlipScreen (&rect);
+ }
+ else
+ {
+ // unlock if locked
+ if (lockcount > 0)
+ MGL_endDirectAccess();
+
+ // set the active page to the displayed page
+ MGL_setActivePage (mgldc, vPage);
+
+ // lock the screen
+ MGL_beginDirectAccess ();
+
+ // save from and draw to screen
+ for (i=0 ; i<(height << repshift) ; i += reps)
+ {
+ for (j=0 ; j<reps ; j++)
+ {
+ memcpy (&backingbuf[(i + j) * 24],
+ (byte *)mgldc->surface + x +
+ ((y << repshift) + i + j) * mgldc->mi.bytesPerLine,
+ width);
+ memcpy ((byte *)mgldc->surface + x +
+ ((y << repshift) + i + j) * mgldc->mi.bytesPerLine,
+ &pbitmap[(i >> repshift) * width],
+ width);
+ }
+ }
+
+ // unlock the screen
+ MGL_endDirectAccess ();
+
+ // restore the original active page
+ MGL_setActivePage (mgldc, aPage);
+
+ // relock the screen if it was locked
+ if (lockcount > 0)
+ MGL_beginDirectAccess();
+ }
+}
+
+
+/*
+================
+D_EndDirectRect
+================
+*/
+void D_EndDirectRect (int x, int y, int width, int height)
+{
+ int i, j, reps, repshift;
+ vrect_t rect;
+
+ if (!vid_initialized)
+ return;
+
+ if (vid.aspect > 1.5)
+ {
+ reps = 2;
+ repshift = 1;
+ }
+ else
+ {
+ reps = 1;
+ repshift = 0;
+ }
+
+ if (vid.numpages == 1)
+ {
+ VID_LockBuffer ();
+
+ if (!vid.direct)
+ Sys_Error ("NULL vid.direct pointer");
+
+ for (i=0 ; i<(height << repshift) ; i += reps)
+ {
+ for (j=0 ; j<reps ; j++)
+ {
+ memcpy (vid.direct + x + ((y << repshift) + i + j) * vid.rowbytes,
+ &backingbuf[(i + j) * 24],
+ width);
+ }
+ }
+
+ VID_UnlockBuffer ();
+
+ rect.x = x;
+ rect.y = y;
+ rect.width = width;
+ rect.height = height << repshift;
+ rect.pnext = NULL;
+
+ FlipScreen (&rect);
+ }
+ else
+ {
+ // unlock if locked
+ if (lockcount > 0)
+ MGL_endDirectAccess();
+
+ // set the active page to the displayed page
+ MGL_setActivePage (mgldc, vPage);
+
+ // lock the screen
+ MGL_beginDirectAccess ();
+
+ // restore to the screen
+ for (i=0 ; i<(height << repshift) ; i += reps)
+ {
+ for (j=0 ; j<reps ; j++)
+ {
+ memcpy ((byte *)mgldc->surface + x +
+ ((y << repshift) + i + j) * mgldc->mi.bytesPerLine,
+ &backingbuf[(i + j) * 24],
+ width);
+ }
+ }
+
+ // unlock the screen
+ MGL_endDirectAccess ();
+
+ // restore the original active page
+ MGL_setActivePage (mgldc, aPage);
+
+ // relock the screen if it was locked
+ if (lockcount > 0)
+ MGL_beginDirectAccess();
+ }
+}
+
+
+//==========================================================================
+
+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,'*',
+ K_ALT,' ', 0 , K_F1, K_F2, K_F3, K_F4, K_F5, // 3
+ K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE, 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, // 6
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 // 7
+};
+
+/*
+=======
+MapKey
+
+Map from windows to quake keynums
+=======
+*/
+int MapKey (int key)
+{
+ key = (key>>16)&255;
+ if (key > 127)
+ return 0;
+
+ return scantokey[key];
+}
+
+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.
+*
+****************************************************************************/
+{
+ HDC hdc;
+ int i, t;
+ static BOOL sound_active;
+
+ ActiveApp = fActive;
+
+// messy, but it seems to work
+ if (vid_fulldib_on_focus_mode)
+ {
+ Minimized = minimize;
+
+ if (Minimized)
+ ActiveApp = false;
+ }
+
+ MGL_appActivate(windc, ActiveApp);
+
+ if (vid_initialized)
+ {
+ // yield the palette if we're losing the focus
+ hdc = GetDC(NULL);
+
+ if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)
+ {
+ if (ActiveApp)
+ {
+ if ((modestate == MS_WINDOWED) || (modestate == MS_FULLDIB))
+ {
+ if (GetSystemPaletteUse(hdc) == SYSPAL_STATIC)
+ {
+ // switch to SYSPAL_NOSTATIC and remap the colors
+ SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC);
+ syscolchg = true;
+ pal_is_nostatic = true;
+ }
+ }
+ }
+ else if (pal_is_nostatic)
+ {
+ if (GetSystemPaletteUse(hdc) == SYSPAL_NOSTATIC)
+ {
+ // switch back to SYSPAL_STATIC and the old mapping
+ SetSystemPaletteUse(hdc, SYSPAL_STATIC);
+ syscolchg = true;
+ }
+
+ pal_is_nostatic = false;
+ }
+ }
+
+ if (!Minimized)
+ VID_SetPalette (vid_curpal);
+
+ scr_fullupdate = 0;
+
+ ReleaseDC(NULL,hdc);
+ }
+
+// enable/disable sound on focus gain/loss
+ if (!ActiveApp && sound_active)
+ {
+ S_BlockSound ();
+ S_ClearBuffer ();
+ sound_active = false;
+ }
+ else if (ActiveApp && !sound_active)
+ {
+ S_UnblockSound ();
+ S_ClearBuffer ();
+ sound_active = true;
+ }
+
+// minimize/restore fulldib windows/mouse-capture normal windows on demand
+ if (!in_mode_set)
+ {
+ if (ActiveApp)
+ {
+ if (vid_fulldib_on_focus_mode)
+ {
+ if (vid_initialized)
+ {
+ msg_suppress_1 = true; // don't want to see normal mode set message
+ VID_SetMode (vid_fulldib_on_focus_mode, vid_curpal);
+ msg_suppress_1 = false;
+
+ t = in_mode_set;
+ in_mode_set = true;
+ AppActivate (true, false);
+ in_mode_set = t;
+ }
+
+ IN_ActivateMouse ();
+ IN_HideMouse ();
+ }
+ else if ((modestate == MS_WINDOWED) && _windowed_mouse.value)
+ {
+ IN_ActivateMouse ();
+ IN_HideMouse ();
+ }
+ }
+
+ if (!ActiveApp)
+ {
+ if (modestate == MS_FULLDIB)
+ {
+ if (vid_initialized)
+ {
+ force_minimized = true;
+ i = vid_fulldib_on_focus_mode;
+ msg_suppress_1 = true; // don't want to see normal mode set message
+ VID_SetMode (windowed_default, vid_curpal);
+ msg_suppress_1 = false;
+ vid_fulldib_on_focus_mode = i;
+ force_minimized = false;
+
+ // we never seem to get WM_ACTIVATE inactive from this mode set, so we'll
+ // do it manually
+ t = in_mode_set;
+ in_mode_set = true;
+ AppActivate (false, true);
+ in_mode_set = t;
+ }
+
+ IN_DeactivateMouse ();
+ IN_ShowMouse ();
+ }
+ else if ((modestate == MS_WINDOWED) && _windowed_mouse.value)
+ {
+ IN_DeactivateMouse ();
+ IN_ShowMouse ();
+ }
+ }
+ }
+}
+
+
+/*
+================
+VID_HandlePause
+================
+*/
+void VID_HandlePause (qboolean pause)
+{
+
+ if ((modestate == MS_WINDOWED) && _windowed_mouse.value)
+ {
+ if (pause)
+ {
+ IN_DeactivateMouse ();
+ IN_ShowMouse ();
+ }
+ else
+ {
+ IN_ActivateMouse ();
+ IN_HideMouse ();
+ }
+ }
+}
+
+
+/*
+===================================================================
+
+MAIN WINDOW
+
+===================================================================
+*/
+
+LONG CDAudio_MessageHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+/* main window procedure */
+LONG WINAPI MainWndProc (
+ HWND hWnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ LONG lRet = 0;
+ int fwKeys, xPos, yPos, fActive, fMinimized, temp;
+ HDC hdc;
+ PAINTSTRUCT ps;
+ static int recursiveflag;
+
+ switch (uMsg)
+ {
+ case WM_CREATE:
+ break;
+
+ case WM_SYSCOMMAND:
+
+ // Check for maximize being hit
+ switch (wParam & ~0x0F)
+ {
+ case SC_MAXIMIZE:
+ // if minimized, bring up as a window before going fullscreen,
+ // so MGL will have the right state to restore
+ if (Minimized)
+ {
+ force_mode_set = true;
+ VID_SetMode (vid_modenum, vid_curpal);
+ force_mode_set = false;
+ }
+
+ VID_SetMode ((int)vid_fullscreen_mode.value, vid_curpal);
+ break;
+
+ case SC_SCREENSAVE:
+ case SC_MONITORPOWER:
+ if (modestate != MS_WINDOWED)
+ {
+ // don't call DefWindowProc() because we don't want to start
+ // the screen saver fullscreen
+ break;
+ }
+
+ // fall through windowed and allow the screen saver to start
+
+ default:
+ if (!in_mode_set)
+ {
+ S_BlockSound ();
+ S_ClearBuffer ();
+ }
+
+ lRet = DefWindowProc (hWnd, uMsg, wParam, lParam);
+
+ if (!in_mode_set)
+ {
+ S_UnblockSound ();
+ }
+ }
+ break;
+
+ case WM_MOVE:
+ window_x = (int) LOWORD(lParam);
+ window_y = (int) HIWORD(lParam);
+ VID_UpdateWindowStatus ();
+
+ if ((modestate == MS_WINDOWED) && !in_mode_set && !Minimized)
+ VID_RememberWindowPos ();
+
+ break;
+
+ case WM_SIZE:
+ Minimized = false;
+
+ if (!(wParam & SIZE_RESTORED))
+ {
+ if (wParam & SIZE_MINIMIZED)
+ Minimized = true;
+ }
+ break;
+
+ case WM_SYSCHAR:
+ // keep Alt-Space from happening
+ 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 ();
+
+ if (!in_mode_set)
+ {
+ if (windc)
+ MGL_activatePalette(windc,true);
+
+ VID_SetPalette(vid_curpal);
+ }
+
+ break;
+
+ case WM_PAINT:
+ hdc = BeginPaint(hWnd, &ps);
+
+ if (!in_mode_set && host_initialized)
+ SCR_UpdateWholeScreen ();
+
+ EndPaint(hWnd, &ps);
+ break;
+
+ case WM_KEYDOWN:
+ case WM_SYSKEYDOWN:
+ if (!in_mode_set)
+ Key_Event (MapKey(lParam), true);
+ break;
+
+ case WM_KEYUP:
+ case WM_SYSKEYUP:
+ if (!in_mode_set)
+ Key_Event (MapKey(lParam), false);
+ 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:
+ if (!in_mode_set)
+ {
+ 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;
+ // KJB: Added these new palette functions
+ case WM_PALETTECHANGED:
+ if ((HWND)wParam == hWnd)
+ break;
+ /* Fall through to WM_QUERYNEWPALETTE */
+ case WM_QUERYNEWPALETTE:
+ hdc = GetDC(NULL);
+
+ if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)
+ vid_palettized = true;
+ else
+ vid_palettized = false;
+
+ ReleaseDC(NULL,hdc);
+
+ scr_fullupdate = 0;
+
+ if (vid_initialized && !in_mode_set && windc && MGL_activatePalette(windc,false) && !Minimized)
+ {
+ VID_SetPalette (vid_curpal);
+ InvalidateRect (mainwindow, NULL, false);
+
+ // specifically required if WM_QUERYNEWPALETTE realizes a new palette
+ lRet = TRUE;
+ }
+ break;
+
+ case WM_DISPLAYCHANGE:
+ if (!in_mode_set && (modestate == MS_WINDOWED) && !vid_fulldib_on_focus_mode)
+ {
+ force_mode_set = true;
+ VID_SetMode (vid_modenum, vid_curpal);
+ force_mode_set = false;
+ }
+ break;
+
+ case WM_CLOSE:
+ // this causes Close in the right-click task bar menu not to work, but right
+ // now bad things happen if Close is handled in that case (garbage and a
+ // crash on Win95)
+ if (!in_mode_set)
+ {
+ if (MessageBox (mainwindow, "Are you sure you want to quit?", "Confirm Exit",
+ MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION) == IDYES)
+ {
+ Sys_Quit ();
+ }
+ }
+ 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 0 if handled message, 1 if not */
+ return lRet;
+}
+
+
+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;
+ int ismode13;
+ int width;
+} modedesc_t;
+
+#define MAX_COLUMN_SIZE 5
+#define MODE_AREA_HEIGHT (MAX_COLUMN_SIZE + 6)
+#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;
+ modedesc_t tmodedesc;
+
+ p = Draw_CachePic ("gfx/vidmodes.lmp");
+ M_DrawPic ( (320-p->width)/2, 4, p);
+
+ for (i=0 ; i<3 ; i++)
+ {
+ ptr = VID_GetModeDescriptionMemCheck (i);
+ modedescs[i].modenum = modelist[i].modenum;
+ modedescs[i].desc = ptr;
+ modedescs[i].ismode13 = 0;
+ modedescs[i].iscur = 0;
+
+ if (vid_modenum == i)
+ modedescs[i].iscur = 1;
+ }
+
+ vid_wmodes = 3;
+ lnummodes = VID_NumModes ();
+
+ for (i=3 ; i<lnummodes ; i++)
+ {
+ ptr = VID_GetModeDescriptionMemCheck (i);
+ pv = VID_GetModePtr (i);
+
+ // we only have room for 15 fullscreen modes, so don't allow
+ // 360-wide modes, because if there are 5 320-wide modes and
+ // 5 360-wide modes, we'll run out of space
+ if (ptr && ((pv->width != 360) || COM_CheckParm("-allow360")))
+ {
+ dup = 0;
+
+ for (j=3 ; j<vid_wmodes ; j++)
+ {
+ if (!strcmp (modedescs[j].desc, ptr))
+ {
+ dup = 1;
+ dupmode = j;
+ break;
+ }
+ }
+
+ if (dup || (vid_wmodes < MAX_MODEDESCS))
+ {
+ if (!dup || !modedescs[dupmode].ismode13 || COM_CheckParm("-noforcevga"))
+ {
+ if (dup)
+ {
+ k = dupmode;
+ }
+ else
+ {
+ k = vid_wmodes;
+ }
+
+ modedescs[k].modenum = i;
+ modedescs[k].desc = ptr;
+ modedescs[k].ismode13 = pv->mode13;
+ modedescs[k].iscur = 0;
+ modedescs[k].width = pv->width;
+
+ if (i == vid_modenum)
+ modedescs[k].iscur = 1;
+
+ if (!dup)
+ vid_wmodes++;
+ }
+ }
+ }
+ }
+
+// sort the modes on width (to handle picking up oddball dibonly modes
+// after all the others)
+ for (i=3 ; i<(vid_wmodes-1) ; i++)
+ {
+ for (j=(i+1) ; j<vid_wmodes ; j++)
+ {
+ if (modedescs[i].width > modedescs[j].width)
+ {
+ tmodedesc = modedescs[i];
+ modedescs[i] = modedescs[j];
+ modedescs[j] = tmodedesc;
+ }
+ }
+ }
+
+
+ M_Print (13*8, 36, "Windowed Modes");
+
+ column = 16;
+ row = 36+2*8;
+
+ for (i=0 ; i<3; i++)
+ {
+ if (modedescs[i].iscur)
+ M_PrintWhite (column, row, modedescs[i].desc);
+ else
+ M_Print (column, row, modedescs[i].desc);
+
+ column += 13*8;
+ }
+
+ if (vid_wmodes > 3)
+ {
+ M_Print (12*8, 36+4*8, "Fullscreen Modes");
+
+ column = 16;
+ row = 36+6*8;
+
+ for (i=3 ; 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 - 3) % VID_ROW_SIZE) == (VID_ROW_SIZE - 1))
+ {
+ column = 16;
+ row += 8;
+ }
+ }
+ }
+
+// line cursor
+ if (vid_testingmode)
+ {
+ sprintf (temp, "TESTING %s",
+ modedescs[vid_line].desc);
+ M_Print (13*8, 36 + MODE_AREA_HEIGHT * 8 + 8*4, temp);
+ M_Print (9*8, 36 + MODE_AREA_HEIGHT * 8 + 8*6,
+ "Please wait 5 seconds...");
+ }
+ else
+ {
+ M_Print (9*8, 36 + MODE_AREA_HEIGHT * 8 + 8,
+ "Press Enter to set mode");
+ M_Print (6*8, 36 + MODE_AREA_HEIGHT * 8 + 8*3,
+ "T to test mode for 5 seconds");
+ ptr = VID_GetModeDescription2 (vid_modenum);
+
+ if (ptr)
+ {
+ sprintf (temp, "D to set default: %s", ptr);
+ M_Print (2*8, 36 + MODE_AREA_HEIGHT * 8 + 8*5, temp);
+ }
+
+ ptr = VID_GetModeDescription2 ((int)_vid_default_mode_win.value);
+
+ if (ptr)
+ {
+ sprintf (temp, "Current default: %s", ptr);
+ M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*6, temp);
+ }
+
+ M_Print (15*8, 36 + MODE_AREA_HEIGHT * 8 + 8*8,
+ "Esc to exit");
+
+ row = 36 + 2*8 + (vid_line / VID_ROW_SIZE) * 8;
+ column = 8 + (vid_line % VID_ROW_SIZE) * 13*8;
+
+ if (vid_line >= 3)
+ row += 3*8;
+
+ M_DrawCharacter (column, row, 12+((int)(realtime*4)&1));
+ }
+}
+
+
+/*
+================
+VID_MenuKey
+================
+*/
+void VID_MenuKey (int key)
+{
+ if (vid_testingmode)
+ return;
+
+ switch (key)
+ {
+ case K_ESCAPE:
+ S_LocalSound ("misc/menu1.wav");
+ M_Menu_Options_f ();
+ break;
+
+ case K_LEFTARROW:
+ S_LocalSound ("misc/menu1.wav");
+ vid_line = ((vid_line / VID_ROW_SIZE) * VID_ROW_SIZE) +
+ ((vid_line + 2) % VID_ROW_SIZE);
+
+ if (vid_line >= vid_wmodes)
+ vid_line = vid_wmodes - 1;
+ break;
+
+ case K_RIGHTARROW:
+ S_LocalSound ("misc/menu1.wav");
+ vid_line = ((vid_line / VID_ROW_SIZE) * VID_ROW_SIZE) +
+ ((vid_line + 4) % VID_ROW_SIZE);
+
+ if (vid_line >= vid_wmodes)
+ vid_line = (vid_line / VID_ROW_SIZE) * VID_ROW_SIZE;
+ break;
+
+ case K_UPARROW:
+ S_LocalSound ("misc/menu1.wav");
+ vid_line -= VID_ROW_SIZE;
+
+ if (vid_line < 0)
+ {
+ vid_line += ((vid_wmodes + (VID_ROW_SIZE - 1)) /
+ VID_ROW_SIZE) * VID_ROW_SIZE;
+
+ while (vid_line >= vid_wmodes)
+ vid_line -= VID_ROW_SIZE;
+ }
+ break;
+
+ case K_DOWNARROW:
+ S_LocalSound ("misc/menu1.wav");
+ vid_line += VID_ROW_SIZE;
+
+ if (vid_line >= vid_wmodes)
+ {
+ vid_line -= ((vid_wmodes + (VID_ROW_SIZE - 1)) /
+ VID_ROW_SIZE) * VID_ROW_SIZE;
+
+ while (vid_line < 0)
+ vid_line += VID_ROW_SIZE;
+ }
+ break;
+
+ case K_ENTER:
+ S_LocalSound ("misc/menu1.wav");
+ VID_SetMode (modedescs[vid_line].modenum, vid_curpal);
+ break;
+
+ case 'T':
+ case 't':
+ S_LocalSound ("misc/menu1.wav");
+ // have to set this before setting the mode because WM_PAINT
+ // happens during the mode set and does a VID_Update, which
+ // checks vid_testingmode
+ vid_testingmode = 1;
+ vid_testendtime = realtime + 5.0;
+
+ if (!VID_SetMode (modedescs[vid_line].modenum, vid_curpal))
+ {
+ vid_testingmode = 0;
+ }
+ break;
+
+ case 'D':
+ case 'd':
+ S_LocalSound ("misc/menu1.wav");
+ firstupdate = 0;
+ Cvar_SetValue ("_vid_default_mode_win", vid_modenum);
+ break;
+
+ default:
+ break;
+ }
+}
|
