From 514e3634722c35bf4b1ae0044a65d23752c18962 Mon Sep 17 00:00:00 2001 From: Berk Date: Tue, 27 Jan 2026 11:09:32 +0300 Subject: [PATCH 01/11] Add Docker build support and documentation (#3960) * Docker builder support * update licenses * oops I forgot change this description --- README.md | 7 +- .../.devcontainer/devcontainer.json | 45 +++++++++ documents/Docker Builder/.docker/Dockerfile | 38 ++++++++ documents/Docker Builder/docker-compose.yml | 10 ++ documents/building-docker.md | 91 +++++++++++++++++++ 5 files changed, 190 insertions(+), 1 deletion(-) create mode 100644 documents/Docker Builder/.devcontainer/devcontainer.json create mode 100644 documents/Docker Builder/.docker/Dockerfile create mode 100644 documents/Docker Builder/docker-compose.yml create mode 100644 documents/building-docker.md diff --git a/README.md b/README.md index e43a2408d..0fb5c26ed 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ @@ -58,6 +58,11 @@ This project began for fun. Given our limited free time, it may take some time b # Building +## Docker + +For building shadPS4 in a containerized environment using Docker and VSCode, check the instructions here: +[**Docker Build Instructions**](https://github.com/shadps4-emu/shadPS4/blob/main/documents/building-docker.md) + ## Windows Check the build instructions for [**Windows**](https://github.com/shadps4-emu/shadPS4/blob/main/documents/building-windows.md). diff --git a/documents/Docker Builder/.devcontainer/devcontainer.json b/documents/Docker Builder/.devcontainer/devcontainer.json new file mode 100644 index 000000000..32e301bd9 --- /dev/null +++ b/documents/Docker Builder/.devcontainer/devcontainer.json @@ -0,0 +1,45 @@ +// SPDX-FileCopyrightText: 2026 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +{ + "name": "shadPS4-dev", + "dockerComposeFile": [ + "../docker-compose.yml" + ], + "containerEnv": { + "GITHUB_TOKEN": "${localEnv:GITHUB_TOKEN}", + "GITHUB_USER": "${localEnv:GITHUB_USER}" + }, + "service": "shadps4", + "workspaceFolder": "/workspaces/shadPS4", + "remoteUser": "root", + "shutdownAction": "none", + "customizations": { + "vscode": { + "extensions": [ + "llvm-vs-code-extensions.vscode-clangd" + ], + "settings": { + "C_Cpp.intelliSenseEngine": "disabled", + "clangd.arguments": [ + "--background-index", + "--clang-tidy", + "--completion-style=detailed", + "--header-insertion=never" + ] + } + } + }, + "settings": { + "cmake.configureOnOpen": false, + "cmake.generator": "Unix Makefiles", + "cmake.environment": { + "CC": "clang", + "CXX": "clang++" + }, + "cmake.configureSettings": { + "CMAKE_CXX_STANDARD": "23", + "CMAKE_CXX_STANDARD_REQUIRED": "ON" + } + } +} \ No newline at end of file diff --git a/documents/Docker Builder/.docker/Dockerfile b/documents/Docker Builder/.docker/Dockerfile new file mode 100644 index 000000000..285144374 --- /dev/null +++ b/documents/Docker Builder/.docker/Dockerfile @@ -0,0 +1,38 @@ +# SPDX-FileCopyrightText: 2026 shadPS4 Emulator Project +# SPDX-License-Identifier: GPL-2.0-or-later + +FROM ubuntu:24.04 + +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && apt-get install -y \ + build-essential \ + clang \ + git \ + ca-certificates \ + wget \ + libasound2-dev \ + libpulse-dev \ + libopenal-dev \ + libssl-dev \ + zlib1g-dev \ + libedit-dev \ + libudev-dev \ + libevdev-dev \ + libsdl2-dev \ + libjack-dev \ + libsndio-dev \ + libxtst-dev \ + libvulkan-dev \ + vulkan-validationlayers \ + libpng-dev \ + clang-tidy \ + && rm -rf /var/lib/apt/lists/* + +RUN wget -qO - https://apt.kitware.com/keys/kitware-archive-latest.asc | gpg --dearmor -o /usr/share/keyrings/kitware-archive-keyring.gpg \ + && echo "deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ noble main" > /etc/apt/sources.list.d/kitware.list \ + && apt-get update \ + && apt-get install -y cmake \ + && rm -rf /var/lib/apt/lists/*/* + +WORKDIR /workspaces/shadPS4 \ No newline at end of file diff --git a/documents/Docker Builder/docker-compose.yml b/documents/Docker Builder/docker-compose.yml new file mode 100644 index 000000000..39efefa72 --- /dev/null +++ b/documents/Docker Builder/docker-compose.yml @@ -0,0 +1,10 @@ +# SPDX-FileCopyrightText: 2026 shadPS4 Emulator Project +# SPDX-License-Identifier: GPL-2.0-or-later + +services: + shadps4: + build: + context: ./.docker + volumes: + - ./emu:/workspaces/shadPS4:cached + tty: true diff --git a/documents/building-docker.md b/documents/building-docker.md new file mode 100644 index 000000000..95be00044 --- /dev/null +++ b/documents/building-docker.md @@ -0,0 +1,91 @@ + + +# Building shadPS4 with Docker and VSCode Support + +This guide explains how to build **shadPS4** using Docker while keeping full compatibility with **VSCode** development. + +--- + +## Prerequisites + +Before starting, ensure you have: + +- **Docker Engine** or **Docker Desktop** installed + [Installation Guide](https://docs.docker.com/engine/install/) + +- **Git** installed on your system. + +--- + +## Step 1: Prepare the Docker Environment + +Inside the container (or on your host if mounting volumes): + +1. Navigate to the repository folder containing the Docker Builder folder: + +```bash +cd +``` + +2. Start the Docker container: + +```bash +docker compose up -d +``` + +This will spin up a container with all the necessary build dependencies, including Clang, CMake, SDL2, Vulkan, and more. + +## Step 2: Clone shadPS4 Source + +```bash +mkdir emu +cd emu +git clone --recursive https://github.com/shadps4-emu/shadPS4.git . + +or your fork link. +``` + +3. Initialize submodules: + +```bash +git submodule update --init --recursive +``` + +## Step 3: Build with CMake + +Generate the build directory and configure the project using Clang: + +```bash +cmake -S . -B build/ -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ +``` + +Then build the project: + +```bash +cmake --build ./build --parallel $(nproc) +``` + +* Tip: To enable debug builds, add -DCMAKE_BUILD_TYPE=Debug to the CMake command. + +--- + +After a successful build, the executable is located at: + +```bash +./build/shadps4 +``` + +## Step 4: VSCode Integration + +1. Open the repository in VSCode. +2. The CMake Tools extension should automatically detect the build directory inside the container or on your host. +3. You can configure build options, build, and debug directly from the VSCode interface without extra manual setup. + +# Notes + +* The Docker environment contains all dependencies, so you don’t need to install anything manually. +* Using Clang inside Docker ensures consistent builds across Linux and macOS runners. +* GitHub Actions are recommended for cross-platform builds, including Windows .exe output, which is not trivial to produce locally without Visual Studio or clang-cl. \ No newline at end of file From 4ba0e6267015dba446509526d373a11fb6cba9c2 Mon Sep 17 00:00:00 2001 From: Stephen Miller <56742918+StevenMiller123@users.noreply.github.com> Date: Tue, 27 Jan 2026 04:25:23 -0600 Subject: [PATCH 02/11] Kernel.Vmm: Attempt to address race conditions involving ClampRangeSize, CopySparseMemory, and TryWriteBacking (#3956) * no no * Adjust locking strategy Use a separate mutex for the initial error checks + GPU unmap instead of using the reader lock. Make sure all writers lock this separate mutex, and for those that don't perform GPU unmaps, lock the writer lock immediately too. This gets around every race condition I've envisioned so far, and hopefully does the trick? * Clang * Always GPU unmap GPU unmaps have logic built-in to only run on mapped areas. Not sure if userfaultfd would work with this, but since that's already broken anyway, I'll let reviewers decide that. Without doing this, I'd need to do an extra pass through VMAs to find what all needs to be GPU modified before I can unmap from GPU, then perform remaining unmap work. Especially for places like MapMemory, that's a lot of code bloat. * Fixups * Update memory.cpp * Rename mutex It's really just a mutex for the sole purpose of dealing with GPU unmaps, so unmap_mutex is a bit more fitting than transition_mutex --- src/common/shared_first_mutex.h | 9 ++ src/core/address_space.cpp | 8 +- src/core/address_space.h | 3 +- src/core/memory.cpp | 214 +++++++++++++++++++------------- src/core/memory.h | 9 +- 5 files changed, 145 insertions(+), 98 deletions(-) diff --git a/src/common/shared_first_mutex.h b/src/common/shared_first_mutex.h index b150c956b..fcf9d0c4f 100644 --- a/src/common/shared_first_mutex.h +++ b/src/common/shared_first_mutex.h @@ -17,6 +17,15 @@ public: writer_active = true; } + bool try_lock() { + std::lock_guard lock(mtx); + if (writer_active || readers > 0) { + return false; + } + writer_active = true; + return true; + } + void unlock() { std::lock_guard lock(mtx); writer_active = false; diff --git a/src/core/address_space.cpp b/src/core/address_space.cpp index f4a6b640e..194f676f9 100644 --- a/src/core/address_space.cpp +++ b/src/core/address_space.cpp @@ -709,7 +709,7 @@ struct AddressSpace::Impl { return ret; } - void Unmap(VAddr virtual_addr, u64 size, bool) { + void Unmap(VAddr virtual_addr, u64 size) { // Check to see if we are adjacent to any regions. VAddr start_address = virtual_addr; VAddr end_address = start_address + size; @@ -792,12 +792,8 @@ void* AddressSpace::MapFile(VAddr virtual_addr, u64 size, u64 offset, u32 prot, #endif } -void AddressSpace::Unmap(VAddr virtual_addr, u64 size, bool has_backing) { -#ifdef _WIN32 +void AddressSpace::Unmap(VAddr virtual_addr, u64 size) { impl->Unmap(virtual_addr, size); -#else - impl->Unmap(virtual_addr, size, has_backing); -#endif } void AddressSpace::Protect(VAddr virtual_addr, u64 size, MemoryPermission perms) { diff --git a/src/core/address_space.h b/src/core/address_space.h index fa47bb47e..b71f66f28 100644 --- a/src/core/address_space.h +++ b/src/core/address_space.h @@ -79,8 +79,9 @@ public: void* MapFile(VAddr virtual_addr, u64 size, u64 offset, u32 prot, uintptr_t fd); /// Unmaps specified virtual memory area. - void Unmap(VAddr virtual_addr, u64 size, bool has_backing); + void Unmap(VAddr virtual_addr, u64 size); + /// Protects requested region. void Protect(VAddr virtual_addr, u64 size, MemoryPermission perms); // Returns an interval set containing all usable regions. diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 32518907a..1aeecebf1 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -79,6 +79,7 @@ u64 MemoryManager::ClampRangeSize(VAddr virtual_addr, u64 size) { return size; } + std::shared_lock lk{mutex}; ASSERT_MSG(IsValidMapping(virtual_addr), "Attempted to access invalid address {:#x}", virtual_addr); @@ -117,6 +118,7 @@ void MemoryManager::SetPrtArea(u32 id, VAddr address, u64 size) { } void MemoryManager::CopySparseMemory(VAddr virtual_addr, u8* dest, u64 size) { + std::shared_lock lk{mutex}; ASSERT_MSG(IsValidMapping(virtual_addr), "Attempted to access invalid address {:#x}", virtual_addr); @@ -137,6 +139,7 @@ void MemoryManager::CopySparseMemory(VAddr virtual_addr, u8* dest, u64 size) { bool MemoryManager::TryWriteBacking(void* address, const void* data, u64 size) { const VAddr virtual_addr = std::bit_cast(address); + std::shared_lock lk{mutex}; ASSERT_MSG(IsValidMapping(virtual_addr, size), "Attempted to access invalid address {:#x}", virtual_addr); @@ -263,9 +266,7 @@ s32 MemoryManager::Free(PAddr phys_addr, u64 size, bool is_checked) { return ORBIS_OK; } - // Lock mutex - std::scoped_lock lk{mutex}; - + std::scoped_lock lk{unmap_mutex}; // If this is a checked free, then all direct memory in range must be allocated. std::vector> free_list; u64 remaining_size = size; @@ -316,6 +317,17 @@ s32 MemoryManager::Free(PAddr phys_addr, u64 size, bool is_checked) { } } } + + // Early unmap from GPU to avoid deadlocking. + for (auto& [addr, unmap_size] : remove_list) { + if (IsValidGpuMapping(addr, unmap_size)) { + rasterizer->UnmapMemory(addr, unmap_size); + } + } + + // Acquire writer lock + std::scoped_lock lk2{mutex}; + for (const auto& [addr, size] : remove_list) { LOG_INFO(Kernel_Vmm, "Unmapping direct mapping {:#x} with size {:#x}", addr, size); UnmapMemoryImpl(addr, size); @@ -337,7 +349,7 @@ s32 MemoryManager::Free(PAddr phys_addr, u64 size, bool is_checked) { } s32 MemoryManager::PoolCommit(VAddr virtual_addr, u64 size, MemoryProt prot, s32 mtype) { - std::scoped_lock lk{mutex}; + std::scoped_lock lk{mutex, unmap_mutex}; ASSERT_MSG(IsValidMapping(virtual_addr, size), "Attempted to access invalid address {:#x}", virtual_addr); @@ -429,54 +441,31 @@ s32 MemoryManager::PoolCommit(VAddr virtual_addr, u64 size, MemoryProt prot, s32 return ORBIS_OK; } -std::pair MemoryManager::CreateArea( - VAddr virtual_addr, u64 size, MemoryProt prot, MemoryMapFlags flags, VMAType type, - std::string_view name, u64 alignment) { - - // Limit the minimum address to SystemManagedVirtualBase to prevent hardware-specific issues. - VAddr mapped_addr = (virtual_addr == 0) ? impl.SystemManagedVirtualBase() : virtual_addr; - - // Fixed mapping means the virtual address must exactly match the provided one. - // On a PS4, the Fixed flag is ignored if address 0 is provided. - if (True(flags & MemoryMapFlags::Fixed) && virtual_addr != 0) { - ASSERT_MSG(IsValidMapping(mapped_addr, size), "Attempted to access invalid address {:#x}", - mapped_addr); - auto vma = FindVMA(mapped_addr)->second; - // There's a possible edge case where we're mapping to a partially reserved range. - // To account for this, unmap any reserved areas within this mapping range first. - auto unmap_addr = mapped_addr; +MemoryManager::VMAHandle MemoryManager::CreateArea(VAddr virtual_addr, u64 size, MemoryProt prot, + MemoryMapFlags flags, VMAType type, + std::string_view name, u64 alignment) { + // Locate the VMA representing the requested region + auto vma = FindVMA(virtual_addr)->second; + if (True(flags & MemoryMapFlags::Fixed)) { + // If fixed is specified, map directly to the region of virtual_addr + size. + // Callers should check to ensure the NoOverwrite flag is handled appropriately beforehand. + auto unmap_addr = virtual_addr; auto unmap_size = size; - - // If flag NoOverwrite is provided, don't overwrite mapped VMAs. - // When it isn't provided, VMAs can be overwritten regardless of if they're mapped. - while ((False(flags & MemoryMapFlags::NoOverwrite) || vma.IsFree()) && - unmap_addr < mapped_addr + size) { + while (unmap_size > 0) { auto unmapped = UnmapBytesFromEntry(unmap_addr, vma, unmap_size); unmap_addr += unmapped; unmap_size -= unmapped; vma = FindVMA(unmap_addr)->second; } - - vma = FindVMA(mapped_addr)->second; - auto remaining_size = vma.base + vma.size - mapped_addr; - if (!vma.IsFree() || remaining_size < size) { - LOG_ERROR(Kernel_Vmm, "Unable to map {:#x} bytes at address {:#x}", size, mapped_addr); - return {ORBIS_KERNEL_ERROR_ENOMEM, vma_map.end()}; - } - } else { - // When MemoryMapFlags::Fixed is not specified, and mapped_addr is 0, - // search from address 0x200000000 instead. - alignment = alignment > 0 ? alignment : 16_KB; - mapped_addr = virtual_addr == 0 ? 0x200000000 : mapped_addr; - mapped_addr = SearchFree(mapped_addr, size, alignment); - if (mapped_addr == -1) { - // No suitable memory areas to map to - return {ORBIS_KERNEL_ERROR_ENOMEM, vma_map.end()}; - } } + vma = FindVMA(virtual_addr)->second; + + // By this point, vma should be free and ready to map. + // Caller performs address searches for non-fixed mappings before this. + ASSERT_MSG(vma.IsFree(), "VMA to map is not free"); // Create a memory area representing this mapping. - const auto new_vma_handle = CarveVMA(mapped_addr, size); + const auto new_vma_handle = CarveVMA(virtual_addr, size); auto& new_vma = new_vma_handle->second; const bool is_exec = True(prot & MemoryProt::CpuExec); if (True(prot & MemoryProt::CpuWrite)) { @@ -484,12 +473,13 @@ std::pair MemoryManager::CreateArea( prot |= MemoryProt::CpuRead; } + // Update VMA appropriately. new_vma.disallow_merge = True(flags & MemoryMapFlags::NoCoalesce); new_vma.prot = prot; new_vma.name = name; new_vma.type = type; new_vma.phys_areas.clear(); - return {ORBIS_OK, new_vma_handle}; + return new_vma_handle; } s32 MemoryManager::MapMemory(void** out_addr, VAddr virtual_addr, u64 size, MemoryProt prot, @@ -504,8 +494,7 @@ s32 MemoryManager::MapMemory(void** out_addr, VAddr virtual_addr, u64 size, Memo total_flexible_size - flexible_usage, size); return ORBIS_KERNEL_ERROR_EINVAL; } - - std::scoped_lock lk{mutex}; + std::scoped_lock lk{unmap_mutex}; PhysHandle dmem_area; // Validate the requested physical address range @@ -538,12 +527,37 @@ s32 MemoryManager::MapMemory(void** out_addr, VAddr virtual_addr, u64 size, Memo } } - auto [result, new_vma_handle] = - CreateArea(virtual_addr, size, prot, flags, type, name, alignment); - if (result != ORBIS_OK) { - return result; + if (True(flags & MemoryMapFlags::Fixed) && True(flags & MemoryMapFlags::NoOverwrite)) { + // Perform necessary error checking for Fixed & NoOverwrite case + ASSERT_MSG(IsValidMapping(virtual_addr, size), "Attempted to access invalid address {:#x}", + virtual_addr); + auto vma = FindVMA(virtual_addr)->second; + auto remaining_size = vma.base + vma.size - virtual_addr; + if (!vma.IsFree() || remaining_size < size) { + LOG_ERROR(Kernel_Vmm, "Unable to map {:#x} bytes at address {:#x}", size, virtual_addr); + return ORBIS_KERNEL_ERROR_ENOMEM; + } + } else if (False(flags & MemoryMapFlags::Fixed)) { + // Find a free virtual addr to map + alignment = alignment > 0 ? alignment : 16_KB; + virtual_addr = virtual_addr == 0 ? DEFAULT_MAPPING_BASE : virtual_addr; + virtual_addr = SearchFree(virtual_addr, size, alignment); + if (virtual_addr == -1) { + // No suitable memory areas to map to + return ORBIS_KERNEL_ERROR_ENOMEM; + } } + // Perform early GPU unmap to avoid potential deadlocks + if (IsValidGpuMapping(virtual_addr, size)) { + rasterizer->UnmapMemory(virtual_addr, size); + } + + // Acquire writer lock. + std::scoped_lock lk2{mutex}; + + // Create VMA representing this mapping. + auto new_vma_handle = CreateArea(virtual_addr, size, prot, flags, type, name, alignment); auto& new_vma = new_vma_handle->second; auto mapped_addr = new_vma.base; bool is_exec = True(prot & MemoryProt::CpuExec); @@ -590,7 +604,7 @@ s32 MemoryManager::MapMemory(void** out_addr, VAddr virtual_addr, u64 size, Memo // Map the physical memory for this direct memory mapping. auto phys_addr_to_search = phys_addr; u64 remaining_size = size; - dmem_area = FindDmemArea(phys_addr); + auto dmem_area = FindDmemArea(phys_addr); while (dmem_area != dmem_map.end() && remaining_size > 0) { // Carve a new dmem area in place of this one with the appropriate type. // Ensure the carved area only covers the current dmem area. @@ -638,14 +652,15 @@ s32 MemoryManager::MapMemory(void** out_addr, VAddr virtual_addr, u64 size, Memo rasterizer->MapMemory(mapped_addr, size); } } + return ORBIS_OK; } s32 MemoryManager::MapFile(void** out_addr, VAddr virtual_addr, u64 size, MemoryProt prot, MemoryMapFlags flags, s32 fd, s64 phys_addr) { - std::scoped_lock lk{mutex}; + uintptr_t handle = 0; + std::scoped_lock lk{unmap_mutex}; // Get the file to map - auto* h = Common::Singleton::Instance(); auto file = h->GetFile(fd); if (file == nullptr) { @@ -663,12 +678,13 @@ s32 MemoryManager::MapFile(void** out_addr, VAddr virtual_addr, u64 size, Memory prot |= MemoryProt::CpuRead; } - const auto handle = file->f.GetFileMapping(); + handle = file->f.GetFileMapping(); if (False(file->f.GetAccessMode() & Common::FS::FileAccessMode::Write) || False(file->f.GetAccessMode() & Common::FS::FileAccessMode::Append)) { - // If the file does not have write access, ensure prot does not contain write permissions. - // On real hardware, these mappings succeed, but the memory cannot be written to. + // If the file does not have write access, ensure prot does not contain write + // permissions. On real hardware, these mappings succeed, but the memory cannot be + // written to. prot &= ~MemoryProt::CpuWrite; } @@ -682,13 +698,38 @@ s32 MemoryManager::MapFile(void** out_addr, VAddr virtual_addr, u64 size, Memory prot &= ~MemoryProt::CpuExec; } - auto [result, new_vma_handle] = - CreateArea(virtual_addr, size, prot, flags, VMAType::File, "anon", 0); - if (result != ORBIS_OK) { - return result; + if (True(flags & MemoryMapFlags::Fixed) && False(flags & MemoryMapFlags::NoOverwrite)) { + ASSERT_MSG(IsValidMapping(virtual_addr, size), "Attempted to access invalid address {:#x}", + virtual_addr); + auto vma = FindVMA(virtual_addr)->second; + + auto remaining_size = vma.base + vma.size - virtual_addr; + if (!vma.IsFree() || remaining_size < size) { + LOG_ERROR(Kernel_Vmm, "Unable to map {:#x} bytes at address {:#x}", size, virtual_addr); + return ORBIS_KERNEL_ERROR_ENOMEM; + } + } else if (False(flags & MemoryMapFlags::Fixed)) { + virtual_addr = virtual_addr == 0 ? DEFAULT_MAPPING_BASE : virtual_addr; + virtual_addr = SearchFree(virtual_addr, size, 16_KB); + if (virtual_addr == -1) { + // No suitable memory areas to map to + return ORBIS_KERNEL_ERROR_ENOMEM; + } } + // Perform early GPU unmap to avoid potential deadlocks + if (IsValidGpuMapping(virtual_addr, size)) { + rasterizer->UnmapMemory(virtual_addr, size); + } + + // Aquire writer lock + std::scoped_lock lk2{mutex}; + + // Update VMA map and map to address space. + auto new_vma_handle = CreateArea(virtual_addr, size, prot, flags, VMAType::File, "anon", 0); + auto& new_vma = new_vma_handle->second; + new_vma.fd = fd; auto mapped_addr = new_vma.base; bool is_exec = True(prot & MemoryProt::CpuExec); @@ -699,7 +740,7 @@ s32 MemoryManager::MapFile(void** out_addr, VAddr virtual_addr, u64 size, Memory } s32 MemoryManager::PoolDecommit(VAddr virtual_addr, u64 size) { - std::scoped_lock lk{mutex}; + std::scoped_lock lk{unmap_mutex}; ASSERT_MSG(IsValidMapping(virtual_addr, size), "Attempted to access invalid address {:#x}", virtual_addr); @@ -713,6 +754,14 @@ s32 MemoryManager::PoolDecommit(VAddr virtual_addr, u64 size) { it++; } + // Perform early GPU unmap to avoid potential deadlocks + if (IsValidGpuMapping(virtual_addr, size)) { + rasterizer->UnmapMemory(virtual_addr, size); + } + + // Aquire writer mutex + std::scoped_lock lk2{mutex}; + // Loop through all vmas in the area, unmap them. u64 remaining_size = size; VAddr current_addr = virtual_addr; @@ -721,13 +770,7 @@ s32 MemoryManager::PoolDecommit(VAddr virtual_addr, u64 size) { const auto& vma_base = handle->second; const auto start_in_vma = current_addr - vma_base.base; const auto size_in_vma = std::min(remaining_size, vma_base.size - start_in_vma); - if (vma_base.type == VMAType::Pooled) { - // We always map PoolCommitted memory to GPU, so unmap when decomitting. - if (IsValidGpuMapping(current_addr, size_in_vma)) { - rasterizer->UnmapMemory(current_addr, size_in_vma); - } - // Track how much pooled memory is decommitted pool_budget += size_in_vma; @@ -772,7 +815,7 @@ s32 MemoryManager::PoolDecommit(VAddr virtual_addr, u64 size) { } // Unmap from address space - impl.Unmap(virtual_addr, size, true); + impl.Unmap(virtual_addr, size); // Tracy memory tracking breaks from merging memory areas. Disabled for now. // TRACK_FREE(virtual_addr, "VMEM"); @@ -783,29 +826,32 @@ s32 MemoryManager::UnmapMemory(VAddr virtual_addr, u64 size) { if (size == 0) { return ORBIS_OK; } - std::scoped_lock lk{mutex}; + + std::scoped_lock lk{unmap_mutex}; + // Align address and size appropriately virtual_addr = Common::AlignDown(virtual_addr, 16_KB); size = Common::AlignUp(size, 16_KB); ASSERT_MSG(IsValidMapping(virtual_addr, size), "Attempted to access invalid address {:#x}", virtual_addr); - u64 bytes_unmapped = UnmapMemoryImpl(virtual_addr, size); - return bytes_unmapped; + + // If the requested range has GPU access, unmap from GPU. + if (IsValidGpuMapping(virtual_addr, size)) { + rasterizer->UnmapMemory(virtual_addr, size); + } + + // Acquire writer lock. + std::scoped_lock lk2{mutex}; + return UnmapMemoryImpl(virtual_addr, size); } u64 MemoryManager::UnmapBytesFromEntry(VAddr virtual_addr, VirtualMemoryArea vma_base, u64 size) { const auto start_in_vma = virtual_addr - vma_base.base; const auto size_in_vma = std::min(vma_base.size - start_in_vma, size); const auto vma_type = vma_base.type; - const bool has_backing = HasPhysicalBacking(vma_base) || vma_base.type == VMAType::File; - const bool readonly_file = - vma_base.prot == MemoryProt::CpuRead && vma_base.type == VMAType::File; - const bool is_exec = True(vma_base.prot & MemoryProt::CpuExec); - if (vma_base.type == VMAType::Free || vma_base.type == VMAType::Pooled) { return size_in_vma; } - PAddr phys_base = 0; VAddr current_addr = virtual_addr; if (vma_base.phys_areas.size() > 0) { u64 size_to_free = size_in_vma; @@ -860,14 +906,9 @@ u64 MemoryManager::UnmapBytesFromEntry(VAddr virtual_addr, VirtualMemoryArea vma if (vma_type != VMAType::Reserved && vma_type != VMAType::PoolReserved) { // Unmap the memory region. - impl.Unmap(virtual_addr, size_in_vma, has_backing); + impl.Unmap(virtual_addr, size_in_vma); // Tracy memory tracking breaks from merging memory areas. Disabled for now. // TRACK_FREE(virtual_addr, "VMEM"); - - // If this mapping has GPU access, unmap from GPU. - if (IsValidGpuMapping(virtual_addr, size)) { - rasterizer->UnmapMemory(virtual_addr, size); - } } return size_in_vma; } @@ -983,7 +1024,7 @@ s32 MemoryManager::Protect(VAddr addr, u64 size, MemoryProt prot) { } // Ensure the range to modify is valid - std::scoped_lock lk{mutex}; + std::scoped_lock lk{mutex, unmap_mutex}; ASSERT_MSG(IsValidMapping(addr, size), "Attempted to access invalid address {:#x}", addr); // Appropriately restrict flags. @@ -1141,7 +1182,7 @@ s32 MemoryManager::DirectQueryAvailable(PAddr search_start, PAddr search_end, u6 } s32 MemoryManager::SetDirectMemoryType(VAddr addr, u64 size, s32 memory_type) { - std::scoped_lock lk{mutex}; + std::scoped_lock lk{mutex, unmap_mutex}; ASSERT_MSG(IsValidMapping(addr, size), "Attempted to access invalid address {:#x}", addr); @@ -1188,7 +1229,7 @@ s32 MemoryManager::SetDirectMemoryType(VAddr addr, u64 size, s32 memory_type) { } void MemoryManager::NameVirtualRange(VAddr virtual_addr, u64 size, std::string_view name) { - std::scoped_lock lk{mutex}; + std::scoped_lock lk{mutex, unmap_mutex}; // Sizes are aligned up to the nearest 16_KB u64 aligned_size = Common::AlignUp(size, 16_KB); @@ -1246,7 +1287,6 @@ s32 MemoryManager::IsStack(VAddr addr, void** start, void** end) { ASSERT_MSG(IsValidMapping(addr), "Attempted to access invalid address {:#x}", addr); const auto& vma = FindVMA(addr)->second; if (vma.IsFree()) { - mutex.unlock_shared(); return ORBIS_KERNEL_ERROR_EACCES; } diff --git a/src/core/memory.h b/src/core/memory.h index 92a1016bf..f9ae64942 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -28,6 +28,8 @@ class MemoryMapViewer; namespace Core { +constexpr u64 DEFAULT_MAPPING_BASE = 0x200000000; + enum class MemoryProt : u32 { NoAccess = 0, CpuRead = 1, @@ -304,10 +306,8 @@ private: vma.type == VMAType::Pooled; } - std::pair CreateArea(VAddr virtual_addr, u64 size, - MemoryProt prot, MemoryMapFlags flags, - VMAType type, std::string_view name, - u64 alignment); + VMAHandle CreateArea(VAddr virtual_addr, u64 size, MemoryProt prot, MemoryMapFlags flags, + VMAType type, std::string_view name, u64 alignment); VAddr SearchFree(VAddr virtual_addr, u64 size, u32 alignment); @@ -333,6 +333,7 @@ private: PhysMap fmem_map; VMAMap vma_map; Common::SharedFirstMutex mutex{}; + std::mutex unmap_mutex{}; u64 total_direct_size{}; u64 total_flexible_size{}; u64 flexible_usage{}; From 1e059cac04426deef931ed9198a824083bca8038 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Tue, 27 Jan 2026 11:27:56 +0100 Subject: [PATCH 03/11] Implement V_LSHR_B64 (#3961) --- src/shader_recompiler/frontend/translate/translate.h | 1 + src/shader_recompiler/frontend/translate/vector_alu.cpp | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/src/shader_recompiler/frontend/translate/translate.h b/src/shader_recompiler/frontend/translate/translate.h index f999a3e3e..3d4d7ca72 100644 --- a/src/shader_recompiler/frontend/translate/translate.h +++ b/src/shader_recompiler/frontend/translate/translate.h @@ -259,6 +259,7 @@ public: void V_CVT_PK_I16_I32(const GcnInst& inst); void V_CVT_PK_U8_F32(const GcnInst& inst); void V_LSHL_B64(const GcnInst& inst); + void V_LSHR_B64(const GcnInst& inst); void V_ALIGNBIT_B32(const GcnInst& inst); void V_ALIGNBYTE_B32(const GcnInst& inst); void V_MUL_F64(const GcnInst& inst); diff --git a/src/shader_recompiler/frontend/translate/vector_alu.cpp b/src/shader_recompiler/frontend/translate/vector_alu.cpp index 0803647a2..5cb04f12f 100644 --- a/src/shader_recompiler/frontend/translate/vector_alu.cpp +++ b/src/shader_recompiler/frontend/translate/vector_alu.cpp @@ -394,6 +394,8 @@ void Translator::EmitVectorAlu(const GcnInst& inst) { return V_CVT_PK_U8_F32(inst); case Opcode::V_LSHL_B64: return V_LSHL_B64(inst); + case Opcode::V_LSHR_B64: + return V_LSHR_B64(inst); case Opcode::V_ADD_F64: return V_ADD_F64(inst); case Opcode::V_ALIGNBIT_B32: @@ -1357,6 +1359,12 @@ void Translator::V_LSHL_B64(const GcnInst& inst) { SetDst64(inst.dst[0], ir.ShiftLeftLogical(src0, ir.BitwiseAnd(src1, ir.Imm64(u64(0x3F))))); } +void Translator::V_LSHR_B64(const GcnInst& inst) { + const IR::U64 src0{GetSrc64(inst.src[0])}; + const IR::U64 src1{GetSrc64(inst.src[1])}; + SetDst64(inst.dst[0], ir.ShiftRightLogical(src0, ir.BitwiseAnd(src1, ir.Imm64(u64(0x3F))))); +} + void Translator::V_ALIGNBIT_B32(const GcnInst& inst) { const IR::U32 src0{GetSrc(inst.src[0])}; const IR::U32 src1{GetSrc(inst.src[1])}; From b17ac0fdda764d3d5dd65d5a322c66018824f430 Mon Sep 17 00:00:00 2001 From: Berk Date: Tue, 27 Jan 2026 16:59:56 +0300 Subject: [PATCH 04/11] Fix most of vscode problems and switch to Arch for more stability (#3964) --- .../.devcontainer/devcontainer.json | 21 ++++--- documents/Docker Builder/.docker/Dockerfile | 58 ++++++++++--------- documents/building-docker.md | 11 +++- 3 files changed, 53 insertions(+), 37 deletions(-) diff --git a/documents/Docker Builder/.devcontainer/devcontainer.json b/documents/Docker Builder/.devcontainer/devcontainer.json index 32e301bd9..9093f6722 100644 --- a/documents/Docker Builder/.devcontainer/devcontainer.json +++ b/documents/Docker Builder/.devcontainer/devcontainer.json @@ -17,29 +17,32 @@ "customizations": { "vscode": { "extensions": [ - "llvm-vs-code-extensions.vscode-clangd" + "llvm-vs-code-extensions.vscode-clangd", + "ms-vscode.cmake-tools" ], "settings": { - "C_Cpp.intelliSenseEngine": "disabled", "clangd.arguments": [ "--background-index", "--clang-tidy", "--completion-style=detailed", - "--header-insertion=never" - ] + "--header-insertion=never", + "--compile-commands-dir=/workspaces/shadPS4/Build/x64-Clang-Release" + ], + "C_Cpp.intelliSenseEngine": "Disabled" } } }, "settings": { - "cmake.configureOnOpen": false, + "cmake.configureOnOpen": false, "cmake.generator": "Unix Makefiles", "cmake.environment": { "CC": "clang", "CXX": "clang++" }, - "cmake.configureSettings": { - "CMAKE_CXX_STANDARD": "23", - "CMAKE_CXX_STANDARD_REQUIRED": "ON" - } + "cmake.configureEnvironment": { + "CMAKE_CXX_STANDARD": "23", + "CMAKE_CXX_STANDARD_REQUIRED": "ON", + "CMAKE_EXPORT_COMPILE_COMMANDS": "ON" + } } } \ No newline at end of file diff --git a/documents/Docker Builder/.docker/Dockerfile b/documents/Docker Builder/.docker/Dockerfile index 285144374..b168a6a72 100644 --- a/documents/Docker Builder/.docker/Dockerfile +++ b/documents/Docker Builder/.docker/Dockerfile @@ -1,38 +1,42 @@ # SPDX-FileCopyrightText: 2026 shadPS4 Emulator Project # SPDX-License-Identifier: GPL-2.0-or-later -FROM ubuntu:24.04 +FROM archlinux:latest -ENV DEBIAN_FRONTEND=noninteractive +RUN pacman-key --init && \ + pacman-key --populate archlinux && \ + pacman -Syu --noconfirm -RUN apt-get update && apt-get install -y \ - build-essential \ +RUN pacman -S --noconfirm \ + base-devel \ clang \ + ninja \ git \ ca-certificates \ wget \ - libasound2-dev \ - libpulse-dev \ - libopenal-dev \ - libssl-dev \ - zlib1g-dev \ - libedit-dev \ - libudev-dev \ - libevdev-dev \ - libsdl2-dev \ - libjack-dev \ - libsndio-dev \ - libxtst-dev \ - libvulkan-dev \ - vulkan-validationlayers \ - libpng-dev \ - clang-tidy \ - && rm -rf /var/lib/apt/lists/* - -RUN wget -qO - https://apt.kitware.com/keys/kitware-archive-latest.asc | gpg --dearmor -o /usr/share/keyrings/kitware-archive-keyring.gpg \ - && echo "deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ noble main" > /etc/apt/sources.list.d/kitware.list \ - && apt-get update \ - && apt-get install -y cmake \ - && rm -rf /var/lib/apt/lists/*/* + alsa-lib \ + libpulse \ + openal \ + openssl \ + zlib \ + libedit \ + systemd-libs \ + libevdev \ + sdl2 \ + jack \ + sndio \ + libxtst \ + vulkan-headers \ + vulkan-validation-layers \ + libpng \ + clang-tools-extra \ + cmake \ + libx11 \ + libxrandr \ + libxcursor \ + libxi \ + libxinerama \ + libxss \ + && pacman -Scc --noconfirm WORKDIR /workspaces/shadPS4 \ No newline at end of file diff --git a/documents/building-docker.md b/documents/building-docker.md index 95be00044..84d238751 100644 --- a/documents/building-docker.md +++ b/documents/building-docker.md @@ -54,7 +54,16 @@ or your fork link. git submodule update --init --recursive ``` -## Step 3: Build with CMake +## Step 3: Build with CMake Tools (GUI) + +Generate build with CMake Tools. + +1. Go `CMake Tools > Configure > '>'` +2. And `Build > '>'` + +Compiled executable in `Build` folder. + +## Alternative Step 3: Build with CMake Generate the build directory and configure the project using Clang: From 1473b2358a639dd5484382db37b97aa72a81c590 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Tue, 27 Jan 2026 19:18:05 +0100 Subject: [PATCH 05/11] Implement V_CMP_OP_F64 (#3962) --- .../frontend/translate/translate.h | 1 + .../frontend/translate/vector_alu.cpp | 69 +++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/src/shader_recompiler/frontend/translate/translate.h b/src/shader_recompiler/frontend/translate/translate.h index 3d4d7ca72..1e93eea7c 100644 --- a/src/shader_recompiler/frontend/translate/translate.h +++ b/src/shader_recompiler/frontend/translate/translate.h @@ -231,6 +231,7 @@ public: // VOPC void V_CMP_F32(ConditionOp op, bool set_exec, const GcnInst& inst); + void V_CMP_F64(ConditionOp op, bool set_exec, const GcnInst& inst); void V_CMP_U32(ConditionOp op, bool is_signed, bool set_exec, const GcnInst& inst); void V_CMP_U64(ConditionOp op, bool is_signed, bool set_exec, const GcnInst& inst); void V_CMP_CLASS_F32(const GcnInst& inst); diff --git a/src/shader_recompiler/frontend/translate/vector_alu.cpp b/src/shader_recompiler/frontend/translate/vector_alu.cpp index 5cb04f12f..35ff6af37 100644 --- a/src/shader_recompiler/frontend/translate/vector_alu.cpp +++ b/src/shader_recompiler/frontend/translate/vector_alu.cpp @@ -264,6 +264,34 @@ void Translator::EmitVectorAlu(const GcnInst& inst) { case Opcode::V_CMPX_TRU_F32: return V_CMP_F32(ConditionOp::TRU, true, inst); + // V_CMP_{OP16}_F64 + case Opcode::V_CMP_F_F64: + return V_CMP_F64(ConditionOp::F, false, inst); + case Opcode::V_CMP_LT_F64: + return V_CMP_F64(ConditionOp::LT, false, inst); + case Opcode::V_CMP_EQ_F64: + return V_CMP_F64(ConditionOp::EQ, false, inst); + case Opcode::V_CMP_LE_F64: + return V_CMP_F64(ConditionOp::LE, false, inst); + case Opcode::V_CMP_GT_F64: + return V_CMP_F64(ConditionOp::GT, false, inst); + case Opcode::V_CMP_LG_F64: + return V_CMP_F64(ConditionOp::LG, false, inst); + case Opcode::V_CMP_GE_F64: + return V_CMP_F64(ConditionOp::GE, false, inst); + case Opcode::V_CMP_U_F64: + return V_CMP_F64(ConditionOp::U, false, inst); + case Opcode::V_CMP_NGE_F64: + return V_CMP_F64(ConditionOp::LT, false, inst); + case Opcode::V_CMP_NGT_F64: + return V_CMP_F64(ConditionOp::LE, false, inst); + case Opcode::V_CMP_NLE_F64: + return V_CMP_F64(ConditionOp::GT, false, inst); + case Opcode::V_CMP_NEQ_F64: + return V_CMP_F64(ConditionOp::LG, false, inst); + case Opcode::V_CMP_NLT_F64: + return V_CMP_F64(ConditionOp::GE, false, inst); + // V_CMP_{OP8}_I32 case Opcode::V_CMP_LT_I32: return V_CMP_U32(ConditionOp::LT, true, false, inst); @@ -1013,6 +1041,47 @@ void Translator::V_CMP_F32(ConditionOp op, bool set_exec, const GcnInst& inst) { } } +void Translator::V_CMP_F64(ConditionOp op, bool set_exec, const GcnInst& inst) { + const IR::F64 src0{GetSrc64(inst.src[0])}; + const IR::F64 src1{GetSrc64(inst.src[1])}; + const IR::U1 result = [&] { + switch (op) { + case ConditionOp::F: + return ir.Imm1(false); + case ConditionOp::EQ: + return ir.FPEqual(src0, src1); + case ConditionOp::LG: + return ir.FPNotEqual(src0, src1); + case ConditionOp::GT: + return ir.FPGreaterThan(src0, src1); + case ConditionOp::LT: + return ir.FPLessThan(src0, src1); + case ConditionOp::LE: + return ir.FPLessThanEqual(src0, src1); + case ConditionOp::GE: + return ir.FPGreaterThanEqual(src0, src1); + case ConditionOp::U: + return ir.LogicalOr(ir.FPIsNan(src0), ir.FPIsNan(src1)); + default: + UNREACHABLE(); + } + }(); + if (set_exec) { + ir.SetExec(result); + } + + switch (inst.dst[1].field) { + case OperandField::VccLo: + ir.SetVcc(result); + break; + case OperandField::ScalarGPR: + ir.SetThreadBitScalarReg(IR::ScalarReg(inst.dst[1].code), result); + break; + default: + UNREACHABLE(); + } +} + void Translator::V_CMP_U32(ConditionOp op, bool is_signed, bool set_exec, const GcnInst& inst) { const IR::U32 src0{GetSrc(inst.src[0])}; const IR::U32 src1{GetSrc(inst.src[1])}; From c81ebe6418b78f25a32c7394147904e6ce9de679 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Tue, 27 Jan 2026 22:08:26 +0100 Subject: [PATCH 06/11] Implement V_FFBH_I32 (#3965) --- .../frontend/translate/translate.h | 1 + .../frontend/translate/vector_alu.cpp | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/shader_recompiler/frontend/translate/translate.h b/src/shader_recompiler/frontend/translate/translate.h index 1e93eea7c..08b0192f5 100644 --- a/src/shader_recompiler/frontend/translate/translate.h +++ b/src/shader_recompiler/frontend/translate/translate.h @@ -219,6 +219,7 @@ public: void V_NOT_B32(const GcnInst& inst); void V_BFREV_B32(const GcnInst& inst); void V_FFBH_U32(const GcnInst& inst); + void V_FFBH_I32(const GcnInst& inst); void V_FFBL_B32(const GcnInst& inst); void V_FREXP_EXP_I32_F64(const GcnInst& inst); void V_FREXP_MANT_F64(const GcnInst& inst); diff --git a/src/shader_recompiler/frontend/translate/vector_alu.cpp b/src/shader_recompiler/frontend/translate/vector_alu.cpp index 35ff6af37..08a0f6527 100644 --- a/src/shader_recompiler/frontend/translate/vector_alu.cpp +++ b/src/shader_recompiler/frontend/translate/vector_alu.cpp @@ -188,6 +188,8 @@ void Translator::EmitVectorAlu(const GcnInst& inst) { return V_FFBH_U32(inst); case Opcode::V_FFBL_B32: return V_FFBL_B32(inst); + case Opcode::V_FFBH_I32: + return V_FFBH_I32(inst); case Opcode::V_FREXP_EXP_I32_F64: return V_FREXP_EXP_I32_F64(inst); case Opcode::V_FREXP_MANT_F64: @@ -948,6 +950,19 @@ void Translator::V_FFBL_B32(const GcnInst& inst) { SetDst(inst.dst[0], ir.FindILsb(src0)); } +void Translator::V_FFBH_I32(const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + // Gcn wants the MSB position counting from the left, but SPIR-V counts from the rightmost (LSB) + // position + const IR::U32 msb_pos = ir.FindSMsb(src0); + const IR::U32 pos_from_left = ir.ISub(ir.Imm32(31), msb_pos); + // Select 0xFFFFFFFF if src0 was 0 or -1 + const IR::U32 minusOne = ir.Imm32(~0U); + const IR::U1 cond = + ir.LogicalAnd(ir.INotEqual(src0, ir.Imm32(0)), ir.INotEqual(src0, minusOne)); + SetDst(inst.dst[0], IR::U32{ir.Select(cond, pos_from_left, minusOne)}); +} + void Translator::V_FREXP_EXP_I32_F64(const GcnInst& inst) { const IR::F64 src0{GetSrc64(inst.src[0])}; SetDst(inst.dst[0], ir.FPFrexpExp(src0)); From 9314633573b1ae73c84df41abaa397b1cd0908be Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Tue, 27 Jan 2026 22:54:01 -0800 Subject: [PATCH 07/11] externals: Update MoltenVK to fix primitive restart disable issue. (#3967) --- externals/MoltenVK | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/externals/MoltenVK b/externals/MoltenVK index f168dec05..f79c6c569 160000 --- a/externals/MoltenVK +++ b/externals/MoltenVK @@ -1 +1 @@ -Subproject commit f168dec05998ab0ca09a400bab6831a95c0bdb2e +Subproject commit f79c6c5690d3ee06ec3a00d11a8b1bab4aa1d030 From cc70fa8bb5effd532ace4c7bdfdfa43f97d92c68 Mon Sep 17 00:00:00 2001 From: kalaposfos13 <153381648+kalaposfos13@users.noreply.github.com> Date: Wed, 28 Jan 2026 12:25:48 +0100 Subject: [PATCH 08/11] Fix thread names not updating correctly (#3968) Also, apply consistency to thread names Also also, copyright 2026 --- src/common/thread.cpp | 9 +++++++++ src/core/libraries/kernel/threads/pthread.cpp | 3 ++- src/core/linker.cpp | 4 ++-- src/emulator.cpp | 4 ++-- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/common/thread.cpp b/src/common/thread.cpp index 54194186c..d6daaa852 100644 --- a/src/common/thread.cpp +++ b/src/common/thread.cpp @@ -174,6 +174,9 @@ bool AccurateSleep(const std::chrono::nanoseconds duration, std::chrono::nanosec // Sets the debugger-visible name of the current thread. void SetCurrentThreadName(const char* name) { + if (Libraries::Kernel::g_curthread) { + Libraries::Kernel::g_curthread->name = std::string{name}; + } SetThreadDescription(GetCurrentThread(), UTF8ToUTF16W(name).data()); } @@ -186,6 +189,9 @@ void SetThreadName(void* thread, const char* name) { // MinGW with the POSIX threading model does not support pthread_setname_np #if !defined(_WIN32) || defined(_MSC_VER) void SetCurrentThreadName(const char* name) { + if (Libraries::Kernel::g_curthread) { + Libraries::Kernel::g_curthread->name = std::string{name}; + } #ifdef __APPLE__ pthread_setname_np(name); #elif defined(__Bitrig__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__) @@ -212,6 +218,9 @@ void SetThreadName(void* thread, const char* name) { #if defined(_WIN32) void SetCurrentThreadName(const char*) { + if (Libraries::Kernel::g_curthread) { + Libraries::Kernel::g_curthread->name = std::string{name}; + } // Do Nothing on MinGW } diff --git a/src/core/libraries/kernel/threads/pthread.cpp b/src/core/libraries/kernel/threads/pthread.cpp index 6c11eebc2..f1107ef30 100644 --- a/src/core/libraries/kernel/threads/pthread.cpp +++ b/src/core/libraries/kernel/threads/pthread.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project +// SPDX-FileCopyrightText: Copyright 2025-2026 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include "common/assert.h" @@ -325,6 +325,7 @@ PthreadT PS4_SYSV_ABI posix_pthread_self() { } void PS4_SYSV_ABI posix_pthread_set_name_np(PthreadT thread, const char* name) { + LOG_INFO(Kernel_Pthread, "called, new name: {}", name); Common::SetCurrentThreadName(name); } diff --git a/src/core/linker.cpp b/src/core/linker.cpp index 97d766a38..7a0653e9f 100644 --- a/src/core/linker.cpp +++ b/src/core/linker.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project +// SPDX-FileCopyrightText: Copyright 2025-2026 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include "common/alignment.h" @@ -105,7 +105,7 @@ void Linker::Execute(const std::vector& args) { memory->SetupMemoryRegions(fmem_size, use_extended_mem1, use_extended_mem2); main_thread.Run([this, module, &args](std::stop_token) { - Common::SetCurrentThreadName("GAME_MainThread"); + Common::SetCurrentThreadName("Game:Main"); if (auto& ipc = IPC::Instance()) { ipc.WaitForStart(); } diff --git a/src/emulator.cpp b/src/emulator.cpp index 263bd9c2b..9044ed027 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project +// SPDX-FileCopyrightText: Copyright 2025-2026 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include @@ -96,7 +96,7 @@ s32 ReadCompiledSdkVersion(const std::filesystem::path& file) { void Emulator::Run(std::filesystem::path file, std::vector args, std::optional p_game_folder) { - Common::SetCurrentThreadName("Main Thread"); + Common::SetCurrentThreadName("shadPS4:Main"); if (waitForDebuggerBeforeRun) { Debugger::WaitForDebuggerAttach(); } From f14bad729c4d83e5e32d90f35a0cd2a2a3f8ff62 Mon Sep 17 00:00:00 2001 From: Stephen Miller <56742918+StevenMiller123@users.noreply.github.com> Date: Wed, 28 Jan 2026 07:10:37 -0600 Subject: [PATCH 09/11] Np: libSceNpPartner001 stubs (#3963) * Initial work * Oops --- CMakeLists.txt | 2 + src/common/logging/filter.cpp | 1 + src/common/logging/types.h | 1 + src/core/libraries/libs.cpp | 2 + src/core/libraries/np/np_partner.cpp | 83 ++++++++++++++++++++++++ src/core/libraries/np/np_partner.h | 15 +++++ src/core/libraries/np/np_partner_error.h | 9 +++ 7 files changed, 113 insertions(+) create mode 100644 src/core/libraries/np/np_partner.cpp create mode 100644 src/core/libraries/np/np_partner.h create mode 100644 src/core/libraries/np/np_partner_error.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c81c7550..0299d242b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -599,6 +599,8 @@ set(NP_LIBS src/core/libraries/np/np_error.h src/core/libraries/np/np_profile_dialog.h src/core/libraries/np/np_sns_facebook_dialog.cpp src/core/libraries/np/np_sns_facebook_dialog.h + src/core/libraries/np/np_partner.cpp + src/core/libraries/np/np_partner.h ) set(ZLIB_LIB src/core/libraries/zlib/zlib.cpp diff --git a/src/common/logging/filter.cpp b/src/common/logging/filter.cpp index 9c8b80255..22ee8ddb3 100644 --- a/src/common/logging/filter.cpp +++ b/src/common/logging/filter.cpp @@ -113,6 +113,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) { SUB(Lib, NpWebApi2) \ SUB(Lib, NpProfileDialog) \ SUB(Lib, NpSnsFacebookDialog) \ + SUB(Lib, NpPartner) \ SUB(Lib, Screenshot) \ SUB(Lib, LibCInternal) \ SUB(Lib, AppContent) \ diff --git a/src/common/logging/types.h b/src/common/logging/types.h index dc7c561a4..ed7bbaa3f 100644 --- a/src/common/logging/types.h +++ b/src/common/logging/types.h @@ -110,6 +110,7 @@ enum class Class : u8 { Lib_Mouse, ///< The LibSceMouse implementation Lib_WebBrowserDialog, ///< The LibSceWebBrowserDialog implementation Lib_NpParty, ///< The LibSceNpParty implementation + Lib_NpPartner, ///< The LibSceNpPartner implementation Lib_Zlib, ///< The LibSceZlib implementation. Lib_Hmd, ///< The LibSceHmd implementation. Lib_HmdSetupDialog, ///< The LibSceHmdSetupDialog implementation. diff --git a/src/core/libraries/libs.cpp b/src/core/libraries/libs.cpp index 7f679e7c2..30fed4fee 100644 --- a/src/core/libraries/libs.cpp +++ b/src/core/libraries/libs.cpp @@ -35,6 +35,7 @@ #include "core/libraries/np/np_commerce.h" #include "core/libraries/np/np_common.h" #include "core/libraries/np/np_manager.h" +#include "core/libraries/np/np_partner.h" #include "core/libraries/np/np_party.h" #include "core/libraries/np/np_profile_dialog.h" #include "core/libraries/np/np_score.h" @@ -105,6 +106,7 @@ void InitHLELibs(Core::Loader::SymbolsResolver* sym) { Libraries::Np::NpSnsFacebookDialog::RegisterLib(sym); Libraries::Np::NpAuth::RegisterLib(sym); Libraries::Np::NpParty::RegisterLib(sym); + Libraries::Np::NpPartner::RegisterLib(sym); Libraries::ScreenShot::RegisterLib(sym); Libraries::AppContent::RegisterLib(sym); Libraries::PngDec::RegisterLib(sym); diff --git a/src/core/libraries/np/np_partner.cpp b/src/core/libraries/np/np_partner.cpp new file mode 100644 index 000000000..447144344 --- /dev/null +++ b/src/core/libraries/np/np_partner.cpp @@ -0,0 +1,83 @@ +// SPDX-FileCopyrightText: Copyright 2026 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include "common/logging/log.h" +#include "core/libraries/error_codes.h" +#include "core/libraries/libs.h" +#include "core/libraries/np/np_partner.h" +#include "core/libraries/np/np_partner_error.h" +#include "core/libraries/system/userservice.h" + +namespace Libraries::Np::NpPartner { + +static bool g_library_init = false; +std::mutex g_library_mutex{}; + +/** + * Terminates the library + */ +s32 PS4_SYSV_ABI Func_A4CC5784DA33517F() { + LOG_ERROR(Lib_NpPartner, "(STUBBED) called"); + if (!g_library_init) { + return ORBIS_NP_PARTNER_ERROR_NOT_INITIALIZED; + } + std::scoped_lock lk{g_library_mutex}; + g_library_init = false; + return ORBIS_OK; +} + +/** + * Aborts requests started by Func_F8E9DB52CD425743 + */ +s32 PS4_SYSV_ABI Func_A507D84D91F39CC7() { + LOG_ERROR(Lib_NpPartner, "(STUBBED) called"); + if (!g_library_init) { + return ORBIS_NP_PARTNER_ERROR_NOT_INITIALIZED; + } + // Request logic is unimplemented, so this does nothing. + return ORBIS_OK; +} + +/** + * Initializes the library + */ +s32 PS4_SYSV_ABI Func_EC2C48E74FF19429() { + LOG_ERROR(Lib_NpPartner, "(STUBBED) called"); + g_library_init = true; + // Also retrieves and sends compiled SDK version to server. + return ORBIS_OK; +} + +/** + * Creates an NP request to determine if the user has a subscription to EA's services. + */ +s32 PS4_SYSV_ABI Func_F8E9DB52CD425743(UserService::OrbisUserServiceUserId user_id, bool* result) { + LOG_ERROR(Lib_NpPartner, "(STUBBED) called"); + if (!g_library_init) { + return ORBIS_NP_PARTNER_ERROR_NOT_INITIALIZED; + } + if (result == nullptr) { + return ORBIS_NP_PARTNER_ERROR_INVALID_ARGUMENT; + } + std::scoped_lock lk{g_library_mutex}; + // In the real library, this creates and sends a request that checks for EA subscription, + // then waits for the request to return a response, and returns that response. + // NP signed out likely returns an error, but I haven't figured out the error code yet. + // For now, stub having no subscription. + *result = false; + return ORBIS_OK; +} + +void RegisterLib(Core::Loader::SymbolsResolver* sym) { + LIB_FUNCTION("pMxXhNozUX8", "libSceNpPartner001", 1, "libSceNpPartner001", + Func_A4CC5784DA33517F); + LIB_FUNCTION("pQfYTZHznMc", "libSceNpPartner001", 1, "libSceNpPartner001", + Func_A507D84D91F39CC7); + LIB_FUNCTION("7CxI50-xlCk", "libSceNpPartner001", 1, "libSceNpPartner001", + Func_EC2C48E74FF19429); + LIB_FUNCTION("+OnbUs1CV0M", "libSceNpPartner001", 1, "libSceNpPartner001", + Func_F8E9DB52CD425743); +}; + +} // namespace Libraries::Np::NpPartner \ No newline at end of file diff --git a/src/core/libraries/np/np_partner.h b/src/core/libraries/np/np_partner.h new file mode 100644 index 000000000..4cb2a6f5f --- /dev/null +++ b/src/core/libraries/np/np_partner.h @@ -0,0 +1,15 @@ +// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/types.h" + +namespace Core::Loader { +class SymbolsResolver; +} + +namespace Libraries::Np::NpPartner { + +void RegisterLib(Core::Loader::SymbolsResolver* sym); +} // namespace Libraries::Np::NpPartner \ No newline at end of file diff --git a/src/core/libraries/np/np_partner_error.h b/src/core/libraries/np/np_partner_error.h new file mode 100644 index 000000000..be1c7c594 --- /dev/null +++ b/src/core/libraries/np/np_partner_error.h @@ -0,0 +1,9 @@ +// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/libraries/error_codes.h" + +constexpr int ORBIS_NP_PARTNER_ERROR_NOT_INITIALIZED = 0x819d0001; +constexpr int ORBIS_NP_PARTNER_ERROR_INVALID_ARGUMENT = 0x819d0002; \ No newline at end of file From 25d175fd41882bd43d9644bc0e98fce3fdd6c535 Mon Sep 17 00:00:00 2001 From: Berk Date: Thu, 29 Jan 2026 15:43:15 +0300 Subject: [PATCH 10/11] [clang-format] Added correct version and vscode formatter (#3971) --- .../.devcontainer/devcontainer.json | 21 +++++++++++-------- documents/Docker Builder/.docker/Dockerfile | 3 +++ 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/documents/Docker Builder/.devcontainer/devcontainer.json b/documents/Docker Builder/.devcontainer/devcontainer.json index 9093f6722..1139ffa33 100644 --- a/documents/Docker Builder/.devcontainer/devcontainer.json +++ b/documents/Docker Builder/.devcontainer/devcontainer.json @@ -17,8 +17,9 @@ "customizations": { "vscode": { "extensions": [ - "llvm-vs-code-extensions.vscode-clangd", - "ms-vscode.cmake-tools" + "llvm-vs-code-extensions.vscode-clangd", + "ms-vscode.cmake-tools", + "xaver.clang-format" ], "settings": { "clangd.arguments": [ @@ -26,23 +27,25 @@ "--clang-tidy", "--completion-style=detailed", "--header-insertion=never", - "--compile-commands-dir=/workspaces/shadPS4/Build/x64-Clang-Release" + "--compile-commands-dir=/workspaces/shadPS4/Build/x64-Clang-Release" ], - "C_Cpp.intelliSenseEngine": "Disabled" + "C_Cpp.intelliSenseEngine": "Disabled" } } }, "settings": { - "cmake.configureOnOpen": false, + "cmake.configureOnOpen": false, "cmake.generator": "Unix Makefiles", "cmake.environment": { "CC": "clang", "CXX": "clang++" }, "cmake.configureEnvironment": { - "CMAKE_CXX_STANDARD": "23", - "CMAKE_CXX_STANDARD_REQUIRED": "ON", - "CMAKE_EXPORT_COMPILE_COMMANDS": "ON" - } + "CMAKE_CXX_STANDARD": "23", + "CMAKE_CXX_STANDARD_REQUIRED": "ON", + "CMAKE_EXPORT_COMPILE_COMMANDS": "ON" + }, + "editor.formatOnSave": true, + "clang-format.executable": "clang-format-19" } } \ No newline at end of file diff --git a/documents/Docker Builder/.docker/Dockerfile b/documents/Docker Builder/.docker/Dockerfile index b168a6a72..6ca9b2da5 100644 --- a/documents/Docker Builder/.docker/Dockerfile +++ b/documents/Docker Builder/.docker/Dockerfile @@ -10,6 +10,7 @@ RUN pacman-key --init && \ RUN pacman -S --noconfirm \ base-devel \ clang \ + clang19 \ ninja \ git \ ca-certificates \ @@ -38,5 +39,7 @@ RUN pacman -S --noconfirm \ libxinerama \ libxss \ && pacman -Scc --noconfirm + +RUN ln -sf /usr/lib/llvm19/bin/clang-format /usr/bin/clang-format-19 WORKDIR /workspaces/shadPS4 \ No newline at end of file From 39a7738d0418a994726ba15ff0ed17591c8b9bb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Thu, 29 Jan 2026 16:46:30 +0100 Subject: [PATCH 11/11] Include NpTus stub (#3970) --- CMakeLists.txt | 2 + src/common/logging/filter.cpp | 1 + src/common/logging/types.h | 1 + src/core/libraries/libs.cpp | 2 + src/core/libraries/np/np_tus.cpp | 1002 ++++++++++++++++++++++++++++++ src/core/libraries/np/np_tus.h | 158 +++++ 6 files changed, 1166 insertions(+) create mode 100644 src/core/libraries/np/np_tus.cpp create mode 100644 src/core/libraries/np/np_tus.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 0299d242b..6deca97db 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -585,6 +585,8 @@ set(NP_LIBS src/core/libraries/np/np_error.h src/core/libraries/np/np_score.h src/core/libraries/np/np_trophy.cpp src/core/libraries/np/np_trophy.h + src/core/libraries/np/np_tus.cpp + src/core/libraries/np/np_tus.h src/core/libraries/np/trophy_ui.cpp src/core/libraries/np/trophy_ui.h src/core/libraries/np/np_web_api.cpp diff --git a/src/common/logging/filter.cpp b/src/common/logging/filter.cpp index 22ee8ddb3..85946e9c4 100644 --- a/src/common/logging/filter.cpp +++ b/src/common/logging/filter.cpp @@ -109,6 +109,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) { SUB(Lib, NpManager) \ SUB(Lib, NpScore) \ SUB(Lib, NpTrophy) \ + SUB(Lib, NpTus) \ SUB(Lib, NpWebApi) \ SUB(Lib, NpWebApi2) \ SUB(Lib, NpProfileDialog) \ diff --git a/src/common/logging/types.h b/src/common/logging/types.h index ed7bbaa3f..127377115 100644 --- a/src/common/logging/types.h +++ b/src/common/logging/types.h @@ -76,6 +76,7 @@ enum class Class : u8 { Lib_NpManager, ///< The LibSceNpManager implementation Lib_NpScore, ///< The LibSceNpScore implementation Lib_NpTrophy, ///< The LibSceNpTrophy implementation + Lib_NpTus, ///< The LibSceNpTus implementation Lib_NpWebApi, ///< The LibSceWebApi implementation Lib_NpWebApi2, ///< The LibSceWebApi2 implementation Lib_NpProfileDialog, ///< The LibSceNpProfileDialog implementation diff --git a/src/core/libraries/libs.cpp b/src/core/libraries/libs.cpp index 30fed4fee..7e8edccec 100644 --- a/src/core/libraries/libs.cpp +++ b/src/core/libraries/libs.cpp @@ -41,6 +41,7 @@ #include "core/libraries/np/np_score.h" #include "core/libraries/np/np_sns_facebook_dialog.h" #include "core/libraries/np/np_trophy.h" +#include "core/libraries/np/np_tus.h" #include "core/libraries/np/np_web_api.h" #include "core/libraries/np/np_web_api2.h" #include "core/libraries/pad/pad.h" @@ -107,6 +108,7 @@ void InitHLELibs(Core::Loader::SymbolsResolver* sym) { Libraries::Np::NpAuth::RegisterLib(sym); Libraries::Np::NpParty::RegisterLib(sym); Libraries::Np::NpPartner::RegisterLib(sym); + Libraries::Np::NpTus::RegisterLib(sym); Libraries::ScreenShot::RegisterLib(sym); Libraries::AppContent::RegisterLib(sym); Libraries::PngDec::RegisterLib(sym); diff --git a/src/core/libraries/np/np_tus.cpp b/src/core/libraries/np/np_tus.cpp new file mode 100644 index 000000000..e0d0aaad1 --- /dev/null +++ b/src/core/libraries/np/np_tus.cpp @@ -0,0 +1,1002 @@ +// SPDX-FileCopyrightText: Copyright 2024-2026 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/logging/log.h" +#include "core/libraries/error_codes.h" +#include "core/libraries/libs.h" +#include "core/libraries/np/np_tus.h" + +namespace Libraries::Np::NpTus { + +s32 PS4_SYSV_ABI sceNpTssCreateNpTitleCtx() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusAddAndGetVariable() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusAddAndGetVariableAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusAddAndGetVariableVUser() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusAddAndGetVariableVUserAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusCreateNpTitleCtx() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusDeleteMultiSlotData() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusDeleteMultiSlotDataAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusDeleteMultiSlotVariable() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusDeleteMultiSlotVariableAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetData() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetDataAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetDataVUser() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetDataVUserAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetFriendsDataStatus() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetFriendsDataStatusAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetFriendsVariable() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetFriendsVariableAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotDataStatus() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotDataStatusAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotDataStatusVUser() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotDataStatusVUserAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotVariable() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotVariableAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotVariableVUser() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotVariableVUserAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiUserDataStatus() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiUserDataStatusAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiUserDataStatusVUser() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiUserDataStatusVUserAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiUserVariable() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiUserVariableAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiUserVariableVUser() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiUserVariableVUserAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusSetData() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusSetDataAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusSetDataVUser() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusSetDataVUserAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusSetMultiSlotVariable() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusSetMultiSlotVariableAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusTryAndSetVariable() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusTryAndSetVariableAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusTryAndSetVariableVUser() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusTryAndSetVariableVUserAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTssCreateNpTitleCtxA() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTssGetData() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTssGetDataAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTssGetSmallStorage() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTssGetSmallStorageAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTssGetStorage() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTssGetStorageAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusAbortRequest() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusAddAndGetVariableA() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusAddAndGetVariableAAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusAddAndGetVariableAVUser() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusAddAndGetVariableAVUserAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusAddAndGetVariableForCrossSave() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusAddAndGetVariableForCrossSaveAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusAddAndGetVariableForCrossSaveVUser() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusAddAndGetVariableForCrossSaveVUserAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusChangeModeForOtherSaveDataOwners() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusCreateNpTitleCtxA() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusCreateRequest() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusCreateTitleCtx() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusDeleteMultiSlotDataA() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusDeleteMultiSlotDataAAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusDeleteMultiSlotDataVUser() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusDeleteMultiSlotDataVUserAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusDeleteMultiSlotVariableA() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusDeleteMultiSlotVariableAAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusDeleteMultiSlotVariableVUser() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusDeleteMultiSlotVariableVUserAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusDeleteNpTitleCtx() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusDeleteRequest() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetDataA() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetDataAAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetDataAVUser() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetDataAVUserAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetDataForCrossSave() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetDataForCrossSaveAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetDataForCrossSaveVUser() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetDataForCrossSaveVUserAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetFriendsDataStatusA() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetFriendsDataStatusAAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetFriendsDataStatusForCrossSave() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetFriendsDataStatusForCrossSaveAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetFriendsVariableA() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetFriendsVariableAAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetFriendsVariableForCrossSave() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetFriendsVariableForCrossSaveAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotDataStatusA() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotDataStatusAAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotDataStatusAVUser() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotDataStatusAVUserAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotDataStatusForCrossSave() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotDataStatusForCrossSaveAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotDataStatusForCrossSaveVUser() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotDataStatusForCrossSaveVUserAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotVariableA() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotVariableAAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotVariableAVUser() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotVariableAVUserAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotVariableForCrossSave() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotVariableForCrossSaveAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotVariableForCrossSaveVUser() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotVariableForCrossSaveVUserAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiUserDataStatusA() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiUserDataStatusAAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiUserDataStatusAVUser() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiUserDataStatusAVUserAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiUserDataStatusForCrossSave() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiUserDataStatusForCrossSaveAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiUserDataStatusForCrossSaveVUser() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiUserDataStatusForCrossSaveVUserAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiUserVariableA() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiUserVariableAAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiUserVariableAVUser() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiUserVariableAVUserAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiUserVariableForCrossSave() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiUserVariableForCrossSaveAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiUserVariableForCrossSaveVUser() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusGetMultiUserVariableForCrossSaveVUserAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusPollAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusSetDataA() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusSetDataAAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusSetDataAVUser() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusSetDataAVUserAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusSetMultiSlotVariableA() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusSetMultiSlotVariableAAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusSetMultiSlotVariableVUser() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusSetMultiSlotVariableVUserAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusSetThreadParam() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusSetTimeout() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusTryAndSetVariableA() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusTryAndSetVariableAAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusTryAndSetVariableAVUser() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusTryAndSetVariableAVUserAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusTryAndSetVariableForCrossSave() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusTryAndSetVariableForCrossSaveAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusTryAndSetVariableForCrossSaveVUser() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusTryAndSetVariableForCrossSaveVUserAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpTusWaitAsync() { + LOG_ERROR(Lib_NpTus, "(STUBBED) called"); + return ORBIS_OK; +} + +void RegisterLib(Core::Loader::SymbolsResolver* sym) { + LIB_FUNCTION("sRVb2Cf0GHg", "libSceNpTusCompat", 1, "libSceNpTus", sceNpTssCreateNpTitleCtx); + LIB_FUNCTION("cRVmNrJDbG8", "libSceNpTusCompat", 1, "libSceNpTus", sceNpTusAddAndGetVariable); + LIB_FUNCTION("Q2UmHdK04c8", "libSceNpTusCompat", 1, "libSceNpTus", + sceNpTusAddAndGetVariableAsync); + LIB_FUNCTION("ukr6FBSrkJw", "libSceNpTusCompat", 1, "libSceNpTus", + sceNpTusAddAndGetVariableVUser); + LIB_FUNCTION("lliK9T6ylJg", "libSceNpTusCompat", 1, "libSceNpTus", + sceNpTusAddAndGetVariableVUserAsync); + LIB_FUNCTION("BIkMmUfNKWM", "libSceNpTusCompat", 1, "libSceNpTus", sceNpTusCreateNpTitleCtx); + LIB_FUNCTION("0DT5bP6YzBo", "libSceNpTusCompat", 1, "libSceNpTus", sceNpTusDeleteMultiSlotData); + LIB_FUNCTION("OCozl1ZtxRY", "libSceNpTusCompat", 1, "libSceNpTus", + sceNpTusDeleteMultiSlotDataAsync); + LIB_FUNCTION("mYhbiRtkE1Y", "libSceNpTusCompat", 1, "libSceNpTus", + sceNpTusDeleteMultiSlotVariable); + LIB_FUNCTION("0nDVqcYECoM", "libSceNpTusCompat", 1, "libSceNpTus", + sceNpTusDeleteMultiSlotVariableAsync); + LIB_FUNCTION("XOzszO4ONWU", "libSceNpTusCompat", 1, "libSceNpTus", sceNpTusGetData); + LIB_FUNCTION("uHtKS5V1T5k", "libSceNpTusCompat", 1, "libSceNpTus", sceNpTusGetDataAsync); + LIB_FUNCTION("GQHCksS7aLs", "libSceNpTusCompat", 1, "libSceNpTus", sceNpTusGetDataVUser); + LIB_FUNCTION("5R6kI-8f+Hk", "libSceNpTusCompat", 1, "libSceNpTus", sceNpTusGetDataVUserAsync); + LIB_FUNCTION("DXigwIBTjWE", "libSceNpTusCompat", 1, "libSceNpTus", + sceNpTusGetFriendsDataStatus); + LIB_FUNCTION("LUwvy0MOSqw", "libSceNpTusCompat", 1, "libSceNpTus", + sceNpTusGetFriendsDataStatusAsync); + LIB_FUNCTION("cy+pAALkHp8", "libSceNpTusCompat", 1, "libSceNpTus", sceNpTusGetFriendsVariable); + LIB_FUNCTION("YFYWOwYI6DY", "libSceNpTusCompat", 1, "libSceNpTus", + sceNpTusGetFriendsVariableAsync); + LIB_FUNCTION("pgcNwFHoOL4", "libSceNpTusCompat", 1, "libSceNpTus", + sceNpTusGetMultiSlotDataStatus); + LIB_FUNCTION("Qyek420uZmM", "libSceNpTusCompat", 1, "libSceNpTus", + sceNpTusGetMultiSlotDataStatusAsync); + LIB_FUNCTION("NGCeFUl5ckM", "libSceNpTusCompat", 1, "libSceNpTus", + sceNpTusGetMultiSlotDataStatusVUser); + LIB_FUNCTION("bHWFSg6jvXc", "libSceNpTusCompat", 1, "libSceNpTus", + sceNpTusGetMultiSlotDataStatusVUserAsync); + LIB_FUNCTION("F+eQlfcka98", "libSceNpTusCompat", 1, "libSceNpTus", + sceNpTusGetMultiSlotVariable); + LIB_FUNCTION("bcPB2rnhQqo", "libSceNpTusCompat", 1, "libSceNpTus", + sceNpTusGetMultiSlotVariableAsync); + LIB_FUNCTION("uFxVYJEkcmc", "libSceNpTusCompat", 1, "libSceNpTus", + sceNpTusGetMultiSlotVariableVUser); + LIB_FUNCTION("qp-rTrq1klk", "libSceNpTusCompat", 1, "libSceNpTus", + sceNpTusGetMultiSlotVariableVUserAsync); + LIB_FUNCTION("NvHjFkx2rnU", "libSceNpTusCompat", 1, "libSceNpTus", + sceNpTusGetMultiUserDataStatus); + LIB_FUNCTION("0zkr0T+NYvI", "libSceNpTusCompat", 1, "libSceNpTus", + sceNpTusGetMultiUserDataStatusAsync); + LIB_FUNCTION("xwJIlK0bHgA", "libSceNpTusCompat", 1, "libSceNpTus", + sceNpTusGetMultiUserDataStatusVUser); + LIB_FUNCTION("I5dlIKkHNkQ", "libSceNpTusCompat", 1, "libSceNpTus", + sceNpTusGetMultiUserDataStatusVUserAsync); + LIB_FUNCTION("6G9+4eIb+cY", "libSceNpTusCompat", 1, "libSceNpTus", + sceNpTusGetMultiUserVariable); + LIB_FUNCTION("YRje5yEXS0U", "libSceNpTusCompat", 1, "libSceNpTus", + sceNpTusGetMultiUserVariableAsync); + LIB_FUNCTION("zB0vaHTzA6g", "libSceNpTusCompat", 1, "libSceNpTus", + sceNpTusGetMultiUserVariableVUser); + LIB_FUNCTION("xZXQuNSTC6o", "libSceNpTusCompat", 1, "libSceNpTus", + sceNpTusGetMultiUserVariableVUserAsync); + LIB_FUNCTION("4NrufkNCkiE", "libSceNpTusCompat", 1, "libSceNpTus", sceNpTusSetData); + LIB_FUNCTION("G68xdfQuiyU", "libSceNpTusCompat", 1, "libSceNpTus", sceNpTusSetDataAsync); + LIB_FUNCTION("+RhzSuuXwxo", "libSceNpTusCompat", 1, "libSceNpTus", sceNpTusSetDataVUser); + LIB_FUNCTION("E4BCVfx-YfM", "libSceNpTusCompat", 1, "libSceNpTus", sceNpTusSetDataVUserAsync); + LIB_FUNCTION("c6aYoa47YgI", "libSceNpTusCompat", 1, "libSceNpTus", + sceNpTusSetMultiSlotVariable); + LIB_FUNCTION("5J9GGMludxY", "libSceNpTusCompat", 1, "libSceNpTus", + sceNpTusSetMultiSlotVariableAsync); + LIB_FUNCTION("ukC55HsotJ4", "libSceNpTusCompat", 1, "libSceNpTus", sceNpTusTryAndSetVariable); + LIB_FUNCTION("xQfR51i4kck", "libSceNpTusCompat", 1, "libSceNpTus", + sceNpTusTryAndSetVariableAsync); + LIB_FUNCTION("ZbitD262GhY", "libSceNpTusCompat", 1, "libSceNpTus", + sceNpTusTryAndSetVariableVUser); + LIB_FUNCTION("trZ6QGW6jHs", "libSceNpTusCompat", 1, "libSceNpTus", + sceNpTusTryAndSetVariableVUserAsync); + LIB_FUNCTION("sRVb2Cf0GHg", "libSceNpTus", 1, "libSceNpTus", sceNpTssCreateNpTitleCtx); + LIB_FUNCTION("lBtrk+7lk14", "libSceNpTus", 1, "libSceNpTus", sceNpTssCreateNpTitleCtxA); + LIB_FUNCTION("-SUR+UoLS6c", "libSceNpTus", 1, "libSceNpTus", sceNpTssGetData); + LIB_FUNCTION("DS2yu3Sjj1o", "libSceNpTus", 1, "libSceNpTus", sceNpTssGetDataAsync); + LIB_FUNCTION("lL+Z3zCKNTs", "libSceNpTus", 1, "libSceNpTus", sceNpTssGetSmallStorage); + LIB_FUNCTION("f2Pe4LGS2II", "libSceNpTus", 1, "libSceNpTus", sceNpTssGetSmallStorageAsync); + LIB_FUNCTION("IVSbAEOxJ6I", "libSceNpTus", 1, "libSceNpTus", sceNpTssGetStorage); + LIB_FUNCTION("k5NZIzggbuk", "libSceNpTus", 1, "libSceNpTus", sceNpTssGetStorageAsync); + LIB_FUNCTION("2eq1bMwgZYo", "libSceNpTus", 1, "libSceNpTus", sceNpTusAbortRequest); + LIB_FUNCTION("cRVmNrJDbG8", "libSceNpTus", 1, "libSceNpTus", sceNpTusAddAndGetVariable); + LIB_FUNCTION("wPFah4-5Xec", "libSceNpTus", 1, "libSceNpTus", sceNpTusAddAndGetVariableA); + LIB_FUNCTION("2dB427dT3Iw", "libSceNpTus", 1, "libSceNpTus", sceNpTusAddAndGetVariableAAsync); + LIB_FUNCTION("Q2UmHdK04c8", "libSceNpTus", 1, "libSceNpTus", sceNpTusAddAndGetVariableAsync); + LIB_FUNCTION("Nt1runsPVJc", "libSceNpTus", 1, "libSceNpTus", sceNpTusAddAndGetVariableAVUser); + LIB_FUNCTION("GjlEgLCh4DY", "libSceNpTus", 1, "libSceNpTus", + sceNpTusAddAndGetVariableAVUserAsync); + LIB_FUNCTION("EPeq43CQKxY", "libSceNpTus", 1, "libSceNpTus", + sceNpTusAddAndGetVariableForCrossSave); + LIB_FUNCTION("mXZi1D2xwZE", "libSceNpTus", 1, "libSceNpTus", + sceNpTusAddAndGetVariableForCrossSaveAsync); + LIB_FUNCTION("4VLlu7EIjzk", "libSceNpTus", 1, "libSceNpTus", + sceNpTusAddAndGetVariableForCrossSaveVUser); + LIB_FUNCTION("6Lu9geO5TiA", "libSceNpTus", 1, "libSceNpTus", + sceNpTusAddAndGetVariableForCrossSaveVUserAsync); + LIB_FUNCTION("ukr6FBSrkJw", "libSceNpTus", 1, "libSceNpTus", sceNpTusAddAndGetVariableVUser); + LIB_FUNCTION("lliK9T6ylJg", "libSceNpTus", 1, "libSceNpTus", + sceNpTusAddAndGetVariableVUserAsync); + LIB_FUNCTION("wjNhItL2wzg", "libSceNpTus", 1, "libSceNpTus", + sceNpTusChangeModeForOtherSaveDataOwners); + LIB_FUNCTION("BIkMmUfNKWM", "libSceNpTus", 1, "libSceNpTus", sceNpTusCreateNpTitleCtx); + LIB_FUNCTION("1n-dGukBgnY", "libSceNpTus", 1, "libSceNpTus", sceNpTusCreateNpTitleCtxA); + LIB_FUNCTION("3bh2aBvvmvM", "libSceNpTus", 1, "libSceNpTus", sceNpTusCreateRequest); + LIB_FUNCTION("hhy8+oecGac", "libSceNpTus", 1, "libSceNpTus", sceNpTusCreateTitleCtx); + LIB_FUNCTION("0DT5bP6YzBo", "libSceNpTus", 1, "libSceNpTus", sceNpTusDeleteMultiSlotData); + LIB_FUNCTION("iXzUOM9sXU0", "libSceNpTus", 1, "libSceNpTus", sceNpTusDeleteMultiSlotDataA); + LIB_FUNCTION("6-+Yqc-NppQ", "libSceNpTus", 1, "libSceNpTus", sceNpTusDeleteMultiSlotDataAAsync); + LIB_FUNCTION("OCozl1ZtxRY", "libSceNpTus", 1, "libSceNpTus", sceNpTusDeleteMultiSlotDataAsync); + LIB_FUNCTION("xutwCvsydkk", "libSceNpTus", 1, "libSceNpTus", sceNpTusDeleteMultiSlotDataVUser); + LIB_FUNCTION("zDeH4tr+0cQ", "libSceNpTus", 1, "libSceNpTus", + sceNpTusDeleteMultiSlotDataVUserAsync); + LIB_FUNCTION("mYhbiRtkE1Y", "libSceNpTus", 1, "libSceNpTus", sceNpTusDeleteMultiSlotVariable); + LIB_FUNCTION("pwnE9Oa1uF8", "libSceNpTus", 1, "libSceNpTus", sceNpTusDeleteMultiSlotVariableA); + LIB_FUNCTION("NQIw7tzo0Ow", "libSceNpTus", 1, "libSceNpTus", + sceNpTusDeleteMultiSlotVariableAAsync); + LIB_FUNCTION("0nDVqcYECoM", "libSceNpTus", 1, "libSceNpTus", + sceNpTusDeleteMultiSlotVariableAsync); + LIB_FUNCTION("o02Mtf8G6V0", "libSceNpTus", 1, "libSceNpTus", + sceNpTusDeleteMultiSlotVariableVUser); + LIB_FUNCTION("WCzd3cxhubo", "libSceNpTus", 1, "libSceNpTus", + sceNpTusDeleteMultiSlotVariableVUserAsync); + LIB_FUNCTION("H3uq7x0sZOI", "libSceNpTus", 1, "libSceNpTus", sceNpTusDeleteNpTitleCtx); + LIB_FUNCTION("CcIH40dYS88", "libSceNpTus", 1, "libSceNpTus", sceNpTusDeleteRequest); + LIB_FUNCTION("XOzszO4ONWU", "libSceNpTus", 1, "libSceNpTus", sceNpTusGetData); + LIB_FUNCTION("yWEHUFkY1qI", "libSceNpTus", 1, "libSceNpTus", sceNpTusGetDataA); + LIB_FUNCTION("xzG8mG9YlKY", "libSceNpTus", 1, "libSceNpTus", sceNpTusGetDataAAsync); + LIB_FUNCTION("uHtKS5V1T5k", "libSceNpTus", 1, "libSceNpTus", sceNpTusGetDataAsync); + LIB_FUNCTION("iaH+Sxlw32k", "libSceNpTus", 1, "libSceNpTus", sceNpTusGetDataAVUser); + LIB_FUNCTION("uoFvgzwawAY", "libSceNpTus", 1, "libSceNpTus", sceNpTusGetDataAVUserAsync); + LIB_FUNCTION("1TE3OvH61qo", "libSceNpTus", 1, "libSceNpTus", sceNpTusGetDataForCrossSave); + LIB_FUNCTION("CFPx3eyaT34", "libSceNpTus", 1, "libSceNpTus", sceNpTusGetDataForCrossSaveAsync); + LIB_FUNCTION("-LxFGYCJwww", "libSceNpTus", 1, "libSceNpTus", sceNpTusGetDataForCrossSaveVUser); + LIB_FUNCTION("B7rBR0CoYLI", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetDataForCrossSaveVUserAsync); + LIB_FUNCTION("GQHCksS7aLs", "libSceNpTus", 1, "libSceNpTus", sceNpTusGetDataVUser); + LIB_FUNCTION("5R6kI-8f+Hk", "libSceNpTus", 1, "libSceNpTus", sceNpTusGetDataVUserAsync); + LIB_FUNCTION("DXigwIBTjWE", "libSceNpTus", 1, "libSceNpTus", sceNpTusGetFriendsDataStatus); + LIB_FUNCTION("yixh7HDKWfk", "libSceNpTus", 1, "libSceNpTus", sceNpTusGetFriendsDataStatusA); + LIB_FUNCTION("OheijxY5RYE", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetFriendsDataStatusAAsync); + LIB_FUNCTION("LUwvy0MOSqw", "libSceNpTus", 1, "libSceNpTus", sceNpTusGetFriendsDataStatusAsync); + LIB_FUNCTION("TDoqRD+CE+M", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetFriendsDataStatusForCrossSave); + LIB_FUNCTION("68B6XDgSANk", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetFriendsDataStatusForCrossSaveAsync); + LIB_FUNCTION("cy+pAALkHp8", "libSceNpTus", 1, "libSceNpTus", sceNpTusGetFriendsVariable); + LIB_FUNCTION("C8TY-UnQoXg", "libSceNpTus", 1, "libSceNpTus", sceNpTusGetFriendsVariableA); + LIB_FUNCTION("wrImtTqUSGM", "libSceNpTus", 1, "libSceNpTus", sceNpTusGetFriendsVariableAAsync); + LIB_FUNCTION("YFYWOwYI6DY", "libSceNpTus", 1, "libSceNpTus", sceNpTusGetFriendsVariableAsync); + LIB_FUNCTION("mD6s8HtMdpk", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetFriendsVariableForCrossSave); + LIB_FUNCTION("FabW3QpY3gQ", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetFriendsVariableForCrossSaveAsync); + LIB_FUNCTION("pgcNwFHoOL4", "libSceNpTus", 1, "libSceNpTus", sceNpTusGetMultiSlotDataStatus); + LIB_FUNCTION("833Y2TnyonE", "libSceNpTus", 1, "libSceNpTus", sceNpTusGetMultiSlotDataStatusA); + LIB_FUNCTION("7uLPqiNvNLc", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetMultiSlotDataStatusAAsync); + LIB_FUNCTION("Qyek420uZmM", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetMultiSlotDataStatusAsync); + LIB_FUNCTION("azmjx3jBAZA", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetMultiSlotDataStatusAVUser); + LIB_FUNCTION("668Ij9MYKEU", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetMultiSlotDataStatusAVUserAsync); + LIB_FUNCTION("DgpRToHWN40", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetMultiSlotDataStatusForCrossSave); + LIB_FUNCTION("LQ6CoHcp+ug", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetMultiSlotDataStatusForCrossSaveAsync); + LIB_FUNCTION("KBfBmtxCdmI", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetMultiSlotDataStatusForCrossSaveVUser); + LIB_FUNCTION("4UF2uu2eDCo", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetMultiSlotDataStatusForCrossSaveVUserAsync); + LIB_FUNCTION("NGCeFUl5ckM", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetMultiSlotDataStatusVUser); + LIB_FUNCTION("bHWFSg6jvXc", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetMultiSlotDataStatusVUserAsync); + LIB_FUNCTION("F+eQlfcka98", "libSceNpTus", 1, "libSceNpTus", sceNpTusGetMultiSlotVariable); + LIB_FUNCTION("GDXlRTxgd+M", "libSceNpTus", 1, "libSceNpTus", sceNpTusGetMultiSlotVariableA); + LIB_FUNCTION("2BnPSY1Oxd8", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetMultiSlotVariableAAsync); + LIB_FUNCTION("bcPB2rnhQqo", "libSceNpTus", 1, "libSceNpTus", sceNpTusGetMultiSlotVariableAsync); + LIB_FUNCTION("AsziNQ9X2uk", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetMultiSlotVariableAVUser); + LIB_FUNCTION("y-DJK+d+leg", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetMultiSlotVariableAVUserAsync); + LIB_FUNCTION("m9XZnxw9AmE", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetMultiSlotVariableForCrossSave); + LIB_FUNCTION("DFlBYT+Lm2I", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetMultiSlotVariableForCrossSaveAsync); + LIB_FUNCTION("wTuuw4-6HI8", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetMultiSlotVariableForCrossSaveVUser); + LIB_FUNCTION("DPcu0qWsd7Q", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetMultiSlotVariableForCrossSaveVUserAsync); + LIB_FUNCTION("uFxVYJEkcmc", "libSceNpTus", 1, "libSceNpTus", sceNpTusGetMultiSlotVariableVUser); + LIB_FUNCTION("qp-rTrq1klk", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetMultiSlotVariableVUserAsync); + LIB_FUNCTION("NvHjFkx2rnU", "libSceNpTus", 1, "libSceNpTus", sceNpTusGetMultiUserDataStatus); + LIB_FUNCTION("lxNDPDnWfMc", "libSceNpTus", 1, "libSceNpTus", sceNpTusGetMultiUserDataStatusA); + LIB_FUNCTION("kt+k6jegYZ8", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetMultiUserDataStatusAAsync); + LIB_FUNCTION("0zkr0T+NYvI", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetMultiUserDataStatusAsync); + LIB_FUNCTION("fJU2TZId210", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetMultiUserDataStatusAVUser); + LIB_FUNCTION("WBh3zfrjS38", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetMultiUserDataStatusAVUserAsync); + LIB_FUNCTION("cVeBif6zdZ4", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetMultiUserDataStatusForCrossSave); + LIB_FUNCTION("lq0Anwhj0wY", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetMultiUserDataStatusForCrossSaveAsync); + LIB_FUNCTION("w-c7U0MW2KY", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetMultiUserDataStatusForCrossSaveVUser); + LIB_FUNCTION("H6sQJ99usfE", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetMultiUserDataStatusForCrossSaveVUserAsync); + LIB_FUNCTION("xwJIlK0bHgA", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetMultiUserDataStatusVUser); + LIB_FUNCTION("I5dlIKkHNkQ", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetMultiUserDataStatusVUserAsync); + LIB_FUNCTION("6G9+4eIb+cY", "libSceNpTus", 1, "libSceNpTus", sceNpTusGetMultiUserVariable); + LIB_FUNCTION("Gjixv5hqRVY", "libSceNpTus", 1, "libSceNpTus", sceNpTusGetMultiUserVariableA); + LIB_FUNCTION("eGunerNP9n0", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetMultiUserVariableAAsync); + LIB_FUNCTION("YRje5yEXS0U", "libSceNpTus", 1, "libSceNpTus", sceNpTusGetMultiUserVariableAsync); + LIB_FUNCTION("fVvocpq4mG4", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetMultiUserVariableAVUser); + LIB_FUNCTION("V8ZA3hHrAbw", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetMultiUserVariableAVUserAsync); + LIB_FUNCTION("Q5uQeScvTPE", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetMultiUserVariableForCrossSave); + LIB_FUNCTION("oZ8DMeTU-50", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetMultiUserVariableForCrossSaveAsync); + LIB_FUNCTION("Djuj2+1VNL0", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetMultiUserVariableForCrossSaveVUser); + LIB_FUNCTION("82RP7itI-zI", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetMultiUserVariableForCrossSaveVUserAsync); + LIB_FUNCTION("zB0vaHTzA6g", "libSceNpTus", 1, "libSceNpTus", sceNpTusGetMultiUserVariableVUser); + LIB_FUNCTION("xZXQuNSTC6o", "libSceNpTus", 1, "libSceNpTus", + sceNpTusGetMultiUserVariableVUserAsync); + LIB_FUNCTION("t7b6dmpQNiI", "libSceNpTus", 1, "libSceNpTus", sceNpTusPollAsync); + LIB_FUNCTION("4NrufkNCkiE", "libSceNpTus", 1, "libSceNpTus", sceNpTusSetData); + LIB_FUNCTION("VzxN3tOouj8", "libSceNpTus", 1, "libSceNpTus", sceNpTusSetDataA); + LIB_FUNCTION("4u58d6g6uwU", "libSceNpTus", 1, "libSceNpTus", sceNpTusSetDataAAsync); + LIB_FUNCTION("G68xdfQuiyU", "libSceNpTus", 1, "libSceNpTus", sceNpTusSetDataAsync); + LIB_FUNCTION("kbWqOt3QjKU", "libSceNpTus", 1, "libSceNpTus", sceNpTusSetDataAVUser); + LIB_FUNCTION("Fmx4tapJGzo", "libSceNpTus", 1, "libSceNpTus", sceNpTusSetDataAVUserAsync); + LIB_FUNCTION("+RhzSuuXwxo", "libSceNpTus", 1, "libSceNpTus", sceNpTusSetDataVUser); + LIB_FUNCTION("E4BCVfx-YfM", "libSceNpTus", 1, "libSceNpTus", sceNpTusSetDataVUserAsync); + LIB_FUNCTION("c6aYoa47YgI", "libSceNpTus", 1, "libSceNpTus", sceNpTusSetMultiSlotVariable); + LIB_FUNCTION("cf-WMA0jYCc", "libSceNpTus", 1, "libSceNpTus", sceNpTusSetMultiSlotVariableA); + LIB_FUNCTION("ypMObSwfcns", "libSceNpTus", 1, "libSceNpTus", + sceNpTusSetMultiSlotVariableAAsync); + LIB_FUNCTION("5J9GGMludxY", "libSceNpTus", 1, "libSceNpTus", sceNpTusSetMultiSlotVariableAsync); + LIB_FUNCTION("1Cz0hTJFyh4", "libSceNpTus", 1, "libSceNpTus", sceNpTusSetMultiSlotVariableVUser); + LIB_FUNCTION("CJAxTxQdwHM", "libSceNpTus", 1, "libSceNpTus", + sceNpTusSetMultiSlotVariableVUserAsync); + LIB_FUNCTION("6GKDdRCFx8c", "libSceNpTus", 1, "libSceNpTus", sceNpTusSetThreadParam); + LIB_FUNCTION("KMlHj+tgfdQ", "libSceNpTus", 1, "libSceNpTus", sceNpTusSetTimeout); + LIB_FUNCTION("ukC55HsotJ4", "libSceNpTus", 1, "libSceNpTus", sceNpTusTryAndSetVariable); + LIB_FUNCTION("0up4MP1wNtc", "libSceNpTus", 1, "libSceNpTus", sceNpTusTryAndSetVariableA); + LIB_FUNCTION("bGTjTkHPHTE", "libSceNpTus", 1, "libSceNpTus", sceNpTusTryAndSetVariableAAsync); + LIB_FUNCTION("xQfR51i4kck", "libSceNpTus", 1, "libSceNpTus", sceNpTusTryAndSetVariableAsync); + LIB_FUNCTION("oGIcxlUabSA", "libSceNpTus", 1, "libSceNpTus", sceNpTusTryAndSetVariableAVUser); + LIB_FUNCTION("uf77muc5Bog", "libSceNpTus", 1, "libSceNpTus", + sceNpTusTryAndSetVariableAVUserAsync); + LIB_FUNCTION("MGvSJEHwyL8", "libSceNpTus", 1, "libSceNpTus", + sceNpTusTryAndSetVariableForCrossSave); + LIB_FUNCTION("JKGYZ2F1yT8", "libSceNpTus", 1, "libSceNpTus", + sceNpTusTryAndSetVariableForCrossSaveAsync); + LIB_FUNCTION("fcCwKpi4CbU", "libSceNpTus", 1, "libSceNpTus", + sceNpTusTryAndSetVariableForCrossSaveVUser); + LIB_FUNCTION("CjVIpztpTNc", "libSceNpTus", 1, "libSceNpTus", + sceNpTusTryAndSetVariableForCrossSaveVUserAsync); + LIB_FUNCTION("ZbitD262GhY", "libSceNpTus", 1, "libSceNpTus", sceNpTusTryAndSetVariableVUser); + LIB_FUNCTION("trZ6QGW6jHs", "libSceNpTus", 1, "libSceNpTus", + sceNpTusTryAndSetVariableVUserAsync); + LIB_FUNCTION("hYPJFWzFPjA", "libSceNpTus", 1, "libSceNpTus", sceNpTusWaitAsync); +}; + +} // namespace Libraries::Np::NpTus \ No newline at end of file diff --git a/src/core/libraries/np/np_tus.h b/src/core/libraries/np/np_tus.h new file mode 100644 index 000000000..3c18099b2 --- /dev/null +++ b/src/core/libraries/np/np_tus.h @@ -0,0 +1,158 @@ +// SPDX-FileCopyrightText: Copyright 2024-2026 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/types.h" + +namespace Core::Loader { +class SymbolsResolver; +} + +namespace Libraries::Np::NpTus { + +s32 PS4_SYSV_ABI sceNpTssCreateNpTitleCtx(); +s32 PS4_SYSV_ABI sceNpTusAddAndGetVariable(); +s32 PS4_SYSV_ABI sceNpTusAddAndGetVariableAsync(); +s32 PS4_SYSV_ABI sceNpTusAddAndGetVariableVUser(); +s32 PS4_SYSV_ABI sceNpTusAddAndGetVariableVUserAsync(); +s32 PS4_SYSV_ABI sceNpTusCreateNpTitleCtx(); +s32 PS4_SYSV_ABI sceNpTusDeleteMultiSlotData(); +s32 PS4_SYSV_ABI sceNpTusDeleteMultiSlotDataAsync(); +s32 PS4_SYSV_ABI sceNpTusDeleteMultiSlotVariable(); +s32 PS4_SYSV_ABI sceNpTusDeleteMultiSlotVariableAsync(); +s32 PS4_SYSV_ABI sceNpTusGetData(); +s32 PS4_SYSV_ABI sceNpTusGetDataAsync(); +s32 PS4_SYSV_ABI sceNpTusGetDataVUser(); +s32 PS4_SYSV_ABI sceNpTusGetDataVUserAsync(); +s32 PS4_SYSV_ABI sceNpTusGetFriendsDataStatus(); +s32 PS4_SYSV_ABI sceNpTusGetFriendsDataStatusAsync(); +s32 PS4_SYSV_ABI sceNpTusGetFriendsVariable(); +s32 PS4_SYSV_ABI sceNpTusGetFriendsVariableAsync(); +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotDataStatus(); +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotDataStatusAsync(); +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotDataStatusVUser(); +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotDataStatusVUserAsync(); +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotVariable(); +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotVariableAsync(); +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotVariableVUser(); +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotVariableVUserAsync(); +s32 PS4_SYSV_ABI sceNpTusGetMultiUserDataStatus(); +s32 PS4_SYSV_ABI sceNpTusGetMultiUserDataStatusAsync(); +s32 PS4_SYSV_ABI sceNpTusGetMultiUserDataStatusVUser(); +s32 PS4_SYSV_ABI sceNpTusGetMultiUserDataStatusVUserAsync(); +s32 PS4_SYSV_ABI sceNpTusGetMultiUserVariable(); +s32 PS4_SYSV_ABI sceNpTusGetMultiUserVariableAsync(); +s32 PS4_SYSV_ABI sceNpTusGetMultiUserVariableVUser(); +s32 PS4_SYSV_ABI sceNpTusGetMultiUserVariableVUserAsync(); +s32 PS4_SYSV_ABI sceNpTusSetData(); +s32 PS4_SYSV_ABI sceNpTusSetDataAsync(); +s32 PS4_SYSV_ABI sceNpTusSetDataVUser(); +s32 PS4_SYSV_ABI sceNpTusSetDataVUserAsync(); +s32 PS4_SYSV_ABI sceNpTusSetMultiSlotVariable(); +s32 PS4_SYSV_ABI sceNpTusSetMultiSlotVariableAsync(); +s32 PS4_SYSV_ABI sceNpTusTryAndSetVariable(); +s32 PS4_SYSV_ABI sceNpTusTryAndSetVariableAsync(); +s32 PS4_SYSV_ABI sceNpTusTryAndSetVariableVUser(); +s32 PS4_SYSV_ABI sceNpTusTryAndSetVariableVUserAsync(); +s32 PS4_SYSV_ABI sceNpTssCreateNpTitleCtxA(); +s32 PS4_SYSV_ABI sceNpTssGetData(); +s32 PS4_SYSV_ABI sceNpTssGetDataAsync(); +s32 PS4_SYSV_ABI sceNpTssGetSmallStorage(); +s32 PS4_SYSV_ABI sceNpTssGetSmallStorageAsync(); +s32 PS4_SYSV_ABI sceNpTssGetStorage(); +s32 PS4_SYSV_ABI sceNpTssGetStorageAsync(); +s32 PS4_SYSV_ABI sceNpTusAbortRequest(); +s32 PS4_SYSV_ABI sceNpTusAddAndGetVariableA(); +s32 PS4_SYSV_ABI sceNpTusAddAndGetVariableAAsync(); +s32 PS4_SYSV_ABI sceNpTusAddAndGetVariableAVUser(); +s32 PS4_SYSV_ABI sceNpTusAddAndGetVariableAVUserAsync(); +s32 PS4_SYSV_ABI sceNpTusAddAndGetVariableForCrossSave(); +s32 PS4_SYSV_ABI sceNpTusAddAndGetVariableForCrossSaveAsync(); +s32 PS4_SYSV_ABI sceNpTusAddAndGetVariableForCrossSaveVUser(); +s32 PS4_SYSV_ABI sceNpTusAddAndGetVariableForCrossSaveVUserAsync(); +s32 PS4_SYSV_ABI sceNpTusChangeModeForOtherSaveDataOwners(); +s32 PS4_SYSV_ABI sceNpTusCreateNpTitleCtxA(); +s32 PS4_SYSV_ABI sceNpTusCreateRequest(); +s32 PS4_SYSV_ABI sceNpTusCreateTitleCtx(); +s32 PS4_SYSV_ABI sceNpTusDeleteMultiSlotDataA(); +s32 PS4_SYSV_ABI sceNpTusDeleteMultiSlotDataAAsync(); +s32 PS4_SYSV_ABI sceNpTusDeleteMultiSlotDataVUser(); +s32 PS4_SYSV_ABI sceNpTusDeleteMultiSlotDataVUserAsync(); +s32 PS4_SYSV_ABI sceNpTusDeleteMultiSlotVariableA(); +s32 PS4_SYSV_ABI sceNpTusDeleteMultiSlotVariableAAsync(); +s32 PS4_SYSV_ABI sceNpTusDeleteMultiSlotVariableVUser(); +s32 PS4_SYSV_ABI sceNpTusDeleteMultiSlotVariableVUserAsync(); +s32 PS4_SYSV_ABI sceNpTusDeleteNpTitleCtx(); +s32 PS4_SYSV_ABI sceNpTusDeleteRequest(); +s32 PS4_SYSV_ABI sceNpTusGetDataA(); +s32 PS4_SYSV_ABI sceNpTusGetDataAAsync(); +s32 PS4_SYSV_ABI sceNpTusGetDataAVUser(); +s32 PS4_SYSV_ABI sceNpTusGetDataAVUserAsync(); +s32 PS4_SYSV_ABI sceNpTusGetDataForCrossSave(); +s32 PS4_SYSV_ABI sceNpTusGetDataForCrossSaveAsync(); +s32 PS4_SYSV_ABI sceNpTusGetDataForCrossSaveVUser(); +s32 PS4_SYSV_ABI sceNpTusGetDataForCrossSaveVUserAsync(); +s32 PS4_SYSV_ABI sceNpTusGetFriendsDataStatusA(); +s32 PS4_SYSV_ABI sceNpTusGetFriendsDataStatusAAsync(); +s32 PS4_SYSV_ABI sceNpTusGetFriendsDataStatusForCrossSave(); +s32 PS4_SYSV_ABI sceNpTusGetFriendsDataStatusForCrossSaveAsync(); +s32 PS4_SYSV_ABI sceNpTusGetFriendsVariableA(); +s32 PS4_SYSV_ABI sceNpTusGetFriendsVariableAAsync(); +s32 PS4_SYSV_ABI sceNpTusGetFriendsVariableForCrossSave(); +s32 PS4_SYSV_ABI sceNpTusGetFriendsVariableForCrossSaveAsync(); +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotDataStatusA(); +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotDataStatusAAsync(); +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotDataStatusAVUser(); +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotDataStatusAVUserAsync(); +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotDataStatusForCrossSave(); +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotDataStatusForCrossSaveAsync(); +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotDataStatusForCrossSaveVUser(); +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotDataStatusForCrossSaveVUserAsync(); +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotVariableA(); +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotVariableAAsync(); +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotVariableAVUser(); +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotVariableAVUserAsync(); +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotVariableForCrossSave(); +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotVariableForCrossSaveAsync(); +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotVariableForCrossSaveVUser(); +s32 PS4_SYSV_ABI sceNpTusGetMultiSlotVariableForCrossSaveVUserAsync(); +s32 PS4_SYSV_ABI sceNpTusGetMultiUserDataStatusA(); +s32 PS4_SYSV_ABI sceNpTusGetMultiUserDataStatusAAsync(); +s32 PS4_SYSV_ABI sceNpTusGetMultiUserDataStatusAVUser(); +s32 PS4_SYSV_ABI sceNpTusGetMultiUserDataStatusAVUserAsync(); +s32 PS4_SYSV_ABI sceNpTusGetMultiUserDataStatusForCrossSave(); +s32 PS4_SYSV_ABI sceNpTusGetMultiUserDataStatusForCrossSaveAsync(); +s32 PS4_SYSV_ABI sceNpTusGetMultiUserDataStatusForCrossSaveVUser(); +s32 PS4_SYSV_ABI sceNpTusGetMultiUserDataStatusForCrossSaveVUserAsync(); +s32 PS4_SYSV_ABI sceNpTusGetMultiUserVariableA(); +s32 PS4_SYSV_ABI sceNpTusGetMultiUserVariableAAsync(); +s32 PS4_SYSV_ABI sceNpTusGetMultiUserVariableAVUser(); +s32 PS4_SYSV_ABI sceNpTusGetMultiUserVariableAVUserAsync(); +s32 PS4_SYSV_ABI sceNpTusGetMultiUserVariableForCrossSave(); +s32 PS4_SYSV_ABI sceNpTusGetMultiUserVariableForCrossSaveAsync(); +s32 PS4_SYSV_ABI sceNpTusGetMultiUserVariableForCrossSaveVUser(); +s32 PS4_SYSV_ABI sceNpTusGetMultiUserVariableForCrossSaveVUserAsync(); +s32 PS4_SYSV_ABI sceNpTusPollAsync(); +s32 PS4_SYSV_ABI sceNpTusSetDataA(); +s32 PS4_SYSV_ABI sceNpTusSetDataAAsync(); +s32 PS4_SYSV_ABI sceNpTusSetDataAVUser(); +s32 PS4_SYSV_ABI sceNpTusSetDataAVUserAsync(); +s32 PS4_SYSV_ABI sceNpTusSetMultiSlotVariableA(); +s32 PS4_SYSV_ABI sceNpTusSetMultiSlotVariableAAsync(); +s32 PS4_SYSV_ABI sceNpTusSetMultiSlotVariableVUser(); +s32 PS4_SYSV_ABI sceNpTusSetMultiSlotVariableVUserAsync(); +s32 PS4_SYSV_ABI sceNpTusSetThreadParam(); +s32 PS4_SYSV_ABI sceNpTusSetTimeout(); +s32 PS4_SYSV_ABI sceNpTusTryAndSetVariableA(); +s32 PS4_SYSV_ABI sceNpTusTryAndSetVariableAAsync(); +s32 PS4_SYSV_ABI sceNpTusTryAndSetVariableAVUser(); +s32 PS4_SYSV_ABI sceNpTusTryAndSetVariableAVUserAsync(); +s32 PS4_SYSV_ABI sceNpTusTryAndSetVariableForCrossSave(); +s32 PS4_SYSV_ABI sceNpTusTryAndSetVariableForCrossSaveAsync(); +s32 PS4_SYSV_ABI sceNpTusTryAndSetVariableForCrossSaveVUser(); +s32 PS4_SYSV_ABI sceNpTusTryAndSetVariableForCrossSaveVUserAsync(); +s32 PS4_SYSV_ABI sceNpTusWaitAsync(); + +void RegisterLib(Core::Loader::SymbolsResolver* sym); +} // namespace Libraries::Np::NpTus \ No newline at end of file