touchscreen.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. // Copyright 2018 yuzu emulator team
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <algorithm>
  5. #include <cstring>
  6. #include "common/common_types.h"
  7. #include "common/settings.h"
  8. #include "core/core.h"
  9. #include "core/core_timing.h"
  10. #include "core/frontend/emu_window.h"
  11. #include "core/hid/emulated_console.h"
  12. #include "core/hid/hid_core.h"
  13. #include "core/hle/service/hid/controllers/touchscreen.h"
  14. namespace Service::HID {
  15. constexpr std::size_t SHARED_MEMORY_OFFSET = 0x400;
  16. Controller_Touchscreen::Controller_Touchscreen(Core::HID::HIDCore& hid_core_)
  17. : ControllerBase{hid_core_} {
  18. console = hid_core.GetEmulatedConsole();
  19. }
  20. Controller_Touchscreen::~Controller_Touchscreen() = default;
  21. void Controller_Touchscreen::OnInit() {}
  22. void Controller_Touchscreen::OnRelease() {}
  23. void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
  24. std::size_t size) {
  25. touch_screen_lifo.timestamp = core_timing.GetCPUTicks();
  26. if (!IsControllerActivated()) {
  27. touch_screen_lifo.buffer_count = 0;
  28. touch_screen_lifo.buffer_tail = 0;
  29. std::memcpy(data, &touch_screen_lifo, sizeof(touch_screen_lifo));
  30. return;
  31. }
  32. const auto touch_status = console->GetTouch();
  33. for (std::size_t id = 0; id < MAX_FINGERS; id++) {
  34. const auto& current_touch = touch_status[id];
  35. auto& finger = fingers[id];
  36. finger.position = current_touch.position;
  37. finger.id = current_touch.id;
  38. if (finger.attribute.start_touch) {
  39. finger.attribute.raw = 0;
  40. continue;
  41. }
  42. if (finger.attribute.end_touch) {
  43. finger.attribute.raw = 0;
  44. finger.pressed = false;
  45. continue;
  46. }
  47. if (!finger.pressed && current_touch.pressed) {
  48. finger.attribute.start_touch.Assign(1);
  49. finger.pressed = true;
  50. continue;
  51. }
  52. if (finger.pressed && !current_touch.pressed) {
  53. finger.attribute.raw = 0;
  54. finger.attribute.end_touch.Assign(1);
  55. }
  56. }
  57. std::array<Core::HID::TouchFinger, MAX_FINGERS> active_fingers;
  58. const auto end_iter = std::copy_if(fingers.begin(), fingers.end(), active_fingers.begin(),
  59. [](const auto& finger) { return finger.pressed; });
  60. const auto active_fingers_count =
  61. static_cast<std::size_t>(std::distance(active_fingers.begin(), end_iter));
  62. const u64 tick = core_timing.GetCPUTicks();
  63. const auto& last_entry = touch_screen_lifo.ReadCurrentEntry().state;
  64. next_state.sampling_number = last_entry.sampling_number + 1;
  65. next_state.entry_count = static_cast<s32>(active_fingers_count);
  66. for (std::size_t id = 0; id < MAX_FINGERS; ++id) {
  67. auto& touch_entry = next_state.states[id];
  68. if (id < active_fingers_count) {
  69. const auto& [active_x, active_y] = active_fingers[id].position;
  70. touch_entry.position = {
  71. .x = static_cast<u16>(active_x * Layout::ScreenUndocked::Width),
  72. .y = static_cast<u16>(active_y * Layout::ScreenUndocked::Height),
  73. };
  74. touch_entry.diameter_x = Settings::values.touchscreen.diameter_x;
  75. touch_entry.diameter_y = Settings::values.touchscreen.diameter_y;
  76. touch_entry.rotation_angle = Settings::values.touchscreen.rotation_angle;
  77. touch_entry.delta_time = tick - active_fingers[id].last_touch;
  78. fingers[active_fingers[id].id].last_touch = tick;
  79. touch_entry.finger = active_fingers[id].id;
  80. touch_entry.attribute.raw = active_fingers[id].attribute.raw;
  81. } else {
  82. // Clear touch entry
  83. touch_entry.attribute.raw = 0;
  84. touch_entry.position = {};
  85. touch_entry.diameter_x = 0;
  86. touch_entry.diameter_y = 0;
  87. touch_entry.rotation_angle = 0;
  88. touch_entry.delta_time = 0;
  89. touch_entry.finger = 0;
  90. }
  91. }
  92. touch_screen_lifo.WriteNextEntry(next_state);
  93. std::memcpy(data + SHARED_MEMORY_OFFSET, &touch_screen_lifo, sizeof(touch_screen_lifo));
  94. }
  95. } // namespace Service::HID