duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

playstation_mouse.cpp (6728B)


      1 // SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
      2 // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
      3 
      4 #include "playstation_mouse.h"
      5 #include "gpu.h"
      6 #include "host.h"
      7 #include "system.h"
      8 
      9 #include "util/state_wrapper.h"
     10 
     11 #include "common/assert.h"
     12 #include "common/log.h"
     13 
     14 #include "IconsPromptFont.h"
     15 
     16 #include <array>
     17 
     18 Log_SetChannel(PlayStationMouse);
     19 
     20 static constexpr std::array<u8, static_cast<size_t>(PlayStationMouse::Binding::ButtonCount)> s_button_indices = {
     21   {11, 10}};
     22 
     23 PlayStationMouse::PlayStationMouse(u32 index) : Controller(index)
     24 {
     25 }
     26 
     27 PlayStationMouse::~PlayStationMouse() = default;
     28 
     29 ControllerType PlayStationMouse::GetType() const
     30 {
     31   return ControllerType::PlayStationMouse;
     32 }
     33 
     34 void PlayStationMouse::Reset()
     35 {
     36   m_transfer_state = TransferState::Idle;
     37 }
     38 
     39 bool PlayStationMouse::DoState(StateWrapper& sw, bool apply_input_state)
     40 {
     41   if (!Controller::DoState(sw, apply_input_state))
     42     return false;
     43 
     44   u16 button_state = m_button_state;
     45   float delta_x = m_delta_x;
     46   float delta_y = m_delta_y;
     47   sw.Do(&button_state);
     48   if (sw.GetVersion() >= 60) [[unlikely]]
     49   {
     50     sw.Do(&delta_x);
     51     sw.Do(&delta_y);
     52   }
     53   else
     54   {
     55     u8 dummy = 0;
     56     sw.Do(&dummy);
     57     sw.Do(&dummy);
     58   }
     59 
     60   if (apply_input_state)
     61   {
     62     m_button_state = button_state;
     63     m_delta_x = delta_x;
     64     m_delta_y = delta_y;
     65   }
     66 
     67   sw.Do(&m_transfer_state);
     68   return true;
     69 }
     70 
     71 float PlayStationMouse::GetBindState(u32 index) const
     72 {
     73   if (index >= s_button_indices.size())
     74     return 0.0f;
     75 
     76   const u32 bit = s_button_indices[index];
     77   return static_cast<float>(((m_button_state >> bit) & 1u) ^ 1u);
     78 }
     79 
     80 void PlayStationMouse::SetBindState(u32 index, float value)
     81 {
     82   if (index >= s_button_indices.size())
     83   {
     84     if (index == static_cast<u32>(Binding::PointerX))
     85       m_delta_x += value;
     86     else if (index == static_cast<u32>(Binding::PointerY))
     87       m_delta_y += value;
     88 
     89     return;
     90   }
     91 
     92   if (value >= 0.5f)
     93     m_button_state &= ~(u16(1) << s_button_indices[index]);
     94   else
     95     m_button_state |= u16(1) << s_button_indices[index];
     96 }
     97 
     98 void PlayStationMouse::ResetTransferState()
     99 {
    100   m_transfer_state = TransferState::Idle;
    101 }
    102 
    103 bool PlayStationMouse::Transfer(const u8 data_in, u8* data_out)
    104 {
    105   static constexpr u16 ID = 0x5A12;
    106 
    107   switch (m_transfer_state)
    108   {
    109     case TransferState::Idle:
    110     {
    111       *data_out = 0xFF;
    112 
    113       if (data_in == 0x01)
    114       {
    115         m_transfer_state = TransferState::Ready;
    116         return true;
    117       }
    118       return false;
    119     }
    120 
    121     case TransferState::Ready:
    122     {
    123       if (data_in == 0x42)
    124       {
    125         *data_out = Truncate8(ID);
    126         m_transfer_state = TransferState::IDMSB;
    127         return true;
    128       }
    129 
    130       *data_out = 0xFF;
    131       return false;
    132     }
    133 
    134     case TransferState::IDMSB:
    135     {
    136       *data_out = Truncate8(ID >> 8);
    137       m_transfer_state = TransferState::ButtonsLSB;
    138       return true;
    139     }
    140 
    141     case TransferState::ButtonsLSB:
    142     {
    143       *data_out = Truncate8(m_button_state);
    144       m_transfer_state = TransferState::ButtonsMSB;
    145       return true;
    146     }
    147 
    148     case TransferState::ButtonsMSB:
    149     {
    150       *data_out = Truncate8(m_button_state >> 8);
    151       m_transfer_state = TransferState::DeltaX;
    152       return true;
    153     }
    154 
    155     case TransferState::DeltaX:
    156     {
    157       const float delta_x =
    158         std::clamp(std::floor(m_delta_x * m_sensitivity_x), static_cast<float>(std::numeric_limits<s8>::min()),
    159                    static_cast<float>(std::numeric_limits<s8>::max()));
    160       m_delta_x -= delta_x / m_sensitivity_x;
    161       *data_out = static_cast<s8>(delta_x);
    162       m_transfer_state = TransferState::DeltaY;
    163       return true;
    164     }
    165 
    166     case TransferState::DeltaY:
    167     {
    168       const float delta_y =
    169         std::clamp(std::floor(m_delta_y * m_sensitivity_y), static_cast<float>(std::numeric_limits<s8>::min()),
    170                    static_cast<float>(std::numeric_limits<s8>::max()));
    171       m_delta_y -= delta_y / m_sensitivity_x;
    172       *data_out = static_cast<s8>(delta_y);
    173       m_transfer_state = TransferState::Idle;
    174       return false;
    175     }
    176 
    177     default:
    178     {
    179       UnreachableCode();
    180     }
    181   }
    182 }
    183 
    184 void PlayStationMouse::LoadSettings(SettingsInterface& si, const char* section, bool initial)
    185 {
    186   Controller::LoadSettings(si, section, initial);
    187 
    188   m_sensitivity_x = si.GetFloatValue(section, "SensitivityX", 1.0f);
    189   m_sensitivity_y = si.GetFloatValue(section, "SensitivityY", 1.0f);
    190 }
    191 
    192 std::unique_ptr<PlayStationMouse> PlayStationMouse::Create(u32 index)
    193 {
    194   return std::make_unique<PlayStationMouse>(index);
    195 }
    196 
    197 static const Controller::ControllerBindingInfo s_binding_info[] = {
    198 #define BUTTON(name, display_name, icon_name, button, genb)                                                            \
    199   {                                                                                                                    \
    200     name, display_name, icon_name, static_cast<u32>(button), InputBindingInfo::Type::Button, genb                      \
    201   }
    202 
    203   // clang-format off
    204   { "Pointer", TRANSLATE_NOOP("PlaystationMouse", "Pointer"), ICON_PF_MOUSE_ANY, static_cast<u32>(PlayStationMouse::Binding::PointerX), InputBindingInfo::Type::Pointer, GenericInputBinding::Unknown },
    205   BUTTON("Left", TRANSLATE_NOOP("PlayStationMouse", "Left Button"), ICON_PF_MOUSE_BUTTON_1, PlayStationMouse::Binding::Left, GenericInputBinding::Cross),
    206   BUTTON("Right", TRANSLATE_NOOP("PlayStationMouse", "Right Button"), ICON_PF_MOUSE_BUTTON_2, PlayStationMouse::Binding::Right, GenericInputBinding::Circle),
    207 // clang-format on
    208 
    209 #undef BUTTON
    210 };
    211 static const SettingInfo s_settings[] = {
    212   {SettingInfo::Type::Float, "SensitivityX", TRANSLATE_NOOP("PlayStationMouse", "Horizontal Sensitivity"),
    213    TRANSLATE_NOOP("PlayStationMouse", "Adjusts the correspondance between physical and virtual mouse movement."), "1.0",
    214    "0.01", "2.0", "0.01", "%.0f", nullptr, 100.0f},
    215   {SettingInfo::Type::Float, "SensitivityY", TRANSLATE_NOOP("PlayStationMouse", "Vertical Sensitivity"),
    216    TRANSLATE_NOOP("PlayStationMouse", "Adjusts the correspondance between physical and virtual mouse movement."), "1.0",
    217    "0.01", "2.0", "0.01", "%.0f", nullptr, 100.0f},
    218 };
    219 
    220 const Controller::ControllerInfo PlayStationMouse::INFO = {ControllerType::PlayStationMouse,
    221                                                            "PlayStationMouse",
    222                                                            TRANSLATE_NOOP("ControllerType", "Mouse"),
    223                                                            ICON_PF_MOUSE,
    224                                                            s_binding_info,
    225                                                            s_settings,
    226                                                            Controller::VibrationCapabilities::NoVibration};