service/hid: Update debug pad, xpad, stubbed and controller base to use ring lifo and the emulated controller

This commit is contained in:
german77 2021-09-20 20:31:06 -05:00 committed by Narr the Reg
parent dbe0301102
commit 072559dede
7 changed files with 80 additions and 166 deletions

View file

@ -35,9 +35,6 @@ public:
virtual void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, virtual void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
std::size_t size) {} std::size_t size) {}
// Called when input devices should be loaded
virtual void OnLoadInputDevices() = 0;
void ActivateController(); void ActivateController();
void DeactivateController(); void DeactivateController();
@ -47,14 +44,6 @@ public:
protected: protected:
bool is_activated{false}; bool is_activated{false};
struct CommonHeader {
s64_le timestamp;
s64_le total_entry_count;
s64_le last_entry_index;
s64_le entry_count;
};
static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size");
Core::System& system; Core::System& system;
}; };
} // namespace Service::HID } // namespace Service::HID

View file

@ -5,7 +5,10 @@
#include <cstring> #include <cstring>
#include "common/common_types.h" #include "common/common_types.h"
#include "common/settings.h" #include "common/settings.h"
#include "core/core.h"
#include "core/core_timing.h" #include "core/core_timing.h"
#include "core/hid/hid_core.h"
#include "core/hid/hid_types.h"
#include "core/hle/service/hid/controllers/debug_pad.h" #include "core/hle/service/hid/controllers/debug_pad.h"
namespace Service::HID { namespace Service::HID {
@ -14,7 +17,10 @@ constexpr s32 HID_JOYSTICK_MAX = 0x7fff;
[[maybe_unused]] constexpr s32 HID_JOYSTICK_MIN = -0x7fff; [[maybe_unused]] constexpr s32 HID_JOYSTICK_MIN = -0x7fff;
enum class JoystickId : std::size_t { Joystick_Left, Joystick_Right }; enum class JoystickId : std::size_t { Joystick_Left, Joystick_Right };
Controller_DebugPad::Controller_DebugPad(Core::System& system_) : ControllerBase{system_} {} Controller_DebugPad::Controller_DebugPad(Core::System& system_) : ControllerBase{system_} {
controller = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Other);
}
Controller_DebugPad::~Controller_DebugPad() = default; Controller_DebugPad::~Controller_DebugPad() = default;
void Controller_DebugPad::OnInit() {} void Controller_DebugPad::OnInit() {}
@ -23,63 +29,29 @@ void Controller_DebugPad::OnRelease() {}
void Controller_DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, void Controller_DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
std::size_t size) { std::size_t size) {
shared_memory.header.timestamp = core_timing.GetCPUTicks();
shared_memory.header.total_entry_count = 17;
if (!IsControllerActivated()) { if (!IsControllerActivated()) {
shared_memory.header.entry_count = 0; debug_pad_lifo.entry_count = 0;
shared_memory.header.last_entry_index = 0; debug_pad_lifo.last_entry_index = 0;
std::memcpy(data, &debug_pad_lifo, sizeof(debug_pad_lifo));
return; return;
} }
shared_memory.header.entry_count = 16;
const auto& last_entry = shared_memory.pad_states[shared_memory.header.last_entry_index]; const auto& last_entry = debug_pad_lifo.ReadCurrentEntry().state;
shared_memory.header.last_entry_index = (shared_memory.header.last_entry_index + 1) % 17; next_state.sampling_number = last_entry.sampling_number + 1;
auto& cur_entry = shared_memory.pad_states[shared_memory.header.last_entry_index];
cur_entry.sampling_number = last_entry.sampling_number + 1;
cur_entry.sampling_number2 = cur_entry.sampling_number;
if (Settings::values.debug_pad_enabled) { if (Settings::values.debug_pad_enabled) {
cur_entry.attribute.connected.Assign(1); next_state.attribute.connected.Assign(1);
auto& pad = cur_entry.pad_state;
using namespace Settings::NativeButton; const auto& button_state = controller->GetDebugPadButtons();
pad.a.Assign(buttons[A - BUTTON_HID_BEGIN]->GetStatus()); const auto& stick_state = controller->GetSticks();
pad.b.Assign(buttons[B - BUTTON_HID_BEGIN]->GetStatus());
pad.x.Assign(buttons[X - BUTTON_HID_BEGIN]->GetStatus());
pad.y.Assign(buttons[Y - BUTTON_HID_BEGIN]->GetStatus());
pad.l.Assign(buttons[L - BUTTON_HID_BEGIN]->GetStatus());
pad.r.Assign(buttons[R - BUTTON_HID_BEGIN]->GetStatus());
pad.zl.Assign(buttons[ZL - BUTTON_HID_BEGIN]->GetStatus());
pad.zr.Assign(buttons[ZR - BUTTON_HID_BEGIN]->GetStatus());
pad.plus.Assign(buttons[Plus - BUTTON_HID_BEGIN]->GetStatus());
pad.minus.Assign(buttons[Minus - BUTTON_HID_BEGIN]->GetStatus());
pad.d_left.Assign(buttons[DLeft - BUTTON_HID_BEGIN]->GetStatus());
pad.d_up.Assign(buttons[DUp - BUTTON_HID_BEGIN]->GetStatus());
pad.d_right.Assign(buttons[DRight - BUTTON_HID_BEGIN]->GetStatus());
pad.d_down.Assign(buttons[DDown - BUTTON_HID_BEGIN]->GetStatus());
const auto [stick_l_x_f, stick_l_y_f] = next_state.pad_state = button_state;
analogs[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetStatus(); next_state.l_stick = stick_state.left;
const auto [stick_r_x_f, stick_r_y_f] = next_state.r_stick = stick_state.right;
analogs[static_cast<std::size_t>(JoystickId::Joystick_Right)]->GetStatus();
cur_entry.l_stick.x = static_cast<s32>(stick_l_x_f * HID_JOYSTICK_MAX);
cur_entry.l_stick.y = static_cast<s32>(stick_l_y_f * HID_JOYSTICK_MAX);
cur_entry.r_stick.x = static_cast<s32>(stick_r_x_f * HID_JOYSTICK_MAX);
cur_entry.r_stick.y = static_cast<s32>(stick_r_y_f * HID_JOYSTICK_MAX);
} }
std::memcpy(data, &shared_memory, sizeof(SharedMemory)); debug_pad_lifo.WriteNextEntry(next_state);
std::memcpy(data, &debug_pad_lifo, sizeof(debug_pad_lifo));
} }
void Controller_DebugPad::OnLoadInputDevices() {
std::transform(Settings::values.debug_pad_buttons.begin(),
Settings::values.debug_pad_buttons.begin() +
Settings::NativeButton::NUM_BUTTONS_HID,
buttons.begin(), Input::CreateDevice<Input::ButtonDevice>);
std::transform(Settings::values.debug_pad_analogs.begin(),
Settings::values.debug_pad_analogs.end(), analogs.begin(),
Input::CreateDevice<Input::AnalogDevice>);
}
} // namespace Service::HID } // namespace Service::HID

View file

@ -10,8 +10,14 @@
#include "common/common_types.h" #include "common/common_types.h"
#include "common/settings.h" #include "common/settings.h"
#include "common/swap.h" #include "common/swap.h"
#include "core/frontend/input.h"
#include "core/hle/service/hid/controllers/controller_base.h" #include "core/hle/service/hid/controllers/controller_base.h"
#include "core/hle/service/hid/ring_lifo.h"
namespace Core::HID {
class EmulatedController;
struct DebugPadButton;
struct AnalogStickState;
} // namespace Core::HID
namespace Service::HID { namespace Service::HID {
class Controller_DebugPad final : public ControllerBase { class Controller_DebugPad final : public ControllerBase {
@ -28,66 +34,31 @@ public:
// When the controller is requesting an update for the shared memory // When the controller is requesting an update for the shared memory
void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override; void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override;
// Called when input devices should be loaded
void OnLoadInputDevices() override;
private: private:
struct AnalogStick { // This is nn::hid::DebugPadAttribute
s32_le x; struct DebugPadAttribute {
s32_le y;
};
static_assert(sizeof(AnalogStick) == 0x8);
struct PadState {
union {
u32_le raw{};
BitField<0, 1, u32> a;
BitField<1, 1, u32> b;
BitField<2, 1, u32> x;
BitField<3, 1, u32> y;
BitField<4, 1, u32> l;
BitField<5, 1, u32> r;
BitField<6, 1, u32> zl;
BitField<7, 1, u32> zr;
BitField<8, 1, u32> plus;
BitField<9, 1, u32> minus;
BitField<10, 1, u32> d_left;
BitField<11, 1, u32> d_up;
BitField<12, 1, u32> d_right;
BitField<13, 1, u32> d_down;
};
};
static_assert(sizeof(PadState) == 0x4, "PadState is an invalid size");
struct Attributes {
union { union {
u32_le raw{}; u32_le raw{};
BitField<0, 1, u32> connected; BitField<0, 1, u32> connected;
}; };
}; };
static_assert(sizeof(Attributes) == 0x4, "Attributes is an invalid size"); static_assert(sizeof(DebugPadAttribute) == 0x4, "DebugPadAttribute is an invalid size");
struct PadStates { // This is nn::hid::DebugPadState
struct DebugPadState {
s64_le sampling_number; s64_le sampling_number;
s64_le sampling_number2; DebugPadAttribute attribute;
Attributes attribute; Core::HID::DebugPadButton pad_state;
PadState pad_state; Core::HID::AnalogStickState r_stick;
AnalogStick r_stick; Core::HID::AnalogStickState l_stick;
AnalogStick l_stick;
}; };
static_assert(sizeof(PadStates) == 0x28, "PadStates is an invalid state"); static_assert(sizeof(DebugPadState) == 0x20, "DebugPadState is an invalid state");
struct SharedMemory { // This is nn::hid::detail::DebugPadLifo
CommonHeader header; Lifo<DebugPadState> debug_pad_lifo{};
std::array<PadStates, 17> pad_states; static_assert(sizeof(debug_pad_lifo) == 0x2C8, "debug_pad_lifo is an invalid size");
INSERT_PADDING_BYTES(0x138); DebugPadState next_state{};
};
static_assert(sizeof(SharedMemory) == 0x400, "SharedMemory is an invalid size");
SharedMemory shared_memory{};
std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::NUM_BUTTONS_HID> Core::HID::EmulatedController* controller;
buttons;
std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NumAnalogs>
analogs;
}; };
} // namespace Service::HID } // namespace Service::HID

View file

@ -31,10 +31,9 @@ void Controller_Stubbed::OnUpdate(const Core::Timing::CoreTiming& core_timing, u
std::memcpy(data + common_offset, &header, sizeof(CommonHeader)); std::memcpy(data + common_offset, &header, sizeof(CommonHeader));
} }
void Controller_Stubbed::OnLoadInputDevices() {}
void Controller_Stubbed::SetCommonHeaderOffset(std::size_t off) { void Controller_Stubbed::SetCommonHeaderOffset(std::size_t off) {
common_offset = off; common_offset = off;
smart_update = true; smart_update = true;
} }
} // namespace Service::HID } // namespace Service::HID

View file

@ -22,12 +22,17 @@ public:
// When the controller is requesting an update for the shared memory // When the controller is requesting an update for the shared memory
void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override; void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override;
// Called when input devices should be loaded
void OnLoadInputDevices() override;
void SetCommonHeaderOffset(std::size_t off); void SetCommonHeaderOffset(std::size_t off);
private: private:
struct CommonHeader {
s64_le timestamp;
s64_le total_entry_count;
s64_le last_entry_index;
s64_le entry_count;
};
static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size");
bool smart_update{}; bool smart_update{};
std::size_t common_offset{}; std::size_t common_offset{};
}; };

View file

@ -19,28 +19,19 @@ void Controller_XPad::OnRelease() {}
void Controller_XPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, void Controller_XPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
std::size_t size) { std::size_t size) {
for (auto& xpad_entry : shared_memory.shared_memory_entries) { if (!IsControllerActivated()) {
xpad_entry.header.timestamp = core_timing.GetCPUTicks(); basic_xpad_lifo.entry_count = 0;
xpad_entry.header.total_entry_count = 17; basic_xpad_lifo.last_entry_index = 0;
std::memcpy(data, &basic_xpad_lifo, sizeof(basic_xpad_lifo));
if (!IsControllerActivated()) { return;
xpad_entry.header.entry_count = 0;
xpad_entry.header.last_entry_index = 0;
return;
}
xpad_entry.header.entry_count = 16;
const auto& last_entry = xpad_entry.pad_states[xpad_entry.header.last_entry_index];
xpad_entry.header.last_entry_index = (xpad_entry.header.last_entry_index + 1) % 17;
auto& cur_entry = xpad_entry.pad_states[xpad_entry.header.last_entry_index];
cur_entry.sampling_number = last_entry.sampling_number + 1;
cur_entry.sampling_number2 = cur_entry.sampling_number;
} }
const auto& last_entry = basic_xpad_lifo.ReadCurrentEntry().state;
next_state.sampling_number = last_entry.sampling_number + 1;
// TODO(ogniK): Update xpad states // TODO(ogniK): Update xpad states
std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory)); basic_xpad_lifo.WriteNextEntry(next_state);
std::memcpy(data + SHARED_MEMORY_OFFSET, &basic_xpad_lifo, sizeof(basic_xpad_lifo));
} }
void Controller_XPad::OnLoadInputDevices() {}
} // namespace Service::HID } // namespace Service::HID

View file

@ -8,7 +8,9 @@
#include "common/common_funcs.h" #include "common/common_funcs.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "common/swap.h" #include "common/swap.h"
#include "core/hid/hid_types.h"
#include "core/hle/service/hid/controllers/controller_base.h" #include "core/hle/service/hid/controllers/controller_base.h"
#include "core/hle/service/hid/ring_lifo.h"
namespace Service::HID { namespace Service::HID {
class Controller_XPad final : public ControllerBase { class Controller_XPad final : public ControllerBase {
@ -25,11 +27,9 @@ public:
// When the controller is requesting an update for the shared memory // When the controller is requesting an update for the shared memory
void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override; void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override;
// Called when input devices should be loaded
void OnLoadInputDevices() override;
private: private:
struct Attributes { // This is nn::hid::BasicXpadAttributeSet
struct BasicXpadAttributeSet {
union { union {
u32_le raw{}; u32_le raw{};
BitField<0, 1, u32> is_connected; BitField<0, 1, u32> is_connected;
@ -40,9 +40,10 @@ private:
BitField<5, 1, u32> is_right_wired; BitField<5, 1, u32> is_right_wired;
}; };
}; };
static_assert(sizeof(Attributes) == 4, "Attributes is an invalid size"); static_assert(sizeof(BasicXpadAttributeSet) == 4, "BasicXpadAttributeSet is an invalid size");
struct Buttons { // This is nn::hid::BasicXpadButtonSet
struct BasicXpadButtonSet {
union { union {
u32_le raw{}; u32_le raw{};
// Button states // Button states
@ -88,35 +89,21 @@ private:
BitField<30, 1, u32> handheld_left_b; BitField<30, 1, u32> handheld_left_b;
}; };
}; };
static_assert(sizeof(Buttons) == 4, "Buttons is an invalid size"); static_assert(sizeof(BasicXpadButtonSet) == 4, "BasicXpadButtonSet is an invalid size");
struct AnalogStick { // This is nn::hid::detail::BasicXpadState
s32_le x; struct BasicXpadState {
s32_le y;
};
static_assert(sizeof(AnalogStick) == 0x8, "AnalogStick is an invalid size");
struct XPadState {
s64_le sampling_number; s64_le sampling_number;
s64_le sampling_number2; BasicXpadAttributeSet attributes;
Attributes attributes; BasicXpadButtonSet pad_states;
Buttons pad_states; Core::HID::AnalogStickState l_stick;
AnalogStick l_stick; Core::HID::AnalogStickState r_stick;
AnalogStick r_stick;
}; };
static_assert(sizeof(XPadState) == 0x28, "XPadState is an invalid size"); static_assert(sizeof(BasicXpadState) == 0x20, "BasicXpadState is an invalid size");
struct XPadEntry { // This is nn::hid::detail::BasicXpadLifo
CommonHeader header; Lifo<BasicXpadState> basic_xpad_lifo{};
std::array<XPadState, 17> pad_states{}; static_assert(sizeof(basic_xpad_lifo) == 0x2C8, "basic_xpad_lifo is an invalid size");
INSERT_PADDING_BYTES(0x138); BasicXpadState next_state{};
};
static_assert(sizeof(XPadEntry) == 0x400, "XPadEntry is an invalid size");
struct SharedMemory {
std::array<XPadEntry, 4> shared_memory_entries{};
};
static_assert(sizeof(SharedMemory) == 0x1000, "SharedMemory is an invalid size");
SharedMemory shared_memory{};
}; };
} // namespace Service::HID } // namespace Service::HID