diff options
Diffstat (limited to 'src/osd/modules/input/input_uwp.cpp')
-rw-r--r-- | src/osd/modules/input/input_uwp.cpp | 649 |
1 files changed, 0 insertions, 649 deletions
diff --git a/src/osd/modules/input/input_uwp.cpp b/src/osd/modules/input/input_uwp.cpp deleted file mode 100644 index 6b3b8675cff..00000000000 --- a/src/osd/modules/input/input_uwp.cpp +++ /dev/null @@ -1,649 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Brad Hughes -//============================================================ -// -// input_uwp.cpp - UWP input implementation -// -//============================================================ - -#include "input_module.h" -#include "modules/osdmodule.h" - -#if defined(OSD_UWP) - -#include <agile.h> -#include <ppltasks.h> -#include <collection.h> -#undef interface - -// 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 -//============================================================ - -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: - 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) - { - } - - void poll() override - { - m_wrapped_device->Poll(); - } - - void reset() override - { - m_wrapped_device->Reset(); - } -}; - -//============================================================ -// 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 - { - m_refmodule->input_init(machine); - } -}; - -//============================================================ -// UWP Keyboard Implementation -//============================================================ - -//============================================================ -// UwpKeyboardDevice -//============================================================ - -private ref class UwpKeyboardDevice : public UwpInputDevice -{ -private: - keyboard_state keyboard; - Platform::Agile<CoreWindow> m_coreWindow; - std::mutex m_state_lock; - -internal: - UwpKeyboardDevice(Platform::Agile<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) - { - coreWindow->Dispatcher->AcceleratorKeyActivated += ref new TypedEventHandler<CoreDispatcher^, AcceleratorKeyEventArgs^>(this, &UwpKeyboardDevice::OnAcceleratorKeyActivated); - 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 Reset() override - { - std::lock_guard<std::mutex> scope_lock(m_state_lock); - memset(&keyboard, 0, sizeof(keyboard)); - } - - void Configure() - { - keyboard_trans_table &table = keyboard_trans_table::instance(); - - // populate it indexed by the scancode - for (int keynum = KEY_UNKNOWN + 1; keynum < MAX_KEYS; keynum++) - { - input_item_id itemid = table.map_di_scancode_to_itemid(keynum); - const char *keyname = table.ui_label_for_mame_key(itemid); - - char temp[256]; - if (keyname == nullptr) - { - snprintf(temp, ARRAY_LENGTH(temp), "Scan%03d", keynum); - keyname = temp; - } - - // 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) - { - std::lock_guard<std::mutex> scope_lock(m_state_lock); - CorePhysicalKeyStatus status = args->KeyStatus; - int discancode = (status.ScanCode & 0x7f) | (status.IsExtendedKey ? 0x80 : 0x00); - keyboard.state[discancode] = 0x80; - } - - void OnKeyUp(CoreWindow^ win, KeyEventArgs^ args) - { - std::lock_guard<std::mutex> scope_lock(m_state_lock); - CorePhysicalKeyStatus status = args->KeyStatus; - int discancode = (status.ScanCode & 0x7f) | (status.IsExtendedKey ? 0x80 : 0x00); - keyboard.state[discancode] = 0; - } - - void OnCharacterReceived(CoreWindow ^sender, CharacterReceivedEventArgs ^args) - { - this->Machine.ui_input().push_char_event(osd_common_t::s_window_list.front()->target(), args->KeyCode); - } - - void OnAcceleratorKeyActivated(CoreDispatcher ^sender, AcceleratorKeyEventArgs ^args) - { - std::lock_guard<std::mutex> scope_lock(m_state_lock); - auto eventType = args->EventType; - if (eventType == CoreAcceleratorKeyEventType::SystemKeyDown || - eventType == CoreAcceleratorKeyEventType::SystemKeyUp) - { - CorePhysicalKeyStatus status = args->KeyStatus; - int discancode = (status.ScanCode & 0x7f) | (status.IsExtendedKey ? 0x80 : 0x00); - keyboard.state[discancode] = - eventType == CoreAcceleratorKeyEventType::SystemKeyDown ? 0x80 : 0; - } - } -}; - -//============================================================ -// UwpKeyboardModule -//============================================================ - -private ref class UwpKeyboardModule : public UwpInputModule -{ -private: - running_machine *m_machine; - -internal: - UwpKeyboardModule() - : UwpInputModule(OSD_KEYBOARDINPUT_PROVIDER, "uwp") - { - } - - void input_init(running_machine &machine) override - { - auto first_window = std::static_pointer_cast<uwp_window_info>(osd_common_t::s_window_list.front()); - auto coreWindow = first_window->platform_window(); - - // allocate the UWP implementation of the device object - UwpKeyboardDevice ^refdevice = ref new UwpKeyboardDevice(coreWindow, machine, "UWP Keyboard 1", "UWP Keyboard 1", *this->NativeModule); - - // Allocate the wrapper and add it to the list - auto created_devinfo = std::make_unique<uwp_input_device>(refdevice); - uwp_input_device *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++) - { - GamepadButtons currentButton = GamepadButtons(1 << butnum); - state.buttons[butnum] = (reading.Buttons & currentButton) != GamepadButtons::None ? 0xFF : 0; - } - - // 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); - - // 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); - - // For the UI, triggering UI_CONFIGURE is odd. It requires a EVENT_CHAR first - static constexpr int menuhotkey = (int)(GamepadButtons::View | GamepadButtons::X); - if (((int)reading.Buttons & menuhotkey) == menuhotkey) - { - ui_event uiev; - memset(&uiev, 0, sizeof(uiev)); - uiev.event_type = ui_event::IME_CHAR; - this->Machine.ui_input().push_event(uiev); - } - } - - void Reset() override - { - memset(&state, 0, sizeof(state)); - } - - 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 -{ -private: - boolean m_joysticks_discovered; - -internal: - UwpJoystickModule() - : UwpInputModule(OSD_JOYSTICKINPUT_PROVIDER, "uwp"), - m_joysticks_discovered(false) - { - } - - 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++; - }); - } - -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(1000)) - CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); - - m_joysticks_discovered = true; - } - - void OnGamepadAdded(Platform::Object ^sender, Gamepad ^pad) - { - if (m_joysticks_discovered) - { - osd_printf_error("Input: UWP Compatible %s gamepad plugged in AFTER discovery complete!\n", pad->IsWireless ? "Wireless" : "Wired"); - } - else - { - 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()) - { - } -}; - -#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) |