From 38aa485f8f0ae6105ffe1905133966b06b77fe15 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Tue, 30 Jun 2020 02:47:47 +1000 Subject: [PATCH] libretro: Analog controller/DualShock support --- .../libretro_d3d11_host_display.cpp | 4 +- .../libretro_host_interface.cpp | 50 ++++++++++++++++++- .../libretro_host_interface.h | 1 + 3 files changed, 51 insertions(+), 4 deletions(-) diff --git a/src/duckstation-libretro/libretro_d3d11_host_display.cpp b/src/duckstation-libretro/libretro_d3d11_host_display.cpp index b153c90f4..e4004f48c 100644 --- a/src/duckstation-libretro/libretro_d3d11_host_display.cpp +++ b/src/duckstation-libretro/libretro_d3d11_host_display.cpp @@ -42,8 +42,8 @@ bool LibretroD3D11HostDisplay::CreateRenderDevice(const WindowInfo& wi, std::str else if (ri->interface_type != RETRO_HW_RENDER_INTERFACE_D3D11 || ri->interface_version != RETRO_HW_RENDER_INTERFACE_D3D11_VERSION) { - Log_ErrorPrint("Unexpected HW interface - type %u version %u", static_cast(ri->interface_type), - static_cast(ri->interface_version)); + Log_ErrorPrintf("Unexpected HW interface - type %u version %u", static_cast(ri->interface_type), + static_cast(ri->interface_version)); return false; } diff --git a/src/duckstation-libretro/libretro_host_interface.cpp b/src/duckstation-libretro/libretro_host_interface.cpp index a7000fffa..7ee605f46 100644 --- a/src/duckstation-libretro/libretro_host_interface.cpp +++ b/src/duckstation-libretro/libretro_host_interface.cpp @@ -544,9 +544,13 @@ void LibretroHostInterface::UpdateControllers() UpdateControllersDigitalController(i); break; + case ControllerType::AnalogController: + UpdateControllersAnalogController(i); + break; + default: - Log_ErrorPrintf("Unhandled controller type '%s'", - Settings::GetControllerTypeDisplayName(m_settings.controller_types[i])); + ReportFormattedError("Unhandled controller type '%s'.", + Settings::GetControllerTypeDisplayName(m_settings.controller_types[i])); break; } } @@ -580,6 +584,48 @@ void LibretroHostInterface::UpdateControllersDigitalController(u32 index) } } +void LibretroHostInterface::UpdateControllersAnalogController(u32 index) +{ + AnalogController* controller = static_cast(m_system->GetController(index)); + DebugAssert(controller); + + static constexpr std::array, 16> button_mapping = { + {{AnalogController::Button::Left, RETRO_DEVICE_ID_JOYPAD_LEFT}, + {AnalogController::Button::Right, RETRO_DEVICE_ID_JOYPAD_RIGHT}, + {AnalogController::Button::Up, RETRO_DEVICE_ID_JOYPAD_UP}, + {AnalogController::Button::Down, RETRO_DEVICE_ID_JOYPAD_DOWN}, + {AnalogController::Button::Circle, RETRO_DEVICE_ID_JOYPAD_A}, + {AnalogController::Button::Cross, RETRO_DEVICE_ID_JOYPAD_B}, + {AnalogController::Button::Triangle, RETRO_DEVICE_ID_JOYPAD_X}, + {AnalogController::Button::Square, RETRO_DEVICE_ID_JOYPAD_Y}, + {AnalogController::Button::Start, RETRO_DEVICE_ID_JOYPAD_START}, + {AnalogController::Button::Select, RETRO_DEVICE_ID_JOYPAD_SELECT}, + {AnalogController::Button::L1, RETRO_DEVICE_ID_JOYPAD_L}, + {AnalogController::Button::L2, RETRO_DEVICE_ID_JOYPAD_L2}, + {AnalogController::Button::L3, RETRO_DEVICE_ID_JOYPAD_L3}, + {AnalogController::Button::R1, RETRO_DEVICE_ID_JOYPAD_R}, + {AnalogController::Button::R2, RETRO_DEVICE_ID_JOYPAD_R2}, + {AnalogController::Button::Analog, RETRO_DEVICE_ID_JOYPAD_R3}}}; + + static constexpr std::array>, 4> axis_mapping = { + {{AnalogController::Axis::LeftX, {RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X}}, + {AnalogController::Axis::LeftY, {RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y}}, + {AnalogController::Axis::RightX, {RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X}}, + {AnalogController::Axis::RightY, {RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y}}}}; + + for (const auto& it : button_mapping) + { + const int16_t state = g_retro_input_state_callback(index, RETRO_DEVICE_JOYPAD, 0, it.second); + controller->SetButtonState(it.first, state != 0); + } + + for (const auto& it : axis_mapping) + { + const int16_t state = g_retro_input_state_callback(index, RETRO_DEVICE_ANALOG, it.second.first, it.second.second); + controller->SetAxisState(static_cast(it.first), std::clamp(static_cast(state) / 32767.0f, -1.0f, 1.0f)); + } +} + static std::optional RetroHwContextToRenderer(retro_hw_context_type type) { switch (type) diff --git a/src/duckstation-libretro/libretro_host_interface.h b/src/duckstation-libretro/libretro_host_interface.h index 1296efca6..11ecea47a 100644 --- a/src/duckstation-libretro/libretro_host_interface.h +++ b/src/duckstation-libretro/libretro_host_interface.h @@ -46,6 +46,7 @@ private: void UpdateSettings(); void UpdateControllers(); void UpdateControllersDigitalController(u32 index); + void UpdateControllersAnalogController(u32 index); void GetSystemAVInfo(struct retro_system_av_info* info, bool use_resolution_scale); void UpdateSystemAVInfo(bool use_resolution_scale); void UpdateGeometry();