diff --git a/README.md b/README.md index f128b429e..797d40801 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ A "BIOS" ROM image is required to to start the emulator and to play games. You c ## Latest News +- 2020/10/30: Option to use analog stick as d-pad for analog controller added. - 2020/10/20: New cheat manager with memory scanning added. More features will be added over time. - 2020/10/05: CD-ROM read speedup enhancement added. - 2020/09/30: CPU overclocking is now supported. Use with caution as it will break games and increase system requirements. It can be set globally or per-game. diff --git a/src/core/analog_controller.cpp b/src/core/analog_controller.cpp index e070565af..3bda73217 100644 --- a/src/core/analog_controller.cpp +++ b/src/core/analog_controller.cpp @@ -189,6 +189,25 @@ void AnalogController::SetMotorState(u8 motor, u8 value) m_motor_state[motor] = value; } +u8 AnalogController::GetExtraButtonMaskLSB() const +{ + if (!m_analog_dpad_in_digital_mode) + return 0xFF; + + static constexpr u8 NEG_THRESHOLD = static_cast(128.0f - (127.0 * 0.5f)); + static constexpr u8 POS_THRESHOLD = static_cast(128.0f + (127.0 * 0.5f)); + + const bool left = (m_axis_state[static_cast(Axis::LeftX)] <= NEG_THRESHOLD); + const bool right = (m_axis_state[static_cast(Axis::LeftX)] >= POS_THRESHOLD); + const bool up = (m_axis_state[static_cast(Axis::LeftY)] <= NEG_THRESHOLD); + const bool down = (m_axis_state[static_cast(Axis::LeftY)] >= POS_THRESHOLD); + + return ~((static_cast(left) << static_cast(Button::Left)) | + (static_cast(right) << static_cast(Button::Right)) | + (static_cast(up) << static_cast(Button::Up)) | + (static_cast(down) << static_cast(Button::Down))); +} + bool AnalogController::Transfer(const u8 data_in, u8* data_out) { bool ack; @@ -284,7 +303,7 @@ bool AnalogController::Transfer(const u8 data_in, u8* data_out) if (m_rumble_unlocked) SetMotorState(1, ((data_in & 0x01) != 0) ? 255 : 0); - *data_out = Truncate8(m_button_state); + *data_out = Truncate8(m_button_state) & GetExtraButtonMaskLSB(); m_state = State::GetStateButtonsMSB; ack = true; } @@ -511,10 +530,15 @@ u32 AnalogController::StaticGetVibrationMotorCount() Controller::SettingList AnalogController::StaticGetSettings() { - static constexpr std::array settings = { + static constexpr std::array settings = { {{SettingInfo::Type::Boolean, "AutoEnableAnalog", TRANSLATABLE("AnalogController", "Enable Analog Mode on Reset"), TRANSLATABLE("AnalogController", "Automatically enables analog mode when the console is reset/powered on."), "false"}, + {SettingInfo::Type::Boolean, "AnalogDPadInDigitalMode", + TRANSLATABLE("AnalogController", "Use Analog Sticks for D-Pad in Digital Mode"), + TRANSLATABLE("AnalogController", + "Allows you to use the analog sticks to control the d-pad in digital mode, as well as the buttons."), + "false"}, {SettingInfo::Type::Float, "AxisScale", TRANSLATABLE("AnalogController", "Analog Axis Scale"), TRANSLATABLE( "AnalogController", @@ -533,6 +557,7 @@ void AnalogController::LoadSettings(const char* section) { Controller::LoadSettings(section); m_auto_enable_analog = g_host_interface->GetBoolSettingValue(section, "AutoEnableAnalog", false); + m_analog_dpad_in_digital_mode = g_host_interface->GetBoolSettingValue(section, "AnalogDPadInDigitalMode", false); m_rumble_bias = static_cast(std::min(g_host_interface->GetIntSettingValue(section, "VibrationBias", 8), 255)); } diff --git a/src/core/analog_controller.h b/src/core/analog_controller.h index c4995b1a1..7b04b1390 100644 --- a/src/core/analog_controller.h +++ b/src/core/analog_controller.h @@ -131,10 +131,12 @@ private: u16 GetID() const; void SetAnalogMode(bool enabled); void SetMotorState(u8 motor, u8 value); + u8 GetExtraButtonMaskLSB() const; u32 m_index; bool m_auto_enable_analog = false; + bool m_analog_dpad_in_digital_mode = false; u8 m_rumble_bias = 8; bool m_analog_mode = false; diff --git a/src/duckstation-libretro/libretro_host_interface.cpp b/src/duckstation-libretro/libretro_host_interface.cpp index c487d9c3b..e40fb1a82 100644 --- a/src/duckstation-libretro/libretro_host_interface.cpp +++ b/src/duckstation-libretro/libretro_host_interface.cpp @@ -457,7 +457,7 @@ void LibretroHostInterface::OnSystemDestroyed() m_using_hardware_renderer = false; } -static std::array s_option_definitions = {{ +static std::array s_option_definitions = {{ {"duckstation_Console.Region", "Console Region", "Determines which region/hardware to emulate. Auto-Detect will use the region of the disc inserted.", @@ -681,6 +681,11 @@ static std::array s_option_definitions = {{ "Automatically enables analog mode in supported controllers at start/reset.", {{"true", "Enabled"}, {"false", "Disabled"}}, "false"}, + {"duckstation_Controller1.AutoEnableAnalog", + "Controller 1 Use Analog Sticks for D-Pad in Digital Mode", + "Allows you to use the analog sticks to control the d-pad in digital mode, as well as the buttons.", + {{"true", "Enabled"}, {"false", "Disabled"}}, + "false"}, {"duckstation_Controller2.Type", "Controller 2 Type", "Sets the type of controller for Slot 2.", @@ -696,6 +701,11 @@ static std::array s_option_definitions = {{ "Automatically enables analog mode in supported controllers at start/reset.", {{"true", "Enabled"}, {"false", "Disabled"}}, "false"}, + {"duckstation_Controller2.AutoEnableAnalog", + "Controller 2 Use Analog Sticks for D-Pad in Digital Mode", + "Allows you to use the analog sticks to control the d-pad in digital mode, as well as the buttons.", + {{"true", "Enabled"}, {"false", "Disabled"}}, + "false"}, {"duckstation_Display.ShowOSDMessages", "Display OSD Messages", "Shows on-screen messages generated by the core.",