summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd/modules/input
diff options
context:
space:
mode:
author Brad Hughes <bradhugh@outlook.com>2016-11-14 21:06:42 -0500
committer Brad Hughes <bradhugh@outlook.com>2016-11-14 21:06:42 -0500
commit0f060802b5308bf79edd34b78063548c34e57df4 (patch)
tree13eb69261b19080a14a99db8277615a640508360 /src/osd/modules/input
parent00cb2804918480d288e7ca02961698d5a15e76bb (diff)
UWP: Enable gamepad support and update keyboard support (nw)
Diffstat (limited to 'src/osd/modules/input')
-rw-r--r--src/osd/modules/input/input_common.cpp14
-rw-r--r--src/osd/modules/input/input_common.h22
-rw-r--r--src/osd/modules/input/input_uwp.cpp565
3 files changed, 529 insertions, 72 deletions
diff --git a/src/osd/modules/input/input_common.cpp b/src/osd/modules/input/input_common.cpp
index e9844d99291..50500aea82e 100644
--- a/src/osd/modules/input/input_common.cpp
+++ b/src/osd/modules/input/input_common.cpp
@@ -37,8 +37,8 @@
#define KEY_TRANS_ENTRY0(mame, sdlsc, sdlkey, disc, virtual, uwp, ascii, UI) { ITEM_ID_##mame, SDL_SCANCODE_ ## sdlsc, SDLK_ ## sdlkey, ascii, "ITEM_ID_"#mame, (char *) UI }
#define KEY_TRANS_ENTRY1(mame, sdlsc, sdlkey, disc, virtual, uwp, ascii) { ITEM_ID_##mame, SDL_SCANCODE_ ## sdlsc, SDLK_ ## sdlkey, ascii, "ITEM_ID_"#mame, (char*) #mame }
#elif defined(OSD_UWP)
-#define KEY_TRANS_ENTRY0(mame, sdlsc, sdlkey, disc, virtual, uwp, ascii, UI) { ITEM_ID_##mame, Windows::System::VirtualKey:: ## uwp, ascii, "ITEM_ID_"#mame, (char *) UI }
-#define KEY_TRANS_ENTRY1(mame, sdlsc, sdlkey, disc, virtual, uwp, ascii) { ITEM_ID_##mame, Windows::System::VirtualKey:: ## uwp, ascii, "ITEM_ID_"#mame, (char*) #mame }
+#define KEY_TRANS_ENTRY0(mame, sdlsc, sdlkey, disc, virtual, uwp, ascii, UI) { ITEM_ID_##mame, KEY_ ## disc, Windows::System::VirtualKey:: ## uwp, ascii, "ITEM_ID_"#mame, (char *) UI }
+#define KEY_TRANS_ENTRY1(mame, sdlsc, sdlkey, disc, virtual, uwp, ascii) { ITEM_ID_##mame, KEY_ ## disc, Windows::System::VirtualKey:: ## uwp, ascii, "ITEM_ID_"#mame, (char*) #mame }
#else
// osd mini
#endif
@@ -227,7 +227,7 @@ input_item_id keyboard_trans_table::lookup_mame_code(const char *scode) const
}
// Windows specific lookup methods
-#if defined(OSD_WINDOWS)
+#if defined(OSD_WINDOWS) || defined(OSD_UWP)
input_item_id keyboard_trans_table::map_di_scancode_to_itemid(int scancode) const
{
@@ -242,6 +242,10 @@ input_item_id keyboard_trans_table::map_di_scancode_to_itemid(int scancode) cons
return ITEM_ID_OTHER_SWITCH;
}
+#endif
+
+#if defined(OSD_WINDOWS)
+
//============================================================
// wininput_vkey_for_mame_code
//============================================================
@@ -262,7 +266,9 @@ int keyboard_trans_table::vkey_for_mame_code(input_code code) const
return 0;
}
-#elif defined(OSD_UWP)
+#endif
+
+#if defined(OSD_UWP)
input_item_id keyboard_trans_table::map_vkey_to_itemid(Windows::System::VirtualKey vkey) const
{
diff --git a/src/osd/modules/input/input_common.h b/src/osd/modules/input/input_common.h
index e2df2593b2d..10dbf85d023 100644
--- a/src/osd/modules/input/input_common.h
+++ b/src/osd/modules/input/input_common.h
@@ -337,6 +337,12 @@ public:
// allocate the device object
auto devinfo = std::make_unique<TActual>(machine, name, id, module, std::forward<TArgs>(args)...);
+ return add_device(machine, std::move(devinfo));
+ }
+
+ template <typename TActual>
+ TActual* add_device(running_machine &machine, std::unique_ptr<TActual> devinfo)
+ {
// Add the device to the machine
devinfo->m_device = machine.input().device_class(devinfo->deviceclass()).add_device(devinfo->name(), devinfo->id(), devinfo.get());
@@ -359,6 +365,7 @@ struct key_trans_entry {
int scan_code;
unsigned char virtual_key;
#elif defined(OSD_UWP)
+ int scan_code;
Windows::System::VirtualKey virtual_key;
#endif
@@ -394,6 +401,7 @@ public:
input_item_id map_di_scancode_to_itemid(int di_scancode) const;
int vkey_for_mame_code(input_code code) const;
#elif defined(OSD_UWP)
+ input_item_id map_di_scancode_to_itemid(int di_scancode) const;
input_item_id map_vkey_to_itemid(Windows::System::VirtualKey vkey) const;
#endif
@@ -564,26 +572,26 @@ const char *const default_axis_name[] =
"RY", "RZ", "SL1", "SL2"
};
-inline static int32_t normalize_absolute_axis(int32_t raw, int32_t rawmin, int32_t rawmax)
+inline static int32_t normalize_absolute_axis(double raw, double rawmin, double rawmax)
{
- int32_t center = (rawmax + rawmin) / 2;
+ double center = (rawmax + rawmin) / 2.0;
// make sure we have valid data
if (rawmin >= rawmax)
- return raw;
+ return int32_t(raw);
// above center
if (raw >= center)
{
- int32_t result = (int64_t)(raw - center) * (int64_t)INPUT_ABSOLUTE_MAX / (int64_t)(rawmax - center);
- return std::min(result, INPUT_ABSOLUTE_MAX);
+ double result = (raw - center) * INPUT_ABSOLUTE_MAX / (rawmax - center);
+ return std::min(result, (double)INPUT_ABSOLUTE_MAX);
}
// below center
else
{
- int32_t result = -((int64_t)(center - raw) * (int64_t)-INPUT_ABSOLUTE_MIN / (int64_t)(center - rawmin));
- return std::max(result, INPUT_ABSOLUTE_MIN);
+ double result = -((center - raw) * (double)-INPUT_ABSOLUTE_MIN / (center - rawmin));
+ return std::max(result, (double)INPUT_ABSOLUTE_MIN);
}
}
diff --git a/src/osd/modules/input/input_uwp.cpp b/src/osd/modules/input/input_uwp.cpp
index 7291e3e2a71..bee9e2367ee 100644
--- a/src/osd/modules/input/input_uwp.cpp
+++ b/src/osd/modules/input/input_uwp.cpp
@@ -21,141 +21,584 @@
// MAME headers
#include "emu.h"
#include "uiinput.h"
+#include "strconv.h"
// MAMEOS headers
#include "winmain.h"
#include "input_common.h"
#include "input_windows.h"
+#define UWP_BUTTON_COUNT 32
+
using namespace concurrency;
using namespace Windows::UI::Core;
using namespace Windows::Foundation;
using namespace Windows::Foundation::Collections;
+using namespace Windows::Gaming::Input;
+
+//============================================================
+// UWP Base device/module implementation
+//============================================================
+
+//============================================================
+// UwpInputDevice - base class for implementing an input
+// device in C++/CX. To be used with uwp_input_device
+//============================================================
-// This device is purely event driven so the implementation is in the module
-class uwp_keyboard_device : public event_based_device<KeyPressEventArgs>
+private ref class UwpInputDevice
{
+private:
+ running_machine & m_machine;
+ std::string m_name;
+ std::string m_id;
+ input_device_class m_devclass;
+ input_module & m_module;
+ input_device *m_inputdevice;
+
+internal:
+ UwpInputDevice(running_machine &machine, const char *name, const char *id, input_device_class deviceclass, input_module &module)
+ : m_machine(machine),
+ m_name(name),
+ m_id(id),
+ m_devclass(deviceclass),
+ m_module(module),
+ m_inputdevice(nullptr)
+ {
+ }
+
+ property running_machine & Machine
+ {
+ running_machine & get() { return m_machine; }
+ }
+
+ property const std::string & Name
+ {
+ const std::string & get() { return m_name; }
+ }
+
+ property const std::string & Id
+ {
+ const std::string & get() { return m_id; }
+ }
+
+ property input_device_class DeviceClass
+ {
+ input_device_class get() { return m_devclass; }
+ }
+
+ property input_module & Module
+ {
+ input_module & get() { return m_module; }
+ }
+
+ property input_device* InputDevice
+ {
+ input_device* get() { return m_inputdevice; }
+ void set(input_device* value) { m_inputdevice = value; }
+ }
+
+ virtual void Poll()
+ {
+ }
+
+ virtual void Reset()
+ {
+ }
+};
+
+//============================================================
+// uwp_input_device - a device that can be used to wrap a
+// C++/CX ref class for an input device implementation
+//============================================================
+
+class uwp_input_device : public device_info
+{
+private:
+ UwpInputDevice ^m_wrapped_device;
+
public:
- keyboard_state keyboard;
+ uwp_input_device(UwpInputDevice ^device)
+ : device_info(device->Machine, device->Name.c_str(), device->Id.c_str(), device->DeviceClass, device->Module),
+ m_wrapped_device(device)
+ {
+ }
- uwp_keyboard_device(running_machine& machine, const char *name, const char *id, input_module &module)
- : event_based_device(machine, name, id, DEVICE_CLASS_KEYBOARD, module),
- keyboard({{0}})
+ void poll() override
{
+ m_wrapped_device->Poll();
}
void reset() override
{
- memset(&keyboard, 0, sizeof(keyboard));
+ m_wrapped_device->Reset();
}
+};
-protected:
- void process_event(KeyPressEventArgs &args) override
+//============================================================
+// UwpInputModule - a base class that can be used to
+// implement an input module with a C++/CX class.
+// normally used with uwp_wininput_module
+//============================================================
+
+class uwp_input_module;
+
+private ref class UwpInputModule
+{
+private:
+ const std::string m_type;
+ const std::string m_name;
+ uwp_input_module *m_module;
+
+internal:
+ UwpInputModule(const char *type, const char *name)
+ : m_type(type),
+ m_name(name),
+ m_module(nullptr)
+ {
+ }
+
+ property const std::string & Type
+ {
+ const std::string & get() { return m_type; }
+ }
+
+ property const std::string & Name
+ {
+ const std::string & get() { return m_name; }
+ }
+
+ property uwp_input_module * NativeModule
+ {
+ uwp_input_module * get() { return m_module; }
+ void set(uwp_input_module * value) { m_module = value; }
+ }
+
+ virtual void input_init(running_machine &machine)
+ {
+ }
+};
+
+//============================================================
+// uwp_input_module - an input module that can be
+// used to create an input module with a C++/CX ref class
+//============================================================
+
+class uwp_input_module : public wininput_module
+{
+private:
+ UwpInputModule^ m_refmodule;
+
+public:
+ uwp_input_module(UwpInputModule^ refmodule)
+ : wininput_module(refmodule->Type.c_str(), refmodule->Name.c_str()),
+ m_refmodule(refmodule)
+ {
+ refmodule->NativeModule = this;
+ }
+
+ void input_init(running_machine &machine) override
{
- keyboard.state[args.vkey] = args.event_id == INPUT_EVENT_KEYDOWN ? 0x80 : 0x00;
+ m_refmodule->input_init(machine);
}
};
-private ref class key_processor sealed
+//============================================================
+// UWP Keyboard Implementation
+//============================================================
+
+//============================================================
+// UwpKeyboardDevice
+//============================================================
+
+private ref class UwpKeyboardDevice : public UwpInputDevice
{
private:
- Platform::Agile<CoreWindow^> m_window;
- input_device_list &m_devicelist;
- running_machine &m_machine;
+ keyboard_state keyboard;
+ Platform::Agile<CoreWindow> m_coreWindow;
internal:
- key_processor(CoreWindow^ window, input_device_list &devicelist, running_machine &machine)
- : m_window(window),
- m_devicelist(devicelist),
- m_machine(machine)
+ UwpKeyboardDevice(CoreWindow ^coreWindow, running_machine& machine, char *name, const char *id, input_module &module)
+ : UwpInputDevice(machine, name, id, DEVICE_CLASS_KEYBOARD, module),
+ keyboard({{0}}),
+ m_coreWindow(coreWindow)
{
- m_window->KeyDown += ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(this, &key_processor::OnKeyDown);
- m_window->KeyUp += ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(this, &key_processor::OnKeyUp);
- m_window->CharacterReceived += ref new TypedEventHandler<CoreWindow^, CharacterReceivedEventArgs^>(this, &key_processor::OnCharacterReceived);
+ coreWindow->KeyDown += ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(this, &UwpKeyboardDevice::OnKeyDown);
+ coreWindow->KeyUp += ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(this, &UwpKeyboardDevice::OnKeyUp);
+ coreWindow->CharacterReceived += ref new TypedEventHandler<CoreWindow^, CharacterReceivedEventArgs^>(this, &UwpKeyboardDevice::OnCharacterReceived);
}
- void OnKeyDown(CoreWindow^ win, KeyEventArgs^ args)
+ void Reset() override
{
- auto &table = keyboard_trans_table::instance();
+ memset(&keyboard, 0, sizeof(keyboard));
+ }
- //if (args->VirtualKey < Windows::System::VirtualKey::Space)
- // m_machine.ui_input().push_char_event(osd_common_t::s_window_list.front()->target(), static_cast<char32_t>(args->VirtualKey));
+ void Configure()
+ {
+ keyboard_trans_table &table = keyboard_trans_table::instance();
+
+ char keyname[256];
- KeyPressEventArgs tmp;
- tmp.event_id = INPUT_EVENT_KEYDOWN;
- tmp.vkey = uint8_t(args->VirtualKey);
- m_devicelist.for_each_device([&tmp](device_info *device)
+ // populate it
+ for (int keynum = 0; keynum < MAX_KEYS; keynum++)
{
- static_cast<uwp_keyboard_device*>(device)->queue_events(&tmp, 1);
- });
+ input_item_id itemid = table.map_di_scancode_to_itemid(keynum);
+
+ //if (GetKeyNameTextA(((keynum & 0x7f) << 16) | ((keynum & 0x80) << 17), keyname, ARRAY_LENGTH(keyname)) == 0)
+ snprintf(keyname, ARRAY_LENGTH(keyname), "Scan%03d", keynum);
+
+ // add the item to the device
+ this->InputDevice->add_item(keyname, itemid, generic_button_get_state<std::uint8_t>, &keyboard.state[keynum]);
+ }
+ }
+
+ void OnKeyDown(CoreWindow^ win, KeyEventArgs^ args)
+ {
+ CorePhysicalKeyStatus status = args->KeyStatus;
+ int discancode = (status.ScanCode & 0x7f) | (status.IsExtendedKey ? 0x80 : 0x00);
+ keyboard.state[discancode] = 0x80;
}
void OnKeyUp(CoreWindow^ win, KeyEventArgs^ args)
{
- KeyPressEventArgs tmp;
- tmp.event_id = INPUT_EVENT_KEYUP;
- tmp.vkey = uint8_t(args->VirtualKey);
- m_devicelist.for_each_device([&tmp](device_info *device)
- {
- static_cast<uwp_keyboard_device*>(device)->queue_events(&tmp, 1);
- });
+ CorePhysicalKeyStatus status = args->KeyStatus;
+ int discancode = (status.ScanCode & 0x7f) | (status.IsExtendedKey ? 0x80 : 0x00);
+ keyboard.state[discancode] = 0;
}
void OnCharacterReceived(CoreWindow ^sender, CharacterReceivedEventArgs ^args)
{
- m_machine.ui_input().push_char_event(osd_common_t::s_window_list.front()->target(), args->KeyCode);
+ this->Machine.ui_input().push_char_event(osd_common_t::s_window_list.front()->target(), args->KeyCode);
}
};
//============================================================
-// uwp_keyboard_module
+// UwpKeyboardModule
//============================================================
-class uwp_keyboard_module : public wininput_module
+private ref class UwpKeyboardModule : public UwpInputModule
{
private:
- key_processor^ m_key_processor;
+ running_machine *m_machine;
-public:
- uwp_keyboard_module()
- : wininput_module(OSD_KEYBOARDINPUT_PROVIDER, "uwp"),
- m_key_processor(nullptr)
+internal:
+ UwpKeyboardModule()
+ : UwpInputModule(OSD_KEYBOARDINPUT_PROVIDER, "uwp")
{
}
- virtual void input_init(running_machine &machine) override
+ void input_init(running_machine &machine) override
{
auto first_window = std::static_pointer_cast<uwp_window_info>(osd_common_t::s_window_list.front());
- m_key_processor = ref new key_processor(first_window->uwp_window(), *devicelist(), machine);
+ CoreWindow ^coreWindow = first_window->uwp_window();
- // Add a single UWP keyboard device
- uwp_keyboard_device *devinfo = devicelist()->create_device<uwp_keyboard_device>(machine, "UWP Keyboard 1", "UWP Keyboard 1", *this);
+ uwp_input_device *devinfo;
- keyboard_trans_table &table = keyboard_trans_table::instance();
+ // allocate the UWP implementation of the device object
+ UwpKeyboardDevice ^refdevice = ref new UwpKeyboardDevice(coreWindow, machine, "UWP Keyboard 1", "UWP Keyboard 1", *this->NativeModule);
- // populate it
- for (int keynum = 0; keynum < MAX_KEYS; keynum++)
+ // Allocate the wrapper and add it to the list
+ auto created_devinfo = std::make_unique<uwp_input_device>(refdevice);
+ devinfo = NativeModule->devicelist()->add_device<uwp_input_device>(machine, std::move(created_devinfo));
+
+ // Give the UWP implementation a handle to the input_device
+ refdevice->InputDevice = devinfo->device();
+
+ // Configure the device
+ refdevice->Configure();
+ }
+};
+
+//============================================================
+// uwp_keyboard_module
+//============================================================
+
+class uwp_keyboard_module : public uwp_input_module
+{
+public:
+ uwp_keyboard_module()
+ : uwp_input_module(ref new UwpKeyboardModule())
+ {
+ }
+};
+
+// default axis names
+static const char *const uwp_axis_name[] =
+{
+ "LSX",
+ "LSY",
+ "RSX",
+ "RSY"
+};
+
+static const input_item_id uwp_axis_ids[] =
+{
+ ITEM_ID_XAXIS,
+ ITEM_ID_YAXIS,
+ ITEM_ID_RXAXIS,
+ ITEM_ID_RYAXIS
+};
+
+struct gamepad_state
+{
+ BYTE buttons[UWP_BUTTON_COUNT];
+ LONG left_trigger;
+ LONG right_trigger;
+ LONG left_thumb_x;
+ LONG left_thumb_y;
+ LONG right_thumb_x;
+ LONG right_thumb_y;
+};
+
+// Maps different UWP GameControllerButtonLabels to a halfway-sane input_item_id in many cases
+static input_item_id buttonlabel_to_itemid[] =
+{
+ input_item_id::ITEM_ID_INVALID, // GameControllerButtonLabel::None
+ input_item_id::ITEM_ID_SELECT, // GameControllerButtonLabel::XboxBack
+ input_item_id::ITEM_ID_START, // GameControllerButtonLabel::XboxStart
+ input_item_id::ITEM_ID_START, // GameControllerButtonLabel::XboxMenu
+ input_item_id::ITEM_ID_SELECT, // GameControllerButtonLabel::XboxView
+ input_item_id::ITEM_ID_HAT1UP, // GameControllerButtonLabel::XboxUp
+ input_item_id::ITEM_ID_HAT1DOWN, // GameControllerButtonLabel::XboxDown
+ input_item_id::ITEM_ID_HAT1LEFT, // GameControllerButtonLabel::XboxLeft
+ input_item_id::ITEM_ID_HAT1RIGHT, // GameControllerButtonLabel::XboxRight
+ input_item_id::ITEM_ID_BUTTON1, // GameControllerButtonLabel::XboxA
+ input_item_id::ITEM_ID_BUTTON2, // GameControllerButtonLabel::XboxB
+ input_item_id::ITEM_ID_BUTTON3, // GameControllerButtonLabel::XboxX
+ input_item_id::ITEM_ID_BUTTON4, // GameControllerButtonLabel::XboxY
+ input_item_id::ITEM_ID_BUTTON5, // GameControllerButtonLabel::XboxLeftBumper
+ input_item_id::ITEM_ID_ZAXIS, // GameControllerButtonLabel::XboxLeftTrigger
+ input_item_id::ITEM_ID_BUTTON7, // GameControllerButtonLabel::XboxLeftStickButton
+ input_item_id::ITEM_ID_BUTTON6, // GameControllerButtonLabel::XboxRightBumper
+ input_item_id::ITEM_ID_RZAXIS, // GameControllerButtonLabel::XboxRightTrigger
+ input_item_id::ITEM_ID_BUTTON8, // GameControllerButtonLabel::XboxRightStickButton
+ input_item_id::ITEM_ID_BUTTON9, // GameControllerButtonLabel::XboxPaddle1
+ input_item_id::ITEM_ID_BUTTON10, // GameControllerButtonLabel::XboxPaddle2
+ input_item_id::ITEM_ID_BUTTON11, // GameControllerButtonLabel::XboxPaddle3
+ input_item_id::ITEM_ID_BUTTON12, // GameControllerButtonLabel::XboxPaddle4
+ input_item_id::ITEM_ID_INVALID, // GameControllerButtonLabel_Mode
+ input_item_id::ITEM_ID_SELECT, // GameControllerButtonLabel_Select
+ input_item_id::ITEM_ID_START, // GameControllerButtonLabel_Menu
+ input_item_id::ITEM_ID_SELECT, // GameControllerButtonLabel_View
+ input_item_id::ITEM_ID_SELECT, // GameControllerButtonLabel_Back
+ input_item_id::ITEM_ID_START, // GameControllerButtonLabel_Start
+ input_item_id::ITEM_ID_OTHER_SWITCH, // GameControllerButtonLabel_Options
+ input_item_id::ITEM_ID_OTHER_SWITCH, // GameControllerButtonLabel_Share
+ input_item_id::ITEM_ID_OTHER_SWITCH, // GameControllerButtonLabel_Up
+ input_item_id::ITEM_ID_OTHER_SWITCH, // GameControllerButtonLabel_Down
+ input_item_id::ITEM_ID_OTHER_SWITCH, // GameControllerButtonLabel_Left
+ input_item_id::ITEM_ID_OTHER_SWITCH, // GameControllerButtonLabel_Right
+ input_item_id::ITEM_ID_BUTTON1, // GameControllerButtonLabel_LetterA
+ input_item_id::ITEM_ID_BUTTON2, // GameControllerButtonLabel_LetterB
+ input_item_id::ITEM_ID_OTHER_SWITCH, // GameControllerButtonLabel_LetterC
+ input_item_id::ITEM_ID_OTHER_SWITCH, // GameControllerButtonLabel_LetterL
+ input_item_id::ITEM_ID_OTHER_SWITCH, // GameControllerButtonLabel_LetterR
+ input_item_id::ITEM_ID_BUTTON3, // GameControllerButtonLabel_LetterX
+ input_item_id::ITEM_ID_BUTTON4, // GameControllerButtonLabel_LetterY
+ input_item_id::ITEM_ID_OTHER_SWITCH, // GameControllerButtonLabel_LetterZ
+ input_item_id::ITEM_ID_OTHER_SWITCH, // GameControllerButtonLabel_Cross
+ input_item_id::ITEM_ID_OTHER_SWITCH, // GameControllerButtonLabel_Circle
+ input_item_id::ITEM_ID_OTHER_SWITCH, // GameControllerButtonLabel_Square
+ input_item_id::ITEM_ID_OTHER_SWITCH, // GameControllerButtonLabel_Triangle
+ input_item_id::ITEM_ID_BUTTON5, // GameControllerButtonLabel_LeftBumper
+ input_item_id::ITEM_ID_ZAXIS, // GameControllerButtonLabel_LeftTrigger
+ input_item_id::ITEM_ID_BUTTON7, // GameControllerButtonLabel_LeftStickButton
+ input_item_id::ITEM_ID_OTHER_SWITCH, // GameControllerButtonLabel_Left1
+ input_item_id::ITEM_ID_OTHER_SWITCH, // GameControllerButtonLabel_Left2
+ input_item_id::ITEM_ID_OTHER_SWITCH, // GameControllerButtonLabel_Left3
+ input_item_id::ITEM_ID_BUTTON6, // GameControllerButtonLabel_RightBumper
+ input_item_id::ITEM_ID_RZAXIS, // GameControllerButtonLabel_RightTrigger
+ input_item_id::ITEM_ID_BUTTON8, // GameControllerButtonLabel_RightStickButton
+ input_item_id::ITEM_ID_OTHER_SWITCH, // GameControllerButtonLabel_Right1
+ input_item_id::ITEM_ID_OTHER_SWITCH, // GameControllerButtonLabel_Right2
+ input_item_id::ITEM_ID_OTHER_SWITCH, // GameControllerButtonLabel_Right3
+ input_item_id::ITEM_ID_BUTTON9, // GameControllerButtonLabel_Paddle1
+ input_item_id::ITEM_ID_BUTTON10, // GameControllerButtonLabel_Paddle2
+ input_item_id::ITEM_ID_BUTTON11, // GameControllerButtonLabel_Paddle3
+ input_item_id::ITEM_ID_BUTTON12, // GameControllerButtonLabel_Paddle4
+ input_item_id::ITEM_ID_OTHER_SWITCH, // GameControllerButtonLabel_Plus
+ input_item_id::ITEM_ID_OTHER_SWITCH, // GameControllerButtonLabel_Minus
+ input_item_id::ITEM_ID_OTHER_SWITCH, // GameControllerButtonLabel_DownLeftArrow
+ input_item_id::ITEM_ID_OTHER_SWITCH, // GameControllerButtonLabel_DialLeft
+ input_item_id::ITEM_ID_OTHER_SWITCH, // GameControllerButtonLabel_DialRight
+ input_item_id::ITEM_ID_OTHER_SWITCH, // GameControllerButtonLabel_Suspension
+};
+
+//============================================================
+// UwpJoystickDevice
+//============================================================
+
+private ref class UwpJoystickDevice : public UwpInputDevice
+{
+private:
+ Gamepad ^m_pad;
+ bool m_configured;
+ gamepad_state state;
+
+internal:
+ UwpJoystickDevice(Gamepad^ pad, running_machine &machine, const char *name, const char *id, input_module &module)
+ : UwpInputDevice(machine, name, id, DEVICE_CLASS_JOYSTICK, module),
+ m_pad(pad),
+ m_configured(false),
+ state({0})
+ {}
+
+ void Poll() override
+ {
+ // If the device hasn't been configured, don't poll
+ if (!m_configured)
+ return;
+
+ GamepadReading reading = m_pad->GetCurrentReading();
+
+ for (int butnum = 0; butnum < UWP_BUTTON_COUNT; butnum++)
{
- input_item_id itemid = table.map_vkey_to_itemid(Windows::System::VirtualKey(keynum));
- char name[20];
+ GamepadButtons currentButton = GamepadButtons(1 << butnum);
+ state.buttons[butnum] = (reading.Buttons & currentButton) != GamepadButtons::None ? 0xFF : 0;
+ }
- // generate/fetch the name
- _snprintf(name, ARRAY_LENGTH(name), "Scan%03d", keynum);
+ // Now grab the axis values
+ // Each of the thumbstick axis members is a signed value between -32768 and 32767 describing the position of the thumbstick
+ // However, the Y axis values are inverted from what MAME expects, so negate the value
+ state.left_thumb_x = normalize_absolute_axis(reading.LeftThumbstickX, -1, 1);
+ state.left_thumb_y = -normalize_absolute_axis(reading.LeftThumbstickY, -1, 1);
+ state.right_thumb_x = normalize_absolute_axis(reading.RightThumbstickX, -1, 1);
+ state.right_thumb_y = -normalize_absolute_axis(reading.RightThumbstickY, -1, 1);
- // add the item to the device
- devinfo->device()->add_item(name, itemid, generic_button_get_state<std::uint8_t>, &devinfo->keyboard.state[keynum]);
+ // Get the trigger values
+ state.left_trigger = normalize_absolute_axis(reading.LeftTrigger, 0.0, 1.0);
+ state.right_trigger = normalize_absolute_axis(reading.RightTrigger, 0.0, 1.0);
+ }
+
+ void Configure()
+ {
+ // If the device has already been configured, don't do it again
+ if (m_configured)
+ return;
+
+ GamepadReading r = m_pad->GetCurrentReading();
+
+ // Add the axes
+ for (int axisnum = 0; axisnum < 4; axisnum++)
+ {
+ this->InputDevice->add_item(
+ uwp_axis_name[axisnum],
+ uwp_axis_ids[axisnum],
+ generic_axis_get_state<LONG>,
+ &state.left_thumb_x + axisnum);
+ }
+
+ // populate the buttons
+ for (int butnum = 0; butnum < UWP_BUTTON_COUNT; butnum++)
+ {
+ GamepadButtons button = GamepadButtons(1 << butnum);
+ auto label = m_pad->GetButtonLabel(button);
+ if (label != GameControllerButtonLabel::None)
+ {
+ std::string desc = osd::text::from_wstring(label.ToString()->Data());
+ this->InputDevice->add_item(
+ desc.c_str(),
+ buttonlabel_to_itemid[static_cast<int>(label)],
+ generic_button_get_state<BYTE>,
+ &state.buttons[butnum]);
+ }
}
+
+ this->InputDevice->add_item(
+ "Left Trigger",
+ ITEM_ID_ZAXIS,
+ generic_axis_get_state<LONG>,
+ &state.left_trigger);
+
+ this->InputDevice->add_item(
+ "Right Trigger",
+ ITEM_ID_RZAXIS,
+ generic_axis_get_state<LONG>,
+ &state.right_trigger);
+
+ m_configured = true;
+ }
+};
+
+//============================================================
+// UwpJoystickModule
+//============================================================
+
+private ref class UwpJoystickModule : public UwpInputModule
+{
+internal:
+ UwpJoystickModule()
+ : UwpInputModule(OSD_JOYSTICKINPUT_PROVIDER, "uwp")
+ {
+ }
+
+ void input_init(running_machine &machine) override
+ {
+ PerformGamepadDiscovery();
+
+ auto pads = Gamepad::Gamepads;
+
+ int padindex = 0;
+ std::for_each(begin(pads), end(pads), [&](Gamepad^ pad)
+ {
+ uwp_input_device *devinfo;
+
+ std::ostringstream namestream;
+ namestream << "UWP Gamepad " << (padindex + 1);
+
+ auto name = namestream.str();
+
+ // allocate the UWP implementation of the device object
+ UwpJoystickDevice ^refdevice = ref new UwpJoystickDevice(pad, machine, name.c_str(), name.c_str(), *this->NativeModule);
+
+ // Allocate the wrapper and add it to the list
+ auto created_devinfo = std::make_unique<uwp_input_device>(refdevice);
+ devinfo = NativeModule->devicelist()->add_device<uwp_input_device>(machine, std::move(created_devinfo));
+
+ // Give the UWP implementation a handle to the input_device
+ refdevice->InputDevice = devinfo->device();
+
+ // Configure the device
+ refdevice->Configure();
+
+ padindex++;
+ });
}
- void exit() override
+private:
+ void PerformGamepadDiscovery()
+ {
+ Gamepad::GamepadAdded += ref new EventHandler<Gamepad ^>(this, &UwpJoystickModule::OnGamepadAdded);
+ auto start = std::chrono::system_clock::now();
+
+ // We need to pause a bit and pump events so gamepads get discovered
+ while (std::chrono::system_clock::now() - start < std::chrono::milliseconds(500))
+ CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
+ }
+
+ void OnGamepadAdded(Platform::Object ^sender, Gamepad ^pad)
+ {
+ osd_printf_verbose("Input: UWP Compatible %s gamepad discovered.\n", pad->IsWireless ? "Wireless" : "Wired");
+ }
+};
+
+//============================================================
+// uwp_joystick_module
+//============================================================
+
+class uwp_joystick_module : public uwp_input_module
+{
+public:
+ uwp_joystick_module()
+ : uwp_input_module(ref new UwpJoystickModule())
{
- m_key_processor = nullptr;
}
};
#else
MODULE_NOT_SUPPORTED(uwp_keyboard_module, OSD_KEYBOARDINPUT_PROVIDER, "uwp")
+MODULE_NOT_SUPPORTED(uwp_joystick_module, OSD_JOYSTICKINPUT_PROVIDER, "uwp")
#endif
MODULE_DEFINITION(KEYBOARDINPUT_UWP, uwp_keyboard_module)
+MODULE_DEFINITION(JOYSTICKINPUT_UWP, uwp_joystick_module)