diff options
Diffstat (limited to 'src/osd/modules/input/input_dinput.cpp')
-rw-r--r-- | src/osd/modules/input/input_dinput.cpp | 473 |
1 files changed, 215 insertions, 258 deletions
diff --git a/src/osd/modules/input/input_dinput.cpp b/src/osd/modules/input/input_dinput.cpp index fcee640981c..57a84fab225 100644 --- a/src/osd/modules/input/input_dinput.cpp +++ b/src/osd/modules/input/input_dinput.cpp @@ -38,165 +38,54 @@ using namespace Microsoft::WRL; -static int32_t dinput_joystick_pov_get_state(void *device_internal, void *item_internal); +namespace { //============================================================ -// dinput_set_dword_property -//============================================================ - -#if DIRECTINPUT_VERSION >= 0x0800 -static HRESULT dinput_set_dword_property(ComPtr<IDirectInputDevice8> device, REFGUID property_guid, DWORD object, DWORD how, DWORD value) -#else -static HRESULT dinput_set_dword_property(ComPtr<IDirectInputDevice> device, REFGUID property_guid, DWORD object, DWORD how, DWORD value) -#endif -{ - DIPROPDWORD dipdw; - - dipdw.diph.dwSize = sizeof(dipdw); - dipdw.diph.dwHeaderSize = sizeof(dipdw.diph); - dipdw.diph.dwObj = object; - dipdw.diph.dwHow = how; - dipdw.dwData = value; - - return device->SetProperty(property_guid, &dipdw.diph); -} - -//============================================================ -// dinput_device - base directinput device +// dinput_joystick_pov_get_state //============================================================ -dinput_device::dinput_device(running_machine &machine, const char *name, const char *id, input_device_class deviceclass, input_module &module) - : device_info(machine, name, id, deviceclass, module), - dinput({nullptr}) -{ -} - -dinput_device::~dinput_device() +int32_t dinput_joystick_pov_get_state(void *device_internal, void *item_internal) { - if (dinput.device != nullptr) - dinput.device.Reset(); -} - -HRESULT dinput_device::poll_dinput(LPVOID pState) const -{ - HRESULT result; + auto *devinfo = static_cast<dinput_joystick_device *>(device_internal); + int povnum = reinterpret_cast<uintptr_t>(item_internal) / 4; + int povdir = reinterpret_cast<uintptr_t>(item_internal) % 4; + int32_t result = 0; - // first poll the device, then get the state -#if DIRECTINPUT_VERSION >= 0x0800 - dinput.device->Poll(); -#else - if (dinput.device2 != nullptr) - dinput.device2->Poll(); -#endif + // get the current state + devinfo->module().poll_if_necessary(devinfo->machine()); + const DWORD pov = devinfo->joystick.state.rgdwPOV[povnum]; - // GetDeviceState returns the immediate state - result = dinput.device->GetDeviceState(dinput.format->dwDataSize, pState); + // if invalid, return 0 + if ((pov & 0xffff) == 0xffff) + return result; - // handle lost inputs here - if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) + // return the current state + switch (povdir) { - result = dinput.device->Acquire(); - if (result == DI_OK) - result = dinput.device->GetDeviceState(dinput.format->dwDataSize, pState); + case POVDIR_LEFT: result = (pov >= 22500 && pov <= 31500); break; + case POVDIR_RIGHT: result = (pov >= 4500 && pov <= 13500); break; + case POVDIR_UP: result = (pov >= 31500 || pov <= 4500); break; + case POVDIR_DOWN: result = (pov >= 13500 && pov <= 22500); break; } - return result; } -//============================================================ -// dinput_keyboard_device - directinput keyboard device -//============================================================ - -dinput_keyboard_device::dinput_keyboard_device(running_machine &machine, const char *name, const char *id, input_module &module) - : dinput_device(machine, name, id, DEVICE_CLASS_KEYBOARD, module), - keyboard({{0}}) -{ -} - -// 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); -} - -void dinput_keyboard_device::reset() -{ - memset(&keyboard.state, 0, sizeof(keyboard.state)); -} //============================================================ -// dinput_api_helper - DirectInput API helper +// dinput_set_dword_property //============================================================ -dinput_api_helper::dinput_api_helper(int version) - : m_dinput(nullptr), - m_dinput_version(version), - m_dinput_create_prt(nullptr) -{ -} - -dinput_api_helper::~dinput_api_helper() +HRESULT dinput_set_dword_property(ComPtr<IDirectInputDevice8> device, REFGUID property_guid, DWORD object, DWORD how, DWORD value) { - m_dinput.Reset(); -} - -int dinput_api_helper::initialize() -{ - HRESULT result; - -#if DIRECTINPUT_VERSION >= 0x0800 - 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 -#endif - { - m_dinput_dll = osd::dynamic_module::open({ "dinput.dll" }); - - m_dinput_create_prt = m_dinput_dll->bind<dinput_create_fn>("DirectInputCreateW"); - if (m_dinput_create_prt == nullptr) - { - osd_printf_verbose("Legacy DirectInput library dinput.dll is not available\n"); - return ERROR_DLL_NOT_FOUND; - } - - // first attempt to initialize DirectInput at v7 - m_dinput_version = 0x0700; - result = (*m_dinput_create_prt)(GetModuleHandleUni(), m_dinput_version, m_dinput.GetAddressOf(), nullptr); - if (result != DI_OK) - { - // if that fails, try version 5 - m_dinput_version = 0x0500; - result = (*m_dinput_create_prt)(GetModuleHandleUni(), m_dinput_version, m_dinput.GetAddressOf(), nullptr); - if (result != DI_OK) - { - m_dinput_version = 0; - return result; - } - } - } - - osd_printf_verbose("DirectInput: Using DirectInput %d\n", m_dinput_version >> 8); - return 0; -} - + DIPROPDWORD dipdw; -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; + dipdw.diph.dwSize = sizeof(dipdw); + dipdw.diph.dwHeaderSize = sizeof(dipdw.diph); + dipdw.diph.dwObj = object; + dipdw.diph.dwHow = how; + dipdw.dwData = value; - return m_dinput->EnumDevices(devclass, device_enum_interface::enum_callback, &ctx, DIEDFL_ATTACHEDONLY); + return device->SetProperty(property_guid, &dipdw.diph); } @@ -218,7 +107,7 @@ public: int init_internal() override { - m_dinput_helper = std::make_unique<dinput_api_helper>(DIRECTINPUT_VERSION); + m_dinput_helper = std::make_unique<dinput_api_helper>(); int result = m_dinput_helper->initialize(); if (result != 0) return result; @@ -236,7 +125,7 @@ public: { HRESULT result = m_dinput_helper->enum_attached_devices(dinput_devclass(), this, &machine); if (result != DI_OK) - fatalerror("DirectInput: Unable to enumerate keyboards (result=%08X)\n", static_cast<uint32_t>(result)); + fatalerror("DirectInput: Unable to enumerate devices (result=%08X)\n", uint32_t(result)); } static std::string device_item_name(dinput_device * devinfo, int offset, const char * defstring, const TCHAR * suffix) @@ -286,11 +175,7 @@ public: int dinput_devclass() override { -#if DIRECTINPUT_VERSION >= 0x0800 return DI8DEVCLASS_KEYBOARD; -#else - return DIDEVTYPE_KEYBOARD; -#endif } BOOL device_enum_callback(LPCDIDEVICEINSTANCE instance, LPVOID ref) override @@ -316,7 +201,7 @@ public: name = device_item_name(devinfo, keynum, defname, nullptr); // add the item to the device - devinfo->device()->add_item(name.c_str(), itemid, generic_button_get_state<std::uint8_t>, &devinfo->keyboard.state[keynum]); + devinfo->device()->add_item(name, itemid, generic_button_get_state<std::uint8_t>, &devinfo->keyboard.state[keynum]); } exit: @@ -324,29 +209,6 @@ public: } }; - -dinput_mouse_device::dinput_mouse_device(running_machine &machine, const char *name, const char *id, input_module &module) - : dinput_device(machine, name, id, DEVICE_CLASS_MOUSE, module), - mouse({0}) -{ -} - -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; -} - -void dinput_mouse_device::reset() -{ - memset(&mouse, 0, sizeof(mouse)); -} - class mouse_input_dinput : public dinput_module { public: @@ -357,11 +219,7 @@ public: int dinput_devclass() override { -#if DIRECTINPUT_VERSION >= 0x0800 return DI8DEVCLASS_POINTER; -#else - return DIDEVTYPE_MOUSE; -#endif } BOOL device_enum_callback(LPCDIDEVICEINSTANCE instance, LPVOID ref) override @@ -373,7 +231,7 @@ public: // allocate and link in a new device devinfo = m_dinput_helper->create_device<dinput_mouse_device>(machine, *this, instance, &c_dfDIMouse2, &c_dfDIMouse, dinput_cooperative_level::FOREGROUND); - if (devinfo == nullptr) + if (!devinfo) goto exit; // set relative mode on the mouse device @@ -394,7 +252,7 @@ public: // add to the mouse device and optionally to the gun device as well std::string name = device_item_name(devinfo, offsetof(DIMOUSESTATE, lX) + axisnum * sizeof(LONG), default_axis_name[axisnum], nullptr); devinfo->device()->add_item( - name.c_str(), + name, static_cast<input_item_id>(ITEM_ID_XAXIS + axisnum), generic_axis_get_state<LONG>, &devinfo->mouse.lX + axisnum); @@ -408,7 +266,7 @@ public: // add to the mouse device std::string name = device_item_name(devinfo, offset, default_button_name(butnum), nullptr); devinfo->device()->add_item( - name.c_str(), + name, static_cast<input_item_id>(ITEM_ID_BUTTON1 + butnum), generic_button_get_state<BYTE>, &devinfo->mouse.rgbButtons[butnum]); @@ -418,14 +276,151 @@ public: return DIENUM_CONTINUE; error: - if (devinfo != nullptr) - devicelist()->free_device(devinfo); + if (devinfo) + devicelist()->free_device(*devinfo); goto exit; } }; -dinput_joystick_device::dinput_joystick_device(running_machine &machine, const char *name, const char *id, input_module &module) - : dinput_device(machine, name, id, DEVICE_CLASS_JOYSTICK, module), + +class joystick_input_dinput : public dinput_module +{ +public: + joystick_input_dinput() : + dinput_module(OSD_JOYSTICKINPUT_PROVIDER, "dinput") + { + } + + int dinput_devclass() override + { + return DI8DEVCLASS_GAMECTRL; + } + + BOOL device_enum_callback(LPCDIDEVICEINSTANCE instance, LPVOID ref) override + { + dinput_cooperative_level cooperative_level = dinput_cooperative_level::FOREGROUND; + running_machine &machine = *static_cast<running_machine *>(ref); + dinput_joystick_device *devinfo; + int result = 0; + + if (!osd_common_t::s_window_list.empty() && osd_common_t::s_window_list.front()->win_has_menu()) + cooperative_level = dinput_cooperative_level::BACKGROUND; + + // allocate and link in a new device + devinfo = m_dinput_helper->create_device<dinput_joystick_device>(machine, *this, instance, &c_dfDIJoystick, nullptr, cooperative_level); + if (devinfo == nullptr) + goto exit; + + result = devinfo->configure(); + if (result != 0) + { + osd_printf_error("Failed to configure DI Joystick device. Error 0x%x\n", static_cast<unsigned int>(result)); + } + + exit: + return DIENUM_CONTINUE; + } +}; + +} // anonymous namespace + + +//============================================================ +// dinput_device - base directinput device +//============================================================ + +dinput_device::dinput_device(running_machine &machine, std::string &&name, std::string &&id, input_device_class deviceclass, input_module &module) + : device_info(machine, std::move(name), std::move(id), deviceclass, module), + dinput({nullptr}) +{ +} + +dinput_device::~dinput_device() +{ + if (dinput.device) + dinput.device.Reset(); +} + +HRESULT dinput_device::poll_dinput(LPVOID pState) const +{ + HRESULT result; + + // first poll the device, then get the state + dinput.device->Poll(); + + // GetDeviceState returns the immediate state + result = dinput.device->GetDeviceState(dinput.format->dwDataSize, pState); + + // handle lost inputs here + if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) + { + result = dinput.device->Acquire(); + if (result == DI_OK) + result = dinput.device->GetDeviceState(dinput.format->dwDataSize, pState); + } + + return result; +} + + +//============================================================ +// dinput_keyboard_device - directinput keyboard device +//============================================================ + +dinput_keyboard_device::dinput_keyboard_device(running_machine &machine, std::string &&name, std::string &&id, input_module &module) + : dinput_device(machine, std::move(name), std::move(id), DEVICE_CLASS_KEYBOARD, module), + keyboard({{0}}) +{ +} + +// 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); +} + +void dinput_keyboard_device::reset() +{ + memset(&keyboard.state, 0, sizeof(keyboard.state)); +} + + +//============================================================ +// dinput_mouse_device - directinput mouse device +//============================================================ + +dinput_mouse_device::dinput_mouse_device(running_machine &machine, std::string &&name, std::string &&id, input_module &module) + : dinput_device(machine, std::move(name), std::move(id), DEVICE_CLASS_MOUSE, module), + mouse({0}) +{ +} + +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; +} + +void dinput_mouse_device::reset() +{ + memset(&mouse, 0, sizeof(mouse)); +} + + +//============================================================ +// dinput_joystick_device - directinput joystick device +//============================================================ + +dinput_joystick_device::dinput_joystick_device(running_machine &machine, std::string &&name, std::string &&id, input_module &module) + : dinput_device(machine, std::move(name), std::move(id), DEVICE_CLASS_JOYSTICK, module), joystick({{0}}) { } @@ -454,8 +449,6 @@ void dinput_joystick_device::poll() int dinput_joystick_device::configure() { HRESULT result; - uint32_t axisnum, axiscount; - auto devicelist = static_cast<input_module_base&>(module()).devicelist(); // temporary approximation of index @@ -482,12 +475,10 @@ int dinput_joystick_device::configure() dinput.caps.dwButtons = std::min(dinput.caps.dwButtons, DWORD(128)); // populate the axes - for (axisnum = axiscount = 0; axiscount < dinput.caps.dwAxes && axisnum < 8; axisnum++) + for (uint32_t axisnum = 0, axiscount = 0; axiscount < dinput.caps.dwAxes && axisnum < 8; axisnum++) { - DIPROPRANGE dipr; - std::string name; - // fetch the range of this axis + DIPROPRANGE dipr; dipr.diph.dwSize = sizeof(dipr); dipr.diph.dwHeaderSize = sizeof(dipr.diph); dipr.diph.dwObj = offsetof(DIJOYSTATE2, lX) + axisnum * sizeof(LONG); @@ -500,9 +491,9 @@ int dinput_joystick_device::configure() 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); + std::string name = dinput_module::device_item_name(this, offsetof(DIJOYSTATE2, lX) + axisnum * sizeof(LONG), default_axis_name[axisnum], nullptr); device()->add_item( - name.c_str(), + name, static_cast<input_item_id>(ITEM_ID_XAXIS + axisnum), generic_axis_get_state<LONG>, &joystick.state.lX + axisnum); @@ -517,19 +508,19 @@ int dinput_joystick_device::configure() // 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<uintptr_t>(povnum * 4 + POVDIR_LEFT))); + device()->add_item(name, ITEM_ID_OTHER_SWITCH, dinput_joystick_pov_get_state, reinterpret_cast<void *>(static_cast<uintptr_t>(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<uintptr_t>(povnum * 4 + POVDIR_RIGHT))); + device()->add_item(name, ITEM_ID_OTHER_SWITCH, dinput_joystick_pov_get_state, reinterpret_cast<void *>(static_cast<uintptr_t>(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<uintptr_t>(povnum * 4 + POVDIR_UP))); + device()->add_item(name, ITEM_ID_OTHER_SWITCH, dinput_joystick_pov_get_state, reinterpret_cast<void *>(static_cast<uintptr_t>(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<uintptr_t>(povnum * 4 + POVDIR_DOWN))); + device()->add_item(name, ITEM_ID_OTHER_SWITCH, dinput_joystick_pov_get_state, reinterpret_cast<void *>(static_cast<uintptr_t>(povnum * 4 + POVDIR_DOWN))); } // populate the buttons @@ -547,91 +538,57 @@ int dinput_joystick_device::configure() else itemid = ITEM_ID_OTHER_SWITCH; - device()->add_item(name.c_str(), itemid, generic_button_get_state<BYTE>, &joystick.state.rgbButtons[butnum]); + device()->add_item(name, itemid, generic_button_get_state<BYTE>, &joystick.state.rgbButtons[butnum]); } return 0; } -class joystick_input_dinput : public dinput_module -{ -public: - joystick_input_dinput() : - dinput_module(OSD_JOYSTICKINPUT_PROVIDER, "dinput") - { - } - - int dinput_devclass() override - { -#if DIRECTINPUT_VERSION >= 0x0800 - return DI8DEVCLASS_GAMECTRL; -#else - return DIDEVTYPE_JOYSTICK; -#endif - } - - BOOL device_enum_callback(LPCDIDEVICEINSTANCE instance, LPVOID ref) override - { - dinput_cooperative_level cooperative_level = dinput_cooperative_level::FOREGROUND; - running_machine &machine = *static_cast<running_machine *>(ref); - dinput_joystick_device *devinfo; - int result = 0; - - if (!osd_common_t::s_window_list.empty() && osd_common_t::s_window_list.front()->win_has_menu()) - cooperative_level = dinput_cooperative_level::BACKGROUND; - - // allocate and link in a new device - devinfo = m_dinput_helper->create_device<dinput_joystick_device>(machine, *this, instance, &c_dfDIJoystick, nullptr, cooperative_level); - if (devinfo == nullptr) - goto exit; - - result = devinfo->configure(); - if (result != 0) - { - osd_printf_error("Failed to configure DI Joystick device. Error 0x%x\n", static_cast<unsigned int>(result)); - } - - exit: - return DIENUM_CONTINUE; - } -}; //============================================================ -// dinput_joystick_pov_get_state +// dinput_api_helper - DirectInput API helper //============================================================ -static int32_t dinput_joystick_pov_get_state(void *device_internal, void *item_internal) +dinput_api_helper::dinput_api_helper() + : m_dinput(nullptr), + m_dinput_create_prt(nullptr) { - auto *devinfo = static_cast<dinput_joystick_device *>(device_internal); - int povnum = reinterpret_cast<uintptr_t>(item_internal) / 4; - int povdir = reinterpret_cast<uintptr_t>(item_internal) % 4; - int32_t result = 0; - DWORD pov; - - // get the current state - devinfo->module().poll_if_necessary(devinfo->machine()); - pov = devinfo->joystick.state.rgdwPOV[povnum]; +} - // if invalid, return 0 - if ((pov & 0xffff) == 0xffff) - return result; +dinput_api_helper::~dinput_api_helper() +{ + m_dinput.Reset(); +} - // return the current state - switch (povdir) +int dinput_api_helper::initialize() +{ + HRESULT result = DirectInput8Create(GetModuleHandleUni(), DIRECTINPUT_VERSION, IID_IDirectInput8, reinterpret_cast<void **>(m_dinput.GetAddressOf()), nullptr); + if (result != DI_OK) { - case POVDIR_LEFT: result = (pov >= 22500 && pov <= 31500); break; - case POVDIR_RIGHT: result = (pov >= 4500 && pov <= 13500); break; - case POVDIR_UP: result = (pov >= 31500 || pov <= 4500); break; - case POVDIR_DOWN: result = (pov >= 13500 && pov <= 22500); break; + return result; } - return result; + + osd_printf_verbose("DirectInput: Using DirectInput %d\n", DIRECTINPUT_VERSION >> 8); + return 0; +} + + +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; + + return m_dinput->EnumDevices(devclass, device_enum_interface::enum_callback, &ctx, DIEDFL_ATTACHEDONLY); } -#else +#else // defined(OSD_WINDOWS) + MODULE_NOT_SUPPORTED(keyboard_input_dinput, OSD_KEYBOARDINPUT_PROVIDER, "dinput") MODULE_NOT_SUPPORTED(mouse_input_dinput, OSD_MOUSEINPUT_PROVIDER, "dinput") MODULE_NOT_SUPPORTED(joystick_input_dinput, OSD_JOYSTICKINPUT_PROVIDER, "dinput") -#endif + +#endif // defined(OSD_WINDOWS) MODULE_DEFINITION(KEYBOARDINPUT_DINPUT, keyboard_input_dinput) MODULE_DEFINITION(MOUSEINPUT_DINPUT, mouse_input_dinput) |