diff --git a/docs/rh-log.txt b/docs/rh-log.txt index a202e6e9c..adba114d0 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,12 @@ -June 27, 2009 (Changes by Graf Zahl) +June 27, 2009 +- Fixed some improper preprocessor lines in autostart/autozend.cpp. +- Added XInput support. For the benefit of people compiling with MinGW, + the CMakeLists.txt checks for xinput.h and disables it if it cannot + be found. (And much to my surprise, I accidentally discovered that if you + have the DirectX SDK installed, those headers actually do work with GCC, + though they add a few extra warnings.) + +June 27, 2009 (Changes by Graf Zahl) - Added Gez's submissions for A_M_Saw customization, area damage and pitch for A_FireCustomMissile. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c2c71a565..3ffb66eed 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -73,6 +73,16 @@ if( WIN32 ) else( NOT D3D_INCLUDE_DIR ) include_directories( ${D3D_INCLUDE_DIR} ) endif( NOT D3D_INCLUDE_DIR ) + + find_path( XINPUT_INCLUDE_DIR xinput.h + PATHS ENV DXSDK_DIR + PATH_SUFFIXES Include ) + if( NOT XINPUT_INCLUDE_DIR ) + message( SEND_ERROR "Could not find xinput.h. XInput will be disabled." ) + add_definitions( -DNO_XINPUT ) + else( NOT XINPUT_INCLUDE_DIR ) + include_directories( ${XINPUT_INCLUDE_DIR} ) + endif( NOT XINPUT_INCLUDE_DIR ) find_library( DX_ddraw_LIBRARY ddraw PATHS ENV DXSDK_DIR @@ -402,6 +412,7 @@ if( WIN32 ) win32/i_keyboard.cpp win32/i_mouse.cpp win32/i_dijoy.cpp + win32/i_xinput.cpp win32/i_main.cpp win32/i_movie.cpp win32/i_system.cpp diff --git a/src/autostart.cpp b/src/autostart.cpp index 5bdfa3c6e..e8e940c5d 100644 --- a/src/autostart.cpp +++ b/src/autostart.cpp @@ -92,7 +92,7 @@ void *GRegHead __attribute__((section(GREG_SECTION))) = 0; void *MRegHead __attribute__((section(MREG_SECTION))) = 0; void *YRegHead __attribute__((section(YREG_SECTION))) = 0; -#elif +#else #error Please fix autostart.cpp for your compiler diff --git a/src/autozend.cpp b/src/autozend.cpp index 84903eee6..58564bca8 100644 --- a/src/autozend.cpp +++ b/src/autozend.cpp @@ -64,7 +64,7 @@ void *GRegTail __attribute__((section(GREG_SECTION))) = 0; void *MRegTail __attribute__((section(MREG_SECTION))) = 0; void *YRegTail __attribute__((section(YREG_SECTION))) = 0; -#elif +#else #error Please fix autozend.cpp for your compiler diff --git a/src/c_bind.cpp b/src/c_bind.cpp index f1dcdb6b1..ff69f2f86 100644 --- a/src/c_bind.cpp +++ b/src/c_bind.cpp @@ -251,6 +251,14 @@ const char *KeyNames[NUM_KEYS] = "axis3plus","axis3minus","axis4plus","axis4minus", "axis5plus","axis5minus","axis6plus","axis6minus", "axis7plus","axis7minus","axis8plus","axis8minus", + + "lstickright","lstickleft","lstickdown","lstickup", // Gamepad axis-based buttons + "rstickright","rstickleft","rstickdown","rstickup", + + "dpadup","dpaddown","dpadleft","dpadright", // Gamepad buttons + "pad_start","pad_back","lthumb","rthumb", + "lshoulder","rshoulder","ltrigger","rtrigger", + "pad_a", "pad_b", "pad_x", "pad_y" }; static FString Bindings[NUM_KEYS]; diff --git a/src/doomdef.h b/src/doomdef.h index 6c5d7ce1d..bd5978ade 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -188,7 +188,34 @@ enum ESkillLevels #define KEY_JOYAXIS8MINUS 0x1AB #define NUM_JOYAXISBUTTONS 8 -#define NUM_KEYS 0x1AC +#define KEY_PAD_LTHUMB_RIGHT 0x1AC +#define KEY_PAD_LTHUMB_LEFT 0x1AD +#define KEY_PAD_LTHUMB_DOWN 0x1AE +#define KEY_PAD_LTHUMB_UP 0x1AF + +#define KEY_PAD_RTHUMB_RIGHT 0x1B0 +#define KEY_PAD_RTHUMB_LEFT 0x1B1 +#define KEY_PAD_RTHUMB_DOWN 0x1B2 +#define KEY_PAD_RTHUMB_UP 0x1B3 + +#define KEY_PAD_DPAD_UP 0x1B4 +#define KEY_PAD_DPAD_DOWN 0x1B5 +#define KEY_PAD_DPAD_LEFT 0x1B6 +#define KEY_PAD_DPAD_RIGHT 0x1B7 +#define KEY_PAD_START 0x1B8 +#define KEY_PAD_BACK 0x1B9 +#define KEY_PAD_LTHUMB 0x1BA +#define KEY_PAD_RTHUMB 0x1BB +#define KEY_PAD_LSHOULDER 0x1BC +#define KEY_PAD_RSHOULDER 0x1BD +#define KEY_PAD_LTRIGGER 0x1BE +#define KEY_PAD_RTRIGGER 0x1BF +#define KEY_PAD_A 0x1C0 +#define KEY_PAD_B 0x1C1 +#define KEY_PAD_X 0x1C2 +#define KEY_PAD_Y 0x1C3 + +#define NUM_KEYS 0x1C4 enum EJoyAxis { diff --git a/src/m_options.cpp b/src/m_options.cpp index 622bb1c12..63f8edf3e 100644 --- a/src/m_options.cpp +++ b/src/m_options.cpp @@ -1700,6 +1700,7 @@ void M_OptDrawer () if (item->type != screenres) { + FString somestring; const char *label; if (item->type != discrete_joy) { @@ -1713,7 +1714,8 @@ void M_OptDrawer () } else { - label = (*item->e.joyvalues)[item->a.joyselection]->GetName(); + somestring = (*item->e.joyvalues)[item->a.joyselection]->GetName(); + label = somestring; } } width = SmallFont->StringWidth(label); diff --git a/src/win32/i_dijoy.cpp b/src/win32/i_dijoy.cpp index d43b41c55..0de745fbf 100644 --- a/src/win32/i_dijoy.cpp +++ b/src/win32/i_dijoy.cpp @@ -136,7 +136,7 @@ public: FString GetIdentifier(); void SetDefaultConfig(); - // IJoystick interface + // IJoystickConfig interface FString GetName(); float GetSensitivity(); virtual void SetSensitivity(float scale); @@ -192,7 +192,6 @@ protected: bool ReorderAxisPair(const GUID &x, const GUID &y, int pos); HRESULT SetDataFormat(); bool SetConfigSection(bool create); - void GenerateButtonEvents(int oldbuttons, int newbuttons, int numbuttons, int base); friend class FDInputJoystickManager; }; @@ -380,33 +379,17 @@ void FDInputJoystick::ProcessInput() { AxisInfo *info = &Axes[i]; LONG value = *(LONG *)(state + info->Ofs); - double deadzone = info->DeadZone; double axisval; BYTE buttonstate; // Scale to [-1.0, 1.0] axisval = (value - info->Min) * 2.0 / (info->Max - info->Min) - 1.0; // Cancel out dead zone - if (fabs(axisval) < deadzone) - { - axisval = 0; - buttonstate = 0; - } - // Make the dead zone the new 0 - else if (axisval < 0) - { - axisval = (axisval + deadzone) / (1.0 - deadzone); - buttonstate = 2; // button minus - } - else - { - axisval = (axisval - deadzone) / (1.0 - deadzone); - buttonstate = 1; // button plus - } + axisval = Joy_RemoveDeadZone(axisval, info->DeadZone, &buttonstate); info->Value = float(axisval); if (i < NUM_JOYAXISBUTTONS) { - GenerateButtonEvents(info->ButtonValue, buttonstate, 2, KEY_JOYAXIS1PLUS + i*2); + Joy_GenerateButtonEvents(info->ButtonValue, buttonstate, 2, KEY_JOYAXIS1PLUS + i*2); } info->ButtonValue = buttonstate; } @@ -441,36 +424,11 @@ void FDInputJoystick::ProcessInput() pov = POVButtons[pov]; // Send events for POV "buttons" that have changed. - GenerateButtonEvents(info->Value, pov, 4, KEY_JOYPOV1_UP + i*4); + Joy_GenerateButtonEvents(info->Value, pov, 4, KEY_JOYPOV1_UP + i*4); info->Value = pov; } } -//=========================================================================== -// -// FDInputJoystick :: GenerateButtonEvents -// -//=========================================================================== - -void FDInputJoystick::GenerateButtonEvents(int oldbuttons, int newbuttons, int numbuttons, int base) -{ - int changed = oldbuttons ^ newbuttons; - if (changed != 0) - { - event_t ev = { 0 }; - int mask = 1; - for (int j = 0; j < 4; mask <<= 1, ++j) - { - if (changed & mask) - { - ev.data1 = base + j; - ev.type = (newbuttons & mask) ? EV_KeyDown : EV_KeyUp; - D_PostEvent(&ev); - } - } - } -} - //=========================================================================== // // FDInputJoystick :: AddAxes @@ -838,11 +796,12 @@ void FDInputJoystick::SetDefaultConfig() { Axes[i].DeadZone = DEFAULT_DEADZONE; Axes[i].Multiplier = 1; + Axes[i].GameAxis = JOYAXIS_None; } // Triggers on a 360 controller have a much smaller deadzone. if (Axes.Size() == 5 && Axes[4].Guid == GUID_ZAxis) { - Axes[4].DeadZone = 30 / 32768.f; + Axes[4].DeadZone = 30 / 256.f; } // Two axes? Horizontal is yaw and vertical is forward. if (Axes.Size() == 2) @@ -1094,7 +1053,7 @@ void FDInputJoystickManager :: AddAxes(float axes[NUM_JOYAXIS]) //=========================================================================== // -// FDInputJoystickManager :: GetJoysticks +// FDInputJoystickManager :: GetDevices // // Adds the IJoystick interfaces for each device we created to the sticks // array. @@ -1150,12 +1109,16 @@ bool FDInputJoystickManager::WndProcHook(HWND hWnd, UINT message, WPARAM wParam, BOOL CALLBACK FDInputJoystickManager::EnumCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef) { - TArray *all = (TArray *)pvRef; - Enumerator thisone; + // Do not add XInput devices if XInput was initialized. + if (JoyDevices[INPUT_XInput] == NULL || !IsXInputDevice(&lpddi->guidProduct)) + { + TArray *all = (TArray *)pvRef; + Enumerator thisone; - thisone.Instance = lpddi->guidInstance; - thisone.Name = lpddi->tszInstanceName; - all->Push(thisone); + thisone.Instance = lpddi->guidInstance; + thisone.Name = lpddi->tszInstanceName; + all->Push(thisone); + } return DIENUM_CONTINUE; } @@ -1383,11 +1346,11 @@ FDInputJoystick *FDInputJoystickManager::EnumDevices() //=========================================================================== // -// I_StartupJoystick +// I_StartupDirectInputJoystick // //=========================================================================== -void I_StartupJoystick() +void I_StartupDirectInputJoystick() { FJoystickCollection *joys = new FDInputJoystickManager; if (joys->GetDevice()) @@ -1395,3 +1358,60 @@ void I_StartupJoystick() JoyDevices[INPUT_DIJoy] = joys; } } + +//=========================================================================== +// +// Joy_RemoveDeadZone +// +//=========================================================================== + +double Joy_RemoveDeadZone(double axisval, double deadzone, BYTE *buttons) +{ + // Cancel out deadzone. + if (fabs(axisval) < deadzone) + { + axisval = 0; + *buttons = 0; + } + // Make the dead zone the new 0. + else if (axisval < 0) + { + axisval = (axisval + deadzone) / (1.0 - deadzone); + *buttons = 2; // button minus + } + else + { + axisval = (axisval - deadzone) / (1.0 - deadzone); + *buttons = 1; // button plus + } + return axisval; +} + +//=========================================================================== +// +// Joy_GenerateButtonEvents +// +// Provided two bitmasks for a set of buttons, generates events to reflect +// any changes from the old to new set, where base is the key for bit 0, +// base+1 is the key for bit 1, etc. +// +//=========================================================================== + +void Joy_GenerateButtonEvents(int oldbuttons, int newbuttons, int numbuttons, int base) +{ + int changed = oldbuttons ^ newbuttons; + if (changed != 0) + { + event_t ev = { 0 }; + int mask = 1; + for (int j = 0; j < numbuttons; mask <<= 1, ++j) + { + if (changed & mask) + { + ev.data1 = base + j; + ev.type = (newbuttons & mask) ? EV_KeyDown : EV_KeyUp; + D_PostEvent(&ev); + } + } + } +} diff --git a/src/win32/i_input.cpp b/src/win32/i_input.cpp index 628aa64d3..fa47c484f 100644 --- a/src/win32/i_input.cpp +++ b/src/win32/i_input.cpp @@ -619,12 +619,15 @@ bool I_InitInput (void *hwnd) Printf ("I_StartupMouse\n"); I_StartupMouse(); - Printf ("I_StartupJoystick\n"); - I_StartupJoystick(); - Printf ("I_StartupKeyboard\n"); I_StartupKeyboard(); + Printf ("I_StartupXInput\n"); + I_StartupXInput(); + + Printf ("I_StartupDirectInputJoystick\n"); + I_StartupDirectInputJoystick(); + return TRUE; } diff --git a/src/win32/i_input.h b/src/win32/i_input.h index 1188846a6..cfbddc1ee 100644 --- a/src/win32/i_input.h +++ b/src/win32/i_input.h @@ -147,7 +147,11 @@ extern FJoystickCollection *JoyDevices[NUM_JOYDEVICES]; void I_StartupMouse(); void I_CheckNativeMouse(bool prefer_native); void I_StartupKeyboard(); -void I_StartupJoystick(); +void I_StartupXInput(); +void I_StartupDirectInputJoystick(); + +void Joy_GenerateButtonEvents(int oldbuttons, int newbuttons, int numbuttons, int base); +double Joy_RemoveDeadZone(double axisval, double deadzone, BYTE *buttons); // USB HID usage page numbers #define HID_GENERIC_DESKTOP_PAGE 0x01 diff --git a/zdoom.vcproj b/zdoom.vcproj index b979a9bfa..6cd5ef76e 100644 --- a/zdoom.vcproj +++ b/zdoom.vcproj @@ -2004,6 +2004,10 @@ RelativePath=".\src\win32\I_system.h" > + +