early-access version 4020
This commit is contained in:
parent
20b067fbf4
commit
ba87c29152
46 changed files with 1130 additions and 766 deletions
|
@ -1,7 +1,7 @@
|
||||||
yuzu emulator early access
|
yuzu emulator early access
|
||||||
=============
|
=============
|
||||||
|
|
||||||
This is the source code for early-access 4019.
|
This is the source code for early-access 4020.
|
||||||
|
|
||||||
## Legal Notice
|
## Legal Notice
|
||||||
|
|
||||||
|
|
|
@ -549,6 +549,11 @@ add_library(core STATIC
|
||||||
hle/service/hid/xcd.cpp
|
hle/service/hid/xcd.cpp
|
||||||
hle/service/hid/xcd.h
|
hle/service/hid/xcd.h
|
||||||
hle/service/hid/errors.h
|
hle/service/hid/errors.h
|
||||||
|
hle/service/hid/controllers/types/debug_pad_types.h
|
||||||
|
hle/service/hid/controllers/types/keyboard_types.h
|
||||||
|
hle/service/hid/controllers/types/mouse_types.h
|
||||||
|
hle/service/hid/controllers/types/npad_types.h
|
||||||
|
hle/service/hid/controllers/types/touch_types.h
|
||||||
hle/service/hid/controllers/applet_resource.cpp
|
hle/service/hid/controllers/applet_resource.cpp
|
||||||
hle/service/hid/controllers/applet_resource.h
|
hle/service/hid/controllers/applet_resource.h
|
||||||
hle/service/hid/controllers/console_six_axis.cpp
|
hle/service/hid/controllers/console_six_axis.cpp
|
||||||
|
@ -569,14 +574,15 @@ add_library(core STATIC
|
||||||
hle/service/hid/controllers/palma.h
|
hle/service/hid/controllers/palma.h
|
||||||
hle/service/hid/controllers/seven_six_axis.cpp
|
hle/service/hid/controllers/seven_six_axis.cpp
|
||||||
hle/service/hid/controllers/seven_six_axis.h
|
hle/service/hid/controllers/seven_six_axis.h
|
||||||
|
hle/service/hid/controllers/shared_memory_format.h
|
||||||
|
hle/service/hid/controllers/shared_memory_holder.cpp
|
||||||
|
hle/service/hid/controllers/shared_memory_holder.h
|
||||||
hle/service/hid/controllers/six_axis.cpp
|
hle/service/hid/controllers/six_axis.cpp
|
||||||
hle/service/hid/controllers/six_axis.h
|
hle/service/hid/controllers/six_axis.h
|
||||||
hle/service/hid/controllers/stubbed.cpp
|
hle/service/hid/controllers/stubbed.cpp
|
||||||
hle/service/hid/controllers/stubbed.h
|
hle/service/hid/controllers/stubbed.h
|
||||||
hle/service/hid/controllers/touchscreen.cpp
|
hle/service/hid/controllers/touchscreen.cpp
|
||||||
hle/service/hid/controllers/touchscreen.h
|
hle/service/hid/controllers/touchscreen.h
|
||||||
hle/service/hid/controllers/xpad.cpp
|
|
||||||
hle/service/hid/controllers/xpad.h
|
|
||||||
hle/service/hid/hidbus/hidbus_base.cpp
|
hle/service/hid/hidbus/hidbus_base.cpp
|
||||||
hle/service/hid/hidbus/hidbus_base.h
|
hle/service/hid/hidbus/hidbus_base.h
|
||||||
hle/service/hid/hidbus/ringcon.cpp
|
hle/service/hid/hidbus/ringcon.cpp
|
||||||
|
|
|
@ -135,7 +135,6 @@ struct KernelCore::Impl {
|
||||||
obj = nullptr;
|
obj = nullptr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
CleanupObject(hid_shared_mem);
|
|
||||||
CleanupObject(font_shared_mem);
|
CleanupObject(font_shared_mem);
|
||||||
CleanupObject(irs_shared_mem);
|
CleanupObject(irs_shared_mem);
|
||||||
CleanupObject(time_shared_mem);
|
CleanupObject(time_shared_mem);
|
||||||
|
@ -744,22 +743,16 @@ struct KernelCore::Impl {
|
||||||
void InitializeHackSharedMemory(KernelCore& kernel) {
|
void InitializeHackSharedMemory(KernelCore& kernel) {
|
||||||
// Setup memory regions for emulated processes
|
// Setup memory regions for emulated processes
|
||||||
// TODO(bunnei): These should not be hardcoded regions initialized within the kernel
|
// TODO(bunnei): These should not be hardcoded regions initialized within the kernel
|
||||||
constexpr std::size_t hid_size{0x40000};
|
|
||||||
constexpr std::size_t font_size{0x1100000};
|
constexpr std::size_t font_size{0x1100000};
|
||||||
constexpr std::size_t irs_size{0x8000};
|
constexpr std::size_t irs_size{0x8000};
|
||||||
constexpr std::size_t time_size{0x1000};
|
constexpr std::size_t time_size{0x1000};
|
||||||
constexpr std::size_t hidbus_size{0x1000};
|
constexpr std::size_t hidbus_size{0x1000};
|
||||||
|
|
||||||
hid_shared_mem = KSharedMemory::Create(system.Kernel());
|
|
||||||
font_shared_mem = KSharedMemory::Create(system.Kernel());
|
font_shared_mem = KSharedMemory::Create(system.Kernel());
|
||||||
irs_shared_mem = KSharedMemory::Create(system.Kernel());
|
irs_shared_mem = KSharedMemory::Create(system.Kernel());
|
||||||
time_shared_mem = KSharedMemory::Create(system.Kernel());
|
time_shared_mem = KSharedMemory::Create(system.Kernel());
|
||||||
hidbus_shared_mem = KSharedMemory::Create(system.Kernel());
|
hidbus_shared_mem = KSharedMemory::Create(system.Kernel());
|
||||||
|
|
||||||
hid_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None,
|
|
||||||
Svc::MemoryPermission::Read, hid_size);
|
|
||||||
KSharedMemory::Register(kernel, hid_shared_mem);
|
|
||||||
|
|
||||||
font_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None,
|
font_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None,
|
||||||
Svc::MemoryPermission::Read, font_size);
|
Svc::MemoryPermission::Read, font_size);
|
||||||
KSharedMemory::Register(kernel, font_shared_mem);
|
KSharedMemory::Register(kernel, font_shared_mem);
|
||||||
|
@ -1190,14 +1183,6 @@ const KSystemResource& KernelCore::GetSystemSystemResource() const {
|
||||||
return *impl->sys_system_resource;
|
return *impl->sys_system_resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
Kernel::KSharedMemory& KernelCore::GetHidSharedMem() {
|
|
||||||
return *impl->hid_shared_mem;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Kernel::KSharedMemory& KernelCore::GetHidSharedMem() const {
|
|
||||||
return *impl->hid_shared_mem;
|
|
||||||
}
|
|
||||||
|
|
||||||
Kernel::KSharedMemory& KernelCore::GetFontSharedMem() {
|
Kernel::KSharedMemory& KernelCore::GetFontSharedMem() {
|
||||||
return *impl->font_shared_mem;
|
return *impl->font_shared_mem;
|
||||||
}
|
}
|
||||||
|
|
|
@ -239,12 +239,6 @@ public:
|
||||||
/// Gets the system resource manager.
|
/// Gets the system resource manager.
|
||||||
const KSystemResource& GetSystemSystemResource() const;
|
const KSystemResource& GetSystemSystemResource() const;
|
||||||
|
|
||||||
/// Gets the shared memory object for HID services.
|
|
||||||
Kernel::KSharedMemory& GetHidSharedMem();
|
|
||||||
|
|
||||||
/// Gets the shared memory object for HID services.
|
|
||||||
const Kernel::KSharedMemory& GetHidSharedMem() const;
|
|
||||||
|
|
||||||
/// Gets the shared memory object for font services.
|
/// Gets the shared memory object for font services.
|
||||||
Kernel::KSharedMemory& GetFontSharedMem();
|
Kernel::KSharedMemory& GetFontSharedMem();
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/hle/kernel/k_shared_memory.h"
|
#include "core/hle/kernel/k_shared_memory.h"
|
||||||
#include "core/hle/service/hid/controllers/applet_resource.h"
|
#include "core/hle/service/hid/controllers/applet_resource.h"
|
||||||
|
#include "core/hle/service/hid/controllers/shared_memory_format.h"
|
||||||
#include "core/hle/service/hid/errors.h"
|
#include "core/hle/service/hid/errors.h"
|
||||||
|
|
||||||
namespace Service::HID {
|
namespace Service::HID {
|
||||||
|
@ -23,11 +24,24 @@ Result AppletResource::CreateAppletResource(u64 aruid) {
|
||||||
return ResultAruidAlreadyRegistered;
|
return ResultAruidAlreadyRegistered;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Here shared memory is created for the process we don't quite emulate this part so
|
auto& shared_memory = shared_memory_holder[index];
|
||||||
// obtain this pointer from system
|
if (!shared_memory.IsMapped()) {
|
||||||
auto& shared_memory = system.Kernel().GetHidSharedMem();
|
const Result result = shared_memory.Initialize(system);
|
||||||
|
if (result.IsError()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (shared_memory.GetAddress() == nullptr) {
|
||||||
|
shared_memory.Finalize();
|
||||||
|
return ResultSharedMemoryNotInitialized;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
data[index].shared_memory_handle = &shared_memory;
|
auto* shared_memory_format = shared_memory.GetAddress();
|
||||||
|
if (shared_memory_format != nullptr) {
|
||||||
|
shared_memory_format->Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
data[index].shared_memory_format = shared_memory_format;
|
||||||
data[index].flag.is_assigned.Assign(true);
|
data[index].flag.is_assigned.Assign(true);
|
||||||
// TODO: InitializeSixAxisControllerConfig(false);
|
// TODO: InitializeSixAxisControllerConfig(false);
|
||||||
active_aruid = aruid;
|
active_aruid = aruid;
|
||||||
|
@ -94,7 +108,7 @@ void AppletResource::UnregisterAppletResourceUserId(u64 aruid) {
|
||||||
|
|
||||||
if (index < AruidIndexMax) {
|
if (index < AruidIndexMax) {
|
||||||
if (data[index].flag.is_assigned) {
|
if (data[index].flag.is_assigned) {
|
||||||
data[index].shared_memory_handle = nullptr;
|
data[index].shared_memory_format = nullptr;
|
||||||
data[index].flag.is_assigned.Assign(false);
|
data[index].flag.is_assigned.Assign(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -120,7 +134,7 @@ void AppletResource::FreeAppletResourceId(u64 aruid) {
|
||||||
|
|
||||||
auto& aruid_data = data[index];
|
auto& aruid_data = data[index];
|
||||||
if (aruid_data.flag.is_assigned) {
|
if (aruid_data.flag.is_assigned) {
|
||||||
aruid_data.shared_memory_handle = nullptr;
|
aruid_data.shared_memory_format = nullptr;
|
||||||
aruid_data.flag.is_assigned.Assign(false);
|
aruid_data.flag.is_assigned.Assign(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -135,7 +149,18 @@ Result AppletResource::GetSharedMemoryHandle(Kernel::KSharedMemory** out_handle,
|
||||||
return ResultAruidNotRegistered;
|
return ResultAruidNotRegistered;
|
||||||
}
|
}
|
||||||
|
|
||||||
*out_handle = data[index].shared_memory_handle;
|
*out_handle = shared_memory_holder[index].GetHandle();
|
||||||
|
return ResultSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result AppletResource::GetSharedMemoryFormat(SharedMemoryFormat** out_shared_memory_format,
|
||||||
|
u64 aruid) {
|
||||||
|
u64 index = GetIndexFromAruid(aruid);
|
||||||
|
if (index >= AruidIndexMax) {
|
||||||
|
return ResultAruidNotRegistered;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_shared_memory_format = data[index].shared_memory_format;
|
||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "common/bit_field.h"
|
#include "common/bit_field.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/hle/result.h"
|
#include "core/hle/result.h"
|
||||||
|
#include "core/hle/service/hid/controllers/shared_memory_holder.h"
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
class System;
|
class System;
|
||||||
|
@ -18,6 +19,8 @@ class KSharedMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Service::HID {
|
namespace Service::HID {
|
||||||
|
struct SharedMemoryFormat;
|
||||||
|
|
||||||
class AppletResource {
|
class AppletResource {
|
||||||
public:
|
public:
|
||||||
explicit AppletResource(Core::System& system_);
|
explicit AppletResource(Core::System& system_);
|
||||||
|
@ -32,6 +35,7 @@ public:
|
||||||
|
|
||||||
u64 GetActiveAruid();
|
u64 GetActiveAruid();
|
||||||
Result GetSharedMemoryHandle(Kernel::KSharedMemory** out_handle, u64 aruid);
|
Result GetSharedMemoryHandle(Kernel::KSharedMemory** out_handle, u64 aruid);
|
||||||
|
Result GetSharedMemoryFormat(SharedMemoryFormat** out_shared_memory_format, u64 aruid);
|
||||||
|
|
||||||
u64 GetIndexFromAruid(u64 aruid);
|
u64 GetIndexFromAruid(u64 aruid);
|
||||||
|
|
||||||
|
@ -80,12 +84,13 @@ private:
|
||||||
struct AruidData {
|
struct AruidData {
|
||||||
DataStatusFlag flag{};
|
DataStatusFlag flag{};
|
||||||
u64 aruid{};
|
u64 aruid{};
|
||||||
Kernel::KSharedMemory* shared_memory_handle{nullptr};
|
SharedMemoryFormat* shared_memory_format{nullptr};
|
||||||
};
|
};
|
||||||
|
|
||||||
u64 active_aruid{};
|
u64 active_aruid{};
|
||||||
AruidRegisterList registration_list{};
|
AruidRegisterList registration_list{};
|
||||||
std::array<AruidData, AruidIndexMax> data{};
|
std::array<AruidData, AruidIndexMax> data{};
|
||||||
|
std::array<SharedMemoryHolder, AruidIndexMax> shared_memory_holder{};
|
||||||
s32 ref_counter{};
|
s32 ref_counter{};
|
||||||
|
|
||||||
Core::System& system;
|
Core::System& system;
|
||||||
|
|
|
@ -6,18 +6,15 @@
|
||||||
#include "core/hid/emulated_console.h"
|
#include "core/hid/emulated_console.h"
|
||||||
#include "core/hid/hid_core.h"
|
#include "core/hid/hid_core.h"
|
||||||
#include "core/hle/service/hid/controllers/console_six_axis.h"
|
#include "core/hle/service/hid/controllers/console_six_axis.h"
|
||||||
|
#include "core/hle/service/hid/controllers/shared_memory_format.h"
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
|
|
||||||
namespace Service::HID {
|
namespace Service::HID {
|
||||||
constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C200;
|
|
||||||
|
|
||||||
ConsoleSixAxis::ConsoleSixAxis(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
|
ConsoleSixAxis::ConsoleSixAxis(Core::HID::HIDCore& hid_core_,
|
||||||
: ControllerBase{hid_core_} {
|
ConsoleSixAxisSensorSharedMemoryFormat& console_shared_memory)
|
||||||
|
: ControllerBase{hid_core_}, shared_memory{console_shared_memory} {
|
||||||
console = hid_core.GetEmulatedConsole();
|
console = hid_core.GetEmulatedConsole();
|
||||||
static_assert(SHARED_MEMORY_OFFSET + sizeof(ConsoleSharedMemory) < shared_memory_size,
|
|
||||||
"ConsoleSharedMemory is bigger than the shared memory");
|
|
||||||
shared_memory = std::construct_at(
|
|
||||||
reinterpret_cast<ConsoleSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ConsoleSixAxis::~ConsoleSixAxis() = default;
|
ConsoleSixAxis::~ConsoleSixAxis() = default;
|
||||||
|
@ -33,10 +30,10 @@ void ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
|
||||||
|
|
||||||
const auto motion_status = console->GetMotion();
|
const auto motion_status = console->GetMotion();
|
||||||
|
|
||||||
shared_memory->sampling_number++;
|
shared_memory.sampling_number++;
|
||||||
shared_memory->is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest;
|
shared_memory.is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest;
|
||||||
shared_memory->verticalization_error = motion_status.verticalization_error;
|
shared_memory.verticalization_error = motion_status.verticalization_error;
|
||||||
shared_memory->gyro_bias = motion_status.gyro_bias;
|
shared_memory.gyro_bias = motion_status.gyro_bias;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Service::HID
|
} // namespace Service::HID
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common/vector_math.h"
|
|
||||||
#include "core/hle/service/hid/controllers/controller_base.h"
|
#include "core/hle/service/hid/controllers/controller_base.h"
|
||||||
|
|
||||||
namespace Core::HID {
|
namespace Core::HID {
|
||||||
|
@ -11,9 +10,12 @@ class EmulatedConsole;
|
||||||
} // namespace Core::HID
|
} // namespace Core::HID
|
||||||
|
|
||||||
namespace Service::HID {
|
namespace Service::HID {
|
||||||
|
struct ConsoleSixAxisSensorSharedMemoryFormat;
|
||||||
|
|
||||||
class ConsoleSixAxis final : public ControllerBase {
|
class ConsoleSixAxis final : public ControllerBase {
|
||||||
public:
|
public:
|
||||||
explicit ConsoleSixAxis(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
|
explicit ConsoleSixAxis(Core::HID::HIDCore& hid_core_,
|
||||||
|
ConsoleSixAxisSensorSharedMemoryFormat& console_shared_memory);
|
||||||
~ConsoleSixAxis() override;
|
~ConsoleSixAxis() override;
|
||||||
|
|
||||||
// Called when the controller is initialized
|
// Called when the controller is initialized
|
||||||
|
@ -26,18 +28,7 @@ public:
|
||||||
void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
|
void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// This is nn::hid::detail::ConsoleSixAxisSensorSharedMemoryFormat
|
ConsoleSixAxisSensorSharedMemoryFormat& shared_memory;
|
||||||
struct ConsoleSharedMemory {
|
|
||||||
u64 sampling_number{};
|
|
||||||
bool is_seven_six_axis_sensor_at_rest{};
|
|
||||||
INSERT_PADDING_BYTES(3); // padding
|
|
||||||
f32 verticalization_error{};
|
|
||||||
Common::Vec3f gyro_bias{};
|
|
||||||
INSERT_PADDING_BYTES(4); // padding
|
|
||||||
};
|
|
||||||
static_assert(sizeof(ConsoleSharedMemory) == 0x20, "ConsoleSharedMemory is an invalid size");
|
|
||||||
|
|
||||||
ConsoleSharedMemory* shared_memory = nullptr;
|
|
||||||
Core::HID::EmulatedConsole* console = nullptr;
|
Core::HID::EmulatedConsole* console = nullptr;
|
||||||
};
|
};
|
||||||
} // namespace Service::HID
|
} // namespace Service::HID
|
||||||
|
|
|
@ -39,9 +39,6 @@ public:
|
||||||
|
|
||||||
bool IsControllerActivated() const;
|
bool IsControllerActivated() const;
|
||||||
|
|
||||||
static const std::size_t hid_entry_count = 17;
|
|
||||||
static const std::size_t shared_memory_size = 0x40000;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool is_activated{false};
|
bool is_activated{false};
|
||||||
|
|
||||||
|
|
|
@ -9,16 +9,13 @@
|
||||||
#include "core/hid/hid_core.h"
|
#include "core/hid/hid_core.h"
|
||||||
#include "core/hid/hid_types.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"
|
||||||
|
#include "core/hle/service/hid/controllers/shared_memory_format.h"
|
||||||
|
|
||||||
namespace Service::HID {
|
namespace Service::HID {
|
||||||
constexpr std::size_t SHARED_MEMORY_OFFSET = 0x00000;
|
|
||||||
|
|
||||||
DebugPad::DebugPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
|
DebugPad::DebugPad(Core::HID::HIDCore& hid_core_,
|
||||||
: ControllerBase{hid_core_} {
|
DebugPadSharedMemoryFormat& debug_pad_shared_memory)
|
||||||
static_assert(SHARED_MEMORY_OFFSET + sizeof(DebugPadSharedMemory) < shared_memory_size,
|
: ControllerBase{hid_core_}, shared_memory{debug_pad_shared_memory} {
|
||||||
"DebugPadSharedMemory is bigger than the shared memory");
|
|
||||||
shared_memory = std::construct_at(
|
|
||||||
reinterpret_cast<DebugPadSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
|
|
||||||
controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other);
|
controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,12 +27,12 @@ void DebugPad::OnRelease() {}
|
||||||
|
|
||||||
void DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
|
void DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
|
||||||
if (!IsControllerActivated()) {
|
if (!IsControllerActivated()) {
|
||||||
shared_memory->debug_pad_lifo.buffer_count = 0;
|
shared_memory.debug_pad_lifo.buffer_count = 0;
|
||||||
shared_memory->debug_pad_lifo.buffer_tail = 0;
|
shared_memory.debug_pad_lifo.buffer_tail = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& last_entry = shared_memory->debug_pad_lifo.ReadCurrentEntry().state;
|
const auto& last_entry = shared_memory.debug_pad_lifo.ReadCurrentEntry().state;
|
||||||
next_state.sampling_number = last_entry.sampling_number + 1;
|
next_state.sampling_number = last_entry.sampling_number + 1;
|
||||||
|
|
||||||
if (Settings::values.debug_pad_enabled) {
|
if (Settings::values.debug_pad_enabled) {
|
||||||
|
@ -49,7 +46,7 @@ void DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
|
||||||
next_state.r_stick = stick_state.right;
|
next_state.r_stick = stick_state.right;
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_memory->debug_pad_lifo.WriteNextEntry(next_state);
|
shared_memory.debug_pad_lifo.WriteNextEntry(next_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Service::HID
|
} // namespace Service::HID
|
||||||
|
|
|
@ -3,21 +3,25 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common/bit_field.h"
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_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"
|
#include "core/hle/service/hid/controllers/types/debug_pad_types.h"
|
||||||
|
|
||||||
namespace Core::HID {
|
namespace Core::HID {
|
||||||
class EmulatedController;
|
class HIDCore;
|
||||||
struct DebugPadButton;
|
}
|
||||||
struct AnalogStickState;
|
|
||||||
} // namespace Core::HID
|
namespace Core::Timing {
|
||||||
|
class CoreTiming;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Service::HID {
|
namespace Service::HID {
|
||||||
|
struct DebugPadSharedMemoryFormat;
|
||||||
|
|
||||||
class DebugPad final : public ControllerBase {
|
class DebugPad final : public ControllerBase {
|
||||||
public:
|
public:
|
||||||
explicit DebugPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
|
explicit DebugPad(Core::HID::HIDCore& hid_core_,
|
||||||
|
DebugPadSharedMemoryFormat& debug_pad_shared_memory);
|
||||||
~DebugPad() override;
|
~DebugPad() override;
|
||||||
|
|
||||||
// Called when the controller is initialized
|
// Called when the controller is initialized
|
||||||
|
@ -30,35 +34,8 @@ public:
|
||||||
void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
|
void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// This is nn::hid::DebugPadAttribute
|
|
||||||
struct DebugPadAttribute {
|
|
||||||
union {
|
|
||||||
u32 raw{};
|
|
||||||
BitField<0, 1, u32> connected;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
static_assert(sizeof(DebugPadAttribute) == 0x4, "DebugPadAttribute is an invalid size");
|
|
||||||
|
|
||||||
// This is nn::hid::DebugPadState
|
|
||||||
struct DebugPadState {
|
|
||||||
s64 sampling_number{};
|
|
||||||
DebugPadAttribute attribute{};
|
|
||||||
Core::HID::DebugPadButton pad_state{};
|
|
||||||
Core::HID::AnalogStickState r_stick{};
|
|
||||||
Core::HID::AnalogStickState l_stick{};
|
|
||||||
};
|
|
||||||
static_assert(sizeof(DebugPadState) == 0x20, "DebugPadState is an invalid state");
|
|
||||||
|
|
||||||
struct DebugPadSharedMemory {
|
|
||||||
// This is nn::hid::detail::DebugPadLifo
|
|
||||||
Lifo<DebugPadState, hid_entry_count> debug_pad_lifo{};
|
|
||||||
static_assert(sizeof(debug_pad_lifo) == 0x2C8, "debug_pad_lifo is an invalid size");
|
|
||||||
INSERT_PADDING_WORDS(0x4E);
|
|
||||||
};
|
|
||||||
static_assert(sizeof(DebugPadSharedMemory) == 0x400, "DebugPadSharedMemory is an invalid size");
|
|
||||||
|
|
||||||
DebugPadState next_state{};
|
DebugPadState next_state{};
|
||||||
DebugPadSharedMemory* shared_memory = nullptr;
|
DebugPadSharedMemoryFormat& shared_memory;
|
||||||
Core::HID::EmulatedController* controller = nullptr;
|
Core::HID::EmulatedController* controller = nullptr;
|
||||||
};
|
};
|
||||||
} // namespace Service::HID
|
} // namespace Service::HID
|
||||||
|
|
|
@ -8,10 +8,9 @@
|
||||||
#include "core/frontend/emu_window.h"
|
#include "core/frontend/emu_window.h"
|
||||||
#include "core/hid/hid_core.h"
|
#include "core/hid/hid_core.h"
|
||||||
#include "core/hle/service/hid/controllers/gesture.h"
|
#include "core/hle/service/hid/controllers/gesture.h"
|
||||||
|
#include "core/hle/service/hid/controllers/shared_memory_format.h"
|
||||||
|
|
||||||
namespace Service::HID {
|
namespace Service::HID {
|
||||||
constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3BA00;
|
|
||||||
|
|
||||||
// HW is around 700, value is set to 400 to make it easier to trigger with mouse
|
// HW is around 700, value is set to 400 to make it easier to trigger with mouse
|
||||||
constexpr f32 swipe_threshold = 400.0f; // Threshold in pixels/s
|
constexpr f32 swipe_threshold = 400.0f; // Threshold in pixels/s
|
||||||
constexpr f32 angle_threshold = 0.015f; // Threshold in radians
|
constexpr f32 angle_threshold = 0.015f; // Threshold in radians
|
||||||
|
@ -23,19 +22,15 @@ constexpr f32 Square(s32 num) {
|
||||||
return static_cast<f32>(num * num);
|
return static_cast<f32>(num * num);
|
||||||
}
|
}
|
||||||
|
|
||||||
Gesture::Gesture(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
|
Gesture::Gesture(Core::HID::HIDCore& hid_core_, GestureSharedMemoryFormat& gesture_shared_memory)
|
||||||
: ControllerBase(hid_core_) {
|
: ControllerBase(hid_core_), shared_memory{gesture_shared_memory} {
|
||||||
static_assert(SHARED_MEMORY_OFFSET + sizeof(GestureSharedMemory) < shared_memory_size,
|
|
||||||
"GestureSharedMemory is bigger than the shared memory");
|
|
||||||
shared_memory = std::construct_at(
|
|
||||||
reinterpret_cast<GestureSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
|
|
||||||
console = hid_core.GetEmulatedConsole();
|
console = hid_core.GetEmulatedConsole();
|
||||||
}
|
}
|
||||||
Gesture::~Gesture() = default;
|
Gesture::~Gesture() = default;
|
||||||
|
|
||||||
void Gesture::OnInit() {
|
void Gesture::OnInit() {
|
||||||
shared_memory->gesture_lifo.buffer_count = 0;
|
shared_memory.gesture_lifo.buffer_count = 0;
|
||||||
shared_memory->gesture_lifo.buffer_tail = 0;
|
shared_memory.gesture_lifo.buffer_tail = 0;
|
||||||
force_update = true;
|
force_update = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,8 +38,8 @@ void Gesture::OnRelease() {}
|
||||||
|
|
||||||
void Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
|
void Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
|
||||||
if (!IsControllerActivated()) {
|
if (!IsControllerActivated()) {
|
||||||
shared_memory->gesture_lifo.buffer_count = 0;
|
shared_memory.gesture_lifo.buffer_count = 0;
|
||||||
shared_memory->gesture_lifo.buffer_tail = 0;
|
shared_memory.gesture_lifo.buffer_tail = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +47,7 @@ void Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
|
||||||
|
|
||||||
GestureProperties gesture = GetGestureProperties();
|
GestureProperties gesture = GetGestureProperties();
|
||||||
f32 time_difference =
|
f32 time_difference =
|
||||||
static_cast<f32>(shared_memory->gesture_lifo.timestamp - last_update_timestamp) /
|
static_cast<f32>(shared_memory.gesture_lifo.timestamp - last_update_timestamp) /
|
||||||
(1000 * 1000 * 1000);
|
(1000 * 1000 * 1000);
|
||||||
|
|
||||||
// Only update if necessary
|
// Only update if necessary
|
||||||
|
@ -60,7 +55,7 @@ void Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
last_update_timestamp = shared_memory->gesture_lifo.timestamp;
|
last_update_timestamp = shared_memory.gesture_lifo.timestamp;
|
||||||
UpdateGestureSharedMemory(gesture, time_difference);
|
UpdateGestureSharedMemory(gesture, time_difference);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,7 +98,7 @@ void Gesture::UpdateGestureSharedMemory(GestureProperties& gesture, f32 time_dif
|
||||||
GestureType type = GestureType::Idle;
|
GestureType type = GestureType::Idle;
|
||||||
GestureAttribute attributes{};
|
GestureAttribute attributes{};
|
||||||
|
|
||||||
const auto& last_entry = shared_memory->gesture_lifo.ReadCurrentEntry().state;
|
const auto& last_entry = shared_memory.gesture_lifo.ReadCurrentEntry().state;
|
||||||
|
|
||||||
// Reset next state to default
|
// Reset next state to default
|
||||||
next_state.sampling_number = last_entry.sampling_number + 1;
|
next_state.sampling_number = last_entry.sampling_number + 1;
|
||||||
|
@ -133,7 +128,7 @@ void Gesture::UpdateGestureSharedMemory(GestureProperties& gesture, f32 time_dif
|
||||||
next_state.points = gesture.points;
|
next_state.points = gesture.points;
|
||||||
last_gesture = gesture;
|
last_gesture = gesture;
|
||||||
|
|
||||||
shared_memory->gesture_lifo.WriteNextEntry(next_state);
|
shared_memory.gesture_lifo.WriteNextEntry(next_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gesture::NewGesture(GestureProperties& gesture, GestureType& type,
|
void Gesture::NewGesture(GestureProperties& gesture, GestureType& type,
|
||||||
|
@ -305,11 +300,11 @@ void Gesture::SetSwipeEvent(GestureProperties& gesture, GestureProperties& last_
|
||||||
next_state.direction = GestureDirection::Up;
|
next_state.direction = GestureDirection::Up;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Gesture::GestureState& Gesture::GetLastGestureEntry() const {
|
const GestureState& Gesture::GetLastGestureEntry() const {
|
||||||
return shared_memory->gesture_lifo.ReadCurrentEntry().state;
|
return shared_memory.gesture_lifo.ReadCurrentEntry().state;
|
||||||
}
|
}
|
||||||
|
|
||||||
Gesture::GestureProperties Gesture::GetGestureProperties() {
|
GestureProperties Gesture::GetGestureProperties() {
|
||||||
GestureProperties gesture;
|
GestureProperties gesture;
|
||||||
std::array<Core::HID::TouchFinger, MAX_POINTS> active_fingers;
|
std::array<Core::HID::TouchFinger, MAX_POINTS> active_fingers;
|
||||||
const auto end_iter = std::copy_if(fingers.begin(), fingers.end(), active_fingers.begin(),
|
const auto end_iter = std::copy_if(fingers.begin(), fingers.end(), active_fingers.begin(),
|
||||||
|
|
|
@ -4,17 +4,19 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include "common/bit_field.h"
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/point.h"
|
|
||||||
#include "core/hid/emulated_console.h"
|
#include "core/hid/emulated_console.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"
|
#include "core/hle/service/hid/controllers/types/touch_types.h"
|
||||||
|
|
||||||
namespace Service::HID {
|
namespace Service::HID {
|
||||||
|
struct GestureSharedMemoryFormat;
|
||||||
|
|
||||||
class Gesture final : public ControllerBase {
|
class Gesture final : public ControllerBase {
|
||||||
public:
|
public:
|
||||||
explicit Gesture(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
|
explicit Gesture(Core::HID::HIDCore& hid_core_,
|
||||||
|
GestureSharedMemoryFormat& gesture_shared_memory);
|
||||||
~Gesture() override;
|
~Gesture() override;
|
||||||
|
|
||||||
// Called when the controller is initialized
|
// Called when the controller is initialized
|
||||||
|
@ -27,79 +29,6 @@ public:
|
||||||
void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
|
void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr size_t MAX_FINGERS = 16;
|
|
||||||
static constexpr size_t MAX_POINTS = 4;
|
|
||||||
|
|
||||||
// This is nn::hid::GestureType
|
|
||||||
enum class GestureType : u32 {
|
|
||||||
Idle, // Nothing touching the screen
|
|
||||||
Complete, // Set at the end of a touch event
|
|
||||||
Cancel, // Set when the number of fingers change
|
|
||||||
Touch, // A finger just touched the screen
|
|
||||||
Press, // Set if last type is touch and the finger hasn't moved
|
|
||||||
Tap, // Fast press then release
|
|
||||||
Pan, // All points moving together across the screen
|
|
||||||
Swipe, // Fast press movement and release of a single point
|
|
||||||
Pinch, // All points moving away/closer to the midpoint
|
|
||||||
Rotate, // All points rotating from the midpoint
|
|
||||||
};
|
|
||||||
|
|
||||||
// This is nn::hid::GestureDirection
|
|
||||||
enum class GestureDirection : u32 {
|
|
||||||
None,
|
|
||||||
Left,
|
|
||||||
Up,
|
|
||||||
Right,
|
|
||||||
Down,
|
|
||||||
};
|
|
||||||
|
|
||||||
// This is nn::hid::GestureAttribute
|
|
||||||
struct GestureAttribute {
|
|
||||||
union {
|
|
||||||
u32 raw{};
|
|
||||||
|
|
||||||
BitField<4, 1, u32> is_new_touch;
|
|
||||||
BitField<8, 1, u32> is_double_tap;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
static_assert(sizeof(GestureAttribute) == 4, "GestureAttribute is an invalid size");
|
|
||||||
|
|
||||||
// This is nn::hid::GestureState
|
|
||||||
struct GestureState {
|
|
||||||
s64 sampling_number{};
|
|
||||||
s64 detection_count{};
|
|
||||||
GestureType type{GestureType::Idle};
|
|
||||||
GestureDirection direction{GestureDirection::None};
|
|
||||||
Common::Point<s32> pos{};
|
|
||||||
Common::Point<s32> delta{};
|
|
||||||
f32 vel_x{};
|
|
||||||
f32 vel_y{};
|
|
||||||
GestureAttribute attributes{};
|
|
||||||
f32 scale{};
|
|
||||||
f32 rotation_angle{};
|
|
||||||
s32 point_count{};
|
|
||||||
std::array<Common::Point<s32>, 4> points{};
|
|
||||||
};
|
|
||||||
static_assert(sizeof(GestureState) == 0x60, "GestureState is an invalid size");
|
|
||||||
|
|
||||||
struct GestureProperties {
|
|
||||||
std::array<Common::Point<s32>, MAX_POINTS> points{};
|
|
||||||
std::size_t active_points{};
|
|
||||||
Common::Point<s32> mid_point{};
|
|
||||||
s64 detection_count{};
|
|
||||||
u64 delta_time{};
|
|
||||||
f32 average_distance{};
|
|
||||||
f32 angle{};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GestureSharedMemory {
|
|
||||||
// This is nn::hid::detail::GestureLifo
|
|
||||||
Lifo<GestureState, hid_entry_count> gesture_lifo{};
|
|
||||||
static_assert(sizeof(gesture_lifo) == 0x708, "gesture_lifo is an invalid size");
|
|
||||||
INSERT_PADDING_WORDS(0x3E);
|
|
||||||
};
|
|
||||||
static_assert(sizeof(GestureSharedMemory) == 0x800, "GestureSharedMemory is an invalid size");
|
|
||||||
|
|
||||||
// Reads input from all available input engines
|
// Reads input from all available input engines
|
||||||
void ReadTouchInput();
|
void ReadTouchInput();
|
||||||
|
|
||||||
|
@ -142,7 +71,7 @@ private:
|
||||||
GestureProperties GetGestureProperties();
|
GestureProperties GetGestureProperties();
|
||||||
|
|
||||||
GestureState next_state{};
|
GestureState next_state{};
|
||||||
GestureSharedMemory* shared_memory = nullptr;
|
GestureSharedMemoryFormat& shared_memory;
|
||||||
Core::HID::EmulatedConsole* console = nullptr;
|
Core::HID::EmulatedConsole* console = nullptr;
|
||||||
|
|
||||||
std::array<Core::HID::TouchFinger, MAX_POINTS> fingers{};
|
std::array<Core::HID::TouchFinger, MAX_POINTS> fingers{};
|
||||||
|
|
|
@ -8,16 +8,13 @@
|
||||||
#include "core/hid/emulated_devices.h"
|
#include "core/hid/emulated_devices.h"
|
||||||
#include "core/hid/hid_core.h"
|
#include "core/hid/hid_core.h"
|
||||||
#include "core/hle/service/hid/controllers/keyboard.h"
|
#include "core/hle/service/hid/controllers/keyboard.h"
|
||||||
|
#include "core/hle/service/hid/controllers/shared_memory_format.h"
|
||||||
|
|
||||||
namespace Service::HID {
|
namespace Service::HID {
|
||||||
constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3800;
|
|
||||||
|
|
||||||
Keyboard::Keyboard(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
|
Keyboard::Keyboard(Core::HID::HIDCore& hid_core_,
|
||||||
: ControllerBase{hid_core_} {
|
KeyboardSharedMemoryFormat& keyboard_shared_memory)
|
||||||
static_assert(SHARED_MEMORY_OFFSET + sizeof(KeyboardSharedMemory) < shared_memory_size,
|
: ControllerBase{hid_core_}, shared_memory{keyboard_shared_memory} {
|
||||||
"KeyboardSharedMemory is bigger than the shared memory");
|
|
||||||
shared_memory = std::construct_at(
|
|
||||||
reinterpret_cast<KeyboardSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
|
|
||||||
emulated_devices = hid_core.GetEmulatedDevices();
|
emulated_devices = hid_core.GetEmulatedDevices();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,12 +26,12 @@ void Keyboard::OnRelease() {}
|
||||||
|
|
||||||
void Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
|
void Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
|
||||||
if (!IsControllerActivated()) {
|
if (!IsControllerActivated()) {
|
||||||
shared_memory->keyboard_lifo.buffer_count = 0;
|
shared_memory.keyboard_lifo.buffer_count = 0;
|
||||||
shared_memory->keyboard_lifo.buffer_tail = 0;
|
shared_memory.keyboard_lifo.buffer_tail = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& last_entry = shared_memory->keyboard_lifo.ReadCurrentEntry().state;
|
const auto& last_entry = shared_memory.keyboard_lifo.ReadCurrentEntry().state;
|
||||||
next_state.sampling_number = last_entry.sampling_number + 1;
|
next_state.sampling_number = last_entry.sampling_number + 1;
|
||||||
|
|
||||||
if (Settings::values.keyboard_enabled) {
|
if (Settings::values.keyboard_enabled) {
|
||||||
|
@ -46,7 +43,7 @@ void Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
|
||||||
next_state.attribute.is_connected.Assign(1);
|
next_state.attribute.is_connected.Assign(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_memory->keyboard_lifo.WriteNextEntry(next_state);
|
shared_memory.keyboard_lifo.WriteNextEntry(next_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Service::HID
|
} // namespace Service::HID
|
||||||
|
|
|
@ -5,18 +5,16 @@
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_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/controllers/types/keyboard_types.h"
|
||||||
#include "core/hle/service/hid/ring_lifo.h"
|
#include "core/hle/service/hid/ring_lifo.h"
|
||||||
|
|
||||||
namespace Core::HID {
|
|
||||||
class EmulatedDevices;
|
|
||||||
struct KeyboardModifier;
|
|
||||||
struct KeyboardKey;
|
|
||||||
} // namespace Core::HID
|
|
||||||
|
|
||||||
namespace Service::HID {
|
namespace Service::HID {
|
||||||
|
struct KeyboardSharedMemoryFormat;
|
||||||
|
|
||||||
class Keyboard final : public ControllerBase {
|
class Keyboard final : public ControllerBase {
|
||||||
public:
|
public:
|
||||||
explicit Keyboard(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
|
explicit Keyboard(Core::HID::HIDCore& hid_core_,
|
||||||
|
KeyboardSharedMemoryFormat& keyboard_shared_memory);
|
||||||
~Keyboard() override;
|
~Keyboard() override;
|
||||||
|
|
||||||
// Called when the controller is initialized
|
// Called when the controller is initialized
|
||||||
|
@ -29,25 +27,8 @@ public:
|
||||||
void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
|
void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// This is nn::hid::detail::KeyboardState
|
|
||||||
struct KeyboardState {
|
|
||||||
s64 sampling_number{};
|
|
||||||
Core::HID::KeyboardModifier modifier{};
|
|
||||||
Core::HID::KeyboardAttribute attribute{};
|
|
||||||
Core::HID::KeyboardKey key{};
|
|
||||||
};
|
|
||||||
static_assert(sizeof(KeyboardState) == 0x30, "KeyboardState is an invalid size");
|
|
||||||
|
|
||||||
struct KeyboardSharedMemory {
|
|
||||||
// This is nn::hid::detail::KeyboardLifo
|
|
||||||
Lifo<KeyboardState, hid_entry_count> keyboard_lifo{};
|
|
||||||
static_assert(sizeof(keyboard_lifo) == 0x3D8, "keyboard_lifo is an invalid size");
|
|
||||||
INSERT_PADDING_WORDS(0xA);
|
|
||||||
};
|
|
||||||
static_assert(sizeof(KeyboardSharedMemory) == 0x400, "KeyboardSharedMemory is an invalid size");
|
|
||||||
|
|
||||||
KeyboardState next_state{};
|
KeyboardState next_state{};
|
||||||
KeyboardSharedMemory* shared_memory = nullptr;
|
KeyboardSharedMemoryFormat& shared_memory;
|
||||||
Core::HID::EmulatedDevices* emulated_devices = nullptr;
|
Core::HID::EmulatedDevices* emulated_devices = nullptr;
|
||||||
};
|
};
|
||||||
} // namespace Service::HID
|
} // namespace Service::HID
|
||||||
|
|
|
@ -8,15 +8,12 @@
|
||||||
#include "core/hid/emulated_devices.h"
|
#include "core/hid/emulated_devices.h"
|
||||||
#include "core/hid/hid_core.h"
|
#include "core/hid/hid_core.h"
|
||||||
#include "core/hle/service/hid/controllers/mouse.h"
|
#include "core/hle/service/hid/controllers/mouse.h"
|
||||||
|
#include "core/hle/service/hid/controllers/shared_memory_format.h"
|
||||||
|
|
||||||
namespace Service::HID {
|
namespace Service::HID {
|
||||||
constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3400;
|
|
||||||
|
|
||||||
Mouse::Mouse(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) : ControllerBase{hid_core_} {
|
Mouse::Mouse(Core::HID::HIDCore& hid_core_, MouseSharedMemoryFormat& mouse_shared_memory)
|
||||||
static_assert(SHARED_MEMORY_OFFSET + sizeof(MouseSharedMemory) < shared_memory_size,
|
: ControllerBase{hid_core_}, shared_memory{mouse_shared_memory} {
|
||||||
"MouseSharedMemory is bigger than the shared memory");
|
|
||||||
shared_memory = std::construct_at(
|
|
||||||
reinterpret_cast<MouseSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
|
|
||||||
emulated_devices = hid_core.GetEmulatedDevices();
|
emulated_devices = hid_core.GetEmulatedDevices();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,14 +24,14 @@ void Mouse::OnRelease() {}
|
||||||
|
|
||||||
void Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
|
void Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
|
||||||
if (!IsControllerActivated()) {
|
if (!IsControllerActivated()) {
|
||||||
shared_memory->mouse_lifo.buffer_count = 0;
|
shared_memory.mouse_lifo.buffer_count = 0;
|
||||||
shared_memory->mouse_lifo.buffer_tail = 0;
|
shared_memory.mouse_lifo.buffer_tail = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
next_state = {};
|
next_state = {};
|
||||||
|
|
||||||
const auto& last_entry = shared_memory->mouse_lifo.ReadCurrentEntry().state;
|
const auto& last_entry = shared_memory.mouse_lifo.ReadCurrentEntry().state;
|
||||||
next_state.sampling_number = last_entry.sampling_number + 1;
|
next_state.sampling_number = last_entry.sampling_number + 1;
|
||||||
|
|
||||||
if (Settings::values.mouse_enabled) {
|
if (Settings::values.mouse_enabled) {
|
||||||
|
@ -53,7 +50,7 @@ void Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
|
||||||
next_state.button = mouse_button_state;
|
next_state.button = mouse_button_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_memory->mouse_lifo.WriteNextEntry(next_state);
|
shared_memory.mouse_lifo.WriteNextEntry(next_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Service::HID
|
} // namespace Service::HID
|
||||||
|
|
|
@ -14,9 +14,11 @@ struct AnalogStickState;
|
||||||
} // namespace Core::HID
|
} // namespace Core::HID
|
||||||
|
|
||||||
namespace Service::HID {
|
namespace Service::HID {
|
||||||
|
struct MouseSharedMemoryFormat;
|
||||||
|
|
||||||
class Mouse final : public ControllerBase {
|
class Mouse final : public ControllerBase {
|
||||||
public:
|
public:
|
||||||
explicit Mouse(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
|
explicit Mouse(Core::HID::HIDCore& hid_core_, MouseSharedMemoryFormat& mouse_shared_memory);
|
||||||
~Mouse() override;
|
~Mouse() override;
|
||||||
|
|
||||||
// Called when the controller is initialized
|
// Called when the controller is initialized
|
||||||
|
@ -29,17 +31,9 @@ public:
|
||||||
void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
|
void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct MouseSharedMemory {
|
|
||||||
// This is nn::hid::detail::MouseLifo
|
|
||||||
Lifo<Core::HID::MouseState, hid_entry_count> mouse_lifo{};
|
|
||||||
static_assert(sizeof(mouse_lifo) == 0x350, "mouse_lifo is an invalid size");
|
|
||||||
INSERT_PADDING_WORDS(0x2C);
|
|
||||||
};
|
|
||||||
static_assert(sizeof(MouseSharedMemory) == 0x400, "MouseSharedMemory is an invalid size");
|
|
||||||
|
|
||||||
Core::HID::MouseState next_state{};
|
Core::HID::MouseState next_state{};
|
||||||
Core::HID::AnalogStickState last_mouse_wheel_state{};
|
Core::HID::AnalogStickState last_mouse_wheel_state{};
|
||||||
MouseSharedMemory* shared_memory = nullptr;
|
MouseSharedMemoryFormat& shared_memory;
|
||||||
Core::HID::EmulatedDevices* emulated_devices = nullptr;
|
Core::HID::EmulatedDevices* emulated_devices = nullptr;
|
||||||
};
|
};
|
||||||
} // namespace Service::HID
|
} // namespace Service::HID
|
||||||
|
|
|
@ -17,12 +17,12 @@
|
||||||
#include "core/hle/kernel/k_event.h"
|
#include "core/hle/kernel/k_event.h"
|
||||||
#include "core/hle/kernel/k_readable_event.h"
|
#include "core/hle/kernel/k_readable_event.h"
|
||||||
#include "core/hle/service/hid/controllers/npad.h"
|
#include "core/hle/service/hid/controllers/npad.h"
|
||||||
|
#include "core/hle/service/hid/controllers/shared_memory_format.h"
|
||||||
#include "core/hle/service/hid/errors.h"
|
#include "core/hle/service/hid/errors.h"
|
||||||
#include "core/hle/service/hid/hid_util.h"
|
#include "core/hle/service/hid/hid_util.h"
|
||||||
#include "core/hle/service/kernel_helpers.h"
|
#include "core/hle/service/kernel_helpers.h"
|
||||||
|
|
||||||
namespace Service::HID {
|
namespace Service::HID {
|
||||||
constexpr std::size_t NPAD_OFFSET = 0x9A00;
|
|
||||||
constexpr std::array<Core::HID::NpadIdType, 10> npad_id_list{
|
constexpr std::array<Core::HID::NpadIdType, 10> npad_id_list{
|
||||||
Core::HID::NpadIdType::Player1, Core::HID::NpadIdType::Player2, Core::HID::NpadIdType::Player3,
|
Core::HID::NpadIdType::Player1, Core::HID::NpadIdType::Player2, Core::HID::NpadIdType::Player3,
|
||||||
Core::HID::NpadIdType::Player4, Core::HID::NpadIdType::Player5, Core::HID::NpadIdType::Player6,
|
Core::HID::NpadIdType::Player4, Core::HID::NpadIdType::Player5, Core::HID::NpadIdType::Player6,
|
||||||
|
@ -30,14 +30,12 @@ constexpr std::array<Core::HID::NpadIdType, 10> npad_id_list{
|
||||||
Core::HID::NpadIdType::Handheld,
|
Core::HID::NpadIdType::Handheld,
|
||||||
};
|
};
|
||||||
|
|
||||||
NPad::NPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
|
NPad::NPad(Core::HID::HIDCore& hid_core_, NpadSharedMemoryFormat& npad_shared_memory_format,
|
||||||
KernelHelpers::ServiceContext& service_context_)
|
KernelHelpers::ServiceContext& service_context_)
|
||||||
: ControllerBase{hid_core_}, service_context{service_context_} {
|
: ControllerBase{hid_core_}, service_context{service_context_} {
|
||||||
static_assert(NPAD_OFFSET + (NPAD_COUNT * sizeof(NpadInternalState)) < shared_memory_size);
|
|
||||||
for (std::size_t i = 0; i < controller_data.size(); ++i) {
|
for (std::size_t i = 0; i < controller_data.size(); ++i) {
|
||||||
auto& controller = controller_data[i];
|
auto& controller = controller_data[i];
|
||||||
controller.shared_memory = std::construct_at(reinterpret_cast<NpadInternalState*>(
|
controller.shared_memory = &npad_shared_memory_format.npad_entry[i].internal_state;
|
||||||
raw_shared_memory_ + NPAD_OFFSET + (i * sizeof(NpadInternalState))));
|
|
||||||
controller.device = hid_core.GetEmulatedControllerByIndex(i);
|
controller.device = hid_core.GetEmulatedControllerByIndex(i);
|
||||||
controller.vibration[Core::HID::EmulatedDeviceIndex::LeftIndex].latest_vibration_value =
|
controller.vibration[Core::HID::EmulatedDeviceIndex::LeftIndex].latest_vibration_value =
|
||||||
Core::HID::DEFAULT_VIBRATION_VALUE;
|
Core::HID::DEFAULT_VIBRATION_VALUE;
|
||||||
|
@ -617,7 +615,7 @@ void NPad::SetHoldType(NpadJoyHoldType joy_hold_type) {
|
||||||
hold_type = joy_hold_type;
|
hold_type = joy_hold_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
NPad::NpadJoyHoldType NPad::GetHoldType() const {
|
NpadJoyHoldType NPad::GetHoldType() const {
|
||||||
return hold_type;
|
return hold_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -630,7 +628,7 @@ void NPad::SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_m
|
||||||
handheld_activation_mode = activation_mode;
|
handheld_activation_mode = activation_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
NPad::NpadHandheldActivationMode NPad::GetNpadHandheldActivationMode() const {
|
NpadHandheldActivationMode NPad::GetNpadHandheldActivationMode() const {
|
||||||
return handheld_activation_mode;
|
return handheld_activation_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -638,7 +636,7 @@ void NPad::SetNpadCommunicationMode(NpadCommunicationMode communication_mode_) {
|
||||||
communication_mode = communication_mode_;
|
communication_mode = communication_mode_;
|
||||||
}
|
}
|
||||||
|
|
||||||
NPad::NpadCommunicationMode NPad::GetNpadCommunicationMode() const {
|
NpadCommunicationMode NPad::GetNpadCommunicationMode() const {
|
||||||
return communication_mode;
|
return communication_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -978,27 +976,27 @@ Result NPad::ResetIsSixAxisSensorDeviceNewlyAssigned(
|
||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
NPad::SixAxisLifo& NPad::GetSixAxisFullkeyLifo(Core::HID::NpadIdType npad_id) {
|
NpadSixAxisSensorLifo& NPad::GetSixAxisFullkeyLifo(Core::HID::NpadIdType npad_id) {
|
||||||
return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_fullkey_lifo;
|
return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_fullkey_lifo;
|
||||||
}
|
}
|
||||||
|
|
||||||
NPad::SixAxisLifo& NPad::GetSixAxisHandheldLifo(Core::HID::NpadIdType npad_id) {
|
NpadSixAxisSensorLifo& NPad::GetSixAxisHandheldLifo(Core::HID::NpadIdType npad_id) {
|
||||||
return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_handheld_lifo;
|
return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_handheld_lifo;
|
||||||
}
|
}
|
||||||
|
|
||||||
NPad::SixAxisLifo& NPad::GetSixAxisDualLeftLifo(Core::HID::NpadIdType npad_id) {
|
NpadSixAxisSensorLifo& NPad::GetSixAxisDualLeftLifo(Core::HID::NpadIdType npad_id) {
|
||||||
return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_dual_left_lifo;
|
return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_dual_left_lifo;
|
||||||
}
|
}
|
||||||
|
|
||||||
NPad::SixAxisLifo& NPad::GetSixAxisDualRightLifo(Core::HID::NpadIdType npad_id) {
|
NpadSixAxisSensorLifo& NPad::GetSixAxisDualRightLifo(Core::HID::NpadIdType npad_id) {
|
||||||
return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_dual_right_lifo;
|
return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_dual_right_lifo;
|
||||||
}
|
}
|
||||||
|
|
||||||
NPad::SixAxisLifo& NPad::GetSixAxisLeftLifo(Core::HID::NpadIdType npad_id) {
|
NpadSixAxisSensorLifo& NPad::GetSixAxisLeftLifo(Core::HID::NpadIdType npad_id) {
|
||||||
return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_left_lifo;
|
return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_left_lifo;
|
||||||
}
|
}
|
||||||
|
|
||||||
NPad::SixAxisLifo& NPad::GetSixAxisRightLifo(Core::HID::NpadIdType npad_id) {
|
NpadSixAxisSensorLifo& NPad::GetSixAxisRightLifo(Core::HID::NpadIdType npad_id) {
|
||||||
return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_right_lifo;
|
return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_right_lifo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1343,7 +1341,7 @@ const Core::HID::SixAxisSensorProperties& NPad::GetSixaxisProperties(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NPad::AppletDetailedUiType NPad::GetAppletDetailedUiType(Core::HID::NpadIdType npad_id) {
|
AppletDetailedUiType NPad::GetAppletDetailedUiType(Core::HID::NpadIdType npad_id) {
|
||||||
const auto& shared_memory = GetControllerFromNpadIdType(npad_id).shared_memory;
|
const auto& shared_memory = GetControllerFromNpadIdType(npad_id).shared_memory;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
#include "core/hid/hid_types.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/controllers/types/npad_types.h"
|
||||||
#include "core/hle/service/hid/ring_lifo.h"
|
#include "core/hle/service/hid/ring_lifo.h"
|
||||||
|
|
||||||
namespace Core::HID {
|
namespace Core::HID {
|
||||||
|
@ -32,10 +33,13 @@ class ServiceContext;
|
||||||
union Result;
|
union Result;
|
||||||
|
|
||||||
namespace Service::HID {
|
namespace Service::HID {
|
||||||
|
struct NpadInternalState;
|
||||||
|
struct NpadSixAxisSensorLifo;
|
||||||
|
struct NpadSharedMemoryFormat;
|
||||||
|
|
||||||
class NPad final : public ControllerBase {
|
class NPad final : public ControllerBase {
|
||||||
public:
|
public:
|
||||||
explicit NPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
|
explicit NPad(Core::HID::HIDCore& hid_core_, NpadSharedMemoryFormat& npad_shared_memory_format,
|
||||||
KernelHelpers::ServiceContext& service_context_);
|
KernelHelpers::ServiceContext& service_context_);
|
||||||
~NPad() override;
|
~NPad() override;
|
||||||
|
|
||||||
|
@ -48,89 +52,6 @@ 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) override;
|
void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
|
||||||
|
|
||||||
// This is nn::hid::NpadJoyHoldType
|
|
||||||
enum class NpadJoyHoldType : u64 {
|
|
||||||
Vertical = 0,
|
|
||||||
Horizontal = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
// This is nn::hid::NpadJoyAssignmentMode
|
|
||||||
enum class NpadJoyAssignmentMode : u32 {
|
|
||||||
Dual = 0,
|
|
||||||
Single = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
// This is nn::hid::NpadJoyDeviceType
|
|
||||||
enum class NpadJoyDeviceType : s64 {
|
|
||||||
Left = 0,
|
|
||||||
Right = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
// This is nn::hid::NpadHandheldActivationMode
|
|
||||||
enum class NpadHandheldActivationMode : u64 {
|
|
||||||
Dual = 0,
|
|
||||||
Single = 1,
|
|
||||||
None = 2,
|
|
||||||
MaxActivationMode = 3,
|
|
||||||
};
|
|
||||||
|
|
||||||
// This is nn::hid::system::AppletFooterUiAttributesSet
|
|
||||||
struct AppletFooterUiAttributes {
|
|
||||||
INSERT_PADDING_BYTES(0x4);
|
|
||||||
};
|
|
||||||
|
|
||||||
// This is nn::hid::system::AppletFooterUiType
|
|
||||||
enum class AppletFooterUiType : u8 {
|
|
||||||
None = 0,
|
|
||||||
HandheldNone = 1,
|
|
||||||
HandheldJoyConLeftOnly = 2,
|
|
||||||
HandheldJoyConRightOnly = 3,
|
|
||||||
HandheldJoyConLeftJoyConRight = 4,
|
|
||||||
JoyDual = 5,
|
|
||||||
JoyDualLeftOnly = 6,
|
|
||||||
JoyDualRightOnly = 7,
|
|
||||||
JoyLeftHorizontal = 8,
|
|
||||||
JoyLeftVertical = 9,
|
|
||||||
JoyRightHorizontal = 10,
|
|
||||||
JoyRightVertical = 11,
|
|
||||||
SwitchProController = 12,
|
|
||||||
CompatibleProController = 13,
|
|
||||||
CompatibleJoyCon = 14,
|
|
||||||
LarkHvc1 = 15,
|
|
||||||
LarkHvc2 = 16,
|
|
||||||
LarkNesLeft = 17,
|
|
||||||
LarkNesRight = 18,
|
|
||||||
Lucia = 19,
|
|
||||||
Verification = 20,
|
|
||||||
Lagon = 21,
|
|
||||||
};
|
|
||||||
|
|
||||||
using AppletFooterUiVariant = u8;
|
|
||||||
|
|
||||||
// This is "nn::hid::system::AppletDetailedUiType".
|
|
||||||
struct AppletDetailedUiType {
|
|
||||||
AppletFooterUiVariant ui_variant;
|
|
||||||
INSERT_PADDING_BYTES(0x2);
|
|
||||||
AppletFooterUiType footer;
|
|
||||||
};
|
|
||||||
static_assert(sizeof(AppletDetailedUiType) == 0x4, "AppletDetailedUiType is an invalid size");
|
|
||||||
// This is nn::hid::NpadCommunicationMode
|
|
||||||
enum class NpadCommunicationMode : u64 {
|
|
||||||
Mode_5ms = 0,
|
|
||||||
Mode_10ms = 1,
|
|
||||||
Mode_15ms = 2,
|
|
||||||
Default = 3,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class NpadRevision : u32 {
|
|
||||||
Revision0 = 0,
|
|
||||||
Revision1 = 1,
|
|
||||||
Revision2 = 2,
|
|
||||||
Revision3 = 3,
|
|
||||||
};
|
|
||||||
|
|
||||||
using SixAxisLifo = Lifo<Core::HID::SixAxisSensorState, hid_entry_count>;
|
|
||||||
|
|
||||||
void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set);
|
void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set);
|
||||||
Core::HID::NpadStyleTag GetSupportedStyleSet() const;
|
Core::HID::NpadStyleTag GetSupportedStyleSet() const;
|
||||||
|
|
||||||
|
@ -188,12 +109,12 @@ public:
|
||||||
Result ResetIsSixAxisSensorDeviceNewlyAssigned(
|
Result ResetIsSixAxisSensorDeviceNewlyAssigned(
|
||||||
const Core::HID::SixAxisSensorHandle& sixaxis_handle);
|
const Core::HID::SixAxisSensorHandle& sixaxis_handle);
|
||||||
|
|
||||||
SixAxisLifo& GetSixAxisFullkeyLifo(Core::HID::NpadIdType npad_id);
|
NpadSixAxisSensorLifo& GetSixAxisFullkeyLifo(Core::HID::NpadIdType npad_id);
|
||||||
SixAxisLifo& GetSixAxisHandheldLifo(Core::HID::NpadIdType npad_id);
|
NpadSixAxisSensorLifo& GetSixAxisHandheldLifo(Core::HID::NpadIdType npad_id);
|
||||||
SixAxisLifo& GetSixAxisDualLeftLifo(Core::HID::NpadIdType npad_id);
|
NpadSixAxisSensorLifo& GetSixAxisDualLeftLifo(Core::HID::NpadIdType npad_id);
|
||||||
SixAxisLifo& GetSixAxisDualRightLifo(Core::HID::NpadIdType npad_id);
|
NpadSixAxisSensorLifo& GetSixAxisDualRightLifo(Core::HID::NpadIdType npad_id);
|
||||||
SixAxisLifo& GetSixAxisLeftLifo(Core::HID::NpadIdType npad_id);
|
NpadSixAxisSensorLifo& GetSixAxisLeftLifo(Core::HID::NpadIdType npad_id);
|
||||||
SixAxisLifo& GetSixAxisRightLifo(Core::HID::NpadIdType npad_id);
|
NpadSixAxisSensorLifo& GetSixAxisRightLifo(Core::HID::NpadIdType npad_id);
|
||||||
|
|
||||||
Result GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const;
|
Result GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const;
|
||||||
Result IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::NpadIdType npad_id,
|
Result IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::NpadIdType npad_id,
|
||||||
|
@ -221,214 +142,6 @@ public:
|
||||||
AppletDetailedUiType GetAppletDetailedUiType(Core::HID::NpadIdType npad_id);
|
AppletDetailedUiType GetAppletDetailedUiType(Core::HID::NpadIdType npad_id);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr std::size_t NPAD_COUNT = 10;
|
|
||||||
|
|
||||||
// This is nn::hid::detail::ColorAttribute
|
|
||||||
enum class ColorAttribute : u32 {
|
|
||||||
Ok = 0,
|
|
||||||
ReadError = 1,
|
|
||||||
NoController = 2,
|
|
||||||
};
|
|
||||||
static_assert(sizeof(ColorAttribute) == 4, "ColorAttribute is an invalid size");
|
|
||||||
|
|
||||||
// This is nn::hid::detail::NpadFullKeyColorState
|
|
||||||
struct NpadFullKeyColorState {
|
|
||||||
ColorAttribute attribute{ColorAttribute::NoController};
|
|
||||||
Core::HID::NpadControllerColor fullkey{};
|
|
||||||
};
|
|
||||||
static_assert(sizeof(NpadFullKeyColorState) == 0xC, "NpadFullKeyColorState is an invalid size");
|
|
||||||
|
|
||||||
// This is nn::hid::detail::NpadJoyColorState
|
|
||||||
struct NpadJoyColorState {
|
|
||||||
ColorAttribute attribute{ColorAttribute::NoController};
|
|
||||||
Core::HID::NpadControllerColor left{};
|
|
||||||
Core::HID::NpadControllerColor right{};
|
|
||||||
};
|
|
||||||
static_assert(sizeof(NpadJoyColorState) == 0x14, "NpadJoyColorState is an invalid size");
|
|
||||||
|
|
||||||
// This is nn::hid::NpadAttribute
|
|
||||||
struct NpadAttribute {
|
|
||||||
union {
|
|
||||||
u32 raw{};
|
|
||||||
BitField<0, 1, u32> is_connected;
|
|
||||||
BitField<1, 1, u32> is_wired;
|
|
||||||
BitField<2, 1, u32> is_left_connected;
|
|
||||||
BitField<3, 1, u32> is_left_wired;
|
|
||||||
BitField<4, 1, u32> is_right_connected;
|
|
||||||
BitField<5, 1, u32> is_right_wired;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
static_assert(sizeof(NpadAttribute) == 4, "NpadAttribute is an invalid size");
|
|
||||||
|
|
||||||
// This is nn::hid::NpadFullKeyState
|
|
||||||
// This is nn::hid::NpadHandheldState
|
|
||||||
// This is nn::hid::NpadJoyDualState
|
|
||||||
// This is nn::hid::NpadJoyLeftState
|
|
||||||
// This is nn::hid::NpadJoyRightState
|
|
||||||
// This is nn::hid::NpadPalmaState
|
|
||||||
// This is nn::hid::NpadSystemExtState
|
|
||||||
struct NPadGenericState {
|
|
||||||
s64_le sampling_number{};
|
|
||||||
Core::HID::NpadButtonState npad_buttons{};
|
|
||||||
Core::HID::AnalogStickState l_stick{};
|
|
||||||
Core::HID::AnalogStickState r_stick{};
|
|
||||||
NpadAttribute connection_status{};
|
|
||||||
INSERT_PADDING_BYTES(4); // Reserved
|
|
||||||
};
|
|
||||||
static_assert(sizeof(NPadGenericState) == 0x28, "NPadGenericState is an invalid size");
|
|
||||||
|
|
||||||
// This is nn::hid::server::NpadGcTriggerState
|
|
||||||
struct NpadGcTriggerState {
|
|
||||||
s64 sampling_number{};
|
|
||||||
s32 l_analog{};
|
|
||||||
s32 r_analog{};
|
|
||||||
};
|
|
||||||
static_assert(sizeof(NpadGcTriggerState) == 0x10, "NpadGcTriggerState is an invalid size");
|
|
||||||
|
|
||||||
// This is nn::hid::NpadSystemProperties
|
|
||||||
struct NPadSystemProperties {
|
|
||||||
union {
|
|
||||||
s64 raw{};
|
|
||||||
BitField<0, 1, s64> is_charging_joy_dual;
|
|
||||||
BitField<1, 1, s64> is_charging_joy_left;
|
|
||||||
BitField<2, 1, s64> is_charging_joy_right;
|
|
||||||
BitField<3, 1, s64> is_powered_joy_dual;
|
|
||||||
BitField<4, 1, s64> is_powered_joy_left;
|
|
||||||
BitField<5, 1, s64> is_powered_joy_right;
|
|
||||||
BitField<9, 1, s64> is_system_unsupported_button;
|
|
||||||
BitField<10, 1, s64> is_system_ext_unsupported_button;
|
|
||||||
BitField<11, 1, s64> is_vertical;
|
|
||||||
BitField<12, 1, s64> is_horizontal;
|
|
||||||
BitField<13, 1, s64> use_plus;
|
|
||||||
BitField<14, 1, s64> use_minus;
|
|
||||||
BitField<15, 1, s64> use_directional_buttons;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
static_assert(sizeof(NPadSystemProperties) == 0x8, "NPadSystemProperties is an invalid size");
|
|
||||||
|
|
||||||
// This is nn::hid::NpadSystemButtonProperties
|
|
||||||
struct NpadSystemButtonProperties {
|
|
||||||
union {
|
|
||||||
s32 raw{};
|
|
||||||
BitField<0, 1, s32> is_home_button_protection_enabled;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
static_assert(sizeof(NpadSystemButtonProperties) == 0x4,
|
|
||||||
"NPadButtonProperties is an invalid size");
|
|
||||||
|
|
||||||
// This is nn::hid::system::DeviceType
|
|
||||||
struct DeviceType {
|
|
||||||
union {
|
|
||||||
u32 raw{};
|
|
||||||
BitField<0, 1, s32> fullkey;
|
|
||||||
BitField<1, 1, s32> debug_pad;
|
|
||||||
BitField<2, 1, s32> handheld_left;
|
|
||||||
BitField<3, 1, s32> handheld_right;
|
|
||||||
BitField<4, 1, s32> joycon_left;
|
|
||||||
BitField<5, 1, s32> joycon_right;
|
|
||||||
BitField<6, 1, s32> palma;
|
|
||||||
BitField<7, 1, s32> lark_hvc_left;
|
|
||||||
BitField<8, 1, s32> lark_hvc_right;
|
|
||||||
BitField<9, 1, s32> lark_nes_left;
|
|
||||||
BitField<10, 1, s32> lark_nes_right;
|
|
||||||
BitField<11, 1, s32> handheld_lark_hvc_left;
|
|
||||||
BitField<12, 1, s32> handheld_lark_hvc_right;
|
|
||||||
BitField<13, 1, s32> handheld_lark_nes_left;
|
|
||||||
BitField<14, 1, s32> handheld_lark_nes_right;
|
|
||||||
BitField<15, 1, s32> lucia;
|
|
||||||
BitField<16, 1, s32> lagon;
|
|
||||||
BitField<17, 1, s32> lager;
|
|
||||||
BitField<31, 1, s32> system;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// This is nn::hid::detail::NfcXcdDeviceHandleStateImpl
|
|
||||||
struct NfcXcdDeviceHandleStateImpl {
|
|
||||||
u64 handle{};
|
|
||||||
bool is_available{};
|
|
||||||
bool is_activated{};
|
|
||||||
INSERT_PADDING_BYTES(0x6); // Reserved
|
|
||||||
u64 sampling_number{};
|
|
||||||
};
|
|
||||||
static_assert(sizeof(NfcXcdDeviceHandleStateImpl) == 0x18,
|
|
||||||
"NfcXcdDeviceHandleStateImpl is an invalid size");
|
|
||||||
|
|
||||||
// This is nn::hid::NpadLarkType
|
|
||||||
enum class NpadLarkType : u32 {
|
|
||||||
Invalid,
|
|
||||||
H1,
|
|
||||||
H2,
|
|
||||||
NL,
|
|
||||||
NR,
|
|
||||||
};
|
|
||||||
|
|
||||||
// This is nn::hid::NpadLuciaType
|
|
||||||
enum class NpadLuciaType : u32 {
|
|
||||||
Invalid,
|
|
||||||
J,
|
|
||||||
E,
|
|
||||||
U,
|
|
||||||
};
|
|
||||||
|
|
||||||
// This is nn::hid::NpadLagonType
|
|
||||||
enum class NpadLagonType : u32 {
|
|
||||||
Invalid,
|
|
||||||
};
|
|
||||||
|
|
||||||
// This is nn::hid::NpadLagerType
|
|
||||||
enum class NpadLagerType : u32 {
|
|
||||||
Invalid,
|
|
||||||
J,
|
|
||||||
E,
|
|
||||||
U,
|
|
||||||
};
|
|
||||||
|
|
||||||
// This is nn::hid::detail::NpadInternalState
|
|
||||||
struct NpadInternalState {
|
|
||||||
Core::HID::NpadStyleTag style_tag{Core::HID::NpadStyleSet::None};
|
|
||||||
NpadJoyAssignmentMode assignment_mode{NpadJoyAssignmentMode::Dual};
|
|
||||||
NpadFullKeyColorState fullkey_color{};
|
|
||||||
NpadJoyColorState joycon_color{};
|
|
||||||
Lifo<NPadGenericState, hid_entry_count> fullkey_lifo{};
|
|
||||||
Lifo<NPadGenericState, hid_entry_count> handheld_lifo{};
|
|
||||||
Lifo<NPadGenericState, hid_entry_count> joy_dual_lifo{};
|
|
||||||
Lifo<NPadGenericState, hid_entry_count> joy_left_lifo{};
|
|
||||||
Lifo<NPadGenericState, hid_entry_count> joy_right_lifo{};
|
|
||||||
Lifo<NPadGenericState, hid_entry_count> palma_lifo{};
|
|
||||||
Lifo<NPadGenericState, hid_entry_count> system_ext_lifo{};
|
|
||||||
Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_fullkey_lifo{};
|
|
||||||
Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_handheld_lifo{};
|
|
||||||
Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_dual_left_lifo{};
|
|
||||||
Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_dual_right_lifo{};
|
|
||||||
Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_left_lifo{};
|
|
||||||
Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_right_lifo{};
|
|
||||||
DeviceType device_type{};
|
|
||||||
INSERT_PADDING_BYTES(0x4); // Reserved
|
|
||||||
NPadSystemProperties system_properties{};
|
|
||||||
NpadSystemButtonProperties button_properties{};
|
|
||||||
Core::HID::NpadBatteryLevel battery_level_dual{};
|
|
||||||
Core::HID::NpadBatteryLevel battery_level_left{};
|
|
||||||
Core::HID::NpadBatteryLevel battery_level_right{};
|
|
||||||
AppletFooterUiAttributes applet_footer_attributes{};
|
|
||||||
AppletFooterUiType applet_footer_type{AppletFooterUiType::None};
|
|
||||||
INSERT_PADDING_BYTES(0x5B); // Reserved
|
|
||||||
INSERT_PADDING_BYTES(0x20); // Unknown
|
|
||||||
Lifo<NpadGcTriggerState, hid_entry_count> gc_trigger_lifo{};
|
|
||||||
NpadLarkType lark_type_l_and_main{};
|
|
||||||
NpadLarkType lark_type_r{};
|
|
||||||
NpadLuciaType lucia_type{};
|
|
||||||
NpadLagonType lagon_type{};
|
|
||||||
NpadLagerType lager_type{};
|
|
||||||
Core::HID::SixAxisSensorProperties sixaxis_fullkey_properties;
|
|
||||||
Core::HID::SixAxisSensorProperties sixaxis_handheld_properties;
|
|
||||||
Core::HID::SixAxisSensorProperties sixaxis_dual_left_properties;
|
|
||||||
Core::HID::SixAxisSensorProperties sixaxis_dual_right_properties;
|
|
||||||
Core::HID::SixAxisSensorProperties sixaxis_left_properties;
|
|
||||||
Core::HID::SixAxisSensorProperties sixaxis_right_properties;
|
|
||||||
INSERT_PADDING_BYTES(0xc06); // Unknown
|
|
||||||
};
|
|
||||||
static_assert(sizeof(NpadInternalState) == 0x5000, "NpadInternalState is an invalid size");
|
|
||||||
|
|
||||||
struct VibrationData {
|
struct VibrationData {
|
||||||
bool device_mounted{};
|
bool device_mounted{};
|
||||||
Core::HID::VibrationValue latest_vibration_value{};
|
Core::HID::VibrationValue latest_vibration_value{};
|
||||||
|
|
|
@ -12,8 +12,7 @@
|
||||||
|
|
||||||
namespace Service::HID {
|
namespace Service::HID {
|
||||||
|
|
||||||
Palma::Palma(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
|
Palma::Palma(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service_context_)
|
||||||
KernelHelpers::ServiceContext& service_context_)
|
|
||||||
: ControllerBase{hid_core_}, service_context{service_context_} {
|
: ControllerBase{hid_core_}, service_context{service_context_} {
|
||||||
controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other);
|
controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other);
|
||||||
operation_complete_event = service_context.CreateEvent("hid:PalmaOperationCompleteEvent");
|
operation_complete_event = service_context.CreateEvent("hid:PalmaOperationCompleteEvent");
|
||||||
|
|
|
@ -97,8 +97,7 @@ public:
|
||||||
static_assert(sizeof(PalmaConnectionHandle) == 0x8,
|
static_assert(sizeof(PalmaConnectionHandle) == 0x8,
|
||||||
"PalmaConnectionHandle has incorrect size.");
|
"PalmaConnectionHandle has incorrect size.");
|
||||||
|
|
||||||
explicit Palma(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
|
explicit Palma(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service_context_);
|
||||||
KernelHelpers::ServiceContext& service_context_);
|
|
||||||
~Palma() override;
|
~Palma() override;
|
||||||
|
|
||||||
// Called when the controller is initialized
|
// Called when the controller is initialized
|
||||||
|
|
239
src/core/hle/service/hid/controllers/shared_memory_format.h
Executable file
239
src/core/hle/service/hid/controllers/shared_memory_format.h
Executable file
|
@ -0,0 +1,239 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/common_funcs.h"
|
||||||
|
#include "common/common_types.h"
|
||||||
|
#include "common/vector_math.h"
|
||||||
|
#include "core/hid/hid_types.h"
|
||||||
|
#include "core/hle/service/hid//controllers/types/debug_pad_types.h"
|
||||||
|
#include "core/hle/service/hid//controllers/types/keyboard_types.h"
|
||||||
|
#include "core/hle/service/hid//controllers/types/mouse_types.h"
|
||||||
|
#include "core/hle/service/hid//controllers/types/npad_types.h"
|
||||||
|
#include "core/hle/service/hid//controllers/types/touch_types.h"
|
||||||
|
#include "core/hle/service/hid/ring_lifo.h"
|
||||||
|
|
||||||
|
namespace Service::HID {
|
||||||
|
static const std::size_t HidEntryCount = 17;
|
||||||
|
|
||||||
|
struct CommonHeader {
|
||||||
|
s64 timestamp{};
|
||||||
|
s64 total_entry_count{};
|
||||||
|
s64 last_entry_index{};
|
||||||
|
s64 entry_count{};
|
||||||
|
};
|
||||||
|
static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size");
|
||||||
|
|
||||||
|
// This is nn::hid::detail::DebugPadSharedMemoryFormat
|
||||||
|
struct DebugPadSharedMemoryFormat {
|
||||||
|
// This is nn::hid::detail::DebugPadLifo
|
||||||
|
Lifo<DebugPadState, HidEntryCount> debug_pad_lifo{};
|
||||||
|
static_assert(sizeof(debug_pad_lifo) == 0x2C8, "debug_pad_lifo is an invalid size");
|
||||||
|
INSERT_PADDING_WORDS(0x4E);
|
||||||
|
};
|
||||||
|
static_assert(sizeof(DebugPadSharedMemoryFormat) == 0x400,
|
||||||
|
"DebugPadSharedMemoryFormat is an invalid size");
|
||||||
|
|
||||||
|
// This is nn::hid::detail::TouchScreenSharedMemoryFormat
|
||||||
|
struct TouchScreenSharedMemoryFormat {
|
||||||
|
// This is nn::hid::detail::TouchScreenLifo
|
||||||
|
Lifo<TouchScreenState, HidEntryCount> touch_screen_lifo{};
|
||||||
|
static_assert(sizeof(touch_screen_lifo) == 0x2C38, "touch_screen_lifo is an invalid size");
|
||||||
|
INSERT_PADDING_WORDS(0xF2);
|
||||||
|
};
|
||||||
|
static_assert(sizeof(TouchScreenSharedMemoryFormat) == 0x3000,
|
||||||
|
"TouchScreenSharedMemoryFormat is an invalid size");
|
||||||
|
|
||||||
|
// This is nn::hid::detail::MouseSharedMemoryFormat
|
||||||
|
struct MouseSharedMemoryFormat {
|
||||||
|
// This is nn::hid::detail::MouseLifo
|
||||||
|
Lifo<Core::HID::MouseState, HidEntryCount> mouse_lifo{};
|
||||||
|
static_assert(sizeof(mouse_lifo) == 0x350, "mouse_lifo is an invalid size");
|
||||||
|
INSERT_PADDING_WORDS(0x2C);
|
||||||
|
};
|
||||||
|
static_assert(sizeof(MouseSharedMemoryFormat) == 0x400,
|
||||||
|
"MouseSharedMemoryFormat is an invalid size");
|
||||||
|
|
||||||
|
// This is nn::hid::detail::KeyboardSharedMemoryFormat
|
||||||
|
struct KeyboardSharedMemoryFormat {
|
||||||
|
// This is nn::hid::detail::KeyboardLifo
|
||||||
|
Lifo<KeyboardState, HidEntryCount> keyboard_lifo{};
|
||||||
|
static_assert(sizeof(keyboard_lifo) == 0x3D8, "keyboard_lifo is an invalid size");
|
||||||
|
INSERT_PADDING_WORDS(0xA);
|
||||||
|
};
|
||||||
|
static_assert(sizeof(KeyboardSharedMemoryFormat) == 0x400,
|
||||||
|
"KeyboardSharedMemoryFormat is an invalid size");
|
||||||
|
|
||||||
|
// This is nn::hid::detail::DigitizerSharedMemoryFormat
|
||||||
|
struct DigitizerSharedMemoryFormat {
|
||||||
|
CommonHeader header;
|
||||||
|
INSERT_PADDING_BYTES(0xFE0);
|
||||||
|
};
|
||||||
|
static_assert(sizeof(DigitizerSharedMemoryFormat) == 0x1000,
|
||||||
|
"DigitizerSharedMemoryFormat is an invalid size");
|
||||||
|
|
||||||
|
// This is nn::hid::detail::HomeButtonSharedMemoryFormat
|
||||||
|
struct HomeButtonSharedMemoryFormat {
|
||||||
|
CommonHeader header;
|
||||||
|
INSERT_PADDING_BYTES(0x1E0);
|
||||||
|
};
|
||||||
|
static_assert(sizeof(HomeButtonSharedMemoryFormat) == 0x200,
|
||||||
|
"HomeButtonSharedMemoryFormat is an invalid size");
|
||||||
|
|
||||||
|
// This is nn::hid::detail::SleepButtonSharedMemoryFormat
|
||||||
|
struct SleepButtonSharedMemoryFormat {
|
||||||
|
CommonHeader header;
|
||||||
|
INSERT_PADDING_BYTES(0x1E0);
|
||||||
|
};
|
||||||
|
static_assert(sizeof(SleepButtonSharedMemoryFormat) == 0x200,
|
||||||
|
"SleepButtonSharedMemoryFormat is an invalid size");
|
||||||
|
|
||||||
|
// This is nn::hid::detail::CaptureButtonSharedMemoryFormat
|
||||||
|
struct CaptureButtonSharedMemoryFormat {
|
||||||
|
CommonHeader header;
|
||||||
|
INSERT_PADDING_BYTES(0x1E0);
|
||||||
|
};
|
||||||
|
static_assert(sizeof(CaptureButtonSharedMemoryFormat) == 0x200,
|
||||||
|
"CaptureButtonSharedMemoryFormat is an invalid size");
|
||||||
|
|
||||||
|
// This is nn::hid::detail::InputDetectorSharedMemoryFormat
|
||||||
|
struct InputDetectorSharedMemoryFormat {
|
||||||
|
CommonHeader header;
|
||||||
|
INSERT_PADDING_BYTES(0x7E0);
|
||||||
|
};
|
||||||
|
static_assert(sizeof(InputDetectorSharedMemoryFormat) == 0x800,
|
||||||
|
"InputDetectorSharedMemoryFormat is an invalid size");
|
||||||
|
|
||||||
|
// This is nn::hid::detail::UniquePadSharedMemoryFormat
|
||||||
|
struct UniquePadSharedMemoryFormat {
|
||||||
|
CommonHeader header;
|
||||||
|
INSERT_PADDING_BYTES(0x3FE0);
|
||||||
|
};
|
||||||
|
static_assert(sizeof(UniquePadSharedMemoryFormat) == 0x4000,
|
||||||
|
"UniquePadSharedMemoryFormat is an invalid size");
|
||||||
|
|
||||||
|
// This is nn::hid::detail::NpadSixAxisSensorLifo
|
||||||
|
struct NpadSixAxisSensorLifo {
|
||||||
|
Lifo<Core::HID::SixAxisSensorState, HidEntryCount> lifo;
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is nn::hid::detail::NpadInternalState
|
||||||
|
struct NpadInternalState {
|
||||||
|
Core::HID::NpadStyleTag style_tag{Core::HID::NpadStyleSet::None};
|
||||||
|
NpadJoyAssignmentMode assignment_mode{NpadJoyAssignmentMode::Dual};
|
||||||
|
NpadFullKeyColorState fullkey_color{};
|
||||||
|
NpadJoyColorState joycon_color{};
|
||||||
|
Lifo<NPadGenericState, HidEntryCount> fullkey_lifo{};
|
||||||
|
Lifo<NPadGenericState, HidEntryCount> handheld_lifo{};
|
||||||
|
Lifo<NPadGenericState, HidEntryCount> joy_dual_lifo{};
|
||||||
|
Lifo<NPadGenericState, HidEntryCount> joy_left_lifo{};
|
||||||
|
Lifo<NPadGenericState, HidEntryCount> joy_right_lifo{};
|
||||||
|
Lifo<NPadGenericState, HidEntryCount> palma_lifo{};
|
||||||
|
Lifo<NPadGenericState, HidEntryCount> system_ext_lifo{};
|
||||||
|
NpadSixAxisSensorLifo sixaxis_fullkey_lifo{};
|
||||||
|
NpadSixAxisSensorLifo sixaxis_handheld_lifo{};
|
||||||
|
NpadSixAxisSensorLifo sixaxis_dual_left_lifo{};
|
||||||
|
NpadSixAxisSensorLifo sixaxis_dual_right_lifo{};
|
||||||
|
NpadSixAxisSensorLifo sixaxis_left_lifo{};
|
||||||
|
NpadSixAxisSensorLifo sixaxis_right_lifo{};
|
||||||
|
DeviceType device_type{};
|
||||||
|
INSERT_PADDING_BYTES(0x4); // Reserved
|
||||||
|
NPadSystemProperties system_properties{};
|
||||||
|
NpadSystemButtonProperties button_properties{};
|
||||||
|
Core::HID::NpadBatteryLevel battery_level_dual{};
|
||||||
|
Core::HID::NpadBatteryLevel battery_level_left{};
|
||||||
|
Core::HID::NpadBatteryLevel battery_level_right{};
|
||||||
|
AppletFooterUiAttributes applet_footer_attributes{};
|
||||||
|
AppletFooterUiType applet_footer_type{AppletFooterUiType::None};
|
||||||
|
INSERT_PADDING_BYTES(0x5B); // Reserved
|
||||||
|
INSERT_PADDING_BYTES(0x20); // Unknown
|
||||||
|
Lifo<NpadGcTriggerState, HidEntryCount> gc_trigger_lifo{};
|
||||||
|
NpadLarkType lark_type_l_and_main{};
|
||||||
|
NpadLarkType lark_type_r{};
|
||||||
|
NpadLuciaType lucia_type{};
|
||||||
|
NpadLagerType lager_type{};
|
||||||
|
Core::HID::SixAxisSensorProperties sixaxis_fullkey_properties;
|
||||||
|
Core::HID::SixAxisSensorProperties sixaxis_handheld_properties;
|
||||||
|
Core::HID::SixAxisSensorProperties sixaxis_dual_left_properties;
|
||||||
|
Core::HID::SixAxisSensorProperties sixaxis_dual_right_properties;
|
||||||
|
Core::HID::SixAxisSensorProperties sixaxis_left_properties;
|
||||||
|
Core::HID::SixAxisSensorProperties sixaxis_right_properties;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(NpadInternalState) == 0x43F8, "NpadInternalState is an invalid size");
|
||||||
|
|
||||||
|
// This is nn::hid::detail::NpadSharedMemoryEntry
|
||||||
|
struct NpadSharedMemoryEntry {
|
||||||
|
NpadInternalState internal_state;
|
||||||
|
INSERT_PADDING_BYTES(0xC08);
|
||||||
|
};
|
||||||
|
static_assert(sizeof(NpadSharedMemoryEntry) == 0x5000, "NpadSharedMemoryEntry is an invalid size");
|
||||||
|
|
||||||
|
// This is nn::hid::detail::NpadSharedMemoryFormat
|
||||||
|
struct NpadSharedMemoryFormat {
|
||||||
|
std::array<NpadSharedMemoryEntry, NPAD_COUNT> npad_entry;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(NpadSharedMemoryFormat) == 0x32000,
|
||||||
|
"NpadSharedMemoryFormat is an invalid size");
|
||||||
|
|
||||||
|
// This is nn::hid::detail::GestureSharedMemoryFormat
|
||||||
|
struct GestureSharedMemoryFormat {
|
||||||
|
// This is nn::hid::detail::GestureLifo
|
||||||
|
Lifo<GestureState, HidEntryCount> gesture_lifo{};
|
||||||
|
static_assert(sizeof(gesture_lifo) == 0x708, "gesture_lifo is an invalid size");
|
||||||
|
INSERT_PADDING_WORDS(0x3E);
|
||||||
|
};
|
||||||
|
static_assert(sizeof(GestureSharedMemoryFormat) == 0x800,
|
||||||
|
"GestureSharedMemoryFormat is an invalid size");
|
||||||
|
|
||||||
|
// This is nn::hid::detail::ConsoleSixAxisSensorSharedMemoryFormat
|
||||||
|
struct ConsoleSixAxisSensorSharedMemoryFormat {
|
||||||
|
u64 sampling_number{};
|
||||||
|
bool is_seven_six_axis_sensor_at_rest{};
|
||||||
|
INSERT_PADDING_BYTES(3); // padding
|
||||||
|
f32 verticalization_error{};
|
||||||
|
Common::Vec3f gyro_bias{};
|
||||||
|
INSERT_PADDING_BYTES(4); // padding
|
||||||
|
};
|
||||||
|
static_assert(sizeof(ConsoleSixAxisSensorSharedMemoryFormat) == 0x20,
|
||||||
|
"ConsoleSixAxisSensorSharedMemoryFormat is an invalid size");
|
||||||
|
|
||||||
|
struct SharedMemoryFormat {
|
||||||
|
void Initialize() {}
|
||||||
|
|
||||||
|
DebugPadSharedMemoryFormat debug_pad;
|
||||||
|
TouchScreenSharedMemoryFormat touch_screen;
|
||||||
|
MouseSharedMemoryFormat mouse;
|
||||||
|
KeyboardSharedMemoryFormat keyboard;
|
||||||
|
DigitizerSharedMemoryFormat digitizer;
|
||||||
|
HomeButtonSharedMemoryFormat home_button;
|
||||||
|
SleepButtonSharedMemoryFormat sleep_button;
|
||||||
|
CaptureButtonSharedMemoryFormat capture_button;
|
||||||
|
InputDetectorSharedMemoryFormat input_detector;
|
||||||
|
UniquePadSharedMemoryFormat unique_pad;
|
||||||
|
NpadSharedMemoryFormat npad;
|
||||||
|
GestureSharedMemoryFormat gesture;
|
||||||
|
ConsoleSixAxisSensorSharedMemoryFormat console;
|
||||||
|
INSERT_PADDING_BYTES(0x19E0);
|
||||||
|
MouseSharedMemoryFormat debug_mouse;
|
||||||
|
INSERT_PADDING_BYTES(0x2000);
|
||||||
|
};
|
||||||
|
static_assert(offsetof(SharedMemoryFormat, debug_pad) == 0x0, "debug_pad has wrong offset");
|
||||||
|
static_assert(offsetof(SharedMemoryFormat, touch_screen) == 0x400, "touch_screen has wrong offset");
|
||||||
|
static_assert(offsetof(SharedMemoryFormat, mouse) == 0x3400, "mouse has wrong offset");
|
||||||
|
static_assert(offsetof(SharedMemoryFormat, keyboard) == 0x3800, "keyboard has wrong offset");
|
||||||
|
static_assert(offsetof(SharedMemoryFormat, digitizer) == 0x3C00, "digitizer has wrong offset");
|
||||||
|
static_assert(offsetof(SharedMemoryFormat, home_button) == 0x4C00, "home_button has wrong offset");
|
||||||
|
static_assert(offsetof(SharedMemoryFormat, sleep_button) == 0x4E00,
|
||||||
|
"sleep_button has wrong offset");
|
||||||
|
static_assert(offsetof(SharedMemoryFormat, capture_button) == 0x5000,
|
||||||
|
"capture_button has wrong offset");
|
||||||
|
static_assert(offsetof(SharedMemoryFormat, input_detector) == 0x5200,
|
||||||
|
"input_detector has wrong offset");
|
||||||
|
static_assert(offsetof(SharedMemoryFormat, npad) == 0x9A00, "npad has wrong offset");
|
||||||
|
static_assert(offsetof(SharedMemoryFormat, gesture) == 0x3BA00, "gesture has wrong offset");
|
||||||
|
static_assert(offsetof(SharedMemoryFormat, console) == 0x3C200, "console has wrong offset");
|
||||||
|
static_assert(offsetof(SharedMemoryFormat, debug_mouse) == 0x3DC00, "debug_mouse has wrong offset");
|
||||||
|
static_assert(sizeof(SharedMemoryFormat) == 0x40000, "SharedMemoryFormat is an invalid size");
|
||||||
|
|
||||||
|
} // namespace Service::HID
|
49
src/core/hle/service/hid/controllers/shared_memory_holder.cpp
Executable file
49
src/core/hle/service/hid/controllers/shared_memory_holder.cpp
Executable file
|
@ -0,0 +1,49 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#include "core/core.h"
|
||||||
|
#include "core/hle/kernel/k_shared_memory.h"
|
||||||
|
#include "core/hle/service/hid/controllers/shared_memory_format.h"
|
||||||
|
#include "core/hle/service/hid/controllers/shared_memory_holder.h"
|
||||||
|
#include "core/hle/service/hid/errors.h"
|
||||||
|
|
||||||
|
namespace Service::HID {
|
||||||
|
SharedMemoryHolder::SharedMemoryHolder() {}
|
||||||
|
|
||||||
|
Result SharedMemoryHolder::Initialize(Core::System& system) {
|
||||||
|
shared_memory = Kernel::KSharedMemory::Create(system.Kernel());
|
||||||
|
const Result result = shared_memory->Initialize(
|
||||||
|
system.DeviceMemory(), nullptr, Kernel::Svc::MemoryPermission::None,
|
||||||
|
Kernel::Svc::MemoryPermission::Read, sizeof(SharedMemoryFormat));
|
||||||
|
if (result.IsError()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
Kernel::KSharedMemory::Register(system.Kernel(), shared_memory);
|
||||||
|
|
||||||
|
is_created = true;
|
||||||
|
is_mapped = true;
|
||||||
|
address = std::construct_at(reinterpret_cast<SharedMemoryFormat*>(shared_memory->GetPointer()));
|
||||||
|
return ResultSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SharedMemoryHolder::Finalize() {
|
||||||
|
if (address != nullptr) {
|
||||||
|
shared_memory->Close();
|
||||||
|
}
|
||||||
|
is_created = false;
|
||||||
|
is_mapped = false;
|
||||||
|
address = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SharedMemoryHolder::IsMapped() {
|
||||||
|
return is_mapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
SharedMemoryFormat* SharedMemoryHolder::GetAddress() {
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
Kernel::KSharedMemory* SharedMemoryHolder::GetHandle() {
|
||||||
|
return shared_memory;
|
||||||
|
}
|
||||||
|
} // namespace Service::HID
|
44
src/core/hle/service/hid/controllers/shared_memory_holder.h
Executable file
44
src/core/hle/service/hid/controllers/shared_memory_holder.h
Executable file
|
@ -0,0 +1,44 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/common_types.h"
|
||||||
|
#include "core/hle/result.h"
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class System;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Kernel {
|
||||||
|
class KSharedMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Service::HID {
|
||||||
|
struct SharedMemoryFormat;
|
||||||
|
|
||||||
|
// This is nn::hid::detail::SharedMemoryHolder
|
||||||
|
class SharedMemoryHolder {
|
||||||
|
public:
|
||||||
|
SharedMemoryHolder();
|
||||||
|
|
||||||
|
Result Initialize(Core::System& system);
|
||||||
|
void Finalize();
|
||||||
|
|
||||||
|
bool IsMapped();
|
||||||
|
SharedMemoryFormat* GetAddress();
|
||||||
|
Kernel::KSharedMemory* GetHandle();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool is_owner{};
|
||||||
|
bool is_created{};
|
||||||
|
bool is_mapped{};
|
||||||
|
INSERT_PADDING_BYTES(0x5);
|
||||||
|
Kernel::KSharedMemory* shared_memory;
|
||||||
|
INSERT_PADDING_BYTES(0x38);
|
||||||
|
SharedMemoryFormat* address = nullptr;
|
||||||
|
};
|
||||||
|
// Correct size is 0x50 bytes
|
||||||
|
static_assert(sizeof(SharedMemoryHolder) == 0x50, "SharedMemoryHolder is an invalid size");
|
||||||
|
|
||||||
|
} // namespace Service::HID
|
|
@ -6,6 +6,7 @@
|
||||||
#include "core/hid/emulated_controller.h"
|
#include "core/hid/emulated_controller.h"
|
||||||
#include "core/hid/hid_core.h"
|
#include "core/hid/hid_core.h"
|
||||||
#include "core/hle/service/hid/controllers/npad.h"
|
#include "core/hle/service/hid/controllers/npad.h"
|
||||||
|
#include "core/hle/service/hid/controllers/shared_memory_format.h"
|
||||||
#include "core/hle/service/hid/controllers/six_axis.h"
|
#include "core/hle/service/hid/controllers/six_axis.h"
|
||||||
#include "core/hle/service/hid/errors.h"
|
#include "core/hle/service/hid/errors.h"
|
||||||
#include "core/hle/service/hid/hid_util.h"
|
#include "core/hle/service/hid/hid_util.h"
|
||||||
|
@ -132,30 +133,30 @@ void SixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
|
||||||
}
|
}
|
||||||
|
|
||||||
sixaxis_fullkey_state.sampling_number =
|
sixaxis_fullkey_state.sampling_number =
|
||||||
sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
|
sixaxis_fullkey_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1;
|
||||||
sixaxis_handheld_state.sampling_number =
|
sixaxis_handheld_state.sampling_number =
|
||||||
sixaxis_handheld_lifo.ReadCurrentEntry().state.sampling_number + 1;
|
sixaxis_handheld_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1;
|
||||||
sixaxis_dual_left_state.sampling_number =
|
sixaxis_dual_left_state.sampling_number =
|
||||||
sixaxis_dual_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
|
sixaxis_dual_left_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1;
|
||||||
sixaxis_dual_right_state.sampling_number =
|
sixaxis_dual_right_state.sampling_number =
|
||||||
sixaxis_dual_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
|
sixaxis_dual_right_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1;
|
||||||
sixaxis_left_lifo_state.sampling_number =
|
sixaxis_left_lifo_state.sampling_number =
|
||||||
sixaxis_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
|
sixaxis_left_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1;
|
||||||
sixaxis_right_lifo_state.sampling_number =
|
sixaxis_right_lifo_state.sampling_number =
|
||||||
sixaxis_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
|
sixaxis_right_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1;
|
||||||
|
|
||||||
if (IndexToNpadIdType(i) == Core::HID::NpadIdType::Handheld) {
|
if (IndexToNpadIdType(i) == Core::HID::NpadIdType::Handheld) {
|
||||||
// This buffer only is updated on handheld on HW
|
// This buffer only is updated on handheld on HW
|
||||||
sixaxis_handheld_lifo.WriteNextEntry(sixaxis_handheld_state);
|
sixaxis_handheld_lifo.lifo.WriteNextEntry(sixaxis_handheld_state);
|
||||||
} else {
|
} else {
|
||||||
// Handheld doesn't update this buffer on HW
|
// Handheld doesn't update this buffer on HW
|
||||||
sixaxis_fullkey_lifo.WriteNextEntry(sixaxis_fullkey_state);
|
sixaxis_fullkey_lifo.lifo.WriteNextEntry(sixaxis_fullkey_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
sixaxis_dual_left_lifo.WriteNextEntry(sixaxis_dual_left_state);
|
sixaxis_dual_left_lifo.lifo.WriteNextEntry(sixaxis_dual_left_state);
|
||||||
sixaxis_dual_right_lifo.WriteNextEntry(sixaxis_dual_right_state);
|
sixaxis_dual_right_lifo.lifo.WriteNextEntry(sixaxis_dual_right_state);
|
||||||
sixaxis_left_lifo.WriteNextEntry(sixaxis_left_lifo_state);
|
sixaxis_left_lifo.lifo.WriteNextEntry(sixaxis_left_lifo_state);
|
||||||
sixaxis_right_lifo.WriteNextEntry(sixaxis_right_lifo_state);
|
sixaxis_right_lifo.lifo.WriteNextEntry(sixaxis_right_lifo_state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,15 +4,14 @@
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/core_timing.h"
|
#include "core/core_timing.h"
|
||||||
#include "core/hid/hid_core.h"
|
#include "core/hle/service/hid/controllers/shared_memory_format.h"
|
||||||
#include "core/hle/service/hid/controllers/stubbed.h"
|
#include "core/hle/service/hid/controllers/stubbed.h"
|
||||||
|
|
||||||
namespace Service::HID {
|
namespace Service::HID {
|
||||||
|
|
||||||
Controller_Stubbed::Controller_Stubbed(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
|
Controller_Stubbed::Controller_Stubbed(Core::HID::HIDCore& hid_core_,
|
||||||
: ControllerBase{hid_core_} {
|
CommonHeader& ring_lifo_header)
|
||||||
raw_shared_memory = raw_shared_memory_;
|
: ControllerBase{hid_core_}, header{ring_lifo_header} {}
|
||||||
}
|
|
||||||
|
|
||||||
Controller_Stubbed::~Controller_Stubbed() = default;
|
Controller_Stubbed::~Controller_Stubbed() = default;
|
||||||
|
|
||||||
|
@ -25,18 +24,10 @@ void Controller_Stubbed::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CommonHeader header{};
|
|
||||||
header.timestamp = core_timing.GetGlobalTimeNs().count();
|
header.timestamp = core_timing.GetGlobalTimeNs().count();
|
||||||
header.total_entry_count = 17;
|
header.total_entry_count = 17;
|
||||||
header.entry_count = 0;
|
header.entry_count = 0;
|
||||||
header.last_entry_index = 0;
|
header.last_entry_index = 0;
|
||||||
|
|
||||||
std::memcpy(raw_shared_memory + common_offset, &header, sizeof(CommonHeader));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Controller_Stubbed::SetCommonHeaderOffset(std::size_t off) {
|
|
||||||
common_offset = off;
|
|
||||||
smart_update = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Service::HID
|
} // namespace Service::HID
|
||||||
|
|
|
@ -7,9 +7,11 @@
|
||||||
#include "core/hle/service/hid/controllers/controller_base.h"
|
#include "core/hle/service/hid/controllers/controller_base.h"
|
||||||
|
|
||||||
namespace Service::HID {
|
namespace Service::HID {
|
||||||
|
struct CommonHeader;
|
||||||
|
|
||||||
class Controller_Stubbed final : public ControllerBase {
|
class Controller_Stubbed final : public ControllerBase {
|
||||||
public:
|
public:
|
||||||
explicit Controller_Stubbed(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
|
explicit Controller_Stubbed(Core::HID::HIDCore& hid_core_, CommonHeader& ring_lifo_header);
|
||||||
~Controller_Stubbed() override;
|
~Controller_Stubbed() override;
|
||||||
|
|
||||||
// Called when the controller is initialized
|
// Called when the controller is initialized
|
||||||
|
@ -21,19 +23,8 @@ 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) override;
|
void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
|
||||||
|
|
||||||
void SetCommonHeaderOffset(std::size_t off);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct CommonHeader {
|
CommonHeader& header;
|
||||||
s64 timestamp{};
|
|
||||||
s64 total_entry_count{};
|
|
||||||
s64 last_entry_index{};
|
|
||||||
s64 entry_count{};
|
|
||||||
};
|
|
||||||
static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size");
|
|
||||||
|
|
||||||
u8* raw_shared_memory = nullptr;
|
|
||||||
bool smart_update{};
|
bool smart_update{};
|
||||||
std::size_t common_offset{};
|
|
||||||
};
|
};
|
||||||
} // namespace Service::HID
|
} // namespace Service::HID
|
||||||
|
|
|
@ -10,18 +10,16 @@
|
||||||
#include "core/frontend/emu_window.h"
|
#include "core/frontend/emu_window.h"
|
||||||
#include "core/hid/emulated_console.h"
|
#include "core/hid/emulated_console.h"
|
||||||
#include "core/hid/hid_core.h"
|
#include "core/hid/hid_core.h"
|
||||||
|
#include "core/hle/service/hid/controllers/shared_memory_format.h"
|
||||||
#include "core/hle/service/hid/controllers/touchscreen.h"
|
#include "core/hle/service/hid/controllers/touchscreen.h"
|
||||||
|
|
||||||
namespace Service::HID {
|
namespace Service::HID {
|
||||||
constexpr std::size_t SHARED_MEMORY_OFFSET = 0x400;
|
|
||||||
|
|
||||||
TouchScreen::TouchScreen(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
|
TouchScreen::TouchScreen(Core::HID::HIDCore& hid_core_,
|
||||||
: ControllerBase{hid_core_}, touchscreen_width(Layout::ScreenUndocked::Width),
|
TouchScreenSharedMemoryFormat& touch_shared_memory)
|
||||||
|
: ControllerBase{hid_core_}, shared_memory{touch_shared_memory},
|
||||||
|
touchscreen_width(Layout::ScreenUndocked::Width),
|
||||||
touchscreen_height(Layout::ScreenUndocked::Height) {
|
touchscreen_height(Layout::ScreenUndocked::Height) {
|
||||||
static_assert(SHARED_MEMORY_OFFSET + sizeof(TouchSharedMemory) < shared_memory_size,
|
|
||||||
"TouchSharedMemory is bigger than the shared memory");
|
|
||||||
shared_memory = std::construct_at(
|
|
||||||
reinterpret_cast<TouchSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
|
|
||||||
console = hid_core.GetEmulatedConsole();
|
console = hid_core.GetEmulatedConsole();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,11 +30,11 @@ void TouchScreen::OnInit() {}
|
||||||
void TouchScreen::OnRelease() {}
|
void TouchScreen::OnRelease() {}
|
||||||
|
|
||||||
void TouchScreen::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
|
void TouchScreen::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
|
||||||
shared_memory->touch_screen_lifo.timestamp = core_timing.GetGlobalTimeNs().count();
|
shared_memory.touch_screen_lifo.timestamp = core_timing.GetGlobalTimeNs().count();
|
||||||
|
|
||||||
if (!IsControllerActivated()) {
|
if (!IsControllerActivated()) {
|
||||||
shared_memory->touch_screen_lifo.buffer_count = 0;
|
shared_memory.touch_screen_lifo.buffer_count = 0;
|
||||||
shared_memory->touch_screen_lifo.buffer_tail = 0;
|
shared_memory.touch_screen_lifo.buffer_tail = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +84,7 @@ void TouchScreen::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
|
||||||
static_cast<std::size_t>(std::distance(active_fingers.begin(), end_iter));
|
static_cast<std::size_t>(std::distance(active_fingers.begin(), end_iter));
|
||||||
|
|
||||||
const u64 timestamp = static_cast<u64>(core_timing.GetGlobalTimeNs().count());
|
const u64 timestamp = static_cast<u64>(core_timing.GetGlobalTimeNs().count());
|
||||||
const auto& last_entry = shared_memory->touch_screen_lifo.ReadCurrentEntry().state;
|
const auto& last_entry = shared_memory.touch_screen_lifo.ReadCurrentEntry().state;
|
||||||
|
|
||||||
next_state.sampling_number = last_entry.sampling_number + 1;
|
next_state.sampling_number = last_entry.sampling_number + 1;
|
||||||
next_state.entry_count = static_cast<s32>(active_fingers_count);
|
next_state.entry_count = static_cast<s32>(active_fingers_count);
|
||||||
|
@ -118,7 +116,7 @@ void TouchScreen::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_memory->touch_screen_lifo.WriteNextEntry(next_state);
|
shared_memory.touch_screen_lifo.WriteNextEntry(next_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TouchScreen::SetTouchscreenDimensions(u32 width, u32 height) {
|
void TouchScreen::SetTouchscreenDimensions(u32 width, u32 height) {
|
||||||
|
|
|
@ -3,10 +3,12 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common/common_funcs.h"
|
#include <array>
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/hid/hid_types.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/controllers/types/touch_types.h"
|
||||||
#include "core/hle/service/hid/ring_lifo.h"
|
#include "core/hle/service/hid/ring_lifo.h"
|
||||||
|
|
||||||
namespace Core::HID {
|
namespace Core::HID {
|
||||||
|
@ -14,9 +16,12 @@ class EmulatedConsole;
|
||||||
} // namespace Core::HID
|
} // namespace Core::HID
|
||||||
|
|
||||||
namespace Service::HID {
|
namespace Service::HID {
|
||||||
|
struct TouchScreenSharedMemoryFormat;
|
||||||
|
|
||||||
class TouchScreen final : public ControllerBase {
|
class TouchScreen final : public ControllerBase {
|
||||||
public:
|
public:
|
||||||
explicit TouchScreen(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
|
explicit TouchScreen(Core::HID::HIDCore& hid_core_,
|
||||||
|
TouchScreenSharedMemoryFormat& touch_shared_memory);
|
||||||
~TouchScreen() override;
|
~TouchScreen() override;
|
||||||
|
|
||||||
// Called when the controller is initialized
|
// Called when the controller is initialized
|
||||||
|
@ -31,27 +36,8 @@ public:
|
||||||
void SetTouchscreenDimensions(u32 width, u32 height);
|
void SetTouchscreenDimensions(u32 width, u32 height);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr std::size_t MAX_FINGERS = 16;
|
|
||||||
|
|
||||||
// This is nn::hid::TouchScreenState
|
|
||||||
struct TouchScreenState {
|
|
||||||
s64 sampling_number{};
|
|
||||||
s32 entry_count{};
|
|
||||||
INSERT_PADDING_BYTES(4); // Reserved
|
|
||||||
std::array<Core::HID::TouchState, MAX_FINGERS> states{};
|
|
||||||
};
|
|
||||||
static_assert(sizeof(TouchScreenState) == 0x290, "TouchScreenState is an invalid size");
|
|
||||||
|
|
||||||
struct TouchSharedMemory {
|
|
||||||
// This is nn::hid::detail::TouchScreenLifo
|
|
||||||
Lifo<TouchScreenState, hid_entry_count> touch_screen_lifo{};
|
|
||||||
static_assert(sizeof(touch_screen_lifo) == 0x2C38, "touch_screen_lifo is an invalid size");
|
|
||||||
INSERT_PADDING_WORDS(0xF2);
|
|
||||||
};
|
|
||||||
static_assert(sizeof(TouchSharedMemory) == 0x3000, "TouchSharedMemory is an invalid size");
|
|
||||||
|
|
||||||
TouchScreenState next_state{};
|
TouchScreenState next_state{};
|
||||||
TouchSharedMemory* shared_memory = nullptr;
|
TouchScreenSharedMemoryFormat& shared_memory;
|
||||||
Core::HID::EmulatedConsole* console = nullptr;
|
Core::HID::EmulatedConsole* console = nullptr;
|
||||||
|
|
||||||
std::array<Core::HID::TouchFinger, MAX_FINGERS> fingers{};
|
std::array<Core::HID::TouchFinger, MAX_FINGERS> fingers{};
|
||||||
|
|
31
src/core/hle/service/hid/controllers/types/debug_pad_types.h
Executable file
31
src/core/hle/service/hid/controllers/types/debug_pad_types.h
Executable file
|
@ -0,0 +1,31 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/bit_field.h"
|
||||||
|
#include "common/common_types.h"
|
||||||
|
#include "core/hid/hid_types.h"
|
||||||
|
|
||||||
|
namespace Service::HID {
|
||||||
|
|
||||||
|
// This is nn::hid::DebugPadAttribute
|
||||||
|
struct DebugPadAttribute {
|
||||||
|
union {
|
||||||
|
u32 raw{};
|
||||||
|
BitField<0, 1, u32> connected;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
static_assert(sizeof(DebugPadAttribute) == 0x4, "DebugPadAttribute is an invalid size");
|
||||||
|
|
||||||
|
// This is nn::hid::DebugPadState
|
||||||
|
struct DebugPadState {
|
||||||
|
s64 sampling_number{};
|
||||||
|
DebugPadAttribute attribute{};
|
||||||
|
Core::HID::DebugPadButton pad_state{};
|
||||||
|
Core::HID::AnalogStickState r_stick{};
|
||||||
|
Core::HID::AnalogStickState l_stick{};
|
||||||
|
};
|
||||||
|
static_assert(sizeof(DebugPadState) == 0x20, "DebugPadState is an invalid state");
|
||||||
|
|
||||||
|
} // namespace Service::HID
|
77
src/core/hle/service/hid/controllers/types/gesture_types.h
Executable file
77
src/core/hle/service/hid/controllers/types/gesture_types.h
Executable file
|
@ -0,0 +1,77 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include "common/bit_field.h"
|
||||||
|
#include "common/common_types.h"
|
||||||
|
#include "common/point.h"
|
||||||
|
|
||||||
|
namespace Service::HID {
|
||||||
|
static constexpr size_t MAX_FINGERS = 16;
|
||||||
|
static constexpr size_t MAX_POINTS = 4;
|
||||||
|
|
||||||
|
// This is nn::hid::GestureType
|
||||||
|
enum class GestureType : u32 {
|
||||||
|
Idle, // Nothing touching the screen
|
||||||
|
Complete, // Set at the end of a touch event
|
||||||
|
Cancel, // Set when the number of fingers change
|
||||||
|
Touch, // A finger just touched the screen
|
||||||
|
Press, // Set if last type is touch and the finger hasn't moved
|
||||||
|
Tap, // Fast press then release
|
||||||
|
Pan, // All points moving together across the screen
|
||||||
|
Swipe, // Fast press movement and release of a single point
|
||||||
|
Pinch, // All points moving away/closer to the midpoint
|
||||||
|
Rotate, // All points rotating from the midpoint
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is nn::hid::GestureDirection
|
||||||
|
enum class GestureDirection : u32 {
|
||||||
|
None,
|
||||||
|
Left,
|
||||||
|
Up,
|
||||||
|
Right,
|
||||||
|
Down,
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is nn::hid::GestureAttribute
|
||||||
|
struct GestureAttribute {
|
||||||
|
union {
|
||||||
|
u32 raw{};
|
||||||
|
|
||||||
|
BitField<4, 1, u32> is_new_touch;
|
||||||
|
BitField<8, 1, u32> is_double_tap;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
static_assert(sizeof(GestureAttribute) == 4, "GestureAttribute is an invalid size");
|
||||||
|
|
||||||
|
// This is nn::hid::GestureState
|
||||||
|
struct GestureState {
|
||||||
|
s64 sampling_number{};
|
||||||
|
s64 detection_count{};
|
||||||
|
GestureType type{GestureType::Idle};
|
||||||
|
GestureDirection direction{GestureDirection::None};
|
||||||
|
Common::Point<s32> pos{};
|
||||||
|
Common::Point<s32> delta{};
|
||||||
|
f32 vel_x{};
|
||||||
|
f32 vel_y{};
|
||||||
|
GestureAttribute attributes{};
|
||||||
|
f32 scale{};
|
||||||
|
f32 rotation_angle{};
|
||||||
|
s32 point_count{};
|
||||||
|
std::array<Common::Point<s32>, 4> points{};
|
||||||
|
};
|
||||||
|
static_assert(sizeof(GestureState) == 0x60, "GestureState is an invalid size");
|
||||||
|
|
||||||
|
struct GestureProperties {
|
||||||
|
std::array<Common::Point<s32>, MAX_POINTS> points{};
|
||||||
|
std::size_t active_points{};
|
||||||
|
Common::Point<s32> mid_point{};
|
||||||
|
s64 detection_count{};
|
||||||
|
u64 delta_time{};
|
||||||
|
f32 average_distance{};
|
||||||
|
f32 angle{};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::HID
|
20
src/core/hle/service/hid/controllers/types/keyboard_types.h
Executable file
20
src/core/hle/service/hid/controllers/types/keyboard_types.h
Executable file
|
@ -0,0 +1,20 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/common_types.h"
|
||||||
|
#include "core/hid/hid_types.h"
|
||||||
|
|
||||||
|
namespace Service::HID {
|
||||||
|
|
||||||
|
// This is nn::hid::detail::KeyboardState
|
||||||
|
struct KeyboardState {
|
||||||
|
s64 sampling_number{};
|
||||||
|
Core::HID::KeyboardModifier modifier{};
|
||||||
|
Core::HID::KeyboardAttribute attribute{};
|
||||||
|
Core::HID::KeyboardKey key{};
|
||||||
|
};
|
||||||
|
static_assert(sizeof(KeyboardState) == 0x30, "KeyboardState is an invalid size");
|
||||||
|
|
||||||
|
} // namespace Service::HID
|
12
src/core/hle/service/hid/controllers/types/mouse_types.h
Executable file
12
src/core/hle/service/hid/controllers/types/mouse_types.h
Executable file
|
@ -0,0 +1,12 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/common_funcs.h"
|
||||||
|
#include "common/common_types.h"
|
||||||
|
#include "common/vector_math.h"
|
||||||
|
#include "core/hid/hid_types.h"
|
||||||
|
#include "core/hle/service/hid/ring_lifo.h"
|
||||||
|
|
||||||
|
namespace Service::HID {} // namespace Service::HID
|
255
src/core/hle/service/hid/controllers/types/npad_types.h
Executable file
255
src/core/hle/service/hid/controllers/types/npad_types.h
Executable file
|
@ -0,0 +1,255 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/common_funcs.h"
|
||||||
|
#include "common/common_types.h"
|
||||||
|
#include "common/vector_math.h"
|
||||||
|
#include "core/hid/hid_types.h"
|
||||||
|
#include "core/hle/service/hid/ring_lifo.h"
|
||||||
|
|
||||||
|
namespace Service::HID {
|
||||||
|
static constexpr std::size_t NPAD_COUNT = 10;
|
||||||
|
|
||||||
|
// This is nn::hid::NpadJoyHoldType
|
||||||
|
enum class NpadJoyHoldType : u64 {
|
||||||
|
Vertical = 0,
|
||||||
|
Horizontal = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is nn::hid::NpadJoyAssignmentMode
|
||||||
|
enum class NpadJoyAssignmentMode : u32 {
|
||||||
|
Dual = 0,
|
||||||
|
Single = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is nn::hid::NpadJoyDeviceType
|
||||||
|
enum class NpadJoyDeviceType : s64 {
|
||||||
|
Left = 0,
|
||||||
|
Right = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is nn::hid::NpadHandheldActivationMode
|
||||||
|
enum class NpadHandheldActivationMode : u64 {
|
||||||
|
Dual = 0,
|
||||||
|
Single = 1,
|
||||||
|
None = 2,
|
||||||
|
MaxActivationMode = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is nn::hid::system::AppletFooterUiAttributesSet
|
||||||
|
struct AppletFooterUiAttributes {
|
||||||
|
INSERT_PADDING_BYTES(0x4);
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is nn::hid::system::AppletFooterUiType
|
||||||
|
enum class AppletFooterUiType : u8 {
|
||||||
|
None = 0,
|
||||||
|
HandheldNone = 1,
|
||||||
|
HandheldJoyConLeftOnly = 2,
|
||||||
|
HandheldJoyConRightOnly = 3,
|
||||||
|
HandheldJoyConLeftJoyConRight = 4,
|
||||||
|
JoyDual = 5,
|
||||||
|
JoyDualLeftOnly = 6,
|
||||||
|
JoyDualRightOnly = 7,
|
||||||
|
JoyLeftHorizontal = 8,
|
||||||
|
JoyLeftVertical = 9,
|
||||||
|
JoyRightHorizontal = 10,
|
||||||
|
JoyRightVertical = 11,
|
||||||
|
SwitchProController = 12,
|
||||||
|
CompatibleProController = 13,
|
||||||
|
CompatibleJoyCon = 14,
|
||||||
|
LarkHvc1 = 15,
|
||||||
|
LarkHvc2 = 16,
|
||||||
|
LarkNesLeft = 17,
|
||||||
|
LarkNesRight = 18,
|
||||||
|
Lucia = 19,
|
||||||
|
Verification = 20,
|
||||||
|
Lagon = 21,
|
||||||
|
};
|
||||||
|
|
||||||
|
using AppletFooterUiVariant = u8;
|
||||||
|
|
||||||
|
// This is "nn::hid::system::AppletDetailedUiType".
|
||||||
|
struct AppletDetailedUiType {
|
||||||
|
AppletFooterUiVariant ui_variant;
|
||||||
|
INSERT_PADDING_BYTES(0x2);
|
||||||
|
AppletFooterUiType footer;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(AppletDetailedUiType) == 0x4, "AppletDetailedUiType is an invalid size");
|
||||||
|
// This is nn::hid::NpadCommunicationMode
|
||||||
|
enum class NpadCommunicationMode : u64 {
|
||||||
|
Mode_5ms = 0,
|
||||||
|
Mode_10ms = 1,
|
||||||
|
Mode_15ms = 2,
|
||||||
|
Default = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class NpadRevision : u32 {
|
||||||
|
Revision0 = 0,
|
||||||
|
Revision1 = 1,
|
||||||
|
Revision2 = 2,
|
||||||
|
Revision3 = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is nn::hid::detail::ColorAttribute
|
||||||
|
enum class ColorAttribute : u32 {
|
||||||
|
Ok = 0,
|
||||||
|
ReadError = 1,
|
||||||
|
NoController = 2,
|
||||||
|
};
|
||||||
|
static_assert(sizeof(ColorAttribute) == 4, "ColorAttribute is an invalid size");
|
||||||
|
|
||||||
|
// This is nn::hid::detail::NpadFullKeyColorState
|
||||||
|
struct NpadFullKeyColorState {
|
||||||
|
ColorAttribute attribute{ColorAttribute::NoController};
|
||||||
|
Core::HID::NpadControllerColor fullkey{};
|
||||||
|
};
|
||||||
|
static_assert(sizeof(NpadFullKeyColorState) == 0xC, "NpadFullKeyColorState is an invalid size");
|
||||||
|
|
||||||
|
// This is nn::hid::detail::NpadJoyColorState
|
||||||
|
struct NpadJoyColorState {
|
||||||
|
ColorAttribute attribute{ColorAttribute::NoController};
|
||||||
|
Core::HID::NpadControllerColor left{};
|
||||||
|
Core::HID::NpadControllerColor right{};
|
||||||
|
};
|
||||||
|
static_assert(sizeof(NpadJoyColorState) == 0x14, "NpadJoyColorState is an invalid size");
|
||||||
|
|
||||||
|
// This is nn::hid::NpadAttribute
|
||||||
|
struct NpadAttribute {
|
||||||
|
union {
|
||||||
|
u32 raw{};
|
||||||
|
BitField<0, 1, u32> is_connected;
|
||||||
|
BitField<1, 1, u32> is_wired;
|
||||||
|
BitField<2, 1, u32> is_left_connected;
|
||||||
|
BitField<3, 1, u32> is_left_wired;
|
||||||
|
BitField<4, 1, u32> is_right_connected;
|
||||||
|
BitField<5, 1, u32> is_right_wired;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
static_assert(sizeof(NpadAttribute) == 4, "NpadAttribute is an invalid size");
|
||||||
|
|
||||||
|
// This is nn::hid::NpadFullKeyState
|
||||||
|
// This is nn::hid::NpadHandheldState
|
||||||
|
// This is nn::hid::NpadJoyDualState
|
||||||
|
// This is nn::hid::NpadJoyLeftState
|
||||||
|
// This is nn::hid::NpadJoyRightState
|
||||||
|
// This is nn::hid::NpadPalmaState
|
||||||
|
// This is nn::hid::NpadSystemExtState
|
||||||
|
struct NPadGenericState {
|
||||||
|
s64_le sampling_number{};
|
||||||
|
Core::HID::NpadButtonState npad_buttons{};
|
||||||
|
Core::HID::AnalogStickState l_stick{};
|
||||||
|
Core::HID::AnalogStickState r_stick{};
|
||||||
|
NpadAttribute connection_status{};
|
||||||
|
INSERT_PADDING_BYTES(4); // Reserved
|
||||||
|
};
|
||||||
|
static_assert(sizeof(NPadGenericState) == 0x28, "NPadGenericState is an invalid size");
|
||||||
|
|
||||||
|
// This is nn::hid::server::NpadGcTriggerState
|
||||||
|
struct NpadGcTriggerState {
|
||||||
|
s64 sampling_number{};
|
||||||
|
s32 l_analog{};
|
||||||
|
s32 r_analog{};
|
||||||
|
};
|
||||||
|
static_assert(sizeof(NpadGcTriggerState) == 0x10, "NpadGcTriggerState is an invalid size");
|
||||||
|
|
||||||
|
// This is nn::hid::NpadSystemProperties
|
||||||
|
struct NPadSystemProperties {
|
||||||
|
union {
|
||||||
|
s64 raw{};
|
||||||
|
BitField<0, 1, s64> is_charging_joy_dual;
|
||||||
|
BitField<1, 1, s64> is_charging_joy_left;
|
||||||
|
BitField<2, 1, s64> is_charging_joy_right;
|
||||||
|
BitField<3, 1, s64> is_powered_joy_dual;
|
||||||
|
BitField<4, 1, s64> is_powered_joy_left;
|
||||||
|
BitField<5, 1, s64> is_powered_joy_right;
|
||||||
|
BitField<9, 1, s64> is_system_unsupported_button;
|
||||||
|
BitField<10, 1, s64> is_system_ext_unsupported_button;
|
||||||
|
BitField<11, 1, s64> is_vertical;
|
||||||
|
BitField<12, 1, s64> is_horizontal;
|
||||||
|
BitField<13, 1, s64> use_plus;
|
||||||
|
BitField<14, 1, s64> use_minus;
|
||||||
|
BitField<15, 1, s64> use_directional_buttons;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
static_assert(sizeof(NPadSystemProperties) == 0x8, "NPadSystemProperties is an invalid size");
|
||||||
|
|
||||||
|
// This is nn::hid::NpadSystemButtonProperties
|
||||||
|
struct NpadSystemButtonProperties {
|
||||||
|
union {
|
||||||
|
s32 raw{};
|
||||||
|
BitField<0, 1, s32> is_home_button_protection_enabled;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
static_assert(sizeof(NpadSystemButtonProperties) == 0x4, "NPadButtonProperties is an invalid size");
|
||||||
|
|
||||||
|
// This is nn::hid::system::DeviceType
|
||||||
|
struct DeviceType {
|
||||||
|
union {
|
||||||
|
u32 raw{};
|
||||||
|
BitField<0, 1, s32> fullkey;
|
||||||
|
BitField<1, 1, s32> debug_pad;
|
||||||
|
BitField<2, 1, s32> handheld_left;
|
||||||
|
BitField<3, 1, s32> handheld_right;
|
||||||
|
BitField<4, 1, s32> joycon_left;
|
||||||
|
BitField<5, 1, s32> joycon_right;
|
||||||
|
BitField<6, 1, s32> palma;
|
||||||
|
BitField<7, 1, s32> lark_hvc_left;
|
||||||
|
BitField<8, 1, s32> lark_hvc_right;
|
||||||
|
BitField<9, 1, s32> lark_nes_left;
|
||||||
|
BitField<10, 1, s32> lark_nes_right;
|
||||||
|
BitField<11, 1, s32> handheld_lark_hvc_left;
|
||||||
|
BitField<12, 1, s32> handheld_lark_hvc_right;
|
||||||
|
BitField<13, 1, s32> handheld_lark_nes_left;
|
||||||
|
BitField<14, 1, s32> handheld_lark_nes_right;
|
||||||
|
BitField<15, 1, s32> lucia;
|
||||||
|
BitField<16, 1, s32> lagon;
|
||||||
|
BitField<17, 1, s32> lager;
|
||||||
|
BitField<31, 1, s32> system;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is nn::hid::detail::NfcXcdDeviceHandleStateImpl
|
||||||
|
struct NfcXcdDeviceHandleStateImpl {
|
||||||
|
u64 handle{};
|
||||||
|
bool is_available{};
|
||||||
|
bool is_activated{};
|
||||||
|
INSERT_PADDING_BYTES(0x6); // Reserved
|
||||||
|
u64 sampling_number{};
|
||||||
|
};
|
||||||
|
static_assert(sizeof(NfcXcdDeviceHandleStateImpl) == 0x18,
|
||||||
|
"NfcXcdDeviceHandleStateImpl is an invalid size");
|
||||||
|
|
||||||
|
// This is nn::hid::NpadLarkType
|
||||||
|
enum class NpadLarkType : u32 {
|
||||||
|
Invalid,
|
||||||
|
H1,
|
||||||
|
H2,
|
||||||
|
NL,
|
||||||
|
NR,
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is nn::hid::NpadLuciaType
|
||||||
|
enum class NpadLuciaType : u32 {
|
||||||
|
Invalid,
|
||||||
|
J,
|
||||||
|
E,
|
||||||
|
U,
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is nn::hid::NpadLagonType
|
||||||
|
enum class NpadLagonType : u32 {
|
||||||
|
Invalid,
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is nn::hid::NpadLagerType
|
||||||
|
enum class NpadLagerType : u32 {
|
||||||
|
Invalid,
|
||||||
|
J,
|
||||||
|
E,
|
||||||
|
U,
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::HID
|
90
src/core/hle/service/hid/controllers/types/touch_types.h
Executable file
90
src/core/hle/service/hid/controllers/types/touch_types.h
Executable file
|
@ -0,0 +1,90 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include "common/bit_field.h"
|
||||||
|
#include "common/common_funcs.h"
|
||||||
|
#include "common/common_types.h"
|
||||||
|
#include "common/point.h"
|
||||||
|
#include "core/hid/hid_types.h"
|
||||||
|
|
||||||
|
namespace Service::HID {
|
||||||
|
static constexpr std::size_t MAX_FINGERS = 16;
|
||||||
|
static constexpr size_t MAX_POINTS = 4;
|
||||||
|
|
||||||
|
// This is nn::hid::GestureType
|
||||||
|
enum class GestureType : u32 {
|
||||||
|
Idle, // Nothing touching the screen
|
||||||
|
Complete, // Set at the end of a touch event
|
||||||
|
Cancel, // Set when the number of fingers change
|
||||||
|
Touch, // A finger just touched the screen
|
||||||
|
Press, // Set if last type is touch and the finger hasn't moved
|
||||||
|
Tap, // Fast press then release
|
||||||
|
Pan, // All points moving together across the screen
|
||||||
|
Swipe, // Fast press movement and release of a single point
|
||||||
|
Pinch, // All points moving away/closer to the midpoint
|
||||||
|
Rotate, // All points rotating from the midpoint
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is nn::hid::GestureDirection
|
||||||
|
enum class GestureDirection : u32 {
|
||||||
|
None,
|
||||||
|
Left,
|
||||||
|
Up,
|
||||||
|
Right,
|
||||||
|
Down,
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is nn::hid::GestureAttribute
|
||||||
|
struct GestureAttribute {
|
||||||
|
union {
|
||||||
|
u32 raw{};
|
||||||
|
|
||||||
|
BitField<4, 1, u32> is_new_touch;
|
||||||
|
BitField<8, 1, u32> is_double_tap;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
static_assert(sizeof(GestureAttribute) == 4, "GestureAttribute is an invalid size");
|
||||||
|
|
||||||
|
// This is nn::hid::GestureState
|
||||||
|
struct GestureState {
|
||||||
|
s64 sampling_number{};
|
||||||
|
s64 detection_count{};
|
||||||
|
GestureType type{GestureType::Idle};
|
||||||
|
GestureDirection direction{GestureDirection::None};
|
||||||
|
Common::Point<s32> pos{};
|
||||||
|
Common::Point<s32> delta{};
|
||||||
|
f32 vel_x{};
|
||||||
|
f32 vel_y{};
|
||||||
|
GestureAttribute attributes{};
|
||||||
|
f32 scale{};
|
||||||
|
f32 rotation_angle{};
|
||||||
|
s32 point_count{};
|
||||||
|
std::array<Common::Point<s32>, 4> points{};
|
||||||
|
};
|
||||||
|
static_assert(sizeof(GestureState) == 0x60, "GestureState is an invalid size");
|
||||||
|
|
||||||
|
struct GestureProperties {
|
||||||
|
std::array<Common::Point<s32>, MAX_POINTS> points{};
|
||||||
|
std::size_t active_points{};
|
||||||
|
Common::Point<s32> mid_point{};
|
||||||
|
s64 detection_count{};
|
||||||
|
u64 delta_time{};
|
||||||
|
f32 average_distance{};
|
||||||
|
f32 angle{};
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is nn::hid::TouchScreenState
|
||||||
|
struct TouchScreenState {
|
||||||
|
s64 sampling_number{};
|
||||||
|
s32 entry_count{};
|
||||||
|
INSERT_PADDING_BYTES(4); // Reserved
|
||||||
|
std::array<Core::HID::TouchState, MAX_FINGERS> states{};
|
||||||
|
};
|
||||||
|
static_assert(sizeof(TouchScreenState) == 0x290, "TouchScreenState is an invalid size");
|
||||||
|
|
||||||
|
} // namespace Service::HID
|
|
@ -28,6 +28,7 @@
|
||||||
#include "core/hle/service/hid/controllers/seven_six_axis.h"
|
#include "core/hle/service/hid/controllers/seven_six_axis.h"
|
||||||
#include "core/hle/service/hid/controllers/six_axis.h"
|
#include "core/hle/service/hid/controllers/six_axis.h"
|
||||||
#include "core/hle/service/hid/controllers/touchscreen.h"
|
#include "core/hle/service/hid/controllers/touchscreen.h"
|
||||||
|
#include "core/hle/service/hid/controllers/types/npad_types.h"
|
||||||
|
|
||||||
namespace Service::HID {
|
namespace Service::HID {
|
||||||
|
|
||||||
|
@ -1099,7 +1100,7 @@ void IHidServer::GetPlayerLedPattern(HLERequestContext& ctx) {
|
||||||
void IHidServer::ActivateNpadWithRevision(HLERequestContext& ctx) {
|
void IHidServer::ActivateNpadWithRevision(HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
struct Parameters {
|
struct Parameters {
|
||||||
NPad::NpadRevision revision;
|
NpadRevision revision;
|
||||||
INSERT_PADDING_WORDS_NOINIT(1);
|
INSERT_PADDING_WORDS_NOINIT(1);
|
||||||
u64 applet_resource_user_id;
|
u64 applet_resource_user_id;
|
||||||
};
|
};
|
||||||
|
@ -1122,7 +1123,7 @@ void IHidServer::ActivateNpadWithRevision(HLERequestContext& ctx) {
|
||||||
void IHidServer::SetNpadJoyHoldType(HLERequestContext& ctx) {
|
void IHidServer::SetNpadJoyHoldType(HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
const auto applet_resource_user_id{rp.Pop<u64>()};
|
const auto applet_resource_user_id{rp.Pop<u64>()};
|
||||||
const auto hold_type{rp.PopEnum<NPad::NpadJoyHoldType>()};
|
const auto hold_type{rp.PopEnum<NpadJoyHoldType>()};
|
||||||
|
|
||||||
GetResourceManager()->GetNpad()->SetHoldType(hold_type);
|
GetResourceManager()->GetNpad()->SetHoldType(hold_type);
|
||||||
|
|
||||||
|
@ -1157,8 +1158,8 @@ void IHidServer::SetNpadJoyAssignmentModeSingleByDefault(HLERequestContext& ctx)
|
||||||
|
|
||||||
Core::HID::NpadIdType new_npad_id{};
|
Core::HID::NpadIdType new_npad_id{};
|
||||||
auto controller = GetResourceManager()->GetNpad();
|
auto controller = GetResourceManager()->GetNpad();
|
||||||
controller->SetNpadMode(new_npad_id, parameters.npad_id, NPad::NpadJoyDeviceType::Left,
|
controller->SetNpadMode(new_npad_id, parameters.npad_id, NpadJoyDeviceType::Left,
|
||||||
NPad::NpadJoyAssignmentMode::Single);
|
NpadJoyAssignmentMode::Single);
|
||||||
|
|
||||||
LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id,
|
LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id,
|
||||||
parameters.applet_resource_user_id);
|
parameters.applet_resource_user_id);
|
||||||
|
@ -1173,7 +1174,7 @@ void IHidServer::SetNpadJoyAssignmentModeSingle(HLERequestContext& ctx) {
|
||||||
Core::HID::NpadIdType npad_id;
|
Core::HID::NpadIdType npad_id;
|
||||||
INSERT_PADDING_WORDS_NOINIT(1);
|
INSERT_PADDING_WORDS_NOINIT(1);
|
||||||
u64 applet_resource_user_id;
|
u64 applet_resource_user_id;
|
||||||
NPad::NpadJoyDeviceType npad_joy_device_type;
|
NpadJoyDeviceType npad_joy_device_type;
|
||||||
};
|
};
|
||||||
static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
|
static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
|
||||||
|
|
||||||
|
@ -1182,7 +1183,7 @@ void IHidServer::SetNpadJoyAssignmentModeSingle(HLERequestContext& ctx) {
|
||||||
Core::HID::NpadIdType new_npad_id{};
|
Core::HID::NpadIdType new_npad_id{};
|
||||||
auto controller = GetResourceManager()->GetNpad();
|
auto controller = GetResourceManager()->GetNpad();
|
||||||
controller->SetNpadMode(new_npad_id, parameters.npad_id, parameters.npad_joy_device_type,
|
controller->SetNpadMode(new_npad_id, parameters.npad_id, parameters.npad_joy_device_type,
|
||||||
NPad::NpadJoyAssignmentMode::Single);
|
NpadJoyAssignmentMode::Single);
|
||||||
|
|
||||||
LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}",
|
LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}",
|
||||||
parameters.npad_id, parameters.applet_resource_user_id,
|
parameters.npad_id, parameters.applet_resource_user_id,
|
||||||
|
@ -1205,7 +1206,7 @@ void IHidServer::SetNpadJoyAssignmentModeDual(HLERequestContext& ctx) {
|
||||||
|
|
||||||
Core::HID::NpadIdType new_npad_id{};
|
Core::HID::NpadIdType new_npad_id{};
|
||||||
auto controller = GetResourceManager()->GetNpad();
|
auto controller = GetResourceManager()->GetNpad();
|
||||||
controller->SetNpadMode(new_npad_id, parameters.npad_id, {}, NPad::NpadJoyAssignmentMode::Dual);
|
controller->SetNpadMode(new_npad_id, parameters.npad_id, {}, NpadJoyAssignmentMode::Dual);
|
||||||
|
|
||||||
LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id,
|
LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id,
|
||||||
parameters.applet_resource_user_id); // Spams a lot when controller applet is open
|
parameters.applet_resource_user_id); // Spams a lot when controller applet is open
|
||||||
|
@ -1257,7 +1258,7 @@ void IHidServer::StopLrAssignmentMode(HLERequestContext& ctx) {
|
||||||
void IHidServer::SetNpadHandheldActivationMode(HLERequestContext& ctx) {
|
void IHidServer::SetNpadHandheldActivationMode(HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
const auto applet_resource_user_id{rp.Pop<u64>()};
|
const auto applet_resource_user_id{rp.Pop<u64>()};
|
||||||
const auto activation_mode{rp.PopEnum<NPad::NpadHandheldActivationMode>()};
|
const auto activation_mode{rp.PopEnum<NpadHandheldActivationMode>()};
|
||||||
|
|
||||||
GetResourceManager()->GetNpad()->SetNpadHandheldActivationMode(activation_mode);
|
GetResourceManager()->GetNpad()->SetNpadHandheldActivationMode(activation_mode);
|
||||||
|
|
||||||
|
@ -1349,7 +1350,7 @@ void IHidServer::SetNpadJoyAssignmentModeSingleWithDestination(HLERequestContext
|
||||||
Core::HID::NpadIdType npad_id;
|
Core::HID::NpadIdType npad_id;
|
||||||
INSERT_PADDING_WORDS_NOINIT(1);
|
INSERT_PADDING_WORDS_NOINIT(1);
|
||||||
u64 applet_resource_user_id;
|
u64 applet_resource_user_id;
|
||||||
NPad::NpadJoyDeviceType npad_joy_device_type;
|
NpadJoyDeviceType npad_joy_device_type;
|
||||||
};
|
};
|
||||||
static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
|
static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
|
||||||
|
|
||||||
|
@ -1359,7 +1360,7 @@ void IHidServer::SetNpadJoyAssignmentModeSingleWithDestination(HLERequestContext
|
||||||
auto controller = GetResourceManager()->GetNpad();
|
auto controller = GetResourceManager()->GetNpad();
|
||||||
const auto is_reassigned =
|
const auto is_reassigned =
|
||||||
controller->SetNpadMode(new_npad_id, parameters.npad_id, parameters.npad_joy_device_type,
|
controller->SetNpadMode(new_npad_id, parameters.npad_id, parameters.npad_joy_device_type,
|
||||||
NPad::NpadJoyAssignmentMode::Single);
|
NpadJoyAssignmentMode::Single);
|
||||||
|
|
||||||
LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}",
|
LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}",
|
||||||
parameters.npad_id, parameters.applet_resource_user_id,
|
parameters.npad_id, parameters.applet_resource_user_id,
|
||||||
|
@ -2315,7 +2316,7 @@ void IHidServer::SetDisallowedPalmaConnection(HLERequestContext& ctx) {
|
||||||
void IHidServer::SetNpadCommunicationMode(HLERequestContext& ctx) {
|
void IHidServer::SetNpadCommunicationMode(HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
const auto applet_resource_user_id{rp.Pop<u64>()};
|
const auto applet_resource_user_id{rp.Pop<u64>()};
|
||||||
const auto communication_mode{rp.PopEnum<NPad::NpadCommunicationMode>()};
|
const auto communication_mode{rp.PopEnum<NpadCommunicationMode>()};
|
||||||
|
|
||||||
GetResourceManager()->GetNpad()->SetNpadCommunicationMode(communication_mode);
|
GetResourceManager()->GetNpad()->SetNpadCommunicationMode(communication_mode);
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "core/hle/service/hid/controllers/npad.h"
|
#include "core/hle/service/hid/controllers/npad.h"
|
||||||
#include "core/hle/service/hid/controllers/palma.h"
|
#include "core/hle/service/hid/controllers/palma.h"
|
||||||
#include "core/hle/service/hid/controllers/touchscreen.h"
|
#include "core/hle/service/hid/controllers/touchscreen.h"
|
||||||
|
#include "core/hle/service/hid/controllers/types/npad_types.h"
|
||||||
#include "core/hle/service/hid/errors.h"
|
#include "core/hle/service/hid/errors.h"
|
||||||
#include "core/hle/service/hid/hid_system_server.h"
|
#include "core/hle/service/hid/hid_system_server.h"
|
||||||
#include "core/hle/service/hid/resource_manager.h"
|
#include "core/hle/service/hid/resource_manager.h"
|
||||||
|
@ -328,7 +329,7 @@ void IHidSystemServer::GetAppletDetailedUiType(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_HID, "called, npad_id_type={}",
|
LOG_DEBUG(Service_HID, "called, npad_id_type={}",
|
||||||
npad_id_type); // Spams a lot when controller applet is running
|
npad_id_type); // Spams a lot when controller applet is running
|
||||||
|
|
||||||
const NPad::AppletDetailedUiType detailed_ui_type =
|
const AppletDetailedUiType detailed_ui_type =
|
||||||
GetResourceManager()->GetNpad()->GetAppletDetailedUiType(npad_id_type);
|
GetResourceManager()->GetNpad()->GetAppletDetailedUiType(npad_id_type);
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
|
|
|
@ -18,10 +18,10 @@
|
||||||
#include "core/hle/service/hid/controllers/npad.h"
|
#include "core/hle/service/hid/controllers/npad.h"
|
||||||
#include "core/hle/service/hid/controllers/palma.h"
|
#include "core/hle/service/hid/controllers/palma.h"
|
||||||
#include "core/hle/service/hid/controllers/seven_six_axis.h"
|
#include "core/hle/service/hid/controllers/seven_six_axis.h"
|
||||||
|
#include "core/hle/service/hid/controllers/shared_memory_format.h"
|
||||||
#include "core/hle/service/hid/controllers/six_axis.h"
|
#include "core/hle/service/hid/controllers/six_axis.h"
|
||||||
#include "core/hle/service/hid/controllers/stubbed.h"
|
#include "core/hle/service/hid/controllers/stubbed.h"
|
||||||
#include "core/hle/service/hid/controllers/touchscreen.h"
|
#include "core/hle/service/hid/controllers/touchscreen.h"
|
||||||
#include "core/hle/service/hid/controllers/xpad.h"
|
|
||||||
|
|
||||||
namespace Service::HID {
|
namespace Service::HID {
|
||||||
|
|
||||||
|
@ -45,40 +45,43 @@ void ResourceManager::Initialize() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8* shared_memory = system.Kernel().GetHidSharedMem().GetPointer();
|
system.HIDCore().ReloadInputDevices();
|
||||||
debug_pad = std::make_shared<DebugPad>(system.HIDCore(), shared_memory);
|
is_initialized = true;
|
||||||
mouse = std::make_shared<Mouse>(system.HIDCore(), shared_memory);
|
}
|
||||||
debug_mouse = std::make_shared<DebugMouse>(system.HIDCore(), shared_memory);
|
|
||||||
keyboard = std::make_shared<Keyboard>(system.HIDCore(), shared_memory);
|
|
||||||
unique_pad = std::make_shared<UniquePad>(system.HIDCore(), shared_memory);
|
|
||||||
npad = std::make_shared<NPad>(system.HIDCore(), shared_memory, service_context);
|
|
||||||
gesture = std::make_shared<Gesture>(system.HIDCore(), shared_memory);
|
|
||||||
touch_screen = std::make_shared<TouchScreen>(system.HIDCore(), shared_memory);
|
|
||||||
xpad = std::make_shared<XPad>(system.HIDCore(), shared_memory);
|
|
||||||
|
|
||||||
palma = std::make_shared<Palma>(system.HIDCore(), shared_memory, service_context);
|
void ResourceManager::InitializeController(u64 aruid) {
|
||||||
|
SharedMemoryFormat* shared_memory = nullptr;
|
||||||
|
const auto result = applet_resource->GetSharedMemoryFormat(&shared_memory, aruid);
|
||||||
|
if (result.IsError()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
home_button = std::make_shared<HomeButton>(system.HIDCore(), shared_memory);
|
debug_pad = std::make_shared<DebugPad>(system.HIDCore(), shared_memory->debug_pad);
|
||||||
sleep_button = std::make_shared<SleepButton>(system.HIDCore(), shared_memory);
|
mouse = std::make_shared<Mouse>(system.HIDCore(), shared_memory->mouse);
|
||||||
capture_button = std::make_shared<CaptureButton>(system.HIDCore(), shared_memory);
|
debug_mouse = std::make_shared<DebugMouse>(system.HIDCore(), shared_memory->debug_mouse);
|
||||||
|
keyboard = std::make_shared<Keyboard>(system.HIDCore(), shared_memory->keyboard);
|
||||||
|
unique_pad = std::make_shared<UniquePad>(system.HIDCore(), shared_memory->unique_pad.header);
|
||||||
|
npad = std::make_shared<NPad>(system.HIDCore(), shared_memory->npad, service_context);
|
||||||
|
gesture = std::make_shared<Gesture>(system.HIDCore(), shared_memory->gesture);
|
||||||
|
touch_screen = std::make_shared<TouchScreen>(system.HIDCore(), shared_memory->touch_screen);
|
||||||
|
|
||||||
|
palma = std::make_shared<Palma>(system.HIDCore(), service_context);
|
||||||
|
|
||||||
|
home_button = std::make_shared<HomeButton>(system.HIDCore(), shared_memory->home_button.header);
|
||||||
|
sleep_button =
|
||||||
|
std::make_shared<SleepButton>(system.HIDCore(), shared_memory->sleep_button.header);
|
||||||
|
capture_button =
|
||||||
|
std::make_shared<CaptureButton>(system.HIDCore(), shared_memory->capture_button.header);
|
||||||
|
digitizer = std::make_shared<Digitizer>(system.HIDCore(), shared_memory->digitizer.header);
|
||||||
|
|
||||||
six_axis = std::make_shared<SixAxis>(system.HIDCore(), npad);
|
six_axis = std::make_shared<SixAxis>(system.HIDCore(), npad);
|
||||||
console_six_axis = std::make_shared<ConsoleSixAxis>(system.HIDCore(), shared_memory);
|
console_six_axis = std::make_shared<ConsoleSixAxis>(system.HIDCore(), shared_memory->console);
|
||||||
seven_six_axis = std::make_shared<SevenSixAxis>(system);
|
seven_six_axis = std::make_shared<SevenSixAxis>(system);
|
||||||
|
|
||||||
home_button->SetCommonHeaderOffset(0x4C00);
|
|
||||||
sleep_button->SetCommonHeaderOffset(0x4E00);
|
|
||||||
capture_button->SetCommonHeaderOffset(0x5000);
|
|
||||||
unique_pad->SetCommonHeaderOffset(0x5A00);
|
|
||||||
debug_mouse->SetCommonHeaderOffset(0x3DC00);
|
|
||||||
|
|
||||||
// Homebrew doesn't try to activate some controllers, so we activate them by default
|
// Homebrew doesn't try to activate some controllers, so we activate them by default
|
||||||
npad->Activate();
|
npad->Activate();
|
||||||
six_axis->Activate();
|
six_axis->Activate();
|
||||||
touch_screen->Activate();
|
touch_screen->Activate();
|
||||||
|
|
||||||
system.HIDCore().ReloadInputDevices();
|
|
||||||
is_initialized = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<AppletResource> ResourceManager::GetAppletResource() const {
|
std::shared_ptr<AppletResource> ResourceManager::GetAppletResource() const {
|
||||||
|
@ -101,6 +104,10 @@ std::shared_ptr<DebugPad> ResourceManager::GetDebugPad() const {
|
||||||
return debug_pad;
|
return debug_pad;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Digitizer> ResourceManager::GetDigitizer() const {
|
||||||
|
return digitizer;
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<Gesture> ResourceManager::GetGesture() const {
|
std::shared_ptr<Gesture> ResourceManager::GetGesture() const {
|
||||||
return gesture;
|
return gesture;
|
||||||
}
|
}
|
||||||
|
@ -163,7 +170,11 @@ Result ResourceManager::CreateAppletResource(u64 aruid) {
|
||||||
|
|
||||||
Result ResourceManager::CreateAppletResourceImpl(u64 aruid) {
|
Result ResourceManager::CreateAppletResourceImpl(u64 aruid) {
|
||||||
std::scoped_lock lock{shared_mutex};
|
std::scoped_lock lock{shared_mutex};
|
||||||
return applet_resource->CreateAppletResource(aruid);
|
const auto result = applet_resource->CreateAppletResource(aruid);
|
||||||
|
if (result.IsSuccess()) {
|
||||||
|
InitializeController(aruid);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ResourceManager::RegisterCoreAppletResource() {
|
Result ResourceManager::RegisterCoreAppletResource() {
|
||||||
|
@ -227,7 +238,6 @@ void ResourceManager::UpdateControllers(std::uintptr_t user_data,
|
||||||
home_button->OnUpdate(core_timing);
|
home_button->OnUpdate(core_timing);
|
||||||
sleep_button->OnUpdate(core_timing);
|
sleep_button->OnUpdate(core_timing);
|
||||||
capture_button->OnUpdate(core_timing);
|
capture_button->OnUpdate(core_timing);
|
||||||
xpad->OnUpdate(core_timing);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceManager::UpdateNpad(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
|
void ResourceManager::UpdateNpad(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
|
||||||
|
|
|
@ -31,10 +31,10 @@ class Palma;
|
||||||
class SevenSixAxis;
|
class SevenSixAxis;
|
||||||
class SixAxis;
|
class SixAxis;
|
||||||
class TouchScreen;
|
class TouchScreen;
|
||||||
class XPad;
|
|
||||||
|
|
||||||
using CaptureButton = Controller_Stubbed;
|
using CaptureButton = Controller_Stubbed;
|
||||||
using DebugMouse = Controller_Stubbed;
|
using DebugMouse = Mouse;
|
||||||
|
using Digitizer = Controller_Stubbed;
|
||||||
using HomeButton = Controller_Stubbed;
|
using HomeButton = Controller_Stubbed;
|
||||||
using SleepButton = Controller_Stubbed;
|
using SleepButton = Controller_Stubbed;
|
||||||
using UniquePad = Controller_Stubbed;
|
using UniquePad = Controller_Stubbed;
|
||||||
|
@ -46,12 +46,14 @@ public:
|
||||||
~ResourceManager();
|
~ResourceManager();
|
||||||
|
|
||||||
void Initialize();
|
void Initialize();
|
||||||
|
void InitializeController(u64 aruid);
|
||||||
|
|
||||||
std::shared_ptr<AppletResource> GetAppletResource() const;
|
std::shared_ptr<AppletResource> GetAppletResource() const;
|
||||||
std::shared_ptr<CaptureButton> GetCaptureButton() const;
|
std::shared_ptr<CaptureButton> GetCaptureButton() const;
|
||||||
std::shared_ptr<ConsoleSixAxis> GetConsoleSixAxis() const;
|
std::shared_ptr<ConsoleSixAxis> GetConsoleSixAxis() const;
|
||||||
std::shared_ptr<DebugMouse> GetDebugMouse() const;
|
std::shared_ptr<DebugMouse> GetDebugMouse() const;
|
||||||
std::shared_ptr<DebugPad> GetDebugPad() const;
|
std::shared_ptr<DebugPad> GetDebugPad() const;
|
||||||
|
std::shared_ptr<Digitizer> GetDigitizer() const;
|
||||||
std::shared_ptr<Gesture> GetGesture() const;
|
std::shared_ptr<Gesture> GetGesture() const;
|
||||||
std::shared_ptr<HomeButton> GetHomeButton() const;
|
std::shared_ptr<HomeButton> GetHomeButton() const;
|
||||||
std::shared_ptr<Keyboard> GetKeyboard() const;
|
std::shared_ptr<Keyboard> GetKeyboard() const;
|
||||||
|
@ -96,6 +98,7 @@ private:
|
||||||
std::shared_ptr<ConsoleSixAxis> console_six_axis = nullptr;
|
std::shared_ptr<ConsoleSixAxis> console_six_axis = nullptr;
|
||||||
std::shared_ptr<DebugMouse> debug_mouse = nullptr;
|
std::shared_ptr<DebugMouse> debug_mouse = nullptr;
|
||||||
std::shared_ptr<DebugPad> debug_pad = nullptr;
|
std::shared_ptr<DebugPad> debug_pad = nullptr;
|
||||||
|
std::shared_ptr<Digitizer> digitizer = nullptr;
|
||||||
std::shared_ptr<Gesture> gesture = nullptr;
|
std::shared_ptr<Gesture> gesture = nullptr;
|
||||||
std::shared_ptr<HomeButton> home_button = nullptr;
|
std::shared_ptr<HomeButton> home_button = nullptr;
|
||||||
std::shared_ptr<Keyboard> keyboard = nullptr;
|
std::shared_ptr<Keyboard> keyboard = nullptr;
|
||||||
|
@ -107,7 +110,6 @@ private:
|
||||||
std::shared_ptr<SleepButton> sleep_button = nullptr;
|
std::shared_ptr<SleepButton> sleep_button = nullptr;
|
||||||
std::shared_ptr<TouchScreen> touch_screen = nullptr;
|
std::shared_ptr<TouchScreen> touch_screen = nullptr;
|
||||||
std::shared_ptr<UniquePad> unique_pad = nullptr;
|
std::shared_ptr<UniquePad> unique_pad = nullptr;
|
||||||
std::shared_ptr<XPad> xpad = nullptr;
|
|
||||||
|
|
||||||
// TODO: Create these resources
|
// TODO: Create these resources
|
||||||
// std::shared_ptr<AudioControl> audio_control = nullptr;
|
// std::shared_ptr<AudioControl> audio_control = nullptr;
|
||||||
|
|
|
@ -23,13 +23,13 @@ constexpr VAddr c = 16 * HIGH_PAGE_SIZE;
|
||||||
|
|
||||||
class RasterizerInterface {
|
class RasterizerInterface {
|
||||||
public:
|
public:
|
||||||
void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) {
|
void UpdatePagesCachedCount(VAddr addr, u64 size, bool cache) {
|
||||||
const u64 page_start{addr >> Core::Memory::YUZU_PAGEBITS};
|
const u64 page_start{addr >> Core::Memory::YUZU_PAGEBITS};
|
||||||
const u64 page_end{(addr + size + Core::Memory::YUZU_PAGESIZE - 1) >>
|
const u64 page_end{(addr + size + Core::Memory::YUZU_PAGESIZE - 1) >>
|
||||||
Core::Memory::YUZU_PAGEBITS};
|
Core::Memory::YUZU_PAGEBITS};
|
||||||
for (u64 page = page_start; page < page_end; ++page) {
|
for (u64 page = page_start; page < page_end; ++page) {
|
||||||
int& value = page_table[page];
|
int& value = page_table[page];
|
||||||
value += delta;
|
value += (cache ? 1 : -1);
|
||||||
if (value < 0) {
|
if (value < 0) {
|
||||||
throw std::logic_error{"negative page"};
|
throw std::logic_error{"negative page"};
|
||||||
}
|
}
|
||||||
|
@ -546,4 +546,4 @@ TEST_CASE("MemoryTracker: Cached write downloads") {
|
||||||
REQUIRE(!memory_track->IsRegionGpuModified(c + PAGE, PAGE));
|
REQUIRE(!memory_track->IsRegionGpuModified(c + PAGE, PAGE));
|
||||||
memory_track->MarkRegionAsCpuModified(c, WORD);
|
memory_track->MarkRegionAsCpuModified(c, WORD);
|
||||||
REQUIRE(rasterizer.Count() == 0);
|
REQUIRE(rasterizer.Count() == 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -473,7 +473,7 @@ private:
|
||||||
VAddr addr = cpu_addr + word_index * BYTES_PER_WORD;
|
VAddr addr = cpu_addr + word_index * BYTES_PER_WORD;
|
||||||
IteratePages(changed_bits, [&](size_t offset, size_t size) {
|
IteratePages(changed_bits, [&](size_t offset, size_t size) {
|
||||||
rasterizer->UpdatePagesCachedCount(addr + offset * BYTES_PER_PAGE,
|
rasterizer->UpdatePagesCachedCount(addr + offset * BYTES_PER_PAGE,
|
||||||
size * BYTES_PER_PAGE, add_to_rasterizer ? 1 : -1);
|
size * BYTES_PER_PAGE, add_to_rasterizer);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
|
||||||
|
#include "common/alignment.h"
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/div_ceil.h"
|
#include "common/div_ceil.h"
|
||||||
|
@ -11,61 +12,63 @@
|
||||||
|
|
||||||
namespace VideoCore {
|
namespace VideoCore {
|
||||||
|
|
||||||
|
static constexpr u16 IdentityValue = 1;
|
||||||
|
|
||||||
using namespace Core::Memory;
|
using namespace Core::Memory;
|
||||||
|
|
||||||
RasterizerAccelerated::RasterizerAccelerated(Memory& cpu_memory_)
|
RasterizerAccelerated::RasterizerAccelerated(Memory& cpu_memory_) : map{}, cpu_memory{cpu_memory_} {
|
||||||
: cached_pages(std::make_unique<CachedPages>()), cpu_memory{cpu_memory_} {}
|
// We are tracking CPU memory, which cannot map more than 39 bits.
|
||||||
|
const VAddr start_address = 0;
|
||||||
|
const VAddr end_address = (1ULL << 39);
|
||||||
|
const IntervalType address_space_interval(start_address, end_address);
|
||||||
|
const auto value = std::make_pair(address_space_interval, IdentityValue);
|
||||||
|
|
||||||
|
map.add(value);
|
||||||
|
}
|
||||||
|
|
||||||
RasterizerAccelerated::~RasterizerAccelerated() = default;
|
RasterizerAccelerated::~RasterizerAccelerated() = default;
|
||||||
|
|
||||||
void RasterizerAccelerated::UpdatePagesCachedCount(VAddr addr, u64 size, int delta) {
|
void RasterizerAccelerated::UpdatePagesCachedCount(VAddr addr, u64 size, bool cache) {
|
||||||
u64 uncache_begin = 0;
|
// Align sizes.
|
||||||
u64 cache_begin = 0;
|
addr = Common::AlignDown(addr, YUZU_PAGESIZE);
|
||||||
u64 uncache_bytes = 0;
|
size = Common::AlignUp(size, YUZU_PAGESIZE);
|
||||||
u64 cache_bytes = 0;
|
|
||||||
|
|
||||||
std::atomic_thread_fence(std::memory_order_acquire);
|
// Declare the overall interval we are going to operate on.
|
||||||
const u64 page_end = Common::DivCeil(addr + size, YUZU_PAGESIZE);
|
const VAddr start_address = addr;
|
||||||
for (u64 page = addr >> YUZU_PAGEBITS; page != page_end; ++page) {
|
const VAddr end_address = addr + size;
|
||||||
std::atomic_uint16_t& count = cached_pages->at(page >> 2).Count(page);
|
const IntervalType modification_range(start_address, end_address);
|
||||||
|
|
||||||
if (delta > 0) {
|
// Find the boundaries of where to iterate.
|
||||||
ASSERT_MSG(count.load(std::memory_order::relaxed) < UINT16_MAX, "Count may overflow!");
|
const auto lower = map.lower_bound(modification_range);
|
||||||
} else if (delta < 0) {
|
const auto upper = map.upper_bound(modification_range);
|
||||||
ASSERT_MSG(count.load(std::memory_order::relaxed) > 0, "Count may underflow!");
|
|
||||||
} else {
|
|
||||||
ASSERT_MSG(false, "Delta must be non-zero!");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adds or subtracts 1, as count is a unsigned 8-bit value
|
// Iterate over the contained intervals.
|
||||||
count.fetch_add(static_cast<u16>(delta), std::memory_order_release);
|
for (auto it = lower; it != upper; it++) {
|
||||||
|
// Intersect interval range with modification range.
|
||||||
|
const auto current_range = modification_range & it->first;
|
||||||
|
|
||||||
// Assume delta is either -1 or 1
|
// Calculate the address and size to operate over.
|
||||||
if (count.load(std::memory_order::relaxed) == 0) {
|
const auto current_addr = current_range.lower();
|
||||||
if (uncache_bytes == 0) {
|
const auto current_size = current_range.upper() - current_addr;
|
||||||
uncache_begin = page;
|
|
||||||
}
|
// Get the current value of the range.
|
||||||
uncache_bytes += YUZU_PAGESIZE;
|
const auto value = it->second;
|
||||||
} else if (uncache_bytes > 0) {
|
|
||||||
cpu_memory.RasterizerMarkRegionCached(uncache_begin << YUZU_PAGEBITS, uncache_bytes,
|
if (cache && value == IdentityValue) {
|
||||||
false);
|
// If we are going to cache, and the value is not yet referenced, then cache this range.
|
||||||
uncache_bytes = 0;
|
cpu_memory.RasterizerMarkRegionCached(current_addr, current_size, true);
|
||||||
}
|
} else if (!cache && value == IdentityValue + 1) {
|
||||||
if (count.load(std::memory_order::relaxed) == 1 && delta > 0) {
|
// If we are going to uncache, and this is the last reference, then uncache this range.
|
||||||
if (cache_bytes == 0) {
|
cpu_memory.RasterizerMarkRegionCached(current_addr, current_size, false);
|
||||||
cache_begin = page;
|
|
||||||
}
|
|
||||||
cache_bytes += YUZU_PAGESIZE;
|
|
||||||
} else if (cache_bytes > 0) {
|
|
||||||
cpu_memory.RasterizerMarkRegionCached(cache_begin << YUZU_PAGEBITS, cache_bytes, true);
|
|
||||||
cache_bytes = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (uncache_bytes > 0) {
|
|
||||||
cpu_memory.RasterizerMarkRegionCached(uncache_begin << YUZU_PAGEBITS, uncache_bytes, false);
|
// Update the set.
|
||||||
}
|
const auto value = std::make_pair(modification_range, IdentityValue);
|
||||||
if (cache_bytes > 0) {
|
if (cache) {
|
||||||
cpu_memory.RasterizerMarkRegionCached(cache_begin << YUZU_PAGEBITS, cache_bytes, true);
|
map.add(value);
|
||||||
|
} else {
|
||||||
|
map.subtract(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array>
|
#include <boost/icl/interval_map.hpp>
|
||||||
#include <atomic>
|
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "video_core/rasterizer_interface.h"
|
#include "video_core/rasterizer_interface.h"
|
||||||
|
@ -21,28 +20,16 @@ public:
|
||||||
explicit RasterizerAccelerated(Core::Memory::Memory& cpu_memory_);
|
explicit RasterizerAccelerated(Core::Memory::Memory& cpu_memory_);
|
||||||
~RasterizerAccelerated() override;
|
~RasterizerAccelerated() override;
|
||||||
|
|
||||||
void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) override;
|
void UpdatePagesCachedCount(VAddr addr, u64 size, bool cache) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class CacheEntry final {
|
using PageIndex = VAddr;
|
||||||
public:
|
using PageReferenceCount = u16;
|
||||||
CacheEntry() = default;
|
|
||||||
|
|
||||||
std::atomic_uint16_t& Count(std::size_t page) {
|
using IntervalMap = boost::icl::interval_map<PageIndex, PageReferenceCount>;
|
||||||
return values[page & 3];
|
using IntervalType = IntervalMap::interval_type;
|
||||||
}
|
|
||||||
|
|
||||||
const std::atomic_uint16_t& Count(std::size_t page) const {
|
IntervalMap map;
|
||||||
return values[page & 3];
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::array<std::atomic_uint16_t, 4> values{};
|
|
||||||
};
|
|
||||||
static_assert(sizeof(CacheEntry) == 8, "CacheEntry should be 8 bytes!");
|
|
||||||
|
|
||||||
using CachedPages = std::array<CacheEntry, 0x2000000>;
|
|
||||||
std::unique_ptr<CachedPages> cached_pages;
|
|
||||||
Core::Memory::Memory& cpu_memory;
|
Core::Memory::Memory& cpu_memory;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -162,7 +162,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Increase/decrease the number of object in pages touching the specified region
|
/// Increase/decrease the number of object in pages touching the specified region
|
||||||
virtual void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) {}
|
virtual void UpdatePagesCachedCount(VAddr addr, u64 size, bool cache) {}
|
||||||
|
|
||||||
/// Initialize disk cached resources for the game being emulated
|
/// Initialize disk cached resources for the game being emulated
|
||||||
virtual void LoadDiskResources(u64 title_id, std::stop_token stop_loading,
|
virtual void LoadDiskResources(u64 title_id, std::stop_token stop_loading,
|
||||||
|
|
|
@ -132,7 +132,7 @@ void ShaderCache::Register(std::unique_ptr<ShaderInfo> data, VAddr addr, size_t
|
||||||
|
|
||||||
storage.push_back(std::move(data));
|
storage.push_back(std::move(data));
|
||||||
|
|
||||||
rasterizer.UpdatePagesCachedCount(addr, size, 1);
|
rasterizer.UpdatePagesCachedCount(addr, size, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShaderCache::InvalidatePagesInRegion(VAddr addr, size_t size) {
|
void ShaderCache::InvalidatePagesInRegion(VAddr addr, size_t size) {
|
||||||
|
@ -209,7 +209,7 @@ void ShaderCache::UnmarkMemory(Entry* entry) {
|
||||||
|
|
||||||
const VAddr addr = entry->addr_start;
|
const VAddr addr = entry->addr_start;
|
||||||
const size_t size = entry->addr_end - addr;
|
const size_t size = entry->addr_end - addr;
|
||||||
rasterizer.UpdatePagesCachedCount(addr, size, -1);
|
rasterizer.UpdatePagesCachedCount(addr, size, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShaderCache::RemoveShadersFromStorage(std::span<ShaderInfo*> removed_shaders) {
|
void ShaderCache::RemoveShadersFromStorage(std::span<ShaderInfo*> removed_shaders) {
|
||||||
|
|
|
@ -2080,7 +2080,7 @@ void TextureCache<P>::TrackImage(ImageBase& image, ImageId image_id) {
|
||||||
ASSERT(False(image.flags & ImageFlagBits::Tracked));
|
ASSERT(False(image.flags & ImageFlagBits::Tracked));
|
||||||
image.flags |= ImageFlagBits::Tracked;
|
image.flags |= ImageFlagBits::Tracked;
|
||||||
if (False(image.flags & ImageFlagBits::Sparse)) {
|
if (False(image.flags & ImageFlagBits::Sparse)) {
|
||||||
rasterizer.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, 1);
|
rasterizer.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (True(image.flags & ImageFlagBits::Registered)) {
|
if (True(image.flags & ImageFlagBits::Registered)) {
|
||||||
|
@ -2091,13 +2091,13 @@ void TextureCache<P>::TrackImage(ImageBase& image, ImageId image_id) {
|
||||||
const auto& map = slot_map_views[map_view_id];
|
const auto& map = slot_map_views[map_view_id];
|
||||||
const VAddr cpu_addr = map.cpu_addr;
|
const VAddr cpu_addr = map.cpu_addr;
|
||||||
const std::size_t size = map.size;
|
const std::size_t size = map.size;
|
||||||
rasterizer.UpdatePagesCachedCount(cpu_addr, size, 1);
|
rasterizer.UpdatePagesCachedCount(cpu_addr, size, true);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ForEachSparseSegment(image,
|
ForEachSparseSegment(image,
|
||||||
[this]([[maybe_unused]] GPUVAddr gpu_addr, VAddr cpu_addr, size_t size) {
|
[this]([[maybe_unused]] GPUVAddr gpu_addr, VAddr cpu_addr, size_t size) {
|
||||||
rasterizer.UpdatePagesCachedCount(cpu_addr, size, 1);
|
rasterizer.UpdatePagesCachedCount(cpu_addr, size, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2106,7 +2106,7 @@ void TextureCache<P>::UntrackImage(ImageBase& image, ImageId image_id) {
|
||||||
ASSERT(True(image.flags & ImageFlagBits::Tracked));
|
ASSERT(True(image.flags & ImageFlagBits::Tracked));
|
||||||
image.flags &= ~ImageFlagBits::Tracked;
|
image.flags &= ~ImageFlagBits::Tracked;
|
||||||
if (False(image.flags & ImageFlagBits::Sparse)) {
|
if (False(image.flags & ImageFlagBits::Sparse)) {
|
||||||
rasterizer.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, -1);
|
rasterizer.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ASSERT(True(image.flags & ImageFlagBits::Registered));
|
ASSERT(True(image.flags & ImageFlagBits::Registered));
|
||||||
|
@ -2117,7 +2117,7 @@ void TextureCache<P>::UntrackImage(ImageBase& image, ImageId image_id) {
|
||||||
const auto& map = slot_map_views[map_view_id];
|
const auto& map = slot_map_views[map_view_id];
|
||||||
const VAddr cpu_addr = map.cpu_addr;
|
const VAddr cpu_addr = map.cpu_addr;
|
||||||
const std::size_t size = map.size;
|
const std::size_t size = map.size;
|
||||||
rasterizer.UpdatePagesCachedCount(cpu_addr, size, -1);
|
rasterizer.UpdatePagesCachedCount(cpu_addr, size, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue