Compare commits

..

20 Commits

Author SHA1 Message Date
yuzubot
20b744ee68 Android 191 2024-01-13 01:00:47 +00:00
yuzubot
d62868644b Merge yuzu-emu#12652 2024-01-13 01:00:46 +00:00
yuzubot
bd30c1e2d9 Merge yuzu-emu#12612 2024-01-13 01:00:46 +00:00
yuzubot
0dc00454e5 Merge yuzu-emu#12610 2024-01-13 01:00:46 +00:00
yuzubot
fd9e7d6cb1 Merge yuzu-emu#12579 2024-01-13 01:00:46 +00:00
liamwhite
f7a3c135e2 Merge pull request #12605 from german77/abstract
service: hid: Create abstracted pad structure
2024-01-12 10:02:13 -05:00
liamwhite
fcb0dff67c Merge pull request #12642 from t895/adapter-refactor
android: Refactor list adapters
2024-01-12 10:01:54 -05:00
german77
b5dac5f525 service: hid: Create abstracted pad structure 2024-01-11 19:35:04 -06:00
Charles Lombardo
a4d90a9a64 Merge pull request #12653 from liamwhite/once-more
ci: fix file mode check in format script
2024-01-11 19:58:41 -05:00
Liam
84787a2ada ci: fix file mode check in format script 2024-01-11 18:57:07 -05:00
t895
d3ba6b334b android: Fix added driver path
While this didn't break anything, the extra separator was unnecessary
2024-01-10 23:14:04 -05:00
t895
dac8c4ce4d android: Add button to use global driver value 2024-01-10 23:14:04 -05:00
t895
9e974d4c7e android: Reload driver data on importing user data 2024-01-10 23:14:04 -05:00
t895
6bfc3c530c android: Rework driver fragment
Applies settings upon selection and uses a new Driver model to represent the information in-view. Also switches from an async diff list to a plain one.
2024-01-10 23:14:04 -05:00
t895
93239f191a android: Refactor DriverAdapter to use AbstractSingleSelectionList 2024-01-10 23:14:04 -05:00
t895
b17db2b462 android: Create generic single selection list adapter 2024-01-10 23:14:04 -05:00
t895
9130366a58 android: Refactor recycler view adapters to use AbstractListAdapter 2024-01-10 23:14:04 -05:00
t895
ad0066a6b6 android: Create generic list adapter for basic lists
Simplifies basic setup for lists
2024-01-10 23:14:04 -05:00
t895
78c323c4eb android: Refactor async diff adapters to use AbstractDiffAdapter 2024-01-10 23:14:04 -05:00
t895
51ad2d10de android: Create generic adapter and viewholder
Eliminates repeated code associated with every async differ list
2024-01-10 23:14:04 -05:00
70 changed files with 3554 additions and 299 deletions

View File

@@ -25,7 +25,7 @@ for f in $FILES_TO_LINT; do
"$CLANG_FORMAT" -i "$f"
done
DIFF=$(git diff)
DIFF=$(git -c core.fileMode=false diff)
if [ ! -z "$DIFF" ]; then
echo "!!! Not compliant to coding style, here is the fix:"

View File

@@ -2,9 +2,8 @@
|----|----|----|----|----|
| [12579](https://github.com/yuzu-emu/yuzu-android//pull/12579) | [`66ae60a9e`](https://github.com/yuzu-emu/yuzu-android//pull/12579/files) | Core: Implement Device Mapping & GPU SMMU | [FernandoS27](https://github.com/FernandoS27/) | Yes |
| [12610](https://github.com/yuzu-emu/yuzu-android//pull/12610) | [`200b371d1`](https://github.com/yuzu-emu/yuzu-android//pull/12610/files) | server_manager: respond to session close correctly | [liamwhite](https://github.com/liamwhite/) | Yes |
| [12611](https://github.com/yuzu-emu/yuzu-android//pull/12611) | [`642a29923`](https://github.com/yuzu-emu/yuzu-android//pull/12611/files) | kernel: fix resource management issues | [liamwhite](https://github.com/liamwhite/) | Yes |
| [12612](https://github.com/yuzu-emu/yuzu-android//pull/12612) | [`417df3b6e`](https://github.com/yuzu-emu/yuzu-android//pull/12612/files) | fsp-srv: use program registry for SetCurrentProcess | [liamwhite](https://github.com/liamwhite/) | Yes |
| [12642](https://github.com/yuzu-emu/yuzu-android//pull/12642) | [`4037afea1`](https://github.com/yuzu-emu/yuzu-android//pull/12642/files) | android: Refactor list adapters | [t895](https://github.com/t895/) | Yes |
| [12612](https://github.com/yuzu-emu/yuzu-android//pull/12612) | [`aae9eea53`](https://github.com/yuzu-emu/yuzu-android//pull/12612/files) | fsp-srv: use program registry for SetCurrentProcess | [liamwhite](https://github.com/liamwhite/) | Yes |
| [12652](https://github.com/yuzu-emu/yuzu-android//pull/12652) | [`2a0d707ce`](https://github.com/yuzu-emu/yuzu-android//pull/12652/files) | shader_recompiler: emulate 8-bit and 16-bit storage writes with cas loop | [liamwhite](https://github.com/liamwhite/) | Yes |
End of merge log. You can find the original README.md below the break.

View File

@@ -410,8 +410,8 @@ void EmulationSession::OnGamepadConnectEvent([[maybe_unused]] int index) {
jauto handheld = m_system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
if (controller->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::Handheld) {
handheld->SetNpadStyleIndex(Core::HID::NpadStyleIndex::ProController);
controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::ProController);
handheld->SetNpadStyleIndex(Core::HID::NpadStyleIndex::Fullkey);
controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::Fullkey);
handheld->Disconnect();
}
}

View File

@@ -2,7 +2,6 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/page_table.h"
#include "common/scope_exit.h"
namespace Common {
@@ -12,10 +11,29 @@ PageTable::~PageTable() noexcept = default;
bool PageTable::BeginTraversal(TraversalEntry* out_entry, TraversalContext* out_context,
Common::ProcessAddress address) const {
out_context->next_offset = GetInteger(address);
out_context->next_page = address / page_size;
// Setup invalid defaults.
out_entry->phys_addr = 0;
out_entry->block_size = page_size;
out_context->next_page = 0;
return this->ContinueTraversal(out_entry, out_context);
// Validate that we can read the actual entry.
const auto page = address / page_size;
if (page >= backing_addr.size()) {
return false;
}
// Validate that the entry is mapped.
const auto phys_addr = backing_addr[page];
if (phys_addr == 0) {
return false;
}
// Populate the results.
out_entry->phys_addr = phys_addr + GetInteger(address);
out_context->next_page = page + 1;
out_context->next_offset = GetInteger(address) + page_size;
return true;
}
bool PageTable::ContinueTraversal(TraversalEntry* out_entry, TraversalContext* context) const {
@@ -23,12 +41,6 @@ bool PageTable::ContinueTraversal(TraversalEntry* out_entry, TraversalContext* c
out_entry->phys_addr = 0;
out_entry->block_size = page_size;
// Regardless of whether the page was mapped, advance on exit.
SCOPE_EXIT({
context->next_page += 1;
context->next_offset += page_size;
});
// Validate that we can read the actual entry.
const auto page = context->next_page;
if (page >= backing_addr.size()) {
@@ -43,6 +55,8 @@ bool PageTable::ContinueTraversal(TraversalEntry* out_entry, TraversalContext* c
// Populate the results.
out_entry->phys_addr = phys_addr + context->next_offset;
context->next_page = page + 1;
context->next_offset += page_size;
return true;
}

View File

@@ -114,7 +114,7 @@ public:
}
Kernel::KThread* GetActiveThread() override {
return state->active_thread.GetPointerUnsafe();
return state->active_thread;
}
private:
@@ -147,14 +147,11 @@ private:
std::scoped_lock lk{connection_lock};
// Find the process we are going to debug.
SetDebugProcess();
// Ensure everything is stopped.
PauseEmulation();
// Set up the new frontend.
frontend = std::make_unique<GDBStub>(*this, system, debug_process.GetPointerUnsafe());
frontend = std::make_unique<GDBStub>(*this, system);
// Set the new state. This will tear down any existing state.
state = ConnectionState{
@@ -197,20 +194,15 @@ private:
UpdateActiveThread();
if (state->info.type == SignalType::Watchpoint) {
frontend->Watchpoint(std::addressof(*state->active_thread),
*state->info.watchpoint);
frontend->Watchpoint(state->active_thread, *state->info.watchpoint);
} else {
frontend->Stopped(std::addressof(*state->active_thread));
frontend->Stopped(state->active_thread);
}
break;
case SignalType::ShuttingDown:
frontend->ShuttingDown();
// Release members.
state->active_thread.Reset(nullptr);
debug_process.Reset(nullptr);
// Wait for emulation to shut down gracefully now.
state->signal_pipe.close();
state->client_socket.shutdown(boost::asio::socket_base::shutdown_both);
@@ -230,7 +222,7 @@ private:
stopped = true;
PauseEmulation();
UpdateActiveThread();
frontend->Stopped(state->active_thread.GetPointerUnsafe());
frontend->Stopped(state->active_thread);
break;
}
case DebuggerAction::Continue:
@@ -240,7 +232,7 @@ private:
MarkResumed([&] {
state->active_thread->SetStepState(Kernel::StepState::StepPending);
state->active_thread->Resume(Kernel::SuspendType::Debug);
ResumeEmulation(state->active_thread.GetPointerUnsafe());
ResumeEmulation(state->active_thread);
});
break;
case DebuggerAction::StepThreadLocked: {
@@ -263,7 +255,6 @@ private:
}
void PauseEmulation() {
Kernel::KScopedLightLock ll{debug_process->GetListLock()};
Kernel::KScopedSchedulerLock sl{system.Kernel()};
// Put all threads to sleep on next scheduler round.
@@ -273,9 +264,6 @@ private:
}
void ResumeEmulation(Kernel::KThread* except = nullptr) {
Kernel::KScopedLightLock ll{debug_process->GetListLock()};
Kernel::KScopedSchedulerLock sl{system.Kernel()};
// Wake up all threads.
for (auto& thread : ThreadList()) {
if (std::addressof(thread) == except) {
@@ -289,16 +277,15 @@ private:
template <typename Callback>
void MarkResumed(Callback&& cb) {
Kernel::KScopedSchedulerLock sl{system.Kernel()};
stopped = false;
cb();
}
void UpdateActiveThread() {
Kernel::KScopedLightLock ll{debug_process->GetListLock()};
auto& threads{ThreadList()};
for (auto& thread : threads) {
if (std::addressof(thread) == state->active_thread.GetPointerUnsafe()) {
if (std::addressof(thread) == state->active_thread) {
// Thread is still alive, no need to update.
return;
}
@@ -306,18 +293,12 @@ private:
state->active_thread = std::addressof(threads.front());
}
private:
void SetDebugProcess() {
debug_process = std::move(system.Kernel().GetProcessList().back());
}
Kernel::KProcess::ThreadList& ThreadList() {
return debug_process->GetThreadList();
return system.ApplicationProcess()->GetThreadList();
}
private:
System& system;
Kernel::KScopedAutoObject<Kernel::KProcess> debug_process;
std::unique_ptr<DebuggerFrontend> frontend;
boost::asio::io_context io_context;
@@ -329,7 +310,7 @@ private:
boost::process::async_pipe signal_pipe;
SignalInfo info;
Kernel::KScopedAutoObject<Kernel::KThread> active_thread;
Kernel::KThread* active_thread;
std::array<u8, 4096> client_data;
bool pipe_data;
};

View File

@@ -108,9 +108,9 @@ static std::string EscapeXML(std::string_view data) {
return escaped;
}
GDBStub::GDBStub(DebuggerBackend& backend_, Core::System& system_, Kernel::KProcess* debug_process_)
: DebuggerFrontend(backend_), system{system_}, debug_process{debug_process_} {
if (GetProcess()->Is64Bit()) {
GDBStub::GDBStub(DebuggerBackend& backend_, Core::System& system_)
: DebuggerFrontend(backend_), system{system_} {
if (system.ApplicationProcess()->Is64Bit()) {
arch = std::make_unique<GDBStubA64>();
} else {
arch = std::make_unique<GDBStubA32>();
@@ -276,7 +276,7 @@ void GDBStub::ExecuteCommand(std::string_view packet, std::vector<DebuggerAction
const size_t size{static_cast<size_t>(strtoll(command.data() + sep, nullptr, 16))};
std::vector<u8> mem(size);
if (GetMemory().ReadBlock(addr, mem.data(), size)) {
if (system.ApplicationMemory().ReadBlock(addr, mem.data(), size)) {
// Restore any bytes belonging to replaced instructions.
auto it = replaced_instructions.lower_bound(addr);
for (; it != replaced_instructions.end() && it->first < addr + size; it++) {
@@ -310,8 +310,8 @@ void GDBStub::ExecuteCommand(std::string_view packet, std::vector<DebuggerAction
const auto mem_substr{std::string_view(command).substr(mem_sep)};
const auto mem{Common::HexStringToVector(mem_substr, false)};
if (GetMemory().WriteBlock(addr, mem.data(), size)) {
Core::InvalidateInstructionCacheRange(GetProcess(), addr, size);
if (system.ApplicationMemory().WriteBlock(addr, mem.data(), size)) {
Core::InvalidateInstructionCacheRange(system.ApplicationProcess(), addr, size);
SendReply(GDB_STUB_REPLY_OK);
} else {
SendReply(GDB_STUB_REPLY_ERR);
@@ -353,7 +353,7 @@ void GDBStub::HandleBreakpointInsert(std::string_view command) {
const size_t addr{static_cast<size_t>(strtoll(command.data() + addr_sep, nullptr, 16))};
const size_t size{static_cast<size_t>(strtoll(command.data() + size_sep, nullptr, 16))};
if (!GetMemory().IsValidVirtualAddressRange(addr, size)) {
if (!system.ApplicationMemory().IsValidVirtualAddressRange(addr, size)) {
SendReply(GDB_STUB_REPLY_ERR);
return;
}
@@ -362,20 +362,22 @@ void GDBStub::HandleBreakpointInsert(std::string_view command) {
switch (type) {
case BreakpointType::Software:
replaced_instructions[addr] = GetMemory().Read32(addr);
GetMemory().Write32(addr, arch->BreakpointInstruction());
Core::InvalidateInstructionCacheRange(GetProcess(), addr, sizeof(u32));
replaced_instructions[addr] = system.ApplicationMemory().Read32(addr);
system.ApplicationMemory().Write32(addr, arch->BreakpointInstruction());
Core::InvalidateInstructionCacheRange(system.ApplicationProcess(), addr, sizeof(u32));
success = true;
break;
case BreakpointType::WriteWatch:
success = GetProcess()->InsertWatchpoint(addr, size, Kernel::DebugWatchpointType::Write);
success = system.ApplicationProcess()->InsertWatchpoint(addr, size,
Kernel::DebugWatchpointType::Write);
break;
case BreakpointType::ReadWatch:
success = GetProcess()->InsertWatchpoint(addr, size, Kernel::DebugWatchpointType::Read);
success = system.ApplicationProcess()->InsertWatchpoint(addr, size,
Kernel::DebugWatchpointType::Read);
break;
case BreakpointType::AccessWatch:
success =
GetProcess()->InsertWatchpoint(addr, size, Kernel::DebugWatchpointType::ReadOrWrite);
success = system.ApplicationProcess()->InsertWatchpoint(
addr, size, Kernel::DebugWatchpointType::ReadOrWrite);
break;
case BreakpointType::Hardware:
default:
@@ -398,7 +400,7 @@ void GDBStub::HandleBreakpointRemove(std::string_view command) {
const size_t addr{static_cast<size_t>(strtoll(command.data() + addr_sep, nullptr, 16))};
const size_t size{static_cast<size_t>(strtoll(command.data() + size_sep, nullptr, 16))};
if (!GetMemory().IsValidVirtualAddressRange(addr, size)) {
if (!system.ApplicationMemory().IsValidVirtualAddressRange(addr, size)) {
SendReply(GDB_STUB_REPLY_ERR);
return;
}
@@ -409,22 +411,24 @@ void GDBStub::HandleBreakpointRemove(std::string_view command) {
case BreakpointType::Software: {
const auto orig_insn{replaced_instructions.find(addr)};
if (orig_insn != replaced_instructions.end()) {
GetMemory().Write32(addr, orig_insn->second);
Core::InvalidateInstructionCacheRange(GetProcess(), addr, sizeof(u32));
system.ApplicationMemory().Write32(addr, orig_insn->second);
Core::InvalidateInstructionCacheRange(system.ApplicationProcess(), addr, sizeof(u32));
replaced_instructions.erase(addr);
success = true;
}
break;
}
case BreakpointType::WriteWatch:
success = GetProcess()->RemoveWatchpoint(addr, size, Kernel::DebugWatchpointType::Write);
success = system.ApplicationProcess()->RemoveWatchpoint(addr, size,
Kernel::DebugWatchpointType::Write);
break;
case BreakpointType::ReadWatch:
success = GetProcess()->RemoveWatchpoint(addr, size, Kernel::DebugWatchpointType::Read);
success = system.ApplicationProcess()->RemoveWatchpoint(addr, size,
Kernel::DebugWatchpointType::Read);
break;
case BreakpointType::AccessWatch:
success =
GetProcess()->RemoveWatchpoint(addr, size, Kernel::DebugWatchpointType::ReadOrWrite);
success = system.ApplicationProcess()->RemoveWatchpoint(
addr, size, Kernel::DebugWatchpointType::ReadOrWrite);
break;
case BreakpointType::Hardware:
default:
@@ -462,10 +466,10 @@ void GDBStub::HandleQuery(std::string_view command) {
const auto target_xml{arch->GetTargetXML()};
SendReply(PaginateBuffer(target_xml, command.substr(30)));
} else if (command.starts_with("Offsets")) {
const auto main_offset = Core::FindMainModuleEntrypoint(GetProcess());
const auto main_offset = Core::FindMainModuleEntrypoint(system.ApplicationProcess());
SendReply(fmt::format("TextSeg={:x}", GetInteger(main_offset)));
} else if (command.starts_with("Xfer:libraries:read::")) {
auto modules = Core::FindModules(GetProcess());
auto modules = Core::FindModules(system.ApplicationProcess());
std::string buffer;
buffer += R"(<?xml version="1.0"?>)";
@@ -479,7 +483,7 @@ void GDBStub::HandleQuery(std::string_view command) {
SendReply(PaginateBuffer(buffer, command.substr(21)));
} else if (command.starts_with("fThreadInfo")) {
// beginning of list
const auto& threads = GetProcess()->GetThreadList();
const auto& threads = system.ApplicationProcess()->GetThreadList();
std::vector<std::string> thread_ids;
for (const auto& thread : threads) {
thread_ids.push_back(fmt::format("{:x}", thread.GetThreadId()));
@@ -493,7 +497,7 @@ void GDBStub::HandleQuery(std::string_view command) {
buffer += R"(<?xml version="1.0"?>)";
buffer += "<threads>";
const auto& threads = GetProcess()->GetThreadList();
const auto& threads = system.ApplicationProcess()->GetThreadList();
for (const auto& thread : threads) {
auto thread_name{Core::GetThreadName(&thread)};
if (!thread_name) {
@@ -609,7 +613,7 @@ void GDBStub::HandleRcmd(const std::vector<u8>& command) {
std::string_view command_str{reinterpret_cast<const char*>(&command[0]), command.size()};
std::string reply;
auto* process = GetProcess();
auto* process = system.ApplicationProcess();
auto& page_table = process->GetPageTable();
const char* commands = "Commands:\n"
@@ -710,7 +714,7 @@ void GDBStub::HandleRcmd(const std::vector<u8>& command) {
}
Kernel::KThread* GDBStub::GetThreadByID(u64 thread_id) {
auto& threads{GetProcess()->GetThreadList()};
auto& threads{system.ApplicationProcess()->GetThreadList()};
for (auto& thread : threads) {
if (thread.GetThreadId() == thread_id) {
return std::addressof(thread);
@@ -779,12 +783,4 @@ void GDBStub::SendStatus(char status) {
backend.WriteToClient(buf);
}
Kernel::KProcess* GDBStub::GetProcess() {
return debug_process;
}
Core::Memory::Memory& GDBStub::GetMemory() {
return GetProcess()->GetMemory();
}
} // namespace Core

View File

@@ -12,22 +12,13 @@
#include "core/debugger/debugger_interface.h"
#include "core/debugger/gdbstub_arch.h"
namespace Kernel {
class KProcess;
}
namespace Core::Memory {
class Memory;
}
namespace Core {
class System;
class GDBStub : public DebuggerFrontend {
public:
explicit GDBStub(DebuggerBackend& backend, Core::System& system,
Kernel::KProcess* debug_process);
explicit GDBStub(DebuggerBackend& backend, Core::System& system);
~GDBStub() override;
void Connected() override;
@@ -51,12 +42,8 @@ private:
void SendReply(std::string_view data);
void SendStatus(char status);
Kernel::KProcess* GetProcess();
Core::Memory::Memory& GetMemory();
private:
Core::System& system;
Kernel::KProcess* debug_process;
std::unique_ptr<GDBStubArch> arch;
std::vector<char> current_command;
std::map<VAddr, u32> replaced_instructions;

View File

@@ -47,7 +47,7 @@ void DefaultControllerApplet::ReconfigureControllers(ReconfigureCallback callbac
// Connect controllers based on the following priority list from highest to lowest priority:
// Pro Controller -> Dual Joycons -> Left Joycon/Right Joycon -> Handheld
if (parameters.allow_pro_controller) {
controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::ProController);
controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::Fullkey);
controller->Connect(true);
} else if (parameters.allow_dual_joycons) {
controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::JoyconDual);

View File

@@ -431,82 +431,9 @@ Result KPageTableBase::InitializeForProcess(Svc::CreateProcessFlag as_type, bool
m_memory_block_slab_manager));
}
Result KPageTableBase::FinalizeProcess() {
// Only process tables should be finalized.
ASSERT(!this->IsKernel());
// HLE processes don't have memory mapped.
R_SUCCEED_IF(m_impl == nullptr);
// NOTE: Here Nintendo calls an unknown OnFinalize function.
// this->OnFinalize();
// NOTE: Here Nintendo calls a second unknown OnFinalize function.
// this->OnFinalize2();
// Get implementation objects.
auto& impl = this->GetImpl();
auto& mm = m_kernel.MemoryManager();
// Traverse, freeing all pages.
{
// Get the address space size.
const size_t as_size = this->GetAddressSpaceSize();
// Begin the traversal.
TraversalContext context;
TraversalEntry cur_entry = {
.phys_addr = 0,
.block_size = 0,
};
bool cur_valid = false;
TraversalEntry next_entry;
bool next_valid;
size_t tot_size = 0;
next_valid = impl.BeginTraversal(std::addressof(next_entry), std::addressof(context),
this->GetAddressSpaceStart());
// Iterate over entries.
while (true) {
if ((!next_valid && !cur_valid) ||
(next_valid && cur_valid &&
next_entry.phys_addr == cur_entry.phys_addr + cur_entry.block_size)) {
cur_entry.block_size += next_entry.block_size;
} else {
if (cur_valid && IsHeapPhysicalAddressForFinalize(cur_entry.phys_addr)) {
mm.Close(cur_entry.phys_addr, cur_entry.block_size / PageSize);
}
// Update tracking variables.
tot_size += cur_entry.block_size;
cur_entry = next_entry;
cur_valid = next_valid;
}
if (cur_entry.block_size + tot_size >= as_size) {
break;
}
next_valid =
impl.ContinueTraversal(std::addressof(next_entry), std::addressof(context));
}
// Handle the last block.
if (cur_valid && IsHeapPhysicalAddressForFinalize(cur_entry.phys_addr)) {
mm.Close(cur_entry.phys_addr, cur_entry.block_size / PageSize);
}
}
R_SUCCEED();
}
void KPageTableBase::Finalize() {
this->FinalizeProcess();
auto HostUnmapCallback = [&](KProcessAddress addr, u64 size) {
if (m_impl->fastmem_arena) {
if (Settings::IsFastmemEnabled()) {
m_system.DeviceMemory().buffer.Unmap(GetInteger(addr), size, false);
}
};

View File

@@ -241,7 +241,6 @@ public:
KResourceLimit* resource_limit, Core::Memory::Memory& memory,
KProcessAddress aslr_space_start);
Result FinalizeProcess();
void Finalize();
bool IsKernel() const {

View File

@@ -172,12 +172,6 @@ void KProcess::Finalize() {
m_resource_limit->Close();
}
// Clear expensive resources, as the destructor is not called for guest objects.
for (auto& interface : m_arm_interfaces) {
interface.reset();
}
m_exclusive_monitor.reset();
// Perform inherited finalization.
KSynchronizationObject::Finalize();
}

View File

@@ -770,7 +770,6 @@ struct KernelCore::Impl {
std::atomic<u64> next_thread_id{1};
// Lists all processes that exist in the current session.
std::mutex process_list_lock;
std::vector<KProcess*> process_list;
std::atomic<KProcess*> application_process{};
std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context;
@@ -870,19 +869,9 @@ KResourceLimit* KernelCore::GetSystemResourceLimit() {
}
void KernelCore::AppendNewProcess(KProcess* process) {
process->Open();
std::scoped_lock lk{impl->process_list_lock};
impl->process_list.push_back(process);
}
void KernelCore::RemoveProcess(KProcess* process) {
std::scoped_lock lk{impl->process_list_lock};
if (std::erase(impl->process_list, process)) {
process->Close();
}
}
void KernelCore::MakeApplicationProcess(KProcess* process) {
impl->MakeApplicationProcess(process);
}
@@ -895,15 +884,8 @@ const KProcess* KernelCore::ApplicationProcess() const {
return impl->application_process;
}
std::list<KScopedAutoObject<KProcess>> KernelCore::GetProcessList() {
std::list<KScopedAutoObject<KProcess>> processes;
std::scoped_lock lk{impl->process_list_lock};
for (auto* const process : impl->process_list) {
processes.emplace_back(process);
}
return processes;
const std::vector<KProcess*>& KernelCore::GetProcessList() const {
return impl->process_list;
}
Kernel::GlobalSchedulerContext& KernelCore::GlobalSchedulerContext() {

View File

@@ -5,7 +5,6 @@
#include <array>
#include <functional>
#include <list>
#include <memory>
#include <string>
#include <unordered_map>
@@ -117,9 +116,8 @@ public:
/// Retrieves a shared pointer to the system resource limit instance.
KResourceLimit* GetSystemResourceLimit();
/// Adds/removes the given pointer to an internal list of active processes.
/// Adds the given shared pointer to an internal list of active processes.
void AppendNewProcess(KProcess* process);
void RemoveProcess(KProcess* process);
/// Makes the given process the new application process.
void MakeApplicationProcess(KProcess* process);
@@ -131,7 +129,7 @@ public:
const KProcess* ApplicationProcess() const;
/// Retrieves the list of processes.
std::list<KScopedAutoObject<KProcess>> GetProcessList();
const std::vector<KProcess*>& GetProcessList() const;
/// Gets the sole instance of the global scheduler
Kernel::GlobalSchedulerContext& GlobalSchedulerContext();

View File

@@ -74,15 +74,13 @@ Result GetProcessList(Core::System& system, s32* out_num_processes, u64 out_proc
}
auto& memory = GetCurrentMemory(kernel);
auto process_list = kernel.GetProcessList();
auto it = process_list.begin();
const auto& process_list = kernel.GetProcessList();
const auto num_processes = process_list.size();
const auto copy_amount =
std::min(static_cast<std::size_t>(out_process_ids_size), num_processes);
for (std::size_t i = 0; i < copy_amount && it != process_list.end(); ++i, ++it) {
memory.Write64(out_process_ids, (*it)->GetProcessId());
for (std::size_t i = 0; i < copy_amount; ++i) {
memory.Write64(out_process_ids, process_list[i]->GetProcessId());
out_process_ids += sizeof(u64);
}

View File

@@ -40,7 +40,7 @@ Result SaveDataController::CreateSaveData(FileSys::VirtualDir* out_save_data,
FileSys::SaveDataSpaceId space,
const FileSys::SaveDataAttribute& attribute) {
LOG_TRACE(Service_FS, "Creating Save Data for space_id={:01X}, save_struct={}", space,
save_struct.DebugInfo());
attribute.DebugInfo());
auto save_data = factory->Create(space, attribute);
if (save_data == nullptr) {

View File

@@ -15,10 +15,9 @@
namespace Service::Glue {
namespace {
std::optional<u64> GetTitleIDForProcessID(Core::System& system, u64 process_id) {
auto list = system.Kernel().GetProcessList();
const auto iter = std::find_if(list.begin(), list.end(), [&process_id](auto& process) {
std::optional<u64> GetTitleIDForProcessID(const Core::System& system, u64 process_id) {
const auto& list = system.Kernel().GetProcessList();
const auto iter = std::find_if(list.begin(), list.end(), [&process_id](const auto& process) {
return process->GetProcessId() == process_id;
});

View File

@@ -22,10 +22,12 @@ void LoopProcess(Core::System& system) {
std::shared_ptr<HidFirmwareSettings> firmware_settings =
std::make_shared<HidFirmwareSettings>();
// TODO: Remove this hack when am is emulated properly.
resource_manager->Initialize();
resource_manager->RegisterAppletResourceUserId(system.ApplicationProcess()->GetProcessId(),
true);
// TODO: Remove this hack until this service is emulated properly.
const auto process_list = system.Kernel().GetProcessList();
if (!process_list.empty()) {
resource_manager->Initialize();
resource_manager->RegisterAppletResourceUserId(process_list[0]->GetId(), true);
}
server_manager->RegisterNamedService(
"hid", std::make_shared<IHidServer>(system, resource_manager, firmware_settings));

View File

@@ -1498,7 +1498,7 @@ void IHidServer::GetVibrationDeviceInfo(HLERequestContext& ctx) {
bool check_device_index = false;
switch (vibration_device_handle.npad_type) {
case Core::HID::NpadStyleIndex::ProController:
case Core::HID::NpadStyleIndex::Fullkey:
case Core::HID::NpadStyleIndex::Handheld:
case Core::HID::NpadStyleIndex::JoyconDual:
case Core::HID::NpadStyleIndex::JoyconLeft:

View File

@@ -22,26 +22,27 @@ constexpr Result ResultProcessNotFound{ErrorModule::PM, 1};
constexpr u64 NO_PROCESS_FOUND_PID{0};
using ProcessList = std::list<Kernel::KScopedAutoObject<Kernel::KProcess>>;
template <typename F>
Kernel::KScopedAutoObject<Kernel::KProcess> SearchProcessList(ProcessList& process_list,
F&& predicate) {
std::optional<Kernel::KProcess*> SearchProcessList(
const std::vector<Kernel::KProcess*>& process_list,
std::function<bool(Kernel::KProcess*)> predicate) {
const auto iter = std::find_if(process_list.begin(), process_list.end(), predicate);
if (iter == process_list.end()) {
return nullptr;
return std::nullopt;
}
return iter->GetPointerUnsafe();
return *iter;
}
void GetApplicationPidGeneric(HLERequestContext& ctx, ProcessList& process_list) {
auto process = SearchProcessList(process_list, [](auto& p) { return p->IsApplication(); });
void GetApplicationPidGeneric(HLERequestContext& ctx,
const std::vector<Kernel::KProcess*>& process_list) {
const auto process = SearchProcessList(process_list, [](const auto& proc) {
return proc->GetProcessId() == Kernel::KProcess::ProcessIdMin;
});
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess);
rb.Push(process.IsNull() ? NO_PROCESS_FOUND_PID : process->GetProcessId());
rb.Push(process.has_value() ? (*process)->GetProcessId() : NO_PROCESS_FOUND_PID);
}
} // Anonymous namespace
@@ -79,7 +80,8 @@ private:
class DebugMonitor final : public ServiceFramework<DebugMonitor> {
public:
explicit DebugMonitor(Core::System& system_) : ServiceFramework{system_, "pm:dmnt"} {
explicit DebugMonitor(Core::System& system_)
: ServiceFramework{system_, "pm:dmnt"}, kernel{system_.Kernel()} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "GetJitDebugProcessIdList"},
@@ -104,11 +106,12 @@ private:
LOG_DEBUG(Service_PM, "called, program_id={:016X}", program_id);
auto list = kernel.GetProcessList();
auto process = SearchProcessList(
list, [program_id](auto& p) { return p->GetProgramId() == program_id; });
const auto process =
SearchProcessList(kernel.GetProcessList(), [program_id](const auto& proc) {
return proc->GetProgramId() == program_id;
});
if (process.IsNull()) {
if (!process.has_value()) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultProcessNotFound);
return;
@@ -116,13 +119,12 @@ private:
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess);
rb.Push(process->GetProcessId());
rb.Push((*process)->GetProcessId());
}
void GetApplicationProcessId(HLERequestContext& ctx) {
LOG_DEBUG(Service_PM, "called");
auto list = kernel.GetProcessList();
GetApplicationPidGeneric(ctx, list);
GetApplicationPidGeneric(ctx, kernel.GetProcessList());
}
void AtmosphereGetProcessInfo(HLERequestContext& ctx) {
@@ -133,10 +135,11 @@ private:
LOG_WARNING(Service_PM, "(Partial Implementation) called, pid={:016X}", pid);
auto list = kernel.GetProcessList();
auto process = SearchProcessList(list, [pid](auto& p) { return p->GetProcessId() == pid; });
const auto process = SearchProcessList(kernel.GetProcessList(), [pid](const auto& proc) {
return proc->GetProcessId() == pid;
});
if (process.IsNull()) {
if (!process.has_value()) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultProcessNotFound);
return;
@@ -156,7 +159,7 @@ private:
OverrideStatus override_status{};
ProgramLocation program_location{
.program_id = process->GetProgramId(),
.program_id = (*process)->GetProgramId(),
.storage_id = 0,
};
@@ -166,11 +169,14 @@ private:
rb.PushRaw(program_location);
rb.PushRaw(override_status);
}
const Kernel::KernelCore& kernel;
};
class Info final : public ServiceFramework<Info> {
public:
explicit Info(Core::System& system_) : ServiceFramework{system_, "pm:info"} {
explicit Info(Core::System& system_, const std::vector<Kernel::KProcess*>& process_list_)
: ServiceFramework{system_, "pm:info"}, process_list{process_list_} {
static const FunctionInfo functions[] = {
{0, &Info::GetProgramId, "GetProgramId"},
{65000, &Info::AtmosphereGetProcessId, "AtmosphereGetProcessId"},
@@ -187,11 +193,11 @@ private:
LOG_DEBUG(Service_PM, "called, process_id={:016X}", process_id);
auto list = kernel.GetProcessList();
auto process = SearchProcessList(
list, [process_id](auto& p) { return p->GetProcessId() == process_id; });
const auto process = SearchProcessList(process_list, [process_id](const auto& proc) {
return proc->GetProcessId() == process_id;
});
if (process.IsNull()) {
if (!process.has_value()) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultProcessNotFound);
return;
@@ -199,7 +205,7 @@ private:
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess);
rb.Push(process->GetProgramId());
rb.Push((*process)->GetProgramId());
}
void AtmosphereGetProcessId(HLERequestContext& ctx) {
@@ -208,11 +214,11 @@ private:
LOG_DEBUG(Service_PM, "called, program_id={:016X}", program_id);
auto list = system.Kernel().GetProcessList();
auto process = SearchProcessList(
list, [program_id](auto& p) { return p->GetProgramId() == program_id; });
const auto process = SearchProcessList(process_list, [program_id](const auto& proc) {
return proc->GetProgramId() == program_id;
});
if (process.IsNull()) {
if (!process.has_value()) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultProcessNotFound);
return;
@@ -220,13 +226,16 @@ private:
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess);
rb.Push(process->GetProcessId());
rb.Push((*process)->GetProcessId());
}
const std::vector<Kernel::KProcess*>& process_list;
};
class Shell final : public ServiceFramework<Shell> {
public:
explicit Shell(Core::System& system_) : ServiceFramework{system_, "pm:shell"} {
explicit Shell(Core::System& system_)
: ServiceFramework{system_, "pm:shell"}, kernel{system_.Kernel()} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "LaunchProgram"},
@@ -248,9 +257,10 @@ public:
private:
void GetApplicationProcessIdForShell(HLERequestContext& ctx) {
LOG_DEBUG(Service_PM, "called");
auto list = kernel.GetProcessList();
GetApplicationPidGeneric(ctx, list);
GetApplicationPidGeneric(ctx, kernel.GetProcessList());
}
const Kernel::KernelCore& kernel;
};
void LoopProcess(Core::System& system) {
@@ -258,7 +268,8 @@ void LoopProcess(Core::System& system) {
server_manager->RegisterNamedService("pm:bm", std::make_shared<BootMode>(system));
server_manager->RegisterNamedService("pm:dmnt", std::make_shared<DebugMonitor>(system));
server_manager->RegisterNamedService("pm:info", std::make_shared<Info>(system));
server_manager->RegisterNamedService(
"pm:info", std::make_shared<Info>(system, system.Kernel().GetProcessList()));
server_manager->RegisterNamedService("pm:shell", std::make_shared<Shell>(system));
ServerManager::RunServer(std::move(server_manager));
}

View File

@@ -36,6 +36,30 @@ add_library(hid_core STATIC
irsensor/processor_base.h
irsensor/tera_plugin_processor.cpp
irsensor/tera_plugin_processor.h
resources/abstracted_pad/abstract_battery_handler.cpp
resources/abstracted_pad/abstract_battery_handler.h
resources/abstracted_pad/abstract_button_handler.cpp
resources/abstracted_pad/abstract_button_handler.h
resources/abstracted_pad/abstract_ir_sensor_handler.cpp
resources/abstracted_pad/abstract_ir_sensor_handler.h
resources/abstracted_pad/abstract_led_handler.cpp
resources/abstracted_pad/abstract_led_handler.h
resources/abstracted_pad/abstract_mcu_handler.cpp
resources/abstracted_pad/abstract_mcu_handler.h
resources/abstracted_pad/abstract_nfc_handler.cpp
resources/abstracted_pad/abstract_nfc_handler.h
resources/abstracted_pad/abstract_pad.cpp
resources/abstracted_pad/abstract_pad.h
resources/abstracted_pad/abstract_pad_holder.cpp
resources/abstracted_pad/abstract_pad_holder.h
resources/abstracted_pad/abstract_palma_handler.cpp
resources/abstracted_pad/abstract_palma_handler.h
resources/abstracted_pad/abstract_properties_handler.cpp
resources/abstracted_pad/abstract_properties_handler.h
resources/abstracted_pad/abstract_sixaxis_handler.cpp
resources/abstracted_pad/abstract_sixaxis_handler.h
resources/abstracted_pad/abstract_vibration_handler.cpp
resources/abstracted_pad/abstract_vibration_handler.h
resources/debug_pad/debug_pad.cpp
resources/debug_pad/debug_pad.h
resources/debug_pad/debug_pad_types.h
@@ -56,6 +80,8 @@ add_library(hid_core STATIC
resources/npad/npad_resource.cpp
resources/npad/npad_resource.h
resources/npad/npad_types.h
resources/npad/npad_vibration.cpp
resources/npad/npad_vibration.h
resources/palma/palma.cpp
resources/palma/palma.h
resources/six_axis/console_six_axis.cpp
@@ -78,6 +104,14 @@ add_library(hid_core STATIC
resources/touch_screen/touch_types.h
resources/unique_pad/unique_pad.cpp
resources/unique_pad/unique_pad.h
resources/vibration/gc_vibration_device.h
resources/vibration/gc_vibration_device.cpp
resources/vibration/n64_vibration_device.h
resources/vibration/n64_vibration_device.cpp
resources/vibration/vibration_base.h
resources/vibration/vibration_base.cpp
resources/vibration/vibration_device.h
resources/vibration/vibration_device.cpp
resources/applet_resource.cpp
resources/applet_resource.h
resources/controller_base.cpp

View File

@@ -27,7 +27,7 @@ EmulatedController::~EmulatedController() = default;
NpadStyleIndex EmulatedController::MapSettingsTypeToNPad(Settings::ControllerType type) {
switch (type) {
case Settings::ControllerType::ProController:
return NpadStyleIndex::ProController;
return NpadStyleIndex::Fullkey;
case Settings::ControllerType::DualJoyconDetached:
return NpadStyleIndex::JoyconDual;
case Settings::ControllerType::LeftJoycon:
@@ -49,13 +49,13 @@ NpadStyleIndex EmulatedController::MapSettingsTypeToNPad(Settings::ControllerTyp
case Settings::ControllerType::SegaGenesis:
return NpadStyleIndex::SegaGenesis;
default:
return NpadStyleIndex::ProController;
return NpadStyleIndex::Fullkey;
}
}
Settings::ControllerType EmulatedController::MapNPadToSettingsType(NpadStyleIndex type) {
switch (type) {
case NpadStyleIndex::ProController:
case NpadStyleIndex::Fullkey:
return Settings::ControllerType::ProController;
case NpadStyleIndex::JoyconDual:
return Settings::ControllerType::DualJoyconDetached;
@@ -106,7 +106,7 @@ void EmulatedController::ReloadFromSettings() {
SetNpadStyleIndex(MapSettingsTypeToNPad(player.controller_type));
original_npad_type = npad_type;
} else {
SetNpadStyleIndex(NpadStyleIndex::ProController);
SetNpadStyleIndex(NpadStyleIndex::Fullkey);
original_npad_type = npad_type;
}
@@ -1073,7 +1073,7 @@ void EmulatedController::SetColors(const Common::Input::CallbackStatus& callback
.body = GetNpadColor(controller.color_values[index].body),
.button = GetNpadColor(controller.color_values[index].buttons),
};
if (npad_type == NpadStyleIndex::ProController) {
if (npad_type == NpadStyleIndex::Fullkey) {
controller.colors_state.left = {
.body = GetNpadColor(controller.color_values[index].left_grip),
.button = GetNpadColor(controller.color_values[index].buttons),
@@ -1356,7 +1356,7 @@ bool EmulatedController::HasNfc() const {
switch (npad_type) {
case NpadStyleIndex::JoyconRight:
case NpadStyleIndex::JoyconDual:
case NpadStyleIndex::ProController:
case NpadStyleIndex::Fullkey:
case NpadStyleIndex::Handheld:
break;
default:
@@ -1548,7 +1548,7 @@ void EmulatedController::SetSupportedNpadStyleTag(NpadStyleTag supported_styles)
// Fallback Fullkey controllers to Pro controllers
if (IsControllerFullkey() && supported_style_tag.fullkey) {
LOG_WARNING(Service_HID, "Reconnecting controller type {} as Pro controller", npad_type);
SetNpadStyleIndex(NpadStyleIndex::ProController);
SetNpadStyleIndex(NpadStyleIndex::Fullkey);
Connect();
return;
}
@@ -1556,13 +1556,13 @@ void EmulatedController::SetSupportedNpadStyleTag(NpadStyleTag supported_styles)
// Fallback Dual joycon controllers to Pro controllers
if (npad_type == NpadStyleIndex::JoyconDual && supported_style_tag.fullkey) {
LOG_WARNING(Service_HID, "Reconnecting controller type {} as Pro controller", npad_type);
SetNpadStyleIndex(NpadStyleIndex::ProController);
SetNpadStyleIndex(NpadStyleIndex::Fullkey);
Connect();
return;
}
// Fallback Pro controllers to Dual joycon
if (npad_type == NpadStyleIndex::ProController && supported_style_tag.joycon_dual) {
if (npad_type == NpadStyleIndex::Fullkey && supported_style_tag.joycon_dual) {
LOG_WARNING(Service_HID, "Reconnecting controller type {} as Dual Joycons", npad_type);
SetNpadStyleIndex(NpadStyleIndex::JoyconDual);
Connect();
@@ -1577,7 +1577,7 @@ bool EmulatedController::IsControllerFullkey(bool use_temporary_value) const {
std::scoped_lock lock{mutex};
const auto type = is_configuring && use_temporary_value ? tmp_npad_type : npad_type;
switch (type) {
case NpadStyleIndex::ProController:
case NpadStyleIndex::Fullkey:
case NpadStyleIndex::GameCube:
case NpadStyleIndex::NES:
case NpadStyleIndex::SNES:
@@ -1593,7 +1593,7 @@ bool EmulatedController::IsControllerSupported(bool use_temporary_value) const {
std::scoped_lock lock{mutex};
const auto type = is_configuring && use_temporary_value ? tmp_npad_type : npad_type;
switch (type) {
case NpadStyleIndex::ProController:
case NpadStyleIndex::Fullkey:
return supported_style_tag.fullkey.As<bool>();
case NpadStyleIndex::Handheld:
return supported_style_tag.handheld.As<bool>();

View File

@@ -220,6 +220,7 @@ enum class NpadIdType : u32 {
};
enum class NpadInterfaceType : u8 {
None = 0,
Bluetooth = 1,
Rail = 2,
Usb = 3,
@@ -229,7 +230,7 @@ enum class NpadInterfaceType : u8 {
// This is nn::hid::NpadStyleIndex
enum class NpadStyleIndex : u8 {
None = 0,
ProController = 3,
Fullkey = 3,
Handheld = 4,
HandheldNES = 4,
JoyconDual = 5,

View File

@@ -42,7 +42,7 @@ constexpr Result IsSixaxisHandleValid(const Core::HID::SixAxisSensorHandle& hand
constexpr Result IsVibrationHandleValid(const Core::HID::VibrationDeviceHandle& handle) {
switch (handle.npad_type) {
case Core::HID::NpadStyleIndex::ProController:
case Core::HID::NpadStyleIndex::Fullkey:
case Core::HID::NpadStyleIndex::Handheld:
case Core::HID::NpadStyleIndex::JoyconDual:
case Core::HID::NpadStyleIndex::JoyconLeft:

View File

@@ -0,0 +1,197 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "core/core_timing.h"
#include "hid_core/hid_result.h"
#include "hid_core/hid_util.h"
#include "hid_core/resources/abstracted_pad/abstract_battery_handler.h"
#include "hid_core/resources/abstracted_pad/abstract_pad_holder.h"
#include "hid_core/resources/abstracted_pad/abstract_properties_handler.h"
#include "hid_core/resources/applet_resource.h"
#include "hid_core/resources/npad/npad_types.h"
#include "hid_core/resources/shared_memory_format.h"
namespace Service::HID {
NpadAbstractBatteryHandler::NpadAbstractBatteryHandler() {}
NpadAbstractBatteryHandler::~NpadAbstractBatteryHandler() = default;
void NpadAbstractBatteryHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) {
abstract_pad_holder = holder;
}
void NpadAbstractBatteryHandler::SetAppletResource(AppletResourceHolder* applet_resource) {
applet_resource_holder = applet_resource;
}
void NpadAbstractBatteryHandler::SetPropertiesHandler(NpadAbstractPropertiesHandler* handler) {
properties_handler = handler;
}
Result NpadAbstractBatteryHandler::IncrementRefCounter() {
if (ref_counter == std::numeric_limits<s32>::max() - 1) {
return ResultNpadHandlerOverflow;
}
ref_counter++;
return ResultSuccess;
}
Result NpadAbstractBatteryHandler::DecrementRefCounter() {
if (ref_counter == 0) {
return ResultNpadHandlerNotInitialized;
}
ref_counter--;
return ResultSuccess;
}
Result NpadAbstractBatteryHandler::UpdateBatteryState(u64 aruid) {
const auto npad_index = NpadIdTypeToIndex(properties_handler->GetNpadId());
AruidData* aruid_data = applet_resource_holder->applet_resource->GetAruidData(aruid);
if (aruid_data == nullptr) {
return ResultSuccess;
}
auto& npad_internal_state =
aruid_data->shared_memory_format->npad.npad_entry[npad_index].internal_state;
auto& system_properties = npad_internal_state.system_properties;
system_properties.is_charging_joy_dual.Assign(dual_battery.is_charging);
system_properties.is_powered_joy_dual.Assign(dual_battery.is_powered);
system_properties.is_charging_joy_left.Assign(left_battery.is_charging);
system_properties.is_powered_joy_left.Assign(left_battery.is_powered);
system_properties.is_charging_joy_right.Assign(right_battery.is_charging);
system_properties.is_powered_joy_right.Assign(right_battery.is_powered);
npad_internal_state.battery_level_dual = dual_battery.battery_level;
npad_internal_state.battery_level_left = left_battery.battery_level;
npad_internal_state.battery_level_right = right_battery.battery_level;
return ResultSuccess;
}
void NpadAbstractBatteryHandler::UpdateBatteryState() {
if (ref_counter == 0) {
return;
}
has_new_battery_data = GetNewBatteryState();
}
bool NpadAbstractBatteryHandler::GetNewBatteryState() {
bool has_changed = false;
Core::HID::NpadPowerInfo new_dual_battery_state{};
Core::HID::NpadPowerInfo new_left_battery_state{};
Core::HID::NpadPowerInfo new_right_battery_state{};
std::array<IAbstractedPad*, 5> abstract_pads{};
const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads);
for (std::size_t i = 0; i < count; i++) {
auto* abstract_pad = abstract_pads[i];
if (!abstract_pad->internal_flags.is_connected) {
continue;
}
const auto power_info = abstract_pad->power_info;
if (power_info.battery_level > Core::HID::NpadBatteryLevel::Full) {
// Abort
continue;
}
const auto style = abstract_pad->assignment_style;
if (style.is_external_assigned || style.is_handheld_assigned) {
new_dual_battery_state = power_info;
}
if (style.is_external_left_assigned || style.is_handheld_left_assigned) {
new_left_battery_state = power_info;
}
if (style.is_external_right_assigned || style.is_handheld_right_assigned) {
new_right_battery_state = power_info;
}
if (abstract_pad->internal_flags.is_battery_low_ovln_required) {
if (abstract_pad->interface_type == Core::HID::NpadInterfaceType::Rail) {
// TODO
}
abstract_pad->internal_flags.is_battery_low_ovln_required.Assign(false);
}
}
if (dual_battery.battery_level != new_dual_battery_state.battery_level ||
dual_battery.is_charging != new_dual_battery_state.is_charging ||
dual_battery.is_powered != new_dual_battery_state.is_powered) {
has_changed = true;
dual_battery = new_dual_battery_state;
}
if (left_battery.battery_level != new_left_battery_state.battery_level ||
left_battery.is_charging != new_left_battery_state.is_charging ||
left_battery.is_powered != new_left_battery_state.is_powered) {
has_changed = true;
left_battery = new_left_battery_state;
}
if (right_battery.battery_level != new_right_battery_state.battery_level ||
right_battery.is_charging != new_right_battery_state.is_charging ||
right_battery.is_powered != new_right_battery_state.is_powered) {
has_changed = true;
right_battery = new_right_battery_state;
}
return has_changed;
}
void NpadAbstractBatteryHandler::UpdateCoreBatteryState() {
if (ref_counter == 0) {
return;
}
if (!has_new_battery_data) {
return;
}
UpdateBatteryState(0);
}
void NpadAbstractBatteryHandler::InitializeBatteryState(u64 aruid) {
UpdateBatteryState(aruid);
}
bool NpadAbstractBatteryHandler::HasBattery() const {
std::array<IAbstractedPad*, 5> abstract_pads{};
const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads);
for (std::size_t i = 0; i < count; i++) {
const auto* abstract_pad = abstract_pads[i];
if (!abstract_pad->internal_flags.is_connected) {
continue;
}
return abstract_pad->disabled_feature_set.has_fullkey_battery ||
abstract_pad->disabled_feature_set.has_left_right_joy_battery;
}
return false;
}
void NpadAbstractBatteryHandler::HasLeftRightBattery(bool& has_left, bool& has_right) const {
std::array<IAbstractedPad*, 5> abstract_pads{};
const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads);
has_left = false;
has_right = false;
for (std::size_t i = 0; i < count; i++) {
const auto* abstract_pad = abstract_pads[i];
if (!abstract_pad->internal_flags.is_connected) {
continue;
}
if (!abstract_pad->disabled_feature_set.has_fullkey_battery &&
!abstract_pad->disabled_feature_set.has_left_right_joy_battery) {
continue;
}
has_left = abstract_pad->assignment_style.is_external_left_assigned ||
abstract_pad->assignment_style.is_handheld_left_assigned;
has_right = abstract_pad->assignment_style.is_external_right_assigned ||
abstract_pad->assignment_style.is_handheld_right_assigned;
}
}
} // namespace Service::HID

View File

@@ -0,0 +1,49 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "common/common_types.h"
#include "core/hle/result.h"
#include "hid_core/hid_types.h"
namespace Service::HID {
struct AppletResourceHolder;
class NpadAbstractedPadHolder;
class NpadAbstractPropertiesHandler;
/// Handles Npad request from HID interfaces
class NpadAbstractBatteryHandler final {
public:
explicit NpadAbstractBatteryHandler();
~NpadAbstractBatteryHandler();
void SetAbstractPadHolder(NpadAbstractedPadHolder* holder);
void SetAppletResource(AppletResourceHolder* applet_resource);
void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler);
Result IncrementRefCounter();
Result DecrementRefCounter();
Result UpdateBatteryState(u64 aruid);
void UpdateBatteryState();
bool GetNewBatteryState();
void UpdateCoreBatteryState();
void InitializeBatteryState(u64 aruid);
bool HasBattery() const;
void HasLeftRightBattery(bool& has_left, bool& has_right) const;
private:
AppletResourceHolder* applet_resource_holder{nullptr};
NpadAbstractedPadHolder* abstract_pad_holder{nullptr};
NpadAbstractPropertiesHandler* properties_handler{nullptr};
s32 ref_counter{};
Core::HID::NpadPowerInfo dual_battery{};
Core::HID::NpadPowerInfo left_battery{};
Core::HID::NpadPowerInfo right_battery{};
bool has_new_battery_data{};
};
} // namespace Service::HID

View File

@@ -0,0 +1,199 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "hid_core/hid_result.h"
#include "hid_core/hid_util.h"
#include "hid_core/resources/abstracted_pad/abstract_button_handler.h"
#include "hid_core/resources/abstracted_pad/abstract_pad_holder.h"
#include "hid_core/resources/abstracted_pad/abstract_properties_handler.h"
#include "hid_core/resources/applet_resource.h"
#include "hid_core/resources/npad/npad_resource.h"
#include "hid_core/resources/npad/npad_types.h"
#include "hid_core/resources/shared_memory_format.h"
namespace Service::HID {
NpadAbstractButtonHandler::NpadAbstractButtonHandler() {}
NpadAbstractButtonHandler::~NpadAbstractButtonHandler() = default;
void NpadAbstractButtonHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) {
abstract_pad_holder = holder;
}
void NpadAbstractButtonHandler::SetAppletResource(AppletResourceHolder* applet_resource) {
applet_resource_holder = applet_resource;
}
void NpadAbstractButtonHandler::SetPropertiesHandler(NpadAbstractPropertiesHandler* handler) {
properties_handler = handler;
}
Result NpadAbstractButtonHandler::IncrementRefCounter() {
if (ref_counter == std::numeric_limits<s32>::max() - 1) {
return ResultNpadHandlerOverflow;
}
ref_counter++;
return ResultSuccess;
}
Result NpadAbstractButtonHandler::DecrementRefCounter() {
if (ref_counter == 0) {
return ResultNpadHandlerNotInitialized;
}
ref_counter--;
return ResultSuccess;
}
Result NpadAbstractButtonHandler::UpdateAllButtonWithHomeProtection(u64 aruid) {
const Core::HID::NpadIdType npad_id = properties_handler->GetNpadId();
auto* data = applet_resource_holder->applet_resource->GetAruidData(aruid);
if (data == nullptr) {
return ResultSuccess;
}
auto& npad_entry = data->shared_memory_format->npad.npad_entry[NpadIdTypeToIndex(npad_id)];
UpdateButtonLifo(npad_entry, aruid);
bool is_home_button_protection_enabled{};
const auto result = applet_resource_holder->shared_npad_resource->GetHomeProtectionEnabled(
is_home_button_protection_enabled, aruid, npad_id);
if (result.IsError()) {
return ResultSuccess;
}
npad_entry.internal_state.button_properties.is_home_button_protection_enabled.Assign(
is_home_button_protection_enabled);
return ResultSuccess;
}
void NpadAbstractButtonHandler::UpdateAllButtonLifo() {
Core::HID::NpadIdType npad_id = properties_handler->GetNpadId();
for (std::size_t i = 0; i < AruidIndexMax; i++) {
auto* data = applet_resource_holder->applet_resource->GetAruidDataByIndex(i);
auto& npad_entry = data->shared_memory_format->npad.npad_entry[NpadIdTypeToIndex(npad_id)];
UpdateButtonLifo(npad_entry, data->aruid);
}
}
void NpadAbstractButtonHandler::UpdateCoreBatteryState() {
Core::HID::NpadIdType npad_id = properties_handler->GetNpadId();
for (std::size_t i = 0; i < AruidIndexMax; i++) {
auto* data = applet_resource_holder->applet_resource->GetAruidDataByIndex(i);
auto& npad_entry = data->shared_memory_format->npad.npad_entry[NpadIdTypeToIndex(npad_id)];
UpdateButtonLifo(npad_entry, data->aruid);
}
}
void NpadAbstractButtonHandler::UpdateButtonState(u64 aruid) {
Core::HID::NpadIdType npad_id = properties_handler->GetNpadId();
auto* data = applet_resource_holder->applet_resource->GetAruidData(aruid);
if (data == nullptr) {
return;
}
auto& npad_entry = data->shared_memory_format->npad.npad_entry[NpadIdTypeToIndex(npad_id)];
UpdateButtonLifo(npad_entry, aruid);
}
Result NpadAbstractButtonHandler::SetHomeProtection(bool is_enabled, u64 aruid) {
const Core::HID::NpadIdType npad_id = properties_handler->GetNpadId();
auto result = applet_resource_holder->shared_npad_resource->SetHomeProtectionEnabled(
aruid, npad_id, is_enabled);
if (result.IsError()) {
return result;
}
auto* data = applet_resource_holder->applet_resource->GetAruidData(aruid);
if (data == nullptr) {
return ResultSuccess;
}
bool is_home_protection_enabled{};
result = applet_resource_holder->shared_npad_resource->GetHomeProtectionEnabled(
is_home_protection_enabled, aruid, npad_id);
if (result.IsError()) {
return ResultSuccess;
}
auto& npad_entry = data->shared_memory_format->npad.npad_entry[NpadIdTypeToIndex(npad_id)];
npad_entry.internal_state.button_properties.is_home_button_protection_enabled.Assign(
is_home_protection_enabled);
return ResultSuccess;
}
bool NpadAbstractButtonHandler::IsButtonPressedOnConsoleMode() {
return is_button_pressed_on_console_mode;
}
void NpadAbstractButtonHandler::EnableCenterClamp() {
std::array<IAbstractedPad*, 5> abstract_pads{};
const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads);
for (std::size_t i = 0; i < count; i++) {
auto* abstract_pad = abstract_pads[i];
if (!abstract_pad->internal_flags.is_connected) {
continue;
}
abstract_pad->internal_flags.use_center_clamp.Assign(true);
}
}
void NpadAbstractButtonHandler::UpdateButtonLifo(NpadSharedMemoryEntry& shared_memory, u64 aruid) {
auto* npad_resource = applet_resource_holder->shared_npad_resource;
Core::HID::NpadStyleTag style_tag = {properties_handler->GetStyleSet(aruid)};
style_tag.system_ext.Assign(npad_resource->GetActiveData()->GetNpadSystemExtState());
UpdateNpadFullkeyLifo(style_tag, 0, aruid, shared_memory);
UpdateHandheldLifo(style_tag, 1, aruid, shared_memory);
UpdateJoyconDualLifo(style_tag, 2, aruid, shared_memory);
UpdateJoyconLeftLifo(style_tag, 3, aruid, shared_memory);
UpdateJoyconRightLifo(style_tag, 4, aruid, shared_memory);
UpdatePalmaLifo(style_tag, 5, aruid, shared_memory);
UpdateSystemExtLifo(style_tag, 6, aruid, shared_memory);
}
void NpadAbstractButtonHandler::UpdateNpadFullkeyLifo(Core::HID::NpadStyleTag style_tag,
int style_index, u64 aruid,
NpadSharedMemoryEntry& shared_memory) {
// TODO
}
void NpadAbstractButtonHandler::UpdateHandheldLifo(Core::HID::NpadStyleTag style_tag,
int style_index, u64 aruid,
NpadSharedMemoryEntry& shared_memory) {
// TODO
}
void NpadAbstractButtonHandler::UpdateJoyconDualLifo(Core::HID::NpadStyleTag style_tag,
int style_index, u64 aruid,
NpadSharedMemoryEntry& shared_memory) {
// TODO
}
void NpadAbstractButtonHandler::UpdateJoyconLeftLifo(Core::HID::NpadStyleTag style_tag,
int style_index, u64 aruid,
NpadSharedMemoryEntry& shared_memory) {
// TODO
}
void NpadAbstractButtonHandler::UpdateJoyconRightLifo(Core::HID::NpadStyleTag style_tag,
int style_index, u64 aruid,
NpadSharedMemoryEntry& shared_memory) {
// TODO
}
void NpadAbstractButtonHandler::UpdateSystemExtLifo(Core::HID::NpadStyleTag style_tag,
int style_index, u64 aruid,
NpadSharedMemoryEntry& shared_memory) {
// TODO
}
void NpadAbstractButtonHandler::UpdatePalmaLifo(Core::HID::NpadStyleTag style_tag, int style_index,
u64 aruid, NpadSharedMemoryEntry& shared_memory) {
// TODO
}
} // namespace Service::HID

View File

@@ -0,0 +1,75 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "common/common_types.h"
#include "core/hle/result.h"
#include "hid_core/hid_types.h"
namespace Service::HID {
struct NpadSharedMemoryEntry;
struct AppletResourceHolder;
class NpadAbstractedPadHolder;
class NpadAbstractPropertiesHandler;
/// Handles Npad request from HID interfaces
class NpadAbstractButtonHandler final {
public:
explicit NpadAbstractButtonHandler();
~NpadAbstractButtonHandler();
void SetAbstractPadHolder(NpadAbstractedPadHolder* holder);
void SetAppletResource(AppletResourceHolder* applet_resource);
void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler);
Result IncrementRefCounter();
Result DecrementRefCounter();
Result UpdateAllButtonWithHomeProtection(u64 aruid);
void UpdateAllButtonLifo();
void UpdateCoreBatteryState();
void UpdateButtonState(u64 aruid);
Result SetHomeProtection(bool is_enabled, u64 aruid);
bool IsButtonPressedOnConsoleMode();
void EnableCenterClamp();
void UpdateButtonLifo(NpadSharedMemoryEntry& shared_memory, u64 aruid);
void UpdateNpadFullkeyLifo(Core::HID::NpadStyleTag style_tag, int index, u64 aruid,
NpadSharedMemoryEntry& shared_memory);
void UpdateHandheldLifo(Core::HID::NpadStyleTag style_tag, int index, u64 aruid,
NpadSharedMemoryEntry& shared_memory);
void UpdateJoyconDualLifo(Core::HID::NpadStyleTag style_tag, int index, u64 aruid,
NpadSharedMemoryEntry& shared_memory);
void UpdateJoyconLeftLifo(Core::HID::NpadStyleTag style_tag, int index, u64 aruid,
NpadSharedMemoryEntry& shared_memory);
void UpdateJoyconRightLifo(Core::HID::NpadStyleTag style_tag, int index, u64 aruid,
NpadSharedMemoryEntry& shared_memory);
void UpdateSystemExtLifo(Core::HID::NpadStyleTag style_tag, int index, u64 aruid,
NpadSharedMemoryEntry& shared_memory);
void UpdatePalmaLifo(Core::HID::NpadStyleTag style_tag, int index, u64 aruid,
NpadSharedMemoryEntry& shared_memory);
private:
struct GcTrigger {
float left;
float right;
};
AppletResourceHolder* applet_resource_holder{nullptr};
NpadAbstractedPadHolder* abstract_pad_holder{nullptr};
NpadAbstractPropertiesHandler* properties_handler{nullptr};
s32 ref_counter{};
bool is_button_pressed_on_console_mode{};
u64 gc_sampling_number{};
GcTrigger gc_trigger_state{};
};
} // namespace Service::HID

View File

@@ -0,0 +1,126 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "core/hle/kernel/k_event.h"
#include "core/hle/kernel/k_readable_event.h"
#include "hid_core/hid_result.h"
#include "hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.h"
#include "hid_core/resources/abstracted_pad/abstract_pad_holder.h"
#include "hid_core/resources/abstracted_pad/abstract_properties_handler.h"
#include "hid_core/resources/npad/npad_types.h"
namespace Service::HID {
NpadAbstractIrSensorHandler::NpadAbstractIrSensorHandler() {}
NpadAbstractIrSensorHandler::~NpadAbstractIrSensorHandler() = default;
void NpadAbstractIrSensorHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) {
abstract_pad_holder = holder;
}
void NpadAbstractIrSensorHandler::SetPropertiesHandler(NpadAbstractPropertiesHandler* handler) {
properties_handler = handler;
}
Result NpadAbstractIrSensorHandler::IncrementRefCounter() {
if (ref_counter == std::numeric_limits<s32>::max() - 1) {
return ResultNpadHandlerOverflow;
}
ref_counter++;
return ResultSuccess;
}
Result NpadAbstractIrSensorHandler::DecrementRefCounter() {
if (ref_counter == 0) {
return ResultNpadHandlerNotInitialized;
}
ref_counter--;
return ResultSuccess;
}
void NpadAbstractIrSensorHandler::UpdateIrSensorState() {
const auto previous_state = sensor_state;
std::array<IAbstractedPad*, 5> abstract_pads{};
const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads);
if (count == 0) {
sensor_state = NpadIrSensorState::Disabled;
if (sensor_state == previous_state) {
return;
}
ir_sensor_event->Signal();
return;
}
bool is_found{};
for (std::size_t i = 0; i < count; i++) {
auto* abstract_pad = abstract_pads[i];
if (!abstract_pad->internal_flags.is_connected) {
continue;
}
if (!abstract_pad->disabled_feature_set.has_bluetooth_address) {
continue;
}
is_found = true;
xcd_handle = abstract_pad->xcd_handle;
}
if (is_found) {
if (sensor_state == NpadIrSensorState::Active) {
return;
}
sensor_state = NpadIrSensorState::Available;
if (sensor_state == previous_state) {
return;
}
ir_sensor_event->Signal();
return;
}
sensor_state = NpadIrSensorState::Unavailable;
if (sensor_state == previous_state) {
return;
}
ir_sensor_event->Signal();
return;
}
Result NpadAbstractIrSensorHandler::ActivateIrSensor(bool is_enabled) {
if (sensor_state == NpadIrSensorState::Unavailable) {
return ResultIrSensorIsNotReady;
}
if (is_enabled && sensor_state == NpadIrSensorState::Available) {
sensor_state = NpadIrSensorState::Active;
} else {
if (is_enabled) {
return ResultSuccess;
}
if (sensor_state != NpadIrSensorState::Active) {
return ResultSuccess;
}
sensor_state = NpadIrSensorState::Available;
}
ir_sensor_event->Signal();
return ResultSuccess;
}
Result NpadAbstractIrSensorHandler::GetIrSensorEventHandle(Kernel::KReadableEvent** out_event) {
*out_event = &ir_sensor_event->GetReadableEvent();
return ResultSuccess;
}
Result NpadAbstractIrSensorHandler::GetXcdHandleForNpadWithIrSensor(u64& handle) const {
if (sensor_state < NpadIrSensorState::Available) {
return ResultIrSensorIsNotReady;
}
handle = xcd_handle;
return ResultSuccess;
}
NpadIrSensorState NpadAbstractIrSensorHandler::GetSensorState() const {
return sensor_state;
}
} // namespace Service::HID

View File

@@ -0,0 +1,56 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "common/common_types.h"
#include "core/hle/result.h"
#include "hid_core/hid_types.h"
namespace Kernel {
class KEvent;
class KReadableEvent;
} // namespace Kernel
enum class NpadIrSensorState : u32 {
Disabled,
Unavailable,
Available,
Active,
};
namespace Service::HID {
class NpadAbstractedPadHolder;
class NpadAbstractPropertiesHandler;
/// Handles Npad request from HID interfaces
class NpadAbstractIrSensorHandler final {
public:
explicit NpadAbstractIrSensorHandler();
~NpadAbstractIrSensorHandler();
void SetAbstractPadHolder(NpadAbstractedPadHolder* holder);
void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler);
Result IncrementRefCounter();
Result DecrementRefCounter();
void UpdateIrSensorState();
Result ActivateIrSensor(bool param_2);
Result GetIrSensorEventHandle(Kernel::KReadableEvent** out_event);
Result GetXcdHandleForNpadWithIrSensor(u64& handle) const;
NpadIrSensorState GetSensorState() const;
private:
NpadAbstractedPadHolder* abstract_pad_holder{nullptr};
NpadAbstractPropertiesHandler* properties_handler{nullptr};
s32 ref_counter{};
Kernel::KEvent* ir_sensor_event{nullptr};
u64 xcd_handle{};
NpadIrSensorState sensor_state{};
};
} // namespace Service::HID

View File

@@ -0,0 +1,123 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "core/core_timing.h"
#include "hid_core/hid_result.h"
#include "hid_core/hid_util.h"
#include "hid_core/resources/abstracted_pad/abstract_led_handler.h"
#include "hid_core/resources/abstracted_pad/abstract_pad_holder.h"
#include "hid_core/resources/abstracted_pad/abstract_properties_handler.h"
#include "hid_core/resources/applet_resource.h"
#include "hid_core/resources/npad/npad_types.h"
namespace Service::HID {
NpadAbstractLedHandler::NpadAbstractLedHandler() {}
NpadAbstractLedHandler::~NpadAbstractLedHandler() = default;
void NpadAbstractLedHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) {
abstract_pad_holder = holder;
}
void NpadAbstractLedHandler::SetAppletResource(AppletResourceHolder* applet_resource) {
applet_resource_holder = applet_resource;
}
void NpadAbstractLedHandler::SetPropertiesHandler(NpadAbstractPropertiesHandler* handler) {
properties_handler = handler;
}
Result NpadAbstractLedHandler::IncrementRefCounter() {
if (ref_counter == std::numeric_limits<s32>::max() - 1) {
return ResultNpadHandlerOverflow;
}
ref_counter++;
return ResultSuccess;
}
Result NpadAbstractLedHandler::DecrementRefCounter() {
if (ref_counter == 0) {
return ResultNpadHandlerNotInitialized;
}
ref_counter--;
return ResultSuccess;
}
void NpadAbstractLedHandler::SetNpadLedHandlerLedPattern() {
const auto npad_id = properties_handler->GetNpadId();
switch (npad_id) {
case Core::HID::NpadIdType::Player1:
left_pattern = Core::HID::LedPattern{1, 0, 0, 0};
break;
case Core::HID::NpadIdType::Player2:
left_pattern = Core::HID::LedPattern{1, 1, 0, 0};
break;
case Core::HID::NpadIdType::Player3:
left_pattern = Core::HID::LedPattern{1, 1, 1, 0};
break;
case Core::HID::NpadIdType::Player4:
left_pattern = Core::HID::LedPattern{1, 1, 1, 1};
break;
case Core::HID::NpadIdType::Player5:
left_pattern = Core::HID::LedPattern{1, 0, 0, 1};
break;
case Core::HID::NpadIdType::Player6:
left_pattern = Core::HID::LedPattern{1, 0, 1, 0};
break;
case Core::HID::NpadIdType::Player7:
left_pattern = Core::HID::LedPattern{1, 0, 1, 1};
break;
case Core::HID::NpadIdType::Player8:
left_pattern = Core::HID::LedPattern{0, 1, 1, 0};
break;
case Core::HID::NpadIdType::Other:
case Core::HID::NpadIdType::Handheld:
left_pattern = Core::HID::LedPattern{0, 0, 0, 0};
break;
default:
ASSERT_MSG(false, "Invalid npad id type");
break;
}
switch (npad_id) {
case Core::HID::NpadIdType::Player1:
right_pattern = Core::HID::LedPattern{0, 0, 0, 1};
break;
case Core::HID::NpadIdType::Player2:
right_pattern = Core::HID::LedPattern{0, 1, 1, 1};
break;
case Core::HID::NpadIdType::Player3:
right_pattern = Core::HID::LedPattern{0, 1, 1, 1};
break;
case Core::HID::NpadIdType::Player4:
right_pattern = Core::HID::LedPattern{1, 1, 1, 1};
break;
case Core::HID::NpadIdType::Player5:
right_pattern = Core::HID::LedPattern{1, 0, 0, 1};
break;
case Core::HID::NpadIdType::Player6:
right_pattern = Core::HID::LedPattern{0, 1, 0, 1};
break;
case Core::HID::NpadIdType::Player7:
right_pattern = Core::HID::LedPattern{1, 1, 0, 1};
break;
case Core::HID::NpadIdType::Player8:
right_pattern = Core::HID::LedPattern{0, 1, 1, 0};
break;
case Core::HID::NpadIdType::Other:
case Core::HID::NpadIdType::Handheld:
right_pattern = Core::HID::LedPattern{0, 0, 0, 0};
break;
default:
ASSERT_MSG(false, "Invalid npad id type");
break;
}
}
void NpadAbstractLedHandler::SetLedBlinkingDevice(Core::HID::LedPattern pattern) {
led_blinking = pattern;
}
} // namespace Service::HID

View File

@@ -0,0 +1,43 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "common/common_types.h"
#include "core/hle/result.h"
#include "hid_core/hid_types.h"
namespace Service::HID {
struct AppletResourceHolder;
class NpadAbstractedPadHolder;
class NpadAbstractPropertiesHandler;
/// Handles Npad request from HID interfaces
class NpadAbstractLedHandler final {
public:
explicit NpadAbstractLedHandler();
~NpadAbstractLedHandler();
void SetAbstractPadHolder(NpadAbstractedPadHolder* holder);
void SetAppletResource(AppletResourceHolder* applet_resource);
void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler);
Result IncrementRefCounter();
Result DecrementRefCounter();
void SetNpadLedHandlerLedPattern();
void SetLedBlinkingDevice(Core::HID::LedPattern pattern);
private:
AppletResourceHolder* applet_resource_holder{nullptr};
NpadAbstractedPadHolder* abstract_pad_holder{nullptr};
NpadAbstractPropertiesHandler* properties_handler{nullptr};
s32 ref_counter{};
Core::HID::LedPattern led_blinking{0, 0, 0, 0};
Core::HID::LedPattern left_pattern{0, 0, 0, 0};
Core::HID::LedPattern right_pattern{0, 0, 0, 0};
u64 led_interval{};
};
} // namespace Service::HID

View File

@@ -0,0 +1,108 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "hid_core/hid_result.h"
#include "hid_core/resources/abstracted_pad/abstract_mcu_handler.h"
#include "hid_core/resources/abstracted_pad/abstract_pad_holder.h"
#include "hid_core/resources/abstracted_pad/abstract_properties_handler.h"
#include "hid_core/resources/npad/npad_types.h"
namespace Service::HID {
NpadAbstractMcuHandler::NpadAbstractMcuHandler() {}
NpadAbstractMcuHandler::~NpadAbstractMcuHandler() = default;
void NpadAbstractMcuHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) {
abstract_pad_holder = holder;
}
void NpadAbstractMcuHandler::SetPropertiesHandler(NpadAbstractPropertiesHandler* handler) {
properties_handler = handler;
}
Result NpadAbstractMcuHandler::IncrementRefCounter() {
if (ref_counter == std::numeric_limits<s32>::max() - 1) {
return ResultNpadHandlerOverflow;
}
ref_counter++;
return ResultSuccess;
}
Result NpadAbstractMcuHandler::DecrementRefCounter() {
if (ref_counter == 0) {
return ResultNpadHandlerNotInitialized;
}
ref_counter--;
return ResultSuccess;
}
void NpadAbstractMcuHandler::UpdateMcuState() {
std::array<IAbstractedPad*, 5> abstract_pads{};
const std::size_t count = properties_handler->GetAbstractedPads(abstract_pads);
if (count == 0) {
mcu_holder = {};
return;
}
for (std::size_t i = 0; i < count; i++) {
auto* abstract_pad = abstract_pads[i];
if (!abstract_pad->internal_flags.is_connected) {
continue;
}
if (!abstract_pad->disabled_feature_set.has_left_joy_rail_bus) {
if (!abstract_pad->disabled_feature_set.has_left_joy_six_axis_sensor &&
!abstract_pad->disabled_feature_set.has_right_joy_six_axis_sensor) {
continue;
}
if (mcu_holder[1].state != NpadMcuState::Active) {
mcu_holder[1].state = NpadMcuState::Available;
}
mcu_holder[1].abstracted_pad = abstract_pad;
continue;
}
if (mcu_holder[0].state != NpadMcuState::Active) {
mcu_holder[0].state = NpadMcuState::Available;
}
mcu_holder[0].abstracted_pad = abstract_pad;
}
}
Result NpadAbstractMcuHandler::GetAbstractedPad(IAbstractedPad** data, u32 mcu_index) {
if (mcu_holder[mcu_index].state == NpadMcuState::None ||
mcu_holder[mcu_index].abstracted_pad == nullptr) {
return ResultMcuIsNotReady;
}
*data = mcu_holder[mcu_index].abstracted_pad;
return ResultSuccess;
}
NpadMcuState NpadAbstractMcuHandler::GetMcuState(u32 mcu_index) {
return mcu_holder[mcu_index].state;
}
Result NpadAbstractMcuHandler::SetMcuState(bool is_enabled, u32 mcu_index) {
NpadMcuState& state = mcu_holder[mcu_index].state;
if (state == NpadMcuState::None) {
return ResultMcuIsNotReady;
}
if ((is_enabled) && (state == NpadMcuState::Available)) {
state = NpadMcuState::Active;
return ResultSuccess;
}
if (is_enabled) {
return ResultSuccess;
}
if (state != NpadMcuState::Active) {
return ResultSuccess;
}
state = NpadMcuState::Available;
return ResultSuccess;
}
} // namespace Service::HID

View File

@@ -0,0 +1,52 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "common/common_types.h"
#include "core/hle/result.h"
#include "hid_core/hid_types.h"
namespace Service::HID {
struct IAbstractedPad;
class NpadAbstractedPadHolder;
class NpadAbstractPropertiesHandler;
enum class NpadMcuState : u32 {
None,
Available,
Active,
};
struct NpadMcuHolder {
NpadMcuState state;
INSERT_PADDING_BYTES(0x4);
IAbstractedPad* abstracted_pad;
};
static_assert(sizeof(NpadMcuHolder) == 0x10, "NpadMcuHolder is an invalid size");
/// Handles Npad request from HID interfaces
class NpadAbstractMcuHandler final {
public:
explicit NpadAbstractMcuHandler();
~NpadAbstractMcuHandler();
void SetAbstractPadHolder(NpadAbstractedPadHolder* holder);
void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler);
Result IncrementRefCounter();
Result DecrementRefCounter();
void UpdateMcuState();
Result GetAbstractedPad(IAbstractedPad** data, u32 mcu_index);
NpadMcuState GetMcuState(u32 mcu_index);
Result SetMcuState(bool is_enabled, u32 mcu_index);
private:
NpadAbstractedPadHolder* abstract_pad_holder{nullptr};
NpadAbstractPropertiesHandler* properties_handler{nullptr};
s32 ref_counter{};
std::array<NpadMcuHolder, 2> mcu_holder{};
};
} // namespace Service::HID

View File

@@ -0,0 +1,140 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "core/hle/kernel/k_event.h"
#include "core/hle/kernel/k_readable_event.h"
#include "hid_core/hid_result.h"
#include "hid_core/resources/abstracted_pad/abstract_nfc_handler.h"
#include "hid_core/resources/abstracted_pad/abstract_pad_holder.h"
#include "hid_core/resources/abstracted_pad/abstract_properties_handler.h"
#include "hid_core/resources/npad/npad_types.h"
namespace Service::HID {
NpadAbstractNfcHandler::NpadAbstractNfcHandler() {}
NpadAbstractNfcHandler::~NpadAbstractNfcHandler() = default;
void NpadAbstractNfcHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) {
abstract_pad_holder = holder;
}
void NpadAbstractNfcHandler::SetPropertiesHandler(NpadAbstractPropertiesHandler* handler) {
properties_handler = handler;
}
Result NpadAbstractNfcHandler::IncrementRefCounter() {
if (ref_counter == std::numeric_limits<s32>::max() - 1) {
return ResultNpadHandlerOverflow;
}
ref_counter++;
return ResultSuccess;
}
Result NpadAbstractNfcHandler::DecrementRefCounter() {
if (ref_counter == 0) {
return ResultNpadHandlerNotInitialized;
}
ref_counter--;
return ResultSuccess;
}
void NpadAbstractNfcHandler::UpdateNfcState() {
std::array<IAbstractedPad*, 5> abstract_pads{};
const std::size_t count = properties_handler->GetAbstractedPads(abstract_pads);
if (count == 0) {
if (sensor_state == NpadNfcState::Active) {
nfc_activate_event->Signal();
}
if (sensor_state == NpadNfcState::Unavailable) {
return;
}
sensor_state = NpadNfcState::Unavailable;
input_event->Signal();
return;
}
bool is_found{};
for (std::size_t i = 0; i < count; i++) {
auto* abstract_pad = abstract_pads[i];
if (!abstract_pad->internal_flags.is_connected) {
continue;
}
if (!abstract_pad->disabled_feature_set.has_nfc) {
continue;
}
is_found = true;
xcd_handle = 0;
}
if (is_found) {
if (sensor_state == NpadNfcState::Active) {
return;
}
if (sensor_state == NpadNfcState::Available) {
return;
}
sensor_state = NpadNfcState::Available;
input_event->Signal();
return;
}
if (sensor_state == NpadNfcState::Active) {
nfc_activate_event->Signal();
}
if (sensor_state == NpadNfcState::Unavailable) {
return;
}
sensor_state = NpadNfcState::Unavailable;
input_event->Signal();
return;
}
bool NpadAbstractNfcHandler::HasNfcSensor() {
return sensor_state != NpadNfcState::Unavailable;
}
bool NpadAbstractNfcHandler::IsNfcActivated() {
return sensor_state == NpadNfcState::Active;
}
Result NpadAbstractNfcHandler::GetAcquireNfcActivateEventHandle(
Kernel::KReadableEvent** out_event) {
*out_event = &nfc_activate_event->GetReadableEvent();
return ResultSuccess;
}
void NpadAbstractNfcHandler::SetInputEvent(Kernel::KEvent* event) {
input_event = event;
}
Result NpadAbstractNfcHandler::ActivateNfc(bool is_enabled) {
if (sensor_state == NpadNfcState::Active) {
return ResultNfcIsNotReady;
}
NpadNfcState new_state = NpadNfcState::Available;
if (is_enabled) {
new_state = NpadNfcState::Active;
}
if (sensor_state != new_state) {
sensor_state = new_state;
nfc_activate_event->Signal();
}
return ResultSuccess;
}
Result NpadAbstractNfcHandler::GetXcdHandleWithNfc(u64& out_xcd_handle) const {
if (sensor_state == NpadNfcState::Unavailable) {
return ResultNfcIsNotReady;
}
if (xcd_handle == 0) {
return ResultNfcXcdHandleIsNotInitialized;
}
out_xcd_handle = xcd_handle;
return ResultSuccess;
}
} // namespace Service::HID

View File

@@ -0,0 +1,57 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "common/common_types.h"
#include "core/hle/result.h"
#include "hid_core/hid_types.h"
namespace Kernel {
class KReadableEvent;
}
enum class NpadNfcState : u32 {
Unavailable,
Available,
Active,
};
namespace Service::HID {
class NpadAbstractedPadHolder;
class NpadAbstractPropertiesHandler;
/// Handles Npad request from HID interfaces
class NpadAbstractNfcHandler final {
public:
explicit NpadAbstractNfcHandler();
~NpadAbstractNfcHandler();
void SetAbstractPadHolder(NpadAbstractedPadHolder* holder);
void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler);
Result IncrementRefCounter();
Result DecrementRefCounter();
void UpdateNfcState();
bool HasNfcSensor();
bool IsNfcActivated();
Result GetAcquireNfcActivateEventHandle(Kernel::KReadableEvent** out_event);
void SetInputEvent(Kernel::KEvent* event);
Result ActivateNfc(bool is_enabled);
Result GetXcdHandleWithNfc(u64& out_xcd_handle) const;
private:
NpadAbstractedPadHolder* abstract_pad_holder{nullptr};
NpadAbstractPropertiesHandler* properties_handler{nullptr};
s32 ref_counter{};
Kernel::KEvent* nfc_activate_event{nullptr};
Kernel::KEvent* input_event{nullptr};
u64 xcd_handle{};
NpadNfcState sensor_state{NpadNfcState::Unavailable};
};
} // namespace Service::HID

View File

@@ -0,0 +1,294 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "hid_core/hid_result.h"
#include "hid_core/resources/abstracted_pad/abstract_pad.h"
#include "hid_core/resources/applet_resource.h"
#include "hid_core/resources/npad/npad_types.h"
namespace Service::HID {
AbstractPad::AbstractPad() {}
AbstractPad::~AbstractPad() = default;
void AbstractPad::SetExternals(AppletResourceHolder* applet_resource,
CaptureButtonResource* capture_button_resource,
HomeButtonResource* home_button_resource,
SixAxisResource* sixaxis_resource, PalmaResource* palma_resource,
VibrationHandler* vibration) {
applet_resource_holder = applet_resource;
properties_handler.SetAppletResource(applet_resource_holder);
properties_handler.SetAbstractPadHolder(&abstract_pad_holder);
led_handler.SetAppletResource(applet_resource_holder);
led_handler.SetAbstractPadHolder(&abstract_pad_holder);
led_handler.SetPropertiesHandler(&properties_handler);
ir_sensor_handler.SetAbstractPadHolder(&abstract_pad_holder);
ir_sensor_handler.SetPropertiesHandler(&properties_handler);
nfc_handler.SetAbstractPadHolder(&abstract_pad_holder);
nfc_handler.SetPropertiesHandler(&properties_handler);
mcu_handler.SetAbstractPadHolder(&abstract_pad_holder);
mcu_handler.SetPropertiesHandler(&properties_handler);
std::array<NpadVibrationDevice*, 2> vibration_devices{&vibration_left, &vibration_right};
vibration_handler.SetAppletResource(applet_resource_holder);
vibration_handler.SetAbstractPadHolder(&abstract_pad_holder);
vibration_handler.SetPropertiesHandler(&properties_handler);
vibration_handler.SetN64Vibration(&vibration_n64);
vibration_handler.SetVibration(vibration_devices);
vibration_handler.SetGcVibration(&vibration_gc);
sixaxis_handler.SetAppletResource(applet_resource_holder);
sixaxis_handler.SetAbstractPadHolder(&abstract_pad_holder);
sixaxis_handler.SetPropertiesHandler(&properties_handler);
sixaxis_handler.SetSixaxisResource(sixaxis_resource);
button_handler.SetAppletResource(applet_resource_holder);
button_handler.SetAbstractPadHolder(&abstract_pad_holder);
button_handler.SetPropertiesHandler(&properties_handler);
battery_handler.SetAppletResource(applet_resource_holder);
battery_handler.SetAbstractPadHolder(&abstract_pad_holder);
battery_handler.SetPropertiesHandler(&properties_handler);
palma_handler.SetAbstractPadHolder(&abstract_pad_holder);
palma_handler.SetPropertiesHandler(&properties_handler);
palma_handler.SetPalmaResource(palma_resource);
}
void AbstractPad::SetNpadId(Core::HID::NpadIdType npad_id) {
properties_handler.SetNpadId(npad_id);
}
Result AbstractPad::Activate() {
if (ref_counter == std::numeric_limits<s32>::max() - 1) {
return ResultNpadHandlerOverflow;
}
if (ref_counter != 0) {
ref_counter++;
return ResultSuccess;
}
std::size_t stage = 0;
Result result = ResultSuccess;
if (result.IsSuccess()) {
stage++;
result = properties_handler.IncrementRefCounter();
}
if (result.IsSuccess()) {
stage++;
result = led_handler.IncrementRefCounter();
}
if (result.IsSuccess()) {
stage++;
result = ir_sensor_handler.IncrementRefCounter();
}
if (result.IsSuccess()) {
stage++;
result = mcu_handler.IncrementRefCounter();
}
if (result.IsSuccess()) {
stage++;
result = nfc_handler.IncrementRefCounter();
}
if (result.IsSuccess()) {
stage++;
result = vibration_handler.IncrementRefCounter();
}
if (result.IsSuccess()) {
stage++;
result = sixaxis_handler.IncrementRefCounter();
}
if (result.IsSuccess()) {
stage++;
result = button_handler.IncrementRefCounter();
}
if (result.IsSuccess()) {
stage++;
result = battery_handler.IncrementRefCounter();
}
if (result.IsSuccess()) {
stage++;
result = palma_handler.IncrementRefCounter();
}
if (result.IsSuccess()) {
ref_counter++;
return result;
}
if (stage > 9) {
battery_handler.DecrementRefCounter();
}
if (stage > 8) {
button_handler.DecrementRefCounter();
}
if (stage > 7) {
sixaxis_handler.DecrementRefCounter();
}
if (stage > 6) {
vibration_handler.DecrementRefCounter();
}
if (stage > 5) {
nfc_handler.DecrementRefCounter();
}
if (stage > 4) {
mcu_handler.DecrementRefCounter();
}
if (stage > 3) {
ir_sensor_handler.DecrementRefCounter();
}
if (stage > 2) {
led_handler.DecrementRefCounter();
}
if (stage > 1) {
properties_handler.DecrementRefCounter();
}
return result;
}
Result AbstractPad::Deactivate() {
if (ref_counter == 0) {
return ResultNpadResourceNotInitialized;
}
ref_counter--;
battery_handler.DecrementRefCounter();
button_handler.DecrementRefCounter();
sixaxis_handler.DecrementRefCounter();
vibration_handler.DecrementRefCounter();
nfc_handler.DecrementRefCounter();
ir_sensor_handler.DecrementRefCounter();
mcu_handler.DecrementRefCounter();
led_handler.DecrementRefCounter();
properties_handler.DecrementRefCounter();
palma_handler.DecrementRefCounter();
return ResultSuccess;
}
Result AbstractPad::ActivateNpad(u64 aruid) {
Result result = ResultSuccess;
if (result.IsSuccess()) {
result = properties_handler.ActivateNpadUnknown0x88(aruid);
}
if (result.IsSuccess()) {
result = sixaxis_handler.UpdateSixAxisState2(aruid);
}
if (result.IsSuccess()) {
result = battery_handler.UpdateBatteryState(aruid);
}
return result;
}
NpadAbstractedPadHolder* AbstractPad::GetAbstractedPadHolder() {
return &abstract_pad_holder;
}
NpadAbstractPropertiesHandler* AbstractPad::GetAbstractPropertiesHandler() {
return &properties_handler;
}
NpadAbstractLedHandler* AbstractPad::GetAbstractLedHandler() {
return &led_handler;
}
NpadAbstractIrSensorHandler* AbstractPad::GetAbstractIrSensorHandler() {
return &ir_sensor_handler;
}
NpadAbstractMcuHandler* AbstractPad::GetAbstractMcuHandler() {
return &mcu_handler;
}
NpadAbstractNfcHandler* AbstractPad::GetAbstractNfcHandler() {
return &nfc_handler;
}
NpadAbstractVibrationHandler* AbstractPad::GetAbstractVibrationHandler() {
return &vibration_handler;
}
NpadAbstractSixAxisHandler* AbstractPad::GetAbstractSixAxisHandler() {
return &sixaxis_handler;
}
NpadAbstractButtonHandler* AbstractPad::GetAbstractButtonHandler() {
return &button_handler;
}
NpadAbstractBatteryHandler* AbstractPad::GetAbstractBatteryHandler() {
return &battery_handler;
}
NpadN64VibrationDevice* AbstractPad::GetN64VibrationDevice() {
return &vibration_n64;
}
NpadVibrationDevice* AbstractPad::GetVibrationDevice(Core::HID::DeviceIndex device_index) {
if (device_index == Core::HID::DeviceIndex::Right) {
return &vibration_right;
}
return &vibration_left;
}
void AbstractPad::GetLeftRightVibrationDevice(std::vector<NpadVibrationDevice*> list) {
list.emplace_back(&vibration_left);
list.emplace_back(&vibration_right);
}
NpadGcVibrationDevice* AbstractPad::GetGCVibrationDevice() {
return &vibration_gc;
}
Core::HID::NpadIdType AbstractPad::GetLastActiveNpad() {
return properties_handler.GetNpadId();
}
void AbstractPad::UpdateInterfaceType() {
if (interface_type != properties_handler.GetInterfaceType()) {
Update();
}
battery_handler.UpdateBatteryState();
}
void AbstractPad::Update() {
properties_handler.UpdateDeviceType();
led_handler.SetNpadLedHandlerLedPattern();
vibration_handler.UpdateVibrationState();
sixaxis_handler.UpdateSixAxisState();
nfc_handler.UpdateNfcState();
ir_sensor_handler.UpdateIrSensorState();
mcu_handler.UpdateMcuState();
palma_handler.UpdatePalmaState();
battery_handler.UpdateBatteryState();
button_handler.EnableCenterClamp();
interface_type = properties_handler.GetInterfaceType();
std::scoped_lock lock{*applet_resource_holder->shared_mutex};
properties_handler.UpdateAllDeviceProperties();
battery_handler.UpdateCoreBatteryState();
button_handler.UpdateCoreBatteryState();
}
void AbstractPad::UpdatePadState() {
button_handler.UpdateAllButtonLifo();
sixaxis_handler.UpdateSixAxisState();
battery_handler.UpdateCoreBatteryState();
}
void AbstractPad::EnableAppletToGetInput(u64 aruid) {
button_handler.UpdateButtonState(aruid);
sixaxis_handler.UpdateSixAxisState(aruid);
battery_handler.UpdateBatteryState(aruid);
}
} // namespace Service::HID

View File

@@ -0,0 +1,123 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include <array>
#include <mutex>
#include "common/common_types.h"
#include "core/hle/result.h"
#include "hid_core/hid_types.h"
#include "hid_core/resources/applet_resource.h"
#include "hid_core/resources/npad/npad_types.h"
#include "hid_core/resources/abstracted_pad/abstract_battery_handler.h"
#include "hid_core/resources/abstracted_pad/abstract_button_handler.h"
#include "hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.h"
#include "hid_core/resources/abstracted_pad/abstract_led_handler.h"
#include "hid_core/resources/abstracted_pad/abstract_mcu_handler.h"
#include "hid_core/resources/abstracted_pad/abstract_nfc_handler.h"
#include "hid_core/resources/abstracted_pad/abstract_pad_holder.h"
#include "hid_core/resources/abstracted_pad/abstract_palma_handler.h"
#include "hid_core/resources/abstracted_pad/abstract_properties_handler.h"
#include "hid_core/resources/abstracted_pad/abstract_sixaxis_handler.h"
#include "hid_core/resources/abstracted_pad/abstract_vibration_handler.h"
#include "hid_core/resources/vibration/gc_vibration_device.h"
#include "hid_core/resources/vibration/n64_vibration_device.h"
#include "hid_core/resources/vibration/vibration_device.h"
namespace Service::HID {
class AppletResource;
class SixAxisResource;
class PalmaResource;
class NPadResource;
class AbstractPad;
class NpadLastActiveHandler;
class NpadIrNfcHandler;
class UniquePads;
class NpadPalmaHandler;
class FirmwareResource;
class NpadVibration;
class NpadHighestBattery;
class NpadGcVibration;
class CaptureButtonResource;
class HomeButtonResource;
class VibrationHandler;
struct HandheldConfig;
/// Handles Npad request from HID interfaces
class AbstractPad final {
public:
explicit AbstractPad();
~AbstractPad();
void SetExternals(AppletResourceHolder* applet_resource,
CaptureButtonResource* capture_button_resource,
HomeButtonResource* home_button_resource, SixAxisResource* sixaxis_resource,
PalmaResource* palma_resource, VibrationHandler* vibration);
void SetNpadId(Core::HID::NpadIdType npad_id);
Result Activate();
Result Deactivate();
Result ActivateNpad(u64 aruid);
NpadAbstractedPadHolder* GetAbstractedPadHolder();
NpadAbstractPropertiesHandler* GetAbstractPropertiesHandler();
NpadAbstractLedHandler* GetAbstractLedHandler();
NpadAbstractIrSensorHandler* GetAbstractIrSensorHandler();
NpadAbstractMcuHandler* GetAbstractMcuHandler();
NpadAbstractNfcHandler* GetAbstractNfcHandler();
NpadAbstractVibrationHandler* GetAbstractVibrationHandler();
NpadAbstractSixAxisHandler* GetAbstractSixAxisHandler();
NpadAbstractButtonHandler* GetAbstractButtonHandler();
NpadAbstractBatteryHandler* GetAbstractBatteryHandler();
NpadN64VibrationDevice* GetN64VibrationDevice();
NpadVibrationDevice* GetVibrationDevice(Core::HID::DeviceIndex device_index);
void GetLeftRightVibrationDevice(std::vector<NpadVibrationDevice*> list);
NpadGcVibrationDevice* GetGCVibrationDevice();
Core::HID::NpadIdType GetLastActiveNpad();
void UpdateInterfaceType();
void Update();
void UpdatePadState();
void EnableAppletToGetInput(u64 aruid);
private:
AppletResourceHolder* applet_resource_holder{nullptr};
NpadAbstractedPadHolder abstract_pad_holder{};
NpadAbstractPropertiesHandler properties_handler{};
NpadAbstractLedHandler led_handler{};
NpadAbstractIrSensorHandler ir_sensor_handler{};
NpadAbstractNfcHandler nfc_handler{};
NpadAbstractMcuHandler mcu_handler{};
NpadAbstractVibrationHandler vibration_handler{};
NpadAbstractSixAxisHandler sixaxis_handler{};
NpadAbstractButtonHandler button_handler{};
NpadAbstractBatteryHandler battery_handler{};
NpadAbstractPalmaHandler palma_handler{};
NpadN64VibrationDevice vibration_n64{};
NpadVibrationDevice vibration_left{};
NpadVibrationDevice vibration_right{};
NpadGcVibrationDevice vibration_gc{};
// SixAxisConfigHolder fullkey_config;
// SixAxisConfigHolder handheld_config;
// SixAxisConfigHolder dual_left_config;
// SixAxisConfigHolder dual_right_config;
// SixAxisConfigHolder left_config;
// SixAxisConfigHolder right_config;
s32 ref_counter{};
Core::HID::NpadInterfaceType interface_type{Core::HID::NpadInterfaceType::None};
};
using FullAbstractPad = std::array<AbstractPad, MaxSupportedNpadIdTypes>;
} // namespace Service::HID

View File

@@ -0,0 +1,99 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "hid_core/hid_result.h"
#include "hid_core/resources/abstracted_pad/abstract_pad_holder.h"
#include "hid_core/resources/npad/npad_types.h"
namespace Service::HID {
Result NpadAbstractedPadHolder::RegisterAbstractPad(IAbstractedPad* abstracted_pad) {
if (list_size >= assignment_list.size()) {
return ResultNpadIsNotProController;
}
for (std::size_t i = 0; i < list_size; i++) {
if (assignment_list[i].device_type == abstracted_pad->device_type) {
return ResultNpadIsNotProController;
}
}
assignment_list[list_size] = {
.abstracted_pad = abstracted_pad,
.device_type = abstracted_pad->device_type,
.interface_type = abstracted_pad->interface_type,
.controller_id = abstracted_pad->controller_id,
};
list_size++;
return ResultSuccess;
}
void NpadAbstractedPadHolder::RemoveAbstractPadByControllerId(u64 controller_id) {
if (list_size == 0) {
return;
}
if (controller_id == 0) {
return;
}
for (std::size_t i = 0; i < list_size; i++) {
if (assignment_list[i].controller_id != controller_id) {
continue;
}
for (std::size_t e = i + 1; e < list_size; e++) {
assignment_list[e - 1] = assignment_list[e];
}
list_size--;
return;
}
}
void NpadAbstractedPadHolder::DetachAbstractedPad() {
while (list_size > 0) {
for (std::size_t i = 1; i < list_size; i++) {
assignment_list[i - 1] = assignment_list[i];
}
list_size--;
}
}
u64 NpadAbstractedPadHolder::RemoveAbstractPadByAssignmentStyle(
Service::HID::AssignmentStyle assignment_style) {
for (std::size_t i = 0; i < list_size; i++) {
if ((assignment_style.raw & assignment_list[i].abstracted_pad->assignment_style.raw) == 0) {
continue;
}
for (std::size_t e = i + 1; e < list_size; e++) {
assignment_list[e - 1] = assignment_list[e];
}
list_size--;
return list_size;
}
return list_size;
}
u32 NpadAbstractedPadHolder::GetAbstractedPads(std::span<IAbstractedPad*> list) const {
u32 num_elements = std::min(static_cast<u32>(list.size()), list_size);
for (std::size_t i = 0; i < num_elements; i++) {
list[i] = assignment_list[i].abstracted_pad;
}
return num_elements;
}
void NpadAbstractedPadHolder::SetAssignmentMode(const NpadJoyAssignmentMode& mode) {
assignment_mode = mode;
}
NpadJoyAssignmentMode NpadAbstractedPadHolder::GetAssignmentMode() const {
return assignment_mode;
}
std::size_t NpadAbstractedPadHolder::GetStyleIndexList(
std::span<Core::HID::NpadStyleIndex> list) const {
for (std::size_t i = 0; i < list_size; i++) {
list[i] = assignment_list[i].device_type;
}
return list_size;
}
} // namespace Service::HID

View File

@@ -0,0 +1,47 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include <array>
#include <mutex>
#include <span>
#include "common/common_types.h"
#include "core/hle/result.h"
#include "hid_core/hid_types.h"
#include "hid_core/resources/npad/npad_types.h"
namespace Service::HID {
struct IAbstractedPad;
struct AbstractAssignmentHolder {
IAbstractedPad* abstracted_pad;
Core::HID::NpadStyleIndex device_type;
Core::HID::NpadInterfaceType interface_type;
INSERT_PADDING_BYTES(0x6);
u64 controller_id;
};
static_assert(sizeof(AbstractAssignmentHolder) == 0x18,
"AbstractAssignmentHolder is an invalid size");
/// This is nn::hid::server::NpadAbstractedPadHolder
class NpadAbstractedPadHolder final {
public:
Result RegisterAbstractPad(IAbstractedPad* abstracted_pad);
void RemoveAbstractPadByControllerId(u64 controller_id);
void DetachAbstractedPad();
u64 RemoveAbstractPadByAssignmentStyle(Service::HID::AssignmentStyle assignment_style);
u32 GetAbstractedPads(std::span<IAbstractedPad*> list) const;
void SetAssignmentMode(const NpadJoyAssignmentMode& mode);
NpadJoyAssignmentMode GetAssignmentMode() const;
std::size_t GetStyleIndexList(std::span<Core::HID::NpadStyleIndex> list) const;
private:
std::array<AbstractAssignmentHolder, 5> assignment_list{};
u32 list_size{};
NpadJoyAssignmentMode assignment_mode{NpadJoyAssignmentMode::Dual};
};
} // namespace Service::HID

View File

@@ -0,0 +1,47 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "hid_core/hid_result.h"
#include "hid_core/resources/abstracted_pad/abstract_palma_handler.h"
#include "hid_core/resources/abstracted_pad/abstract_properties_handler.h"
namespace Service::HID {
NpadAbstractPalmaHandler::NpadAbstractPalmaHandler() {}
NpadAbstractPalmaHandler::~NpadAbstractPalmaHandler() = default;
void NpadAbstractPalmaHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) {
abstract_pad_holder = holder;
}
void NpadAbstractPalmaHandler::SetPropertiesHandler(NpadAbstractPropertiesHandler* handler) {
properties_handler = handler;
return;
}
void NpadAbstractPalmaHandler::SetPalmaResource(PalmaResource* resource) {
palma_resource = resource;
}
Result NpadAbstractPalmaHandler::IncrementRefCounter() {
if (ref_counter == std::numeric_limits<s32>::max() - 1) {
return ResultNpadHandlerOverflow;
}
ref_counter++;
return ResultSuccess;
}
Result NpadAbstractPalmaHandler::DecrementRefCounter() {
if (ref_counter == 0) {
return ResultNpadHandlerNotInitialized;
}
ref_counter--;
return ResultSuccess;
}
void NpadAbstractPalmaHandler::UpdatePalmaState() {
// TODO
}
} // namespace Service::HID

View File

@@ -0,0 +1,37 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "common/common_types.h"
#include "core/hle/result.h"
#include "hid_core/hid_types.h"
namespace Service::HID {
class NpadAbstractedPadHolder;
class NpadAbstractPropertiesHandler;
class PalmaResource;
class NpadAbstractPalmaHandler final {
public:
explicit NpadAbstractPalmaHandler();
~NpadAbstractPalmaHandler();
void SetAbstractPadHolder(NpadAbstractedPadHolder* holder);
void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler);
void SetPalmaResource(PalmaResource* resource);
Result IncrementRefCounter();
Result DecrementRefCounter();
void UpdatePalmaState();
private:
NpadAbstractedPadHolder* abstract_pad_holder{nullptr};
NpadAbstractPropertiesHandler* properties_handler{nullptr};
PalmaResource* palma_resource{nullptr};
s32 ref_counter{};
};
} // namespace Service::HID

View File

@@ -0,0 +1,322 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "hid_core/hid_util.h"
#include "hid_core/resources/abstracted_pad/abstract_pad_holder.h"
#include "hid_core/resources/abstracted_pad/abstract_properties_handler.h"
#include "hid_core/resources/applet_resource.h"
#include "hid_core/resources/npad/npad_resource.h"
#include "hid_core/resources/npad/npad_types.h"
#include "hid_core/resources/shared_memory_format.h"
namespace Service::HID {
NpadAbstractPropertiesHandler::NpadAbstractPropertiesHandler() {}
NpadAbstractPropertiesHandler::~NpadAbstractPropertiesHandler() = default;
void NpadAbstractPropertiesHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) {
abstract_pad_holder = holder;
return;
}
void NpadAbstractPropertiesHandler::SetAppletResource(AppletResourceHolder* applet_resource) {
applet_resource_holder = applet_resource;
return;
}
void NpadAbstractPropertiesHandler::SetNpadId(Core::HID::NpadIdType npad_id) {
if (!IsNpadIdValid(npad_id)) {
ASSERT_MSG(false, "Invalid npad id");
}
npad_id_type = npad_id;
}
Core::HID::NpadIdType NpadAbstractPropertiesHandler::GetNpadId() const {
return npad_id_type;
}
Result NpadAbstractPropertiesHandler::IncrementRefCounter() {
if (ref_counter == std::numeric_limits<s32>::max() - 1) {
return ResultNpadHandlerOverflow;
}
if (ref_counter != 0) {
ref_counter++;
return ResultSuccess;
}
const auto npad_index = NpadIdTypeToIndex(npad_id_type);
for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) {
auto* data = applet_resource_holder->applet_resource->GetAruidData(aruid_index);
auto& internal_state =
data->shared_memory_format->npad.npad_entry[npad_index].internal_state;
if (!data->flag.is_assigned) {
continue;
}
internal_state.fullkey_lifo.buffer_count = 0;
internal_state.handheld_lifo.buffer_count = 0;
internal_state.joy_dual_lifo.buffer_count = 0;
internal_state.joy_left_lifo.buffer_count = 0;
internal_state.joy_right_lifo.buffer_count = 0;
internal_state.palma_lifo.buffer_count = 0;
internal_state.system_ext_lifo.buffer_count = 0;
internal_state.gc_trigger_lifo.buffer_count = 0;
internal_state.sixaxis_fullkey_lifo.lifo.buffer_count = 0;
internal_state.sixaxis_handheld_lifo.lifo.buffer_count = 0;
internal_state.sixaxis_dual_left_lifo.lifo.buffer_count = 0;
internal_state.sixaxis_dual_right_lifo.lifo.buffer_count = 0;
internal_state.sixaxis_left_lifo.lifo.buffer_count = 0;
internal_state.sixaxis_right_lifo.lifo.buffer_count = 0;
internal_state.style_tag = {Core::HID::NpadStyleSet::None};
internal_state.assignment_mode = NpadJoyAssignmentMode::Dual;
internal_state.joycon_color = {};
internal_state.fullkey_color = {};
internal_state.system_properties.raw = 0;
internal_state.button_properties.raw = 0;
internal_state.device_type.raw = 0;
internal_state.battery_level_dual = Core::HID::NpadBatteryLevel::Empty;
internal_state.battery_level_left = Core::HID::NpadBatteryLevel::Empty;
internal_state.battery_level_right = Core::HID::NpadBatteryLevel::Empty;
internal_state.applet_footer_type = AppletFooterUiType::None;
internal_state.applet_footer_attributes = {};
internal_state.lark_type_l_and_main = {};
internal_state.lark_type_r = {};
internal_state.sixaxis_fullkey_properties.is_newly_assigned.Assign(true);
internal_state.sixaxis_handheld_properties.is_newly_assigned.Assign(true);
internal_state.sixaxis_dual_left_properties.is_newly_assigned.Assign(true);
internal_state.sixaxis_dual_right_properties.is_newly_assigned.Assign(true);
internal_state.sixaxis_left_properties.is_newly_assigned.Assign(true);
internal_state.sixaxis_right_properties.is_newly_assigned.Assign(true);
}
ref_counter++;
return ResultSuccess;
}
Result NpadAbstractPropertiesHandler::DecrementRefCounter() {
if (ref_counter == 0) {
return ResultNpadHandlerNotInitialized;
}
ref_counter--;
return ResultSuccess;
}
Result NpadAbstractPropertiesHandler::ActivateNpadUnknown0x88(u64 aruid) {
const auto npad_index = NpadIdTypeToIndex(npad_id_type);
for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) {
auto* data = applet_resource_holder->applet_resource->GetAruidData(aruid_index);
if (!data->flag.is_assigned || data->aruid != aruid) {
continue;
}
UpdateDeviceProperties(aruid, data->shared_memory_format->npad.npad_entry[npad_index]);
return ResultSuccess;
}
return ResultSuccess;
}
void NpadAbstractPropertiesHandler::UpdateDeviceType() {
// TODO
}
void NpadAbstractPropertiesHandler::UpdateDeviceColor() {
// TODO
}
void NpadAbstractPropertiesHandler::UpdateFooterAttributes() {
// TODO
}
void NpadAbstractPropertiesHandler::UpdateAllDeviceProperties() {
const auto npad_index = NpadIdTypeToIndex(npad_id_type);
for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) {
auto* data = applet_resource_holder->applet_resource->GetAruidData(aruid_index);
if (!data->flag.is_assigned) {
continue;
}
auto& npad_entry = data->shared_memory_format->npad.npad_entry[npad_index];
UpdateDeviceProperties(data->aruid, npad_entry);
}
}
Core::HID::NpadInterfaceType NpadAbstractPropertiesHandler::GetFullkeyInterfaceType() {
std::array<IAbstractedPad*, 5> abstract_pads{};
const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads);
for (std::size_t i = 0; i < count; i++) {
auto* abstract_pad = abstract_pads[i];
if (!abstract_pad->internal_flags.is_connected) {
continue;
}
if (abstract_pad->device_type != Core::HID::NpadStyleIndex::Fullkey) {
continue;
}
if (abstract_pad->interface_type >= Core::HID::NpadInterfaceType::Embedded) {
// Abort
continue;
}
return abstract_pad->interface_type;
}
return Core::HID::NpadInterfaceType::None;
}
Core::HID::NpadInterfaceType NpadAbstractPropertiesHandler::GetInterfaceType() {
std::array<IAbstractedPad*, 5> abstract_pads{};
const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads);
for (std::size_t i = 0; i < count; i++) {
auto* abstract_pad = abstract_pads[i];
if (!abstract_pad->internal_flags.is_connected) {
continue;
}
if (!abstract_pad->disabled_feature_set.has_identification_code) {
continue;
}
if (abstract_pad->interface_type >= Core::HID::NpadInterfaceType::Embedded) {
// Abort
continue;
}
return abstract_pad->interface_type;
}
return Core::HID::NpadInterfaceType::None;
}
Core::HID::NpadStyleSet NpadAbstractPropertiesHandler::GetStyleSet(u64 aruid) {
// TODO
return Core::HID::NpadStyleSet::None;
}
std::size_t NpadAbstractPropertiesHandler::GetAbstractedPadsWithStyleTag(
std::span<IAbstractedPad*> list, Core::HID::NpadStyleTag style) {
std::array<IAbstractedPad*, 5> abstract_pads{};
const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads);
if (count == 0) {
return count;
}
bool is_supported_style_set{};
const auto result = applet_resource_holder->shared_npad_resource->IsSupportedNpadStyleSet(
is_supported_style_set, applet_resource_holder->applet_resource->GetActiveAruid());
if (!is_supported_style_set || result.IsError()) {
for (std::size_t i = 0; i < count; i++) {
// TODO
}
return count;
}
std::size_t filtered_count{};
for (std::size_t i = 0; i < count; i++) {
auto* abstract_pad = abstract_pads[i];
const bool is_enabled = true;
if (is_enabled) {
list[filtered_count] = abstract_pad;
filtered_count++;
}
}
return filtered_count;
}
std::size_t NpadAbstractPropertiesHandler::GetAbstractedPads(std::span<IAbstractedPad*> list) {
Core::HID::NpadStyleTag style{
GetStyleSet(applet_resource_holder->applet_resource->GetActiveAruid())};
return GetAbstractedPadsWithStyleTag(list, style);
}
AppletFooterUiType NpadAbstractPropertiesHandler::GetAppletFooterUiType() {
return applet_ui_type.footer;
}
AppletDetailedUiType NpadAbstractPropertiesHandler::GetAppletDetailedUiType() {
return applet_ui_type;
}
void NpadAbstractPropertiesHandler::UpdateDeviceProperties(u64 aruid,
NpadSharedMemoryEntry& internal_state) {
// TODO
}
Core::HID::NpadInterfaceType NpadAbstractPropertiesHandler::GetNpadInterfaceType() {
std::array<IAbstractedPad*, 5> abstract_pads{};
const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads);
for (std::size_t i = 0; i < count; i++) {
auto* abstract_pad = abstract_pads[i];
if (!abstract_pad->internal_flags.is_connected) {
continue;
}
if (abstract_pad->interface_type >= Core::HID::NpadInterfaceType::Embedded) {
// Abort
continue;
}
return abstract_pad->interface_type;
}
return Core::HID::NpadInterfaceType::None;
}
Result NpadAbstractPropertiesHandler::GetNpadFullKeyGripColor(
Core::HID::NpadColor& main_color, Core::HID::NpadColor& sub_color) const {
std::array<IAbstractedPad*, 5> abstract_pads{};
const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads);
if (applet_ui_type.footer != AppletFooterUiType::SwitchProController) {
return ResultNpadIsNotProController;
}
for (std::size_t i = 0; i < count; i++) {
auto* abstract_pad = abstract_pads[i];
if (!abstract_pad->internal_flags.is_connected) {
continue;
}
return ResultSuccess;
}
return ResultNpadIsNotProController;
}
void NpadAbstractPropertiesHandler::GetNpadLeftRightInterfaceType(
Core::HID::NpadInterfaceType& out_left_interface,
Core::HID::NpadInterfaceType& out_right_interface) const {
out_left_interface = Core::HID::NpadInterfaceType::None;
out_right_interface = Core::HID::NpadInterfaceType::None;
std::array<IAbstractedPad*, 5> abstract_pads{};
const std::size_t count = abstract_pad_holder->GetAbstractedPads(abstract_pads);
for (std::size_t i = 0; i < count; i++) {
auto* abstract_pad = abstract_pads[i];
if (!abstract_pad->internal_flags.is_connected) {
continue;
}
if (abstract_pad->assignment_style.is_external_left_assigned &&
abstract_pad->assignment_style.is_handheld_left_assigned) {
if (abstract_pad->interface_type > Core::HID::NpadInterfaceType::Embedded) {
// Abort
continue;
}
out_left_interface = abstract_pad->interface_type;
continue;
}
if (abstract_pad->assignment_style.is_external_right_assigned &&
abstract_pad->assignment_style.is_handheld_right_assigned) {
if (abstract_pad->interface_type > Core::HID::NpadInterfaceType::Embedded) {
// Abort
continue;
}
out_right_interface = abstract_pad->interface_type;
continue;
}
}
}
} // namespace Service::HID

View File

@@ -0,0 +1,86 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include <span>
#include "common/common_types.h"
#include "core/hle/result.h"
#include "hid_core/hid_types.h"
#include "hid_core/resources/npad/npad_types.h"
namespace Service::HID {
struct NpadSharedMemoryEntry;
struct AppletResourceHolder;
class NpadAbstractedPadHolder;
struct ColorProperties {
ColorAttribute attribute;
Core::HID::NpadControllerColor color;
INSERT_PADDING_BYTES(0x4);
};
/// Handles Npad request from HID interfaces
class NpadAbstractPropertiesHandler final {
public:
explicit NpadAbstractPropertiesHandler();
~NpadAbstractPropertiesHandler();
void SetAbstractPadHolder(NpadAbstractedPadHolder* holder);
void SetAppletResource(AppletResourceHolder* applet_resource);
void SetNpadId(Core::HID::NpadIdType npad_id);
Core::HID::NpadIdType GetNpadId() const;
Result IncrementRefCounter();
Result DecrementRefCounter();
Result ActivateNpadUnknown0x88(u64 aruid);
void UpdateDeviceType();
void UpdateDeviceColor();
void UpdateFooterAttributes();
void UpdateAllDeviceProperties();
Core::HID::NpadInterfaceType GetFullkeyInterfaceType();
Core::HID::NpadInterfaceType GetInterfaceType();
Core::HID::NpadStyleSet GetStyleSet(u64 aruid);
std::size_t GetAbstractedPadsWithStyleTag(std::span<IAbstractedPad*> list,
Core::HID::NpadStyleTag style);
std::size_t GetAbstractedPads(std::span<IAbstractedPad*> list);
AppletFooterUiType GetAppletFooterUiType();
AppletDetailedUiType GetAppletDetailedUiType();
void UpdateDeviceProperties(u64 aruid, NpadSharedMemoryEntry& internal_state);
Core::HID::NpadInterfaceType GetNpadInterfaceType();
Result GetNpadFullKeyGripColor(Core::HID::NpadColor& main_color,
Core::HID::NpadColor& sub_color) const;
void GetNpadLeftRightInterfaceType(Core::HID::NpadInterfaceType& param_2,
Core::HID::NpadInterfaceType& param_3) const;
private:
AppletResourceHolder* applet_resource_holder{nullptr};
NpadAbstractedPadHolder* abstract_pad_holder{nullptr};
Core::HID::NpadIdType npad_id_type{Core::HID::NpadIdType::Invalid};
s32 ref_counter{};
Core::HID::DeviceIndex device_type{};
AppletDetailedUiType applet_ui_type{};
AppletFooterUiAttributes applet_ui_attributes{};
bool is_vertical{};
bool is_horizontal{};
bool use_plus{};
bool use_minus{};
bool has_directional_buttons{};
ColorProperties fullkey_color{};
ColorProperties left_color{};
ColorProperties right_color{};
};
} // namespace Service::HID

View File

@@ -0,0 +1,154 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "hid_core/hid_result.h"
#include "hid_core/hid_util.h"
#include "hid_core/resources/abstracted_pad/abstract_pad_holder.h"
#include "hid_core/resources/abstracted_pad/abstract_properties_handler.h"
#include "hid_core/resources/abstracted_pad/abstract_sixaxis_handler.h"
#include "hid_core/resources/applet_resource.h"
#include "hid_core/resources/npad/npad_types.h"
#include "hid_core/resources/shared_memory_format.h"
namespace Service::HID {
NpadAbstractSixAxisHandler::NpadAbstractSixAxisHandler() {}
NpadAbstractSixAxisHandler::~NpadAbstractSixAxisHandler() = default;
void NpadAbstractSixAxisHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) {
abstract_pad_holder = holder;
}
void NpadAbstractSixAxisHandler::SetAppletResource(AppletResourceHolder* applet_resource) {
applet_resource_holder = applet_resource;
}
void NpadAbstractSixAxisHandler::SetPropertiesHandler(NpadAbstractPropertiesHandler* handler) {
properties_handler = handler;
}
void NpadAbstractSixAxisHandler::SetSixaxisResource(SixAxisResource* resource) {
six_axis_resource = resource;
}
Result NpadAbstractSixAxisHandler::IncrementRefCounter() {
if (ref_counter == std::numeric_limits<s32>::max() - 1) {
return ResultNpadHandlerOverflow;
}
ref_counter++;
return ResultSuccess;
}
Result NpadAbstractSixAxisHandler::DecrementRefCounter() {
if (ref_counter == 0) {
return ResultNpadHandlerNotInitialized;
}
ref_counter--;
return ResultSuccess;
}
u64 NpadAbstractSixAxisHandler::IsFirmwareUpdateAvailable() {
// TODO
return false;
}
Result NpadAbstractSixAxisHandler::UpdateSixAxisState() {
Core::HID::NpadIdType npad_id = properties_handler->GetNpadId();
for (std::size_t i = 0; i < AruidIndexMax; i++) {
auto* data = applet_resource_holder->applet_resource->GetAruidDataByIndex(i);
if (data->flag.is_assigned) {
continue;
}
auto& npad_entry = data->shared_memory_format->npad.npad_entry[NpadIdTypeToIndex(npad_id)];
UpdateSixaxisInternalState(npad_entry, data->aruid,
data->flag.enable_six_axis_sensor.As<bool>());
}
return ResultSuccess;
}
Result NpadAbstractSixAxisHandler::UpdateSixAxisState(u64 aruid) {
Core::HID::NpadIdType npad_id = properties_handler->GetNpadId();
auto* data = applet_resource_holder->applet_resource->GetAruidData(aruid);
if (data == nullptr) {
return ResultSuccess;
}
auto& npad_entry = data->shared_memory_format->npad.npad_entry[NpadIdTypeToIndex(npad_id)];
UpdateSixaxisInternalState(npad_entry, data->aruid,
data->flag.enable_six_axis_sensor.As<bool>());
return ResultSuccess;
}
Result NpadAbstractSixAxisHandler::UpdateSixAxisState2(u64 aruid) {
const auto npad_index = NpadIdTypeToIndex(properties_handler->GetNpadId());
AruidData* aruid_data = applet_resource_holder->applet_resource->GetAruidData(aruid);
if (aruid_data == nullptr) {
return ResultSuccess;
}
auto& npad_internal_state = aruid_data->shared_memory_format->npad.npad_entry[npad_index];
UpdateSixaxisInternalState(npad_internal_state, aruid,
aruid_data->flag.enable_six_axis_sensor.As<bool>());
return ResultSuccess;
}
void NpadAbstractSixAxisHandler::UpdateSixaxisInternalState(NpadSharedMemoryEntry& npad_entry,
u64 aruid, bool is_sensor_enabled) {
const Core::HID::NpadStyleTag style_tag{properties_handler->GetStyleSet(aruid)};
if (!style_tag.palma) {
UpdateSixaxisFullkeyLifo(style_tag, npad_entry.internal_state.sixaxis_fullkey_lifo,
is_sensor_enabled);
} else {
UpdateSixAxisPalmaLifo(style_tag, npad_entry.internal_state.sixaxis_fullkey_lifo,
is_sensor_enabled);
}
UpdateSixaxisHandheldLifo(style_tag, npad_entry.internal_state.sixaxis_handheld_lifo,
is_sensor_enabled);
UpdateSixaxisDualLifo(style_tag, npad_entry.internal_state.sixaxis_dual_left_lifo,
is_sensor_enabled);
UpdateSixaxisDualLifo(style_tag, npad_entry.internal_state.sixaxis_dual_right_lifo,
is_sensor_enabled);
UpdateSixaxisLeftLifo(style_tag, npad_entry.internal_state.sixaxis_left_lifo,
is_sensor_enabled);
UpdateSixaxisRightLifo(style_tag, npad_entry.internal_state.sixaxis_right_lifo,
is_sensor_enabled);
// TODO: Set sixaxis properties
}
void NpadAbstractSixAxisHandler::UpdateSixaxisFullkeyLifo(Core::HID::NpadStyleTag style_tag,
NpadSixAxisSensorLifo& sensor_lifo,
bool is_sensor_enabled) {
// TODO
}
void NpadAbstractSixAxisHandler::UpdateSixAxisPalmaLifo(Core::HID::NpadStyleTag style_tag,
NpadSixAxisSensorLifo& sensor_lifo,
bool is_sensor_enabled) {
// TODO
}
void NpadAbstractSixAxisHandler::UpdateSixaxisHandheldLifo(Core::HID::NpadStyleTag style_tag,
NpadSixAxisSensorLifo& sensor_lifo,
bool is_sensor_enabled) {
// TODO
}
void NpadAbstractSixAxisHandler::UpdateSixaxisDualLifo(Core::HID::NpadStyleTag style_tag,
NpadSixAxisSensorLifo& sensor_lifo,
bool is_sensor_enabled) {
// TODO
}
void NpadAbstractSixAxisHandler::UpdateSixaxisLeftLifo(Core::HID::NpadStyleTag style_tag,
NpadSixAxisSensorLifo& sensor_lifo,
bool is_sensor_enabled) {
// TODO
}
void NpadAbstractSixAxisHandler::UpdateSixaxisRightLifo(Core::HID::NpadStyleTag style_tag,
NpadSixAxisSensorLifo& sensor_lifo,
bool is_sensor_enabled) {
// TODO
}
} // namespace Service::HID

View File

@@ -0,0 +1,61 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "common/common_types.h"
#include "core/hle/result.h"
#include "hid_core/hid_types.h"
namespace Service::HID {
class SixAxisResource;
struct AppletResourceHolder;
class NpadAbstractedPadHolder;
class NpadAbstractPropertiesHandler;
struct NpadSixAxisSensorLifo;
/// Handles Npad request from HID interfaces
class NpadAbstractSixAxisHandler final {
public:
explicit NpadAbstractSixAxisHandler();
~NpadAbstractSixAxisHandler();
void SetAbstractPadHolder(NpadAbstractedPadHolder* holder);
void SetAppletResource(AppletResourceHolder* applet_resource);
void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler);
void SetSixaxisResource(SixAxisResource* resource);
Result IncrementRefCounter();
Result DecrementRefCounter();
u64 IsFirmwareUpdateAvailable();
Result UpdateSixAxisState();
Result UpdateSixAxisState(u64 aruid);
Result UpdateSixAxisState2(u64 aruid);
private:
void UpdateSixaxisInternalState(NpadSharedMemoryEntry& npad_entry, u64 aruid,
bool is_sensor_enabled);
void UpdateSixaxisFullkeyLifo(Core::HID::NpadStyleTag style_tag,
NpadSixAxisSensorLifo& sensor_lifo, bool is_sensor_enabled);
void UpdateSixAxisPalmaLifo(Core::HID::NpadStyleTag style_tag,
NpadSixAxisSensorLifo& sensor_lifo, bool is_sensor_enabled);
void UpdateSixaxisHandheldLifo(Core::HID::NpadStyleTag style_tag,
NpadSixAxisSensorLifo& sensor_lifo, bool is_sensor_enabled);
void UpdateSixaxisDualLifo(Core::HID::NpadStyleTag style_tag,
NpadSixAxisSensorLifo& sensor_lifo, bool is_sensor_enabled);
void UpdateSixaxisLeftLifo(Core::HID::NpadStyleTag style_tag,
NpadSixAxisSensorLifo& sensor_lifo, bool is_sensor_enabled);
void UpdateSixaxisRightLifo(Core::HID::NpadStyleTag style_tag,
NpadSixAxisSensorLifo& sensor_lifo, bool is_sensor_enabled);
AppletResourceHolder* applet_resource_holder{nullptr};
NpadAbstractedPadHolder* abstract_pad_holder{nullptr};
NpadAbstractPropertiesHandler* properties_handler{nullptr};
SixAxisResource* six_axis_resource{nullptr};
s32 ref_counter{};
};
} // namespace Service::HID

View File

@@ -0,0 +1,73 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "hid_core/hid_result.h"
#include "hid_core/hid_util.h"
#include "hid_core/resources/abstracted_pad/abstract_pad_holder.h"
#include "hid_core/resources/abstracted_pad/abstract_properties_handler.h"
#include "hid_core/resources/abstracted_pad/abstract_vibration_handler.h"
#include "hid_core/resources/applet_resource.h"
#include "hid_core/resources/npad/npad_vibration.h"
#include "hid_core/resources/vibration/gc_vibration_device.h"
#include "hid_core/resources/vibration/n64_vibration_device.h"
#include "hid_core/resources/vibration/vibration_device.h"
namespace Service::HID {
NpadAbstractVibrationHandler::NpadAbstractVibrationHandler() {}
NpadAbstractVibrationHandler::~NpadAbstractVibrationHandler() = default;
void NpadAbstractVibrationHandler::SetAbstractPadHolder(NpadAbstractedPadHolder* holder) {
abstract_pad_holder = holder;
}
void NpadAbstractVibrationHandler::SetAppletResource(AppletResourceHolder* applet_resource) {
applet_resource_holder = applet_resource;
}
void NpadAbstractVibrationHandler::SetPropertiesHandler(NpadAbstractPropertiesHandler* handler) {
properties_handler = handler;
}
void NpadAbstractVibrationHandler::SetN64Vibration(NpadN64VibrationDevice* n64_device) {
n64_vibration_device = n64_device;
}
void NpadAbstractVibrationHandler::SetVibration(std::span<NpadVibrationDevice*> device) {
for (std::size_t i = 0; i < device.size() && i < vibration_device.size(); i++) {
vibration_device[i] = device[i];
}
}
void NpadAbstractVibrationHandler::SetGcVibration(NpadGcVibrationDevice* gc_device) {
gc_vibration_device = gc_device;
}
Result NpadAbstractVibrationHandler::IncrementRefCounter() {
if (ref_counter == std::numeric_limits<s32>::max() - 1) {
return ResultNpadHandlerOverflow;
}
ref_counter++;
return ResultSuccess;
}
Result NpadAbstractVibrationHandler::DecrementRefCounter() {
if (ref_counter == 0) {
return ResultNpadHandlerNotInitialized;
}
ref_counter--;
return ResultSuccess;
}
void NpadAbstractVibrationHandler::UpdateVibrationState() {
const bool is_handheld_hid_enabled =
applet_resource_holder->handheld_config->is_handheld_hid_enabled;
const bool is_force_handheld_style_vibration =
applet_resource_holder->handheld_config->is_force_handheld_style_vibration;
if (!is_handheld_hid_enabled && is_force_handheld_style_vibration) {
// TODO
}
}
} // namespace Service::HID

View File

@@ -0,0 +1,51 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include <span>
#include "common/common_types.h"
#include "core/hle/result.h"
#include "hid_core/hid_types.h"
namespace Service::HID {
struct AppletResourceHolder;
class NpadAbstractedPadHolder;
class NpadAbstractPropertiesHandler;
class NpadGcVibrationDevice;
class NpadVibrationDevice;
class NpadN64VibrationDevice;
class NpadVibration;
/// Keeps track of battery levels and updates npad battery shared memory values
class NpadAbstractVibrationHandler final {
public:
explicit NpadAbstractVibrationHandler();
~NpadAbstractVibrationHandler();
void SetAbstractPadHolder(NpadAbstractedPadHolder* holder);
void SetAppletResource(AppletResourceHolder* applet_resource);
void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler);
void SetN64Vibration(NpadN64VibrationDevice* n64_device);
void SetVibration(std::span<NpadVibrationDevice*> device);
void SetGcVibration(NpadGcVibrationDevice* gc_device);
Result IncrementRefCounter();
Result DecrementRefCounter();
void UpdateVibrationState();
private:
AppletResourceHolder* applet_resource_holder{nullptr};
NpadAbstractedPadHolder* abstract_pad_holder{nullptr};
NpadAbstractPropertiesHandler* properties_handler{nullptr};
NpadN64VibrationDevice* n64_vibration_device{nullptr};
std::array<NpadVibrationDevice*, 2> vibration_device{};
NpadGcVibrationDevice* gc_vibration_device{nullptr};
NpadVibration* vibration_handler{nullptr};
s32 ref_counter{};
};
} // namespace Service::HID

View File

@@ -193,7 +193,7 @@ void NPad::InitNewlyAddedController(u64 aruid, Core::HID::NpadIdType npad_id) {
case Core::HID::NpadStyleIndex::None:
ASSERT(false);
break;
case Core::HID::NpadStyleIndex::ProController:
case Core::HID::NpadStyleIndex::Fullkey:
shared_memory->fullkey_color.attribute = ColorAttribute::Ok;
shared_memory->fullkey_color.fullkey = body_colors.fullkey;
shared_memory->battery_level_dual = battery_level.dual.battery_level;
@@ -491,7 +491,7 @@ void NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
case Core::HID::NpadStyleIndex::None:
ASSERT(false);
break;
case Core::HID::NpadStyleIndex::ProController:
case Core::HID::NpadStyleIndex::Fullkey:
case Core::HID::NpadStyleIndex::NES:
case Core::HID::NpadStyleIndex::SNES:
case Core::HID::NpadStyleIndex::N64:
@@ -1292,7 +1292,7 @@ Core::HID::SixAxisSensorProperties& NPad::GetSixaxisProperties(
u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle) {
auto& controller = GetControllerFromHandle(aruid, sixaxis_handle);
switch (sixaxis_handle.npad_type) {
case Core::HID::NpadStyleIndex::ProController:
case Core::HID::NpadStyleIndex::Fullkey:
case Core::HID::NpadStyleIndex::Pokeball:
return controller.shared_memory->sixaxis_fullkey_properties;
case Core::HID::NpadStyleIndex::Handheld:
@@ -1315,7 +1315,7 @@ const Core::HID::SixAxisSensorProperties& NPad::GetSixaxisProperties(
u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle) const {
const auto& controller = GetControllerFromHandle(aruid, sixaxis_handle);
switch (sixaxis_handle.npad_type) {
case Core::HID::NpadStyleIndex::ProController:
case Core::HID::NpadStyleIndex::Fullkey:
case Core::HID::NpadStyleIndex::Pokeball:
return controller.shared_memory->sixaxis_fullkey_properties;
case Core::HID::NpadStyleIndex::Handheld:

View File

@@ -151,7 +151,7 @@ Core::HID::NpadStyleSet NPadData::GetSupportedNpadStyleSet() const {
bool NPadData::IsNpadStyleIndexSupported(Core::HID::NpadStyleIndex style_index) const {
Core::HID::NpadStyleTag style = {supported_npad_style_set};
switch (style_index) {
case Core::HID::NpadStyleIndex::ProController:
case Core::HID::NpadStyleIndex::Fullkey:
return style.fullkey.As<bool>();
case Core::HID::NpadStyleIndex::Handheld:
return style.handheld.As<bool>();

View File

@@ -252,4 +252,103 @@ enum class NpadLagerType : u32 {
U,
};
// nn::hidtypes::FeatureType
struct FeatureType {
union {
u64 raw{};
BitField<0, 1, u64> has_left_analog_stick;
BitField<1, 1, u64> has_right_analog_stick;
BitField<2, 1, u64> has_left_joy_six_axis_sensor;
BitField<3, 1, u64> has_right_joy_six_axis_sensor;
BitField<4, 1, u64> has_fullkey_joy_six_axis_sensor;
BitField<5, 1, u64> has_left_lra_vibration_device;
BitField<6, 1, u64> has_right_lra_vibration_device;
BitField<7, 1, u64> has_gc_vibration_device;
BitField<8, 1, u64> has_erm_vibration_device;
BitField<9, 1, u64> has_left_joy_rail_bus;
BitField<10, 1, u64> has_right_joy_rail_bus;
BitField<11, 1, u64> has_internal_bus;
BitField<12, 1, u64> is_palma;
BitField<13, 1, u64> has_nfc;
BitField<14, 1, u64> has_ir_sensor;
BitField<15, 1, u64> is_analog_stick_calibration_supported;
BitField<16, 1, u64> is_six_axis_Sensor_user_calibration_supported;
BitField<17, 1, u64> has_left_right_joy_battery;
BitField<18, 1, u64> has_fullkey_battery;
BitField<19, 1, u64> is_disconnect_controller_if_battery_none;
BitField<20, 1, u64> has_controller_color;
BitField<21, 1, u64> has_grip_color;
BitField<22, 1, u64> has_identification_code;
BitField<23, 1, u64> has_bluetooth_address;
BitField<24, 1, u64> has_mcu;
BitField<25, 1, u64> has_notification_led;
BitField<26, 1, u64> has_directional_buttons;
BitField<27, 1, u64> has_indicator_led;
BitField<28, 1, u64> is_button_config_embedded_supported;
BitField<29, 1, u64> is_button_config_full_supported;
BitField<30, 1, u64> is_button_config_left_supported;
BitField<31, 1, u64> is_button_config_right_supported;
BitField<32, 1, u64> is_usb_hid_device;
BitField<33, 1, u64> is_kuina_device;
BitField<34, 1, u64> is_direct_usb_to_bt_switching_device;
BitField<35, 1, u64> is_normalize_analog_stick_with_inner_cross;
};
};
static_assert(sizeof(FeatureType) == 8, "FeatureType is an invalid size");
// This is nn::hid::AssignmentStyle
struct AssignmentStyle {
union {
u32 raw{};
BitField<0, 1, u32> is_external_assigned;
BitField<1, 1, u32> is_external_left_assigned;
BitField<2, 1, u32> is_external_right_assigned;
BitField<3, 1, u32> is_handheld_assigned;
BitField<4, 1, u32> is_handheld_left_assigned;
BitField<5, 1, u32> is_handheld_right_assigned;
};
};
static_assert(sizeof(AssignmentStyle) == 4, "AssignmentStyle is an invalid size");
// This is nn::hid::server::IAbstractedPad::InternalFlags
struct InternalFlags {
union {
u32 raw{};
BitField<0, 1, u32> is_bound;
BitField<1, 1, u32> is_connected;
BitField<2, 1, u32> is_battery_low_ovln_required;
BitField<3, 1, u32> is_battery_low_ovln_delay_required;
BitField<4, 1, u32> is_sample_recieved;
BitField<5, 1, u32> is_virtual_input;
BitField<6, 1, u32> is_wired;
BitField<8, 1, u32> use_center_clamp;
BitField<9, 1, u32> has_virtual_six_axis_sensor_acceleration;
BitField<10, 1, u32> has_virtual_six_axis_sensor_angle;
BitField<11, 1, u32> is_debug_pad;
};
};
static_assert(sizeof(InternalFlags) == 4, "InternalFlags is an invalid size");
/// This is nn::hid::server::IAbstractedPad
struct IAbstractedPad {
InternalFlags internal_flags;
u64 controller_id;
u32 controller_number;
u64 low_battery_display_delay_time;
u64 low_battery_display_delay_interval;
FeatureType feature_set;
FeatureType disabled_feature_set;
AssignmentStyle assignment_style;
Core::HID::NpadStyleIndex device_type;
Core::HID::NpadInterfaceType interface_type;
Core::HID::NpadPowerInfo power_info;
u32 pad_state;
u32 button_mask;
u32 system_button_mask;
u8 indicator;
std::vector<f32> virtual_six_axis_sensor_acceleration;
std::vector<f32> virtual_six_axis_sensor_angle;
u64 xcd_handle;
u64 color;
};
} // namespace Service::HID

View File

@@ -0,0 +1,80 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "hid_core/hid_result.h"
#include "hid_core/resources/npad/npad_vibration.h"
namespace Service::HID {
NpadVibration::NpadVibration() {}
NpadVibration::~NpadVibration() = default;
Result NpadVibration::Activate() {
std::scoped_lock lock{mutex};
const f32 master_volume = 1.0f; // nn::settings::system::GetVibrationMasterVolume();
// if (master_volume < 0.0f || master_volume > 1.0f) {
// return ResultVibrationStrenghtOutOfRange;
// }
volume = master_volume;
return ResultSuccess;
}
Result NpadVibration::Deactivate() {
return ResultSuccess;
}
Result NpadVibration::SetVibrationMasterVolume(f32 master_volume) {
std::scoped_lock lock{mutex};
if (master_volume < 0.0f && master_volume > 1.0f) {
return ResultVibrationStrenghtOutOfRange;
}
volume = master_volume;
// nn::settings::system::SetVibrationMasterVolume(master_volume);
return ResultSuccess;
}
Result NpadVibration::GetVibrationVolume(f32& out_volume) const {
std::scoped_lock lock{mutex};
out_volume = volume;
return ResultSuccess;
}
Result NpadVibration::GetVibrationMasterVolume(f32& out_volume) const {
std::scoped_lock lock{mutex};
const f32 master_volume = 1.0f; // nn::settings::system::GetVibrationMasterVolume();
// if (master_volume < 0.0f || master_volume > 1.0f) {
// return ResultVibrationStrenghtOutOfRange;
// }
out_volume = master_volume;
return ResultSuccess;
}
Result NpadVibration::BeginPermitVibrationSession(u64 aruid) {
std::scoped_lock lock{mutex};
session_aruid = aruid;
volume = 1.0;
return ResultSuccess;
}
Result NpadVibration::EndPermitVibrationSession() {
std::scoped_lock lock{mutex};
const f32 master_volume = 1.0f; // nn::settings::system::GetVibrationMasterVolume();
// if (master_volume < 0.0f || master_volume > 1.0f) {
// return ResultVibrationStrenghtOutOfRange;
// }
volume = master_volume;
session_aruid = 0;
return ResultSuccess;
}
} // namespace Service::HID

View File

@@ -0,0 +1,34 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include <mutex>
#include "common/common_types.h"
#include "core/hle/result.h"
namespace Service::HID {
class NpadVibration final {
public:
explicit NpadVibration();
~NpadVibration();
Result Activate();
Result Deactivate();
Result SetVibrationMasterVolume(f32 master_volume);
Result GetVibrationVolume(f32& out_volume) const;
Result GetVibrationMasterVolume(f32& out_volume) const;
Result BeginPermitVibrationSession(u64 aruid);
Result EndPermitVibrationSession();
private:
f32 volume{};
u64 session_aruid{};
mutable std::mutex mutex;
};
} // namespace Service::HID

View File

@@ -114,7 +114,7 @@ void SixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
case Core::HID::NpadStyleIndex::None:
ASSERT(false);
break;
case Core::HID::NpadStyleIndex::ProController:
case Core::HID::NpadStyleIndex::Fullkey:
set_motion_state(sixaxis_fullkey_state, motion_state[0]);
break;
case Core::HID::NpadStyleIndex::Handheld:
@@ -345,7 +345,7 @@ SixAxis::SixaxisParameters& SixAxis::GetSixaxisState(
const Core::HID::SixAxisSensorHandle& sixaxis_handle) {
auto& controller = GetControllerFromHandle(sixaxis_handle);
switch (sixaxis_handle.npad_type) {
case Core::HID::NpadStyleIndex::ProController:
case Core::HID::NpadStyleIndex::Fullkey:
case Core::HID::NpadStyleIndex::Pokeball:
return controller.sixaxis_fullkey;
case Core::HID::NpadStyleIndex::Handheld:
@@ -368,7 +368,7 @@ const SixAxis::SixaxisParameters& SixAxis::GetSixaxisState(
const Core::HID::SixAxisSensorHandle& sixaxis_handle) const {
const auto& controller = GetControllerFromHandle(sixaxis_handle);
switch (sixaxis_handle.npad_type) {
case Core::HID::NpadStyleIndex::ProController:
case Core::HID::NpadStyleIndex::Fullkey:
case Core::HID::NpadStyleIndex::Pokeball:
return controller.sixaxis_fullkey;
case Core::HID::NpadStyleIndex::Handheld:

View File

@@ -0,0 +1,106 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "hid_core/hid_result.h"
#include "hid_core/resources/npad/npad_types.h"
#include "hid_core/resources/npad/npad_vibration.h"
#include "hid_core/resources/vibration/gc_vibration_device.h"
namespace Service::HID {
NpadGcVibrationDevice::NpadGcVibrationDevice() {}
Result NpadGcVibrationDevice::IncrementRefCounter() {
if (ref_counter == 0 && is_mounted) {
f32 volume = 1.0f;
const auto result = vibration_handler->GetVibrationVolume(volume);
if (result.IsSuccess()) {
// TODO: SendVibrationGcErmCommand
}
}
ref_counter++;
return ResultSuccess;
}
Result NpadGcVibrationDevice::DecrementRefCounter() {
if (ref_counter == 1 && !is_mounted) {
f32 volume = 1.0f;
const auto result = vibration_handler->GetVibrationVolume(volume);
if (result.IsSuccess()) {
// TODO: SendVibrationGcErmCommand
}
}
if (ref_counter > 0) {
ref_counter--;
}
return ResultSuccess;
}
Result NpadGcVibrationDevice::SendVibrationGcErmCommand(Core::HID::VibrationGcErmCommand command) {
if (!is_mounted) {
return ResultSuccess;
}
f32 volume = 1.0f;
const auto result = vibration_handler->GetVibrationVolume(volume);
if (result.IsError()) {
return result;
}
if (volume == 0.0) {
command = Core::HID::VibrationGcErmCommand::Stop;
} else {
if (command > Core::HID::VibrationGcErmCommand::StopHard) {
// Abort
return ResultSuccess;
}
}
// TODO: SendVibrationGcErmCommand
return ResultSuccess;
}
Result NpadGcVibrationDevice::GetActualVibrationGcErmCommand(
Core::HID::VibrationGcErmCommand& out_command) {
if (!is_mounted) {
out_command = Core::HID::VibrationGcErmCommand::Stop;
return ResultSuccess;
}
f32 volume = 1.0f;
const auto result = vibration_handler->GetVibrationVolume(volume);
if (result.IsError()) {
return result;
}
if (volume == 0.0f) {
out_command = Core::HID::VibrationGcErmCommand::Stop;
return ResultSuccess;
}
// TODO: GetActualVibrationGcErmCommand
return ResultSuccess;
}
Result NpadGcVibrationDevice::SendVibrationNotificationPattern(
Core::HID::VibrationGcErmCommand command) {
if (!is_mounted) {
return ResultSuccess;
}
f32 volume = 1.0f;
const auto result = vibration_handler->GetVibrationVolume(volume);
if (result.IsError()) {
return result;
}
if (volume <= 0.0f) {
command = Core::HID::VibrationGcErmCommand::Stop;
}
if (command > Core::HID::VibrationGcErmCommand::StopHard) {
// Abort
return ResultSuccess;
}
// TODO: SendVibrationNotificationPattern
return ResultSuccess;
}
} // namespace Service::HID

View File

@@ -0,0 +1,31 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include <array>
#include <mutex>
#include "common/common_types.h"
#include "core/hle/result.h"
#include "hid_core/hid_types.h"
#include "hid_core/resources/npad/npad_types.h"
#include "hid_core/resources/vibration/vibration_base.h"
namespace Service::HID {
class NpadVibration;
/// Handles Npad request from HID interfaces
class NpadGcVibrationDevice final : public NpadVibrationBase {
public:
explicit NpadGcVibrationDevice();
Result IncrementRefCounter() override;
Result DecrementRefCounter() override;
Result SendVibrationGcErmCommand(Core::HID::VibrationGcErmCommand command);
Result GetActualVibrationGcErmCommand(Core::HID::VibrationGcErmCommand& out_command);
Result SendVibrationNotificationPattern(Core::HID::VibrationGcErmCommand command);
};
} // namespace Service::HID

View File

@@ -0,0 +1,80 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "hid_core/hid_result.h"
#include "hid_core/resources/npad/npad_types.h"
#include "hid_core/resources/npad/npad_vibration.h"
#include "hid_core/resources/vibration/n64_vibration_device.h"
namespace Service::HID {
NpadN64VibrationDevice::NpadN64VibrationDevice() {}
Result NpadN64VibrationDevice::IncrementRefCounter() {
if (ref_counter == 0 && is_mounted) {
f32 volume = 1.0f;
const auto result = vibration_handler->GetVibrationVolume(volume);
if (result.IsSuccess()) {
// TODO: SendVibrationInBool
}
}
ref_counter++;
return ResultSuccess;
}
Result NpadN64VibrationDevice::DecrementRefCounter() {
if (ref_counter == 1) {
if (!is_mounted) {
ref_counter = 0;
if (is_mounted != false) {
// TODO: SendVibrationInBool
}
return ResultSuccess;
}
f32 volume = 1.0f;
const auto result = vibration_handler->GetVibrationVolume(volume);
if (result.IsSuccess()) {
// TODO
}
}
if (ref_counter > 0) {
ref_counter--;
}
return ResultSuccess;
}
Result NpadN64VibrationDevice::SendValueInBool(bool is_vibrating) {
if (ref_counter < 1) {
return ResultVibrationNotInitialized;
}
if (is_mounted) {
f32 volume = 1.0f;
const auto result = vibration_handler->GetVibrationVolume(volume);
if (result.IsError()) {
return result;
}
// TODO: SendVibrationInBool
}
return ResultSuccess;
}
Result NpadN64VibrationDevice::SendVibrationNotificationPattern([[maybe_unused]] u32 pattern) {
if (!is_mounted) {
return ResultSuccess;
}
f32 volume = 1.0f;
const auto result = vibration_handler->GetVibrationVolume(volume);
if (result.IsError()) {
return result;
}
if (volume <= 0.0) {
pattern = 0;
}
// TODO: SendVibrationNotificationPattern
return ResultSuccess;
}
} // namespace Service::HID

View File

@@ -0,0 +1,29 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include <array>
#include <mutex>
#include "common/common_types.h"
#include "core/hle/result.h"
#include "hid_core/hid_types.h"
#include "hid_core/resources/npad/npad_types.h"
#include "hid_core/resources/vibration/vibration_base.h"
namespace Service::HID {
class NpadVibration;
/// Handles Npad request from HID interfaces
class NpadN64VibrationDevice final : public NpadVibrationBase {
public:
explicit NpadN64VibrationDevice();
Result IncrementRefCounter() override;
Result DecrementRefCounter() override;
Result SendValueInBool(bool is_vibrating);
Result SendVibrationNotificationPattern(u32 pattern);
};
} // namespace Service::HID

View File

@@ -0,0 +1,30 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "hid_core/hid_result.h"
#include "hid_core/resources/npad/npad_types.h"
#include "hid_core/resources/npad/npad_vibration.h"
#include "hid_core/resources/vibration/vibration_base.h"
namespace Service::HID {
NpadVibrationBase::NpadVibrationBase() {}
Result NpadVibrationBase::IncrementRefCounter() {
ref_counter++;
return ResultSuccess;
}
Result NpadVibrationBase::DecrementRefCounter() {
if (ref_counter > 0) {
ref_counter--;
}
return ResultSuccess;
}
bool NpadVibrationBase::IsVibrationMounted() const {
return is_mounted;
}
} // namespace Service::HID

View File

@@ -0,0 +1,28 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "common/common_types.h"
#include "core/hle/result.h"
namespace Service::HID {
class NpadVibration;
/// Handles Npad request from HID interfaces
class NpadVibrationBase {
public:
explicit NpadVibrationBase();
virtual Result IncrementRefCounter();
virtual Result DecrementRefCounter();
bool IsVibrationMounted() const;
protected:
u64 xcd_handle{};
s32 ref_counter{};
bool is_mounted{};
NpadVibration* vibration_handler{nullptr};
};
} // namespace Service::HID

View File

@@ -0,0 +1,84 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "hid_core/hid_result.h"
#include "hid_core/resources/npad/npad_types.h"
#include "hid_core/resources/npad/npad_vibration.h"
#include "hid_core/resources/vibration/vibration_device.h"
namespace Service::HID {
NpadVibrationDevice::NpadVibrationDevice() {}
Result NpadVibrationDevice::IncrementRefCounter() {
ref_counter++;
return ResultSuccess;
}
Result NpadVibrationDevice::DecrementRefCounter() {
if (ref_counter > 0) {
ref_counter--;
}
return ResultSuccess;
}
Result NpadVibrationDevice::SendVibrationValue(const Core::HID::VibrationValue& value) {
if (ref_counter == 0) {
return ResultVibrationNotInitialized;
}
if (!is_mounted) {
return ResultSuccess;
}
f32 volume = 1.0f;
const auto result = vibration_handler->GetVibrationVolume(volume);
if (result.IsError()) {
return result;
}
if (volume <= 0.0f) {
// TODO: SendVibrationValue
return ResultSuccess;
}
Core::HID::VibrationValue vibration_value = value;
vibration_value.high_amplitude *= volume;
vibration_value.low_amplitude *= volume;
// TODO: SendVibrationValue
return ResultSuccess;
}
Result NpadVibrationDevice::SendVibrationNotificationPattern([[maybe_unused]] u32 pattern) {
if (!is_mounted) {
return ResultSuccess;
}
f32 volume = 1.0f;
const auto result = vibration_handler->GetVibrationVolume(volume);
if (result.IsError()) {
return result;
}
if (volume <= 0.0) {
pattern = 0;
}
// return xcd_handle->SendVibrationNotificationPattern(pattern);
return ResultSuccess;
}
Result NpadVibrationDevice::GetActualVibrationValue(Core::HID::VibrationValue& out_value) {
if (ref_counter < 1) {
return ResultVibrationNotInitialized;
}
out_value = Core::HID::DEFAULT_VIBRATION_VALUE;
if (!is_mounted) {
return ResultSuccess;
}
// TODO: SendVibrationValue
return ResultSuccess;
}
} // namespace Service::HID

View File

@@ -0,0 +1,35 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include <array>
#include <mutex>
#include "common/common_types.h"
#include "core/hle/result.h"
#include "hid_core/hid_types.h"
#include "hid_core/resources/npad/npad_types.h"
#include "hid_core/resources/vibration/vibration_base.h"
namespace Service::HID {
class NpadVibration;
/// Handles Npad request from HID interfaces
class NpadVibrationDevice final : public NpadVibrationBase {
public:
explicit NpadVibrationDevice();
Result IncrementRefCounter();
Result DecrementRefCounter();
Result SendVibrationValue(const Core::HID::VibrationValue& value);
Result SendVibrationNotificationPattern(u32 pattern);
Result GetActualVibrationValue(Core::HID::VibrationValue& out_value);
private:
u32 device_index{};
};
} // namespace Service::HID

View File

@@ -65,6 +65,14 @@ void WriteStorage32(EmitContext& ctx, const IR::Value& binding, const IR::Value&
WriteStorage(ctx, binding, offset, value, ctx.storage_types.U32, sizeof(u32),
&StorageDefinitions::U32, index_offset);
}
void WriteStorageByCasLoop(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset,
Id value, Id bit_offset, Id bit_count) {
const Id pointer{StoragePointer(ctx, binding, offset, ctx.storage_types.U32, sizeof(u32),
&StorageDefinitions::U32)};
ctx.OpFunctionCall(ctx.TypeVoid(), ctx.write_storage_cas_loop_func, pointer, value, bit_offset,
bit_count);
}
} // Anonymous namespace
void EmitLoadGlobalU8(EmitContext&) {
@@ -219,26 +227,42 @@ Id EmitLoadStorage128(EmitContext& ctx, const IR::Value& binding, const IR::Valu
void EmitWriteStorageU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset,
Id value) {
WriteStorage(ctx, binding, offset, ctx.OpSConvert(ctx.U8, value), ctx.storage_types.U8,
sizeof(u8), &StorageDefinitions::U8);
if (ctx.profile.support_int8) {
WriteStorage(ctx, binding, offset, ctx.OpSConvert(ctx.U8, value), ctx.storage_types.U8,
sizeof(u8), &StorageDefinitions::U8);
} else {
WriteStorageByCasLoop(ctx, binding, offset, value, ctx.BitOffset8(offset), ctx.Const(8u));
}
}
void EmitWriteStorageS8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset,
Id value) {
WriteStorage(ctx, binding, offset, ctx.OpSConvert(ctx.S8, value), ctx.storage_types.S8,
sizeof(s8), &StorageDefinitions::S8);
if (ctx.profile.support_int8) {
WriteStorage(ctx, binding, offset, ctx.OpSConvert(ctx.S8, value), ctx.storage_types.S8,
sizeof(s8), &StorageDefinitions::S8);
} else {
WriteStorageByCasLoop(ctx, binding, offset, value, ctx.BitOffset8(offset), ctx.Const(8u));
}
}
void EmitWriteStorageU16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset,
Id value) {
WriteStorage(ctx, binding, offset, ctx.OpSConvert(ctx.U16, value), ctx.storage_types.U16,
sizeof(u16), &StorageDefinitions::U16);
if (ctx.profile.support_int16) {
WriteStorage(ctx, binding, offset, ctx.OpSConvert(ctx.U16, value), ctx.storage_types.U16,
sizeof(u16), &StorageDefinitions::U16);
} else {
WriteStorageByCasLoop(ctx, binding, offset, value, ctx.BitOffset16(offset), ctx.Const(16u));
}
}
void EmitWriteStorageS16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset,
Id value) {
WriteStorage(ctx, binding, offset, ctx.OpSConvert(ctx.S16, value), ctx.storage_types.S16,
sizeof(s16), &StorageDefinitions::S16);
if (ctx.profile.support_int16) {
WriteStorage(ctx, binding, offset, ctx.OpSConvert(ctx.S16, value), ctx.storage_types.S16,
sizeof(s16), &StorageDefinitions::S16);
} else {
WriteStorageByCasLoop(ctx, binding, offset, value, ctx.BitOffset16(offset), ctx.Const(16u));
}
}
void EmitWriteStorage32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset,

View File

@@ -480,6 +480,7 @@ EmitContext::EmitContext(const Profile& profile_, const RuntimeInfo& runtime_inf
DefineTextures(program.info, texture_binding, bindings.texture_scaling_index);
DefineImages(program.info, image_binding, bindings.image_scaling_index);
DefineAttributeMemAccess(program.info);
DefineWriteStorageCasLoopFunction(program.info);
DefineGlobalMemoryFunctions(program.info);
DefineRescalingInput(program.info);
DefineRenderArea(program.info);
@@ -877,6 +878,56 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) {
}
}
void EmitContext::DefineWriteStorageCasLoopFunction(const Info& info) {
if (profile.support_int8 && profile.support_int16) {
return;
}
if (!info.uses_int8 && !info.uses_int16) {
return;
}
AddCapability(spv::Capability::VariablePointersStorageBuffer);
const Id ptr_type{TypePointer(spv::StorageClass::StorageBuffer, U32[1])};
const Id func_type{TypeFunction(void_id, ptr_type, U32[1], U32[1], U32[1])};
const Id func{OpFunction(void_id, spv::FunctionControlMask::MaskNone, func_type)};
const Id pointer{OpFunctionParameter(ptr_type)};
const Id value{OpFunctionParameter(U32[1])};
const Id bit_offset{OpFunctionParameter(U32[1])};
const Id bit_count{OpFunctionParameter(U32[1])};
AddLabel();
const Id scope_device{Const(1u)};
const Id ordering_relaxed{u32_zero_value};
const Id body_label{OpLabel()};
const Id continue_label{OpLabel()};
const Id endloop_label{OpLabel()};
const Id beginloop_label{OpLabel()};
OpBranch(beginloop_label);
AddLabel(beginloop_label);
OpLoopMerge(endloop_label, continue_label, spv::LoopControlMask::MaskNone);
OpBranch(body_label);
AddLabel(body_label);
const Id expected_value{OpLoad(U32[1], pointer)};
const Id desired_value{OpBitFieldInsert(U32[1], expected_value, value, bit_offset, bit_count)};
const Id actual_value{OpAtomicCompareExchange(U32[1], pointer, scope_device, ordering_relaxed,
ordering_relaxed, desired_value, expected_value)};
const Id store_successful{OpIEqual(U1, expected_value, actual_value)};
OpBranchConditional(store_successful, endloop_label, continue_label);
AddLabel(endloop_label);
OpReturn();
AddLabel(continue_label);
OpBranch(beginloop_label);
OpFunctionEnd();
write_storage_cas_loop_func = func;
}
void EmitContext::DefineGlobalMemoryFunctions(const Info& info) {
if (!info.uses_global_memory || !profile.support_int64) {
return;

View File

@@ -325,6 +325,8 @@ public:
Id f32x2_min_cas{};
Id f32x2_max_cas{};
Id write_storage_cas_loop_func{};
Id load_global_func_u32{};
Id load_global_func_u32x2{};
Id load_global_func_u32x4{};
@@ -372,6 +374,7 @@ private:
void DefineTextures(const Info& info, u32& binding, u32& scaling_index);
void DefineImages(const Info& info, u32& binding, u32& scaling_index);
void DefineAttributeMemAccess(const Info& info);
void DefineWriteStorageCasLoopFunction(const Info& info);
void DefineGlobalMemoryFunctions(const Info& info);
void DefineRescalingInput(const Info& info);
void DefineRescalingInputPushConstant();

View File

@@ -41,7 +41,7 @@ void UpdateController(Core::HID::EmulatedController* controller,
bool IsControllerCompatible(Core::HID::NpadStyleIndex controller_type,
Core::Frontend::ControllerParameters parameters) {
switch (controller_type) {
case Core::HID::NpadStyleIndex::ProController:
case Core::HID::NpadStyleIndex::Fullkey:
return parameters.allow_pro_controller;
case Core::HID::NpadStyleIndex::JoyconDual:
return parameters.allow_dual_joycons;
@@ -462,7 +462,7 @@ void QtControllerSelectorDialog::SetEmulatedControllers(std::size_t player_index
};
if (npad_style_set.fullkey == 1) {
add_item(Core::HID::NpadStyleIndex::ProController, tr("Pro Controller"));
add_item(Core::HID::NpadStyleIndex::Fullkey, tr("Pro Controller"));
}
if (npad_style_set.joycon_dual == 1) {
@@ -519,7 +519,7 @@ Core::HID::NpadStyleIndex QtControllerSelectorDialog::GetControllerTypeFromIndex
[index](const auto& pair) { return pair.first == index; });
if (it == pairs.end()) {
return Core::HID::NpadStyleIndex::ProController;
return Core::HID::NpadStyleIndex::Fullkey;
}
return it->second;
@@ -549,7 +549,7 @@ void QtControllerSelectorDialog::UpdateControllerIcon(std::size_t player_index)
const QString stylesheet = [this, player_index] {
switch (GetControllerTypeFromIndex(emulated_controllers[player_index]->currentIndex(),
player_index)) {
case Core::HID::NpadStyleIndex::ProController:
case Core::HID::NpadStyleIndex::Fullkey:
case Core::HID::NpadStyleIndex::GameCube:
return QStringLiteral("image: url(:/controller/applet_pro_controller%0); ");
case Core::HID::NpadStyleIndex::JoyconDual:

View File

@@ -832,7 +832,7 @@ void QtSoftwareKeyboardDialog::SetControllerImage() {
}();
switch (controller_type) {
case Core::HID::NpadStyleIndex::ProController:
case Core::HID::NpadStyleIndex::Fullkey:
case Core::HID::NpadStyleIndex::GameCube:
ui->icon_controller->setStyleSheet(
QStringLiteral("image: url(:/overlay/controller_pro%1.png);").arg(theme));

View File

@@ -1094,7 +1094,7 @@ void ConfigureInputPlayer::SetConnectableControllers() {
};
if (npad_style_set.fullkey == 1) {
add_item(Core::HID::NpadStyleIndex::ProController, tr("Pro Controller"));
add_item(Core::HID::NpadStyleIndex::Fullkey, tr("Pro Controller"));
}
if (npad_style_set.joycon_dual == 1) {
@@ -1149,7 +1149,7 @@ Core::HID::NpadStyleIndex ConfigureInputPlayer::GetControllerTypeFromIndex(int i
[index](const auto& pair) { return pair.first == index; });
if (it == index_controller_type_pairs.end()) {
return Core::HID::NpadStyleIndex::ProController;
return Core::HID::NpadStyleIndex::Fullkey;
}
return it->second;
@@ -1178,7 +1178,7 @@ void ConfigureInputPlayer::UpdateInputDevices() {
void ConfigureInputPlayer::UpdateControllerAvailableButtons() {
auto layout = GetControllerTypeFromIndex(ui->comboControllerType->currentIndex());
if (debug) {
layout = Core::HID::NpadStyleIndex::ProController;
layout = Core::HID::NpadStyleIndex::Fullkey;
}
// List of all the widgets that will be hidden by any of the following layouts that need
@@ -1206,7 +1206,7 @@ void ConfigureInputPlayer::UpdateControllerAvailableButtons() {
std::vector<QWidget*> layout_hidden;
switch (layout) {
case Core::HID::NpadStyleIndex::ProController:
case Core::HID::NpadStyleIndex::Fullkey:
case Core::HID::NpadStyleIndex::Handheld:
layout_hidden = {
ui->buttonShoulderButtonsSLSRLeft,
@@ -1254,7 +1254,7 @@ void ConfigureInputPlayer::UpdateControllerAvailableButtons() {
void ConfigureInputPlayer::UpdateControllerEnabledButtons() {
auto layout = GetControllerTypeFromIndex(ui->comboControllerType->currentIndex());
if (debug) {
layout = Core::HID::NpadStyleIndex::ProController;
layout = Core::HID::NpadStyleIndex::Fullkey;
}
// List of all the widgets that will be disabled by any of the following layouts that need
@@ -1271,7 +1271,7 @@ void ConfigureInputPlayer::UpdateControllerEnabledButtons() {
std::vector<QWidget*> layout_disable;
switch (layout) {
case Core::HID::NpadStyleIndex::ProController:
case Core::HID::NpadStyleIndex::Fullkey:
case Core::HID::NpadStyleIndex::JoyconDual:
case Core::HID::NpadStyleIndex::Handheld:
case Core::HID::NpadStyleIndex::JoyconLeft:
@@ -1304,7 +1304,7 @@ void ConfigureInputPlayer::UpdateMotionButtons() {
// Show/hide the "Motion 1/2" groupboxes depending on the currently selected controller.
switch (GetControllerTypeFromIndex(ui->comboControllerType->currentIndex())) {
case Core::HID::NpadStyleIndex::ProController:
case Core::HID::NpadStyleIndex::Fullkey:
case Core::HID::NpadStyleIndex::JoyconLeft:
case Core::HID::NpadStyleIndex::Handheld:
// Show "Motion 1" and hide "Motion 2".
@@ -1333,11 +1333,11 @@ void ConfigureInputPlayer::UpdateMotionButtons() {
void ConfigureInputPlayer::UpdateControllerButtonNames() {
auto layout = GetControllerTypeFromIndex(ui->comboControllerType->currentIndex());
if (debug) {
layout = Core::HID::NpadStyleIndex::ProController;
layout = Core::HID::NpadStyleIndex::Fullkey;
}
switch (layout) {
case Core::HID::NpadStyleIndex::ProController:
case Core::HID::NpadStyleIndex::Fullkey:
case Core::HID::NpadStyleIndex::JoyconDual:
case Core::HID::NpadStyleIndex::Handheld:
case Core::HID::NpadStyleIndex::JoyconLeft:

View File

@@ -244,7 +244,7 @@ void PlayerControlPreview::paintEvent(QPaintEvent* event) {
case Core::HID::NpadStyleIndex::GameCube:
DrawGCController(p, center);
break;
case Core::HID::NpadStyleIndex::ProController:
case Core::HID::NpadStyleIndex::Fullkey:
default:
DrawProController(p, center);
break;

View File

@@ -3988,7 +3988,7 @@ void GMainWindow::OnToggleDockedMode() {
tr("Handheld controller can't be used on docked mode. Pro "
"controller will be selected."));
handheld->Disconnect();
player_1->SetNpadStyleIndex(Core::HID::NpadStyleIndex::ProController);
player_1->SetNpadStyleIndex(Core::HID::NpadStyleIndex::Fullkey);
player_1->Connect();
controller_dialog->refreshConfiguration();
}

View File

@@ -66,7 +66,7 @@ void ControllerNavigation::ControllerUpdateButton() {
}
switch (controller_type) {
case Core::HID::NpadStyleIndex::ProController:
case Core::HID::NpadStyleIndex::Fullkey:
case Core::HID::NpadStyleIndex::JoyconDual:
case Core::HID::NpadStyleIndex::Handheld:
case Core::HID::NpadStyleIndex::GameCube:
@@ -116,7 +116,7 @@ void ControllerNavigation::ControllerUpdateStick() {
}
switch (controller_type) {
case Core::HID::NpadStyleIndex::ProController:
case Core::HID::NpadStyleIndex::Fullkey:
case Core::HID::NpadStyleIndex::JoyconDual:
case Core::HID::NpadStyleIndex::Handheld:
case Core::HID::NpadStyleIndex::GameCube: