summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd/modules/input/input_dinput.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/osd/modules/input/input_dinput.cpp')
-rw-r--r--src/osd/modules/input/input_dinput.cpp710
1 files changed, 407 insertions, 303 deletions
diff --git a/src/osd/modules/input/input_dinput.cpp b/src/osd/modules/input/input_dinput.cpp
index 3461f9aad24..375beb32df1 100644
--- a/src/osd/modules/input/input_dinput.cpp
+++ b/src/osd/modules/input/input_dinput.cpp
@@ -8,71 +8,39 @@
#include "modules/osdmodule.h"
-#if defined(OSD_WINDOWS)
+#if defined(OSD_WINDOWS) || defined(SDLMAME_WIN32)
-#include "emu.h"
+// emu
+#include "emu.h" // put this here before Windows headers define interface as a macro
#include "input_dinput.h"
-#include "winutil.h"
+#include "windows/winutil.h"
+
+// lib/util
+#include "util/corestr.h"
+
+#ifdef SDLMAME_WIN32
+#include <SDL2/SDL.h>
+#include <SDL2/SDL_syswm.h>
+#endif
-#include <mutex>
+#include <algorithm>
+#include <iterator>
+#include <memory>
// standard windows headers
#include <initguid.h>
#include <tchar.h>
-namespace {
-
-using namespace Microsoft::WRL;
-
-//============================================================
-// dinput_joystick_pov_get_state
-//============================================================
-
-int32_t dinput_joystick_pov_get_state(void *device_internal, void *item_internal)
-{
- 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;
-
- // get the current state
- devinfo->module().poll_if_necessary(devinfo->machine());
- const DWORD pov = devinfo->joystick.state.rgdwPOV[povnum];
-
- // if invalid, return 0
- if ((pov & 0xffff) == 0xffff)
- return result;
-
- // return the current state
- switch (povdir)
- {
- 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;
-}
-
+namespace osd {
-//============================================================
-// dinput_set_dword_property
-//============================================================
+namespace {
-HRESULT dinput_set_dword_property(ComPtr<IDirectInputDevice8> device, REFGUID property_guid, DWORD object, DWORD how, DWORD value)
+BOOL CALLBACK device_enum_interface_callback(LPCDIDEVICEINSTANCE instance, LPVOID ref)
{
- 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);
+ return static_cast<device_enum_interface *>(ref)->device_enum_callback(instance);
}
@@ -80,76 +48,52 @@ HRESULT dinput_set_dword_property(ComPtr<IDirectInputDevice8> device, REFGUID pr
// dinput_module - base directinput module
//============================================================
-class dinput_module : public wininput_module, public device_enum_interface
+class dinput_module : public input_module_impl<dinput_device, osd_common_t>, public device_enum_interface
{
protected:
std::unique_ptr<dinput_api_helper> m_dinput_helper;
public:
- dinput_module(const char* type, const char* name)
- : wininput_module(type, name),
- m_dinput_helper(nullptr)
+ dinput_module(const char* type, const char* name) :
+ input_module_impl<dinput_device, osd_common_t>(type, name),
+ m_dinput_helper(nullptr)
{
}
- int init_internal() override
+ virtual int init(osd_interface &osd, osd_options const &options) override
{
m_dinput_helper = std::make_unique<dinput_api_helper>();
- int result = m_dinput_helper->initialize();
- if (result != 0)
+ int const result = m_dinput_helper->initialize();
+ if (result)
+ {
+ m_dinput_helper.reset();
return result;
+ }
- return 0;
+ return input_module_impl<dinput_device, osd_common_t>::init(osd, options);
}
- void exit() override
+ virtual void exit() override
{
- wininput_module::exit();
- m_dinput_helper.reset();
- }
+ input_module_impl<dinput_device, osd_common_t>::exit();
- void input_init(running_machine &machine) override
- {
- HRESULT result = m_dinput_helper->enum_attached_devices(dinput_devclass(), this, &machine);
- if (result != DI_OK)
- fatalerror("DirectInput: Unable to enumerate devices (result=%08X)\n", uint32_t(result));
+ m_dinput_helper.reset();
}
- static std::string device_item_name(dinput_device *devinfo, int offset, const char *defstring, const char *suffix)
+ virtual void input_init(running_machine &machine) override
{
- DIDEVICEOBJECTINSTANCE instance = { 0 };
- HRESULT result;
+ input_module_impl<dinput_device, osd_common_t>::input_init(machine);
- // query the key name
- 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 nullptr
+ HRESULT result = m_dinput_helper->enum_attached_devices(dinput_devclass(), *this);
if (result != DI_OK)
- {
- if (defstring == nullptr)
- return nullptr;
-
- // Return the default value
- std::string result(defstring);
- if (suffix)
- result.append(" ").append(suffix);
- return result;
- }
-
- // convert the name to utf8
- std::string namestring = osd::text::from_tstring(instance.tszName);
-
- // if no suffix, return as-is
- if (suffix)
- namestring.append(" ").append(suffix);
- return namestring;
+ fatalerror("DirectInput: Unable to enumerate devices (result=%08X)\n", uint32_t(result));
}
protected:
virtual int dinput_devclass() = 0;
};
+
class keyboard_input_dinput : public dinput_module
{
public:
@@ -158,42 +102,29 @@ public:
{
}
- int dinput_devclass() override
+ virtual int dinput_devclass() override
{
return DI8DEVCLASS_KEYBOARD;
}
- BOOL device_enum_callback(LPCDIDEVICEINSTANCE instance, LPVOID ref) override
+ virtual BOOL device_enum_callback(LPCDIDEVICEINSTANCE instance) override
{
- running_machine &machine = *static_cast<running_machine *>(ref);
- dinput_keyboard_device *devinfo;
- int keynum;
-
// allocate and link in a new device
- devinfo = m_dinput_helper->create_device<dinput_keyboard_device>(machine, *this, instance, &c_dfDIKeyboard, nullptr, dinput_cooperative_level::FOREGROUND);
- if (devinfo == nullptr)
- goto exit;
-
- // populate it
- for (keynum = 0; keynum < MAX_KEYS; keynum++)
- {
- input_item_id itemid = keyboard_trans_table::instance().map_di_scancode_to_itemid(keynum);
- char defname[20];
- std::string name;
-
- // generate/fetch the name
- snprintf(defname, std::size(defname), "Scan%03d", keynum);
- name = device_item_name(devinfo, keynum, defname, nullptr);
-
- // add the item to the device
- devinfo->device()->add_item(name, itemid, generic_button_get_state<std::uint8_t>, &devinfo->keyboard.state[keynum]);
- }
+ auto devinfo = m_dinput_helper->create_device<dinput_keyboard_device>(
+ *this,
+ instance,
+ &c_dfDIKeyboard,
+ nullptr,
+ background_input() ? dinput_cooperative_level::BACKGROUND : dinput_cooperative_level::FOREGROUND,
+ [] (auto...) { return true; });
+ if (devinfo)
+ add_device(DEVICE_CLASS_KEYBOARD, std::move(devinfo));
- exit:
return DIENUM_CONTINUE;
}
};
+
class mouse_input_dinput : public dinput_module
{
public:
@@ -202,68 +133,40 @@ public:
{
}
- int dinput_devclass() override
+ virtual int dinput_devclass() override
{
return DI8DEVCLASS_POINTER;
}
- BOOL device_enum_callback(LPCDIDEVICEINSTANCE instance, LPVOID ref) override
+ virtual BOOL device_enum_callback(LPCDIDEVICEINSTANCE instance) override
{
- dinput_mouse_device *devinfo = nullptr;
- running_machine &machine = *static_cast<running_machine *>(ref);
- int axisnum, butnum;
- HRESULT result;
-
// 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)
- goto exit;
-
- // set relative mode on the mouse device
- result = dinput_set_dword_property(devinfo->dinput.device, DIPROP_AXISMODE, 0, DIPH_DEVICE, DIPROPAXISMODE_REL);
- if (result != DI_OK && result != DI_PROPNOEFFECT)
- {
- osd_printf_error("DirectInput: Unable to set relative mode for mouse %u (%s)\n", static_cast<unsigned int>(devicelist().size()), devinfo->name());
- goto error;
- }
-
- // cap the number of axes and buttons based on the format
- devinfo->dinput.caps.dwAxes = std::min(devinfo->dinput.caps.dwAxes, DWORD(3));
- devinfo->dinput.caps.dwButtons = std::min(devinfo->dinput.caps.dwButtons, DWORD((devinfo->dinput.format == &c_dfDIMouse) ? 4 : 8));
-
- // populate the axes
- for (axisnum = 0; axisnum < devinfo->dinput.caps.dwAxes; axisnum++)
- {
- // 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,
- static_cast<input_item_id>(ITEM_ID_XAXIS + axisnum),
- generic_axis_get_state<LONG>,
- &devinfo->mouse.lX + axisnum);
- }
-
- // populate the buttons
- for (butnum = 0; butnum < devinfo->dinput.caps.dwButtons; butnum++)
- {
- auto offset = reinterpret_cast<uintptr_t>(&static_cast<DIMOUSESTATE *>(nullptr)->rgbButtons[butnum]);
-
- // add to the mouse device
- std::string name = device_item_name(devinfo, offset, default_button_name(butnum).c_str(), nullptr);
- devinfo->device()->add_item(
- name,
- static_cast<input_item_id>(ITEM_ID_BUTTON1 + butnum),
- generic_button_get_state<BYTE>,
- &devinfo->mouse.rgbButtons[butnum]);
- }
+ auto devinfo = m_dinput_helper->create_device<dinput_mouse_device>(
+ *this,
+ instance,
+ &c_dfDIMouse2,
+ &c_dfDIMouse,
+ background_input() ? dinput_cooperative_level::BACKGROUND : dinput_cooperative_level::FOREGROUND,
+ [] (auto const &device, auto const &format) -> bool
+ {
+ // set relative mode
+ HRESULT const result = dinput_api_helper::set_dword_property(
+ device,
+ DIPROP_AXISMODE,
+ 0,
+ DIPH_DEVICE,
+ DIPROPAXISMODE_REL);
+ if ((result != DI_OK) && (result != DI_PROPNOEFFECT))
+ {
+ osd_printf_error("DirectInput: Unable to set relative mode for mouse.\n");
+ return false;
+ }
+ return true;
+ });
+ if (devinfo)
+ add_device(DEVICE_CLASS_MOUSE, std::move(devinfo));
- exit:
return DIENUM_CONTINUE;
-
- error:
- if (devinfo)
- devicelist().free_device(*devinfo);
- goto exit;
}
};
@@ -276,33 +179,39 @@ public:
{
}
- int dinput_devclass() override
+ virtual int dinput_devclass() override
{
return DI8DEVCLASS_GAMECTRL;
}
- BOOL device_enum_callback(LPCDIDEVICEINSTANCE instance, LPVOID ref) override
+ virtual BOOL device_enum_callback(LPCDIDEVICEINSTANCE instance) 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));
- }
+ auto devinfo = m_dinput_helper->create_device<dinput_joystick_device>(
+ *this,
+ instance,
+ &c_dfDIJoystick,
+ nullptr,
+ background_input() ? dinput_cooperative_level::BACKGROUND : dinput_cooperative_level::FOREGROUND,
+ [] (auto const &device, auto const &format) -> bool
+ {
+ // set absolute mode
+ HRESULT const result = dinput_api_helper::set_dword_property(
+ device,
+ DIPROP_AXISMODE,
+ 0,
+ DIPH_DEVICE,
+ DIPROPAXISMODE_ABS);
+ if ((result != DI_OK) && (result != DI_PROPNOEFFECT))
+ {
+ osd_printf_error("DirectInput: Unable to set absolute mode for joystick.\n");
+ return false;
+ }
+ return true;
+ });
+ if (devinfo)
+ add_device(DEVICE_CLASS_JOYSTICK, std::move(devinfo));
- exit:
return DIENUM_CONTINUE;
}
};
@@ -314,16 +223,18 @@ public:
// 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()
+dinput_device::dinput_device(
+ std::string &&name,
+ std::string &&id,
+ input_module &module,
+ Microsoft::WRL::ComPtr<IDirectInputDevice8> &&device,
+ DIDEVCAPS const &caps,
+ LPCDIDATAFORMAT format) :
+ device_info(std::move(name), std::move(id), module),
+ m_device(std::move(device)),
+ m_caps(caps),
+ m_format(format)
{
- if (dinput.device)
- dinput.device.Reset();
}
HRESULT dinput_device::poll_dinput(LPVOID pState) const
@@ -331,45 +242,91 @@ 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);
+ result = m_device->Poll();
// handle lost inputs here
- if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED)
+ if ((result == DIERR_INPUTLOST) || (result == DIERR_NOTACQUIRED))
{
- result = dinput.device->Acquire();
- if (result == DI_OK)
- result = dinput.device->GetDeviceState(dinput.format->dwDataSize, pState);
+ result = m_device->Acquire();
+ if ((result == DI_OK) || (result == S_FALSE))
+ result = m_device->Poll();
}
+ // GetDeviceState returns the immediate state
+ if ((result == DI_OK) || (result == DI_NOEFFECT))
+ result = m_device->GetDeviceState(m_format->dwDataSize, pState);
+
return result;
}
+std::string dinput_device::item_name(int offset, std::string_view defstring, const char *suffix) const
+{
+ // query the key name
+ DIDEVICEOBJECTINSTANCE instance = { 0 };
+ instance.dwSize = sizeof(instance);
+ HRESULT const result = m_device->GetObjectInfo(&instance, offset, DIPH_BYOFFSET);
+
+ // use the default value if it failed
+ std::string name;
+ if (result != DI_OK)
+ name = defstring;
+ else
+ name = text::from_tstring(instance.tszName);
+
+ // if no suffix, return as-is
+ if (suffix)
+ name.append(" ").append(suffix);
+
+ return name;
+}
+
//============================================================
// 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}})
+dinput_keyboard_device::dinput_keyboard_device(
+ std::string &&name,
+ std::string &&id,
+ input_module &module,
+ Microsoft::WRL::ComPtr<IDirectInputDevice8> &&device,
+ DIDEVCAPS const &caps,
+ LPCDIDATAFORMAT format) :
+ dinput_device(std::move(name), std::move(id), module, std::move(device), caps, format),
+ m_keyboard({ { 0 } })
{
}
-// Polls the direct input immediate state
void dinput_keyboard_device::poll()
{
+ // poll the DirectInput immediate state
std::lock_guard<std::mutex> scope_lock(m_device_lock);
-
- // Poll the state
- dinput_device::poll_dinput(&keyboard.state);
+ poll_dinput(&m_keyboard.state);
}
void dinput_keyboard_device::reset()
{
- memset(&keyboard.state, 0, sizeof(keyboard.state));
+ memset(&m_keyboard.state, 0, sizeof(m_keyboard.state));
+}
+
+void dinput_keyboard_device::configure(input_device &device)
+{
+ // populate it
+ char defname[20];
+ for (int keynum = 0; keynum < MAX_KEYS; keynum++)
+ {
+ input_item_id itemid = keyboard_trans_table::instance().map_di_scancode_to_itemid(keynum);
+
+ // generate/fetch the name
+ snprintf(defname, std::size(defname), "Scan%03d", keynum);
+
+ // add the item to the device
+ device.add_item(
+ item_name(keynum, defname, nullptr),
+ itemid,
+ generic_button_get_state<std::uint8_t>,
+ &m_keyboard.state[keynum]);
+ }
}
@@ -377,26 +334,63 @@ void dinput_keyboard_device::reset()
// 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})
+dinput_mouse_device::dinput_mouse_device(
+ std::string &&name,
+ std::string &&id,
+ input_module &module,
+ Microsoft::WRL::ComPtr<IDirectInputDevice8> &&device,
+ DIDEVCAPS const &caps,
+ LPCDIDATAFORMAT format) :
+ dinput_device(std::move(name), std::move(id), module, std::move(device), caps, format),
+ m_mouse({0})
{
+ // cap the number of axes and buttons based on the format
+ m_caps.dwAxes = std::min(m_caps.dwAxes, DWORD(3));
+ m_caps.dwButtons = std::min(m_caps.dwButtons, DWORD((m_format == &c_dfDIMouse) ? 4 : 8));
}
void dinput_mouse_device::poll()
{
// poll
- dinput_device::poll_dinput(&mouse);
-
- // scale the axis data
- mouse.lX *= osd::INPUT_RELATIVE_PER_PIXEL;
- mouse.lY *= osd::INPUT_RELATIVE_PER_PIXEL;
- mouse.lZ *= osd::INPUT_RELATIVE_PER_PIXEL;
+ if (poll_dinput(&m_mouse) == DI_OK)
+ {
+ // scale the axis data
+ m_mouse.lX *= INPUT_RELATIVE_PER_PIXEL;
+ m_mouse.lY *= INPUT_RELATIVE_PER_PIXEL;
+ m_mouse.lZ *= INPUT_RELATIVE_PER_PIXEL;
+ }
}
void dinput_mouse_device::reset()
{
- memset(&mouse, 0, sizeof(mouse));
+ memset(&m_mouse, 0, sizeof(m_mouse));
+}
+
+void dinput_mouse_device::configure(input_device &device)
+{
+ // populate the axes
+ for (int axisnum = 0; axisnum < m_caps.dwAxes; axisnum++)
+ {
+ // add to the mouse device and optionally to the gun device as well
+ device.add_item(
+ item_name(offsetof(DIMOUSESTATE, lX) + axisnum * sizeof(LONG), default_axis_name[axisnum], nullptr),
+ input_item_id(ITEM_ID_XAXIS + axisnum),
+ generic_axis_get_state<LONG>,
+ &m_mouse.lX + axisnum);
+ }
+
+ // populate the buttons
+ for (int butnum = 0; butnum < m_caps.dwButtons; butnum++)
+ {
+ auto offset = reinterpret_cast<uintptr_t>(&static_cast<DIMOUSESTATE *>(nullptr)->rgbButtons[butnum]);
+
+ // add to the mouse device
+ device.add_item(
+ item_name(offset, default_button_name(butnum), nullptr),
+ input_item_id(ITEM_ID_BUTTON1 + butnum),
+ generic_button_get_state<BYTE>,
+ &m_mouse.rgbButtons[butnum]);
+ }
}
@@ -404,64 +398,58 @@ void dinput_mouse_device::reset()
// 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}})
+dinput_joystick_device::dinput_joystick_device(
+ std::string &&name,
+ std::string &&id,
+ input_module &module,
+ Microsoft::WRL::ComPtr<IDirectInputDevice8> &&device,
+ DIDEVCAPS const &caps,
+ LPCDIDATAFORMAT format) :
+ dinput_device(std::move(name), std::move(id), module, std::move(device), caps, format),
+ m_joystick({ { 0 } })
{
+ // cap the number of axes, POVs, and buttons based on the format
+ m_caps.dwAxes = std::min(m_caps.dwAxes, DWORD(8));
+ m_caps.dwPOVs = std::min(m_caps.dwPOVs, DWORD(4));
+ m_caps.dwButtons = std::min(m_caps.dwButtons, DWORD(128));
}
void dinput_joystick_device::reset()
{
- memset(&joystick.state, 0, sizeof(joystick.state));
- std::fill(std::begin(joystick.state.rgdwPOV), std::end(joystick.state.rgdwPOV), 0xffff);
+ memset(&m_joystick.state, 0, sizeof(m_joystick.state));
+ std::fill(std::begin(m_joystick.state.rgdwPOV), std::end(m_joystick.state.rgdwPOV), 0xffff);
}
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++)
+ if (dinput_device::poll_dinput(&m_joystick.state) == DI_OK)
{
- LONG *axis = (&joystick.state.lX) + axisnum;
- *axis = normalize_absolute_axis(*axis, joystick.rangemin[axisnum], joystick.rangemax[axisnum]);
+ // normalize axis values
+ for (int axisnum = 0; axisnum < 8; axisnum++)
+ {
+ LONG *const axis = &m_joystick.state.lX + axisnum;
+ *axis = normalize_absolute_axis(*axis, m_joystick.rangemin[axisnum], m_joystick.rangemax[axisnum]);
+ }
}
}
-int dinput_joystick_device::configure()
+void dinput_joystick_device::configure(input_device &device)
{
HRESULT result;
- 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);
+ result = dinput_api_helper::set_dword_property(m_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());
+ osd_printf_warning("DirectInput: Unable to reset deadzone for joystick %s.\n", name());
// turn off saturation; we do our own calculations
- result = dinput_set_dword_property(dinput.device, DIPROP_SATURATION, 0, DIPH_DEVICE, 10000);
+ result = dinput_api_helper::set_dword_property(m_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 = std::min(dinput.caps.dwAxes, DWORD(8));
- dinput.caps.dwPOVs = std::min(dinput.caps.dwPOVs, DWORD(4));
- dinput.caps.dwButtons = std::min(dinput.caps.dwButtons, DWORD(128));
+ osd_printf_warning("DirectInput: Unable to reset saturation for joystick %s.\n", name());
// populate the axes
- for (uint32_t axisnum = 0, axiscount = 0; axiscount < dinput.caps.dwAxes && axisnum < 8; axisnum++)
+ for (uint32_t axisnum = 0, axiscount = 0; axiscount < m_caps.dwAxes && axisnum < 8; axisnum++)
{
// fetch the range of this axis
DIPROPRANGE dipr;
@@ -469,67 +457,62 @@ int dinput_joystick_device::configure()
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);
+ result = m_device->GetProperty(DIPROP_RANGE, &dipr.diph);
if (result != DI_OK)
+ {
+ osd_printf_verbose("DirectInput: Unable to get properties for joystick %s axis %u.\n", name(), axisnum);
continue;
+ }
- joystick.rangemin[axisnum] = dipr.lMin;
- joystick.rangemax[axisnum] = dipr.lMax;
+ m_joystick.rangemin[axisnum] = dipr.lMin;
+ m_joystick.rangemax[axisnum] = dipr.lMax;
// populate the item description as well
- std::string name = dinput_module::device_item_name(this, offsetof(DIJOYSTATE2, lX) + axisnum * sizeof(LONG), default_axis_name[axisnum], nullptr);
- device()->add_item(
- name,
- static_cast<input_item_id>(ITEM_ID_XAXIS + axisnum),
- generic_axis_get_state<LONG>,
- &joystick.state.lX + axisnum);
+ device.add_item(
+ item_name(offsetof(DIJOYSTATE2, lX) + axisnum * sizeof(LONG), default_axis_name[axisnum], nullptr),
+ input_item_id(ITEM_ID_XAXIS + axisnum),
+ generic_axis_get_state<LONG>,
+ &m_joystick.state.lX + axisnum);
axiscount++;
}
// populate the POVs
- for (uint32_t povnum = 0; povnum < dinput.caps.dwPOVs; povnum++)
+ for (uint32_t povnum = 0; povnum < m_caps.dwPOVs; povnum++)
{
- std::string name;
-
// left
- name = dinput_module::device_item_name(this, offsetof(DIJOYSTATE2, rgdwPOV) + povnum * sizeof(DWORD), default_pov_name(povnum).c_str(), "Left");
- device()->add_item(
- name,
+ device.add_item(
+ item_name(offsetof(DIJOYSTATE2, rgdwPOV) + povnum * sizeof(DWORD), default_pov_name(povnum), "Left"),
input_item_id(povnum * 4 + ITEM_ID_HAT1LEFT),
- dinput_joystick_pov_get_state,
+ &dinput_joystick_device::pov_get_state,
reinterpret_cast<void *>(uintptr_t(povnum * 4 + POVDIR_LEFT)));
// right
- name = dinput_module::device_item_name(this, offsetof(DIJOYSTATE2, rgdwPOV) + povnum * sizeof(DWORD), default_pov_name(povnum).c_str(), "Right");
- device()->add_item(
- name,
+ device.add_item(
+ item_name(offsetof(DIJOYSTATE2, rgdwPOV) + povnum * sizeof(DWORD), default_pov_name(povnum), "Right"),
input_item_id(povnum * 4 + ITEM_ID_HAT1RIGHT),
- dinput_joystick_pov_get_state,
+ &dinput_joystick_device::pov_get_state,
reinterpret_cast<void *>(uintptr_t(povnum * 4 + POVDIR_RIGHT)));
// up
- name = dinput_module::device_item_name(this, offsetof(DIJOYSTATE2, rgdwPOV) + povnum * sizeof(DWORD), default_pov_name(povnum).c_str(), "Up");
- device()->add_item(
- name,
+ device.add_item(
+ item_name(offsetof(DIJOYSTATE2, rgdwPOV) + povnum * sizeof(DWORD), default_pov_name(povnum), "Up"),
input_item_id(povnum * 4 + ITEM_ID_HAT1UP),
- dinput_joystick_pov_get_state,
+ &dinput_joystick_device::pov_get_state,
reinterpret_cast<void *>(uintptr_t(povnum * 4 + POVDIR_UP)));
// down
- name = dinput_module::device_item_name(this, offsetof(DIJOYSTATE2, rgdwPOV) + povnum * sizeof(DWORD), default_pov_name(povnum).c_str(), "Down");
- device()->add_item(
- name,
+ device.add_item(
+ item_name(offsetof(DIJOYSTATE2, rgdwPOV) + povnum * sizeof(DWORD), default_pov_name(povnum), "Down"),
input_item_id(povnum * 4 + ITEM_ID_HAT1DOWN),
- dinput_joystick_pov_get_state,
+ &dinput_joystick_device::pov_get_state,
reinterpret_cast<void *>(uintptr_t(povnum * 4 + POVDIR_DOWN)));
}
// populate the buttons
- for (uint32_t butnum = 0; butnum < dinput.caps.dwButtons; butnum++)
+ for (uint32_t butnum = 0; butnum < m_caps.dwButtons; butnum++)
{
auto offset = reinterpret_cast<uintptr_t>(&static_cast<DIJOYSTATE2 *>(nullptr)->rgbButtons[butnum]);
- std::string name = dinput_module::device_item_name(this, offset, default_button_name(butnum).c_str(), nullptr);
input_item_id itemid;
if (butnum < INPUT_MAX_BUTTONS)
@@ -539,7 +522,35 @@ int dinput_joystick_device::configure()
else
itemid = ITEM_ID_OTHER_SWITCH;
- device()->add_item(name, itemid, generic_button_get_state<BYTE>, &joystick.state.rgbButtons[butnum]);
+ device.add_item(
+ item_name(offset, default_button_name(butnum), nullptr),
+ itemid,
+ generic_button_get_state<BYTE>,
+ &m_joystick.state.rgbButtons[butnum]);
+ }
+}
+
+int32_t dinput_joystick_device::pov_get_state(void *device_internal, void *item_internal)
+{
+ auto *const devinfo = static_cast<dinput_joystick_device *>(device_internal);
+ int const povnum = uintptr_t(item_internal) / 4;
+ int const povdir = uintptr_t(item_internal) % 4;
+
+ // get the current state
+ devinfo->module().poll_if_necessary();
+ DWORD const pov = devinfo->m_joystick.state.rgdwPOV[povnum];
+
+ // if invalid, return 0
+ if ((pov & 0xffff) == 0xffff)
+ return 0;
+
+ // return the current state
+ switch (povdir)
+ {
+ case POVDIR_LEFT: return (pov >= 22500) && (pov <= 31500);
+ case POVDIR_RIGHT: return (pov >= 4500) && (pov <= 13500);
+ case POVDIR_UP: return (pov >= 31500) || (pov <= 4500);
+ case POVDIR_DOWN: return (pov >= 13500) && (pov <= 22500);
}
return 0;
@@ -573,25 +584,118 @@ int dinput_api_helper::initialize()
}
-HRESULT dinput_api_helper::enum_attached_devices(int devclass, device_enum_interface *enumerate_interface, void *state) const
+HRESULT dinput_api_helper::enum_attached_devices(int devclass, device_enum_interface &enumerate_interface) const
{
- device_enum_interface::dinput_callback_context ctx;
- ctx.self = enumerate_interface;
- ctx.state = state;
+ return m_dinput->EnumDevices(devclass, device_enum_interface_callback, &enumerate_interface, DIEDFL_ATTACHEDONLY);
+}
+
- return m_dinput->EnumDevices(devclass, device_enum_interface::enum_callback, &ctx, DIEDFL_ATTACHEDONLY);
+std::pair<Microsoft::WRL::ComPtr<IDirectInputDevice8>, LPCDIDATAFORMAT> dinput_api_helper::open_device(
+ LPCDIDEVICEINSTANCE instance,
+ LPCDIDATAFORMAT format1,
+ LPCDIDATAFORMAT format2,
+ dinput_cooperative_level cooperative_level)
+{
+ HRESULT result;
+
+ // attempt to create a device
+ Microsoft::WRL::ComPtr<IDirectInputDevice8> device;
+ result = m_dinput->CreateDevice(instance->guidInstance, device.GetAddressOf(), nullptr);
+ if (result != DI_OK)
+ {
+ osd_printf_error("DirectInput: Unable to create device.\n");
+ return std::make_pair(nullptr, nullptr);
+ }
+
+ // attempt to set the data format
+ LPCDIDATAFORMAT format = format1;
+ result = device->SetDataFormat(format);
+ if ((result != DI_OK) && format2)
+ {
+ // use the secondary format if available
+ osd_printf_verbose("DirectInput: Error setting primary data format, trying secondary format.\n");
+ format = format2;
+ result = device->SetDataFormat(format);
+ }
+ if (result != DI_OK)
+ {
+ osd_printf_error("DirectInput: Unable to set data format.\n");
+ return std::make_pair(nullptr, nullptr);
+ }
+
+ // default window to the first window in the list
+ HWND window_handle;
+ DWORD di_cooperative_level;
+#if defined(OSD_WINDOWS)
+ auto const window = std::static_pointer_cast<win_window_info>(osd_common_t::s_window_list.front());
+ bool const standalone_window = window && !window->attached_mode();
+#elif defined(SDLMAME_WIN32)
+ auto const window = std::static_pointer_cast<sdl_window_info>(osd_common_t::s_window_list.front());
+ bool const standalone_window = bool(window);
+#endif
+ if (!standalone_window)
+ {
+ // in attached mode we have to ignore the caller and hook up to the desktop window
+ window_handle = GetDesktopWindow();
+ di_cooperative_level = DISCL_BACKGROUND | DISCL_NONEXCLUSIVE;
+ }
+ else
+ {
+#if defined(OSD_WINDOWS)
+ window_handle = window->platform_window();
+#elif defined(SDLMAME_WIN32)
+ auto const sdlwindow = window->platform_window();
+ SDL_SysWMinfo info;
+ SDL_VERSION(&info.version);
+ SDL_GetWindowWMInfo(sdlwindow, &info);
+ window_handle = info.info.win.window;
+#endif
+ switch (cooperative_level)
+ {
+ case dinput_cooperative_level::BACKGROUND:
+ di_cooperative_level = DISCL_BACKGROUND | DISCL_NONEXCLUSIVE;
+ break;
+ case dinput_cooperative_level::FOREGROUND:
+ di_cooperative_level = DISCL_FOREGROUND | DISCL_NONEXCLUSIVE;
+ break;
+ default:
+ throw false;
+ }
+ }
+
+ // set the cooperative level
+ result = device->SetCooperativeLevel(window_handle, di_cooperative_level);
+ if (result != DI_OK)
+ {
+ osd_printf_error("DirectInput: Unable to set cooperative level.\n");
+ return std::make_pair(nullptr, nullptr);
+ }
+
+ // return new device
+ return std::make_pair(std::move(device), format);
}
-#else // defined(OSD_WINDOWS)
+} // namespace osd
+
+
+#else // defined(OSD_WINDOWS) || defined(SDLMAME_WIN32)
#include "input_module.h"
+namespace osd {
+
+namespace {
+
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 // defined(OSD_WINDOWS)
+} // anonymous namespace
+
+} // namespace osd
+
+#endif // defined(OSD_WINDOWS) || defined(SDLMAME_WIN32)
-MODULE_DEFINITION(KEYBOARDINPUT_DINPUT, keyboard_input_dinput)
-MODULE_DEFINITION(MOUSEINPUT_DINPUT, mouse_input_dinput)
-MODULE_DEFINITION(JOYSTICKINPUT_DINPUT, joystick_input_dinput)
+MODULE_DEFINITION(KEYBOARDINPUT_DINPUT, osd::keyboard_input_dinput)
+MODULE_DEFINITION(MOUSEINPUT_DINPUT, osd::mouse_input_dinput)
+MODULE_DEFINITION(JOYSTICKINPUT_DINPUT, osd::joystick_input_dinput)