diff --git a/CMakeLists.txt b/CMakeLists.txt index 804bd3f46..66029ec3b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -587,6 +587,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 @@ -601,6 +603,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/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..1139ffa33 --- /dev/null +++ b/documents/Docker Builder/.devcontainer/devcontainer.json @@ -0,0 +1,51 @@ +// 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", + "ms-vscode.cmake-tools", + "xaver.clang-format" + ], + "settings": { + "clangd.arguments": [ + "--background-index", + "--clang-tidy", + "--completion-style=detailed", + "--header-insertion=never", + "--compile-commands-dir=/workspaces/shadPS4/Build/x64-Clang-Release" + ], + "C_Cpp.intelliSenseEngine": "Disabled" + } + } + }, + "settings": { + "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" + }, + "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 new file mode 100644 index 000000000..6ca9b2da5 --- /dev/null +++ b/documents/Docker Builder/.docker/Dockerfile @@ -0,0 +1,45 @@ +# SPDX-FileCopyrightText: 2026 shadPS4 Emulator Project +# SPDX-License-Identifier: GPL-2.0-or-later + +FROM archlinux:latest + +RUN pacman-key --init && \ + pacman-key --populate archlinux && \ + pacman -Syu --noconfirm + +RUN pacman -S --noconfirm \ + base-devel \ + clang \ + clang19 \ + ninja \ + git \ + ca-certificates \ + wget \ + 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 + +RUN ln -sf /usr/lib/llvm19/bin/clang-format /usr/bin/clang-format-19 + +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..84d238751 --- /dev/null +++ b/documents/building-docker.md @@ -0,0 +1,100 @@ + + +# 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 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: + +```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 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 diff --git a/src/common/logging/filter.cpp b/src/common/logging/filter.cpp index 9c8b80255..85946e9c4 100644 --- a/src/common/logging/filter.cpp +++ b/src/common/logging/filter.cpp @@ -109,10 +109,12 @@ 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) \ 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..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 @@ -110,6 +111,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/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/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/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/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/libraries/libs.cpp b/src/core/libraries/libs.cpp index 7f679e7c2..7e8edccec 100644 --- a/src/core/libraries/libs.cpp +++ b/src/core/libraries/libs.cpp @@ -35,11 +35,13 @@ #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" #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" @@ -105,6 +107,8 @@ 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::Np::NpTus::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 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 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/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{}; 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(); } diff --git a/src/shader_recompiler/frontend/translate/translate.h b/src/shader_recompiler/frontend/translate/translate.h index f999a3e3e..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); @@ -231,6 +232,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); @@ -259,6 +261,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..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: @@ -264,6 +266,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); @@ -394,6 +424,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: @@ -918,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)); @@ -1011,6 +1056,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])}; @@ -1357,6 +1443,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])};