X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=vid_wgl.c;h=1902eef76d7a3c1f71296175105f979621d3a255;hb=045f7768d970a449ecde1c762d141d83535170c1;hp=578b94a15e3a597fa553d66a304275927fd0ad49;hpb=7bbc05e4b0d3041dfdac6fc6c5506710594fe2c9;p=xonotic%2Fdarkplaces.git diff --git a/vid_wgl.c b/vid_wgl.c index 578b94a1..1902eef7 100644 --- a/vid_wgl.c +++ b/vid_wgl.c @@ -17,484 +17,350 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -// gl_vidnt.c -- NT GL vid component +// vid_wgl.c -- NT GL vid component + +#ifdef SUPPORTDIRECTX +// Include DX libs +#pragma comment(lib, "dinput8.lib") +#pragma comment(lib, "dxguid.lib") +#ifndef DIRECTINPUT_VERSION +# define DIRECTINPUT_VERSION 0x0500 /* Version 5.0 */ +#endif +#endif #include "quakedef.h" -#include "winquake.h" +#include +#include +#ifdef SUPPORTDIRECTX +#include +#endif #include "resource.h" #include - -#define MAX_MODE_LIST 30 -#define VID_ROW_SIZE 3 -#define MAXWIDTH 10000 -#define MAXHEIGHT 10000 - -#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}, +#ifdef SUPPORTDIRECTX +#include +#endif + +extern HINSTANCE global_hInstance; + + +#ifndef WM_MOUSEWHEEL +#define WM_MOUSEWHEEL 0x020A +#endif + +// Tell startup code that we have a client +int cl_available = true; + +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}, +// {"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} }; -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 badmode; +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 windowed, leavecurrentmode; -static qboolean vid_canalttab = 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_usinghidecursor = false; +static qboolean vid_usingvsync = false; +static qboolean vid_usevsync = false; static HICON hIcon; -int DIBWidth, DIBHeight; -RECT WindowRect; -DWORD WindowStyle, ExWindowStyle; - +// used by cd_win.c and snd_win.c HWND mainwindow; -int vid_modenum = NO_MODE; -int vid_realmode; -int vid_default = MODE_WINDOWED; -static int windowed_default; -unsigned char vid_curpal[256*3]; +static HDC baseDC; +static HGLRC baseRC; -HGLRC baseRC; -HDC maindc; +//HWND WINAPI InitializeWindow (HINSTANCE hInstance, int nCmdShow); -HWND WINAPI InitializeWindow (HINSTANCE hInstance, int nCmdShow); +static qboolean vid_isfullscreen; -// global video state -viddef_t vid; +//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); +//LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); +//void AppActivate(BOOL fActive, BOOL minimize); +//void ClearAllStates (void); +//void VID_UpdateWindowStatus (void); //==================================== -int window_center_x, window_center_y, window_x, window_y, window_width, window_height; -RECT window_rect; - -// direct draw software compatability stuff - -void CenterWindow(HWND hWndCenter, int width, int height, BOOL lefttopjustify) +static int window_x, window_y; + +static qboolean mouseinitialized; + +#ifdef SUPPORTDIRECTX +static qboolean dinput; +#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); +#endif + +// 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 */ + +// mouse variables +static int mouse_buttons; +static int mouse_oldbuttonstate; + +static unsigned int uiWheelMessage; +#ifdef SUPPORTDIRECTX +static qboolean dinput_acquired; + +static unsigned int mstate_di; +#endif + +// 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 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); -} + AxisNada = 0, AxisForward, AxisLook, AxisSide, AxisTurn +}; -qboolean VID_SetWindowedMode (int modenum) +static DWORD dwAxisFlags[JOY_MAX_AXES] = { - int lastmodestate, width, height; - RECT rect; - - lastmodestate = modestate; - - WindowRect.top = WindowRect.left = 0; - - WindowRect.right = modelist[modenum].width; - WindowRect.bottom = modelist[modenum].height; - - DIBWidth = modelist[modenum].width; - DIBHeight = modelist[modenum].height; - - WindowStyle = WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX; - ExWindowStyle = 0; - - rect = WindowRect; - AdjustWindowRectEx(&rect, WindowStyle, false, 0); - - width = rect.right - rect.left; - height = rect.bottom - rect.top; - - // Create the DIB window - mainwindow = CreateWindowEx (ExWindowStyle, gamename, gamename, WindowStyle, rect.left, rect.top, width, height, NULL, NULL, global_hInstance, NULL); - - if (!mainwindow) - Sys_Error ("Couldn't create DIB window"); - - // Center and show the DIB window - CenterWindow(mainwindow, WindowRect.right - WindowRect.left, WindowRect.bottom - WindowRect.top, false); - - ShowWindow (mainwindow, SW_SHOWDEFAULT); - UpdateWindow (mainwindow); - - modestate = MS_WINDOWED; - - if (vid.conheight > modelist[modenum].height) - vid.conheight = modelist[modenum].height; - if (vid.conwidth > modelist[modenum].width) - vid.conwidth = modelist[modenum].width; + JOY_RETURNX, JOY_RETURNY, JOY_RETURNZ, JOY_RETURNR, JOY_RETURNU, JOY_RETURNV +}; - SendMessage (mainwindow, WM_SETICON, (WPARAM)true, (LPARAM)hIcon); - SendMessage (mainwindow, WM_SETICON, (WPARAM)false, (LPARAM)hIcon); +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; + +#ifdef SUPPORTDIRECTX +static LPDIRECTINPUT g_pdi; +static LPDIRECTINPUTDEVICE g_pMouse; +static HINSTANCE hInstDI; +#endif + +static JOYINFOEX ji; + +// forward-referenced functions +static void IN_StartupJoystick (void); +static void Joy_AdvancedUpdate_f (void); +static void IN_JoyMove (void); +static void IN_StartupMouse (void); - return true; -} +//==================================== -qboolean VID_SetFullDIBMode (int modenum) +void VID_Finish (void) { - int lastmodestate, width, height; - RECT rect; - - if (!leavecurrentmode) + vid_usevsync = vid_vsync.integer && !cls.timedemo && qwglSwapIntervalEXT; + if (vid_usingvsync != vid_usevsync) { - 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"); + vid_usingvsync = vid_usevsync; + qwglSwapIntervalEXT (vid_usevsync); } - 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 - mainwindow = CreateWindowEx (ExWindowStyle, gamename, gamename, WindowStyle, rect.left, rect.top, width, height, NULL, NULL, global_hInstance, NULL); - - if (!mainwindow) - Sys_Error ("Couldn't create DIB window"); - - ShowWindow (mainwindow, SW_SHOWDEFAULT); - UpdateWindow (mainwindow); - - if (vid.conheight > modelist[modenum].height) - vid.conheight = modelist[modenum].height; - if (vid.conwidth > modelist[modenum].width) - vid.conwidth = modelist[modenum].width; - -// needed because we're not getting WM_MOVE messages fullscreen on NT - window_x = 0; - window_y = 0; - - SendMessage (mainwindow, WM_SETICON, (WPARAM)true, (LPARAM)hIcon); - SendMessage (mainwindow, WM_SETICON, (WPARAM)false, (LPARAM)hIcon); - - return true; -} - - -int VID_SetMode (int modenum) -{ - int original_mode; - qboolean stat = 0; - MSG msg; - - if ((windowed && (modenum != 0)) || (!windowed && (modenum < 1)) || (!windowed && (modenum >= nummodes))) - Sys_Error ("Bad video mode\n"); - - 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) - stat = VID_SetWindowedMode(modenum); - else if (modelist[modenum].type == MS_FULLDIB) - stat = VID_SetFullDIBMode(modenum); - else - Sys_Error ("VID_SetMode: Bad mode type in modelist"); - - window_width = DIBWidth; - window_height = DIBHeight; - VID_UpdateWindowStatus (); - - CDAudio_Resume (); - - 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_modenum = modenum; - Cvar_SetValue ("vid_mode", (float)vid_modenum); - - while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) + if (!vid_hidden) { - TranslateMessage (&msg); - DispatchMessage (&msg); + CHECKGLERROR + if (r_speeds.integer == 2 || gl_finish.integer) + { + qglFinish();CHECKGLERROR + } + SwapBuffers(baseDC); } - Sleep (100); - - SetWindowPos (mainwindow, HWND_TOP, 0, 0, 0, 0, SWP_DRAWFRAME | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOCOPYBITS); + // make sure a context switch can happen every frame - Logitech drivers + // input drivers sometimes eat cpu time every 3 seconds or lag badly + // without this help + Sleep(0); - SetForegroundWindow (mainwindow); + VID_UpdateGamma(false, 256); +} -// fix the leftover Alt from any Alt-Tab or the like that switched us away - ClearAllStates (); +//========================================================================== - if (!msg_suppress_1) - Con_SafePrintf ("Video mode %s initialized.\n", VID_GetModeDescription (vid_modenum)); - return true; -} -/* -================ -VID_UpdateWindowStatus -================ -*/ -void VID_UpdateWindowStatus (void) +static unsigned char scantokey[128] = { - 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 (); -} - +// 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 +}; -//==================================== /* -================= -VID_GetWindowSize -================= +======= +MapKey + +Map from windows to quake keynums +======= */ -void VID_GetWindowSize (int *x, int *y, int *width, int *height) +static int MapKey (int key, int virtualkey) { - *x = *y = 0; - *width = WindowRect.right - WindowRect.left; - *height = WindowRect.bottom - WindowRect.top; -} + int result; + int modified = (key >> 16) & 255; + qboolean is_extended = false; - -void VID_Finish (void) -{ - int vid_usemouse; - if (r_render.integer && !scr_skipupdate) + if (modified < 128 && scantokey[modified]) + result = scantokey[modified]; + else { - qglFinish(); - SwapBuffers(maindc); + result = 0; + Con_DPrintf("key 0x%02x (0x%8x, 0x%8x) has no translation\n", modified, key, virtualkey); } -// handle the mouse state when windowed if that's changed - vid_usemouse = false; - if (vid_mouse.integer && !key_consoleactive) - vid_usemouse = true; - if (modestate == MS_FULLDIB) - vid_usemouse = true; - if (!vid_activewindow) - vid_usemouse = false; - if (vid_usemouse) + if (key & (1 << 24)) + is_extended = true; + + if ( !is_extended ) { - if (!vid_usingmouse) + switch ( result ) { - vid_usingmouse = true; - IN_ActivateMouse (); - IN_HideMouse(); + 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 { - if (vid_usingmouse) + switch ( result ) { - vid_usingmouse = false; - IN_DeactivateMouse (); - IN_ShowMouse(); + case 0x0D: + return K_KP_ENTER; + case 0x2F: + return K_KP_SLASH; + case 0xAF: + return K_KP_PLUS; } + return result; } } -void VID_SetDefaultMode (void) -{ - IN_DeactivateMouse (); -} - -void VID_RestoreSystemGamma(void); - -void VID_Shutdown (void) -{ - HGLRC hRC; - HDC hDC; - int i; - GLuint temp[8192]; - - if (vid_initialized) - { - 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+1; - qglDeleteTextures(8192, temp); - - if (hRC) - wglDeleteContext(hRC); - - // close the library before we get rid of the window - GL_CloseLibrary(); - - if (hDC && mainwindow) - ReleaseDC(mainwindow, hDC); - - if (modestate == MS_FULLDIB) - ChangeDisplaySettings (NULL, 0); - - if (maindc && mainwindow) - ReleaseDC (mainwindow, maindc); - - AppActivate(false, false); - - VID_RestoreSystemGamma(); - } -} - - -//========================================================================== - - -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; -} - - - -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_LEFTARROW,'5' ,K_RIGHTARROW,'+' ,K_END , // 4 - K_DOWNARROW,K_PGDN,K_INS,K_DEL,0 ,0 ,0 ,K_F11 ,K_F12 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5 - 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6 - 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7 -}; - - -/* -======= -MapKey - -Map from windows to quake keynums -======= -*/ -int MapKey (int key, 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]; -} - /* =================================================================== @@ -508,23 +374,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) /**************************************************************************** * @@ -537,28 +393,34 @@ 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; + vid_activewindow = fActive != FALSE; + vid_hidden = minimize != FALSE; -// 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) { - if (modestate == MS_FULLDIB) + if (vid_isfullscreen) { - if (vid_canalttab && vid_wassuspended) + if (vid_wassuspended) { vid_wassuspended = false; ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN); @@ -568,16 +430,12 @@ 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 (); - if (modestate == MS_FULLDIB && vid_canalttab) + VID_SetMouse(false, false, false); + if (vid_isfullscreen) { ChangeDisplaySettings (NULL, 0); vid_wassuspended = true; @@ -586,14 +444,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; + unsigned char state[256]; + unsigned char asciichar[4]; + int vkey; + int charlength; + qboolean down = false; if ( uMsg == uiWheelMessage ) uMsg = WM_MOUSEWHEEL; @@ -601,7 +498,7 @@ LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) switch (uMsg) { case WM_KILLFOCUS: - if (modestate == MS_FULLDIB) + if (vid_isfullscreen) ShowWindow(mainwindow, SW_SHOWMINNOACTIVE); break; @@ -611,23 +508,40 @@ 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 (); + VID_SetMouse(false, false, 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, (LPWORD)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 + // note: password-locked screensavers on Vista still work + if (vid_activewindow && ((wParam & 0xFFF0) == SC_SCREENSAVE || (wParam & 0xFFF0) == SC_MONITORPOWER)) + lRet = 0; + else + lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); + 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: @@ -636,6 +550,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; @@ -648,7 +564,37 @@ 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; + +#ifdef SUPPORTDIRECTX + if (!dinput_acquired) +#endif + { + // 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; @@ -670,7 +616,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; @@ -684,14 +630,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); @@ -707,658 +648,1467 @@ LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) return lRet; } +int VID_SetGamma(unsigned short *ramps, int rampsize) +{ + 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, int rampsize) { - return nummodes; + HDC hdc = GetDC (NULL); + int i = GetDeviceGammaRamp(hdc, ramps); + ReleaseDC (NULL, hdc); + return i; // return success or failure } +static HINSTANCE gldll; -/* -================= -VID_GetModePtr -================= -*/ -vmode_t *VID_GetModePtr (int modenum) +static void GL_CloseLibrary(void) { + FreeLibrary(gldll); + gldll = 0; + gl_driver[0] = 0; + qwglGetProcAddress = NULL; + gl_extensions = ""; + gl_platform = ""; + gl_platformextensions = ""; +} - if ((modenum >= 0) && (modenum < nummodes)) - return &modelist[modenum]; - else - return &badmode; +static 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; + } + strlcpy(gl_driver, name, sizeof(gl_driver)); + return true; } +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; +} -/* -================= -VID_GetModeDescription -================= -*/ -char *VID_GetModeDescription (int mode) +#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) { - char *pinfo; - vmode_t *pv; - static char temp[100]; + WNDCLASS wc; - if ((mode < 0) || (mode >= nummodes)) - return NULL; + InitCommonControls(); + hIcon = LoadIcon (global_hInstance, MAKEINTRESOURCE (IDI_ICON1)); - if (!leavecurrentmode) - { - pv = VID_GetModePtr (mode); - pinfo = pv->modedesc; - } - else - { - sprintf (temp, "Desktop resolution (%dx%d)", modelist[MODE_FULLSCREEN_DEFAULT].width, modelist[MODE_FULLSCREEN_DEFAULT].height); - pinfo = temp; - } + // Register the frame class + wc.style = 0; + wc.lpfnWndProc = (WNDPROC)MainWndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = global_hInstance; + wc.hIcon = hIcon; + wc.hCursor = LoadCursor (NULL,IDC_ARROW); + wc.hbrBackground = NULL; + wc.lpszMenuName = 0; + wc.lpszClassName = "DarkPlacesWindowClass"; - return pinfo; -} + if (!RegisterClass (&wc)) + Con_Printf ("Couldn't register window class\n"); + memset(&initialdevmode, 0, sizeof(initialdevmode)); + EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &initialdevmode); -// KJB: Added this to return the mode driver name in description for console + IN_Init(); +} -char *VID_GetExtModeDescription (int mode) +qboolean VID_InitMode(viddef_mode_t *mode) { - static char pinfo[40]; - vmode_t *pv; + 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 windowpass; + int pixelformat, newpixelformat; + UINT numpixelformats; + DWORD WindowStyle, ExWindowStyle; + int CenterX, CenterY; + const char *gldrivername; + int depth; + DEVMODE thismode; + qboolean foundmode, foundgoodmode; + int *a; + float *af; + int attribs[128]; + float attribsf[16]; + int bpp = mode->bitsperpixel; + int width = mode->width; + int height = mode->height; + int refreshrate = (int)floor(mode->refreshrate+0.5); + int stereobuffer = mode->stereobuffer; + int samples = mode->samples; + int fullscreen = mode->fullscreen; - if ((mode < 0) || (mode >= nummodes)) - return NULL; + if (vid_initialized) + Sys_Error("VID_InitMode called when video is already initialised"); - pv = VID_GetModePtr (mode); - if (modelist[mode].type == MS_FULLDIB) + // if stencil is enabled, ask for alpha too + if (bpp >= 32) { - if (!leavecurrentmode) - sprintf(pinfo,"%s fullscreen", pv->modedesc); - else - sprintf (pinfo, "Desktop resolution (%dx%d)", modelist[MODE_FULLSCREEN_DEFAULT].width, modelist[MODE_FULLSCREEN_DEFAULT].height); + pfd.cRedBits = 8; + pfd.cGreenBits = 8; + pfd.cBlueBits = 8; + pfd.cAlphaBits = 8; + pfd.cDepthBits = 24; + pfd.cStencilBits = 8; } else { - if (modestate == MS_WINDOWED) - sprintf(pinfo, "%s windowed", pv->modedesc); - else - sprintf(pinfo, "windowed"); + pfd.cRedBits = 5; + pfd.cGreenBits = 5; + pfd.cBlueBits = 5; + pfd.cAlphaBits = 0; + pfd.cDepthBits = 16; + pfd.cStencilBits = 0; } - return pinfo; -} + 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; -/* -================= -VID_DescribeCurrentMode_f -================= -*/ -void VID_DescribeCurrentMode_f (void) -{ - Con_Printf ("%s\n", VID_GetExtModeDescription (vid_modenum)); -} - - -/* -================= -VID_NumModes_f -================= -*/ -void VID_NumModes_f (void) -{ - if (nummodes == 1) - Con_Printf ("%d video mode is available\n", nummodes); + 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++ = 8; + *a++ = WGL_DEPTH_BITS_ARB; + *a++ = 24; + *a++ = WGL_STENCIL_BITS_ARB; + *a++ = 8; + } else - Con_Printf ("%d video modes are available\n", nummodes); -} + { + *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; + } -/* -================= -VID_DescribeMode_f -================= -*/ -void VID_DescribeMode_f (void) -{ - int t, modenum; + if (samples > 1) + { + *a++ = WGL_SAMPLE_BUFFERS_ARB; + *a++ = 1; + *a++ = WGL_SAMPLES_ARB; + *a++ = samples; + } - modenum = atoi (Cmd_Argv(1)); + *a = 0; + *af = 0; - t = leavecurrentmode; - leavecurrentmode = 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]; + if (!GL_OpenLibrary(gldrivername)) + { + Con_Printf("Unable to load GL driver %s\n", gldrivername); + return false; + } - Con_Printf ("%s\n", VID_GetExtModeDescription (modenum)); + memset(&gdevmode, 0, sizeof(gdevmode)); - leavecurrentmode = t; -} + vid_isfullscreen = false; + if (fullscreen) + { + 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; -/* -================= -VID_DescribeModes_f -================= -*/ -void VID_DescribeModes_f (void) -{ - int i, lnummodes, t; - char *pinfo; - vmode_t *pv; + 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_extra.integer) + Con_DPrintf("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_extra.integer) + Con_DPrintf("wrong bpp\n"); + continue; + } + if(thismode.dmPelsWidth != (DWORD)width) + { + if(developer_extra.integer) + Con_DPrintf("wrong width\n"); + continue; + } + if(thismode.dmPelsHeight != (DWORD)height) + { + if(developer_extra.integer) + Con_DPrintf("wrong height\n"); + continue; + } - lnummodes = VID_NumModes (); + 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_extra.integer) + Con_DPrintf("too high refresh rate\n"); + continue; + } + else if(thismode.dmDisplayFrequency <= gdevmode.dmDisplayFrequency) + { + if(developer_extra.integer) + Con_DPrintf("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_extra.integer) + Con_DPrintf("doesn't beat previous best match (too high)\n"); + continue; + } + } + // otherwise, take anything - t = leavecurrentmode; - leavecurrentmode = 0; + memcpy(&gdevmode, &thismode, sizeof(gdevmode)); + if(thismode.dmDisplayFrequency <= (DWORD)refreshrate) + foundgoodmode = true; + else + { + if(developer_extra.integer) + Con_DPrintf("(out of range)\n"); + } + foundmode = true; + if(developer_extra.integer) + Con_DPrintf("accepted\n"); + } + } - for (i=1 ; i depth) + { + VID_Shutdown(); + Con_Print("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; } - leavecurrentmode = t; -} + rect.top = 0; + rect.left = 0; + rect.right = width; + rect.bottom = height; + AdjustWindowRectEx(&rect, WindowStyle, false, 0); -void VID_AddMode(int type, int width, int height, int modenum, int halfscreen, int dib, int fullscreen, int bpp) -{ - int i; - if (nummodes >= MAX_MODE_LIST) - return; - modelist[nummodes].type = type; - modelist[nummodes].width = width; - modelist[nummodes].height = height; - modelist[nummodes].modenum = modenum; - modelist[nummodes].halfscreen = halfscreen; - modelist[nummodes].dib = dib; - modelist[nummodes].fullscreen = fullscreen; - modelist[nummodes].bpp = bpp; - if (bpp == 0) - sprintf (modelist[nummodes].modedesc, "%dx%d", width, height); + if (fullscreen) + { + CenterX = 0; + CenterY = 0; + } else - sprintf (modelist[nummodes].modedesc, "%dx%dx%d", width, height, bpp); - for (i = 0;i < nummodes;i++) { - if (!memcmp(&modelist[i], &modelist[nummodes], sizeof(vmode_t))) - return; + CenterX = (GetSystemMetrics(SM_CXSCREEN) - (rect.right - rect.left)) / 2; + CenterY = (GetSystemMetrics(SM_CYSCREEN) - (rect.bottom - rect.top)) / 2; } - nummodes++; -} + CenterX = max(0, CenterX); + CenterY = max(0, CenterY); + + // x and y may be changed by WM_MOVE messages + window_x = CenterX; + window_y = CenterY; + rect.left += CenterX; + rect.right += CenterX; + rect.top += CenterY; + rect.bottom += CenterY; + + pixelformat = 0; + newpixelformat = 0; + // start out at the final windowpass if samples is 1 as it's the only feature we need extended pixel formats for + for (windowpass = samples == 1;windowpass < 2;windowpass++) + { + gl_extensions = ""; + gl_platformextensions = ""; -void VID_InitDIB (HINSTANCE hInstance) -{ - int w, h; - WNDCLASS wc; + 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, %p, %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, global_hInstance, NULL); + VID_Shutdown(); + return false; + } - // Register the frame class - wc.style = 0; - wc.lpfnWndProc = (WNDPROC)MainWndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = hInstance; - wc.hIcon = 0; - wc.hCursor = LoadCursor (NULL,IDC_ARROW); - wc.hbrBackground = NULL; - wc.lpszMenuName = 0; - wc.lpszClassName = gamename; + baseDC = GetDC(mainwindow); - if (!RegisterClass (&wc) ) - Sys_Error ("Couldn't register window class"); + if (!newpixelformat) + newpixelformat = ChoosePixelFormat(baseDC, &pfd); + pixelformat = newpixelformat; + if (!pixelformat) + { + VID_Shutdown(); + Con_Printf("ChoosePixelFormat(%p, %p) failed\n", baseDC, &pfd); + return false; + } - if (COM_CheckParm("-width")) - w = atoi(com_argv[COM_CheckParm("-width")+1]); - else - w = 640; + if (SetPixelFormat(baseDC, pixelformat, &pfd) == false) + { + VID_Shutdown(); + Con_Printf("SetPixelFormat(%p, %d, %p) failed\n", baseDC, pixelformat, &pfd); + return false; + } - if (w < 320) - w = 320; + if (!GL_CheckExtension("wgl", wglfuncs, NULL, false)) + { + VID_Shutdown(); + Con_Print("wgl functions not found\n"); + return false; + } - if (COM_CheckParm("-height")) - h = atoi(com_argv[COM_CheckParm("-height")+1]); - else - h = w * 240/320; + 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(%p, %p) failed\n", baseDC, baseRC); + return false; + } - if (h < 240) - h = 240; + 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"); - VID_AddMode(MS_WINDOWED, w, h, 0, 0, 1, 0, 0); -} + gl_extensions = (const char *)qglGetString(GL_EXTENSIONS); + gl_platform = "WGL"; + gl_platformextensions = ""; + if (qwglGetExtensionsStringARB) + gl_platformextensions = (const char *)qwglGetExtensionsStringARB(baseDC); -/* -================= -VID_InitFullDIB -================= -*/ -void VID_InitFullDIB (HINSTANCE hInstance) -{ - DEVMODE devmode; - int modenum; - int originalnummodes; - int numlowresmodes; - int j; - int bpp; - int done; - BOOL stat; - -// enumerate >8 bpp modes - originalnummodes = nummodes; - modenum = 0; - - do - { - stat = EnumDisplaySettings (NULL, modenum, &devmode); + if (!gl_extensions) + gl_extensions = ""; + if (!gl_platformextensions) + gl_platformextensions = ""; - if ((devmode.dmBitsPerPel >= 15) && (devmode.dmPelsWidth <= MAXWIDTH) && (devmode.dmPelsHeight <= MAXHEIGHT) && (nummodes < MAX_MODE_LIST)) - { - devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; + // 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 (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL) + 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)) { - // 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")) && (devmode.dmPelsWidth > (devmode.dmPelsHeight << 1))) - VID_AddMode(MS_FULLDIB, devmode.dmPelsWidth >> 1, devmode.dmPelsHeight, 0, 1, 1, 1, devmode.dmBitsPerPel); - else - VID_AddMode(MS_FULLDIB, devmode.dmPelsWidth, devmode.dmPelsHeight, 0, 0, 1, 1, devmode.dmBitsPerPel); + TranslateMessage (&msg); + DispatchMessage (&msg); } } - - modenum++; } - while (stat); -// see if there are any low-res modes that aren't being reported - numlowresmodes = sizeof(lowresmodes) / sizeof(lowresmodes[0]); - bpp = 16; - done = 0; + /* + if (!fullscreen) + SetWindowPos (mainwindow, NULL, CenterX, CenterY, 0, 0,SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME); + */ + + ShowWindow (mainwindow, SW_SHOWDEFAULT); + UpdateWindow (mainwindow); + + // 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); - do + while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) { - for (j=0 ; (j= 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) != FALSE; + } + else + restore_spi = false; + SetCursorPos ((window_x + vid.width / 2), (window_y + vid.height / 2)); + + SetCapture (mainwindow); + ClipCursor (&window_rect); + } + } + } + else + { + if (vid_usingmouse) + { + vid_usingmouse = false; + cl_ignoremousemoves = 2; +#ifdef SUPPORTDIRECTX + if (dinput_acquired) + { + IDirectInputDevice_Unacquire(g_pMouse); + dinput_acquired = false; + } + else +#endif + { + // restore system mouseparms if we changed them + if (restore_spi) + SystemParametersInfo (SPI_SETMOUSE, 0, originalmouseparms, 0); + restore_spi = false; + ClipCursor (NULL); + ReleaseCapture (); + } + } + } + + if (vid_usinghidecursor != hidecursor) + { + vid_usinghidecursor = hidecursor; + ShowCursor (!hidecursor); + } } + +#ifdef SUPPORTDIRECTX /* -=================== -VID_Init -=================== +=========== +IN_InitDInput +=========== */ -void VID_Init (void) +static qboolean IN_InitDInput (void) { - int i; - int basenummodes, width, height = 0, bpp, findbpp, done; - HDC hdc; - DEVMODE devmode; + HRESULT hr; + DIPROPDWORD dipdw = { + { + sizeof(DIPROPDWORD), // diph.dwSize + sizeof(DIPROPHEADER), // diph.dwHeaderSize + 0, // diph.dwObj + DIPH_DEVICE, // diph.dwHow + }, + DINPUT_BUFFERSIZE, // dwData + }; - GL_OpenLibrary(); + if (!hInstDI) + { + hInstDI = LoadLibrary("dinput.dll"); - memset(&devmode, 0, sizeof(devmode)); + if (hInstDI == NULL) + { + Con_Print("Couldn't load dinput.dll\n"); + return false; + } + } - Cmd_AddCommand ("vid_nummodes", VID_NumModes_f); - Cmd_AddCommand ("vid_describecurrentmode", VID_DescribeCurrentMode_f); - Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f); - Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f); + if (!pDirectInputCreate) + { + pDirectInputCreate = (HRESULT (__stdcall *)(HINSTANCE,DWORD,LPDIRECTINPUT *,LPUNKNOWN))GetProcAddress(hInstDI,"DirectInputCreateA"); - VID_GetSystemGamma(); + if (!pDirectInputCreate) + { + Con_Print("Couldn't get DI proc addr\n"); + return false; + } + } - hIcon = LoadIcon (global_hInstance, MAKEINTRESOURCE (IDI_ICON2)); +// register with DirectInput and get an IDirectInput to play with. + hr = iDirectInputCreate(global_hInstance, DIRECTINPUT_VERSION, &g_pdi, NULL); - InitCommonControls(); + if (FAILED(hr)) + { + return false; + } + +// obtain an interface to the system mouse device. +#ifdef __cplusplus + hr = IDirectInput_CreateDevice(g_pdi, GUID_SysMouse, &g_pMouse, NULL); +#else + hr = IDirectInput_CreateDevice(g_pdi, &GUID_SysMouse, &g_pMouse, NULL); +#endif - VID_InitDIB (global_hInstance); - basenummodes = nummodes = 1; + if (FAILED(hr)) + { + Con_Print("Couldn't open DI mouse device\n"); + return false; + } - VID_InitFullDIB (global_hInstance); +// set the data format to "mouse format". + hr = IDirectInputDevice_SetDataFormat(g_pMouse, &c_dfDIMouse); - if (COM_CheckParm("-window")) + if (FAILED(hr)) { - hdc = GetDC (NULL); + Con_Print("Couldn't set DI mouse format\n"); + return false; + } - if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) - Sys_Error ("Can't run in non-RGB mode"); +// set the cooperativity level. + hr = IDirectInputDevice_SetCooperativeLevel(g_pMouse, mainwindow, + DISCL_EXCLUSIVE | DISCL_FOREGROUND); - ReleaseDC (NULL, hdc); + if (FAILED(hr)) + { + Con_Print("Couldn't set DI coop level\n"); + return false; + } - windowed = true; - vid_default = MODE_WINDOWED; +// set the buffer size to DINPUT_BUFFERSIZE elements. +// the buffer size is a DWORD property associated with the device + hr = IDirectInputDevice_SetProperty(g_pMouse, DIPROP_BUFFERSIZE, &dipdw.diph); + + if (FAILED(hr)) + { + Con_Print("Couldn't set DI buffersize\n"); + return false; } + + return true; +} +#endif + + +/* +=========== +IN_StartupMouse +=========== +*/ +static void IN_StartupMouse (void) +{ + if (COM_CheckParm ("-nomouse")) + return; + + mouseinitialized = true; + +#ifdef SUPPORTDIRECTX +// COMMANDLINEOPTION: Windows Input: -dinput enables DirectInput for mouse/joystick input + if (COM_CheckParm ("-dinput")) + dinput = IN_InitDInput (); + + if (dinput) + Con_Print("DirectInput initialized\n"); else - { - if (nummodes == 1) - Sys_Error ("No RGB fullscreen modes available"); + Con_Print("DirectInput not initialized\n"); +#endif - windowed = false; + mouse_buttons = 10; +} - if (COM_CheckParm("-mode")) - vid_default = atoi(com_argv[COM_CheckParm("-mode")+1]); - else + +/* +=========== +IN_MouseMove +=========== +*/ +static void IN_MouseMove (void) +{ + POINT current_pos; + + GetCursorPos (¤t_pos); + in_windowmouse_x = current_pos.x - window_x; + in_windowmouse_y = current_pos.y - window_y; + + if (!vid_usingmouse) + return; + +#ifdef SUPPORTDIRECTX + if (dinput_acquired) + { + int i; + DIDEVICEOBJECTDATA od; + DWORD dwElements; + HRESULT hr; + + for (;;) { - if (COM_CheckParm("-current")) + dwElements = 1; + + hr = IDirectInputDevice_GetDeviceData(g_pMouse, + sizeof(DIDEVICEOBJECTDATA), &od, &dwElements, 0); + + if ((hr == DIERR_INPUTLOST) || (hr == DIERR_NOTACQUIRED)) { - modelist[MODE_FULLSCREEN_DEFAULT].width = GetSystemMetrics (SM_CXSCREEN); - modelist[MODE_FULLSCREEN_DEFAULT].height = GetSystemMetrics (SM_CYSCREEN); - vid_default = MODE_FULLSCREEN_DEFAULT; - leavecurrentmode = 1; + IDirectInputDevice_Acquire(g_pMouse); + break; } - else - { - if (COM_CheckParm("-width")) - width = atoi(com_argv[COM_CheckParm("-width")+1]); - else - width = 640; - if (COM_CheckParm("-bpp")) - { - bpp = atoi(com_argv[COM_CheckParm("-bpp")+1]); - findbpp = 0; - } - else - { - bpp = 15; - findbpp = 1; - } + /* Unable to read data or no data available */ + if (FAILED(hr) || dwElements == 0) + break; - if (COM_CheckParm("-height")) - height = atoi(com_argv[COM_CheckParm("-height")+1]); + /* Look at the element to see what happened */ - // if they want to force it, add the specified mode to the list - if (COM_CheckParm("-force") && (nummodes < MAX_MODE_LIST)) - VID_AddMode(MS_FULLDIB, width, height, 0, 0, 1, 1, bpp); + switch (od.dwOfs) + { + case DIMOFS_X: + in_mouse_x += (LONG) od.dwData; + break; - done = 0; + case DIMOFS_Y: + in_mouse_y += (LONG) od.dwData; + break; - do - { - if (COM_CheckParm("-height")) + case DIMOFS_Z: + if((LONG) od.dwData < 0) { - height = atoi(com_argv[COM_CheckParm("-height")+1]); - - for (i=1, vid_default=0 ; i 0) { - for (i=1, vid_default=0 ; iwidth)/2, 4, "gfx/vidmodes.lmp"); + memset (&ji, 0, sizeof(ji)); + ji.dwSize = sizeof(ji); + ji.dwFlags = joy_flags; + + if (joyGetPosEx (joy_id, &ji) == JOYERR_NOERROR) + { + // this is a hack -- there is a bug in the Logitech WingMan Warrior DirectInput Driver + // rather than having 32768 be the zero point, they have the zero point at 32668 + // go figure -- anyway, now we get the full resolution out of the device + if (joy_wwhack1.integer != 0.0) + { + ji.dwUpos += 100; + } + return true; + } + else + { + // read error occurred + // turning off the joystick seems too harsh for 1 read error, + // but what should be done? + return false; + } +} + - vid_wmodes = 0; - lnummodes = VID_NumModes (); +/* +=========== +IN_JoyMove +=========== +*/ +static void IN_JoyMove (void) +{ + float speed, aspeed; + float fAxisValue, fTemp; + int i, mouselook = (in_mlook.state & 1) || freelook.integer; - for (i=1 ; (i 0) + // verify joystick is available and that the user wants to use it + if (!joy_avail || !in_joystick.integer) { - M_Print (2*8, 36+0*8, "Fullscreen Modes (WIDTHxHEIGHTxBPP)"); + return; + } + + // collect the joystick data, if possible + if (IN_ReadJoystick () != true) + { + return; + } + + if (in_speed.state & 1) + speed = cl_movespeedkey.value; + else + speed = 1; + // LordHavoc: viewzoom affects sensitivity for sniping + aspeed = speed * cl.realframetime * cl.viewzoom; + + // loop through the axes + for (i = 0; i < JOY_MAX_AXES; i++) + { + // 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 + { + // user wants forward control to be forward control + if (fabs(fAxisValue) > joy_forwardthreshold.value) + { + cl.cmd.forwardmove += (fAxisValue * joy_forwardsensitivity.value) * speed * cl_forwardspeed.value; + } + } + break; + + case AxisSide: + if (fabs(fAxisValue) > joy_sidethreshold.value) + { + cl.cmd.sidemove += (fAxisValue * joy_sidesensitivity.value) * speed * cl_sidespeed.value; + } + break; + + case AxisTurn: + if ((in_strafe.state & 1) || (lookstrafe.integer && mouselook)) + { + // user wants turn control to become side control + if (fabs(fAxisValue) > joy_sidethreshold.value) + { + cl.cmd.sidemove -= (fAxisValue * joy_sidesensitivity.value) * speed * cl_sidespeed.value; + } + } else - M_Print (column, row, modedescs[i].desc); + { + // 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; + } - column += 13*8; + } + } + break; - if ((i % VID_ROW_SIZE) == (VID_ROW_SIZE - 1)) + case AxisLook: + if (mouselook) { - column = 8; - row += 8; + 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); + Cvar_RegisterVariable (&vid_forcerefreshrate); + Cmd_AddCommand ("joyadvancedupdate", Joy_AdvancedUpdate_f, "applies current joyadv* cvar settings to the joystick driver"); } +static void IN_Shutdown(void) +{ +#ifdef SUPPORTDIRECTX + if (g_pMouse) + IDirectInputDevice_Release(g_pMouse); + g_pMouse = NULL; + + if (g_pdi) + IDirectInput_Release(g_pdi); + g_pdi = NULL; +#endif +} -/* -================ -VID_MenuKey -================ -*/ -void VID_MenuKey (int key) +size_t VID_ListModes(vid_mode_t *modes, size_t maxcount) { - switch (key) - { - case K_ESCAPE: - S_LocalSound ("misc/menu1.wav"); - M_Menu_Options_f (); - break; + int i; + size_t k; + DEVMODE thismode; - default: - break; + thismode.dmSize = sizeof(thismode); + thismode.dmDriverExtra = 0; + k = 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(k >= maxcount) + break; + modes[k].width = thismode.dmPelsWidth; + modes[k].height = thismode.dmPelsHeight; + modes[k].bpp = thismode.dmBitsPerPel; + modes[k].refreshrate = thismode.dmDisplayFrequency; + modes[k].pixelheight_num = 1; + modes[k].pixelheight_denom = 1; // Win32 apparently does not provide this (FIXME) + ++k; } + return k; } -