diff options
77 files changed, 1479 insertions, 1086 deletions
diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index ea1302b2f..c073f3f3f 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -79,7 +79,8 @@ jobs: fetch-depth: 0 - name: Install dependencies run: | - brew install autoconf automake boost@1.83 ccache ffmpeg fmt glslang hidapi libtool libusb lz4 ninja nlohmann-json openssl pkg-config qt@5 sdl2 speexdsp zlib zlib zstd + # workaround for https://github.com/actions/setup-python/issues/577 + brew install autoconf automake boost@1.83 ccache ffmpeg fmt glslang hidapi libtool libusb lz4 ninja nlohmann-json openssl pkg-config qt@5 sdl2 speexdsp zlib zlib zstd || brew link --overwrite python@3.12 - name: Build run: | mkdir build diff --git a/externals/vcpkg b/externals/vcpkg -Subproject ef2eef17340f3fbd679327d286fad06dd6e838e +Subproject a42af01b72c28a8e1d7b48107b33e4f286a55ef diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp index 3d795b57f..e5d3158c8 100644 --- a/src/android/app/src/main/jni/native.cpp +++ b/src/android/app/src/main/jni/native.cpp @@ -291,9 +291,6 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string // Initialize filesystem. ConfigureFilesystemProvider(filepath); - // Initialize account manager - m_profile_manager = std::make_unique<Service::Account::ProfileManager>(); - // Load the ROM. m_load_result = m_system.Load(EmulationSession::GetInstance().Window(), filepath); if (m_load_result != Core::SystemResultStatus::Success) { @@ -736,8 +733,8 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_initializeEmptyUserDirectory(JNIEnv* auto vfs_nand_dir = EmulationSession::GetInstance().System().GetFilesystem()->OpenDirectory( Common::FS::PathToUTF8String(nand_dir), FileSys::Mode::Read); - Service::Account::ProfileManager manager; - const auto user_id = manager.GetUser(static_cast<std::size_t>(0)); + const auto user_id = EmulationSession::GetInstance().System().GetProfileManager().GetUser( + static_cast<std::size_t>(0)); ASSERT(user_id); const auto user_save_data_path = FileSys::SaveDataFactory::GetFullPath( diff --git a/src/android/app/src/main/jni/native.h b/src/android/app/src/main/jni/native.h index 78ef96802..f1457bd1f 100644 --- a/src/android/app/src/main/jni/native.h +++ b/src/android/app/src/main/jni/native.h @@ -73,7 +73,6 @@ private: std::atomic<bool> m_is_running = false; std::atomic<bool> m_is_paused = false; SoftwareKeyboard::AndroidKeyboard* m_software_keyboard{}; - std::unique_ptr<Service::Account::ProfileManager> m_profile_manager; std::unique_ptr<FileSys::ManualContentProvider> m_manual_provider; // GPU driver parameters diff --git a/src/common/fs/path_util.cpp b/src/common/fs/path_util.cpp index c3a81f9a9..d2f50432a 100644 --- a/src/common/fs/path_util.cpp +++ b/src/common/fs/path_util.cpp @@ -354,18 +354,36 @@ std::string_view RemoveTrailingSlash(std::string_view path) { return path; } -std::vector<std::string> SplitPathComponents(std::string_view filename) { - std::string copy(filename); - std::replace(copy.begin(), copy.end(), '\\', '/'); - std::vector<std::string> out; - - std::stringstream stream(copy); - std::string item; - while (std::getline(stream, item, '/')) { - out.push_back(std::move(item)); +template <typename F> +static void ForEachPathComponent(std::string_view filename, F&& cb) { + const char* component_begin = filename.data(); + const char* const end = component_begin + filename.size(); + for (const char* it = component_begin; it != end; ++it) { + const char c = *it; + if (c == '\\' || c == '/') { + if (component_begin != it) { + cb(std::string_view{component_begin, it}); + } + component_begin = it + 1; + } } + if (component_begin != end) { + cb(std::string_view{component_begin, end}); + } +} + +std::vector<std::string_view> SplitPathComponents(std::string_view filename) { + std::vector<std::string_view> components; + ForEachPathComponent(filename, [&](auto component) { components.emplace_back(component); }); + + return components; +} + +std::vector<std::string> SplitPathComponentsCopy(std::string_view filename) { + std::vector<std::string> components; + ForEachPathComponent(filename, [&](auto component) { components.emplace_back(component); }); - return out; + return components; } std::string SanitizePath(std::string_view path_, DirectorySeparator directory_separator) { diff --git a/src/common/fs/path_util.h b/src/common/fs/path_util.h index 2874ea738..23c8b1359 100644 --- a/src/common/fs/path_util.h +++ b/src/common/fs/path_util.h @@ -289,7 +289,11 @@ enum class DirectorySeparator { // Splits the path on '/' or '\' and put the components into a vector // i.e. "C:\Users\Yuzu\Documents\save.bin" becomes {"C:", "Users", "Yuzu", "Documents", "save.bin" } -[[nodiscard]] std::vector<std::string> SplitPathComponents(std::string_view filename); +[[nodiscard]] std::vector<std::string_view> SplitPathComponents(std::string_view filename); + +// Splits the path on '/' or '\' and put the components into a vector +// i.e. "C:\Users\Yuzu\Documents\save.bin" becomes {"C:", "Users", "Yuzu", "Documents", "save.bin" } +[[nodiscard]] std::vector<std::string> SplitPathComponentsCopy(std::string_view filename); // Removes trailing slash, makes all '\\' into '/', and removes duplicate '/'. Makes '/' into '\\' // depending if directory_separator is BackwardSlash or PlatformDefault and running on windows diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp index 4bfc64f2d..e540375b8 100644 --- a/src/common/host_memory.cpp +++ b/src/common/host_memory.cpp @@ -11,10 +11,6 @@ #elif defined(__linux__) || defined(__FreeBSD__) // ^^^ Windows ^^^ vvv Linux vvv -#ifdef ANDROID -#include <android/sharedmem.h> -#endif - #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif @@ -193,6 +189,11 @@ public: } } + bool ClearBackingRegion(size_t physical_offset, size_t length) { + // TODO: This does not seem to be possible on Windows. + return false; + } + void EnableDirectMappedAddress() { // TODO UNREACHABLE(); @@ -442,9 +443,7 @@ public: } // Backing memory initialization -#ifdef ANDROID - fd = ASharedMemory_create("HostMemory", backing_size); -#elif defined(__FreeBSD__) && __FreeBSD__ < 13 +#if defined(__FreeBSD__) && __FreeBSD__ < 13 // XXX Drop after FreeBSD 12.* reaches EOL on 2024-06-30 fd = shm_open(SHM_ANON, O_RDWR, 0600); #else @@ -455,7 +454,6 @@ public: throw std::bad_alloc{}; } -#ifndef ANDROID // Defined to extend the file with zeros int ret = ftruncate(fd, backing_size); if (ret != 0) { @@ -463,7 +461,6 @@ public: strerror(errno)); throw std::bad_alloc{}; } -#endif backing_base = static_cast<u8*>( mmap(nullptr, backing_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)); @@ -552,6 +549,19 @@ public: ASSERT_MSG(ret == 0, "mprotect failed: {}", strerror(errno)); } + bool ClearBackingRegion(size_t physical_offset, size_t length) { +#ifdef __linux__ + // Set MADV_REMOVE on backing map to destroy it instantly. + // This also deletes the area from the backing file. + int ret = madvise(backing_base + physical_offset, length, MADV_REMOVE); + ASSERT_MSG(ret == 0, "madvise failed: {}", strerror(errno)); + + return true; +#else + return false; +#endif + } + void EnableDirectMappedAddress() { virtual_base = nullptr; } @@ -623,6 +633,10 @@ public: void Protect(size_t virtual_offset, size_t length, bool read, bool write, bool execute) {} + bool ClearBackingRegion(size_t physical_offset, size_t length) { + return false; + } + void EnableDirectMappedAddress() {} u8* backing_base{nullptr}; @@ -698,6 +712,12 @@ void HostMemory::Protect(size_t virtual_offset, size_t length, bool read, bool w impl->Protect(virtual_offset + virtual_base_offset, length, read, write, execute); } +void HostMemory::ClearBackingRegion(size_t physical_offset, size_t length, u32 fill_value) { + if (!impl || fill_value != 0 || !impl->ClearBackingRegion(physical_offset, length)) { + std::memset(backing_base + physical_offset, fill_value, length); + } +} + void HostMemory::EnableDirectMappedAddress() { if (impl) { impl->EnableDirectMappedAddress(); diff --git a/src/common/host_memory.h b/src/common/host_memory.h index cebfacab2..747c5850c 100644 --- a/src/common/host_memory.h +++ b/src/common/host_memory.h @@ -48,6 +48,8 @@ public: void EnableDirectMappedAddress(); + void ClearBackingRegion(size_t physical_offset, size_t length, u32 fill_value); + [[nodiscard]] u8* BackingBasePointer() noexcept { return backing_base; } diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index bffe68bd3..b22c9fd05 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -549,6 +549,11 @@ add_library(core STATIC hle/service/hid/xcd.cpp hle/service/hid/xcd.h hle/service/hid/errors.h + hle/service/hid/controllers/types/debug_pad_types.h + hle/service/hid/controllers/types/keyboard_types.h + hle/service/hid/controllers/types/mouse_types.h + hle/service/hid/controllers/types/npad_types.h + hle/service/hid/controllers/types/touch_types.h hle/service/hid/controllers/applet_resource.cpp hle/service/hid/controllers/applet_resource.h hle/service/hid/controllers/console_six_axis.cpp @@ -569,14 +574,15 @@ add_library(core STATIC hle/service/hid/controllers/palma.h hle/service/hid/controllers/seven_six_axis.cpp hle/service/hid/controllers/seven_six_axis.h + hle/service/hid/controllers/shared_memory_format.h + hle/service/hid/controllers/shared_memory_holder.cpp + hle/service/hid/controllers/shared_memory_holder.h hle/service/hid/controllers/six_axis.cpp hle/service/hid/controllers/six_axis.h hle/service/hid/controllers/stubbed.cpp hle/service/hid/controllers/stubbed.h hle/service/hid/controllers/touchscreen.cpp hle/service/hid/controllers/touchscreen.h - hle/service/hid/controllers/xpad.cpp - hle/service/hid/controllers/xpad.h hle/service/hid/hidbus/hidbus_base.cpp hle/service/hid/hidbus/hidbus_base.h hle/service/hid/hidbus/ringcon.cpp diff --git a/src/core/core.cpp b/src/core/core.cpp index 229cb879c..b14f74976 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -36,6 +36,7 @@ #include "core/hle/kernel/k_scheduler.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/physical_core.h" +#include "core/hle/service/acc/profile_manager.h" #include "core/hle/service/am/applets/applets.h" #include "core/hle/service/apm/apm_controller.h" #include "core/hle/service/filesystem/filesystem.h" @@ -130,8 +131,8 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs, struct System::Impl { explicit Impl(System& system) : kernel{system}, fs_controller{system}, memory{system}, hid_core{}, room_network{}, - cpu_manager{system}, reporter{system}, applet_manager{system}, time_manager{system}, - gpu_dirty_memory_write_manager{} { + cpu_manager{system}, reporter{system}, applet_manager{system}, profile_manager{}, + time_manager{system}, gpu_dirty_memory_write_manager{} { memory.SetGPUDirtyManagers(gpu_dirty_memory_write_manager); } @@ -532,6 +533,7 @@ struct System::Impl { /// Service State Service::Glue::ARPManager arp_manager; + Service::Account::ProfileManager profile_manager; Service::Time::TimeManager time_manager; /// Service manager @@ -921,6 +923,14 @@ const Service::APM::Controller& System::GetAPMController() const { return impl->apm_controller; } +Service::Account::ProfileManager& System::GetProfileManager() { + return impl->profile_manager; +} + +const Service::Account::ProfileManager& System::GetProfileManager() const { + return impl->profile_manager; +} + Service::Time::TimeManager& System::GetTimeManager() { return impl->time_manager; } diff --git a/src/core/core.h b/src/core/core.h index 05a222f5c..473204db7 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -45,6 +45,10 @@ class Memory; namespace Service { +namespace Account { +class ProfileManager; +} // namespace Account + namespace AM::Applets { struct AppletFrontendSet; class AppletManager; @@ -383,6 +387,9 @@ public: [[nodiscard]] Service::APM::Controller& GetAPMController(); [[nodiscard]] const Service::APM::Controller& GetAPMController() const; + [[nodiscard]] Service::Account::ProfileManager& GetProfileManager(); + [[nodiscard]] const Service::Account::ProfileManager& GetProfileManager() const; + [[nodiscard]] Service::Time::TimeManager& GetTimeManager(); [[nodiscard]] const Service::Time::TimeManager& GetTimeManager() const; diff --git a/src/core/file_sys/vfs.cpp b/src/core/file_sys/vfs.cpp index 639842401..b7105c8ff 100644 --- a/src/core/file_sys/vfs.cpp +++ b/src/core/file_sys/vfs.cpp @@ -201,8 +201,6 @@ std::string VfsFile::GetFullPath() const { VirtualFile VfsDirectory::GetFileRelative(std::string_view path) const { auto vec = Common::FS::SplitPathComponents(path); - vec.erase(std::remove_if(vec.begin(), vec.end(), [](const auto& str) { return str.empty(); }), - vec.end()); if (vec.empty()) { return nullptr; } @@ -237,8 +235,6 @@ VirtualFile VfsDirectory::GetFileAbsolute(std::string_view path) const { VirtualDir VfsDirectory::GetDirectoryRelative(std::string_view path) const { auto vec = Common::FS::SplitPathComponents(path); - vec.erase(std::remove_if(vec.begin(), vec.end(), [](const auto& str) { return str.empty(); }), - vec.end()); if (vec.empty()) { // TODO(DarkLordZach): Return this directory if path is '/' or similar. Can't currently // because of const-ness @@ -303,8 +299,6 @@ std::size_t VfsDirectory::GetSize() const { VirtualFile VfsDirectory::CreateFileRelative(std::string_view path) { auto vec = Common::FS::SplitPathComponents(path); - vec.erase(std::remove_if(vec.begin(), vec.end(), [](const auto& str) { return str.empty(); }), - vec.end()); if (vec.empty()) { return nullptr; } @@ -334,8 +328,6 @@ VirtualFile VfsDirectory::CreateFileAbsolute(std::string_view path) { VirtualDir VfsDirectory::CreateDirectoryRelative(std::string_view path) { auto vec = Common::FS::SplitPathComponents(path); - vec.erase(std::remove_if(vec.begin(), vec.end(), [](const auto& str) { return str.empty(); }), - vec.end()); if (vec.empty()) { return nullptr; } diff --git a/src/core/file_sys/vfs_real.cpp b/src/core/file_sys/vfs_real.cpp index 1c706e4d8..cd9b79786 100644 --- a/src/core/file_sys/vfs_real.cpp +++ b/src/core/file_sys/vfs_real.cpp @@ -268,7 +268,7 @@ void RealVfsFilesystem::RemoveReferenceFromListLocked(FileReference& reference) RealVfsFile::RealVfsFile(RealVfsFilesystem& base_, std::unique_ptr<FileReference> reference_, const std::string& path_, Mode perms_, std::optional<u64> size_) : base(base_), reference(std::move(reference_)), path(path_), - parent_path(FS::GetParentPath(path_)), path_components(FS::SplitPathComponents(path_)), + parent_path(FS::GetParentPath(path_)), path_components(FS::SplitPathComponentsCopy(path_)), size(size_), perms(perms_) {} RealVfsFile::~RealVfsFile() { @@ -276,7 +276,7 @@ RealVfsFile::~RealVfsFile() { } std::string RealVfsFile::GetName() const { - return path_components.back(); + return path_components.empty() ? "" : std::string(path_components.back()); } std::size_t RealVfsFile::GetSize() const { @@ -375,7 +375,7 @@ std::vector<VirtualDir> RealVfsDirectory::IterateEntries<RealVfsDirectory, VfsDi RealVfsDirectory::RealVfsDirectory(RealVfsFilesystem& base_, const std::string& path_, Mode perms_) : base(base_), path(FS::RemoveTrailingSlash(path_)), parent_path(FS::GetParentPath(path)), - path_components(FS::SplitPathComponents(path)), perms(perms_) { + path_components(FS::SplitPathComponentsCopy(path)), perms(perms_) { if (!FS::Exists(path) && True(perms & Mode::Write)) { void(FS::CreateDirs(path)); } @@ -464,7 +464,7 @@ bool RealVfsDirectory::IsReadable() const { } std::string RealVfsDirectory::GetName() const { - return path_components.back(); + return path_components.empty() ? "" : std::string(path_components.back()); } VirtualDir RealVfsDirectory::GetParentDirectory() const { diff --git a/src/core/hid/input_interpreter.cpp b/src/core/hid/input_interpreter.cpp index a6bdd28f2..072f38a68 100644 --- a/src/core/hid/input_interpreter.cpp +++ b/src/core/hid/input_interpreter.cpp @@ -20,6 +20,9 @@ InputInterpreter::InputInterpreter(Core::System& system) InputInterpreter::~InputInterpreter() = default; void InputInterpreter::PollInput() { + if (npad == nullptr) { + return; + } const auto button_state = npad->GetAndResetPressState(); previous_index = current_index; diff --git a/src/core/hle/kernel/k_memory_manager.cpp b/src/core/hle/kernel/k_memory_manager.cpp index 0a973ec8c..d6bd27296 100644 --- a/src/core/hle/kernel/k_memory_manager.cpp +++ b/src/core/hle/kernel/k_memory_manager.cpp @@ -421,8 +421,9 @@ Result KMemoryManager::AllocateForProcess(KPageGroup* out, size_t num_pages, u32 } else { // Set all the allocated memory. for (const auto& block : *out) { - std::memset(m_system.DeviceMemory().GetPointer<void>(block.GetAddress()), fill_pattern, - block.GetSize()); + m_system.DeviceMemory().buffer.ClearBackingRegion(GetInteger(block.GetAddress()) - + Core::DramMemoryMap::Base, + block.GetSize(), fill_pattern); } } diff --git a/src/core/hle/kernel/k_page_table_base.cpp b/src/core/hle/kernel/k_page_table_base.cpp index 4c416d809..423289145 100644 --- a/src/core/hle/kernel/k_page_table_base.cpp +++ b/src/core/hle/kernel/k_page_table_base.cpp @@ -81,6 +81,11 @@ void InvalidateInstructionCache(KernelCore& kernel, AddressType addr, u64 size) } } +void ClearBackingRegion(Core::System& system, KPhysicalAddress addr, u64 size, u32 fill_value) { + system.DeviceMemory().buffer.ClearBackingRegion(GetInteger(addr) - Core::DramMemoryMap::Base, + size, fill_value); +} + template <typename AddressType> Result InvalidateDataCache(AddressType addr, u64 size) { R_SUCCEED(); @@ -1363,8 +1368,7 @@ Result KPageTableBase::MapInsecureMemory(KProcessAddress address, size_t size) { // Clear all the newly allocated pages. for (const auto& it : pg) { - std::memset(GetHeapVirtualPointer(m_kernel, it.GetAddress()), - static_cast<u32>(m_heap_fill_value), it.GetSize()); + ClearBackingRegion(m_system, it.GetAddress(), it.GetSize(), m_heap_fill_value); } // Lock the table. @@ -1570,8 +1574,7 @@ Result KPageTableBase::AllocateAndMapPagesImpl(PageLinkedList* page_list, KProce // Clear all pages. for (const auto& it : pg) { - std::memset(GetHeapVirtualPointer(m_kernel, it.GetAddress()), - static_cast<u32>(m_heap_fill_value), it.GetSize()); + ClearBackingRegion(m_system, it.GetAddress(), it.GetSize(), m_heap_fill_value); } // Map the pages. @@ -2159,8 +2162,7 @@ Result KPageTableBase::SetHeapSize(KProcessAddress* out, size_t size) { // Clear all the newly allocated pages. for (const auto& it : pg) { - std::memset(GetHeapVirtualPointer(m_kernel, it.GetAddress()), m_heap_fill_value, - it.GetSize()); + ClearBackingRegion(m_system, it.GetAddress(), it.GetSize(), m_heap_fill_value); } // Map the pages. diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 8cb05ca0b..e479dacde 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -135,7 +135,6 @@ struct KernelCore::Impl { obj = nullptr; } }; - CleanupObject(hid_shared_mem); CleanupObject(font_shared_mem); CleanupObject(irs_shared_mem); CleanupObject(time_shared_mem); @@ -744,22 +743,16 @@ struct KernelCore::Impl { void InitializeHackSharedMemory(KernelCore& kernel) { // Setup memory regions for emulated processes // TODO(bunnei): These should not be hardcoded regions initialized within the kernel - constexpr std::size_t hid_size{0x40000}; constexpr std::size_t font_size{0x1100000}; constexpr std::size_t irs_size{0x8000}; constexpr std::size_t time_size{0x1000}; constexpr std::size_t hidbus_size{0x1000}; - hid_shared_mem = KSharedMemory::Create(system.Kernel()); font_shared_mem = KSharedMemory::Create(system.Kernel()); irs_shared_mem = KSharedMemory::Create(system.Kernel()); time_shared_mem = KSharedMemory::Create(system.Kernel()); hidbus_shared_mem = KSharedMemory::Create(system.Kernel()); - hid_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, - Svc::MemoryPermission::Read, hid_size); - KSharedMemory::Register(kernel, hid_shared_mem); - font_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, Svc::MemoryPermission::Read, font_size); KSharedMemory::Register(kernel, font_shared_mem); @@ -1190,14 +1183,6 @@ const KSystemResource& KernelCore::GetSystemSystemResource() const { return *impl->sys_system_resource; } -Kernel::KSharedMemory& KernelCore::GetHidSharedMem() { - return *impl->hid_shared_mem; -} - -const Kernel::KSharedMemory& KernelCore::GetHidSharedMem() const { - return *impl->hid_shared_mem; -} - Kernel::KSharedMemory& KernelCore::GetFontSharedMem() { return *impl->font_shared_mem; } diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 69b5bbd6c..78c88902c 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -239,12 +239,6 @@ public: /// Gets the system resource manager. const KSystemResource& GetSystemSystemResource() const; - /// Gets the shared memory object for HID services. - Kernel::KSharedMemory& GetHidSharedMem(); - - /// Gets the shared memory object for HID services. - const Kernel::KSharedMemory& GetHidSharedMem() const; - /// Gets the shared memory object for font services. Kernel::KSharedMemory& GetFontSharedMem(); diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index 508db7360..780f8c74d 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp @@ -104,11 +104,7 @@ Result VfsDirectoryServiceWrapper::CreateDirectory(const std::string& path_) con const auto components = Common::FS::SplitPathComponents(path); std::string relative_path; for (const auto& component : components) { - // Skip empty path components - if (component.empty()) { - continue; - } - relative_path = Common::FS::SanitizePath(relative_path + '/' + component); + relative_path = Common::FS::SanitizePath(fmt::format("{}/{}", relative_path, component)); auto new_dir = backing->CreateSubdirectory(relative_path); if (new_dir == nullptr) { // TODO(DarkLordZach): Find a better error code for this diff --git a/src/core/hle/service/hid/controllers/applet_resource.cpp b/src/core/hle/service/hid/controllers/applet_resource.cpp index ee60d8b44..c8e74c764 100644 --- a/src/core/hle/service/hid/controllers/applet_resource.cpp +++ b/src/core/hle/service/hid/controllers/applet_resource.cpp @@ -4,6 +4,7 @@ #include "core/core.h" #include "core/hle/kernel/k_shared_memory.h" #include "core/hle/service/hid/controllers/applet_resource.h" +#include "core/hle/service/hid/controllers/shared_memory_format.h" #include "core/hle/service/hid/errors.h" namespace Service::HID { @@ -23,11 +24,24 @@ Result AppletResource::CreateAppletResource(u64 aruid) { return ResultAruidAlreadyRegistered; } - // TODO: Here shared memory is created for the process we don't quite emulate this part so - // obtain this pointer from system - auto& shared_memory = system.Kernel().GetHidSharedMem(); + auto& shared_memory = shared_memory_holder[index]; + if (!shared_memory.IsMapped()) { + const Result result = shared_memory.Initialize(system); + if (result.IsError()) { + return result; + } + if (shared_memory.GetAddress() == nullptr) { + shared_memory.Finalize(); + return ResultSharedMemoryNotInitialized; + } + } - data[index].shared_memory_handle = &shared_memory; + auto* shared_memory_format = shared_memory.GetAddress(); + if (shared_memory_format != nullptr) { + shared_memory_format->Initialize(); + } + + data[index].shared_memory_format = shared_memory_format; data[index].flag.is_assigned.Assign(true); // TODO: InitializeSixAxisControllerConfig(false); active_aruid = aruid; @@ -94,7 +108,7 @@ void AppletResource::UnregisterAppletResourceUserId(u64 aruid) { if (index < AruidIndexMax) { if (data[index].flag.is_assigned) { - data[index].shared_memory_handle = nullptr; + data[index].shared_memory_format = nullptr; data[index].flag.is_assigned.Assign(false); } } @@ -112,6 +126,19 @@ void AppletResource::UnregisterAppletResourceUserId(u64 aruid) { } } +void AppletResource::FreeAppletResourceId(u64 aruid) { + u64 index = GetIndexFromAruid(aruid); + if (index >= AruidIndexMax) { + return; + } + + auto& aruid_data = data[index]; + if (aruid_data.flag.is_assigned) { + aruid_data.shared_memory_format = nullptr; + aruid_data.flag.is_assigned.Assign(false); + } +} + u64 AppletResource::GetActiveAruid() { return active_aruid; } @@ -122,7 +149,18 @@ Result AppletResource::GetSharedMemoryHandle(Kernel::KSharedMemory** out_handle, return ResultAruidNotRegistered; } - *out_handle = data[index].shared_memory_handle; + *out_handle = shared_memory_holder[index].GetHandle(); + return ResultSuccess; +} + +Result AppletResource::GetSharedMemoryFormat(SharedMemoryFormat** out_shared_memory_format, + u64 aruid) { + u64 index = GetIndexFromAruid(aruid); + if (index >= AruidIndexMax) { + return ResultAruidNotRegistered; + } + + *out_shared_memory_format = data[index].shared_memory_format; return ResultSuccess; } @@ -196,4 +234,80 @@ void AppletResource::EnablePalmaBoostMode(u64 aruid, bool is_enabled) { data[index].flag.enable_palma_boost_mode.Assign(is_enabled); } +Result AppletResource::RegisterCoreAppletResource() { + if (ref_counter == std::numeric_limits<s32>::max() - 1) { + return ResultAppletResourceOverflow; + } + if (ref_counter == 0) { + const u64 index = GetIndexFromAruid(0); + if (index < AruidIndexMax) { + return ResultAruidAlreadyRegistered; + } + + std::size_t data_index = AruidIndexMax; + for (std::size_t i = 0; i < AruidIndexMax; i++) { + if (!data[i].flag.is_initialized) { + data_index = i; + break; + } + } + + if (data_index == AruidIndexMax) { + return ResultAruidNoAvailableEntries; + } + + AruidData& aruid_data = data[data_index]; + + aruid_data.aruid = 0; + aruid_data.flag.is_initialized.Assign(true); + aruid_data.flag.enable_pad_input.Assign(true); + aruid_data.flag.enable_six_axis_sensor.Assign(true); + aruid_data.flag.bit_18.Assign(true); + aruid_data.flag.enable_touchscreen.Assign(true); + + data_index = AruidIndexMax; + for (std::size_t i = 0; i < AruidIndexMax; i++) { + if (registration_list.flag[i] == RegistrationStatus::Initialized) { + if (registration_list.aruid[i] != 0) { + continue; + } + data_index = i; + break; + } + if (registration_list.flag[i] == RegistrationStatus::None) { + data_index = i; + break; + } + } + + Result result = ResultSuccess; + + if (data_index == AruidIndexMax) { + result = CreateAppletResource(0); + } else { + registration_list.flag[data_index] = RegistrationStatus::Initialized; + registration_list.aruid[data_index] = 0; + } + + if (result.IsError()) { + UnregisterAppletResourceUserId(0); + return result; + } + } + ref_counter++; + return ResultSuccess; +} + +Result AppletResource::UnregisterCoreAppletResource() { + if (ref_counter == 0) { + return ResultAppletResourceNotInitialized; + } + + if (--ref_counter == 0) { + UnregisterAppletResourceUserId(0); + } + + return ResultSuccess; +} + } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/applet_resource.h b/src/core/hle/service/hid/controllers/applet_resource.h index 3dcec2898..e7991f93a 100644 --- a/src/core/hle/service/hid/controllers/applet_resource.h +++ b/src/core/hle/service/hid/controllers/applet_resource.h @@ -8,6 +8,7 @@ #include "common/bit_field.h" #include "common/common_types.h" #include "core/hle/result.h" +#include "core/hle/service/hid/controllers/shared_memory_holder.h" namespace Core { class System; @@ -18,6 +19,8 @@ class KSharedMemory; } namespace Service::HID { +struct SharedMemoryFormat; + class AppletResource { public: explicit AppletResource(Core::System& system_); @@ -28,8 +31,11 @@ public: Result RegisterAppletResourceUserId(u64 aruid, bool enable_input); void UnregisterAppletResourceUserId(u64 aruid); + void FreeAppletResourceId(u64 aruid); + u64 GetActiveAruid(); Result GetSharedMemoryHandle(Kernel::KSharedMemory** out_handle, u64 aruid); + Result GetSharedMemoryFormat(SharedMemoryFormat** out_shared_memory_format, u64 aruid); u64 GetIndexFromAruid(u64 aruid); @@ -42,6 +48,9 @@ public: void SetIsPalmaConnectable(u64 aruid, bool is_connectable); void EnablePalmaBoostMode(u64 aruid, bool is_enabled); + Result RegisterCoreAppletResource(); + Result UnregisterCoreAppletResource(); + private: static constexpr std::size_t AruidIndexMax = 0x20; @@ -75,12 +84,14 @@ private: struct AruidData { DataStatusFlag flag{}; u64 aruid{}; - Kernel::KSharedMemory* shared_memory_handle{nullptr}; + SharedMemoryFormat* shared_memory_format{nullptr}; }; u64 active_aruid{}; AruidRegisterList registration_list{}; std::array<AruidData, AruidIndexMax> data{}; + std::array<SharedMemoryHolder, AruidIndexMax> shared_memory_holder{}; + s32 ref_counter{}; Core::System& system; }; diff --git a/src/core/hle/service/hid/controllers/console_six_axis.cpp b/src/core/hle/service/hid/controllers/console_six_axis.cpp index b2bf1d78d..3961d2b5f 100644 --- a/src/core/hle/service/hid/controllers/console_six_axis.cpp +++ b/src/core/hle/service/hid/controllers/console_six_axis.cpp @@ -1,23 +1,18 @@ // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "core/core.h" #include "core/core_timing.h" #include "core/hid/emulated_console.h" #include "core/hid/hid_core.h" #include "core/hle/service/hid/controllers/console_six_axis.h" -#include "core/memory.h" +#include "core/hle/service/hid/controllers/shared_memory_format.h" namespace Service::HID { -constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C200; -ConsoleSixAxis::ConsoleSixAxis(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) - : ControllerBase{hid_core_} { +ConsoleSixAxis::ConsoleSixAxis(Core::HID::HIDCore& hid_core_, + ConsoleSixAxisSensorSharedMemoryFormat& console_shared_memory) + : ControllerBase{hid_core_}, shared_memory{console_shared_memory} { console = hid_core.GetEmulatedConsole(); - static_assert(SHARED_MEMORY_OFFSET + sizeof(ConsoleSharedMemory) < shared_memory_size, - "ConsoleSharedMemory is bigger than the shared memory"); - shared_memory = std::construct_at( - reinterpret_cast<ConsoleSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET)); } ConsoleSixAxis::~ConsoleSixAxis() = default; @@ -33,10 +28,10 @@ void ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) { const auto motion_status = console->GetMotion(); - shared_memory->sampling_number++; - shared_memory->is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest; - shared_memory->verticalization_error = motion_status.verticalization_error; - shared_memory->gyro_bias = motion_status.gyro_bias; + shared_memory.sampling_number++; + shared_memory.is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest; + shared_memory.verticalization_error = motion_status.verticalization_error; + shared_memory.gyro_bias = motion_status.gyro_bias; } } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/console_six_axis.h b/src/core/hle/service/hid/controllers/console_six_axis.h index 5b7c6a29a..3d1c9ce23 100644 --- a/src/core/hle/service/hid/controllers/console_six_axis.h +++ b/src/core/hle/service/hid/controllers/console_six_axis.h @@ -3,7 +3,6 @@ #pragma once -#include "common/vector_math.h" #include "core/hle/service/hid/controllers/controller_base.h" namespace Core::HID { @@ -11,9 +10,12 @@ class EmulatedConsole; } // namespace Core::HID namespace Service::HID { +struct ConsoleSixAxisSensorSharedMemoryFormat; + class ConsoleSixAxis final : public ControllerBase { public: - explicit ConsoleSixAxis(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_); + explicit ConsoleSixAxis(Core::HID::HIDCore& hid_core_, + ConsoleSixAxisSensorSharedMemoryFormat& console_shared_memory); ~ConsoleSixAxis() override; // Called when the controller is initialized @@ -26,18 +28,7 @@ public: void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; private: - // This is nn::hid::detail::ConsoleSixAxisSensorSharedMemoryFormat - struct ConsoleSharedMemory { - u64 sampling_number{}; - bool is_seven_six_axis_sensor_at_rest{}; - INSERT_PADDING_BYTES(3); // padding - f32 verticalization_error{}; - Common::Vec3f gyro_bias{}; - INSERT_PADDING_BYTES(4); // padding - }; - static_assert(sizeof(ConsoleSharedMemory) == 0x20, "ConsoleSharedMemory is an invalid size"); - - ConsoleSharedMemory* shared_memory = nullptr; + ConsoleSixAxisSensorSharedMemoryFormat& shared_memory; Core::HID::EmulatedConsole* console = nullptr; }; } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/controller_base.h b/src/core/hle/service/hid/controllers/controller_base.h index 9a44ee41e..4326c7821 100644 --- a/src/core/hle/service/hid/controllers/controller_base.h +++ b/src/core/hle/service/hid/controllers/controller_base.h @@ -39,9 +39,6 @@ public: bool IsControllerActivated() const; - static const std::size_t hid_entry_count = 17; - static const std::size_t shared_memory_size = 0x40000; - protected: bool is_activated{false}; diff --git a/src/core/hle/service/hid/controllers/debug_pad.cpp b/src/core/hle/service/hid/controllers/debug_pad.cpp index 9de19ebfc..7d2370b4f 100644 --- a/src/core/hle/service/hid/controllers/debug_pad.cpp +++ b/src/core/hle/service/hid/controllers/debug_pad.cpp @@ -1,24 +1,19 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include <cstring> -#include "common/common_types.h" #include "common/settings.h" #include "core/core_timing.h" #include "core/hid/emulated_controller.h" #include "core/hid/hid_core.h" #include "core/hid/hid_types.h" #include "core/hle/service/hid/controllers/debug_pad.h" +#include "core/hle/service/hid/controllers/shared_memory_format.h" namespace Service::HID { -constexpr std::size_t SHARED_MEMORY_OFFSET = 0x00000; - -DebugPad::DebugPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) - : ControllerBase{hid_core_} { - static_assert(SHARED_MEMORY_OFFSET + sizeof(DebugPadSharedMemory) < shared_memory_size, - "DebugPadSharedMemory is bigger than the shared memory"); - shared_memory = std::construct_at( - reinterpret_cast<DebugPadSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET)); + +DebugPad::DebugPad(Core::HID::HIDCore& hid_core_, + DebugPadSharedMemoryFormat& debug_pad_shared_memory) + : ControllerBase{hid_core_}, shared_memory{debug_pad_shared_memory} { controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other); } @@ -30,12 +25,12 @@ void DebugPad::OnRelease() {} void DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) { if (!IsControllerActivated()) { - shared_memory->debug_pad_lifo.buffer_count = 0; - shared_memory->debug_pad_lifo.buffer_tail = 0; + shared_memory.debug_pad_lifo.buffer_count = 0; + shared_memory.debug_pad_lifo.buffer_tail = 0; return; } - const auto& last_entry = shared_memory->debug_pad_lifo.ReadCurrentEntry().state; + const auto& last_entry = shared_memory.debug_pad_lifo.ReadCurrentEntry().state; next_state.sampling_number = last_entry.sampling_number + 1; if (Settings::values.debug_pad_enabled) { @@ -49,7 +44,7 @@ void DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) { next_state.r_stick = stick_state.right; } - shared_memory->debug_pad_lifo.WriteNextEntry(next_state); + shared_memory.debug_pad_lifo.WriteNextEntry(next_state); } } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/debug_pad.h b/src/core/hle/service/hid/controllers/debug_pad.h index 5566dba77..8ab29eca8 100644 --- a/src/core/hle/service/hid/controllers/debug_pad.h +++ b/src/core/hle/service/hid/controllers/debug_pad.h @@ -3,21 +3,24 @@ #pragma once -#include "common/bit_field.h" -#include "common/common_types.h" #include "core/hle/service/hid/controllers/controller_base.h" -#include "core/hle/service/hid/ring_lifo.h" +#include "core/hle/service/hid/controllers/types/debug_pad_types.h" namespace Core::HID { -class EmulatedController; -struct DebugPadButton; -struct AnalogStickState; -} // namespace Core::HID +class HIDCore; +} + +namespace Core::Timing { +class CoreTiming; +} namespace Service::HID { +struct DebugPadSharedMemoryFormat; + class DebugPad final : public ControllerBase { public: - explicit DebugPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_); + explicit DebugPad(Core::HID::HIDCore& hid_core_, + DebugPadSharedMemoryFormat& debug_pad_shared_memory); ~DebugPad() override; // Called when the controller is initialized @@ -30,35 +33,8 @@ public: void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; private: - // This is nn::hid::DebugPadAttribute - struct DebugPadAttribute { - union { - u32 raw{}; - BitField<0, 1, u32> connected; - }; - }; - static_assert(sizeof(DebugPadAttribute) == 0x4, "DebugPadAttribute is an invalid size"); - - // This is nn::hid::DebugPadState - struct DebugPadState { - s64 sampling_number{}; - DebugPadAttribute attribute{}; - Core::HID::DebugPadButton pad_state{}; - Core::HID::AnalogStickState r_stick{}; - Core::HID::AnalogStickState l_stick{}; - }; - static_assert(sizeof(DebugPadState) == 0x20, "DebugPadState is an invalid state"); - - struct DebugPadSharedMemory { - // This is nn::hid::detail::DebugPadLifo - Lifo<DebugPadState, hid_entry_count> debug_pad_lifo{}; - static_assert(sizeof(debug_pad_lifo) == 0x2C8, "debug_pad_lifo is an invalid size"); - INSERT_PADDING_WORDS(0x4E); - }; - static_assert(sizeof(DebugPadSharedMemory) == 0x400, "DebugPadSharedMemory is an invalid size"); - DebugPadState next_state{}; - DebugPadSharedMemory* shared_memory = nullptr; + DebugPadSharedMemoryFormat& shared_memory; Core::HID::EmulatedController* controller = nullptr; }; } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/gesture.cpp b/src/core/hle/service/hid/controllers/gesture.cpp index 59b2ec73c..f658005f6 100644 --- a/src/core/hle/service/hid/controllers/gesture.cpp +++ b/src/core/hle/service/hid/controllers/gesture.cpp @@ -1,17 +1,15 @@ // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "common/logging/log.h" #include "common/math_util.h" #include "common/settings.h" -#include "core/core_timing.h" #include "core/frontend/emu_window.h" +#include "core/hid/emulated_console.h" #include "core/hid/hid_core.h" #include "core/hle/service/hid/controllers/gesture.h" +#include "core/hle/service/hid/controllers/shared_memory_format.h" namespace Service::HID { -constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3BA00; - // HW is around 700, value is set to 400 to make it easier to trigger with mouse constexpr f32 swipe_threshold = 400.0f; // Threshold in pixels/s constexpr f32 angle_threshold = 0.015f; // Threshold in radians @@ -23,19 +21,15 @@ constexpr f32 Square(s32 num) { return static_cast<f32>(num * num); } -Gesture::Gesture(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) - : ControllerBase(hid_core_) { - static_assert(SHARED_MEMORY_OFFSET + sizeof(GestureSharedMemory) < shared_memory_size, - "GestureSharedMemory is bigger than the shared memory"); - shared_memory = std::construct_at( - reinterpret_cast<GestureSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET)); +Gesture::Gesture(Core::HID::HIDCore& hid_core_, GestureSharedMemoryFormat& gesture_shared_memory) + : ControllerBase(hid_core_), shared_memory{gesture_shared_memory} { console = hid_core.GetEmulatedConsole(); } Gesture::~Gesture() = default; void Gesture::OnInit() { - shared_memory->gesture_lifo.buffer_count = 0; - shared_memory->gesture_lifo.buffer_tail = 0; + shared_memory.gesture_lifo.buffer_count = 0; + shared_memory.gesture_lifo.buffer_tail = 0; force_update = true; } @@ -43,8 +37,8 @@ void Gesture::OnRelease() {} void Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing) { if (!IsControllerActivated()) { - shared_memory->gesture_lifo.buffer_count = 0; - shared_memory->gesture_lifo.buffer_tail = 0; + shared_memory.gesture_lifo.buffer_count = 0; + shared_memory.gesture_lifo.buffer_tail = 0; return; } @@ -52,7 +46,7 @@ void Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing) { GestureProperties gesture = GetGestureProperties(); f32 time_difference = - static_cast<f32>(shared_memory->gesture_lifo.timestamp - last_update_timestamp) / + static_cast<f32>(shared_memory.gesture_lifo.timestamp - last_update_timestamp) / (1000 * 1000 * 1000); // Only update if necessary @@ -60,7 +54,7 @@ void Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing) { return; } - last_update_timestamp = shared_memory->gesture_lifo.timestamp; + last_update_timestamp = shared_memory.gesture_lifo.timestamp; UpdateGestureSharedMemory(gesture, time_difference); } @@ -103,7 +97,7 @@ void Gesture::UpdateGestureSharedMemory(GestureProperties& gesture, f32 time_dif GestureType type = GestureType::Idle; GestureAttribute attributes{}; - const auto& last_entry = shared_memory->gesture_lifo.ReadCurrentEntry().state; + const auto& last_entry = shared_memory.gesture_lifo.ReadCurrentEntry().state; // Reset next state to default next_state.sampling_number = last_entry.sampling_number + 1; @@ -133,7 +127,7 @@ void Gesture::UpdateGestureSharedMemory(GestureProperties& gesture, f32 time_dif next_state.points = gesture.points; last_gesture = gesture; - shared_memory->gesture_lifo.WriteNextEntry(next_state); + shared_memory.gesture_lifo.WriteNextEntry(next_state); } void Gesture::NewGesture(GestureProperties& gesture, GestureType& type, @@ -305,11 +299,11 @@ void Gesture::SetSwipeEvent(GestureProperties& gesture, GestureProperties& last_ next_state.direction = GestureDirection::Up; } -const Gesture::GestureState& Gesture::GetLastGestureEntry() const { - return shared_memory->gesture_lifo.ReadCurrentEntry().state; +const GestureState& Gesture::GetLastGestureEntry() const { + return shared_memory.gesture_lifo.ReadCurrentEntry().state; } -Gesture::GestureProperties Gesture::GetGestureProperties() { +GestureProperties Gesture::GetGestureProperties() { GestureProperties gesture; std::array<Core::HID::TouchFinger, MAX_POINTS> active_fingers; const auto end_iter = std::copy_if(fingers.begin(), fingers.end(), active_fingers.begin(), diff --git a/src/core/hle/service/hid/controllers/gesture.h b/src/core/hle/service/hid/controllers/gesture.h index 4c6f8ee07..41fdfcd03 100644 --- a/src/core/hle/service/hid/controllers/gesture.h +++ b/src/core/hle/service/hid/controllers/gesture.h @@ -4,17 +4,22 @@ #pragma once #include <array> -#include "common/bit_field.h" + #include "common/common_types.h" -#include "common/point.h" -#include "core/hid/emulated_console.h" #include "core/hle/service/hid/controllers/controller_base.h" -#include "core/hle/service/hid/ring_lifo.h" +#include "core/hle/service/hid/controllers/types/touch_types.h" + +namespace Core::HID { +class EmulatedConsole; +} namespace Service::HID { +struct GestureSharedMemoryFormat; + class Gesture final : public ControllerBase { public: - explicit Gesture(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_); + explicit Gesture(Core::HID::HIDCore& hid_core_, + GestureSharedMemoryFormat& gesture_shared_memory); ~Gesture() override; // Called when the controller is initialized @@ -27,79 +32,6 @@ public: void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; private: - static constexpr size_t MAX_FINGERS = 16; - static constexpr size_t MAX_POINTS = 4; - - // This is nn::hid::GestureType - enum class GestureType : u32 { - Idle, // Nothing touching the screen - Complete, // Set at the end of a touch event - Cancel, // Set when the number of fingers change - Touch, // A finger just touched the screen - Press, // Set if last type is touch and the finger hasn't moved - Tap, // Fast press then release - Pan, // All points moving together across the screen - Swipe, // Fast press movement and release of a single point - Pinch, // All points moving away/closer to the midpoint - Rotate, // All points rotating from the midpoint - }; - - // This is nn::hid::GestureDirection - enum class GestureDirection : u32 { - None, - Left, - Up, - Right, - Down, - }; - - // This is nn::hid::GestureAttribute - struct GestureAttribute { - union { - u32 raw{}; - - BitField<4, 1, u32> is_new_touch; - BitField<8, 1, u32> is_double_tap; - }; - }; - static_assert(sizeof(GestureAttribute) == 4, "GestureAttribute is an invalid size"); - - // This is nn::hid::GestureState - struct GestureState { - s64 sampling_number{}; - s64 detection_count{}; - GestureType type{GestureType::Idle}; - GestureDirection direction{GestureDirection::None}; - Common::Point<s32> pos{}; - Common::Point<s32> delta{}; - f32 vel_x{}; - f32 vel_y{}; - GestureAttribute attributes{}; - f32 scale{}; - f32 rotation_angle{}; - s32 point_count{}; - std::array<Common::Point<s32>, 4> points{}; - }; - static_assert(sizeof(GestureState) == 0x60, "GestureState is an invalid size"); - - struct GestureProperties { - std::array<Common::Point<s32>, MAX_POINTS> points{}; - std::size_t active_points{}; - Common::Point<s32> mid_point{}; - s64 detection_count{}; - u64 delta_time{}; - f32 average_distance{}; - f32 angle{}; - }; - - struct GestureSharedMemory { - // This is nn::hid::detail::GestureLifo - Lifo<GestureState, hid_entry_count> gesture_lifo{}; - static_assert(sizeof(gesture_lifo) == 0x708, "gesture_lifo is an invalid size"); - INSERT_PADDING_WORDS(0x3E); - }; - static_assert(sizeof(GestureSharedMemory) == 0x800, "GestureSharedMemory is an invalid size"); - // Reads input from all available input engines void ReadTouchInput(); @@ -142,7 +74,7 @@ private: GestureProperties GetGestureProperties(); GestureState next_state{}; - GestureSharedMemory* shared_memory = nullptr; + GestureSharedMemoryFormat& shared_memory; Core::HID::EmulatedConsole* console = nullptr; std::array<Core::HID::TouchFinger, MAX_POINTS> fingers{}; diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp index ddb1b0ba4..871e5036a 100644 --- a/src/core/hle/service/hid/controllers/keyboard.cpp +++ b/src/core/hle/service/hid/controllers/keyboard.cpp @@ -1,23 +1,18 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include <cstring> -#include "common/common_types.h" #include "common/settings.h" #include "core/core_timing.h" #include "core/hid/emulated_devices.h" #include "core/hid/hid_core.h" #include "core/hle/service/hid/controllers/keyboard.h" +#include "core/hle/service/hid/controllers/shared_memory_format.h" namespace Service::HID { -constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3800; - -Keyboard::Keyboard(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) - : ControllerBase{hid_core_} { - static_assert(SHARED_MEMORY_OFFSET + sizeof(KeyboardSharedMemory) < shared_memory_size, - "KeyboardSharedMemory is bigger than the shared memory"); - shared_memory = std::construct_at( - reinterpret_cast<KeyboardSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET)); + +Keyboard::Keyboard(Core::HID::HIDCore& hid_core_, + KeyboardSharedMemoryFormat& keyboard_shared_memory) + : ControllerBase{hid_core_}, shared_memory{keyboard_shared_memory} { emulated_devices = hid_core.GetEmulatedDevices(); } @@ -29,12 +24,12 @@ void Keyboard::OnRelease() {} void Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing) { if (!IsControllerActivated()) { - shared_memory->keyboard_lifo.buffer_count = 0; - shared_memory->keyboard_lifo.buffer_tail = 0; + shared_memory.keyboard_lifo.buffer_count = 0; + shared_memory.keyboard_lifo.buffer_tail = 0; return; } - const auto& last_entry = shared_memory->keyboard_lifo.ReadCurrentEntry().state; + const auto& last_entry = shared_memory.keyboard_lifo.ReadCurrentEntry().state; next_state.sampling_number = last_entry.sampling_number + 1; if (Settings::values.keyboard_enabled) { @@ -46,7 +41,7 @@ void Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing) { next_state.attribute.is_connected.Assign(1); } - shared_memory->keyboard_lifo.WriteNextEntry(next_state); + shared_memory.keyboard_lifo.WriteNextEntry(next_state); } } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/keyboard.h b/src/core/hle/service/hid/controllers/keyboard.h index 172ec1309..4d72171b9 100644 --- a/src/core/hle/service/hid/controllers/keyboard.h +++ b/src/core/hle/service/hid/controllers/keyboard.h @@ -3,20 +3,16 @@ #pragma once -#include "common/common_types.h" #include "core/hle/service/hid/controllers/controller_base.h" -#include "core/hle/service/hid/ring_lifo.h" - -namespace Core::HID { -class EmulatedDevices; -struct KeyboardModifier; -struct KeyboardKey; -} // namespace Core::HID +#include "core/hle/service/hid/controllers/types/keyboard_types.h" namespace Service::HID { +struct KeyboardSharedMemoryFormat; + class Keyboard final : public ControllerBase { public: - explicit Keyboard(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_); + explicit Keyboard(Core::HID::HIDCore& hid_core_, + KeyboardSharedMemoryFormat& keyboard_shared_memory); ~Keyboard() override; // Called when the controller is initialized @@ -29,25 +25,8 @@ public: void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; private: - // This is nn::hid::detail::KeyboardState - struct KeyboardState { - s64 sampling_number{}; - Core::HID::KeyboardModifier modifier{}; - Core::HID::KeyboardAttribute attribute{}; - Core::HID::KeyboardKey key{}; - }; - static_assert(sizeof(KeyboardState) == 0x30, "KeyboardState is an invalid size"); - - struct KeyboardSharedMemory { - // This is nn::hid::detail::KeyboardLifo - Lifo<KeyboardState, hid_entry_count> keyboard_lifo{}; - static_assert(sizeof(keyboard_lifo) == 0x3D8, "keyboard_lifo is an invalid size"); - INSERT_PADDING_WORDS(0xA); - }; - static_assert(sizeof(KeyboardSharedMemory) == 0x400, "KeyboardSharedMemory is an invalid size"); - KeyboardState next_state{}; - KeyboardSharedMemory* shared_memory = nullptr; + KeyboardSharedMemoryFormat& shared_memory; Core::HID::EmulatedDevices* emulated_devices = nullptr; }; } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/mouse.cpp b/src/core/hle/service/hid/controllers/mouse.cpp index 6e5a04e34..de5b2c804 100644 --- a/src/core/hle/service/hid/controllers/mouse.cpp +++ b/src/core/hle/service/hid/controllers/mouse.cpp @@ -1,22 +1,17 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include <cstring> -#include "common/common_types.h" #include "core/core_timing.h" #include "core/frontend/emu_window.h" #include "core/hid/emulated_devices.h" #include "core/hid/hid_core.h" #include "core/hle/service/hid/controllers/mouse.h" +#include "core/hle/service/hid/controllers/shared_memory_format.h" namespace Service::HID { -constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3400; -Mouse::Mouse(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) : ControllerBase{hid_core_} { - static_assert(SHARED_MEMORY_OFFSET + sizeof(MouseSharedMemory) < shared_memory_size, - "MouseSharedMemory is bigger than the shared memory"); - shared_memory = std::construct_at( - reinterpret_cast<MouseSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET)); +Mouse::Mouse(Core::HID::HIDCore& hid_core_, MouseSharedMemoryFormat& mouse_shared_memory) + : ControllerBase{hid_core_}, shared_memory{mouse_shared_memory} { emulated_devices = hid_core.GetEmulatedDevices(); } @@ -27,14 +22,14 @@ void Mouse::OnRelease() {} void Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing) { if (!IsControllerActivated()) { - shared_memory->mouse_lifo.buffer_count = 0; - shared_memory->mouse_lifo.buffer_tail = 0; + shared_memory.mouse_lifo.buffer_count = 0; + shared_memory.mouse_lifo.buffer_tail = 0; return; } next_state = {}; - const auto& last_entry = shared_memory->mouse_lifo.ReadCurrentEntry().state; + const auto& last_entry = shared_memory.mouse_lifo.ReadCurrentEntry().state; next_state.sampling_number = last_entry.sampling_number + 1; if (Settings::values.mouse_enabled) { @@ -53,7 +48,7 @@ void Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing) { next_state.button = mouse_button_state; } - shared_memory->mouse_lifo.WriteNextEntry(next_state); + shared_memory.mouse_lifo.WriteNextEntry(next_state); } } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/mouse.h b/src/core/hle/service/hid/controllers/mouse.h index a80f3823f..363f316a5 100644 --- a/src/core/hle/service/hid/controllers/mouse.h +++ b/src/core/hle/service/hid/controllers/mouse.h @@ -3,9 +3,7 @@ #pragma once -#include "common/common_types.h" #include "core/hle/service/hid/controllers/controller_base.h" -#include "core/hle/service/hid/ring_lifo.h" namespace Core::HID { class EmulatedDevices; @@ -14,9 +12,11 @@ struct AnalogStickState; } // namespace Core::HID namespace Service::HID { +struct MouseSharedMemoryFormat; + class Mouse final : public ControllerBase { public: - explicit Mouse(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_); + explicit Mouse(Core::HID::HIDCore& hid_core_, MouseSharedMemoryFormat& mouse_shared_memory); ~Mouse() override; // Called when the controller is initialized @@ -29,17 +29,9 @@ public: void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; private: - struct MouseSharedMemory { - // This is nn::hid::detail::MouseLifo - Lifo<Core::HID::MouseState, hid_entry_count> mouse_lifo{}; - static_assert(sizeof(mouse_lifo) == 0x350, "mouse_lifo is an invalid size"); - INSERT_PADDING_WORDS(0x2C); - }; - static_assert(sizeof(MouseSharedMemory) == 0x400, "MouseSharedMemory is an invalid size"); - Core::HID::MouseState next_state{}; Core::HID::AnalogStickState last_mouse_wheel_state{}; - MouseSharedMemory* shared_memory = nullptr; + MouseSharedMemoryFormat& shared_memory; Core::HID::EmulatedDevices* emulated_devices = nullptr; }; } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 08ee9de9c..53a737cf5 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -17,12 +17,12 @@ #include "core/hle/kernel/k_event.h" #include "core/hle/kernel/k_readable_event.h" #include "core/hle/service/hid/controllers/npad.h" +#include "core/hle/service/hid/controllers/shared_memory_format.h" #include "core/hle/service/hid/errors.h" #include "core/hle/service/hid/hid_util.h" #include "core/hle/service/kernel_helpers.h" namespace Service::HID { -constexpr std::size_t NPAD_OFFSET = 0x9A00; constexpr std::array<Core::HID::NpadIdType, 10> npad_id_list{ Core::HID::NpadIdType::Player1, Core::HID::NpadIdType::Player2, Core::HID::NpadIdType::Player3, Core::HID::NpadIdType::Player4, Core::HID::NpadIdType::Player5, Core::HID::NpadIdType::Player6, @@ -30,14 +30,12 @@ constexpr std::array<Core::HID::NpadIdType, 10> npad_id_list{ Core::HID::NpadIdType::Handheld, }; -NPad::NPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_, +NPad::NPad(Core::HID::HIDCore& hid_core_, NpadSharedMemoryFormat& npad_shared_memory_format, KernelHelpers::ServiceContext& service_context_) : ControllerBase{hid_core_}, service_context{service_context_} { - static_assert(NPAD_OFFSET + (NPAD_COUNT * sizeof(NpadInternalState)) < shared_memory_size); for (std::size_t i = 0; i < controller_data.size(); ++i) { auto& controller = controller_data[i]; - controller.shared_memory = std::construct_at(reinterpret_cast<NpadInternalState*>( - raw_shared_memory_ + NPAD_OFFSET + (i * sizeof(NpadInternalState)))); + controller.shared_memory = &npad_shared_memory_format.npad_entry[i].internal_state; controller.device = hid_core.GetEmulatedControllerByIndex(i); controller.vibration[Core::HID::EmulatedDeviceIndex::LeftIndex].latest_vibration_value = Core::HID::DEFAULT_VIBRATION_VALUE; @@ -617,7 +615,7 @@ void NPad::SetHoldType(NpadJoyHoldType joy_hold_type) { hold_type = joy_hold_type; } -NPad::NpadJoyHoldType NPad::GetHoldType() const { +NpadJoyHoldType NPad::GetHoldType() const { return hold_type; } @@ -630,7 +628,7 @@ void NPad::SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_m handheld_activation_mode = activation_mode; } -NPad::NpadHandheldActivationMode NPad::GetNpadHandheldActivationMode() const { +NpadHandheldActivationMode NPad::GetNpadHandheldActivationMode() const { return handheld_activation_mode; } @@ -638,7 +636,7 @@ void NPad::SetNpadCommunicationMode(NpadCommunicationMode communication_mode_) { communication_mode = communication_mode_; } -NPad::NpadCommunicationMode NPad::GetNpadCommunicationMode() const { +NpadCommunicationMode NPad::GetNpadCommunicationMode() const { return communication_mode; } @@ -978,27 +976,27 @@ Result NPad::ResetIsSixAxisSensorDeviceNewlyAssigned( return ResultSuccess; } -NPad::SixAxisLifo& NPad::GetSixAxisFullkeyLifo(Core::HID::NpadIdType npad_id) { +NpadSixAxisSensorLifo& NPad::GetSixAxisFullkeyLifo(Core::HID::NpadIdType npad_id) { return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_fullkey_lifo; } -NPad::SixAxisLifo& NPad::GetSixAxisHandheldLifo(Core::HID::NpadIdType npad_id) { +NpadSixAxisSensorLifo& NPad::GetSixAxisHandheldLifo(Core::HID::NpadIdType npad_id) { return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_handheld_lifo; } -NPad::SixAxisLifo& NPad::GetSixAxisDualLeftLifo(Core::HID::NpadIdType npad_id) { +NpadSixAxisSensorLifo& NPad::GetSixAxisDualLeftLifo(Core::HID::NpadIdType npad_id) { return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_dual_left_lifo; } -NPad::SixAxisLifo& NPad::GetSixAxisDualRightLifo(Core::HID::NpadIdType npad_id) { +NpadSixAxisSensorLifo& NPad::GetSixAxisDualRightLifo(Core::HID::NpadIdType npad_id) { return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_dual_right_lifo; } -NPad::SixAxisLifo& NPad::GetSixAxisLeftLifo(Core::HID::NpadIdType npad_id) { +NpadSixAxisSensorLifo& NPad::GetSixAxisLeftLifo(Core::HID::NpadIdType npad_id) { return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_left_lifo; } -NPad::SixAxisLifo& NPad::GetSixAxisRightLifo(Core::HID::NpadIdType npad_id) { +NpadSixAxisSensorLifo& NPad::GetSixAxisRightLifo(Core::HID::NpadIdType npad_id) { return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_right_lifo; } @@ -1343,7 +1341,7 @@ const Core::HID::SixAxisSensorProperties& NPad::GetSixaxisProperties( } } -NPad::AppletDetailedUiType NPad::GetAppletDetailedUiType(Core::HID::NpadIdType npad_id) { +AppletDetailedUiType NPad::GetAppletDetailedUiType(Core::HID::NpadIdType npad_id) { const auto& shared_memory = GetControllerFromNpadIdType(npad_id).shared_memory; return { diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 9167c93f0..4e2412356 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -8,12 +8,10 @@ #include <mutex> #include <span> -#include "common/bit_field.h" #include "common/common_types.h" - #include "core/hid/hid_types.h" #include "core/hle/service/hid/controllers/controller_base.h" -#include "core/hle/service/hid/ring_lifo.h" +#include "core/hle/service/hid/controllers/types/npad_types.h" namespace Core::HID { class EmulatedController; @@ -32,10 +30,13 @@ class ServiceContext; union Result; namespace Service::HID { +struct NpadInternalState; +struct NpadSixAxisSensorLifo; +struct NpadSharedMemoryFormat; class NPad final : public ControllerBase { public: - explicit NPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_, + explicit NPad(Core::HID::HIDCore& hid_core_, NpadSharedMemoryFormat& npad_shared_memory_format, KernelHelpers::ServiceContext& service_context_); ~NPad() override; @@ -48,89 +49,6 @@ public: // When the controller is requesting an update for the shared memory void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; - // This is nn::hid::NpadJoyHoldType - enum class NpadJoyHoldType : u64 { - Vertical = 0, - Horizontal = 1, - }; - - // This is nn::hid::NpadJoyAssignmentMode - enum class NpadJoyAssignmentMode : u32 { - Dual = 0, - Single = 1, - }; - - // This is nn::hid::NpadJoyDeviceType - enum class NpadJoyDeviceType : s64 { - Left = 0, - Right = 1, - }; - - // This is nn::hid::NpadHandheldActivationMode - enum class NpadHandheldActivationMode : u64 { - Dual = 0, - Single = 1, - None = 2, - MaxActivationMode = 3, - }; - - // This is nn::hid::system::AppletFooterUiAttributesSet - struct AppletFooterUiAttributes { - INSERT_PADDING_BYTES(0x4); - }; - - // This is nn::hid::system::AppletFooterUiType - enum class AppletFooterUiType : u8 { - None = 0, - HandheldNone = 1, - HandheldJoyConLeftOnly = 2, - HandheldJoyConRightOnly = 3, - HandheldJoyConLeftJoyConRight = 4, - JoyDual = 5, - JoyDualLeftOnly = 6, - JoyDualRightOnly = 7, - JoyLeftHorizontal = 8, - JoyLeftVertical = 9, - JoyRightHorizontal = 10, - JoyRightVertical = 11, - SwitchProController = 12, - CompatibleProController = 13, - CompatibleJoyCon = 14, - LarkHvc1 = 15, - LarkHvc2 = 16, - LarkNesLeft = 17, - LarkNesRight = 18, - Lucia = 19, - Verification = 20, - Lagon = 21, - }; - - using AppletFooterUiVariant = u8; - - // This is "nn::hid::system::AppletDetailedUiType". - struct AppletDetailedUiType { - AppletFooterUiVariant ui_variant; - INSERT_PADDING_BYTES(0x2); - AppletFooterUiType footer; - }; - static_assert(sizeof(AppletDetailedUiType) == 0x4, "AppletDetailedUiType is an invalid size"); - // This is nn::hid::NpadCommunicationMode - enum class NpadCommunicationMode : u64 { - Mode_5ms = 0, - Mode_10ms = 1, - Mode_15ms = 2, - Default = 3, - }; - - enum class NpadRevision : u32 { - Revision0 = 0, - Revision1 = 1, - Revision2 = 2, - Revision3 = 3, - }; - - using SixAxisLifo = Lifo<Core::HID::SixAxisSensorState, hid_entry_count>; - void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set); Core::HID::NpadStyleTag GetSupportedStyleSet() const; @@ -188,12 +106,12 @@ public: Result ResetIsSixAxisSensorDeviceNewlyAssigned( const Core::HID::SixAxisSensorHandle& sixaxis_handle); - SixAxisLifo& GetSixAxisFullkeyLifo(Core::HID::NpadIdType npad_id); - SixAxisLifo& GetSixAxisHandheldLifo(Core::HID::NpadIdType npad_id); - SixAxisLifo& GetSixAxisDualLeftLifo(Core::HID::NpadIdType npad_id); - SixAxisLifo& GetSixAxisDualRightLifo(Core::HID::NpadIdType npad_id); - SixAxisLifo& GetSixAxisLeftLifo(Core::HID::NpadIdType npad_id); - SixAxisLifo& GetSixAxisRightLifo(Core::HID::NpadIdType npad_id); + NpadSixAxisSensorLifo& GetSixAxisFullkeyLifo(Core::HID::NpadIdType npad_id); + NpadSixAxisSensorLifo& GetSixAxisHandheldLifo(Core::HID::NpadIdType npad_id); + NpadSixAxisSensorLifo& GetSixAxisDualLeftLifo(Core::HID::NpadIdType npad_id); + NpadSixAxisSensorLifo& GetSixAxisDualRightLifo(Core::HID::NpadIdType npad_id); + NpadSixAxisSensorLifo& GetSixAxisLeftLifo(Core::HID::NpadIdType npad_id); + NpadSixAxisSensorLifo& GetSixAxisRightLifo(Core::HID::NpadIdType npad_id); Result GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const; Result IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::NpadIdType npad_id, @@ -221,214 +139,6 @@ public: AppletDetailedUiType GetAppletDetailedUiType(Core::HID::NpadIdType npad_id); private: - static constexpr std::size_t NPAD_COUNT = 10; - - // This is nn::hid::detail::ColorAttribute - enum class ColorAttribute : u32 { - Ok = 0, - ReadError = 1, - NoController = 2, - }; - static_assert(sizeof(ColorAttribute) == 4, "ColorAttribute is an invalid size"); - - // This is nn::hid::detail::NpadFullKeyColorState - struct NpadFullKeyColorState { - ColorAttribute attribute{ColorAttribute::NoController}; - Core::HID::NpadControllerColor fullkey{}; - }; - static_assert(sizeof(NpadFullKeyColorState) == 0xC, "NpadFullKeyColorState is an invalid size"); - - // This is nn::hid::detail::NpadJoyColorState - struct NpadJoyColorState { - ColorAttribute attribute{ColorAttribute::NoController}; - Core::HID::NpadControllerColor left{}; - Core::HID::NpadControllerColor right{}; - }; - static_assert(sizeof(NpadJoyColorState) == 0x14, "NpadJoyColorState is an invalid size"); - - // This is nn::hid::NpadAttribute - struct NpadAttribute { - union { - u32 raw{}; - BitField<0, 1, u32> is_connected; - BitField<1, 1, u32> is_wired; - BitField<2, 1, u32> is_left_connected; - BitField<3, 1, u32> is_left_wired; - BitField<4, 1, u32> is_right_connected; - BitField<5, 1, u32> is_right_wired; - }; - }; - static_assert(sizeof(NpadAttribute) == 4, "NpadAttribute is an invalid size"); - - // This is nn::hid::NpadFullKeyState - // This is nn::hid::NpadHandheldState - // This is nn::hid::NpadJoyDualState - // This is nn::hid::NpadJoyLeftState - // This is nn::hid::NpadJoyRightState - // This is nn::hid::NpadPalmaState - // This is nn::hid::NpadSystemExtState - struct NPadGenericState { - s64_le sampling_number{}; - Core::HID::NpadButtonState npad_buttons{}; - Core::HID::AnalogStickState l_stick{}; - Core::HID::AnalogStickState r_stick{}; - NpadAttribute connection_status{}; - INSERT_PADDING_BYTES(4); // Reserved - }; - static_assert(sizeof(NPadGenericState) == 0x28, "NPadGenericState is an invalid size"); - - // This is nn::hid::server::NpadGcTriggerState - struct NpadGcTriggerState { - s64 sampling_number{}; - s32 l_analog{}; - s32 r_analog{}; - }; - static_assert(sizeof(NpadGcTriggerState) == 0x10, "NpadGcTriggerState is an invalid size"); - - // This is nn::hid::NpadSystemProperties - struct NPadSystemProperties { - union { - s64 raw{}; - BitField<0, 1, s64> is_charging_joy_dual; - BitField<1, 1, s64> is_charging_joy_left; - BitField<2, 1, s64> is_charging_joy_right; - BitField<3, 1, s64> is_powered_joy_dual; - BitField<4, 1, s64> is_powered_joy_left; - BitField<5, 1, s64> is_powered_joy_right; - BitField<9, 1, s64> is_system_unsupported_button; - BitField<10, 1, s64> is_system_ext_unsupported_button; - BitField<11, 1, s64> is_vertical; - BitField<12, 1, s64> is_horizontal; - BitField<13, 1, s64> use_plus; - BitField<14, 1, s64> use_minus; - BitField<15, 1, s64> use_directional_buttons; - }; - }; - static_assert(sizeof(NPadSystemProperties) == 0x8, "NPadSystemProperties is an invalid size"); - - // This is nn::hid::NpadSystemButtonProperties - struct NpadSystemButtonProperties { - union { - s32 raw{}; - BitField<0, 1, s32> is_home_button_protection_enabled; - }; - }; - static_assert(sizeof(NpadSystemButtonProperties) == 0x4, - "NPadButtonProperties is an invalid size"); - - // This is nn::hid::system::DeviceType - struct DeviceType { - union { - u32 raw{}; - BitField<0, 1, s32> fullkey; - BitField<1, 1, s32> debug_pad; - BitField<2, 1, s32> handheld_left; - BitField<3, 1, s32> handheld_right; - BitField<4, 1, s32> joycon_left; - BitField<5, 1, s32> joycon_right; - BitField<6, 1, s32> palma; - BitField<7, 1, s32> lark_hvc_left; - BitField<8, 1, s32> lark_hvc_right; - BitField<9, 1, s32> lark_nes_left; - BitField<10, 1, s32> lark_nes_right; - BitField<11, 1, s32> handheld_lark_hvc_left; - BitField<12, 1, s32> handheld_lark_hvc_right; - BitField<13, 1, s32> handheld_lark_nes_left; - BitField<14, 1, s32> handheld_lark_nes_right; - BitField<15, 1, s32> lucia; - BitField<16, 1, s32> lagon; - BitField<17, 1, s32> lager; - BitField<31, 1, s32> system; - }; - }; - - // This is nn::hid::detail::NfcXcdDeviceHandleStateImpl - struct NfcXcdDeviceHandleStateImpl { - u64 handle{}; - bool is_available{}; - bool is_activated{}; - INSERT_PADDING_BYTES(0x6); // Reserved - u64 sampling_number{}; - }; - static_assert(sizeof(NfcXcdDeviceHandleStateImpl) == 0x18, - "NfcXcdDeviceHandleStateImpl is an invalid size"); - - // This is nn::hid::NpadLarkType - enum class NpadLarkType : u32 { - Invalid, - H1, - H2, - NL, - NR, - }; - - // This is nn::hid::NpadLuciaType - enum class NpadLuciaType : u32 { - Invalid, - J, - E, - U, - }; - - // This is nn::hid::NpadLagonType - enum class NpadLagonType : u32 { - Invalid, - }; - - // This is nn::hid::NpadLagerType - enum class NpadLagerType : u32 { - Invalid, - J, - E, - U, - }; - - // This is nn::hid::detail::NpadInternalState - struct NpadInternalState { - Core::HID::NpadStyleTag style_tag{Core::HID::NpadStyleSet::None}; - NpadJoyAssignmentMode assignment_mode{NpadJoyAssignmentMode::Dual}; - NpadFullKeyColorState fullkey_color{}; - NpadJoyColorState joycon_color{}; - Lifo<NPadGenericState, hid_entry_count> fullkey_lifo{}; - Lifo<NPadGenericState, hid_entry_count> handheld_lifo{}; - Lifo<NPadGenericState, hid_entry_count> joy_dual_lifo{}; - Lifo<NPadGenericState, hid_entry_count> joy_left_lifo{}; - Lifo<NPadGenericState, hid_entry_count> joy_right_lifo{}; - Lifo<NPadGenericState, hid_entry_count> palma_lifo{}; - Lifo<NPadGenericState, hid_entry_count> system_ext_lifo{}; - Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_fullkey_lifo{}; - Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_handheld_lifo{}; - Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_dual_left_lifo{}; - Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_dual_right_lifo{}; - Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_left_lifo{}; - Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_right_lifo{}; - DeviceType device_type{}; - INSERT_PADDING_BYTES(0x4); // Reserved - NPadSystemProperties system_properties{}; - NpadSystemButtonProperties button_properties{}; - Core::HID::NpadBatteryLevel battery_level_dual{}; - Core::HID::NpadBatteryLevel battery_level_left{}; - Core::HID::NpadBatteryLevel battery_level_right{}; - AppletFooterUiAttributes applet_footer_attributes{}; - AppletFooterUiType applet_footer_type{AppletFooterUiType::None}; - INSERT_PADDING_BYTES(0x5B); // Reserved - INSERT_PADDING_BYTES(0x20); // Unknown - Lifo<NpadGcTriggerState, hid_entry_count> gc_trigger_lifo{}; - NpadLarkType lark_type_l_and_main{}; - NpadLarkType lark_type_r{}; - NpadLuciaType lucia_type{}; - NpadLagonType lagon_type{}; - NpadLagerType lager_type{}; - Core::HID::SixAxisSensorProperties sixaxis_fullkey_properties; - Core::HID::SixAxisSensorProperties sixaxis_handheld_properties; - Core::HID::SixAxisSensorProperties sixaxis_dual_left_properties; - Core::HID::SixAxisSensorProperties sixaxis_dual_right_properties; - Core::HID::SixAxisSensorProperties sixaxis_left_properties; - Core::HID::SixAxisSensorProperties sixaxis_right_properties; - INSERT_PADDING_BYTES(0xc06); // Unknown - }; - static_assert(sizeof(NpadInternalState) == 0x5000, "NpadInternalState is an invalid size"); - struct VibrationData { bool device_mounted{}; Core::HID::VibrationValue latest_vibration_value{}; @@ -479,7 +189,7 @@ private: std::atomic<u64> press_state{}; - std::array<NpadControllerData, NPAD_COUNT> controller_data{}; + std::array<NpadControllerData, NpadCount> controller_data{}; KernelHelpers::ServiceContext& service_context; std::mutex mutex; std::vector<Core::HID::NpadIdType> supported_npad_id_types{}; diff --git a/src/core/hle/service/hid/controllers/palma.cpp b/src/core/hle/service/hid/controllers/palma.cpp index 588ff9d62..aa0454b5e 100644 --- a/src/core/hle/service/hid/controllers/palma.cpp +++ b/src/core/hle/service/hid/controllers/palma.cpp @@ -12,8 +12,7 @@ namespace Service::HID { -Palma::Palma(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_, - KernelHelpers::ServiceContext& service_context_) +Palma::Palma(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service_context_) : ControllerBase{hid_core_}, service_context{service_context_} { controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other); operation_complete_event = service_context.CreateEvent("hid:PalmaOperationCompleteEvent"); diff --git a/src/core/hle/service/hid/controllers/palma.h b/src/core/hle/service/hid/controllers/palma.h index a6047f36a..73884230d 100644 --- a/src/core/hle/service/hid/controllers/palma.h +++ b/src/core/hle/service/hid/controllers/palma.h @@ -97,8 +97,7 @@ public: static_assert(sizeof(PalmaConnectionHandle) == 0x8, "PalmaConnectionHandle has incorrect size."); - explicit Palma(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_, - KernelHelpers::ServiceContext& service_context_); + explicit Palma(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service_context_); ~Palma() override; // Called when the controller is initialized diff --git a/src/core/hle/service/hid/controllers/shared_memory_format.h b/src/core/hle/service/hid/controllers/shared_memory_format.h new file mode 100644 index 000000000..2986c113e --- /dev/null +++ b/src/core/hle/service/hid/controllers/shared_memory_format.h @@ -0,0 +1,240 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "common/common_funcs.h" +#include "common/common_types.h" +#include "common/vector_math.h" +#include "core/hid/hid_types.h" +#include "core/hle/service/hid//controllers/types/debug_pad_types.h" +#include "core/hle/service/hid//controllers/types/keyboard_types.h" +#include "core/hle/service/hid//controllers/types/mouse_types.h" +#include "core/hle/service/hid//controllers/types/npad_types.h" +#include "core/hle/service/hid//controllers/types/touch_types.h" +#include "core/hle/service/hid/ring_lifo.h" + +namespace Service::HID { +static const std::size_t HidEntryCount = 17; + +struct CommonHeader { + s64 timestamp{}; + s64 total_entry_count{}; + s64 last_entry_index{}; + s64 entry_count{}; +}; +static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size"); + +// This is nn::hid::detail::DebugPadSharedMemoryFormat +struct DebugPadSharedMemoryFormat { + // This is nn::hid::detail::DebugPadLifo + Lifo<DebugPadState, HidEntryCount> debug_pad_lifo{}; + static_assert(sizeof(debug_pad_lifo) == 0x2C8, "debug_pad_lifo is an invalid size"); + INSERT_PADDING_WORDS(0x4E); +}; +static_assert(sizeof(DebugPadSharedMemoryFormat) == 0x400, + "DebugPadSharedMemoryFormat is an invalid size"); + +// This is nn::hid::detail::TouchScreenSharedMemoryFormat +struct TouchScreenSharedMemoryFormat { + // This is nn::hid::detail::TouchScreenLifo + Lifo<TouchScreenState, HidEntryCount> touch_screen_lifo{}; + static_assert(sizeof(touch_screen_lifo) == 0x2C38, "touch_screen_lifo is an invalid size"); + INSERT_PADDING_WORDS(0xF2); +}; +static_assert(sizeof(TouchScreenSharedMemoryFormat) == 0x3000, + "TouchScreenSharedMemoryFormat is an invalid size"); + +// This is nn::hid::detail::MouseSharedMemoryFormat +struct MouseSharedMemoryFormat { + // This is nn::hid::detail::MouseLifo + Lifo<Core::HID::MouseState, HidEntryCount> mouse_lifo{}; + static_assert(sizeof(mouse_lifo) == 0x350, "mouse_lifo is an invalid size"); + INSERT_PADDING_WORDS(0x2C); +}; +static_assert(sizeof(MouseSharedMemoryFormat) == 0x400, + "MouseSharedMemoryFormat is an invalid size"); + +// This is nn::hid::detail::KeyboardSharedMemoryFormat +struct KeyboardSharedMemoryFormat { + // This is nn::hid::detail::KeyboardLifo + Lifo<KeyboardState, HidEntryCount> keyboard_lifo{}; + static_assert(sizeof(keyboard_lifo) == 0x3D8, "keyboard_lifo is an invalid size"); + INSERT_PADDING_WORDS(0xA); +}; +static_assert(sizeof(KeyboardSharedMemoryFormat) == 0x400, + "KeyboardSharedMemoryFormat is an invalid size"); + +// This is nn::hid::detail::DigitizerSharedMemoryFormat +struct DigitizerSharedMemoryFormat { + CommonHeader header; + INSERT_PADDING_BYTES(0xFE0); +}; +static_assert(sizeof(DigitizerSharedMemoryFormat) == 0x1000, + "DigitizerSharedMemoryFormat is an invalid size"); + +// This is nn::hid::detail::HomeButtonSharedMemoryFormat +struct HomeButtonSharedMemoryFormat { + CommonHeader header; + INSERT_PADDING_BYTES(0x1E0); +}; +static_assert(sizeof(HomeButtonSharedMemoryFormat) == 0x200, + "HomeButtonSharedMemoryFormat is an invalid size"); + +// This is nn::hid::detail::SleepButtonSharedMemoryFormat +struct SleepButtonSharedMemoryFormat { + CommonHeader header; + INSERT_PADDING_BYTES(0x1E0); +}; +static_assert(sizeof(SleepButtonSharedMemoryFormat) == 0x200, + "SleepButtonSharedMemoryFormat is an invalid size"); + +// This is nn::hid::detail::CaptureButtonSharedMemoryFormat +struct CaptureButtonSharedMemoryFormat { + CommonHeader header; + INSERT_PADDING_BYTES(0x1E0); +}; +static_assert(sizeof(CaptureButtonSharedMemoryFormat) == 0x200, + "CaptureButtonSharedMemoryFormat is an invalid size"); + +// This is nn::hid::detail::InputDetectorSharedMemoryFormat +struct InputDetectorSharedMemoryFormat { + CommonHeader header; + INSERT_PADDING_BYTES(0x7E0); +}; +static_assert(sizeof(InputDetectorSharedMemoryFormat) == 0x800, + "InputDetectorSharedMemoryFormat is an invalid size"); + +// This is nn::hid::detail::UniquePadSharedMemoryFormat +struct UniquePadSharedMemoryFormat { + CommonHeader header; + INSERT_PADDING_BYTES(0x3FE0); +}; +static_assert(sizeof(UniquePadSharedMemoryFormat) == 0x4000, + "UniquePadSharedMemoryFormat is an invalid size"); + +// This is nn::hid::detail::NpadSixAxisSensorLifo +struct NpadSixAxisSensorLifo { + Lifo<Core::HID::SixAxisSensorState, HidEntryCount> lifo; +}; + +// This is nn::hid::detail::NpadInternalState +struct NpadInternalState { + Core::HID::NpadStyleTag style_tag{Core::HID::NpadStyleSet::None}; + NpadJoyAssignmentMode assignment_mode{NpadJoyAssignmentMode::Dual}; + NpadFullKeyColorState fullkey_color{}; + NpadJoyColorState joycon_color{}; + Lifo<NPadGenericState, HidEntryCount> fullkey_lifo{}; + Lifo<NPadGenericState, HidEntryCount> handheld_lifo{}; + Lifo<NPadGenericState, HidEntryCount> joy_dual_lifo{}; + Lifo<NPadGenericState, HidEntryCount> joy_left_lifo{}; + Lifo<NPadGenericState, HidEntryCount> joy_right_lifo{}; + Lifo<NPadGenericState, HidEntryCount> palma_lifo{}; + Lifo<NPadGenericState, HidEntryCount> system_ext_lifo{}; + NpadSixAxisSensorLifo sixaxis_fullkey_lifo{}; + NpadSixAxisSensorLifo sixaxis_handheld_lifo{}; + NpadSixAxisSensorLifo sixaxis_dual_left_lifo{}; + NpadSixAxisSensorLifo sixaxis_dual_right_lifo{}; + NpadSixAxisSensorLifo sixaxis_left_lifo{}; + NpadSixAxisSensorLifo sixaxis_right_lifo{}; + DeviceType device_type{}; + INSERT_PADDING_BYTES(0x4); // Reserved + NPadSystemProperties system_properties{}; + NpadSystemButtonProperties button_properties{}; + Core::HID::NpadBatteryLevel battery_level_dual{}; + Core::HID::NpadBatteryLevel battery_level_left{}; + Core::HID::NpadBatteryLevel battery_level_right{}; + AppletFooterUiAttributes applet_footer_attributes{}; + AppletFooterUiType applet_footer_type{AppletFooterUiType::None}; + INSERT_PADDING_BYTES(0x5B); // Reserved + INSERT_PADDING_BYTES(0x20); // Unknown + Lifo<NpadGcTriggerState, HidEntryCount> gc_trigger_lifo{}; + NpadLarkType lark_type_l_and_main{}; + NpadLarkType lark_type_r{}; + NpadLuciaType lucia_type{}; + NpadLagerType lager_type{}; + Core::HID::SixAxisSensorProperties sixaxis_fullkey_properties; + Core::HID::SixAxisSensorProperties sixaxis_handheld_properties; + Core::HID::SixAxisSensorProperties sixaxis_dual_left_properties; + Core::HID::SixAxisSensorProperties sixaxis_dual_right_properties; + Core::HID::SixAxisSensorProperties sixaxis_left_properties; + Core::HID::SixAxisSensorProperties sixaxis_right_properties; +}; +static_assert(sizeof(NpadInternalState) == 0x43F8, "NpadInternalState is an invalid size"); + +// This is nn::hid::detail::NpadSharedMemoryEntry +struct NpadSharedMemoryEntry { + NpadInternalState internal_state; + INSERT_PADDING_BYTES(0xC08); +}; +static_assert(sizeof(NpadSharedMemoryEntry) == 0x5000, "NpadSharedMemoryEntry is an invalid size"); + +// This is nn::hid::detail::NpadSharedMemoryFormat +struct NpadSharedMemoryFormat { + std::array<NpadSharedMemoryEntry, NpadCount> npad_entry; +}; +static_assert(sizeof(NpadSharedMemoryFormat) == 0x32000, + "NpadSharedMemoryFormat is an invalid size"); + +// This is nn::hid::detail::GestureSharedMemoryFormat +struct GestureSharedMemoryFormat { + // This is nn::hid::detail::GestureLifo + Lifo<GestureState, HidEntryCount> gesture_lifo{}; + static_assert(sizeof(gesture_lifo) == 0x708, "gesture_lifo is an invalid size"); + INSERT_PADDING_WORDS(0x3E); +}; +static_assert(sizeof(GestureSharedMemoryFormat) == 0x800, + "GestureSharedMemoryFormat is an invalid size"); + +// This is nn::hid::detail::ConsoleSixAxisSensorSharedMemoryFormat +struct ConsoleSixAxisSensorSharedMemoryFormat { + u64 sampling_number{}; + bool is_seven_six_axis_sensor_at_rest{}; + INSERT_PADDING_BYTES(3); // padding + f32 verticalization_error{}; + Common::Vec3f gyro_bias{}; + INSERT_PADDING_BYTES(4); // padding +}; +static_assert(sizeof(ConsoleSixAxisSensorSharedMemoryFormat) == 0x20, + "ConsoleSixAxisSensorSharedMemoryFormat is an invalid size"); + +// This is nn::hid::detail::SharedMemoryFormat +struct SharedMemoryFormat { + void Initialize() {} + + DebugPadSharedMemoryFormat debug_pad; + TouchScreenSharedMemoryFormat touch_screen; + MouseSharedMemoryFormat mouse; + KeyboardSharedMemoryFormat keyboard; + DigitizerSharedMemoryFormat digitizer; + HomeButtonSharedMemoryFormat home_button; + SleepButtonSharedMemoryFormat sleep_button; + CaptureButtonSharedMemoryFormat capture_button; + InputDetectorSharedMemoryFormat input_detector; + UniquePadSharedMemoryFormat unique_pad; + NpadSharedMemoryFormat npad; + GestureSharedMemoryFormat gesture; + ConsoleSixAxisSensorSharedMemoryFormat console; + INSERT_PADDING_BYTES(0x19E0); + MouseSharedMemoryFormat debug_mouse; + INSERT_PADDING_BYTES(0x2000); +}; +static_assert(offsetof(SharedMemoryFormat, debug_pad) == 0x0, "debug_pad has wrong offset"); +static_assert(offsetof(SharedMemoryFormat, touch_screen) == 0x400, "touch_screen has wrong offset"); +static_assert(offsetof(SharedMemoryFormat, mouse) == 0x3400, "mouse has wrong offset"); +static_assert(offsetof(SharedMemoryFormat, keyboard) == 0x3800, "keyboard has wrong offset"); +static_assert(offsetof(SharedMemoryFormat, digitizer) == 0x3C00, "digitizer has wrong offset"); +static_assert(offsetof(SharedMemoryFormat, home_button) == 0x4C00, "home_button has wrong offset"); +static_assert(offsetof(SharedMemoryFormat, sleep_button) == 0x4E00, + "sleep_button has wrong offset"); +static_assert(offsetof(SharedMemoryFormat, capture_button) == 0x5000, + "capture_button has wrong offset"); +static_assert(offsetof(SharedMemoryFormat, input_detector) == 0x5200, + "input_detector has wrong offset"); +static_assert(offsetof(SharedMemoryFormat, npad) == 0x9A00, "npad has wrong offset"); +static_assert(offsetof(SharedMemoryFormat, gesture) == 0x3BA00, "gesture has wrong offset"); +static_assert(offsetof(SharedMemoryFormat, console) == 0x3C200, "console has wrong offset"); +static_assert(offsetof(SharedMemoryFormat, debug_mouse) == 0x3DC00, "debug_mouse has wrong offset"); +static_assert(sizeof(SharedMemoryFormat) == 0x40000, "SharedMemoryFormat is an invalid size"); + +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/shared_memory_holder.cpp b/src/core/hle/service/hid/controllers/shared_memory_holder.cpp new file mode 100644 index 000000000..51581188e --- /dev/null +++ b/src/core/hle/service/hid/controllers/shared_memory_holder.cpp @@ -0,0 +1,53 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "core/core.h" +#include "core/hle/kernel/k_shared_memory.h" +#include "core/hle/service/hid/controllers/shared_memory_format.h" +#include "core/hle/service/hid/controllers/shared_memory_holder.h" +#include "core/hle/service/hid/errors.h" + +namespace Service::HID { +SharedMemoryHolder::SharedMemoryHolder() {} + +SharedMemoryHolder::~SharedMemoryHolder() { + Finalize(); +} + +Result SharedMemoryHolder::Initialize(Core::System& system) { + shared_memory = Kernel::KSharedMemory::Create(system.Kernel()); + const Result result = shared_memory->Initialize( + system.DeviceMemory(), nullptr, Kernel::Svc::MemoryPermission::None, + Kernel::Svc::MemoryPermission::Read, sizeof(SharedMemoryFormat)); + if (result.IsError()) { + return result; + } + Kernel::KSharedMemory::Register(system.Kernel(), shared_memory); + + is_created = true; + is_mapped = true; + address = std::construct_at(reinterpret_cast<SharedMemoryFormat*>(shared_memory->GetPointer())); + return ResultSuccess; +} + +void SharedMemoryHolder::Finalize() { + if (address != nullptr) { + shared_memory->Close(); + } + is_created = false; + is_mapped = false; + address = nullptr; +} + +bool SharedMemoryHolder::IsMapped() { + return is_mapped; +} + +SharedMemoryFormat* SharedMemoryHolder::GetAddress() { + return address; +} + +Kernel::KSharedMemory* SharedMemoryHolder::GetHandle() { + return shared_memory; +} +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/shared_memory_holder.h b/src/core/hle/service/hid/controllers/shared_memory_holder.h new file mode 100644 index 000000000..943407c00 --- /dev/null +++ b/src/core/hle/service/hid/controllers/shared_memory_holder.h @@ -0,0 +1,44 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "core/hle/result.h" + +namespace Core { +class System; +} + +namespace Kernel { +class KSharedMemory; +} + +namespace Service::HID { +struct SharedMemoryFormat; + +// This is nn::hid::detail::SharedMemoryHolder +class SharedMemoryHolder { +public: + SharedMemoryHolder(); + ~SharedMemoryHolder(); + + Result Initialize(Core::System& system); + void Finalize(); + + bool IsMapped(); + SharedMemoryFormat* GetAddress(); + Kernel::KSharedMemory* GetHandle(); + +private: + bool is_owner{}; + bool is_created{}; + bool is_mapped{}; + INSERT_PADDING_BYTES(0x5); + Kernel::KSharedMemory* shared_memory; + INSERT_PADDING_BYTES(0x38); + SharedMemoryFormat* address = nullptr; +}; +// Correct size is 0x50 bytes +static_assert(sizeof(SharedMemoryHolder) == 0x50, "SharedMemoryHolder is an invalid size"); + +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/six_axis.cpp b/src/core/hle/service/hid/controllers/six_axis.cpp index 3d24a5c04..36b72f9ea 100644 --- a/src/core/hle/service/hid/controllers/six_axis.cpp +++ b/src/core/hle/service/hid/controllers/six_axis.cpp @@ -6,6 +6,7 @@ #include "core/hid/emulated_controller.h" #include "core/hid/hid_core.h" #include "core/hle/service/hid/controllers/npad.h" +#include "core/hle/service/hid/controllers/shared_memory_format.h" #include "core/hle/service/hid/controllers/six_axis.h" #include "core/hle/service/hid/errors.h" #include "core/hle/service/hid/hid_util.h" @@ -132,30 +133,30 @@ void SixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) { } sixaxis_fullkey_state.sampling_number = - sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; + sixaxis_fullkey_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1; sixaxis_handheld_state.sampling_number = - sixaxis_handheld_lifo.ReadCurrentEntry().state.sampling_number + 1; + sixaxis_handheld_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1; sixaxis_dual_left_state.sampling_number = - sixaxis_dual_left_lifo.ReadCurrentEntry().state.sampling_number + 1; + sixaxis_dual_left_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1; sixaxis_dual_right_state.sampling_number = - sixaxis_dual_right_lifo.ReadCurrentEntry().state.sampling_number + 1; + sixaxis_dual_right_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1; sixaxis_left_lifo_state.sampling_number = - sixaxis_left_lifo.ReadCurrentEntry().state.sampling_number + 1; + sixaxis_left_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1; sixaxis_right_lifo_state.sampling_number = - sixaxis_right_lifo.ReadCurrentEntry().state.sampling_number + 1; + sixaxis_right_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1; if (IndexToNpadIdType(i) == Core::HID::NpadIdType::Handheld) { // This buffer only is updated on handheld on HW - sixaxis_handheld_lifo.WriteNextEntry(sixaxis_handheld_state); + sixaxis_handheld_lifo.lifo.WriteNextEntry(sixaxis_handheld_state); } else { // Handheld doesn't update this buffer on HW - sixaxis_fullkey_lifo.WriteNextEntry(sixaxis_fullkey_state); + sixaxis_fullkey_lifo.lifo.WriteNextEntry(sixaxis_fullkey_state); } - sixaxis_dual_left_lifo.WriteNextEntry(sixaxis_dual_left_state); - sixaxis_dual_right_lifo.WriteNextEntry(sixaxis_dual_right_state); - sixaxis_left_lifo.WriteNextEntry(sixaxis_left_lifo_state); - sixaxis_right_lifo.WriteNextEntry(sixaxis_right_lifo_state); + sixaxis_dual_left_lifo.lifo.WriteNextEntry(sixaxis_dual_left_state); + sixaxis_dual_right_lifo.lifo.WriteNextEntry(sixaxis_dual_right_state); + sixaxis_left_lifo.lifo.WriteNextEntry(sixaxis_left_lifo_state); + sixaxis_right_lifo.lifo.WriteNextEntry(sixaxis_right_lifo_state); } } diff --git a/src/core/hle/service/hid/controllers/stubbed.cpp b/src/core/hle/service/hid/controllers/stubbed.cpp index 9e2f3ab21..e2a5f5d79 100644 --- a/src/core/hle/service/hid/controllers/stubbed.cpp +++ b/src/core/hle/service/hid/controllers/stubbed.cpp @@ -1,18 +1,15 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include <cstring> -#include "common/common_types.h" #include "core/core_timing.h" -#include "core/hid/hid_core.h" +#include "core/hle/service/hid/controllers/shared_memory_format.h" #include "core/hle/service/hid/controllers/stubbed.h" namespace Service::HID { -Controller_Stubbed::Controller_Stubbed(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) - : ControllerBase{hid_core_} { - raw_shared_memory = raw_shared_memory_; -} +Controller_Stubbed::Controller_Stubbed(Core::HID::HIDCore& hid_core_, + CommonHeader& ring_lifo_header) + : ControllerBase{hid_core_}, header{ring_lifo_header} {} Controller_Stubbed::~Controller_Stubbed() = default; @@ -25,18 +22,10 @@ void Controller_Stubbed::OnUpdate(const Core::Timing::CoreTiming& core_timing) { return; } - CommonHeader header{}; header.timestamp = core_timing.GetGlobalTimeNs().count(); header.total_entry_count = 17; header.entry_count = 0; header.last_entry_index = 0; - - std::memcpy(raw_shared_memory + common_offset, &header, sizeof(CommonHeader)); -} - -void Controller_Stubbed::SetCommonHeaderOffset(std::size_t off) { - common_offset = off; - smart_update = true; } } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/stubbed.h b/src/core/hle/service/hid/controllers/stubbed.h index 1483a968e..d2052fb17 100644 --- a/src/core/hle/service/hid/controllers/stubbed.h +++ b/src/core/hle/service/hid/controllers/stubbed.h @@ -3,13 +3,14 @@ #pragma once -#include "common/common_types.h" #include "core/hle/service/hid/controllers/controller_base.h" namespace Service::HID { +struct CommonHeader; + class Controller_Stubbed final : public ControllerBase { public: - explicit Controller_Stubbed(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_); + explicit Controller_Stubbed(Core::HID::HIDCore& hid_core_, CommonHeader& ring_lifo_header); ~Controller_Stubbed() override; // Called when the controller is initialized @@ -21,19 +22,8 @@ public: // When the controller is requesting an update for the shared memory void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; - void SetCommonHeaderOffset(std::size_t off); - private: - struct CommonHeader { - s64 timestamp{}; - s64 total_entry_count{}; - s64 last_entry_index{}; - s64 entry_count{}; - }; - static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size"); - - u8* raw_shared_memory = nullptr; + CommonHeader& header; bool smart_update{}; - std::size_t common_offset{}; }; } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp index fcd973414..469750006 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.cpp +++ b/src/core/hle/service/hid/controllers/touchscreen.cpp @@ -2,26 +2,22 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include <algorithm> -#include <cstring> #include "common/common_types.h" #include "common/settings.h" -#include "core/core.h" #include "core/core_timing.h" #include "core/frontend/emu_window.h" #include "core/hid/emulated_console.h" #include "core/hid/hid_core.h" +#include "core/hle/service/hid/controllers/shared_memory_format.h" #include "core/hle/service/hid/controllers/touchscreen.h" namespace Service::HID { -constexpr std::size_t SHARED_MEMORY_OFFSET = 0x400; -TouchScreen::TouchScreen(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) - : ControllerBase{hid_core_}, touchscreen_width(Layout::ScreenUndocked::Width), +TouchScreen::TouchScreen(Core::HID::HIDCore& hid_core_, + TouchScreenSharedMemoryFormat& touch_shared_memory) + : ControllerBase{hid_core_}, shared_memory{touch_shared_memory}, + touchscreen_width(Layout::ScreenUndocked::Width), touchscreen_height(Layout::ScreenUndocked::Height) { - static_assert(SHARED_MEMORY_OFFSET + sizeof(TouchSharedMemory) < shared_memory_size, - "TouchSharedMemory is bigger than the shared memory"); - shared_memory = std::construct_at( - reinterpret_cast<TouchSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET)); console = hid_core.GetEmulatedConsole(); } @@ -32,11 +28,11 @@ void TouchScreen::OnInit() {} void TouchScreen::OnRelease() {} void TouchScreen::OnUpdate(const Core::Timing::CoreTiming& core_timing) { - shared_memory->touch_screen_lifo.timestamp = core_timing.GetGlobalTimeNs().count(); + shared_memory.touch_screen_lifo.timestamp = core_timing.GetGlobalTimeNs().count(); if (!IsControllerActivated()) { - shared_memory->touch_screen_lifo.buffer_count = 0; - shared_memory->touch_screen_lifo.buffer_tail = 0; + shared_memory.touch_screen_lifo.buffer_count = 0; + shared_memory.touch_screen_lifo.buffer_tail = 0; return; } @@ -86,7 +82,7 @@ void TouchScreen::OnUpdate(const Core::Timing::CoreTiming& core_timing) { static_cast<std::size_t>(std::distance(active_fingers.begin(), end_iter)); const u64 timestamp = static_cast<u64>(core_timing.GetGlobalTimeNs().count()); - const auto& last_entry = shared_memory->touch_screen_lifo.ReadCurrentEntry().state; + const auto& last_entry = shared_memory.touch_screen_lifo.ReadCurrentEntry().state; next_state.sampling_number = last_entry.sampling_number + 1; next_state.entry_count = static_cast<s32>(active_fingers_count); @@ -118,7 +114,7 @@ void TouchScreen::OnUpdate(const Core::Timing::CoreTiming& core_timing) { } } - shared_memory->touch_screen_lifo.WriteNextEntry(next_state); + shared_memory.touch_screen_lifo.WriteNextEntry(next_state); } void TouchScreen::SetTouchscreenDimensions(u32 width, u32 height) { diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h index 79f026a81..5b6305bfc 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.h +++ b/src/core/hle/service/hid/controllers/touchscreen.h @@ -3,20 +3,23 @@ #pragma once -#include "common/common_funcs.h" -#include "common/common_types.h" +#include <array> + #include "core/hid/hid_types.h" #include "core/hle/service/hid/controllers/controller_base.h" -#include "core/hle/service/hid/ring_lifo.h" +#include "core/hle/service/hid/controllers/types/touch_types.h" namespace Core::HID { class EmulatedConsole; } // namespace Core::HID namespace Service::HID { +struct TouchScreenSharedMemoryFormat; + class TouchScreen final : public ControllerBase { public: - explicit TouchScreen(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_); + explicit TouchScreen(Core::HID::HIDCore& hid_core_, + TouchScreenSharedMemoryFormat& touch_shared_memory); ~TouchScreen() override; // Called when the controller is initialized @@ -31,27 +34,8 @@ public: void SetTouchscreenDimensions(u32 width, u32 height); private: - static constexpr std::size_t MAX_FINGERS = 16; - - // This is nn::hid::TouchScreenState - struct TouchScreenState { - s64 sampling_number{}; - s32 entry_count{}; - INSERT_PADDING_BYTES(4); // Reserved - std::array<Core::HID::TouchState, MAX_FINGERS> states{}; - }; - static_assert(sizeof(TouchScreenState) == 0x290, "TouchScreenState is an invalid size"); - - struct TouchSharedMemory { - // This is nn::hid::detail::TouchScreenLifo - Lifo<TouchScreenState, hid_entry_count> touch_screen_lifo{}; - static_assert(sizeof(touch_screen_lifo) == 0x2C38, "touch_screen_lifo is an invalid size"); - INSERT_PADDING_WORDS(0xF2); - }; - static_assert(sizeof(TouchSharedMemory) == 0x3000, "TouchSharedMemory is an invalid size"); - TouchScreenState next_state{}; - TouchSharedMemory* shared_memory = nullptr; + TouchScreenSharedMemoryFormat& shared_memory; Core::HID::EmulatedConsole* console = nullptr; std::array<Core::HID::TouchFinger, MAX_FINGERS> fingers{}; diff --git a/src/core/hle/service/hid/controllers/types/debug_pad_types.h b/src/core/hle/service/hid/controllers/types/debug_pad_types.h new file mode 100644 index 000000000..a96171b62 --- /dev/null +++ b/src/core/hle/service/hid/controllers/types/debug_pad_types.h @@ -0,0 +1,31 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "common/bit_field.h" +#include "common/common_types.h" +#include "core/hid/hid_types.h" + +namespace Service::HID { + +// This is nn::hid::DebugPadAttribute +struct DebugPadAttribute { + union { + u32 raw{}; + BitField<0, 1, u32> connected; + }; +}; +static_assert(sizeof(DebugPadAttribute) == 0x4, "DebugPadAttribute is an invalid size"); + +// This is nn::hid::DebugPadState +struct DebugPadState { + s64 sampling_number{}; + DebugPadAttribute attribute{}; + Core::HID::DebugPadButton pad_state{}; + Core::HID::AnalogStickState r_stick{}; + Core::HID::AnalogStickState l_stick{}; +}; +static_assert(sizeof(DebugPadState) == 0x20, "DebugPadState is an invalid state"); + +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/types/gesture_types.h b/src/core/hle/service/hid/controllers/types/gesture_types.h new file mode 100644 index 000000000..b4f034cd3 --- /dev/null +++ b/src/core/hle/service/hid/controllers/types/gesture_types.h @@ -0,0 +1,77 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include <array> +#include "common/bit_field.h" +#include "common/common_types.h" +#include "common/point.h" + +namespace Service::HID { +static constexpr size_t MAX_FINGERS = 16; +static constexpr size_t MAX_POINTS = 4; + +// This is nn::hid::GestureType +enum class GestureType : u32 { + Idle, // Nothing touching the screen + Complete, // Set at the end of a touch event + Cancel, // Set when the number of fingers change + Touch, // A finger just touched the screen + Press, // Set if last type is touch and the finger hasn't moved + Tap, // Fast press then release + Pan, // All points moving together across the screen + Swipe, // Fast press movement and release of a single point + Pinch, // All points moving away/closer to the midpoint + Rotate, // All points rotating from the midpoint +}; + +// This is nn::hid::GestureDirection +enum class GestureDirection : u32 { + None, + Left, + Up, + Right, + Down, +}; + +// This is nn::hid::GestureAttribute +struct GestureAttribute { + union { + u32 raw{}; + + BitField<4, 1, u32> is_new_touch; + BitField<8, 1, u32> is_double_tap; + }; +}; +static_assert(sizeof(GestureAttribute) == 4, "GestureAttribute is an invalid size"); + +// This is nn::hid::GestureState +struct GestureState { + s64 sampling_number{}; + s64 detection_count{}; + GestureType type{GestureType::Idle}; + GestureDirection direction{GestureDirection::None}; + Common::Point<s32> pos{}; + Common::Point<s32> delta{}; + f32 vel_x{}; + f32 vel_y{}; + GestureAttribute attributes{}; + f32 scale{}; + f32 rotation_angle{}; + s32 point_count{}; + std::array<Common::Point<s32>, 4> points{}; +}; +static_assert(sizeof(GestureState) == 0x60, "GestureState is an invalid size"); + +struct GestureProperties { + std::array<Common::Point<s32>, MAX_POINTS> points{}; + std::size_t active_points{}; + Common::Point<s32> mid_point{}; + s64 detection_count{}; + u64 delta_time{}; + f32 average_distance{}; + f32 angle{}; +}; + +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/types/keyboard_types.h b/src/core/hle/service/hid/controllers/types/keyboard_types.h new file mode 100644 index 000000000..f44a536b9 --- /dev/null +++ b/src/core/hle/service/hid/controllers/types/keyboard_types.h @@ -0,0 +1,20 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "common/common_types.h" +#include "core/hid/hid_types.h" + +namespace Service::HID { + +// This is nn::hid::detail::KeyboardState +struct KeyboardState { + s64 sampling_number{}; + Core::HID::KeyboardModifier modifier{}; + Core::HID::KeyboardAttribute attribute{}; + Core::HID::KeyboardKey key{}; +}; +static_assert(sizeof(KeyboardState) == 0x30, "KeyboardState is an invalid size"); + +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/types/mouse_types.h b/src/core/hle/service/hid/controllers/types/mouse_types.h new file mode 100644 index 000000000..8bd6e167c --- /dev/null +++ b/src/core/hle/service/hid/controllers/types/mouse_types.h @@ -0,0 +1,8 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "common/common_types.h" + +namespace Service::HID {} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/types/npad_types.h b/src/core/hle/service/hid/controllers/types/npad_types.h new file mode 100644 index 000000000..a5ce2562b --- /dev/null +++ b/src/core/hle/service/hid/controllers/types/npad_types.h @@ -0,0 +1,254 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "common/bit_field.h" +#include "common/common_funcs.h" +#include "common/common_types.h" +#include "core/hid/hid_types.h" + +namespace Service::HID { +static constexpr std::size_t NpadCount = 10; + +// This is nn::hid::NpadJoyHoldType +enum class NpadJoyHoldType : u64 { + Vertical = 0, + Horizontal = 1, +}; + +// This is nn::hid::NpadJoyAssignmentMode +enum class NpadJoyAssignmentMode : u32 { + Dual = 0, + Single = 1, +}; + +// This is nn::hid::NpadJoyDeviceType +enum class NpadJoyDeviceType : s64 { + Left = 0, + Right = 1, +}; + +// This is nn::hid::NpadHandheldActivationMode +enum class NpadHandheldActivationMode : u64 { + Dual = 0, + Single = 1, + None = 2, + MaxActivationMode = 3, +}; + +// This is nn::hid::system::AppletFooterUiAttributesSet +struct AppletFooterUiAttributes { + INSERT_PADDING_BYTES(0x4); +}; + +// This is nn::hid::system::AppletFooterUiType +enum class AppletFooterUiType : u8 { + None = 0, + HandheldNone = 1, + HandheldJoyConLeftOnly = 2, + HandheldJoyConRightOnly = 3, + HandheldJoyConLeftJoyConRight = 4, + JoyDual = 5, + JoyDualLeftOnly = 6, + JoyDualRightOnly = 7, + JoyLeftHorizontal = 8, + JoyLeftVertical = 9, + JoyRightHorizontal = 10, + JoyRightVertical = 11, + SwitchProController = 12, + CompatibleProController = 13, + CompatibleJoyCon = 14, + LarkHvc1 = 15, + LarkHvc2 = 16, + LarkNesLeft = 17, + LarkNesRight = 18, + Lucia = 19, + Verification = 20, + Lagon = 21, +}; + +using AppletFooterUiVariant = u8; + +// This is "nn::hid::system::AppletDetailedUiType". +struct AppletDetailedUiType { + AppletFooterUiVariant ui_variant; + INSERT_PADDING_BYTES(0x2); + AppletFooterUiType footer; +}; +static_assert(sizeof(AppletDetailedUiType) == 0x4, "AppletDetailedUiType is an invalid size"); +// This is nn::hid::NpadCommunicationMode +enum class NpadCommunicationMode : u64 { + Mode_5ms = 0, + Mode_10ms = 1, + Mode_15ms = 2, + Default = 3, +}; + +enum class NpadRevision : u32 { + Revision0 = 0, + Revision1 = 1, + Revision2 = 2, + Revision3 = 3, +}; + +// This is nn::hid::detail::ColorAttribute +enum class ColorAttribute : u32 { + Ok = 0, + ReadError = 1, + NoController = 2, +}; +static_assert(sizeof(ColorAttribute) == 4, "ColorAttribute is an invalid size"); + +// This is nn::hid::detail::NpadFullKeyColorState +struct NpadFullKeyColorState { + ColorAttribute attribute{ColorAttribute::NoController}; + Core::HID::NpadControllerColor fullkey{}; +}; +static_assert(sizeof(NpadFullKeyColorState) == 0xC, "NpadFullKeyColorState is an invalid size"); + +// This is nn::hid::detail::NpadJoyColorState +struct NpadJoyColorState { + ColorAttribute attribute{ColorAttribute::NoController}; + Core::HID::NpadControllerColor left{}; + Core::HID::NpadControllerColor right{}; +}; +static_assert(sizeof(NpadJoyColorState) == 0x14, "NpadJoyColorState is an invalid size"); + +// This is nn::hid::NpadAttribute +struct NpadAttribute { + union { + u32 raw{}; + BitField<0, 1, u32> is_connected; + BitField<1, 1, u32> is_wired; + BitField<2, 1, u32> is_left_connected; + BitField<3, 1, u32> is_left_wired; + BitField<4, 1, u32> is_right_connected; + BitField<5, 1, u32> is_right_wired; + }; +}; +static_assert(sizeof(NpadAttribute) == 4, "NpadAttribute is an invalid size"); + +// This is nn::hid::NpadFullKeyState +// This is nn::hid::NpadHandheldState +// This is nn::hid::NpadJoyDualState +// This is nn::hid::NpadJoyLeftState +// This is nn::hid::NpadJoyRightState +// This is nn::hid::NpadPalmaState +// This is nn::hid::NpadSystemExtState +struct NPadGenericState { + s64_le sampling_number{}; + Core::HID::NpadButtonState npad_buttons{}; + Core::HID::AnalogStickState l_stick{}; + Core::HID::AnalogStickState r_stick{}; + NpadAttribute connection_status{}; + INSERT_PADDING_BYTES(4); // Reserved +}; +static_assert(sizeof(NPadGenericState) == 0x28, "NPadGenericState is an invalid size"); + +// This is nn::hid::server::NpadGcTriggerState +struct NpadGcTriggerState { + s64 sampling_number{}; + s32 l_analog{}; + s32 r_analog{}; +}; +static_assert(sizeof(NpadGcTriggerState) == 0x10, "NpadGcTriggerState is an invalid size"); + +// This is nn::hid::NpadSystemProperties +struct NPadSystemProperties { + union { + s64 raw{}; + BitField<0, 1, s64> is_charging_joy_dual; + BitField<1, 1, s64> is_charging_joy_left; + BitField<2, 1, s64> is_charging_joy_right; + BitField<3, 1, s64> is_powered_joy_dual; + BitField<4, 1, s64> is_powered_joy_left; + BitField<5, 1, s64> is_powered_joy_right; + BitField<9, 1, s64> is_system_unsupported_button; + BitField<10, 1, s64> is_system_ext_unsupported_button; + BitField<11, 1, s64> is_vertical; + BitField<12, 1, s64> is_horizontal; + BitField<13, 1, s64> use_plus; + BitField<14, 1, s64> use_minus; + BitField<15, 1, s64> use_directional_buttons; + }; +}; +static_assert(sizeof(NPadSystemProperties) == 0x8, "NPadSystemProperties is an invalid size"); + +// This is nn::hid::NpadSystemButtonProperties +struct NpadSystemButtonProperties { + union { + s32 raw{}; + BitField<0, 1, s32> is_home_button_protection_enabled; + }; +}; +static_assert(sizeof(NpadSystemButtonProperties) == 0x4, "NPadButtonProperties is an invalid size"); + +// This is nn::hid::system::DeviceType +struct DeviceType { + union { + u32 raw{}; + BitField<0, 1, s32> fullkey; + BitField<1, 1, s32> debug_pad; + BitField<2, 1, s32> handheld_left; + BitField<3, 1, s32> handheld_right; + BitField<4, 1, s32> joycon_left; + BitField<5, 1, s32> joycon_right; + BitField<6, 1, s32> palma; + BitField<7, 1, s32> lark_hvc_left; + BitField<8, 1, s32> lark_hvc_right; + BitField<9, 1, s32> lark_nes_left; + BitField<10, 1, s32> lark_nes_right; + BitField<11, 1, s32> handheld_lark_hvc_left; + BitField<12, 1, s32> handheld_lark_hvc_right; + BitField<13, 1, s32> handheld_lark_nes_left; + BitField<14, 1, s32> handheld_lark_nes_right; + BitField<15, 1, s32> lucia; + BitField<16, 1, s32> lagon; + BitField<17, 1, s32> lager; + BitField<31, 1, s32> system; + }; +}; + +// This is nn::hid::detail::NfcXcdDeviceHandleStateImpl +struct NfcXcdDeviceHandleStateImpl { + u64 handle{}; + bool is_available{}; + bool is_activated{}; + INSERT_PADDING_BYTES(0x6); // Reserved + u64 sampling_number{}; +}; +static_assert(sizeof(NfcXcdDeviceHandleStateImpl) == 0x18, + "NfcXcdDeviceHandleStateImpl is an invalid size"); + +// This is nn::hid::NpadLarkType +enum class NpadLarkType : u32 { + Invalid, + H1, + H2, + NL, + NR, +}; + +// This is nn::hid::NpadLuciaType +enum class NpadLuciaType : u32 { + Invalid, + J, + E, + U, +}; + +// This is nn::hid::NpadLagonType +enum class NpadLagonType : u32 { + Invalid, +}; + +// This is nn::hid::NpadLagerType +enum class NpadLagerType : u32 { + Invalid, + J, + E, + U, +}; + +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/types/touch_types.h b/src/core/hle/service/hid/controllers/types/touch_types.h new file mode 100644 index 000000000..efeaa796d --- /dev/null +++ b/src/core/hle/service/hid/controllers/types/touch_types.h @@ -0,0 +1,90 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include <array> + +#include <array> +#include "common/bit_field.h" +#include "common/common_funcs.h" +#include "common/common_types.h" +#include "common/point.h" +#include "core/hid/hid_types.h" + +namespace Service::HID { +static constexpr std::size_t MAX_FINGERS = 16; +static constexpr size_t MAX_POINTS = 4; + +// This is nn::hid::GestureType +enum class GestureType : u32 { + Idle, // Nothing touching the screen + Complete, // Set at the end of a touch event + Cancel, // Set when the number of fingers change + Touch, // A finger just touched the screen + Press, // Set if last type is touch and the finger hasn't moved + Tap, // Fast press then release + Pan, // All points moving together across the screen + Swipe, // Fast press movement and release of a single point + Pinch, // All points moving away/closer to the midpoint + Rotate, // All points rotating from the midpoint +}; + +// This is nn::hid::GestureDirection +enum class GestureDirection : u32 { + None, + Left, + Up, + Right, + Down, +}; + +// This is nn::hid::GestureAttribute +struct GestureAttribute { + union { + u32 raw{}; + + BitField<4, 1, u32> is_new_touch; + BitField<8, 1, u32> is_double_tap; + }; +}; +static_assert(sizeof(GestureAttribute) == 4, "GestureAttribute is an invalid size"); + +// This is nn::hid::GestureState +struct GestureState { + s64 sampling_number{}; + s64 detection_count{}; + GestureType type{GestureType::Idle}; + GestureDirection direction{GestureDirection::None}; + Common::Point<s32> pos{}; + Common::Point<s32> delta{}; + f32 vel_x{}; + f32 vel_y{}; + GestureAttribute attributes{}; + f32 scale{}; + f32 rotation_angle{}; + s32 point_count{}; + std::array<Common::Point<s32>, 4> points{}; +}; +static_assert(sizeof(GestureState) == 0x60, "GestureState is an invalid size"); + +struct GestureProperties { + std::array<Common::Point<s32>, MAX_POINTS> points{}; + std::size_t active_points{}; + Common::Point<s32> mid_point{}; + s64 detection_count{}; + u64 delta_time{}; + f32 average_distance{}; + f32 angle{}; +}; + +// This is nn::hid::TouchScreenState +struct TouchScreenState { + s64 sampling_number{}; + s32 entry_count{}; + INSERT_PADDING_BYTES(4); // Reserved + std::array<Core::HID::TouchState, MAX_FINGERS> states{}; +}; +static_assert(sizeof(TouchScreenState) == 0x290, "TouchScreenState is an invalid size"); + +} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/xpad.cpp b/src/core/hle/service/hid/controllers/xpad.cpp deleted file mode 100644 index 0aaed1fa7..000000000 --- a/src/core/hle/service/hid/controllers/xpad.cpp +++ /dev/null @@ -1,39 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include <cstring> -#include "common/common_types.h" -#include "core/core_timing.h" -#include "core/hid/hid_core.h" -#include "core/hle/service/hid/controllers/xpad.h" - -namespace Service::HID { -constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C00; - -XPad::XPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) : ControllerBase{hid_core_} { - static_assert(SHARED_MEMORY_OFFSET + sizeof(XpadSharedMemory) < shared_memory_size, - "XpadSharedMemory is bigger than the shared memory"); - shared_memory = std::construct_at( - reinterpret_cast<XpadSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET)); -} -XPad::~XPad() = default; - -void XPad::OnInit() {} - -void XPad::OnRelease() {} - -void XPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) { - if (!IsControllerActivated()) { - shared_memory->basic_xpad_lifo.buffer_count = 0; - shared_memory->basic_xpad_lifo.buffer_tail = 0; - return; - } - - const auto& last_entry = shared_memory->basic_xpad_lifo.ReadCurrentEntry().state; - next_state.sampling_number = last_entry.sampling_number + 1; - // TODO(ogniK): Update xpad states - - shared_memory->basic_xpad_lifo.WriteNextEntry(next_state); -} - -} // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/xpad.h b/src/core/hle/service/hid/controllers/xpad.h deleted file mode 100644 index 9e63a317a..000000000 --- a/src/core/hle/service/hid/controllers/xpad.h +++ /dev/null @@ -1,112 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "common/bit_field.h" -#include "common/common_types.h" -#include "core/hid/hid_types.h" -#include "core/hle/service/hid/controllers/controller_base.h" -#include "core/hle/service/hid/ring_lifo.h" - -namespace Service::HID { -class XPad final : public ControllerBase { -public: - explicit XPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_); - ~XPad() override; - - // Called when the controller is initialized - void OnInit() override; - - // When the controller is released - void OnRelease() override; - - // When the controller is requesting an update for the shared memory - void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; - -private: - // This is nn::hid::BasicXpadAttributeSet - struct BasicXpadAttributeSet { - union { - u32 raw{}; - BitField<0, 1, u32> is_connected; - BitField<1, 1, u32> is_wired; - BitField<2, 1, u32> is_left_connected; - BitField<3, 1, u32> is_left_wired; - BitField<4, 1, u32> is_right_connected; - BitField<5, 1, u32> is_right_wired; - }; - }; - static_assert(sizeof(BasicXpadAttributeSet) == 4, "BasicXpadAttributeSet is an invalid size"); - - // This is nn::hid::BasicXpadButtonSet - struct BasicXpadButtonSet { - union { - u32 raw{}; - // Button states - BitField<0, 1, u32> a; - BitField<1, 1, u32> b; - BitField<2, 1, u32> x; - BitField<3, 1, u32> y; - BitField<4, 1, u32> l_stick; - BitField<5, 1, u32> r_stick; - BitField<6, 1, u32> l; - BitField<7, 1, u32> r; - BitField<8, 1, u32> zl; - BitField<9, 1, u32> zr; - BitField<10, 1, u32> plus; - BitField<11, 1, u32> minus; - - // D-Pad - BitField<12, 1, u32> d_left; - BitField<13, 1, u32> d_up; - BitField<14, 1, u32> d_right; - BitField<15, 1, u32> d_down; - - // Left JoyStick - BitField<16, 1, u32> l_stick_left; - BitField<17, 1, u32> l_stick_up; - BitField<18, 1, u32> l_stick_right; - BitField<19, 1, u32> l_stick_down; - - // Right JoyStick - BitField<20, 1, u32> r_stick_left; - BitField<21, 1, u32> r_stick_up; - BitField<22, 1, u32> r_stick_right; - BitField<23, 1, u32> r_stick_down; - - // Not always active? - BitField<24, 1, u32> left_sl; - BitField<25, 1, u32> left_sr; - - BitField<26, 1, u32> right_sl; - BitField<27, 1, u32> right_sr; - - BitField<28, 1, u32> palma; - BitField<30, 1, u32> handheld_left_b; - }; - }; - static_assert(sizeof(BasicXpadButtonSet) == 4, "BasicXpadButtonSet is an invalid size"); - - // This is nn::hid::detail::BasicXpadState - struct BasicXpadState { - s64 sampling_number{}; - BasicXpadAttributeSet attributes{}; - BasicXpadButtonSet pad_states{}; - Core::HID::AnalogStickState l_stick{}; - Core::HID::AnalogStickState r_stick{}; - }; - static_assert(sizeof(BasicXpadState) == 0x20, "BasicXpadState is an invalid size"); - - struct XpadSharedMemory { - // This is nn::hid::detail::BasicXpadLifo - Lifo<BasicXpadState, hid_entry_count> basic_xpad_lifo{}; - static_assert(sizeof(basic_xpad_lifo) == 0x2C8, "basic_xpad_lifo is an invalid size"); - INSERT_PADDING_WORDS(0x4E); - }; - static_assert(sizeof(XpadSharedMemory) == 0x400, "XpadSharedMemory is an invalid size"); - - BasicXpadState next_state{}; - XpadSharedMemory* shared_memory = nullptr; -}; -} // namespace Service::HID diff --git a/src/core/hle/service/hid/errors.h b/src/core/hle/service/hid/errors.h index f00cb831f..6dc976fe1 100644 --- a/src/core/hle/service/hid/errors.h +++ b/src/core/hle/service/hid/errors.h @@ -20,6 +20,9 @@ constexpr Result InvalidNpadId{ErrorModule::HID, 709}; constexpr Result NpadNotConnected{ErrorModule::HID, 710}; constexpr Result InvalidArraySize{ErrorModule::HID, 715}; +constexpr Result ResultAppletResourceOverflow{ErrorModule::HID, 1041}; +constexpr Result ResultAppletResourceNotInitialized{ErrorModule::HID, 1042}; +constexpr Result ResultSharedMemoryNotInitialized{ErrorModule::HID, 1043}; constexpr Result ResultAruidNoAvailableEntries{ErrorModule::HID, 1044}; constexpr Result ResultAruidAlreadyRegistered{ErrorModule::HID, 1046}; constexpr Result ResultAruidNotRegistered{ErrorModule::HID, 1047}; diff --git a/src/core/hle/service/hid/hid_server.cpp b/src/core/hle/service/hid/hid_server.cpp index e0f4051aa..de24b0401 100644 --- a/src/core/hle/service/hid/hid_server.cpp +++ b/src/core/hle/service/hid/hid_server.cpp @@ -28,6 +28,7 @@ #include "core/hle/service/hid/controllers/seven_six_axis.h" #include "core/hle/service/hid/controllers/six_axis.h" #include "core/hle/service/hid/controllers/touchscreen.h" +#include "core/hle/service/hid/controllers/types/npad_types.h" namespace Service::HID { @@ -222,16 +223,14 @@ void IHidServer::CreateAppletResource(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; - LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); - Result result = GetResourceManager()->CreateAppletResource(applet_resource_user_id); - if (result.IsSuccess()) { - result = GetResourceManager()->GetNpad()->Activate(applet_resource_user_id); - } + + LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, result=0x{:X}", + applet_resource_user_id, result.raw); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(result); - rb.PushIpcInterface<IAppletResource>(system, resource_manager); + rb.PushIpcInterface<IAppletResource>(system, resource_manager, applet_resource_user_id); } void IHidServer::ActivateDebugPad(HLERequestContext& ctx) { @@ -1101,7 +1100,7 @@ void IHidServer::GetPlayerLedPattern(HLERequestContext& ctx) { void IHidServer::ActivateNpadWithRevision(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { - NPad::NpadRevision revision; + NpadRevision revision; INSERT_PADDING_WORDS_NOINIT(1); u64 applet_resource_user_id; }; @@ -1124,7 +1123,7 @@ void IHidServer::ActivateNpadWithRevision(HLERequestContext& ctx) { void IHidServer::SetNpadJoyHoldType(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; - const auto hold_type{rp.PopEnum<NPad::NpadJoyHoldType>()}; + const auto hold_type{rp.PopEnum<NpadJoyHoldType>()}; GetResourceManager()->GetNpad()->SetHoldType(hold_type); @@ -1159,8 +1158,8 @@ void IHidServer::SetNpadJoyAssignmentModeSingleByDefault(HLERequestContext& ctx) Core::HID::NpadIdType new_npad_id{}; auto controller = GetResourceManager()->GetNpad(); - controller->SetNpadMode(new_npad_id, parameters.npad_id, NPad::NpadJoyDeviceType::Left, - NPad::NpadJoyAssignmentMode::Single); + controller->SetNpadMode(new_npad_id, parameters.npad_id, NpadJoyDeviceType::Left, + NpadJoyAssignmentMode::Single); LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id, parameters.applet_resource_user_id); @@ -1175,7 +1174,7 @@ void IHidServer::SetNpadJoyAssignmentModeSingle(HLERequestContext& ctx) { Core::HID::NpadIdType npad_id; INSERT_PADDING_WORDS_NOINIT(1); u64 applet_resource_user_id; - NPad::NpadJoyDeviceType npad_joy_device_type; + NpadJoyDeviceType npad_joy_device_type; }; static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size."); @@ -1184,7 +1183,7 @@ void IHidServer::SetNpadJoyAssignmentModeSingle(HLERequestContext& ctx) { Core::HID::NpadIdType new_npad_id{}; auto controller = GetResourceManager()->GetNpad(); controller->SetNpadMode(new_npad_id, parameters.npad_id, parameters.npad_joy_device_type, - NPad::NpadJoyAssignmentMode::Single); + NpadJoyAssignmentMode::Single); LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}", parameters.npad_id, parameters.applet_resource_user_id, @@ -1207,7 +1206,7 @@ void IHidServer::SetNpadJoyAssignmentModeDual(HLERequestContext& ctx) { Core::HID::NpadIdType new_npad_id{}; auto controller = GetResourceManager()->GetNpad(); - controller->SetNpadMode(new_npad_id, parameters.npad_id, {}, NPad::NpadJoyAssignmentMode::Dual); + controller->SetNpadMode(new_npad_id, parameters.npad_id, {}, NpadJoyAssignmentMode::Dual); LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id, parameters.applet_resource_user_id); // Spams a lot when controller applet is open @@ -1259,7 +1258,7 @@ void IHidServer::StopLrAssignmentMode(HLERequestContext& ctx) { void IHidServer::SetNpadHandheldActivationMode(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; - const auto activation_mode{rp.PopEnum<NPad::NpadHandheldActivationMode>()}; + const auto activation_mode{rp.PopEnum<NpadHandheldActivationMode>()}; GetResourceManager()->GetNpad()->SetNpadHandheldActivationMode(activation_mode); @@ -1351,7 +1350,7 @@ void IHidServer::SetNpadJoyAssignmentModeSingleWithDestination(HLERequestContext Core::HID::NpadIdType npad_id; INSERT_PADDING_WORDS_NOINIT(1); u64 applet_resource_user_id; - NPad::NpadJoyDeviceType npad_joy_device_type; + NpadJoyDeviceType npad_joy_device_type; }; static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size."); @@ -1361,7 +1360,7 @@ void IHidServer::SetNpadJoyAssignmentModeSingleWithDestination(HLERequestContext auto controller = GetResourceManager()->GetNpad(); const auto is_reassigned = controller->SetNpadMode(new_npad_id, parameters.npad_id, parameters.npad_joy_device_type, - NPad::NpadJoyAssignmentMode::Single); + NpadJoyAssignmentMode::Single); LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}", parameters.npad_id, parameters.applet_resource_user_id, @@ -2317,7 +2316,7 @@ void IHidServer::SetDisallowedPalmaConnection(HLERequestContext& ctx) { void IHidServer::SetNpadCommunicationMode(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; - const auto communication_mode{rp.PopEnum<NPad::NpadCommunicationMode>()}; + const auto communication_mode{rp.PopEnum<NpadCommunicationMode>()}; GetResourceManager()->GetNpad()->SetNpadCommunicationMode(communication_mode); diff --git a/src/core/hle/service/hid/hid_system_server.cpp b/src/core/hle/service/hid/hid_system_server.cpp index 4d33456a3..5cc88c4a1 100644 --- a/src/core/hle/service/hid/hid_system_server.cpp +++ b/src/core/hle/service/hid/hid_system_server.cpp @@ -5,6 +5,7 @@ #include "core/hle/service/hid/controllers/npad.h" #include "core/hle/service/hid/controllers/palma.h" #include "core/hle/service/hid/controllers/touchscreen.h" +#include "core/hle/service/hid/controllers/types/npad_types.h" #include "core/hle/service/hid/errors.h" #include "core/hle/service/hid/hid_system_server.h" #include "core/hle/service/hid/resource_manager.h" @@ -328,7 +329,7 @@ void IHidSystemServer::GetAppletDetailedUiType(HLERequestContext& ctx) { LOG_DEBUG(Service_HID, "called, npad_id_type={}", npad_id_type); // Spams a lot when controller applet is running - const NPad::AppletDetailedUiType detailed_ui_type = + const AppletDetailedUiType detailed_ui_type = GetResourceManager()->GetNpad()->GetAppletDetailedUiType(npad_id_type); IPC::ResponseBuilder rb{ctx, 3}; diff --git a/src/core/hle/service/hid/resource_manager.cpp b/src/core/hle/service/hid/resource_manager.cpp index 60d4ef71f..6c6cbd802 100644 --- a/src/core/hle/service/hid/resource_manager.cpp +++ b/src/core/hle/service/hid/resource_manager.cpp @@ -18,10 +18,10 @@ #include "core/hle/service/hid/controllers/npad.h" #include "core/hle/service/hid/controllers/palma.h" #include "core/hle/service/hid/controllers/seven_six_axis.h" +#include "core/hle/service/hid/controllers/shared_memory_format.h" #include "core/hle/service/hid/controllers/six_axis.h" #include "core/hle/service/hid/controllers/stubbed.h" #include "core/hle/service/hid/controllers/touchscreen.h" -#include "core/hle/service/hid/controllers/xpad.h" namespace Service::HID { @@ -45,40 +45,43 @@ void ResourceManager::Initialize() { return; } - u8* shared_memory = system.Kernel().GetHidSharedMem().GetPointer(); - debug_pad = std::make_shared<DebugPad>(system.HIDCore(), shared_memory); - mouse = std::make_shared<Mouse>(system.HIDCore(), shared_memory); - debug_mouse = std::make_shared<DebugMouse>(system.HIDCore(), shared_memory); - keyboard = std::make_shared<Keyboard>(system.HIDCore(), shared_memory); - unique_pad = std::make_shared<UniquePad>(system.HIDCore(), shared_memory); - npad = std::make_shared<NPad>(system.HIDCore(), shared_memory, service_context); - gesture = std::make_shared<Gesture>(system.HIDCore(), shared_memory); - touch_screen = std::make_shared<TouchScreen>(system.HIDCore(), shared_memory); - xpad = std::make_shared<XPad>(system.HIDCore(), shared_memory); + system.HIDCore().ReloadInputDevices(); + is_initialized = true; +} + +void ResourceManager::InitializeController(u64 aruid) { + SharedMemoryFormat* shared_memory = nullptr; + const auto result = applet_resource->GetSharedMemoryFormat(&shared_memory, aruid); + if (result.IsError()) { + return; + } - palma = std::make_shared<Palma>(system.HIDCore(), shared_memory, service_context); + debug_pad = std::make_shared<DebugPad>(system.HIDCore(), shared_memory->debug_pad); + mouse = std::make_shared<Mouse>(system.HIDCore(), shared_memory->mouse); + debug_mouse = std::make_shared<DebugMouse>(system.HIDCore(), shared_memory->debug_mouse); + keyboard = std::make_shared<Keyboard>(system.HIDCore(), shared_memory->keyboard); + unique_pad = std::make_shared<UniquePad>(system.HIDCore(), shared_memory->unique_pad.header); + npad = std::make_shared<NPad>(system.HIDCore(), shared_memory->npad, service_context); + gesture = std::make_shared<Gesture>(system.HIDCore(), shared_memory->gesture); + touch_screen = std::make_shared<TouchScreen>(system.HIDCore(), shared_memory->touch_screen); - home_button = std::make_shared<HomeButton>(system.HIDCore(), shared_memory); - sleep_button = std::make_shared<SleepButton>(system.HIDCore(), shared_memory); - capture_button = std::make_shared<CaptureButton>(system.HIDCore(), shared_memory); + palma = std::make_shared<Palma>(system.HIDCore(), service_context); + + home_button = std::make_shared<HomeButton>(system.HIDCore(), shared_memory->home_button.header); + sleep_button = + std::make_shared<SleepButton>(system.HIDCore(), shared_memory->sleep_button.header); + capture_button = + std::make_shared<CaptureButton>(system.HIDCore(), shared_memory->capture_button.header); + digitizer = std::make_shared<Digitizer>(system.HIDCore(), shared_memory->digitizer.header); six_axis = std::make_shared<SixAxis>(system.HIDCore(), npad); - console_six_axis = std::make_shared<ConsoleSixAxis>(system.HIDCore(), shared_memory); + console_six_axis = std::make_shared<ConsoleSixAxis>(system.HIDCore(), shared_memory->console); seven_six_axis = std::make_shared<SevenSixAxis>(system); - home_button->SetCommonHeaderOffset(0x4C00); - sleep_button->SetCommonHeaderOffset(0x4E00); - capture_button->SetCommonHeaderOffset(0x5000); - unique_pad->SetCommonHeaderOffset(0x5A00); - debug_mouse->SetCommonHeaderOffset(0x3DC00); - // Homebrew doesn't try to activate some controllers, so we activate them by default npad->Activate(); six_axis->Activate(); touch_screen->Activate(); - - system.HIDCore().ReloadInputDevices(); - is_initialized = true; } std::shared_ptr<AppletResource> ResourceManager::GetAppletResource() const { @@ -101,6 +104,10 @@ std::shared_ptr<DebugPad> ResourceManager::GetDebugPad() const { return debug_pad; } +std::shared_ptr<Digitizer> ResourceManager::GetDigitizer() const { + return digitizer; +} + std::shared_ptr<Gesture> ResourceManager::GetGesture() const { return gesture; } @@ -146,8 +153,38 @@ std::shared_ptr<UniquePad> ResourceManager::GetUniquePad() const { } Result ResourceManager::CreateAppletResource(u64 aruid) { + if (aruid == 0) { + const auto result = RegisterCoreAppletResource(); + if (result.IsError()) { + return result; + } + return GetNpad()->Activate(); + } + + const auto result = CreateAppletResourceImpl(aruid); + if (result.IsError()) { + return result; + } + return GetNpad()->Activate(aruid); +} + +Result ResourceManager::CreateAppletResourceImpl(u64 aruid) { + std::scoped_lock lock{shared_mutex}; + const auto result = applet_resource->CreateAppletResource(aruid); + if (result.IsSuccess()) { + InitializeController(aruid); + } + return result; +} + +Result ResourceManager::RegisterCoreAppletResource() { std::scoped_lock lock{shared_mutex}; - return applet_resource->CreateAppletResource(aruid); + return applet_resource->RegisterCoreAppletResource(); +} + +Result ResourceManager::UnregisterCoreAppletResource() { + std::scoped_lock lock{shared_mutex}; + return applet_resource->UnregisterCoreAppletResource(); } Result ResourceManager::RegisterAppletResourceUserId(u64 aruid, bool bool_value) { @@ -165,6 +202,11 @@ Result ResourceManager::GetSharedMemoryHandle(Kernel::KSharedMemory** out_handle return applet_resource->GetSharedMemoryHandle(out_handle, aruid); } +void ResourceManager::FreeAppletResourceId(u64 aruid) { + std::scoped_lock lock{shared_mutex}; + applet_resource->FreeAppletResourceId(aruid); +} + void ResourceManager::EnableInput(u64 aruid, bool is_enabled) { std::scoped_lock lock{shared_mutex}; applet_resource->EnableInput(aruid, is_enabled); @@ -189,6 +231,7 @@ void ResourceManager::UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) { auto& core_timing = system.CoreTiming(); debug_pad->OnUpdate(core_timing); + digitizer->OnUpdate(core_timing); unique_pad->OnUpdate(core_timing); gesture->OnUpdate(core_timing); touch_screen->OnUpdate(core_timing); @@ -196,7 +239,6 @@ void ResourceManager::UpdateControllers(std::uintptr_t user_data, home_button->OnUpdate(core_timing); sleep_button->OnUpdate(core_timing); capture_button->OnUpdate(core_timing); - xpad->OnUpdate(core_timing); } void ResourceManager::UpdateNpad(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) { @@ -219,8 +261,10 @@ void ResourceManager::UpdateMotion(std::uintptr_t user_data, std::chrono::nanose console_six_axis->OnUpdate(core_timing); } -IAppletResource::IAppletResource(Core::System& system_, std::shared_ptr<ResourceManager> resource) - : ServiceFramework{system_, "IAppletResource"}, resource_manager{resource} { +IAppletResource::IAppletResource(Core::System& system_, std::shared_ptr<ResourceManager> resource, + u64 applet_resource_user_id) + : ServiceFramework{system_, "IAppletResource"}, aruid{applet_resource_user_id}, + resource_manager{resource} { static const FunctionInfo functions[] = { {0, &IAppletResource::GetSharedMemoryHandle, "GetSharedMemoryHandle"}, }; @@ -274,14 +318,14 @@ IAppletResource::~IAppletResource() { system.CoreTiming().UnscheduleEvent(default_update_event, 0); system.CoreTiming().UnscheduleEvent(mouse_keyboard_update_event, 0); system.CoreTiming().UnscheduleEvent(motion_update_event, 0); + resource_manager->FreeAppletResourceId(aruid); } void IAppletResource::GetSharedMemoryHandle(HLERequestContext& ctx) { - LOG_DEBUG(Service_HID, "called"); - Kernel::KSharedMemory* handle; - const u64 applet_resource_user_id = resource_manager->GetAppletResource()->GetActiveAruid(); - const auto result = resource_manager->GetSharedMemoryHandle(&handle, applet_resource_user_id); + const auto result = resource_manager->GetSharedMemoryHandle(&handle, aruid); + + LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, result=0x{:X}", aruid, result.raw); IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(result); diff --git a/src/core/hle/service/hid/resource_manager.h b/src/core/hle/service/hid/resource_manager.h index a78e2b729..5ad7cb564 100644 --- a/src/core/hle/service/hid/resource_manager.h +++ b/src/core/hle/service/hid/resource_manager.h @@ -31,10 +31,10 @@ class Palma; class SevenSixAxis; class SixAxis; class TouchScreen; -class XPad; using CaptureButton = Controller_Stubbed; -using DebugMouse = Controller_Stubbed; +using DebugMouse = Mouse; +using Digitizer = Controller_Stubbed; using HomeButton = Controller_Stubbed; using SleepButton = Controller_Stubbed; using UniquePad = Controller_Stubbed; @@ -46,12 +46,14 @@ public: ~ResourceManager(); void Initialize(); + void InitializeController(u64 aruid); std::shared_ptr<AppletResource> GetAppletResource() const; std::shared_ptr<CaptureButton> GetCaptureButton() const; std::shared_ptr<ConsoleSixAxis> GetConsoleSixAxis() const; std::shared_ptr<DebugMouse> GetDebugMouse() const; std::shared_ptr<DebugPad> GetDebugPad() const; + std::shared_ptr<Digitizer> GetDigitizer() const; std::shared_ptr<Gesture> GetGesture() const; std::shared_ptr<HomeButton> GetHomeButton() const; std::shared_ptr<Keyboard> GetKeyboard() const; @@ -66,10 +68,13 @@ public: Result CreateAppletResource(u64 aruid); + Result RegisterCoreAppletResource(); + Result UnregisterCoreAppletResource(); Result RegisterAppletResourceUserId(u64 aruid, bool bool_value); void UnregisterAppletResourceUserId(u64 aruid); Result GetSharedMemoryHandle(Kernel::KSharedMemory** out_handle, u64 aruid); + void FreeAppletResourceId(u64 aruid); void EnableInput(u64 aruid, bool is_enabled); void EnableSixAxisSensor(u64 aruid, bool is_enabled); @@ -82,6 +87,8 @@ public: void UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); private: + Result CreateAppletResourceImpl(u64 aruid); + bool is_initialized{false}; mutable std::mutex shared_mutex; @@ -91,6 +98,7 @@ private: std::shared_ptr<ConsoleSixAxis> console_six_axis = nullptr; std::shared_ptr<DebugMouse> debug_mouse = nullptr; std::shared_ptr<DebugPad> debug_pad = nullptr; + std::shared_ptr<Digitizer> digitizer = nullptr; std::shared_ptr<Gesture> gesture = nullptr; std::shared_ptr<HomeButton> home_button = nullptr; std::shared_ptr<Keyboard> keyboard = nullptr; @@ -102,7 +110,6 @@ private: std::shared_ptr<SleepButton> sleep_button = nullptr; std::shared_ptr<TouchScreen> touch_screen = nullptr; std::shared_ptr<UniquePad> unique_pad = nullptr; - std::shared_ptr<XPad> xpad = nullptr; // TODO: Create these resources // std::shared_ptr<AudioControl> audio_control = nullptr; @@ -121,7 +128,8 @@ private: class IAppletResource final : public ServiceFramework<IAppletResource> { public: - explicit IAppletResource(Core::System& system_, std::shared_ptr<ResourceManager> resource); + explicit IAppletResource(Core::System& system_, std::shared_ptr<ResourceManager> resource, + u64 applet_resource_user_id); ~IAppletResource() override; private: @@ -132,6 +140,7 @@ private: std::shared_ptr<Core::Timing::EventType> mouse_keyboard_update_event; std::shared_ptr<Core::Timing::EventType> motion_update_event; + u64 aruid; std::shared_ptr<ResourceManager> resource_manager; }; diff --git a/src/core/hle/service/ssl/ssl.cpp b/src/core/hle/service/ssl/ssl.cpp index 6c8427b0d..0fbb43057 100644 --- a/src/core/hle/service/ssl/ssl.cpp +++ b/src/core/hle/service/ssl/ssl.cpp @@ -240,7 +240,7 @@ private: return ret; } - Result ReadImpl(std::vector<u8>* out_data, size_t size) { + Result ReadImpl(std::vector<u8>* out_data) { ASSERT_OR_EXECUTE(did_handshake, { return ResultInternalError; }); size_t actual_size{}; Result res = backend->Read(&actual_size, *out_data); @@ -326,8 +326,8 @@ private: } void Read(HLERequestContext& ctx) { - std::vector<u8> output_bytes; - const Result res = ReadImpl(&output_bytes, ctx.GetWriteBufferSize()); + std::vector<u8> output_bytes(ctx.GetWriteBufferSize()); + const Result res = ReadImpl(&output_bytes); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(res); if (res == ResultSuccess) { diff --git a/src/core/memory/cheat_engine.cpp b/src/core/memory/cheat_engine.cpp index db30ba598..3fc4024dc 100644 --- a/src/core/memory/cheat_engine.cpp +++ b/src/core/memory/cheat_engine.cpp @@ -62,7 +62,7 @@ u64 StandardVmCallbacks::HidKeysDown() { } const auto applet_resource = hid->GetResourceManager(); - if (applet_resource == nullptr) { + if (applet_resource == nullptr || applet_resource->GetNpad() == nullptr) { LOG_WARNING(CheatEngine, "Attempted to read input state, but applet resource is not initialized!"); return 0; diff --git a/src/tests/video_core/memory_tracker.cpp b/src/tests/video_core/memory_tracker.cpp index 618793668..2dbff21af 100644 --- a/src/tests/video_core/memory_tracker.cpp +++ b/src/tests/video_core/memory_tracker.cpp @@ -23,13 +23,13 @@ constexpr VAddr c = 16 * HIGH_PAGE_SIZE; class RasterizerInterface { public: - void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) { + void UpdatePagesCachedCount(VAddr addr, u64 size, bool cache) { const u64 page_start{addr >> Core::Memory::YUZU_PAGEBITS}; const u64 page_end{(addr + size + Core::Memory::YUZU_PAGESIZE - 1) >> Core::Memory::YUZU_PAGEBITS}; for (u64 page = page_start; page < page_end; ++page) { int& value = page_table[page]; - value += delta; + value += (cache ? 1 : -1); if (value < 0) { throw std::logic_error{"negative page"}; } @@ -546,4 +546,4 @@ TEST_CASE("MemoryTracker: Cached write downloads") { REQUIRE(!memory_track->IsRegionGpuModified(c + PAGE, PAGE)); memory_track->MarkRegionAsCpuModified(c, WORD); REQUIRE(rasterizer.Count() == 0); -}
\ No newline at end of file +} diff --git a/src/video_core/buffer_cache/word_manager.h b/src/video_core/buffer_cache/word_manager.h index a336bde41..95b752055 100644 --- a/src/video_core/buffer_cache/word_manager.h +++ b/src/video_core/buffer_cache/word_manager.h @@ -473,7 +473,7 @@ private: VAddr addr = cpu_addr + word_index * BYTES_PER_WORD; IteratePages(changed_bits, [&](size_t offset, size_t size) { rasterizer->UpdatePagesCachedCount(addr + offset * BYTES_PER_PAGE, - size * BYTES_PER_PAGE, add_to_rasterizer ? 1 : -1); + size * BYTES_PER_PAGE, add_to_rasterizer); }); } diff --git a/src/video_core/rasterizer_accelerated.cpp b/src/video_core/rasterizer_accelerated.cpp index f200a650f..3c9477f6e 100644 --- a/src/video_core/rasterizer_accelerated.cpp +++ b/src/video_core/rasterizer_accelerated.cpp @@ -3,6 +3,7 @@ #include <atomic> +#include "common/alignment.h" #include "common/assert.h" #include "common/common_types.h" #include "common/div_ceil.h" @@ -11,61 +12,65 @@ namespace VideoCore { +static constexpr u16 IdentityValue = 1; + using namespace Core::Memory; -RasterizerAccelerated::RasterizerAccelerated(Memory& cpu_memory_) - : cached_pages(std::make_unique<CachedPages>()), cpu_memory{cpu_memory_} {} +RasterizerAccelerated::RasterizerAccelerated(Memory& cpu_memory_) : map{}, cpu_memory{cpu_memory_} { + // We are tracking CPU memory, which cannot map more than 39 bits. + const VAddr start_address = 0; + const VAddr end_address = (1ULL << 39); + const IntervalType address_space_interval(start_address, end_address); + const auto value = std::make_pair(address_space_interval, IdentityValue); + + map.add(value); +} RasterizerAccelerated::~RasterizerAccelerated() = default; -void RasterizerAccelerated::UpdatePagesCachedCount(VAddr addr, u64 size, int delta) { - u64 uncache_begin = 0; - u64 cache_begin = 0; - u64 uncache_bytes = 0; - u64 cache_bytes = 0; - - std::atomic_thread_fence(std::memory_order_acquire); - const u64 page_end = Common::DivCeil(addr + size, YUZU_PAGESIZE); - for (u64 page = addr >> YUZU_PAGEBITS; page != page_end; ++page) { - std::atomic_uint16_t& count = cached_pages->at(page >> 2).Count(page); - - if (delta > 0) { - ASSERT_MSG(count.load(std::memory_order::relaxed) < UINT16_MAX, "Count may overflow!"); - } else if (delta < 0) { - ASSERT_MSG(count.load(std::memory_order::relaxed) > 0, "Count may underflow!"); - } else { - ASSERT_MSG(false, "Delta must be non-zero!"); - } +void RasterizerAccelerated::UpdatePagesCachedCount(VAddr addr, u64 size, bool cache) { + std::scoped_lock lk{map_lock}; - // Adds or subtracts 1, as count is a unsigned 8-bit value - count.fetch_add(static_cast<u16>(delta), std::memory_order_release); - - // Assume delta is either -1 or 1 - if (count.load(std::memory_order::relaxed) == 0) { - if (uncache_bytes == 0) { - uncache_begin = page; - } - uncache_bytes += YUZU_PAGESIZE; - } else if (uncache_bytes > 0) { - cpu_memory.RasterizerMarkRegionCached(uncache_begin << YUZU_PAGEBITS, uncache_bytes, - false); - uncache_bytes = 0; - } - if (count.load(std::memory_order::relaxed) == 1 && delta > 0) { - if (cache_bytes == 0) { - cache_begin = page; - } - cache_bytes += YUZU_PAGESIZE; - } else if (cache_bytes > 0) { - cpu_memory.RasterizerMarkRegionCached(cache_begin << YUZU_PAGEBITS, cache_bytes, true); - cache_bytes = 0; + // Align sizes. + addr = Common::AlignDown(addr, YUZU_PAGESIZE); + size = Common::AlignUp(size, YUZU_PAGESIZE); + + // Declare the overall interval we are going to operate on. + const VAddr start_address = addr; + const VAddr end_address = addr + size; + const IntervalType modification_range(start_address, end_address); + + // Find the boundaries of where to iterate. + const auto lower = map.lower_bound(modification_range); + const auto upper = map.upper_bound(modification_range); + + // Iterate over the contained intervals. + for (auto it = lower; it != upper; it++) { + // Intersect interval range with modification range. + const auto current_range = modification_range & it->first; + + // Calculate the address and size to operate over. + const auto current_addr = current_range.lower(); + const auto current_size = current_range.upper() - current_addr; + + // Get the current value of the range. + const auto value = it->second; + + if (cache && value == IdentityValue) { + // If we are going to cache, and the value is not yet referenced, then cache this range. + cpu_memory.RasterizerMarkRegionCached(current_addr, current_size, true); + } else if (!cache && value == IdentityValue + 1) { + // If we are going to uncache, and this is the last reference, then uncache this range. + cpu_memory.RasterizerMarkRegionCached(current_addr, current_size, false); } } - if (uncache_bytes > 0) { - cpu_memory.RasterizerMarkRegionCached(uncache_begin << YUZU_PAGEBITS, uncache_bytes, false); - } - if (cache_bytes > 0) { - cpu_memory.RasterizerMarkRegionCached(cache_begin << YUZU_PAGEBITS, cache_bytes, true); + + // Update the set. + const auto value = std::make_pair(modification_range, IdentityValue); + if (cache) { + map.add(value); + } else { + map.subtract(value); } } diff --git a/src/video_core/rasterizer_accelerated.h b/src/video_core/rasterizer_accelerated.h index e6c0ea87a..f1968f186 100644 --- a/src/video_core/rasterizer_accelerated.h +++ b/src/video_core/rasterizer_accelerated.h @@ -3,8 +3,8 @@ #pragma once -#include <array> -#include <atomic> +#include <mutex> +#include <boost/icl/interval_map.hpp> #include "common/common_types.h" #include "video_core/rasterizer_interface.h" @@ -21,28 +21,17 @@ public: explicit RasterizerAccelerated(Core::Memory::Memory& cpu_memory_); ~RasterizerAccelerated() override; - void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) override; + void UpdatePagesCachedCount(VAddr addr, u64 size, bool cache) override; private: - class CacheEntry final { - public: - CacheEntry() = default; + using PageIndex = VAddr; + using PageReferenceCount = u16; - std::atomic_uint16_t& Count(std::size_t page) { - return values[page & 3]; - } + using IntervalMap = boost::icl::interval_map<PageIndex, PageReferenceCount>; + using IntervalType = IntervalMap::interval_type; - const std::atomic_uint16_t& Count(std::size_t page) const { - return values[page & 3]; - } - - private: - std::array<std::atomic_uint16_t, 4> values{}; - }; - static_assert(sizeof(CacheEntry) == 8, "CacheEntry should be 8 bytes!"); - - using CachedPages = std::array<CacheEntry, 0x2000000>; - std::unique_ptr<CachedPages> cached_pages; + IntervalMap map; + std::mutex map_lock; Core::Memory::Memory& cpu_memory; }; diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h index af1469147..fd42d26b5 100644 --- a/src/video_core/rasterizer_interface.h +++ b/src/video_core/rasterizer_interface.h @@ -162,7 +162,7 @@ public: } /// Increase/decrease the number of object in pages touching the specified region - virtual void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) {} + virtual void UpdatePagesCachedCount(VAddr addr, u64 size, bool cache) {} /// Initialize disk cached resources for the game being emulated virtual void LoadDiskResources(u64 title_id, std::stop_token stop_loading, diff --git a/src/video_core/shader_cache.cpp b/src/video_core/shader_cache.cpp index e81cd031b..a109f9cbe 100644 --- a/src/video_core/shader_cache.cpp +++ b/src/video_core/shader_cache.cpp @@ -132,7 +132,7 @@ void ShaderCache::Register(std::unique_ptr<ShaderInfo> data, VAddr addr, size_t storage.push_back(std::move(data)); - rasterizer.UpdatePagesCachedCount(addr, size, 1); + rasterizer.UpdatePagesCachedCount(addr, size, true); } void ShaderCache::InvalidatePagesInRegion(VAddr addr, size_t size) { @@ -209,7 +209,7 @@ void ShaderCache::UnmarkMemory(Entry* entry) { const VAddr addr = entry->addr_start; const size_t size = entry->addr_end - addr; - rasterizer.UpdatePagesCachedCount(addr, size, -1); + rasterizer.UpdatePagesCachedCount(addr, size, false); } void ShaderCache::RemoveShadersFromStorage(std::span<ShaderInfo*> removed_shaders) { diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 0d5a1709f..d7941f6a4 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -2080,7 +2080,7 @@ void TextureCache<P>::TrackImage(ImageBase& image, ImageId image_id) { ASSERT(False(image.flags & ImageFlagBits::Tracked)); image.flags |= ImageFlagBits::Tracked; if (False(image.flags & ImageFlagBits::Sparse)) { - rasterizer.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, 1); + rasterizer.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, true); return; } if (True(image.flags & ImageFlagBits::Registered)) { @@ -2091,13 +2091,13 @@ void TextureCache<P>::TrackImage(ImageBase& image, ImageId image_id) { const auto& map = slot_map_views[map_view_id]; const VAddr cpu_addr = map.cpu_addr; const std::size_t size = map.size; - rasterizer.UpdatePagesCachedCount(cpu_addr, size, 1); + rasterizer.UpdatePagesCachedCount(cpu_addr, size, true); } return; } ForEachSparseSegment(image, [this]([[maybe_unused]] GPUVAddr gpu_addr, VAddr cpu_addr, size_t size) { - rasterizer.UpdatePagesCachedCount(cpu_addr, size, 1); + rasterizer.UpdatePagesCachedCount(cpu_addr, size, true); }); } @@ -2106,7 +2106,7 @@ void TextureCache<P>::UntrackImage(ImageBase& image, ImageId image_id) { ASSERT(True(image.flags & ImageFlagBits::Tracked)); image.flags &= ~ImageFlagBits::Tracked; if (False(image.flags & ImageFlagBits::Sparse)) { - rasterizer.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, -1); + rasterizer.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, false); return; } ASSERT(True(image.flags & ImageFlagBits::Registered)); @@ -2117,7 +2117,7 @@ void TextureCache<P>::UntrackImage(ImageBase& image, ImageId image_id) { const auto& map = slot_map_views[map_view_id]; const VAddr cpu_addr = map.cpu_addr; const std::size_t size = map.size; - rasterizer.UpdatePagesCachedCount(cpu_addr, size, -1); + rasterizer.UpdatePagesCachedCount(cpu_addr, size, false); } } diff --git a/src/yuzu/applets/qt_profile_select.cpp b/src/yuzu/applets/qt_profile_select.cpp index 1f3f23038..79162a491 100644 --- a/src/yuzu/applets/qt_profile_select.cpp +++ b/src/yuzu/applets/qt_profile_select.cpp @@ -14,6 +14,8 @@ #include "common/fs/path_util.h" #include "common/string_util.h" #include "core/constants.h" +#include "core/core.h" +#include "core/hle/service/acc/profile_manager.h" #include "yuzu/applets/qt_profile_select.h" #include "yuzu/main.h" #include "yuzu/util/controller_navigation.h" @@ -47,9 +49,9 @@ QPixmap GetIcon(Common::UUID uuid) { } // Anonymous namespace QtProfileSelectionDialog::QtProfileSelectionDialog( - Core::HID::HIDCore& hid_core, QWidget* parent, + Core::System& system, QWidget* parent, const Core::Frontend::ProfileSelectParameters& parameters) - : QDialog(parent), profile_manager(std::make_unique<Service::Account::ProfileManager>()) { + : QDialog(parent), profile_manager{system.GetProfileManager()} { outer_layout = new QVBoxLayout; instruction_label = new QLabel(); @@ -68,7 +70,7 @@ QtProfileSelectionDialog::QtProfileSelectionDialog( tree_view = new QTreeView; item_model = new QStandardItemModel(tree_view); tree_view->setModel(item_model); - controller_navigation = new ControllerNavigation(hid_core, this); + controller_navigation = new ControllerNavigation(system.HIDCore(), this); tree_view->setAlternatingRowColors(true); tree_view->setSelectionMode(QHeaderView::SingleSelection); @@ -106,10 +108,10 @@ QtProfileSelectionDialog::QtProfileSelectionDialog( SelectUser(tree_view->currentIndex()); }); - const auto& profiles = profile_manager->GetAllUsers(); + const auto& profiles = profile_manager.GetAllUsers(); for (const auto& user : profiles) { Service::Account::ProfileBase profile{}; - if (!profile_manager->GetProfileBase(user, profile)) + if (!profile_manager.GetProfileBase(user, profile)) continue; const auto username = Common::StringFromFixedZeroTerminatedBuffer( @@ -134,7 +136,7 @@ QtProfileSelectionDialog::~QtProfileSelectionDialog() { int QtProfileSelectionDialog::exec() { // Skip profile selection when there's only one. - if (profile_manager->GetUserCount() == 1) { + if (profile_manager.GetUserCount() == 1) { user_index = 0; return QDialog::Accepted; } diff --git a/src/yuzu/applets/qt_profile_select.h b/src/yuzu/applets/qt_profile_select.h index 99056e274..607f1777c 100644 --- a/src/yuzu/applets/qt_profile_select.h +++ b/src/yuzu/applets/qt_profile_select.h @@ -7,7 +7,6 @@ #include <QDialog> #include <QList> #include "core/frontend/applets/profile_select.h" -#include "core/hle/service/acc/profile_manager.h" class ControllerNavigation; class GMainWindow; @@ -20,15 +19,19 @@ class QStandardItemModel; class QTreeView; class QVBoxLayout; -namespace Core::HID { -class HIDCore; -} // namespace Core::HID +namespace Core { +class System; +} + +namespace Service::Account { +class ProfileManager; +} class QtProfileSelectionDialog final : public QDialog { Q_OBJECT public: - explicit QtProfileSelectionDialog(Core::HID::HIDCore& hid_core, QWidget* parent, + explicit QtProfileSelectionDialog(Core::System& system, QWidget* parent, const Core::Frontend::ProfileSelectParameters& parameters); ~QtProfileSelectionDialog() override; @@ -58,7 +61,7 @@ private: QScrollArea* scroll_area; QDialogButtonBox* buttons; - std::unique_ptr<Service::Account::ProfileManager> profile_manager; + Service::Account::ProfileManager& profile_manager; ControllerNavigation* controller_navigation = nullptr; }; diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui index 22b51f39c..d842b0135 100644 --- a/src/yuzu/configuration/configure_debug.ui +++ b/src/yuzu/configuration/configure_debug.ui @@ -381,7 +381,7 @@ <item row="5" column="0"> <widget class="QCheckBox" name="disable_buffer_reorder"> <property name="toolTip"> - <string><html><head/><body><p>When checked, disables reording of mapped memory uploads which allows to associate uploads with specific draws. May reduce performance in some cases.</p></body></html></string> + <string><html><head/><body><p>When checked, disables reordering of mapped memory uploads which allows to associate uploads with specific draws. May reduce performance in some cases.</p></body></html></string> </property> <property name="text"> <string>Disable Buffer Reorder</string> diff --git a/src/yuzu/configuration/configure_profile_manager.cpp b/src/yuzu/configuration/configure_profile_manager.cpp index 6d2219bf5..fa5f383d6 100644 --- a/src/yuzu/configuration/configure_profile_manager.cpp +++ b/src/yuzu/configuration/configure_profile_manager.cpp @@ -76,9 +76,9 @@ QString GetProfileUsernameFromUser(QWidget* parent, const QString& description_t } } // Anonymous namespace -ConfigureProfileManager::ConfigureProfileManager(const Core::System& system_, QWidget* parent) +ConfigureProfileManager::ConfigureProfileManager(Core::System& system_, QWidget* parent) : QWidget(parent), ui{std::make_unique<Ui::ConfigureProfileManager>()}, - profile_manager(std::make_unique<Service::Account::ProfileManager>()), system{system_} { + profile_manager{system_.GetProfileManager()}, system{system_} { ui->setupUi(this); tree_view = new QTreeView; @@ -149,10 +149,10 @@ void ConfigureProfileManager::SetConfiguration() { } void ConfigureProfileManager::PopulateUserList() { - const auto& profiles = profile_manager->GetAllUsers(); + const auto& profiles = profile_manager.GetAllUsers(); for (const auto& user : profiles) { Service::Account::ProfileBase profile{}; - if (!profile_manager->GetProfileBase(user, profile)) + if (!profile_manager.GetProfileBase(user, profile)) continue; const auto username = Common::StringFromFixedZeroTerminatedBuffer( @@ -167,11 +167,11 @@ void ConfigureProfileManager::PopulateUserList() { } void ConfigureProfileManager::UpdateCurrentUser() { - ui->pm_add->setEnabled(profile_manager->GetUserCount() < Service::Account::MAX_USERS); + ui->pm_add->setEnabled(profile_manager.GetUserCount() < Service::Account::MAX_USERS); - const auto& current_user = profile_manager->GetUser(Settings::values.current_user.GetValue()); + const auto& current_user = profile_manager.GetUser(Settings::values.current_user.GetValue()); ASSERT(current_user); - const auto username = GetAccountUsername(*profile_manager, *current_user); + const auto username = GetAccountUsername(profile_manager, *current_user); scene->clear(); scene->addPixmap( @@ -187,11 +187,11 @@ void ConfigureProfileManager::ApplyConfiguration() { void ConfigureProfileManager::SelectUser(const QModelIndex& index) { Settings::values.current_user = - std::clamp<s32>(index.row(), 0, static_cast<s32>(profile_manager->GetUserCount() - 1)); + std::clamp<s32>(index.row(), 0, static_cast<s32>(profile_manager.GetUserCount() - 1)); UpdateCurrentUser(); - ui->pm_remove->setEnabled(profile_manager->GetUserCount() >= 2); + ui->pm_remove->setEnabled(profile_manager.GetUserCount() >= 2); ui->pm_rename->setEnabled(true); ui->pm_set_image->setEnabled(true); } @@ -204,18 +204,18 @@ void ConfigureProfileManager::AddUser() { } const auto uuid = Common::UUID::MakeRandom(); - profile_manager->CreateNewUser(uuid, username.toStdString()); + profile_manager.CreateNewUser(uuid, username.toStdString()); item_model->appendRow(new QStandardItem{GetIcon(uuid), FormatUserEntryText(username, uuid)}); } void ConfigureProfileManager::RenameUser() { const auto user = tree_view->currentIndex().row(); - const auto uuid = profile_manager->GetUser(user); + const auto uuid = profile_manager.GetUser(user); ASSERT(uuid); Service::Account::ProfileBase profile{}; - if (!profile_manager->GetProfileBase(*uuid, profile)) + if (!profile_manager.GetProfileBase(*uuid, profile)) return; const auto new_username = GetProfileUsernameFromUser(this, tr("Enter a new username:")); @@ -227,7 +227,7 @@ void ConfigureProfileManager::RenameUser() { std::fill(profile.username.begin(), profile.username.end(), '\0'); std::copy(username_std.begin(), username_std.end(), profile.username.begin()); - profile_manager->SetProfileBase(*uuid, profile); + profile_manager.SetProfileBase(*uuid, profile); item_model->setItem( user, 0, @@ -238,9 +238,9 @@ void ConfigureProfileManager::RenameUser() { void ConfigureProfileManager::ConfirmDeleteUser() { const auto index = tree_view->currentIndex().row(); - const auto uuid = profile_manager->GetUser(index); + const auto uuid = profile_manager.GetUser(index); ASSERT(uuid); - const auto username = GetAccountUsername(*profile_manager, *uuid); + const auto username = GetAccountUsername(profile_manager, *uuid); confirm_dialog->SetInfo(username, *uuid, [this, uuid]() { DeleteUser(*uuid); }); confirm_dialog->show(); @@ -252,7 +252,7 @@ void ConfigureProfileManager::DeleteUser(const Common::UUID& uuid) { } UpdateCurrentUser(); - if (!profile_manager->RemoveUser(uuid)) { + if (!profile_manager.RemoveUser(uuid)) { return; } @@ -265,7 +265,7 @@ void ConfigureProfileManager::DeleteUser(const Common::UUID& uuid) { void ConfigureProfileManager::SetUserImage() { const auto index = tree_view->currentIndex().row(); - const auto uuid = profile_manager->GetUser(index); + const auto uuid = profile_manager.GetUser(index); ASSERT(uuid); const auto file = QFileDialog::getOpenFileName(this, tr("Select User Image"), QString(), @@ -317,7 +317,7 @@ void ConfigureProfileManager::SetUserImage() { } } - const auto username = GetAccountUsername(*profile_manager, *uuid); + const auto username = GetAccountUsername(profile_manager, *uuid); item_model->setItem(index, 0, new QStandardItem{GetIcon(*uuid), FormatUserEntryText(username, *uuid)}); UpdateCurrentUser(); diff --git a/src/yuzu/configuration/configure_profile_manager.h b/src/yuzu/configuration/configure_profile_manager.h index c4b1a334e..39560fdd9 100644 --- a/src/yuzu/configuration/configure_profile_manager.h +++ b/src/yuzu/configuration/configure_profile_manager.h @@ -52,7 +52,7 @@ class ConfigureProfileManager : public QWidget { Q_OBJECT public: - explicit ConfigureProfileManager(const Core::System& system_, QWidget* parent = nullptr); + explicit ConfigureProfileManager(Core::System& system_, QWidget* parent = nullptr); ~ConfigureProfileManager() override; void ApplyConfiguration(); @@ -85,7 +85,6 @@ private: std::unique_ptr<Ui::ConfigureProfileManager> ui; bool enabled = false; - std::unique_ptr<Service::Account::ProfileManager> profile_manager; - + Service::Account::ProfileManager& profile_manager; const Core::System& system; }; diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index b056c3717..f31ed7ebb 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -346,7 +346,7 @@ GMainWindow::GMainWindow(std::unique_ptr<QtConfig> config_, bool has_broken_vulk SetDiscordEnabled(UISettings::values.enable_discord_presence.GetValue()); discord_rpc->Update(); - play_time_manager = std::make_unique<PlayTime::PlayTimeManager>(); + play_time_manager = std::make_unique<PlayTime::PlayTimeManager>(system->GetProfileManager()); system->GetRoomNetwork().Init(); @@ -526,8 +526,7 @@ GMainWindow::GMainWindow(std::unique_ptr<QtConfig> config_, bool has_broken_vulk continue; } - const Service::Account::ProfileManager manager; - if (!manager.UserExistsIndex(selected_user)) { + if (!system->GetProfileManager().UserExistsIndex(selected_user)) { LOG_ERROR(Frontend, "Selected user doesn't exist"); continue; } @@ -691,7 +690,7 @@ void GMainWindow::ControllerSelectorRequestExit() { void GMainWindow::ProfileSelectorSelectProfile( const Core::Frontend::ProfileSelectParameters& parameters) { - profile_select_applet = new QtProfileSelectionDialog(system->HIDCore(), this, parameters); + profile_select_applet = new QtProfileSelectionDialog(*system, this, parameters); SCOPE_EXIT({ profile_select_applet->deleteLater(); profile_select_applet = nullptr; @@ -706,8 +705,8 @@ void GMainWindow::ProfileSelectorSelectProfile( return; } - const Service::Account::ProfileManager manager; - const auto uuid = manager.GetUser(static_cast<std::size_t>(profile_select_applet->GetIndex())); + const auto uuid = system->GetProfileManager().GetUser( + static_cast<std::size_t>(profile_select_applet->GetIndex())); if (!uuid.has_value()) { emit ProfileSelectorFinishedSelection(std::nullopt); return; @@ -1856,7 +1855,7 @@ bool GMainWindow::LoadROM(const QString& filename, u64 program_id, std::size_t p bool GMainWindow::SelectAndSetCurrentUser( const Core::Frontend::ProfileSelectParameters& parameters) { - QtProfileSelectionDialog dialog(system->HIDCore(), this, parameters); + QtProfileSelectionDialog dialog(*system, this, parameters); dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint); dialog.setWindowModality(Qt::WindowModal); @@ -2271,7 +2270,7 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target .display_options = {}, .purpose = Service::AM::Applets::UserSelectionPurpose::General, }; - QtProfileSelectionDialog dialog(system->HIDCore(), this, parameters); + QtProfileSelectionDialog dialog(*system, this, parameters); dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint); dialog.setWindowModality(Qt::WindowModal); @@ -2288,8 +2287,8 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target return; } - Service::Account::ProfileManager manager; - const auto user_id = manager.GetUser(static_cast<std::size_t>(index)); + const auto user_id = + system->GetProfileManager().GetUser(static_cast<std::size_t>(index)); ASSERT(user_id); const auto user_save_data_path = FileSys::SaveDataFactory::GetFullPath( diff --git a/src/yuzu/multiplayer/lobby.cpp b/src/yuzu/multiplayer/lobby.cpp index 603e9ae3d..41692c05b 100644 --- a/src/yuzu/multiplayer/lobby.cpp +++ b/src/yuzu/multiplayer/lobby.cpp @@ -27,9 +27,9 @@ Lobby::Lobby(QWidget* parent, QStandardItemModel* list, std::shared_ptr<Core::AnnounceMultiplayerSession> session, Core::System& system_) : QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint), - ui(std::make_unique<Ui::Lobby>()), announce_multiplayer_session(session), - profile_manager(std::make_unique<Service::Account::ProfileManager>()), system{system_}, - room_network{system.GetRoomNetwork()} { + ui(std::make_unique<Ui::Lobby>()), + announce_multiplayer_session(session), system{system_}, room_network{ + system.GetRoomNetwork()} { ui->setupUi(this); // setup the watcher for background connections @@ -299,14 +299,15 @@ void Lobby::OnRefreshLobby() { } std::string Lobby::GetProfileUsername() { - const auto& current_user = profile_manager->GetUser(Settings::values.current_user.GetValue()); + const auto& current_user = + system.GetProfileManager().GetUser(Settings::values.current_user.GetValue()); Service::Account::ProfileBase profile{}; if (!current_user.has_value()) { return ""; } - if (!profile_manager->GetProfileBase(*current_user, profile)) { + if (!system.GetProfileManager().GetProfileBase(*current_user, profile)) { return ""; } diff --git a/src/yuzu/multiplayer/lobby.h b/src/yuzu/multiplayer/lobby.h index 2674ae7c3..e78c9cae3 100644 --- a/src/yuzu/multiplayer/lobby.h +++ b/src/yuzu/multiplayer/lobby.h @@ -24,10 +24,6 @@ namespace Core { class System; } -namespace Service::Account { -class ProfileManager; -} - /** * Listing of all public games pulled from services. The lobby should be simple enough for users to * find the game they want to play, and join it. @@ -103,7 +99,6 @@ private: QFutureWatcher<AnnounceMultiplayerRoom::RoomList> room_list_watcher; std::weak_ptr<Core::AnnounceMultiplayerSession> announce_multiplayer_session; - std::unique_ptr<Service::Account::ProfileManager> profile_manager; QFutureWatcher<void>* watcher; Validation validation; Core::System& system; diff --git a/src/yuzu/play_time_manager.cpp b/src/yuzu/play_time_manager.cpp index 155c36b7d..94c99274d 100644 --- a/src/yuzu/play_time_manager.cpp +++ b/src/yuzu/play_time_manager.cpp @@ -20,8 +20,8 @@ struct PlayTimeElement { PlayTime play_time; }; -std::optional<std::filesystem::path> GetCurrentUserPlayTimePath() { - const Service::Account::ProfileManager manager; +std::optional<std::filesystem::path> GetCurrentUserPlayTimePath( + const Service::Account::ProfileManager& manager) { const auto uuid = manager.GetUser(static_cast<s32>(Settings::values.current_user)); if (!uuid.has_value()) { return std::nullopt; @@ -30,8 +30,9 @@ std::optional<std::filesystem::path> GetCurrentUserPlayTimePath() { uuid->RawString().append(".bin"); } -[[nodiscard]] bool ReadPlayTimeFile(PlayTimeDatabase& out_play_time_db) { - const auto filename = GetCurrentUserPlayTimePath(); +[[nodiscard]] bool ReadPlayTimeFile(PlayTimeDatabase& out_play_time_db, + const Service::Account::ProfileManager& manager) { + const auto filename = GetCurrentUserPlayTimePath(manager); if (!filename.has_value()) { LOG_ERROR(Frontend, "Failed to get current user path"); @@ -66,8 +67,9 @@ std::optional<std::filesystem::path> GetCurrentUserPlayTimePath() { return true; } -[[nodiscard]] bool WritePlayTimeFile(const PlayTimeDatabase& play_time_db) { - const auto filename = GetCurrentUserPlayTimePath(); +[[nodiscard]] bool WritePlayTimeFile(const PlayTimeDatabase& play_time_db, + const Service::Account::ProfileManager& manager) { + const auto filename = GetCurrentUserPlayTimePath(manager); if (!filename.has_value()) { LOG_ERROR(Frontend, "Failed to get current user path"); @@ -96,8 +98,9 @@ std::optional<std::filesystem::path> GetCurrentUserPlayTimePath() { } // namespace -PlayTimeManager::PlayTimeManager() { - if (!ReadPlayTimeFile(database)) { +PlayTimeManager::PlayTimeManager(Service::Account::ProfileManager& profile_manager) + : manager{profile_manager} { + if (!ReadPlayTimeFile(database, manager)) { LOG_ERROR(Frontend, "Failed to read play time database! Resetting to default."); } } @@ -142,7 +145,7 @@ void PlayTimeManager::AutoTimestamp(std::stop_token stop_token) { } void PlayTimeManager::Save() { - if (!WritePlayTimeFile(database)) { + if (!WritePlayTimeFile(database, manager)) { LOG_ERROR(Frontend, "Failed to update play time database!"); } } diff --git a/src/yuzu/play_time_manager.h b/src/yuzu/play_time_manager.h index 5f96f3447..1714b9131 100644 --- a/src/yuzu/play_time_manager.h +++ b/src/yuzu/play_time_manager.h @@ -11,6 +11,10 @@ #include "common/common_types.h" #include "common/polyfill_thread.h" +namespace Service::Account { +class ProfileManager; +} + namespace PlayTime { using ProgramId = u64; @@ -19,7 +23,7 @@ using PlayTimeDatabase = std::map<ProgramId, PlayTime>; class PlayTimeManager { public: - explicit PlayTimeManager(); + explicit PlayTimeManager(Service::Account::ProfileManager& profile_manager); ~PlayTimeManager(); YUZU_NON_COPYABLE(PlayTimeManager); @@ -32,11 +36,13 @@ public: void Stop(); private: + void AutoTimestamp(std::stop_token stop_token); + void Save(); + PlayTimeDatabase database; u64 running_program_id; std::jthread play_time_thread; - void AutoTimestamp(std::stop_token stop_token); - void Save(); + Service::Account::ProfileManager& manager; }; QString ReadablePlayTime(qulonglong time_seconds); diff --git a/vcpkg.json b/vcpkg.json index da4e9edb9..01a4657d4 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -1,7 +1,7 @@ { "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json", "name": "yuzu", - "builtin-baseline": "cbf56573a987527b39272e88cbdd11389b78c6e4", + "builtin-baseline": "a42af01b72c28a8e1d7b48107b33e4f286a55ef6", "version": "1.0", "dependencies": [ "boost-algorithm", @@ -50,7 +50,7 @@ }, { "name": "fmt", - "version": "10.0.0" + "version": "10.1.1" } ] } |