X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=vid_wgl.c;h=88cc6814fa86a398ffc597527827e271902c17f1;hp=d2c0184041aa2cf2afb9c28bf35ea6d0011020c8;hb=ecddae3859018ea01887528f3248f03a138be6c3;hpb=1f7e4ae8b04d68b88f1c63c87a6b819b2a4a76f6 diff --git a/vid_wgl.c b/vid_wgl.c index d2c01840..88cc6814 100644 --- a/vid_wgl.c +++ b/vid_wgl.c @@ -19,28 +19,46 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // gl_vidnt.c -- NT GL vid component +// we don't need a very new dinput +#define DIRECTINPUT_VERSION 0x0300 + #include "quakedef.h" -#include "winquake.h" +#include +#include +#include #include "resource.h" #include +#include + +extern HINSTANCE global_hInstance; + +#ifndef WM_MOUSEWHEEL +#define WM_MOUSEWHEEL 0x020A +#endif + +// 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 gl_extensionfunctionlist_t wglfuncs[] = +qboolean vid_supportrefreshrate = true; + +static int (WINAPI *qwglChoosePixelFormat)(HDC, CONST PIXELFORMATDESCRIPTOR *); +static int (WINAPI *qwglDescribePixelFormat)(HDC, int, UINT, LPPIXELFORMATDESCRIPTOR); +//static int (WINAPI *qwglGetPixelFormat)(HDC); +static BOOL (WINAPI *qwglSetPixelFormat)(HDC, int, CONST PIXELFORMATDESCRIPTOR *); +static BOOL (WINAPI *qwglSwapBuffers)(HDC); +static HGLRC (WINAPI *qwglCreateContext)(HDC); +static BOOL (WINAPI *qwglDeleteContext)(HGLRC); +static HGLRC (WINAPI *qwglGetCurrentContext)(VOID); +static HDC (WINAPI *qwglGetCurrentDC)(VOID); +static PROC (WINAPI *qwglGetProcAddress)(LPCSTR); +static BOOL (WINAPI *qwglMakeCurrent)(HDC, HGLRC); +static BOOL (WINAPI *qwglSwapIntervalEXT)(int interval); +static const char *(WINAPI *qwglGetExtensionsStringARB)(HDC hdc); +static BOOL (WINAPI *qwglChoosePixelFormatARB)(HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); +static BOOL (WINAPI *qwglGetPixelFormatAttribivARB)(HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues); + +static dllfunction_t wglfuncs[] = { {"wglChoosePixelFormat", (void **) &qwglChoosePixelFormat}, {"wglDescribePixelFormat", (void **) &qwglDescribePixelFormat}, @@ -56,30 +74,36 @@ static gl_extensionfunctionlist_t wglfuncs[] = {NULL, NULL} }; -static gl_extensionfunctionlist_t wglswapintervalfuncs[] = +static dllfunction_t wglswapintervalfuncs[] = { {"wglSwapIntervalEXT", (void **) &qwglSwapIntervalEXT}, {NULL, NULL} }; -void VID_RestoreGameGamma(void); -void VID_GetSystemGamma(void); -void VID_RestoreSystemGamma(void); - -qboolean scr_skipupdate; +static dllfunction_t wglpixelformatfuncs[] = +{ + {"wglChoosePixelFormatARB", (void **) &qwglChoosePixelFormatARB}, + {"wglGetPixelFormatAttribivARB", (void **) &qwglGetPixelFormatAttribivARB}, + {NULL, NULL} +}; -static DEVMODE gdevmode; +static DEVMODE gdevmode, initialdevmode; static qboolean vid_initialized = false; static qboolean vid_wassuspended = false; -static int vid_usingmouse; -extern qboolean mouseactive; // from in_win.c +static qboolean vid_usingmouse = false; +static qboolean vid_usingvsync = false; +static qboolean vid_usevsync = false; static HICON hIcon; +// used by cd_win.c and snd_win.c HWND mainwindow; +static HDC baseDC; +static HGLRC baseRC; + //HWND WINAPI InitializeWindow (HINSTANCE hInstance, int nCmdShow); -static int vid_isfullscreen; +static qboolean vid_isfullscreen; //void VID_MenuDraw (void); //void VID_MenuKey (int key); @@ -91,95 +115,159 @@ static int vid_isfullscreen; //==================================== -int window_x, window_y, window_width, window_height; -int window_center_x, window_center_y; +static int window_x, window_y; -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); +static void IN_Activate (qboolean grab); -qboolean mouseinitialized; +static qboolean mouseinitialized; static qboolean dinput; -/* -================ -VID_UpdateWindowStatus -================ -*/ -void VID_UpdateWindowStatus (void) -{ - window_center_x = window_x + window_width / 2; - window_center_y = window_y + window_height / 2; +// input code - if (mouseinitialized && mouseactive && !dinput) - { - 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); - } -} +#define DINPUT_BUFFERSIZE 16 +#define iDirectInputCreate(a,b,c,d) pDirectInputCreate(a,b,c,d) +static HRESULT (WINAPI *pDirectInputCreate)(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUT * lplpDirectInput, LPUNKNOWN punkOuter); -//==================================== +// 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 +#ifndef MK_XBUTTON1 + #define MK_XBUTTON1 0x0020 + #define MK_XBUTTON2 0x0040 +#endif +#ifndef MK_XBUTTON3 +// 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 +/* :: backslash */ -/* -================= -VID_GetWindowSize -================= -*/ -void VID_GetWindowSize (int *x, int *y, int *width, int *height) +// mouse variables +static int mouse_buttons; +static int mouse_oldbuttonstate; + +static unsigned int uiWheelMessage; +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 { - *x = 0; - *y = 0; - *width = window_width; - *height = window_height; -} + AxisNada = 0, AxisForward, AxisLook, AxisSide, AxisTurn +}; + +static DWORD dwAxisFlags[JOY_MAX_AXES] = +{ + JOY_RETURNX, JOY_RETURNY, JOY_RETURNZ, JOY_RETURNR, JOY_RETURNU, JOY_RETURNV +}; + +static DWORD dwAxisMap[JOY_MAX_AXES]; +static DWORD dwControlMap[JOY_MAX_AXES]; +static 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. +static cvar_t in_joystick = {CVAR_SAVE, "joystick","0", "enables joysticks"}; +static cvar_t joy_name = {0, "joyname", "joystick", "name of joystick to use (informational only, used only by joyadvanced 1 mode)"}; +static cvar_t joy_advanced = {0, "joyadvanced", "0", "use more than 2 axis joysticks (configuring this is very technical)"}; +static cvar_t joy_advaxisx = {0, "joyadvaxisx", "0", "axis mapping for joyadvanced 1 mode"}; +static cvar_t joy_advaxisy = {0, "joyadvaxisy", "0", "axis mapping for joyadvanced 1 mode"}; +static cvar_t joy_advaxisz = {0, "joyadvaxisz", "0", "axis mapping for joyadvanced 1 mode"}; +static cvar_t joy_advaxisr = {0, "joyadvaxisr", "0", "axis mapping for joyadvanced 1 mode"}; +static cvar_t joy_advaxisu = {0, "joyadvaxisu", "0", "axis mapping for joyadvanced 1 mode"}; +static cvar_t joy_advaxisv = {0, "joyadvaxisv", "0", "axis mapping for joyadvanced 1 mode"}; +static cvar_t joy_forwardthreshold = {0, "joyforwardthreshold", "0.15", "minimum joystick movement necessary to move forward"}; +static cvar_t joy_sidethreshold = {0, "joysidethreshold", "0.15", "minimum joystick movement necessary to move sideways (strafing)"}; +static cvar_t joy_pitchthreshold = {0, "joypitchthreshold", "0.15", "minimum joystick movement necessary to look up/down"}; +static cvar_t joy_yawthreshold = {0, "joyyawthreshold", "0.15", "minimum joystick movement necessary to turn left/right"}; +static cvar_t joy_forwardsensitivity = {0, "joyforwardsensitivity", "-1.0", "how fast the joystick moves forward"}; +static cvar_t joy_sidesensitivity = {0, "joysidesensitivity", "-1.0", "how fast the joystick moves sideways (strafing)"}; +static cvar_t joy_pitchsensitivity = {0, "joypitchsensitivity", "1.0", "how fast the joystick looks up/down"}; +static cvar_t joy_yawsensitivity = {0, "joyyawsensitivity", "-1.0", "how fast the joystick turns left/right"}; +static cvar_t joy_wwhack1 = {0, "joywwhack1", "0.0", "special hack for wingman warrior"}; +static cvar_t joy_wwhack2 = {0, "joywwhack2", "0.0", "special hack for wingman warrior"}; + +static cvar_t vid_forcerefreshrate = {0, "vid_forcerefreshrate", "0", "try to set the given vid_refreshrate even if Windows doesn't list it as valid video mode"}; + +static qboolean joy_avail, joy_advancedinit, joy_haspov; +static DWORD joy_oldbuttonstate, joy_oldpovstate; + +static int joy_id; +static DWORD joy_flags; +static DWORD joy_numbuttons; + +static LPDIRECTINPUT g_pdi; +static LPDIRECTINPUTDEVICE g_pMouse; +static JOYINFOEX ji; -void VID_Finish (void) +static HINSTANCE hInstDI; + +// forward-referenced functions +static void IN_StartupJoystick (void); +static void Joy_AdvancedUpdate_f (void); +static void IN_JoyMove (void); +static void IN_StartupMouse (void); + + +//==================================== + +void VID_Finish (qboolean allowmousegrab) { - HDC hdc; - int vid_usemouse; - if (r_render.integer && !scr_skipupdate) + qboolean vid_usemouse; + + vid_usevsync = vid_vsync.integer && !cls.timedemo && gl_videosyncavailable; + if (vid_usingvsync != vid_usevsync && gl_videosyncavailable) { - qglFinish(); - hdc = GetDC(mainwindow); - SwapBuffers(hdc); - ReleaseDC(mainwindow, hdc); + vid_usingvsync = vid_usevsync; + qwglSwapIntervalEXT (vid_usevsync); } // handle the mouse state when windowed if that's changed vid_usemouse = false; - if (vid_mouse.integer && !key_consoleactive) + if (allowmousegrab && vid_mouse.integer && !key_consoleactive && (key_dest != key_game || !cls.demoplayback)) vid_usemouse = true; if (vid_isfullscreen) vid_usemouse = true; if (!vid_activewindow) vid_usemouse = false; - if (vid_usemouse) - { - if (!vid_usingmouse) - { - vid_usingmouse = true; - IN_ActivateMouse (); - IN_HideMouse(); - } - } - else + IN_Activate(vid_usemouse); + + if (r_render.integer && !vid_hidden) { - if (vid_usingmouse) + CHECKGLERROR + if (r_speeds.integer || gl_finish.integer) { - vid_usingmouse = false; - IN_DeactivateMouse (); - IN_ShowMouse(); + qglFinish();CHECKGLERROR } + SwapBuffers(baseDC); } + + VID_UpdateGamma(false, 256); } //========================================================================== @@ -187,17 +275,17 @@ void VID_Finish (void) -qbyte scantokey[128] = +static unsigned char 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 +// 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 }; @@ -208,14 +296,64 @@ MapKey Map from windows to quake keynums ======= */ -int MapKey (int key, int virtualkey) +static 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; + } } /* @@ -231,23 +369,13 @@ MAIN WINDOW ClearAllStates ================ */ -void ClearAllStates (void) +static 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 (); + if (vid_usingmouse) + mouse_oldbuttonstate = 0; } -void VID_RestoreGameGamma(void); -extern qboolean host_loopactive; - void AppActivate(BOOL fActive, BOOL minimize) /**************************************************************************** * @@ -260,21 +388,27 @@ void AppActivate(BOOL fActive, BOOL minimize) * ****************************************************************************/ { - static BOOL sound_active; + static qboolean sound_active = false; // initially blocked by Sys_InitConsole() vid_activewindow = fActive; vid_hidden = minimize; -// enable/disable sound on focus gain/loss - if (!vid_activewindow && sound_active) + // enable/disable sound on focus gain/loss + if (!vid_hidden && (vid_activewindow || !snd_mutewhenidle.integer)) { - S_BlockSound (); - sound_active = false; + if (!sound_active) + { + S_UnblockSound (); + sound_active = true; + } } - else if (vid_activewindow && !sound_active) + else { - S_UnblockSound (); - sound_active = true; + if (sound_active) + { + S_BlockSound (); + sound_active = false; + } } if (fActive) @@ -291,15 +425,11 @@ void AppActivate(BOOL fActive, BOOL minimize) // LordHavoc: from dabb, fix for alt-tab bug in NVidia drivers MoveWindow(mainwindow,0,0,gdevmode.dmPelsWidth,gdevmode.dmPelsHeight,false); } - if (host_loopactive) - VID_RestoreGameGamma(); } if (!fActive) { - vid_usingmouse = false; - IN_DeactivateMouse (); - IN_ShowMouse (); + IN_Activate (false); if (vid_isfullscreen) { ChangeDisplaySettings (NULL, 0); @@ -309,14 +439,53 @@ void AppActivate(BOOL fActive, BOOL minimize) } } +//TODO: move it around in vid_wgl.c since I dont think this is the right position +void Sys_SendKeyEvents (void) +{ + MSG msg; + + while (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE)) + { + if (!GetMessage (&msg, NULL, 0, 0)) + Sys_Quit (1); + + TranslateMessage (&msg); + DispatchMessage (&msg); + } +} + LONG CDAudio_MessageHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); +static keynum_t buttonremap[16] = +{ + K_MOUSE1, + K_MOUSE2, + K_MOUSE3, + K_MOUSE4, + K_MOUSE5, + K_MOUSE6, + K_MOUSE7, + K_MOUSE8, + K_MOUSE9, + K_MOUSE10, + K_MOUSE11, + K_MOUSE12, + K_MOUSE13, + K_MOUSE14, + K_MOUSE15, + K_MOUSE16, +}; + /* main window procedure */ LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { LONG lRet = 1; int fActive, fMinimized, temp; - extern unsigned int uiWheelMessage; + char state[256]; + char asciichar[4]; + int vkey; + int charlength; + qboolean down = false; if ( uMsg == uiWheelMessage ) uMsg = WM_MOUSEWHEEL; @@ -334,23 +503,37 @@ LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) case WM_MOVE: window_x = (int) LOWORD(lParam); window_y = (int) HIWORD(lParam); - VID_UpdateWindowStatus (); + IN_Activate(false); break; case WM_KEYDOWN: case WM_SYSKEYDOWN: - Key_Event (MapKey(lParam, wParam), true); - break; - + down = true; case WM_KEYUP: case WM_SYSKEYUP: - Key_Event (MapKey(lParam, wParam), 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 + charlength = ToAscii (wParam, lParam >> 16, state, (unsigned short *)asciichar, 0); + if (vkey == K_ALT || vkey == K_CTRL || vkey == K_SHIFT || charlength == 0) + asciichar[0] = 0; + else if( charlength == 2 ) { + asciichar[0] = asciichar[1]; + } + Key_Event (vkey, asciichar[0], down); break; case WM_SYSCHAR: // keep Alt-Space from happening break; + case WM_SYSCOMMAND: + // prevent screensaver from occuring while the active window + if (vid_activewindow && ((wParam & 0xFFF0) == SC_SCREENSAVE || (wParam & 0xFFF0) == SC_MONITORPOWER)) + lRet = 0;; // note: password-locked screensavers on Vista still work + 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: @@ -359,6 +542,8 @@ LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 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; @@ -371,7 +556,35 @@ LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) if (wParam & MK_MBUTTON) temp |= 4; - IN_MouseEvent (temp); + /* 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; + + if (vid_usingmouse && !dinput_acquired) + { + // perform button actions + int i; + for (i=0 ; i 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; @@ -393,7 +606,7 @@ LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) case WM_CLOSE: if (MessageBox (mainwindow, "Are you sure you want to quit?", "Confirm Exit", MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION) == IDYES) - Sys_Quit (); + Sys_Quit (0); break; @@ -407,14 +620,9 @@ LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) break; - case WM_DESTROY: - { - if (mainwindow) - DestroyWindow (mainwindow); - - PostQuitMessage (0); - } - break; + //case WM_DESTROY: + // PostQuitMessage (0); + // break; case MM_MCINOTIFY: lRet = CDAudio_MessageHandler (hWnd, uMsg, wParam, lParam); @@ -430,190 +638,48 @@ LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) return lRet; } - -//static int grabsysgamma = true; -WORD systemgammaramps[3][256], currentgammaramps[3][256]; - -int VID_SetGamma(float prescale, float gamma, float scale, float base) +int VID_SetGamma(unsigned short *ramps, int rampsize) { - int i; - HDC hdc; - hdc = GetDC (NULL); - - BuildGammaTable16(prescale, gamma, scale, base, ¤tgammaramps[0][0]); - for (i = 0;i < 256;i++) - currentgammaramps[1][i] = currentgammaramps[2][i] = currentgammaramps[0][i]; - - i = SetDeviceGammaRamp(hdc, ¤tgammaramps[0][0]); - + HDC hdc = GetDC (NULL); + int i = SetDeviceGammaRamp(hdc, ramps); ReleaseDC (NULL, hdc); return i; // return success or failure } -void VID_RestoreGameGamma(void) -{ - VID_UpdateGamma(true); -} - -void VID_GetSystemGamma(void) +int VID_GetGamma(unsigned short *ramps, int rampsize) { - HDC hdc; - hdc = GetDC (NULL); - - GetDeviceGammaRamp(hdc, &systemgammaramps[0][0]); - + HDC hdc = GetDC (NULL); + int i = GetDeviceGammaRamp(hdc, ramps); ReleaseDC (NULL, hdc); + return i; // return success or failure } -void VID_RestoreSystemGamma(void) -{ - HDC hdc; - hdc = GetDC (NULL); - - SetDeviceGammaRamp(hdc, &systemgammaramps[0][0]); - - ReleaseDC (NULL, hdc); -} - -//======================================================== -// Video menu stuff -//======================================================== - -#if 0 -extern void M_Menu_Options_f (void); -extern void M_Print (float cx, float cy, char *str); -extern void M_PrintWhite (float cx, float cy, char *str); -extern void M_DrawCharacter (float cx, float cy, int num); -extern void M_DrawPic (float cx, float cy, char *picname); - -static int vid_wmodes; - -typedef struct -{ - int modenum; - char *desc; - int iscur; -} modedesc_t; - -#define MAX_COLUMN_SIZE 9 -#define MODE_AREA_HEIGHT (MAX_COLUMN_SIZE + 2) -#define MAX_MODEDESCS (MAX_COLUMN_SIZE*3) - -static modedesc_t modedescs[MAX_MODEDESCS]; - -/* -================ -VID_MenuDraw -================ -*/ -void VID_MenuDraw (void) -{ - cachepic_t *p; - char *ptr; - int lnummodes, i, k, column, row; - vmode_t *pv; - - p = Draw_CachePic ("gfx/vidmodes.lmp"); - M_DrawPic ( (320-p->width)/2, 4, "gfx/vidmodes.lmp"); - - vid_wmodes = 0; - lnummodes = VID_NumModes (); - - for (i=1 ; (i 0) - { - M_Print (2*8, 36+0*8, "Fullscreen Modes (WIDTHxHEIGHTxBPP)"); - - column = 8; - row = 36+2*8; - - for (i=0 ; i"); - 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 HINSTANCE gldll; -/* -================ -VID_MenuKey -================ -*/ -void VID_MenuKey (int key) +static void GL_CloseLibrary(void) { - switch (key) - { - case K_ESCAPE: - S_LocalSound ("misc/menu1.wav"); - M_Menu_Options_f (); - break; - - default: - break; - } + FreeLibrary(gldll); + gldll = 0; + gl_driver[0] = 0; + qwglGetProcAddress = NULL; + gl_extensions = ""; + gl_platform = ""; + gl_platformextensions = ""; } -#endif - -static HINSTANCE gldll; -int GL_OpenLibrary(const char *name) +static int GL_OpenLibrary(const char *name) { - Con_Printf("Loading GL driver %s\n", 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); + strlcpy(gl_driver, name, sizeof(gl_driver)); return true; } -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; @@ -624,12 +690,71 @@ void *GL_GetProcAddress(const char *name) return p; } +#ifndef WGL_ARB_pixel_format +#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 +#define WGL_DRAW_TO_WINDOW_ARB 0x2001 +#define WGL_DRAW_TO_BITMAP_ARB 0x2002 +#define WGL_ACCELERATION_ARB 0x2003 +#define WGL_NEED_PALETTE_ARB 0x2004 +#define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005 +#define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006 +#define WGL_SWAP_METHOD_ARB 0x2007 +#define WGL_NUMBER_OVERLAYS_ARB 0x2008 +#define WGL_NUMBER_UNDERLAYS_ARB 0x2009 +#define WGL_TRANSPARENT_ARB 0x200A +#define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037 +#define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038 +#define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039 +#define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A +#define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B +#define WGL_SHARE_DEPTH_ARB 0x200C +#define WGL_SHARE_STENCIL_ARB 0x200D +#define WGL_SHARE_ACCUM_ARB 0x200E +#define WGL_SUPPORT_GDI_ARB 0x200F +#define WGL_SUPPORT_OPENGL_ARB 0x2010 +#define WGL_DOUBLE_BUFFER_ARB 0x2011 +#define WGL_STEREO_ARB 0x2012 +#define WGL_PIXEL_TYPE_ARB 0x2013 +#define WGL_COLOR_BITS_ARB 0x2014 +#define WGL_RED_BITS_ARB 0x2015 +#define WGL_RED_SHIFT_ARB 0x2016 +#define WGL_GREEN_BITS_ARB 0x2017 +#define WGL_GREEN_SHIFT_ARB 0x2018 +#define WGL_BLUE_BITS_ARB 0x2019 +#define WGL_BLUE_SHIFT_ARB 0x201A +#define WGL_ALPHA_BITS_ARB 0x201B +#define WGL_ALPHA_SHIFT_ARB 0x201C +#define WGL_ACCUM_BITS_ARB 0x201D +#define WGL_ACCUM_RED_BITS_ARB 0x201E +#define WGL_ACCUM_GREEN_BITS_ARB 0x201F +#define WGL_ACCUM_BLUE_BITS_ARB 0x2020 +#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 +#define WGL_DEPTH_BITS_ARB 0x2022 +#define WGL_STENCIL_BITS_ARB 0x2023 +#define WGL_AUX_BUFFERS_ARB 0x2024 +#define WGL_NO_ACCELERATION_ARB 0x2025 +#define WGL_GENERIC_ACCELERATION_ARB 0x2026 +#define WGL_FULL_ACCELERATION_ARB 0x2027 +#define WGL_SWAP_EXCHANGE_ARB 0x2028 +#define WGL_SWAP_COPY_ARB 0x2029 +#define WGL_SWAP_UNDEFINED_ARB 0x202A +#define WGL_TYPE_RGBA_ARB 0x202B +#define WGL_TYPE_COLORINDEX_ARB 0x202C +#endif + +#ifndef WGL_ARB_multisample +#define WGL_SAMPLE_BUFFERS_ARB 0x2041 +#define WGL_SAMPLES_ARB 0x2042 +#endif + + +static void IN_Init(void); void VID_Init(void) { WNDCLASS wc; InitCommonControls(); - hIcon = LoadIcon (global_hInstance, MAKEINTRESOURCE (IDI_ICON2)); + hIcon = LoadIcon (global_hInstance, MAKEINTRESOURCE (IDI_ICON1)); // Register the frame class wc.style = 0; @@ -637,41 +762,22 @@ void VID_Init(void) wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = global_hInstance; - wc.hIcon = 0; + wc.hIcon = hIcon; 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"); + Con_Printf ("Couldn't register window class\n"); - uiWheelMessage = RegisterWindowMessage ( "MSWHEEL_ROLLMSG" ); + memset(&initialdevmode, 0, sizeof(initialdevmode)); + EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &initialdevmode); - // 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); + IN_Init(); } -int VID_InitMode (int fullscreen, int width, int height, int bpp, int stencil) +int VID_InitMode (int fullscreen, int width, int height, int bpp, int refreshrate, int stereobuffer, int samples) { int i; HDC hdc; @@ -698,21 +804,93 @@ int VID_InitMode (int fullscreen, int width, int height, int bpp, int stencil) 0, // reserved 0, 0, 0 // layer masks ignored }; - int pixelformat; + int windowpass; + int pixelformat, newpixelformat; + int numpixelformats; DWORD WindowStyle, ExWindowStyle; - HGLRC baseRC; int CenterX, CenterY; const char *gldrivername; - + int depth; + DEVMODE thismode; + qboolean foundmode, foundgoodmode; + int *a; + float *af; + int attribs[128]; + float attribsf[16]; + if (vid_initialized) - Sys_Error("VID_InitMode called when video is already initialised\n"); + Sys_Error("VID_InitMode called when video is already initialised"); - if (stencil) + // if stencil is enabled, ask for alpha too + if (bpp >= 32) + { pfd.cStencilBits = 8; + pfd.cAlphaBits = 8; + } else + { pfd.cStencilBits = 0; + pfd.cAlphaBits = 0; + } + + if (stereobuffer) + pfd.dwFlags |= PFD_STEREO; + + a = attribs; + af = attribsf; + *a++ = WGL_DRAW_TO_WINDOW_ARB; + *a++ = GL_TRUE; + *a++ = WGL_ACCELERATION_ARB; + *a++ = WGL_FULL_ACCELERATION_ARB; + *a++ = WGL_DOUBLE_BUFFER_ARB; + *a++ = true; + + if (bpp >= 32) + { + *a++ = WGL_RED_BITS_ARB; + *a++ = 8; + *a++ = WGL_GREEN_BITS_ARB; + *a++ = 8; + *a++ = WGL_BLUE_BITS_ARB; + *a++ = 8; + *a++ = WGL_ALPHA_BITS_ARB; + *a++ = 1; + *a++ = WGL_DEPTH_BITS_ARB; + *a++ = 24; + *a++ = WGL_STENCIL_BITS_ARB; + *a++ = 8; + } + else + { + *a++ = WGL_RED_BITS_ARB; + *a++ = 1; + *a++ = WGL_GREEN_BITS_ARB; + *a++ = 1; + *a++ = WGL_BLUE_BITS_ARB; + *a++ = 1; + *a++ = WGL_DEPTH_BITS_ARB; + *a++ = 16; + } + + if (stereobuffer) + { + *a++ = WGL_STEREO_ARB; + *a++ = GL_TRUE; + } + + if (samples > 1) + { + *a++ = WGL_SAMPLE_BUFFERS_ARB; + *a++ = 1; + *a++ = WGL_SAMPLES_ARB; + *a++ = samples; + } + + *a = 0; + *af = 0; gldrivername = "opengl32.dll"; +// COMMANDLINEOPTION: Windows WGL: -gl_driver selects a GL driver library, default is opengl32.dll, useful only for 3dfxogl.dll or 3dfxvgl.dll, if you don't know what this is for, you don't need it i = COM_CheckParm("-gl_driver"); if (i && i < com_argc - 1) gldrivername = com_argv[i + 1]; @@ -724,17 +902,110 @@ int VID_InitMode (int fullscreen, int width, int height, int bpp, int stencil) memset(&gdevmode, 0, sizeof(gdevmode)); - VID_GetSystemGamma(); - 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) + if(vid_forcerefreshrate.integer) + { + foundmode = true; + gdevmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; + gdevmode.dmBitsPerPel = bpp; + gdevmode.dmPelsWidth = width; + gdevmode.dmPelsHeight = height; + gdevmode.dmSize = sizeof (gdevmode); + if(refreshrate) + { + gdevmode.dmFields |= DM_DISPLAYFREQUENCY; + gdevmode.dmDisplayFrequency = refreshrate; + } + } + else + { + if(refreshrate == 0) + refreshrate = initialdevmode.dmDisplayFrequency; // default vid_refreshrate to the rate of the desktop + + foundmode = false; + foundgoodmode = false; + + thismode.dmSize = sizeof(thismode); + thismode.dmDriverExtra = 0; + for(i = 0; EnumDisplaySettings(NULL, i, &thismode); ++i) + { + if(~thismode.dmFields & (DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY)) + { + Con_DPrintf("enumerating modes yielded a bogus item... please debug this\n"); + continue; + } + if(developer.integer >= 100) + Con_Printf("Found mode %dx%dx%dbpp %dHz... ", (int)thismode.dmPelsWidth, (int)thismode.dmPelsHeight, (int)thismode.dmBitsPerPel, (int)thismode.dmDisplayFrequency); + if(thismode.dmBitsPerPel != (DWORD)bpp) + { + if(developer.integer >= 100) + Con_Printf("wrong bpp\n"); + continue; + } + if(thismode.dmPelsWidth != (DWORD)width) + { + if(developer.integer >= 100) + Con_Printf("wrong width\n"); + continue; + } + if(thismode.dmPelsHeight != (DWORD)height) + { + if(developer.integer >= 100) + Con_Printf("wrong height\n"); + continue; + } + + if(foundgoodmode) + { + // if we have a good mode, make sure this mode is better than the previous one, and allowed by the refreshrate + if(thismode.dmDisplayFrequency > (DWORD)refreshrate) + { + if(developer.integer >= 100) + Con_Printf("too high refresh rate\n"); + continue; + } + else if(thismode.dmDisplayFrequency <= gdevmode.dmDisplayFrequency) + { + if(developer.integer >= 100) + Con_Printf("doesn't beat previous best match (too low)\n"); + continue; + } + } + else if(foundmode) + { + // we do have one, but it isn't good... make sure it has a lower frequency than the previous one + if(thismode.dmDisplayFrequency >= gdevmode.dmDisplayFrequency) + { + if(developer.integer >= 100) + Con_Printf("doesn't beat previous best match (too high)\n"); + continue; + } + } + // otherwise, take anything + + memcpy(&gdevmode, &thismode, sizeof(gdevmode)); + if(thismode.dmDisplayFrequency <= (DWORD)refreshrate) + foundgoodmode = true; + else + { + if(developer.integer >= 100) + Con_Printf("(out of range)\n"); + } + foundmode = true; + if(developer.integer >= 100) + Con_Printf("accepted\n"); + } + } + + if (!foundmode) + { + VID_Shutdown(); + Con_Printf("Unable to find the requested mode %dx%dx%dbpp\n", width, height, bpp); + return false; + } + else 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); @@ -743,17 +1014,24 @@ int VID_InitMode (int fullscreen, int width, int height, int bpp, int stencil) vid_isfullscreen = true; WindowStyle = WS_POPUP; - ExWindowStyle = 0; + ExWindowStyle = WS_EX_TOPMOST; } else { hdc = GetDC (NULL); i = GetDeviceCaps(hdc, RASTERCAPS); + depth = GetDeviceCaps(hdc, PLANES) * GetDeviceCaps(hdc, BITSPIXEL); ReleaseDC (NULL, hdc); if (i & RC_PALETTE) { VID_Shutdown(); - Con_Printf ("Can't run in non-RGB mode\n"); + Con_Print("Can't run in non-RGB mode\n"); + return false; + } + if (bpp > depth) + { + VID_Shutdown(); + Con_Print("A higher desktop depth is required to run this video mode\n"); return false; } @@ -783,21 +1061,111 @@ int VID_InitMode (int fullscreen, int width, int height, int bpp, int stencil) // 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) + pixelformat = 0; + newpixelformat = 0; + for (windowpass = 0;windowpass < 2;windowpass++) { - VID_Shutdown(); - Con_Printf("CreateWindowEx(%d, %s, %s, %d, %d, %d, %d, %d, %p, %p, %d, %p) failed\n", ExWindowStyle, gamename, gamename, WindowStyle, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, global_hInstance, NULL); - return false; + 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", (int)ExWindowStyle, "DarkPlacesWindowClass", gamename, (int)WindowStyle, (int)(rect.left), (int)(rect.top), (int)(rect.right - rect.left), (int)(rect.bottom - rect.top), NULL, NULL, (int)global_hInstance, NULL); + VID_Shutdown(); + return false; + } + + baseDC = GetDC(mainwindow); + + if (!newpixelformat) + newpixelformat = ChoosePixelFormat(baseDC, &pfd); + pixelformat = newpixelformat; + if (!pixelformat) + { + VID_Shutdown(); + Con_Printf("ChoosePixelFormat(%d, %p) failed\n", (int)baseDC, &pfd); + return false; + } + + if (SetPixelFormat(baseDC, pixelformat, &pfd) == false) + { + VID_Shutdown(); + Con_Printf("SetPixelFormat(%d, %d, %p) failed\n", (int)baseDC, pixelformat, &pfd); + return false; + } + + if (!GL_CheckExtension("wgl", wglfuncs, NULL, false)) + { + VID_Shutdown(); + Con_Print("wgl functions not found\n"); + return false; + } + + baseRC = qwglCreateContext(baseDC); + if (!baseRC) + { + VID_Shutdown(); + Con_Print("Could not initialize GL (wglCreateContext failed).\n\nMake sure you are in 65536 color mode, and try running -window.\n"); + return false; + } + if (!qwglMakeCurrent(baseDC, baseRC)) + { + VID_Shutdown(); + Con_Printf("wglMakeCurrent(%d, %d) failed\n", (int)baseDC, (int)baseRC); + return false; + } + + if ((qglGetString = (const GLubyte* (GLAPIENTRY *)(GLenum name))GL_GetProcAddress("glGetString")) == NULL) + { + VID_Shutdown(); + Con_Print("glGetString not found\n"); + return false; + } + if ((qwglGetExtensionsStringARB = (const char *(WINAPI *)(HDC hdc))GL_GetProcAddress("wglGetExtensionsStringARB")) == NULL) + Con_Print("wglGetExtensionsStringARB not found\n"); + + 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(baseDC); + + // now some nice Windows pain: + // we have created a window, we needed one to find out if there are + // any multisample pixel formats available, the problem is that to + // actually use one of those multisample formats we now have to + // recreate the window (yes Microsoft OpenGL really is that bad) + + if (windowpass == 0) + { + if (!GL_CheckExtension("WGL_ARB_pixel_format", wglpixelformatfuncs, "-noarbpixelformat", false) || !qwglChoosePixelFormatARB(baseDC, attribs, attribsf, 1, &newpixelformat, &numpixelformats) || !newpixelformat) + break; + // ok we got one - do it all over again with newpixelformat + qwglMakeCurrent(NULL, NULL); + qwglDeleteContext(baseRC);baseRC = 0; + ReleaseDC(mainwindow, baseDC);baseDC = 0; + // eat up any messages waiting for us + while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage (&msg); + DispatchMessage (&msg); + } + } } + Con_DPrintf("GL_VENDOR: %s\n", gl_vendor); + Con_DPrintf("GL_RENDERER: %s\n", gl_renderer); + Con_DPrintf("GL_VERSION: %s\n", gl_version); + Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions); + Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions); + /* if (!fullscreen) SetWindowPos (mainwindow, NULL, CenterX, CenterY, 0, 0,SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME); @@ -806,11 +1174,6 @@ int VID_InitMode (int fullscreen, int width, int height, int bpp, int stencil) 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 @@ -827,384 +1190,136 @@ int VID_InitMode (int fullscreen, int width, int height, int bpp, int stencil) 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; -} - -void VID_Shutdown (void) -{ - HGLRC hRC = 0; - HDC hDC = 0; - - if (vid_initialized) - { - vid_initialized = false; - - IN_DeactivateMouse (); - IN_ShowMouse (); - - if (g_pMouse) - IDirectInputDevice_Release(g_pMouse); - g_pMouse = NULL; - - if (g_pdi) - IDirectInput_Release(g_pdi); - g_pdi = NULL; - - 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); - - if (vid_isfullscreen) - ChangeDisplaySettings (NULL, 0); - - AppActivate(false, false); - - VID_RestoreSystemGamma(); - } -} - - -// input code - -#include - -#define DINPUT_BUFFERSIZE 16 -#define iDirectInputCreate(a,b,c,d) pDirectInputCreate(a,b,c,d) - -HRESULT (WINAPI *pDirectInputCreate)(HINSTANCE hinst, DWORD dwVersion, - LPDIRECTINPUT * lplpDirectInput, LPUNKNOWN punkOuter); - -// 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 -{ - AxisNada = 0, AxisForward, AxisLook, AxisSide, AxisTurn -}; - -DWORD dwAxisFlags[JOY_MAX_AXES] = -{ - JOY_RETURNX, JOY_RETURNY, JOY_RETURNZ, JOY_RETURNR, JOY_RETURNU, JOY_RETURNV -}; - -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; + SetWindowPos (mainwindow, HWND_TOP, 0, 0, 0, 0, SWP_DRAWFRAME | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOCOPYBITS); -static HINSTANCE hInstDI; + SetForegroundWindow (mainwindow); -//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,}, -}; + // fix the leftover Alt from any Alt-Tab or the like that switched us away + ClearAllStates (); -#define NUM_OBJECTS (sizeof(rgodf) / sizeof(rgodf[0])) + gl_videosyncavailable = false; -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 -}; +// COMMANDLINEOPTION: Windows WGL: -novideosync disables WGL_EXT_swap_control + gl_videosyncavailable = GL_CheckExtension("WGL_EXT_swap_control", wglswapintervalfuncs, "-novideosync", false); -// forward-referenced functions -void IN_StartupJoystick (void); -void Joy_AdvancedUpdate_f (void); -void IN_JoyMove (usercmd_t *cmd); + GL_Init (); + //vid_menudrawfn = VID_MenuDraw; + //vid_menukeyfn = VID_MenuKey; + vid_usingmouse = false; + vid_usingvsync = false; + vid_hidden = false; + vid_initialized = true; -/* -=========== -IN_ShowMouse -=========== -*/ -void IN_ShowMouse (void) -{ - if (!mouseshowtoggle) + IN_StartupMouse (); + IN_StartupJoystick (); + + if (gl_videosyncavailable) { - ShowCursor (true); - mouseshowtoggle = 1; + vid_usevsync = vid_vsync.integer; + vid_usingvsync = vid_vsync.integer; + qwglSwapIntervalEXT (vid_usevsync); } -} + return true; +} -/* -=========== -IN_HideMouse -=========== -*/ -void IN_HideMouse (void) +static void IN_Shutdown(void); +void VID_Shutdown (void) { - if (mouseshowtoggle) - { - ShowCursor (false); - mouseshowtoggle = 0; - } -} + if(vid_initialized == false) + return; + VID_RestoreSystemGamma(); -/* -=========== -IN_ActivateMouse -=========== -*/ -void IN_ActivateMouse (void) + vid_initialized = false; + IN_Shutdown(); + if (qwglMakeCurrent) + qwglMakeCurrent(NULL, NULL); + if (baseRC && qwglDeleteContext) + qwglDeleteContext(baseRC); + // close the library before we get rid of the window + GL_CloseLibrary(); + if (baseDC && mainwindow) + ReleaseDC(mainwindow, baseDC); + AppActivate(false, false); + if (mainwindow) + DestroyWindow(mainwindow); + mainwindow = 0; + if (vid_isfullscreen) + ChangeDisplaySettings (NULL, 0); + vid_isfullscreen = false; +} + +static void IN_Activate (qboolean grab) { + static qboolean restore_spi; + static int originalmouseparms[3]; - mouseactivatetoggle = true; + if (!mouseinitialized) + return; - if (mouseinitialized) + if (grab) { - if (dinput) + if (!vid_usingmouse) { - if (g_pMouse) + vid_usingmouse = true; + cl_ignoremousemoves = 2; + if (dinput && g_pMouse) { - if (!dinput_acquired) - { - IDirectInputDevice_Acquire(g_pMouse); - dinput_acquired = true; - } + IDirectInputDevice_Acquire(g_pMouse); + dinput_acquired = true; } else { - return; + RECT window_rect; + window_rect.left = window_x; + window_rect.top = window_y; + window_rect.right = window_x + vid.width; + window_rect.bottom = window_y + vid.height; + + // change mouse settings to turn off acceleration +// COMMANDLINEOPTION: Windows GDI Input: -noforcemparms disables setting of mouse parameters (not used with -dinput, windows only) + if (!COM_CheckParm ("-noforcemparms") && SystemParametersInfo (SPI_GETMOUSE, 0, originalmouseparms, 0)) + { + int newmouseparms[3]; + newmouseparms[0] = 0; // threshold to double movement (only if accel level is >= 1) + newmouseparms[1] = 0; // threshold to quadruple movement (only if accel level is >= 2) + newmouseparms[2] = 0; // maximum level of acceleration (0 = off) + restore_spi = SystemParametersInfo (SPI_SETMOUSE, 0, newmouseparms, 0); + } + else + restore_spi = false; + SetCursorPos ((window_x + vid.width / 2), (window_y + vid.height / 2)); + + SetCapture (mainwindow); + ClipCursor (&window_rect); } + ShowCursor (false); } - 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); - } - - mouseactive = true; } -} - - -/* -=========== -IN_DeactivateMouse -=========== -*/ -void IN_DeactivateMouse (void) -{ - - mouseactivatetoggle = false; - - if (mouseinitialized) + else { - if (dinput) + if (vid_usingmouse) { - if (g_pMouse) + vid_usingmouse = false; + cl_ignoremousemoves = 2; + if (dinput_acquired) { - if (dinput_acquired) - { - IDirectInputDevice_Unacquire(g_pMouse); - dinput_acquired = false; - } + IDirectInputDevice_Unacquire(g_pMouse); + dinput_acquired = false; } + else + { + // restore system mouseparms if we changed them + if (restore_spi) + SystemParametersInfo (SPI_SETMOUSE, 0, originalmouseparms, 0); + restore_spi = false; + ClipCursor (NULL); + ReleaseCapture (); + } + ShowCursor (true); } - else - { - if (restore_spi) - SystemParametersInfo (SPI_SETMOUSE, 0, originalmouseparms, 0); - - ClipCursor (NULL); - ReleaseCapture (); - } - - mouseactive = false; } } @@ -1214,7 +1329,7 @@ void IN_DeactivateMouse (void) IN_InitDInput =========== */ -qboolean IN_InitDInput (void) +static qboolean IN_InitDInput (void) { HRESULT hr; DIPROPDWORD dipdw = { @@ -1230,10 +1345,10 @@ qboolean IN_InitDInput (void) if (!hInstDI) { hInstDI = LoadLibrary("dinput.dll"); - + if (hInstDI == NULL) { - Con_SafePrintf ("Couldn't load dinput.dll\n"); + Con_Print("Couldn't load dinput.dll\n"); return false; } } @@ -1244,7 +1359,7 @@ qboolean IN_InitDInput (void) if (!pDirectInputCreate) { - Con_SafePrintf ("Couldn't get DI proc addr\n"); + Con_Print("Couldn't get DI proc addr\n"); return false; } } @@ -1262,16 +1377,16 @@ qboolean IN_InitDInput (void) if (FAILED(hr)) { - Con_SafePrintf ("Couldn't open DI mouse device\n"); + Con_Print("Couldn't open DI mouse device\n"); return false; } // set the data format to "mouse format". - hr = IDirectInputDevice_SetDataFormat(g_pMouse, &df); + hr = IDirectInputDevice_SetDataFormat(g_pMouse, &c_dfDIMouse); if (FAILED(hr)) { - Con_SafePrintf ("Couldn't set DI mouse format\n"); + Con_Print("Couldn't set DI mouse format\n"); return false; } @@ -1281,7 +1396,7 @@ qboolean IN_InitDInput (void) if (FAILED(hr)) { - Con_SafePrintf ("Couldn't set DI coop level\n"); + Con_Print("Couldn't set DI coop level\n"); return false; } @@ -1292,7 +1407,7 @@ qboolean IN_InitDInput (void) if (FAILED(hr)) { - Con_SafePrintf ("Couldn't set DI buffersize\n"); + Con_Print("Couldn't set DI buffersize\n"); return false; } @@ -1305,89 +1420,23 @@ qboolean IN_InitDInput (void) IN_StartupMouse =========== */ -void IN_StartupMouse (void) +static void IN_StartupMouse (void) { - if (COM_CheckParm ("-nomouse") || COM_CheckParm("-safe")) - return; + if (COM_CheckParm ("-nomouse")) + return; mouseinitialized = true; +// COMMANDLINEOPTION: Windows Input: -dinput enables DirectInput for mouse/joystick input if (COM_CheckParm ("-dinput")) - { dinput = IN_InitDInput (); - if (dinput) - { - Con_SafePrintf ("DirectInput initialized\n"); - } - else - { - Con_SafePrintf ("DirectInput not initialized\n"); - } - } - - if (!dinput) - { - mouseparmsvalid = SystemParametersInfo (SPI_GETMOUSE, 0, originalmouseparms, 0); - - if (mouseparmsvalid) - { - if ( COM_CheckParm ("-noforcemspd") ) - newmouseparms[2] = originalmouseparms[2]; - - if ( COM_CheckParm ("-noforcemaccel") ) - { - newmouseparms[0] = originalmouseparms[0]; - newmouseparms[1] = originalmouseparms[1]; - } - - if ( COM_CheckParm ("-noforcemparms") ) - { - newmouseparms[0] = originalmouseparms[0]; - newmouseparms[1] = originalmouseparms[1]; - newmouseparms[2] = originalmouseparms[2]; - } - } - } - - mouse_buttons = 3; - -// if a fullscreen video mode was set before the mouse was initialized, -// set the mouse state appropriately - if (mouseactivatetoggle) - IN_ActivateMouse (); -} - - -/* -=========== -IN_MouseEvent -=========== -*/ -void IN_MouseEvent (int mstate) -{ - int i; - - if (mouseactive && !dinput) - { - // perform button actions - for (i=0 ; i 0) + { + Key_Event (K_MWHEELUP, 0, true); + Key_Event (K_MWHEELUP, 0, false); + } break; case DIMOFS_BUTTON0: @@ -1465,41 +1527,39 @@ void IN_MouseMove (usercmd_t *cmd) else mstate_di &= ~(1<<2); break; - } - } - - // perform button actions - 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) @@ -1928,7 +1937,7 @@ void IN_JoyMove (usercmd_t *cmd) // user wants forward control to be forward control if (fabs(fAxisValue) > joy_forwardthreshold.value) { - cmd->forwardmove += (fAxisValue * joy_forwardsensitivity.value) * speed * cl_forwardspeed.value; + cl.cmd.forwardmove += (fAxisValue * joy_forwardsensitivity.value) * speed * cl_forwardspeed.value; } } break; @@ -1936,7 +1945,7 @@ void IN_JoyMove (usercmd_t *cmd) case AxisSide: if (fabs(fAxisValue) > joy_sidethreshold.value) { - cmd->sidemove += (fAxisValue * joy_sidesensitivity.value) * speed * cl_sidespeed.value; + cl.cmd.sidemove += (fAxisValue * joy_sidesensitivity.value) * speed * cl_sidespeed.value; } break; @@ -1946,7 +1955,7 @@ void IN_JoyMove (usercmd_t *cmd) // user wants turn control to become side control if (fabs(fAxisValue) > joy_sidethreshold.value) { - cmd->sidemove -= (fAxisValue * joy_sidesensitivity.value) * speed * cl_sidespeed.value; + cl.cmd.sidemove -= (fAxisValue * joy_sidesensitivity.value) * speed * cl_sidespeed.value; } } else @@ -2001,3 +2010,43 @@ void IN_JoyMove (usercmd_t *cmd) } } +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); + Cvar_RegisterVariable (&vid_forcerefreshrate); + Cmd_AddCommand ("joyadvancedupdate", Joy_AdvancedUpdate_f, "applies current joyadv* cvar settings to the joystick driver"); +} + +static void IN_Shutdown(void) +{ + IN_Activate (false); + + if (g_pMouse) + IDirectInputDevice_Release(g_pMouse); + g_pMouse = NULL; + + if (g_pdi) + IDirectInput_Release(g_pdi); + g_pdi = NULL; +}