diff options
author | 2016-04-04 22:01:00 -0400 | |
---|---|---|
committer | 2016-04-04 22:01:00 -0400 | |
commit | 3dd8afd6c0b80a998758095b79d9dd5bd1cde017 (patch) | |
tree | 2e0d341a4c44699080353bd9fd323170af2e04e4 /src/osd/modules/input/input_dinput.cpp | |
parent | d5b01cf514212573c6490132cabf736b8b7ae9a8 (diff) |
Hybrid DirectInput/XInput module
Diffstat (limited to 'src/osd/modules/input/input_dinput.cpp')
-rw-r--r-- | src/osd/modules/input/input_dinput.cpp | 572 |
1 files changed, 251 insertions, 321 deletions
diff --git a/src/osd/modules/input/input_dinput.cpp b/src/osd/modules/input/input_dinput.cpp index 1e4272e6317..ca3bad08026 100644 --- a/src/osd/modules/input/input_dinput.cpp +++ b/src/osd/modules/input/input_dinput.cpp @@ -14,6 +14,7 @@ // standard windows headers #define WIN32_LEAN_AND_MEAN #include <windows.h> +#include <initguid.h> #include <tchar.h> #include <wrl/client.h> @@ -31,17 +32,15 @@ #include "strconv.h" // MAMEOS headers -#include "winmain.h" #include "window.h" #include "winutil.h" #include "input_common.h" #include "input_windows.h" +#include "input_dinput.h" using namespace Microsoft::WRL; -#define STRUCTSIZE(x) (m_dinput_version == 0x0300) ? sizeof(x##_DX3) : sizeof(x) - static INT32 dinput_joystick_pov_get_state(void *device_internal, void *item_internal); //============================================================ @@ -58,255 +57,184 @@ static HRESULT dinput_set_dword_property(ComPtr<IDirectInputDevice> device, REFG dipdw.diph.dwHow = how; dipdw.dwData = value; - return IDirectInputDevice_SetProperty(device.Get(), property_guid, &dipdw.diph); + return device->SetProperty(property_guid, &dipdw.diph); } //============================================================ // dinput_device - base directinput device //============================================================ -// DirectInput-specific information about a device -struct dinput_api_state +dinput_device::dinput_device(running_machine &machine, const char *name, input_device_class deviceclass, input_module &module) + : device_info(machine, name, deviceclass, module), + dinput({nullptr}) { - ComPtr<IDirectInputDevice> device; - ComPtr<IDirectInputDevice2> device2; - DIDEVCAPS caps; - LPCDIDATAFORMAT format; -}; +} -class dinput_device : public device_info +dinput_device::~dinput_device() { -public: - dinput_api_state dinput; + if (dinput.device != nullptr) + dinput.device.Reset(); +} - dinput_device(running_machine &machine, const char *name, input_device_class deviceclass, input_module &module) - : device_info(machine, name, deviceclass, module), - dinput({nullptr}) - { - } +HRESULT dinput_device::poll_dinput(LPVOID pState) const +{ + HRESULT result; - virtual ~dinput_device() - { - if (dinput.device2 != nullptr) - dinput.device2.Reset(); + // first poll the device, then get the state + if (dinput.device2 != nullptr) + dinput.device2->Poll(); - if (dinput.device != nullptr) - dinput.device.Reset(); - } + // GetDeviceState returns the immediate state + result = dinput.device->GetDeviceState(dinput.format->dwDataSize, pState); -protected: - HRESULT poll_dinput(LPVOID pState) const + // handle lost inputs here + if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) { - HRESULT result; - - // first poll the device, then get the state - if (dinput.device2 != nullptr) - IDirectInputDevice2_Poll(dinput.device2.Get()); - - // GetDeviceState returns the immediate state - result = IDirectInputDevice_GetDeviceState(dinput.device.Get(), dinput.format->dwDataSize, pState); - - // handle lost inputs here - if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) - { - result = IDirectInputDevice_Acquire(dinput.device.Get()); - if (result == DI_OK) - result = IDirectInputDevice_GetDeviceState(dinput.device.Get(), dinput.format->dwDataSize, pState); - } - - return result; + result = dinput.device->Acquire(); + if (result == DI_OK) + result = dinput.device->GetDeviceState(dinput.format->dwDataSize, pState); } -}; + + return result; +} //============================================================ // dinput_keyboard_device - directinput keyboard device //============================================================ -class dinput_keyboard_device : public dinput_device +dinput_keyboard_device::dinput_keyboard_device(running_machine &machine, const char *name, input_module &module) + : dinput_device(machine, name, DEVICE_CLASS_KEYBOARD, module), + keyboard({{0}}) { -private: - std::mutex m_device_lock; - -public: - keyboard_state keyboard; - - dinput_keyboard_device(running_machine &machine, const char *name, input_module &module) - : dinput_device(machine, name, DEVICE_CLASS_KEYBOARD, module), - keyboard({{0}}) - { - } +} - // Polls the direct input immediate state - void poll() override - { - std::lock_guard<std::mutex> scope_lock(m_device_lock); +// Polls the direct input immediate state +void dinput_keyboard_device::poll() +{ + std::lock_guard<std::mutex> scope_lock(m_device_lock); - // Poll the state - dinput_device::poll_dinput(&keyboard.state); - } + // Poll the state + dinput_device::poll_dinput(&keyboard.state); +} - void reset() override - { - memset(&keyboard.state, 0, sizeof(keyboard.state)); - } -}; +void dinput_keyboard_device::reset() +{ + memset(&keyboard.state, 0, sizeof(keyboard.state)); +} //============================================================ -// dinput_module - base directinput module +// dinput_api_helper - DirectInput API helper //============================================================ -class dinput_module : public wininput_module +dinput_api_helper::dinput_api_helper(int version) + : m_dinput(nullptr), + m_dinput_version(version), + m_pfn_DirectInputCreate("DirectInputCreateW", L"dinput.dll") { -private: - ComPtr<IDirectInput> m_dinput; - int m_dinput_version; +} -public: - dinput_module(const char* type, const char* name) - : wininput_module(type, name), - m_dinput(nullptr), - m_dinput_version(0) - { - } +dinput_api_helper::~dinput_api_helper() +{ + m_dinput.Reset(); +} - int init_internal() override - { - HRESULT result; +int dinput_api_helper::initialize() +{ + HRESULT result; -#if DIRECTINPUT_VERSION >= 0x800 - m_dinput_version = DIRECTINPUT_VERSION; + if (m_dinput_version >= 0x0800) + { result = DirectInput8Create(GetModuleHandleUni(), m_dinput_version, IID_IDirectInput8, reinterpret_cast<void **>(m_dinput.GetAddressOf()), nullptr); if (result != DI_OK) { m_dinput_version = 0; return result; } -#else - // first attempt to initialize DirectInput at the current version - m_dinput_version = DIRECTINPUT_VERSION; - result = DirectInputCreate(GetModuleHandleUni(), m_dinput_version, m_dinput.GetAddressOf(), nullptr); + } + else + { + result = m_pfn_DirectInputCreate.initialize(); + if (result != DI_OK) + return result; + + // first attempt to initialize DirectInput at v7 + m_dinput_version = 0x0700; + result = m_pfn_DirectInputCreate(GetModuleHandleUni(), m_dinput_version, m_dinput.GetAddressOf(), nullptr); if (result != DI_OK) { // if that fails, try version 5 m_dinput_version = 0x0500; - result = DirectInputCreate(GetModuleHandleUni(), m_dinput_version, m_dinput.GetAddressOf(), nullptr); + result = m_pfn_DirectInputCreate(GetModuleHandleUni(), m_dinput_version, m_dinput.GetAddressOf(), nullptr); if (result != DI_OK) { - // if that fails, try version 3 - m_dinput_version = 0x0300; - result = DirectInputCreate(GetModuleHandleUni(), m_dinput_version, m_dinput.GetAddressOf(), nullptr); - if (result != DI_OK) - { - m_dinput_version = 0; - return result; - } + m_dinput_version = 0; + return result; } } -#endif - - osd_printf_verbose("DirectInput: Using DirectInput %d\n", m_dinput_version >> 8); - return 0; } - void exit() override - { - m_dinput.Reset(); - wininput_module::exit(); - } + osd_printf_verbose("DirectInput: Using DirectInput %d\n", m_dinput_version >> 8); + return 0; +} - virtual BOOL device_enum_callback(LPCDIDEVICEINSTANCE instance, LPVOID ref) = 0; - struct dinput_callback_context - { - dinput_module * self; - running_machine * machine; - }; +HRESULT dinput_api_helper::enum_attached_devices(int devclass, device_enum_interface *enumerate_interface, void *state) const +{ + device_enum_interface::dinput_callback_context ctx; + ctx.self = enumerate_interface; + ctx.state = state; - static BOOL CALLBACK enum_callback(LPCDIDEVICEINSTANCE instance, LPVOID ref) - { - auto context = static_cast<dinput_callback_context*>(ref); - return context->self->device_enum_callback(instance, context->machine); - } + return m_dinput->EnumDevices(devclass, device_enum_interface::enum_callback, &ctx, DIEDFL_ATTACHEDONLY); +} - void input_init(running_machine &machine) override - { - dinput_callback_context context = { this, &machine }; - HRESULT result = IDirectInput_EnumDevices(m_dinput.Get(), dinput_devclass(), enum_callback, &context, DIEDFL_ATTACHEDONLY); - if (result != DI_OK) - fatalerror("DirectInput: Unable to enumerate keyboards (result=%08X)\n", static_cast<UINT32>(result)); - } +//============================================================ +// dinput_module - base directinput module +//============================================================ +class dinput_module : public wininput_module, public device_enum_interface +{ protected: - virtual int dinput_devclass() = 0; + std::unique_ptr<dinput_api_helper> m_dinput_helper; - template <class TDevice> - TDevice* create_dinput_device( - running_machine &machine, - LPCDIDEVICEINSTANCE instance, - LPCDIDATAFORMAT format1, - LPCDIDATAFORMAT format2, - DWORD cooperative_level) +public: + dinput_module(const char* type, const char* name) + : wininput_module(type, name), + m_dinput_helper(nullptr) { - HRESULT result; - - // convert instance name to utf8 - auto osd_deleter = [](void *ptr) { osd_free(ptr); }; - auto utf8_instance_name = std::unique_ptr<char, decltype(osd_deleter)>(utf8_from_tstring(instance->tszInstanceName), osd_deleter); - - // allocate memory for the device object - TDevice* devinfo = devicelist()->create_device<TDevice>(machine, utf8_instance_name.get(), *this); - - // attempt to create a device - result = IDirectInput_CreateDevice(m_dinput.Get(), WRAP_REFIID(instance->guidInstance), devinfo->dinput.device.GetAddressOf(), NULL); - if (result != DI_OK) - goto error; + } - // try to get a version 2 device for it - result = IDirectInputDevice_QueryInterface(devinfo->dinput.device.Get(), WRAP_REFIID(IID_IDirectInputDevice2), reinterpret_cast<void **>(devinfo->dinput.device2.GetAddressOf())); - if (result != DI_OK) - devinfo->dinput.device2 = nullptr; + int init_internal() override + { + m_dinput_helper = std::make_unique<dinput_api_helper>(DIRECTINPUT_VERSION); + int result = m_dinput_helper->initialize(); + if (result != 0) + return result; - // get the caps - devinfo->dinput.caps.dwSize = STRUCTSIZE(DIDEVCAPS); - result = IDirectInputDevice_GetCapabilities(devinfo->dinput.device.Get(), &devinfo->dinput.caps); - if (result != DI_OK) - goto error; + return 0; + } - // attempt to set the data format - devinfo->dinput.format = format1; - result = IDirectInputDevice_SetDataFormat(devinfo->dinput.device.Get(), devinfo->dinput.format); - if (result != DI_OK) - { - // use the secondary format if available - if (format2 != nullptr) - { - devinfo->dinput.format = format2; - result = IDirectInputDevice_SetDataFormat(devinfo->dinput.device.Get(), devinfo->dinput.format); - } - if (result != DI_OK) - goto error; - } + void exit() override + { + wininput_module::exit(); + m_dinput_helper.reset(); + } - // set the cooperative level - result = IDirectInputDevice_SetCooperativeLevel(devinfo->dinput.device.Get(), win_window_list->m_hwnd, cooperative_level); + void input_init(running_machine &machine) override + { + HRESULT result = m_dinput_helper->enum_attached_devices(dinput_devclass(), this, &machine); if (result != DI_OK) - goto error; - return devinfo; - - error: - devicelist()->free_device(devinfo); - return nullptr; + fatalerror("DirectInput: Unable to enumerate keyboards (result=%08X)\n", static_cast<UINT32>(result)); } - std::string device_item_name(dinput_device * devinfo, int offset, const char * defstring, const TCHAR * suffix) const + static std::string device_item_name(dinput_device * devinfo, int offset, const char * defstring, const TCHAR * suffix) { DIDEVICEOBJECTINSTANCE instance = { 0 }; HRESULT result; // query the key name - instance.dwSize = STRUCTSIZE(DIDEVICEOBJECTINSTANCE); - result = IDirectInputDevice_GetObjectInfo(devinfo->dinput.device.Get(), &instance, offset, DIPH_BYOFFSET); + instance.dwSize = sizeof(instance); + result = devinfo->dinput.device->GetObjectInfo(&instance, offset, DIPH_BYOFFSET); // if we got an error and have no default string, just return NULL if (result != DI_OK) @@ -342,6 +270,9 @@ protected: return std::string(combined.get()); } + +protected: + virtual int dinput_devclass() = 0; }; class keyboard_input_dinput : public dinput_module @@ -368,7 +299,7 @@ public: int keynum; // allocate and link in a new device - devinfo = create_dinput_device<dinput_keyboard_device>(machine, instance, &c_dfDIKeyboard, nullptr, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE); + devinfo = m_dinput_helper->create_device<dinput_keyboard_device>(machine, *this, instance, &c_dfDIKeyboard, nullptr, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE); if (devinfo == nullptr) goto exit; @@ -392,33 +323,28 @@ public: } }; -class dinput_mouse_device : public dinput_device -{ -public: - mouse_state mouse; - dinput_mouse_device(running_machine &machine, const char *name, input_module &module) - : dinput_device(machine, name, DEVICE_CLASS_MOUSE, module), - mouse({0}) - { - } +dinput_mouse_device::dinput_mouse_device(running_machine &machine, const char *name, input_module &module) + : dinput_device(machine, name, DEVICE_CLASS_MOUSE, module), + mouse({0}) +{ +} - void poll() override - { - // poll - dinput_device::poll_dinput(&mouse); +void dinput_mouse_device::poll() +{ + // poll + dinput_device::poll_dinput(&mouse); - // scale the axis data - mouse.lX *= INPUT_RELATIVE_PER_PIXEL; - mouse.lY *= INPUT_RELATIVE_PER_PIXEL; - mouse.lZ *= INPUT_RELATIVE_PER_PIXEL; - } + // scale the axis data + mouse.lX *= INPUT_RELATIVE_PER_PIXEL; + mouse.lY *= INPUT_RELATIVE_PER_PIXEL; + mouse.lZ *= INPUT_RELATIVE_PER_PIXEL; +} - void reset() override - { - memset(&mouse, 0, sizeof(mouse)); - } -}; +void dinput_mouse_device::reset() +{ + memset(&mouse, 0, sizeof(mouse)); +} class mouse_input_dinput : public dinput_module { @@ -445,7 +371,7 @@ public: HRESULT result; // allocate and link in a new device - devinfo = create_dinput_device<dinput_mouse_device>(machine, instance, &c_dfDIMouse2, &c_dfDIMouse, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE); + devinfo = m_dinput_helper->create_device<dinput_mouse_device>(machine, *this, instance, &c_dfDIMouse2, &c_dfDIMouse, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE); if (devinfo == nullptr) goto exit; @@ -489,46 +415,130 @@ public: } }; -// state information for a joystick; DirectInput state must be first element -struct dinput_joystick_state +dinput_joystick_device::dinput_joystick_device(running_machine &machine, const char *name, input_module &module) + : dinput_device(machine, name, DEVICE_CLASS_JOYSTICK, module), + joystick({{0}}) { - DIJOYSTATE state; - LONG rangemin[8]; - LONG rangemax[8]; -}; +} -class dinput_joystick_device : public dinput_device +void dinput_joystick_device::reset() { -public: - dinput_joystick_state joystick; + memset(&joystick.state, 0, sizeof(joystick.state)); +} + +void dinput_joystick_device::poll() +{ + int axisnum; + + // poll the device first + if (dinput_device::poll_dinput(&joystick.state) != ERROR_SUCCESS) + return; + + // normalize axis values + for (axisnum = 0; axisnum < 8; axisnum++) + { + LONG *axis = (&joystick.state.lX) + axisnum; + *axis = normalize_absolute_axis(*axis, joystick.rangemin[axisnum], joystick.rangemax[axisnum]); + } +} + +int dinput_joystick_device::configure() +{ + HRESULT result; + UINT32 axisnum, axiscount; + + auto devicelist = static_cast<input_module_base&>(module()).devicelist(); + + // temporary approximation of index + int devindex = devicelist->size(); + + // set absolute mode + result = dinput_set_dword_property(dinput.device, DIPROP_AXISMODE, 0, DIPH_DEVICE, DIPROPAXISMODE_ABS); + if (result != DI_OK && result != DI_PROPNOEFFECT) + osd_printf_warning("DirectInput: Unable to set absolute mode for joystick %d (%s)\n", devindex, name()); + + // turn off deadzone; we do our own calculations + result = dinput_set_dword_property(dinput.device, DIPROP_DEADZONE, 0, DIPH_DEVICE, 0); + if (result != DI_OK && result != DI_PROPNOEFFECT) + osd_printf_warning("DirectInput: Unable to reset deadzone for joystick %d (%s)\n", devindex, name()); - dinput_joystick_device(running_machine &machine, const char *name, input_module &module) - : dinput_device(machine, name, DEVICE_CLASS_JOYSTICK, module), - joystick({{0}}) + // turn off saturation; we do our own calculations + result = dinput_set_dword_property(dinput.device, DIPROP_SATURATION, 0, DIPH_DEVICE, 10000); + if (result != DI_OK && result != DI_PROPNOEFFECT) + osd_printf_warning("DirectInput: Unable to reset saturation for joystick %d (%s)\n", devindex, name()); + + // cap the number of axes, POVs, and buttons based on the format + dinput.caps.dwAxes = MIN(dinput.caps.dwAxes, 8); + dinput.caps.dwPOVs = MIN(dinput.caps.dwPOVs, 4); + dinput.caps.dwButtons = MIN(dinput.caps.dwButtons, 128); + + // populate the axes + for (axisnum = axiscount = 0; axiscount < dinput.caps.dwAxes && axisnum < 8; axisnum++) { + DIPROPRANGE dipr; + std::string name; + + // fetch the range of this axis + dipr.diph.dwSize = sizeof(dipr); + dipr.diph.dwHeaderSize = sizeof(dipr.diph); + dipr.diph.dwObj = offsetof(DIJOYSTATE2, lX) + axisnum * sizeof(LONG); + dipr.diph.dwHow = DIPH_BYOFFSET; + result = dinput.device->GetProperty(DIPROP_RANGE, &dipr.diph); + if (result != DI_OK) + continue; + + joystick.rangemin[axisnum] = dipr.lMin; + joystick.rangemax[axisnum] = dipr.lMax; + + // populate the item description as well + name = dinput_module::device_item_name(this, offsetof(DIJOYSTATE2, lX) + axisnum * sizeof(LONG), default_axis_name[axisnum], nullptr); + device()->add_item(name.c_str(), static_cast<input_item_id>(ITEM_ID_XAXIS + axisnum), generic_axis_get_state, &joystick.state.lX + axisnum); + + axiscount++; } - void reset() override + // populate the POVs + for (UINT32 povnum = 0; povnum < dinput.caps.dwPOVs; povnum++) { - memset(&joystick.state, 0, sizeof(joystick.state)); + std::string name; + + // left + name = dinput_module::device_item_name(this, offsetof(DIJOYSTATE2, rgdwPOV) + povnum * sizeof(DWORD), default_pov_name(povnum), TEXT("L")); + device()->add_item(name.c_str(), ITEM_ID_OTHER_SWITCH, dinput_joystick_pov_get_state, reinterpret_cast<void *>(static_cast<FPTR>(povnum * 4 + POVDIR_LEFT))); + + // right + name = dinput_module::device_item_name(this, offsetof(DIJOYSTATE2, rgdwPOV) + povnum * sizeof(DWORD), default_pov_name(povnum), TEXT("R")); + device()->add_item(name.c_str(), ITEM_ID_OTHER_SWITCH, dinput_joystick_pov_get_state, reinterpret_cast<void *>(static_cast<FPTR>(povnum * 4 + POVDIR_RIGHT))); + + // up + name = dinput_module::device_item_name(this, offsetof(DIJOYSTATE2, rgdwPOV) + povnum * sizeof(DWORD), default_pov_name(povnum), TEXT("U")); + device()->add_item(name.c_str(), ITEM_ID_OTHER_SWITCH, dinput_joystick_pov_get_state, reinterpret_cast<void *>(static_cast<FPTR>(povnum * 4 + POVDIR_UP))); + + // down + name = dinput_module::device_item_name(this, offsetof(DIJOYSTATE2, rgdwPOV) + povnum * sizeof(DWORD), default_pov_name(povnum), TEXT("D")); + device()->add_item(name.c_str(), ITEM_ID_OTHER_SWITCH, dinput_joystick_pov_get_state, reinterpret_cast<void *>(static_cast<FPTR>(povnum * 4 + POVDIR_DOWN))); } - void poll() override + // populate the buttons + for (UINT32 butnum = 0; butnum < dinput.caps.dwButtons; butnum++) { - int axisnum; + FPTR offset = reinterpret_cast<FPTR>(&static_cast<DIJOYSTATE2 *>(nullptr)->rgbButtons[butnum]); + std::string name = dinput_module::device_item_name(this, offset, default_button_name(butnum), nullptr); - // poll the device first - if (dinput_device::poll_dinput(&joystick.state) != ERROR_SUCCESS) - return; + input_item_id itemid; - // normalize axis values - for (axisnum = 0; axisnum < 8; axisnum++) - { - LONG *axis = (&joystick.state.lX) + axisnum; - *axis = normalize_absolute_axis(*axis, joystick.rangemin[axisnum], joystick.rangemax[axisnum]); - } + if (butnum < INPUT_MAX_BUTTONS) + itemid = static_cast<input_item_id>(ITEM_ID_BUTTON1 + butnum); + else if (butnum < INPUT_MAX_BUTTONS + INPUT_MAX_ADD_SWITCH) + itemid = static_cast<input_item_id>(ITEM_ID_ADD_SWITCH1 - INPUT_MAX_BUTTONS + butnum); + else + itemid = ITEM_ID_OTHER_SWITCH; + + device()->add_item(name.c_str(), itemid, generic_button_get_state, &joystick.state.rgbButtons[butnum]); } -}; + + return 0; +} class joystick_input_dinput : public dinput_module { @@ -550,102 +560,22 @@ public: BOOL device_enum_callback(LPCDIDEVICEINSTANCE instance, LPVOID ref) override { DWORD cooperative_level = DISCL_FOREGROUND | DISCL_NONEXCLUSIVE; - int axisnum, axiscount, povnum, butnum; running_machine &machine = *static_cast<running_machine *>(ref); dinput_joystick_device *devinfo; - HRESULT result; + int result = 0; - if (win_window_list != nullptr && win_window_list->win_has_menu()) { + if (win_window_list != nullptr && win_window_list->win_has_menu()) cooperative_level = DISCL_BACKGROUND | DISCL_NONEXCLUSIVE; - } + // allocate and link in a new device - devinfo = create_dinput_device<dinput_joystick_device>(machine, instance, &c_dfDIJoystick, nullptr, cooperative_level); + devinfo = m_dinput_helper->create_device<dinput_joystick_device>(machine, *this, instance, &c_dfDIJoystick, nullptr, cooperative_level); if (devinfo == nullptr) goto exit; - // set absolute mode - result = dinput_set_dword_property(devinfo->dinput.device, DIPROP_AXISMODE, 0, DIPH_DEVICE, DIPROPAXISMODE_ABS); - if (result != DI_OK && result != DI_PROPNOEFFECT) - osd_printf_warning("DirectInput: Unable to set absolute mode for joystick %d (%s)\n", devicelist()->size(), devinfo->name()); - - // turn off deadzone; we do our own calculations - result = dinput_set_dword_property(devinfo->dinput.device, DIPROP_DEADZONE, 0, DIPH_DEVICE, 0); - if (result != DI_OK && result != DI_PROPNOEFFECT) - osd_printf_warning("DirectInput: Unable to reset deadzone for joystick %d (%s)\n", devicelist()->size(), devinfo->name()); - - // turn off saturation; we do our own calculations - result = dinput_set_dword_property(devinfo->dinput.device, DIPROP_SATURATION, 0, DIPH_DEVICE, 10000); - if (result != DI_OK && result != DI_PROPNOEFFECT) - osd_printf_warning("DirectInput: Unable to reset saturation for joystick %d (%s)\n", devicelist()->size(), devinfo->name()); - - // cap the number of axes, POVs, and buttons based on the format - devinfo->dinput.caps.dwAxes = MIN(devinfo->dinput.caps.dwAxes, 8); - devinfo->dinput.caps.dwPOVs = MIN(devinfo->dinput.caps.dwPOVs, 4); - devinfo->dinput.caps.dwButtons = MIN(devinfo->dinput.caps.dwButtons, 128); - - // populate the axes - for (axisnum = axiscount = 0; axiscount < devinfo->dinput.caps.dwAxes && axisnum < 8; axisnum++) + result = devinfo->configure(); + if (result != 0) { - DIPROPRANGE dipr; - std::string name; - - // fetch the range of this axis - dipr.diph.dwSize = sizeof(dipr); - dipr.diph.dwHeaderSize = sizeof(dipr.diph); - dipr.diph.dwObj = offsetof(DIJOYSTATE2, lX) + axisnum * sizeof(LONG); - dipr.diph.dwHow = DIPH_BYOFFSET; - result = IDirectInputDevice_GetProperty(devinfo->dinput.device.Get(), DIPROP_RANGE, &dipr.diph); - if (result != DI_OK) - continue; - - devinfo->joystick.rangemin[axisnum] = dipr.lMin; - devinfo->joystick.rangemax[axisnum] = dipr.lMax; - - // populate the item description as well - name = device_item_name(devinfo, offsetof(DIJOYSTATE2, lX) + axisnum * sizeof(LONG), default_axis_name[axisnum], nullptr); - devinfo->device()->add_item(name.c_str(), static_cast<input_item_id>(ITEM_ID_XAXIS + axisnum), generic_axis_get_state, &devinfo->joystick.state.lX + axisnum); - - axiscount++; - } - - // populate the POVs - for (povnum = 0; povnum < devinfo->dinput.caps.dwPOVs; povnum++) - { - std::string name; - - // left - name = device_item_name(devinfo, offsetof(DIJOYSTATE2, rgdwPOV) + povnum * sizeof(DWORD), default_pov_name(povnum), TEXT("L")); - devinfo->device()->add_item(name.c_str(), ITEM_ID_OTHER_SWITCH, dinput_joystick_pov_get_state, reinterpret_cast<void *>(static_cast<FPTR>(povnum * 4 + POVDIR_LEFT))); - - // right - name = device_item_name(devinfo, offsetof(DIJOYSTATE2, rgdwPOV) + povnum * sizeof(DWORD), default_pov_name(povnum), TEXT("R")); - devinfo->device()->add_item(name.c_str(), ITEM_ID_OTHER_SWITCH, dinput_joystick_pov_get_state, reinterpret_cast<void *>(static_cast<FPTR>(povnum * 4 + POVDIR_RIGHT))); - - // up - name = device_item_name(devinfo, offsetof(DIJOYSTATE2, rgdwPOV) + povnum * sizeof(DWORD), default_pov_name(povnum), TEXT("U")); - devinfo->device()->add_item(name.c_str(), ITEM_ID_OTHER_SWITCH, dinput_joystick_pov_get_state, reinterpret_cast<void *>(static_cast<FPTR>(povnum * 4 + POVDIR_UP))); - - // down - name = device_item_name(devinfo, offsetof(DIJOYSTATE2, rgdwPOV) + povnum * sizeof(DWORD), default_pov_name(povnum), TEXT("D")); - devinfo->device()->add_item(name.c_str(), ITEM_ID_OTHER_SWITCH, dinput_joystick_pov_get_state, reinterpret_cast<void *>(static_cast<FPTR>(povnum * 4 + POVDIR_DOWN))); - } - - // populate the buttons - for (butnum = 0; butnum < devinfo->dinput.caps.dwButtons; butnum++) - { - FPTR offset = reinterpret_cast<FPTR>(&static_cast<DIJOYSTATE2 *>(nullptr)->rgbButtons[butnum]); - std::string name = device_item_name(devinfo, offset, default_button_name(butnum), nullptr); - - input_item_id itemid; - - if (butnum < INPUT_MAX_BUTTONS) - itemid = static_cast<input_item_id>(ITEM_ID_BUTTON1 + butnum); - else if (butnum < INPUT_MAX_BUTTONS + INPUT_MAX_ADD_SWITCH) - itemid = static_cast<input_item_id>(ITEM_ID_ADD_SWITCH1 - INPUT_MAX_BUTTONS + butnum); - else - itemid = ITEM_ID_OTHER_SWITCH; - - devinfo->device()->add_item(name.c_str(), itemid, generic_button_get_state, &devinfo->joystick.state.rgbButtons[butnum]); + osd_printf_error("Failed to configure DI Joystick device. Error 0x%x\n", static_cast<unsigned int>(result)); } exit: |