X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=vid_wgl.c;h=4b72f7744e43a60359816cbf52e741730ef80b3e;hp=7f2247c53c5c767e25d63779769305cdee8dfeaa;hb=6254924244c3008ac5daa51421ff726de590f2be;hpb=8dcce44300385b12c46d494c06aadcfa35a8bc14 diff --git a/vid_wgl.c b/vid_wgl.c index 7f2247c5..4b72f774 100644 --- a/vid_wgl.c +++ b/vid_wgl.c @@ -8,7 +8,7 @@ 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. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -24,448 +24,234 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "resource.h" #include -#define MAX_MODE_LIST 30 -#define VID_ROW_SIZE 3 -#define WARP_WIDTH 320 -#define WARP_HEIGHT 200 -#define MAXWIDTH 10000 -#define MAXHEIGHT 10000 -#define BASEWIDTH 320 -#define BASEHEIGHT 200 - -#define MODE_WINDOWED 0 -#define NO_MODE (MODE_WINDOWED - 1) -#define MODE_FULLSCREEN_DEFAULT (MODE_WINDOWED + 1) - -typedef struct { - modestate_t type; - int width; - int height; - int modenum; - int dib; - int fullscreen; - int bpp; - int halfscreen; - char modedesc[17]; -} vmode_t; - -typedef struct { - int width; - int height; -} lmode_t; - -lmode_t lowresmodes[] = { - {320, 200}, - {320, 240}, - {400, 300}, - {512, 384}, +// Tell startup code that we have a client +int cl_available = true; + +int (WINAPI *qwglChoosePixelFormat)(HDC, CONST PIXELFORMATDESCRIPTOR *); +int (WINAPI *qwglDescribePixelFormat)(HDC, int, UINT, LPPIXELFORMATDESCRIPTOR); +//int (WINAPI *qwglGetPixelFormat)(HDC); +BOOL (WINAPI *qwglSetPixelFormat)(HDC, int, CONST PIXELFORMATDESCRIPTOR *); +BOOL (WINAPI *qwglSwapBuffers)(HDC); +HGLRC (WINAPI *qwglCreateContext)(HDC); +BOOL (WINAPI *qwglDeleteContext)(HGLRC); +HGLRC (WINAPI *qwglGetCurrentContext)(VOID); +HDC (WINAPI *qwglGetCurrentDC)(VOID); +PROC (WINAPI *qwglGetProcAddress)(LPCSTR); +BOOL (WINAPI *qwglMakeCurrent)(HDC, HGLRC); +BOOL (WINAPI *qwglSwapIntervalEXT)(int interval); +const char *(WINAPI *qwglGetExtensionsStringARB)(HDC hdc); + +static dllfunction_t wglfuncs[] = +{ + {"wglChoosePixelFormat", (void **) &qwglChoosePixelFormat}, + {"wglDescribePixelFormat", (void **) &qwglDescribePixelFormat}, +// {"wglGetPixelFormat", (void **) &qwglGetPixelFormat}, + {"wglSetPixelFormat", (void **) &qwglSetPixelFormat}, + {"wglSwapBuffers", (void **) &qwglSwapBuffers}, + {"wglCreateContext", (void **) &qwglCreateContext}, + {"wglDeleteContext", (void **) &qwglDeleteContext}, + {"wglGetProcAddress", (void **) &qwglGetProcAddress}, + {"wglMakeCurrent", (void **) &qwglMakeCurrent}, + {"wglGetCurrentContext", (void **) &qwglGetCurrentContext}, + {"wglGetCurrentDC", (void **) &qwglGetCurrentDC}, + {NULL, NULL} }; -const char *gl_vendor; -const char *gl_renderer; -const char *gl_version; -const char *gl_extensions; - -qboolean DDActive; -qboolean scr_skipupdate; +static dllfunction_t wglswapintervalfuncs[] = +{ + {"wglSwapIntervalEXT", (void **) &qwglSwapIntervalEXT}, + {NULL, NULL} +}; -static vmode_t modelist[MAX_MODE_LIST]; -static int nummodes; -static vmode_t *pcurrentmode; -static vmode_t badmode; +qboolean scr_skipupdate; -static DEVMODE gdevmode; -static qboolean vid_initialized = false; -static qboolean windowed, leavecurrentmode; -static qboolean vid_canalttab = false; +static DEVMODE gdevmode; +static qboolean vid_initialized = false; static qboolean vid_wassuspended = false; -static int windowed_mouse; -extern qboolean mouseactive; // from in_win.c -static HICON hIcon; - -int DIBWidth, DIBHeight; -RECT WindowRect; -DWORD WindowStyle, ExWindowStyle; - -HWND mainwindow, dibwindow; - -int vid_modenum = NO_MODE; -int vid_realmode; -int vid_default = MODE_WINDOWED; -static int windowed_default; -unsigned char vid_curpal[256*3]; - -HGLRC baseRC; -HDC maindc; +static int vid_usingmouse; +extern qboolean mouseactive; // from in_win.c +static HICON hIcon; -glvert_t glv; +HWND mainwindow; -HWND WINAPI InitializeWindow (HINSTANCE hInstance, int nCmdShow); +//HWND WINAPI InitializeWindow (HINSTANCE hInstance, int nCmdShow); -viddef_t vid; // global video state +static int vid_isfullscreen; -float gldepthmin, gldepthmax; +//void VID_MenuDraw (void); +//void VID_MenuKey (int key); -modestate_t modestate = MS_UNINIT; - -void VID_MenuDraw (void); -void VID_MenuKey (int key); - -LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); -void AppActivate(BOOL fActive, BOOL minimize); -char *VID_GetModeDescription (int mode); -void ClearAllStates (void); -void VID_UpdateWindowStatus (void); -void GL_Init (void); - -// LordHavoc: ARB multitexture support -int gl_mtex_enum = 0; - -qboolean is8bit = false; -qboolean isPermedia = false; -qboolean isATI = false; // LordHavoc: special differences for ATI's broken drivers -qboolean isG200 = false; // LordHavoc: the Matrox G200 can't do per pixel alpha, and it uses a D3D driver for GL... ugh... -qboolean isRagePro = false; // LordHavoc: the ATI Rage Pro has limitations with per pixel alpha (the color scaler does not apply to per pixel alpha images...), although not as bad as a G200. -qboolean gl_mtexable = false; -qboolean gl_arrays = false; +//LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); +//void AppActivate(BOOL fActive, BOOL minimize); +//void ClearAllStates (void); +//void VID_UpdateWindowStatus (void); //==================================== -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","1", true}; - -int window_center_x, window_center_y, window_x, window_y, window_width, window_height; -RECT window_rect; - -// direct draw software compatability stuff - -void VID_HandlePause (qboolean pause) -{ -} - -void VID_ForceLockState (int lk) -{ -} - -void VID_LockBuffer (void) -{ -} - -void VID_UnlockBuffer (void) -{ -} - -int VID_ForceUnlockedAndReturnState (void) -{ - return 0; -} - -void CenterWindow(HWND hWndCenter, int width, int height, BOOL lefttopjustify) -{ - int CenterX, CenterY; - - CenterX = (GetSystemMetrics(SM_CXSCREEN) - width) / 2; - CenterY = (GetSystemMetrics(SM_CYSCREEN) - height) / 2; - if (CenterX > CenterY*2) - CenterX >>= 1; // dual screens - CenterX = (CenterX < 0) ? 0: CenterX; - CenterY = (CenterY < 0) ? 0: CenterY; - SetWindowPos (hWndCenter, NULL, CenterX, CenterY, 0, 0, - SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME); -} - -qboolean VID_SetWindowedMode (int modenum) -{ - int lastmodestate, width, height; - RECT rect; - - lastmodestate = modestate; +int window_x, window_y, window_width, window_height; +int window_center_x, window_center_y; - WindowRect.top = WindowRect.left = 0; +void IN_ShowMouse (void); +void IN_DeactivateMouse (void); +void IN_HideMouse (void); +void IN_ActivateMouse (void); +void IN_MouseEvent (int mstate); +void IN_UpdateClipCursor (void); - WindowRect.right = modelist[modenum].width; - WindowRect.bottom = modelist[modenum].height; +qboolean mouseinitialized; +static qboolean dinput; - DIBWidth = modelist[modenum].width; - DIBHeight = modelist[modenum].height; +// input code - WindowStyle = WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_SYSMENU | - WS_MINIMIZEBOX; - ExWindowStyle = 0; +#include - rect = WindowRect; - AdjustWindowRectEx(&rect, WindowStyle, FALSE, 0); +#define DINPUT_BUFFERSIZE 16 +#define iDirectInputCreate(a,b,c,d) pDirectInputCreate(a,b,c,d) - width = rect.right - rect.left; - height = rect.bottom - rect.top; +HRESULT (WINAPI *pDirectInputCreate)(HINSTANCE hinst, DWORD dwVersion, + LPDIRECTINPUT * lplpDirectInput, LPUNKNOWN punkOuter); - // Create the DIB window - dibwindow = CreateWindowEx ( - ExWindowStyle, -#ifdef NEHAHRA - "DPNehahraQuake", - "DPNehahraGLQuake", -#else - "DarkPlacesQuake", - "DarkPlacesGLQuake", +// LordHavoc: thanks to backslash for this support for mouse buttons 4 and 5 +/* backslash :: imouse explorer buttons */ +/* These are #ifdefed out for non-Win2K in the February 2001 version of + MS's platform SDK, but we need them for compilation. . . */ +#ifndef WM_XBUTTONDOWN + #define WM_XBUTTONDOWN 0x020B + #define WM_XBUTTONUP 0x020C #endif - WindowStyle, - rect.left, rect.top, - width, - height, - NULL, - NULL, - global_hInstance, - NULL); - - if (!dibwindow) - Sys_Error ("Couldn't create DIB window"); - - // Center and show the DIB window - CenterWindow(dibwindow, WindowRect.right - WindowRect.left, - WindowRect.bottom - WindowRect.top, false); - - ShowWindow (dibwindow, SW_SHOWDEFAULT); - UpdateWindow (dibwindow); - - modestate = MS_WINDOWED; - - // LordHavoc: using GDI functions on an OpenGL window? bad idea - /* -// because we have set the background brush for the window to NULL -// (to avoid flickering when re-sizing the window on the desktop), -// we clear the window to black when created, otherwise it will be -// empty while Quake starts up. - hdc = GetDC(dibwindow); - PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS); - ReleaseDC(dibwindow, hdc); - */ - - if (vid.conheight > modelist[modenum].height) - vid.conheight = modelist[modenum].height; - if (vid.conwidth > modelist[modenum].width) - vid.conwidth = modelist[modenum].width; - vid.width = vid.conwidth; - vid.height = vid.conheight; - - vid.numpages = 2; - - mainwindow = dibwindow; - - SendMessage (mainwindow, WM_SETICON, (WPARAM)TRUE, (LPARAM)hIcon); - SendMessage (mainwindow, WM_SETICON, (WPARAM)FALSE, (LPARAM)hIcon); - - return true; -} - - -qboolean VID_SetFullDIBMode (int modenum) -{ - int lastmodestate, width, height; - RECT rect; - - if (!leavecurrentmode) - { - gdevmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; - gdevmode.dmBitsPerPel = modelist[modenum].bpp; - gdevmode.dmPelsWidth = modelist[modenum].width << - modelist[modenum].halfscreen; - gdevmode.dmPelsHeight = modelist[modenum].height; - gdevmode.dmSize = sizeof (gdevmode); - - if (ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) - Sys_Error ("Couldn't set fullscreen DIB mode"); - } - - lastmodestate = modestate; - modestate = MS_FULLDIB; - - WindowRect.top = WindowRect.left = 0; - - WindowRect.right = modelist[modenum].width; - WindowRect.bottom = modelist[modenum].height; - - DIBWidth = modelist[modenum].width; - DIBHeight = modelist[modenum].height; - - WindowStyle = WS_POPUP; - ExWindowStyle = 0; - - rect = WindowRect; - AdjustWindowRectEx(&rect, WindowStyle, FALSE, 0); - - width = rect.right - rect.left; - height = rect.bottom - rect.top; - - // Create the DIB window - dibwindow = CreateWindowEx ( - ExWindowStyle, -#ifdef NEHAHRA - "DPNehahraQuake", - "DPNehahraGLQuake", -#else - "DarkPlacesQuake", - "DarkPlacesGLQuake", +#ifndef MK_XBUTTON1 + #define MK_XBUTTON1 0x0020 + #define MK_XBUTTON2 0x0040 +// LordHavoc: lets hope this allows more buttons in the future... + #define MK_XBUTTON3 0x0080 + #define MK_XBUTTON4 0x0100 + #define MK_XBUTTON5 0x0200 + #define MK_XBUTTON6 0x0400 + #define MK_XBUTTON7 0x0800 #endif - WindowStyle, - rect.left, rect.top, - width, - height, - NULL, - NULL, - global_hInstance, - NULL); - - if (!dibwindow) - Sys_Error ("Couldn't create DIB window"); - - ShowWindow (dibwindow, SW_SHOWDEFAULT); - UpdateWindow (dibwindow); - - // LordHavoc: using GDI functions on an OpenGL window? bad idea - /* - // Because we have set the background brush for the window to NULL - // (to avoid flickering when re-sizing the window on the desktop), we - // clear the window to black when created, otherwise it will be - // empty while Quake starts up. - hdc = GetDC(dibwindow); - PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS); - ReleaseDC(dibwindow, hdc); - */ - - if (vid.conheight > modelist[modenum].height) - vid.conheight = modelist[modenum].height; - if (vid.conwidth > modelist[modenum].width) - vid.conwidth = modelist[modenum].width; - vid.width = vid.conwidth; - vid.height = vid.conheight; - - vid.numpages = 2; - -// needed because we're not getting WM_MOVE messages fullscreen on NT - window_x = 0; - window_y = 0; - - mainwindow = dibwindow; - - SendMessage (mainwindow, WM_SETICON, (WPARAM)TRUE, (LPARAM)hIcon); - SendMessage (mainwindow, WM_SETICON, (WPARAM)FALSE, (LPARAM)hIcon); - - return true; -} - - -int VID_SetMode (int modenum, unsigned char *palette) +/* :: backslash */ + +// mouse variables +int mouse_buttons; +int mouse_oldbuttonstate; +POINT current_pos; +int mouse_x, mouse_y, old_mouse_x, old_mouse_y, mx_accum, my_accum; + +static qboolean restore_spi; +static int originalmouseparms[3], newmouseparms[3] = {0, 0, 1}; + +unsigned int uiWheelMessage; +qboolean mouseactive; +//qboolean mouseinitialized; +static qboolean mouseparmsvalid, mouseactivatetoggle; +static qboolean mouseshowtoggle = 1; +static qboolean dinput_acquired; + +static unsigned int mstate_di; + +// joystick defines and variables +// where should defines be moved? +#define JOY_ABSOLUTE_AXIS 0x00000000 // control like a joystick +#define JOY_RELATIVE_AXIS 0x00000010 // control like a mouse, spinner, trackball +#define JOY_MAX_AXES 6 // X, Y, Z, R, U, V +#define JOY_AXIS_X 0 +#define JOY_AXIS_Y 1 +#define JOY_AXIS_Z 2 +#define JOY_AXIS_R 3 +#define JOY_AXIS_U 4 +#define JOY_AXIS_V 5 + +enum _ControlList { - int original_mode, temp; - qboolean stat; - MSG msg; - - if ((windowed && (modenum != 0)) || - (!windowed && (modenum < 1)) || - (!windowed && (modenum >= nummodes))) - { - Sys_Error ("Bad video mode\n"); - } - -// so Con_Printfs don't mess us up by forcing vid and snd updates - temp = scr_disabled_for_loading; - scr_disabled_for_loading = true; - - CDAudio_Pause (); - - if (vid_modenum == NO_MODE) - original_mode = windowed_default; - else - original_mode = vid_modenum; - - // Set either the fullscreen or windowed mode - if (modelist[modenum].type == MS_WINDOWED) - { - if (_windowed_mouse.value && key_dest == key_game) - { - stat = VID_SetWindowedMode(modenum); - IN_ActivateMouse (); - IN_HideMouse (); - } - else - { - IN_DeactivateMouse (); - IN_ShowMouse (); - stat = VID_SetWindowedMode(modenum); - } - } - else if (modelist[modenum].type == MS_FULLDIB) - { - stat = VID_SetFullDIBMode(modenum); - IN_ActivateMouse (); - IN_HideMouse (); - } - else - { - Sys_Error ("VID_SetMode: Bad mode type in modelist"); - } - - window_width = DIBWidth; - window_height = DIBHeight; - VID_UpdateWindowStatus (); - - CDAudio_Resume (); - scr_disabled_for_loading = temp; - - if (!stat) - { - Sys_Error ("Couldn't set video mode"); - } - -// now we try to make sure we get the focus on the mode switch, because -// sometimes in some systems we don't. We grab the foreground, then -// finish setting up, pump all our messages, and sleep for a little while -// to let messages finish bouncing around the system, then we put -// ourselves at the top of the z order, then grab the foreground again, -// Who knows if it helps, but it probably doesn't hurt - SetForegroundWindow (mainwindow); - VID_SetPalette (palette); - vid_modenum = modenum; - Cvar_SetValue ("vid_mode", (float)vid_modenum); - - while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) - { - TranslateMessage (&msg); - DispatchMessage (&msg); - } - - Sleep (100); - - SetWindowPos (mainwindow, HWND_TOP, 0, 0, 0, 0, - SWP_DRAWFRAME | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | - SWP_NOCOPYBITS); - - SetForegroundWindow (mainwindow); - -// fix the leftover Alt from any Alt-Tab or the like that switched us away - ClearAllStates (); + AxisNada = 0, AxisForward, AxisLook, AxisSide, AxisTurn +}; - if (!msg_suppress_1) - Con_SafePrintf ("Video mode %s initialized.\n", VID_GetModeDescription (vid_modenum)); +DWORD dwAxisFlags[JOY_MAX_AXES] = +{ + JOY_RETURNX, JOY_RETURNY, JOY_RETURNZ, JOY_RETURNR, JOY_RETURNU, JOY_RETURNV +}; - VID_SetPalette (palette); +DWORD dwAxisMap[JOY_MAX_AXES]; +DWORD dwControlMap[JOY_MAX_AXES]; +PDWORD pdwRawValue[JOY_MAX_AXES]; + +// none of these cvars are saved over a session +// this means that advanced controller configuration needs to be executed +// each time. this avoids any problems with getting back to a default usage +// or when changing from one controller to another. this way at least something +// works. +cvar_t in_joystick = {CVAR_SAVE, "joystick","0"}; +cvar_t joy_name = {0, "joyname", "joystick"}; +cvar_t joy_advanced = {0, "joyadvanced", "0"}; +cvar_t joy_advaxisx = {0, "joyadvaxisx", "0"}; +cvar_t joy_advaxisy = {0, "joyadvaxisy", "0"}; +cvar_t joy_advaxisz = {0, "joyadvaxisz", "0"}; +cvar_t joy_advaxisr = {0, "joyadvaxisr", "0"}; +cvar_t joy_advaxisu = {0, "joyadvaxisu", "0"}; +cvar_t joy_advaxisv = {0, "joyadvaxisv", "0"}; +cvar_t joy_forwardthreshold = {0, "joyforwardthreshold", "0.15"}; +cvar_t joy_sidethreshold = {0, "joysidethreshold", "0.15"}; +cvar_t joy_pitchthreshold = {0, "joypitchthreshold", "0.15"}; +cvar_t joy_yawthreshold = {0, "joyyawthreshold", "0.15"}; +cvar_t joy_forwardsensitivity = {0, "joyforwardsensitivity", "-1.0"}; +cvar_t joy_sidesensitivity = {0, "joysidesensitivity", "-1.0"}; +cvar_t joy_pitchsensitivity = {0, "joypitchsensitivity", "1.0"}; +cvar_t joy_yawsensitivity = {0, "joyyawsensitivity", "-1.0"}; +cvar_t joy_wwhack1 = {0, "joywwhack1", "0.0"}; +cvar_t joy_wwhack2 = {0, "joywwhack2", "0.0"}; + +qboolean joy_avail, joy_advancedinit, joy_haspov; +DWORD joy_oldbuttonstate, joy_oldpovstate; + +int joy_id; +DWORD joy_flags; +DWORD joy_numbuttons; + +static LPDIRECTINPUT g_pdi; +static LPDIRECTINPUTDEVICE g_pMouse; + +static JOYINFOEX ji; + +static HINSTANCE hInstDI; + +//static qboolean dinput; + +typedef struct MYDATA { + LONG lX; // X axis goes here + LONG lY; // Y axis goes here + LONG lZ; // Z axis goes here + BYTE bButtonA; // One button goes here + BYTE bButtonB; // Another button goes here + BYTE bButtonC; // Another button goes here + BYTE bButtonD; // Another button goes here +} MYDATA; + +static DIOBJECTDATAFORMAT rgodf[] = { + { &GUID_XAxis, FIELD_OFFSET(MYDATA, lX), DIDFT_AXIS | DIDFT_ANYINSTANCE, 0,}, + { &GUID_YAxis, FIELD_OFFSET(MYDATA, lY), DIDFT_AXIS | DIDFT_ANYINSTANCE, 0,}, + { &GUID_ZAxis, FIELD_OFFSET(MYDATA, lZ), 0x80000000 | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0,}, + { 0, FIELD_OFFSET(MYDATA, bButtonA), DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,}, + { 0, FIELD_OFFSET(MYDATA, bButtonB), DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,}, + { 0, FIELD_OFFSET(MYDATA, bButtonC), 0x80000000 | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,}, + { 0, FIELD_OFFSET(MYDATA, bButtonD), 0x80000000 | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,}, +}; - vid.recalc_refdef = 1; +#define NUM_OBJECTS (sizeof(rgodf) / sizeof(rgodf[0])) - return true; -} +static DIDATAFORMAT df = { + sizeof(DIDATAFORMAT), // this structure + sizeof(DIOBJECTDATAFORMAT), // size of object data format + DIDF_RELAXIS, // absolute axis coordinates + sizeof(MYDATA), // device data size + NUM_OBJECTS, // number of objects + rgodf, // and here they are +}; +// forward-referenced functions +void IN_StartupJoystick (void); +void Joy_AdvancedUpdate_f (void); +void IN_JoyMove (usercmd_t *cmd); +void IN_StartupMouse (void); /* ================ @@ -474,324 +260,94 @@ VID_UpdateWindowStatus */ void VID_UpdateWindowStatus (void) { + window_center_x = window_x + window_width / 2; + window_center_y = window_y + window_height / 2; - 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 (); -} - - -//==================================== - -void CheckVertexArrays (void) -{ - if (COM_CheckParm("-novertex")) - { - Con_Printf("...vertex array support disabled\n"); - return; - } - if ((qglArrayElement = (void *) wglGetProcAddress("glArrayElement")) - && (qglColorPointer = (void *) wglGetProcAddress("glColorPointer")) -// && (qglDrawArrays = (void *) wglGetProcAddress("glDrawArrays")) - && (qglDrawElements = (void *) wglGetProcAddress("glDrawElements")) -// && (qglInterleavedArrays = (void *) wglGetProcAddress("glInterleavedArrays")) - && (qglTexCoordPointer = (void *) wglGetProcAddress("glTexCoordPointer")) - && (qglVertexPointer = (void *) wglGetProcAddress("glVertexPointer")) - ) - { - Con_Printf("...vertex array support detected\n"); - gl_arrays = true; - return; - } - - Con_Printf("...vertex array support disabled (not detected - get a better driver)\n"); -} - -int texture_extension_number = 1; - -void CheckMultiTexture(void) -{ - qglMTexCoord2f = NULL; - qglSelectTexture = NULL; - // Check to see if multitexture is disabled - if (COM_CheckParm("-nomtex")) - { - Con_Printf("...multitexture disabled\n"); - return; - } - // Test for ARB_multitexture - if (!COM_CheckParm("-SGISmtex") && strstr(gl_extensions, "GL_ARB_multitexture ")) - { - Con_Printf("...using GL_ARB_multitexture\n"); - qglMTexCoord2f = (void *) wglGetProcAddress("glMultiTexCoord2fARB"); - qglSelectTexture = (void *) wglGetProcAddress("glActiveTextureARB"); - gl_mtexable = true; - gl_mtex_enum = GL_TEXTURE0_ARB; - } - else if (strstr(gl_extensions, "GL_SGIS_multitexture ")) // Test for SGIS_multitexture (if ARB_multitexture not found) + if (mouseinitialized && mouseactive && !dinput) { - Con_Printf("...using GL_SGIS_multitexture\n"); - qglMTexCoord2f = (void *) wglGetProcAddress("glMTexCoord2fSGIS"); - qglSelectTexture = (void *) wglGetProcAddress("glSelectTextureSGIS"); - gl_mtexable = true; - gl_mtex_enum = TEXTURE0_SGIS; + RECT window_rect; + window_rect.left = window_x; + window_rect.top = window_y; + window_rect.right = window_x + window_width; + window_rect.bottom = window_y + window_height; + ClipCursor (&window_rect); } - if (!gl_mtexable) - Con_Printf("...multitexture disabled (not detected)\n"); } -/* -=============== -GL_Init -=============== -*/ -extern char *QSG_EXTENSIONS; -void GL_Init (void) -{ - gl_vendor = glGetString (GL_VENDOR); - Con_Printf ("GL_VENDOR: %s\n", gl_vendor); - gl_renderer = glGetString (GL_RENDERER); - Con_Printf ("GL_RENDERER: %s\n", gl_renderer); - - gl_version = glGetString (GL_VERSION); - Con_Printf ("GL_VERSION: %s\n", gl_version); - gl_extensions = glGetString (GL_EXTENSIONS); - Con_Printf ("GL_EXTENSIONS: %s\n", gl_extensions); - -// Con_Printf ("%s %s\n", gl_renderer, gl_version); - - if (strnicmp(gl_renderer,"Permedia",8)==0) - isPermedia = true; - - // LordHavoc: special differences for ATI (broken 8bit color when also using 32bit? weird!) - if (strnicmp(gl_vendor,"ATI",3)==0) - { - isATI = true; - if (strnicmp(gl_renderer,"Rage Pro",8)==0) - isRagePro = true; - } - if (strnicmp(gl_renderer,"Matrox G200 Direct3D",20)==0) // a D3D driver for GL? sigh... - isG200 = true; - CheckMultiTexture (); - CheckVertexArrays (); - - // LordHavoc: report supported extensions - Con_Printf ("\nQSG extensions: %s\n", QSG_EXTENSIONS); - - // LordHavoc: set up state -// glEnable(GL_DEPTH_TEST); -// glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); -// glShadeModel(GL_SMOOTH); -// glEnable(GL_TEXTURE_2D); - glAlphaFunc(GL_GREATER, 0.5); -// if (isRagePro || isG200) -// { -// glEnable(GL_ALPHA_TEST); -// glAlphaFunc(GL_GREATER, 0.5); -// } -// else -// glDisable(GL_ALPHA_TEST); -// glDepthMask(1); -// glDisable(GL_DITHER); // LordHavoc: disable dithering -// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); -// glEnable(GL_BLEND); - -// glClearColor (0,0,0,0); // LordHavoc: changed from red to black - glCullFace(GL_FRONT); - -// glAlphaFunc(GL_GREATER, 0.666); -} +//==================================== /* ================= -GL_BeginRendering - +VID_GetWindowSize ================= */ -void GL_BeginRendering (int *x, int *y, int *width, int *height) +void VID_GetWindowSize (int *x, int *y, int *width, int *height) { -// extern cvar_t gl_clear; - - *x = *y = 0; - *width = WindowRect.right - WindowRect.left; - *height = WindowRect.bottom - WindowRect.top; - -// if (!wglMakeCurrent( maindc, baseRC )) -// Sys_Error ("wglMakeCurrent failed"); - -// glViewport (*x, *y, *width, *height); + *x = 0; + *y = 0; + *width = window_width; + *height = window_height; } -void GL_EndRendering (void) +void VID_Finish (void) { - if (!scr_skipupdate) - SwapBuffers(maindc); + HDC hdc; + int vid_usemouse; + if (r_render.integer && !scr_skipupdate) + { + qglFinish(); + hdc = GetDC(mainwindow); + SwapBuffers(hdc); + ReleaseDC(mainwindow, hdc); + } // handle the mouse state when windowed if that's changed - if (modestate == MS_WINDOWED) + vid_usemouse = false; + if (vid_mouse.integer && !key_consoleactive) + vid_usemouse = true; + if (vid_isfullscreen) + vid_usemouse = true; + if (!vid_activewindow) + vid_usemouse = false; + if (vid_usemouse) { - if (!_windowed_mouse.value) - { - if (windowed_mouse) - { - IN_DeactivateMouse (); - IN_ShowMouse (); - windowed_mouse = false; - } - } - else + if (!vid_usingmouse) { - windowed_mouse = true; - if (key_dest == key_game && !mouseactive && ActiveApp) - { - IN_ActivateMouse (); - IN_HideMouse (); - } - else if (mouseactive && key_dest != key_game) - { - IN_DeactivateMouse (); - IN_ShowMouse (); - } + vid_usingmouse = true; + IN_ActivateMouse (); + IN_HideMouse(); } } -} - -void VID_SetDefaultMode (void) -{ - IN_DeactivateMouse (); -} - - -void VID_Shutdown (void) -{ - HGLRC hRC; - HDC hDC; - int i; - GLuint temp[8192]; - - if (vid_initialized) + else { - vid_canalttab = false; - hRC = wglGetCurrentContext(); - hDC = wglGetCurrentDC(); - - wglMakeCurrent(NULL, NULL); - - // LordHavoc: free textures before closing (may help NVIDIA) - for (i = 0;i < 8192;i++) temp[i] = i; - glDeleteTextures(8192, temp); - - if (hRC) - wglDeleteContext(hRC); - - if (hDC && dibwindow) - ReleaseDC(dibwindow, hDC); - - if (modestate == MS_FULLDIB) - ChangeDisplaySettings (NULL, 0); - - if (maindc && dibwindow) - ReleaseDC (dibwindow, maindc); - - AppActivate(false, false); + if (vid_usingmouse) + { + vid_usingmouse = false; + IN_DeactivateMouse (); + IN_ShowMouse(); + } } } - //========================================================================== -BOOL bSetupPixelFormat(HDC hDC) -{ - static PIXELFORMATDESCRIPTOR pfd = { - sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd - 1, // version number - PFD_DRAW_TO_WINDOW // support window - | PFD_SUPPORT_OPENGL // support OpenGL - | PFD_DOUBLEBUFFER , // double buffered - PFD_TYPE_RGBA, // RGBA type - 24, // 24-bit color depth - 0, 0, 0, 0, 0, 0, // color bits ignored - 0, // no alpha buffer - 0, // shift bit ignored - 0, // no accumulation buffer - 0, 0, 0, 0, // accum bits ignored - 32, // 32-bit z-buffer - 0, // no stencil buffer - 0, // no auxiliary buffer - PFD_MAIN_PLANE, // main layer - 0, // reserved - 0, 0, 0 // layer masks ignored - }; - int pixelformat; - - if ( (pixelformat = ChoosePixelFormat(hDC, &pfd)) == 0 ) - { - MessageBox(NULL, "ChoosePixelFormat failed", "Error", MB_OK); - return FALSE; - } - - if (SetPixelFormat(hDC, pixelformat, &pfd) == FALSE) - { - MessageBox(NULL, "SetPixelFormat failed", "Error", MB_OK); - return FALSE; - } - - return TRUE; -} - -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 - }; - -byte shiftscantokey[128] = - { -// 0 1 2 3 4 5 6 7 -// 8 9 A B C D E F - 0 , 27, '!', '@', '#', '$', '%', '^', - '&', '*', '(', ')', '_', '+', 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,'%',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 - }; +qbyte 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_KP_MINUS,K_LEFTARROW,K_KP_5,K_RIGHTARROW,K_KP_PLUS ,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 +}; /* @@ -801,14 +357,64 @@ MapKey Map from windows to quake keynums ======= */ -int MapKey (int key) +int MapKey (int key, int virtualkey) { - key = (key>>16)&255; - if (key > 127) - return 0; - if (scantokey[key] == 0) - Con_DPrintf("key 0x%02x has no translation\n", key); - return scantokey[key]; + int result; + int modified = (key >> 16) & 255; + qboolean is_extended = false; + + if (modified < 128 && scantokey[modified]) + result = scantokey[modified]; + else + { + result = 0; + Con_DPrintf("key 0x%02x (0x%8x, 0x%8x) has no translation\n", modified, key, virtualkey); + } + + if (key & (1 << 24)) + is_extended = true; + + if ( !is_extended ) + { + switch ( result ) + { + case K_HOME: + return K_KP_HOME; + case K_UPARROW: + return K_KP_UPARROW; + case K_PGUP: + return K_KP_PGUP; + case K_LEFTARROW: + return K_KP_LEFTARROW; + case K_RIGHTARROW: + return K_KP_RIGHTARROW; + case K_END: + return K_KP_END; + case K_DOWNARROW: + return K_KP_DOWNARROW; + case K_PGDN: + return K_KP_PGDN; + case K_INS: + return K_KP_INS; + case K_DEL: + return K_KP_DEL; + default: + return result; + } + } + else + { + switch ( result ) + { + case 0x0D: + return K_KP_ENTER; + case 0x2F: + return K_KP_SLASH; + case 0xAF: + return K_KP_PLUS; + } + return result; + } } /* @@ -826,18 +432,12 @@ 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 (); } +extern qboolean host_loopactive; + void AppActivate(BOOL fActive, BOOL minimize) /**************************************************************************** * @@ -852,16 +452,16 @@ void AppActivate(BOOL fActive, BOOL minimize) { static BOOL sound_active; - ActiveApp = fActive; - Minimized = minimize; + vid_activewindow = fActive; + vid_hidden = minimize; // enable/disable sound on focus gain/loss - if (!ActiveApp && sound_active) + if (!vid_activewindow && sound_active) { S_BlockSound (); sound_active = false; } - else if (ActiveApp && !sound_active) + else if (vid_activewindow && !sound_active) { S_UnblockSound (); sound_active = true; @@ -869,62 +469,55 @@ void AppActivate(BOOL fActive, BOOL minimize) if (fActive) { - if (modestate == MS_FULLDIB) + if (vid_isfullscreen) { - IN_ActivateMouse (); - IN_HideMouse (); - if (vid_canalttab && vid_wassuspended) { + if (vid_wassuspended) + { vid_wassuspended = false; ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN); ShowWindow(mainwindow, SW_SHOWNORMAL); } - } - else if ((modestate == MS_WINDOWED) && _windowed_mouse.value && key_dest == key_game) - { - IN_ActivateMouse (); - IN_HideMouse (); + + // LordHavoc: from dabb, fix for alt-tab bug in NVidia drivers + MoveWindow(mainwindow,0,0,gdevmode.dmPelsWidth,gdevmode.dmPelsHeight,false); } } if (!fActive) { - if (modestate == MS_FULLDIB) - { - IN_DeactivateMouse (); - IN_ShowMouse (); - if (vid_canalttab) { - ChangeDisplaySettings (NULL, 0); - vid_wassuspended = true; - } - } - else if ((modestate == MS_WINDOWED) && _windowed_mouse.value) + vid_usingmouse = false; + IN_DeactivateMouse (); + IN_ShowMouse (); + if (vid_isfullscreen) { - IN_DeactivateMouse (); - IN_ShowMouse (); + ChangeDisplaySettings (NULL, 0); + vid_wassuspended = true; } + VID_RestoreSystemGamma(); } } 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 WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { - LONG lRet = 1; + LONG lRet = 1; int fActive, fMinimized, temp; + char state[256]; + char asciichar[4]; + int vkey; + qboolean down = false; + extern unsigned int uiWheelMessage; if ( uMsg == uiWheelMessage ) uMsg = WM_MOUSEWHEEL; - switch (uMsg) - { + switch (uMsg) + { case WM_KILLFOCUS: - if (modestate == MS_FULLDIB) + if (vid_isfullscreen) ShowWindow(mainwindow, SW_SHOWMINNOACTIVE); break; @@ -936,15 +529,19 @@ LONG WINAPI MainWndProc ( window_y = (int) HIWORD(lParam); VID_UpdateWindowStatus (); break; - + case WM_KEYDOWN: case WM_SYSKEYDOWN: - Key_Event (MapKey(lParam), true); - break; - + down = true; case WM_KEYUP: case WM_SYSKEYUP: - Key_Event (MapKey(lParam), false); + vkey = MapKey(lParam, wParam); + GetKeyboardState (state); + // alt/ctrl/shift tend to produce funky ToAscii values, + // and if it's not a single character we don't know care about it + if (vkey == K_ALT || vkey == K_CTRL || vkey == K_SHIFT || ToAscii (wParam, lParam >> 16, state, asciichar, 0) != 1) + asciichar[0] = 0; + Key_Event (vkey, asciichar[0], down); break; case WM_SYSCHAR: @@ -959,6 +556,8 @@ LONG WINAPI MainWndProc ( case WM_RBUTTONUP: case WM_MBUTTONDOWN: case WM_MBUTTONUP: + case WM_XBUTTONDOWN: // backslash :: imouse explorer buttons + case WM_XBUTTONUP: // backslash :: imouse explorer buttons case WM_MOUSEMOVE: temp = 0; @@ -971,6 +570,26 @@ LONG WINAPI MainWndProc ( if (wParam & MK_MBUTTON) temp |= 4; + /* backslash :: imouse explorer buttons */ + if (wParam & MK_XBUTTON1) + temp |= 8; + + if (wParam & MK_XBUTTON2) + temp |= 16; + /* :: backslash */ + + // LordHavoc: lets hope this allows more buttons in the future... + if (wParam & MK_XBUTTON3) + temp |= 32; + if (wParam & MK_XBUTTON4) + temp |= 64; + if (wParam & MK_XBUTTON5) + temp |= 128; + if (wParam & MK_XBUTTON6) + temp |= 256; + if (wParam & MK_XBUTTON7) + temp |= 512; + IN_MouseEvent (temp); break; @@ -978,27 +597,24 @@ LONG WINAPI MainWndProc ( // 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: + case WM_MOUSEWHEEL: if ((short) HIWORD(wParam) > 0) { - Key_Event(K_MWHEELUP, true); - Key_Event(K_MWHEELUP, false); + Key_Event(K_MWHEELUP, 0, true); + Key_Event(K_MWHEELUP, 0, false); } else { - Key_Event(K_MWHEELDOWN, true); - Key_Event(K_MWHEELDOWN, false); + Key_Event(K_MWHEELDOWN, 0, true); + Key_Event(K_MWHEELDOWN, 0, false); } break; - case WM_SIZE: - break; + case WM_SIZE: + break; - case WM_CLOSE: - if (MessageBox (mainwindow, "Are you sure you want to quit?", "Confirm Exit", - MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION) == IDYES) - { + case WM_CLOSE: + if (MessageBox (mainwindow, "Are you sure you want to quit?", "Confirm Exit", MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION) == IDYES) Sys_Quit (); - } - break; + break; case WM_ACTIVATE: fActive = LOWORD(wParam); @@ -1010,812 +626,1337 @@ LONG WINAPI MainWndProc ( break; - case WM_DESTROY: - { - if (dibwindow) - DestroyWindow (dibwindow); - - PostQuitMessage (0); - } - break; + //case WM_DESTROY: + // PostQuitMessage (0); + // break; case MM_MCINOTIFY: - lRet = CDAudio_MessageHandler (hWnd, uMsg, wParam, lParam); + lRet = CDAudio_MessageHandler (hWnd, uMsg, wParam, lParam); break; - default: - /* pass all unhandled messages to DefWindowProc */ - lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); - break; - } + default: + /* pass all unhandled messages to DefWindowProc */ + lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); + break; + } - /* return 1 if handled message, 0 if not */ - return lRet; + /* return 1 if handled message, 0 if not */ + return lRet; } +int VID_SetGamma(unsigned short *ramps) +{ + HDC hdc = GetDC (NULL); + int i = SetDeviceGammaRamp(hdc, ramps); + ReleaseDC (NULL, hdc); + return i; // return success or failure +} -/* -================= -VID_NumModes -================= -*/ -int VID_NumModes (void) +int VID_GetGamma(unsigned short *ramps) { - return nummodes; + HDC hdc = GetDC (NULL); + int i = GetDeviceGammaRamp(hdc, ramps); + ReleaseDC (NULL, hdc); + return i; // return success or failure } - -/* -================= -VID_GetModePtr -================= -*/ -vmode_t *VID_GetModePtr (int modenum) +static HINSTANCE gldll; + +int GL_OpenLibrary(const char *name) { + Con_Printf("Loading OpenGL driver %s\n", name); + GL_CloseLibrary(); + if (!(gldll = LoadLibrary(name))) + { + Con_Printf("Unable to LoadLibrary %s\n", name); + return false; + } + strcpy(gl_driver, name); + return true; +} - if ((modenum >= 0) && (modenum < nummodes)) - return &modelist[modenum]; - else - return &badmode; +void GL_CloseLibrary(void) +{ + FreeLibrary(gldll); + gldll = 0; + gl_driver[0] = 0; + qwglGetProcAddress = NULL; + gl_extensions = ""; + gl_platform = ""; + gl_platformextensions = ""; +} + +void *GL_GetProcAddress(const char *name) +{ + void *p = NULL; + if (qwglGetProcAddress != NULL) + p = (void *) qwglGetProcAddress(name); + if (p == NULL) + p = (void *) GetProcAddress(gldll, name); + return p; } +static void IN_Init(void); +void VID_Init(void) +{ + WNDCLASS wc; -/* -================= -VID_GetModeDescription -================= -*/ -char *VID_GetModeDescription (int mode) + InitCommonControls(); + hIcon = LoadIcon (global_hInstance, MAKEINTRESOURCE (IDI_ICON2)); + + // Register the frame class + wc.style = 0; + wc.lpfnWndProc = (WNDPROC)MainWndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = global_hInstance; + wc.hIcon = 0; + wc.hCursor = LoadCursor (NULL,IDC_ARROW); + wc.hbrBackground = NULL; + wc.lpszMenuName = 0; + wc.lpszClassName = "DarkPlacesWindowClass"; + + if (!RegisterClass (&wc)) + Sys_Error("Couldn't register window class\n"); + + IN_Init(); +} + +int VID_InitMode (int fullscreen, int width, int height, int bpp) { - char *pinfo; - vmode_t *pv; - static char temp[100]; + int i; + HDC hdc; + RECT rect; + MSG msg; + PIXELFORMATDESCRIPTOR pfd = + { + sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd + 1, // version number + PFD_DRAW_TO_WINDOW // support window + | PFD_SUPPORT_OPENGL // support OpenGL + | PFD_DOUBLEBUFFER , // double buffered + PFD_TYPE_RGBA, // RGBA type + 24, // 24-bit color depth + 0, 0, 0, 0, 0, 0, // color bits ignored + 0, // no alpha buffer + 0, // shift bit ignored + 0, // no accumulation buffer + 0, 0, 0, 0, // accum bits ignored + 32, // 32-bit z-buffer + 0, // no stencil buffer + 0, // no auxiliary buffer + PFD_MAIN_PLANE, // main layer + 0, // reserved + 0, 0, 0 // layer masks ignored + }; + int pixelformat; + DWORD WindowStyle, ExWindowStyle; + HGLRC baseRC; + int CenterX, CenterY; + const char *gldrivername; + int depth; - if ((mode < 0) || (mode >= nummodes)) - return NULL; + if (vid_initialized) + Sys_Error("VID_InitMode called when video is already initialised\n"); - if (!leavecurrentmode) + // if stencil is enabled, ask for alpha too + if (bpp >= 32) { - pv = VID_GetModePtr (mode); - pinfo = pv->modedesc; + pfd.cStencilBits = 8; + pfd.cAlphaBits = 8; } else { - sprintf (temp, "Desktop resolution (%dx%d)", - modelist[MODE_FULLSCREEN_DEFAULT].width, - modelist[MODE_FULLSCREEN_DEFAULT].height); - pinfo = temp; + pfd.cStencilBits = 0; + pfd.cAlphaBits = 0; } - return pinfo; -} - - -// KJB: Added this to return the mode driver name in description for console + gldrivername = "opengl32.dll"; + i = COM_CheckParm("-gl_driver"); + if (i && i < com_argc - 1) + gldrivername = com_argv[i + 1]; + if (!GL_OpenLibrary(gldrivername)) + { + Con_Printf("Unable to load GL driver %s\n", gldrivername); + return false; + } -char *VID_GetExtModeDescription (int mode) -{ - static char pinfo[40]; - vmode_t *pv; + memset(&gdevmode, 0, sizeof(gdevmode)); - if ((mode < 0) || (mode >= nummodes)) - return NULL; + vid_isfullscreen = false; + if (fullscreen) + { + gdevmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; + gdevmode.dmBitsPerPel = bpp; + gdevmode.dmPelsWidth = width; + gdevmode.dmPelsHeight = height; + gdevmode.dmSize = sizeof (gdevmode); + if (ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) + { + VID_Shutdown(); + Con_Printf("Unable to change to requested mode %dx%dx%dbpp\n", width, height, bpp); + return false; + } - pv = VID_GetModePtr (mode); - if (modelist[mode].type == MS_FULLDIB) + vid_isfullscreen = true; + WindowStyle = WS_POPUP; + ExWindowStyle = WS_EX_TOPMOST; + } + else { - if (!leavecurrentmode) + hdc = GetDC (NULL); + i = GetDeviceCaps(hdc, RASTERCAPS); + depth = GetDeviceCaps(hdc, PLANES) * GetDeviceCaps(hdc, BITSPIXEL); + ReleaseDC (NULL, hdc); + if (i & RC_PALETTE) { - sprintf(pinfo,"%s fullscreen", pv->modedesc); + VID_Shutdown(); + Con_Printf ("Can't run in non-RGB mode\n"); + return false; } - else + if (bpp > depth) { - sprintf (pinfo, "Desktop resolution (%dx%d)", - modelist[MODE_FULLSCREEN_DEFAULT].width, - modelist[MODE_FULLSCREEN_DEFAULT].height); + VID_Shutdown(); + Con_Printf ("A higher desktop depth is required to run this video mode\n"); + return false; } + + WindowStyle = WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX; + ExWindowStyle = 0; + } + + rect.top = 0; + rect.left = 0; + rect.right = width; + rect.bottom = height; + AdjustWindowRectEx(&rect, WindowStyle, false, 0); + + if (fullscreen) + { + CenterX = 0; + CenterY = 0; } else { - if (modestate == MS_WINDOWED) - sprintf(pinfo, "%s windowed", pv->modedesc); - else - sprintf(pinfo, "windowed"); + CenterX = (GetSystemMetrics(SM_CXSCREEN) - (rect.right - rect.left)) / 2; + CenterY = (GetSystemMetrics(SM_CYSCREEN) - (rect.bottom - rect.top)) / 2; + } + CenterX = max(0, CenterX); + CenterY = max(0, CenterY); + + // x and y may be changed by WM_MOVE messages + window_x = CenterX; + window_y = CenterY; + window_width = width; + window_height = height; + rect.left += CenterX; + rect.right += CenterX; + rect.top += CenterY; + rect.bottom += CenterY; + + mainwindow = CreateWindowEx (ExWindowStyle, "DarkPlacesWindowClass", gamename, WindowStyle, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, global_hInstance, NULL); + if (!mainwindow) + { + Con_Printf("CreateWindowEx(%d, %s, %s, %d, %d, %d, %d, %d, %p, %p, %d, %p) failed\n", ExWindowStyle, "DarkPlacesWindowClass", gamename, WindowStyle, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, global_hInstance, NULL); + VID_Shutdown(); + return false; } - return pinfo; + /* + if (!fullscreen) + SetWindowPos (mainwindow, NULL, CenterX, CenterY, 0, 0,SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME); + */ + + ShowWindow (mainwindow, SW_SHOWDEFAULT); + UpdateWindow (mainwindow); + + SendMessage (mainwindow, WM_SETICON, (WPARAM)true, (LPARAM)hIcon); + SendMessage (mainwindow, WM_SETICON, (WPARAM)false, (LPARAM)hIcon); + + VID_UpdateWindowStatus (); + + // now we try to make sure we get the focus on the mode switch, because + // sometimes in some systems we don't. We grab the foreground, then + // finish setting up, pump all our messages, and sleep for a little while + // to let messages finish bouncing around the system, then we put + // ourselves at the top of the z order, then grab the foreground again, + // Who knows if it helps, but it probably doesn't hurt + SetForegroundWindow (mainwindow); + + while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage (&msg); + DispatchMessage (&msg); + } + + Sleep (100); + + SetWindowPos (mainwindow, HWND_TOP, 0, 0, 0, 0, SWP_DRAWFRAME | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOCOPYBITS); + + SetForegroundWindow (mainwindow); + + // fix the leftover Alt from any Alt-Tab or the like that switched us away + ClearAllStates (); + + hdc = GetDC(mainwindow); + + if ((pixelformat = ChoosePixelFormat(hdc, &pfd)) == 0) + { + VID_Shutdown(); + Con_Printf("ChoosePixelFormat(%d, %p) failed\n", hdc, &pfd); + return false; + } + + if (SetPixelFormat(hdc, pixelformat, &pfd) == false) + { + VID_Shutdown(); + Con_Printf("SetPixelFormat(%d, %d, %p) failed\n", hdc, pixelformat, &pfd); + return false; + } + + if (!GL_CheckExtension("wgl", wglfuncs, NULL, false)) + { + VID_Shutdown(); + Con_Printf("wgl functions not found\n"); + return false; + } + + baseRC = qwglCreateContext(hdc); + if (!baseRC) + { + VID_Shutdown(); + Con_Printf("Could not initialize GL (wglCreateContext failed).\n\nMake sure you are in 65536 color mode, and try running -window.\n"); + return false; + } + if (!qwglMakeCurrent(hdc, baseRC)) + { + VID_Shutdown(); + Con_Printf("wglMakeCurrent(%d, %d) failed\n", hdc, baseRC); + return false; + } + + qglGetString = GL_GetProcAddress("glGetString"); + qwglGetExtensionsStringARB = GL_GetProcAddress("wglGetExtensionsStringARB"); + if (qglGetString == NULL) + { + VID_Shutdown(); + Con_Printf("glGetString not found\n"); + return false; + } + gl_renderer = qglGetString(GL_RENDERER); + gl_vendor = qglGetString(GL_VENDOR); + gl_version = qglGetString(GL_VERSION); + gl_extensions = qglGetString(GL_EXTENSIONS); + gl_platform = "WGL"; + gl_platformextensions = ""; + + if (qwglGetExtensionsStringARB) + gl_platformextensions = qwglGetExtensionsStringARB(hdc); + + gl_videosyncavailable = GL_CheckExtension("WGL_EXT_swap_control", wglswapintervalfuncs, NULL, false); + ReleaseDC(mainwindow, hdc); + + GL_Init (); + + // LordHavoc: special differences for ATI (broken 8bit color when also using 32bit? weird!) + if (strncasecmp(gl_vendor,"ATI",3)==0) + { + if (strncasecmp(gl_renderer,"Rage Pro",8)==0) + isRagePro = true; + } + if (strncasecmp(gl_renderer,"Matrox G200 Direct3D",20)==0) // a D3D driver for GL? sigh... + isG200 = true; + + //vid_menudrawfn = VID_MenuDraw; + //vid_menukeyfn = VID_MenuKey; + vid_hidden = false; + vid_initialized = true; + + IN_StartupMouse (); + IN_StartupJoystick (); + + return true; +} + +static void IN_Shutdown(void); +void VID_Shutdown (void) +{ + HGLRC hRC = 0; + HDC hDC = 0; + + if(vid_initialized == false) + return; + + VID_RestoreSystemGamma(); + + vid_initialized = false; + IN_Shutdown(); + if (qwglGetCurrentContext) + hRC = qwglGetCurrentContext(); + if (qwglGetCurrentDC) + hDC = qwglGetCurrentDC(); + if (qwglMakeCurrent) + qwglMakeCurrent(NULL, NULL); + if (hRC && qwglDeleteContext) + qwglDeleteContext(hRC); + // close the library before we get rid of the window + GL_CloseLibrary(); + if (hDC && mainwindow) + ReleaseDC(mainwindow, hDC); + AppActivate(false, false); + if (mainwindow) + DestroyWindow(mainwindow); + mainwindow = 0; + if (vid_isfullscreen) + ChangeDisplaySettings (NULL, 0); + vid_isfullscreen = false; } /* -================= -VID_DescribeCurrentMode_f -================= +=========== +IN_ShowMouse +=========== */ -void VID_DescribeCurrentMode_f (void) +void IN_ShowMouse (void) { - Con_Printf ("%s\n", VID_GetExtModeDescription (vid_modenum)); + if (!mouseshowtoggle) + { + ShowCursor (true); + mouseshowtoggle = 1; + } } /* -================= -VID_NumModes_f -================= +=========== +IN_HideMouse +=========== */ -void VID_NumModes_f (void) +void IN_HideMouse (void) { - - if (nummodes == 1) - Con_Printf ("%d video mode is available\n", nummodes); - else - Con_Printf ("%d video modes are available\n", nummodes); + if (mouseshowtoggle) + { + ShowCursor (false); + mouseshowtoggle = 0; + } } /* -================= -VID_DescribeMode_f -================= +=========== +IN_ActivateMouse +=========== */ -void VID_DescribeMode_f (void) +void IN_ActivateMouse (void) { - int t, modenum; - - modenum = atoi (Cmd_Argv(1)); - t = leavecurrentmode; - leavecurrentmode = 0; + mouseactivatetoggle = true; - Con_Printf ("%s\n", VID_GetExtModeDescription (modenum)); + if (mouseinitialized) + { + if (dinput) + { + if (g_pMouse) + { + if (!dinput_acquired) + { + IDirectInputDevice_Acquire(g_pMouse); + dinput_acquired = true; + } + } + else + { + return; + } + } + else + { + RECT window_rect; + window_rect.left = window_x; + window_rect.top = window_y; + window_rect.right = window_x + window_width; + window_rect.bottom = window_y + window_height; + + if (mouseparmsvalid) + restore_spi = SystemParametersInfo (SPI_SETMOUSE, 0, newmouseparms, 0); + + SetCursorPos (window_center_x, window_center_y); + SetCapture (mainwindow); + ClipCursor (&window_rect); + } - leavecurrentmode = t; + mouseactive = true; + } } /* -================= -VID_DescribeModes_f -================= +=========== +IN_DeactivateMouse +=========== */ -void VID_DescribeModes_f (void) +void IN_DeactivateMouse (void) { - int i, lnummodes, t; - char *pinfo; - vmode_t *pv; - lnummodes = VID_NumModes (); + mouseactivatetoggle = false; - t = leavecurrentmode; - leavecurrentmode = 0; - - for (i=1 ; i8 bpp modes - originalnummodes = nummodes; - modenum = 0; + mouseinitialized = true; - do + if (COM_CheckParm ("-dinput")) { - stat = EnumDisplaySettings (NULL, modenum, &devmode); + dinput = IN_InitDInput (); - if ((devmode.dmBitsPerPel >= 15) && - (devmode.dmPelsWidth <= MAXWIDTH) && - (devmode.dmPelsHeight <= MAXHEIGHT) && - (nummodes < MAX_MODE_LIST)) + if (dinput) { - devmode.dmFields = DM_BITSPERPEL | - DM_PELSWIDTH | - DM_PELSHEIGHT; - - if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) == - DISP_CHANGE_SUCCESSFUL) - { - modelist[nummodes].type = MS_FULLDIB; - modelist[nummodes].width = devmode.dmPelsWidth; - modelist[nummodes].height = devmode.dmPelsHeight; - modelist[nummodes].modenum = 0; - modelist[nummodes].halfscreen = 0; - modelist[nummodes].dib = 1; - modelist[nummodes].fullscreen = 1; - modelist[nummodes].bpp = devmode.dmBitsPerPel; - sprintf (modelist[nummodes].modedesc, "%dx%dx%d", - devmode.dmPelsWidth, devmode.dmPelsHeight, - devmode.dmBitsPerPel); - - // if the width is more than twice the height, reduce it by half because this - // is probably a dual-screen monitor - if (!COM_CheckParm("-noadjustaspect")) - { - if (modelist[nummodes].width > (modelist[nummodes].height << 1)) - { - modelist[nummodes].width >>= 1; - modelist[nummodes].halfscreen = 1; - sprintf (modelist[nummodes].modedesc, "%dx%dx%d", - modelist[nummodes].width, - modelist[nummodes].height, - modelist[nummodes].bpp); - } - } - - for (i=originalnummodes, existingmode = 0 ; iwidth)/2, 4, p); + memset (&ji, 0, sizeof(ji)); + ji.dwSize = sizeof(ji); + ji.dwFlags = joy_flags; - vid_wmodes = 0; - lnummodes = VID_NumModes (); - - for (i=1 ; (i 0) + if (in_speed.state & 1) + speed = cl_movespeedkey.value; + else + speed = 1; + // LordHavoc: viewzoom affects sensitivity for sniping + aspeed = speed * host_realframetime * cl.viewzoom; + + // loop through the axes + for (i = 0; i < JOY_MAX_AXES; i++) { - M_Print (2*8, 36+0*8, "Fullscreen Modes (WIDTHxHEIGHTxBPP)"); + // get the floating point zero-centered, potentially-inverted data for the current axis + fAxisValue = (float) *pdwRawValue[i]; + // move centerpoint to zero + fAxisValue -= 32768.0; + + if (joy_wwhack2.integer != 0.0) + { + if (dwAxisMap[i] == AxisTurn) + { + // this is a special formula for the Logitech WingMan Warrior + // y=ax^b; where a = 300 and b = 1.3 + // also x values are in increments of 800 (so this is factored out) + // then bounds check result to level out excessively high spin rates + fTemp = 300.0 * pow(abs(fAxisValue) / 800.0, 1.3); + if (fTemp > 14000.0) + fTemp = 14000.0; + // restore direction information + fAxisValue = (fAxisValue > 0.0) ? fTemp : -fTemp; + } + } - column = 8; - row = 36+2*8; + // convert range from -32768..32767 to -1..1 + fAxisValue /= 32768.0; - for (i=0 ; i joy_pitchthreshold.value) + { + // if mouse invert is on, invert the joystick pitch value + // only absolute control support here (joy_advanced is false) + if (m_pitch.value < 0.0) + { + cl.viewangles[PITCH] -= (fAxisValue * joy_pitchsensitivity.value) * aspeed * cl_pitchspeed.value; + } + else + { + cl.viewangles[PITCH] += (fAxisValue * joy_pitchsensitivity.value) * aspeed * cl_pitchspeed.value; + } + V_StopPitchDrift(); + } + else + { + // no pitch movement + // disable pitch return-to-center unless requested by user + // *** this code can be removed when the lookspring bug is fixed + // *** the bug always has the lookspring feature on + if(lookspring.value == 0.0) + V_StopPitchDrift(); + } + } else - M_Print (column, row, modedescs[i].desc); + { + // user wants forward control to be forward control + if (fabs(fAxisValue) > joy_forwardthreshold.value) + { + cmd->forwardmove += (fAxisValue * joy_forwardsensitivity.value) * speed * cl_forwardspeed.value; + } + } + break; - column += 13*8; + case AxisSide: + if (fabs(fAxisValue) > joy_sidethreshold.value) + { + cmd->sidemove += (fAxisValue * joy_sidesensitivity.value) * speed * cl_sidespeed.value; + } + break; - if ((i % VID_ROW_SIZE) == (VID_ROW_SIZE - 1)) + case AxisTurn: + if ((in_strafe.state & 1) || (lookstrafe.integer && mouselook)) { - column = 8; - row += 8; + // user wants turn control to become side control + if (fabs(fAxisValue) > joy_sidethreshold.value) + { + cmd->sidemove -= (fAxisValue * joy_sidesensitivity.value) * speed * cl_sidespeed.value; + } } + else + { + // user wants turn control to be turn control + if (fabs(fAxisValue) > joy_yawthreshold.value) + { + if(dwControlMap[i] == JOY_ABSOLUTE_AXIS) + { + cl.viewangles[YAW] += (fAxisValue * joy_yawsensitivity.value) * aspeed * cl_yawspeed.value; + } + else + { + cl.viewangles[YAW] += (fAxisValue * joy_yawsensitivity.value) * speed * 180.0; + } + + } + } + break; + + case AxisLook: + if (mouselook) + { + if (fabs(fAxisValue) > joy_pitchthreshold.value) + { + // pitch movement detected and pitch movement desired by user + if(dwControlMap[i] == JOY_ABSOLUTE_AXIS) + { + cl.viewangles[PITCH] += (fAxisValue * joy_pitchsensitivity.value) * aspeed * cl_pitchspeed.value; + } + else + { + cl.viewangles[PITCH] += (fAxisValue * joy_pitchsensitivity.value) * speed * 180.0; + } + V_StopPitchDrift(); + } + else + { + // no pitch movement + // disable pitch return-to-center unless requested by user + // *** this code can be removed when the lookspring bug is fixed + // *** the bug always has the lookspring feature on + if(lookspring.integer == 0) + V_StopPitchDrift(); + } + } + break; + + default: + break; } } - - M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*2, - "Video modes must be set from the"); - M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*3, - "command line with -width "); - M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*4, - "and -bpp "); - M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*6, - "Select windowed mode with -window"); } +static void IN_Init(void) +{ + uiWheelMessage = RegisterWindowMessage ( "MSWHEEL_ROLLMSG" ); + + // joystick variables + Cvar_RegisterVariable (&in_joystick); + Cvar_RegisterVariable (&joy_name); + Cvar_RegisterVariable (&joy_advanced); + Cvar_RegisterVariable (&joy_advaxisx); + Cvar_RegisterVariable (&joy_advaxisy); + Cvar_RegisterVariable (&joy_advaxisz); + Cvar_RegisterVariable (&joy_advaxisr); + Cvar_RegisterVariable (&joy_advaxisu); + Cvar_RegisterVariable (&joy_advaxisv); + Cvar_RegisterVariable (&joy_forwardthreshold); + Cvar_RegisterVariable (&joy_sidethreshold); + Cvar_RegisterVariable (&joy_pitchthreshold); + Cvar_RegisterVariable (&joy_yawthreshold); + Cvar_RegisterVariable (&joy_forwardsensitivity); + Cvar_RegisterVariable (&joy_sidesensitivity); + Cvar_RegisterVariable (&joy_pitchsensitivity); + Cvar_RegisterVariable (&joy_yawsensitivity); + Cvar_RegisterVariable (&joy_wwhack1); + Cvar_RegisterVariable (&joy_wwhack2); + Cmd_AddCommand ("joyadvancedupdate", Joy_AdvancedUpdate_f); +} -/* -================ -VID_MenuKey -================ -*/ -void VID_MenuKey (int key) +static void IN_Shutdown(void) { - switch (key) - { - case K_ESCAPE: - S_LocalSound ("misc/menu1.wav"); - M_Menu_Options_f (); - break; + IN_DeactivateMouse (); + IN_ShowMouse (); - default: - break; - } + if (g_pMouse) + IDirectInputDevice_Release(g_pMouse); + g_pMouse = NULL; + + if (g_pdi) + IDirectInput_Release(g_pdi); + g_pdi = NULL; }