mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-04-20 11:35:45 +00:00
Merge branch 'shadps4-emu:main' into main
This commit is contained in:
commit
1a26b93e02
97 changed files with 1555 additions and 1587 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -107,3 +107,6 @@
|
|||
path = externals/MoltenVK/cereal
|
||||
url = https://github.com/USCiLab/cereal
|
||||
shallow = true
|
||||
[submodule "externals/libusb"]
|
||||
path = externals/libusb
|
||||
url = https://github.com/libusb/libusb-cmake.git
|
||||
|
|
|
@ -9,7 +9,8 @@ set(CMAKE_CXX_STANDARD_REQUIRED True)
|
|||
|
||||
if(APPLE)
|
||||
list(APPEND ADDITIONAL_LANGUAGES OBJC)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 14)
|
||||
# Starting with 15.4, Rosetta 2 has support for all the necessary instruction sets.
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 15.4)
|
||||
endif()
|
||||
|
||||
if (NOT CMAKE_BUILD_TYPE)
|
||||
|
@ -53,8 +54,9 @@ else()
|
|||
endif()
|
||||
|
||||
if (ARCHITECTURE STREQUAL "x86_64")
|
||||
# Set x86_64 target level to Sandy Bridge to generally match what is supported for PS4 guest code with CPU patches.
|
||||
add_compile_options(-march=sandybridge)
|
||||
# Target the same CPU architecture as the PS4, to maintain the same level of compatibility.
|
||||
# Exclude SSE4a as it is only available on AMD CPUs.
|
||||
add_compile_options(-march=btver2 -mtune=generic -mno-sse4a)
|
||||
endif()
|
||||
|
||||
if (APPLE AND ARCHITECTURE STREQUAL "x86_64" AND CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "arm64")
|
||||
|
@ -114,6 +116,7 @@ git_branch_name(GIT_BRANCH)
|
|||
string(TIMESTAMP BUILD_DATE "%Y-%m-%d %H:%M:%S")
|
||||
|
||||
message("start git things")
|
||||
|
||||
# Try to get the upstream remote and branch
|
||||
message("check for remote and branch")
|
||||
execute_process(
|
||||
|
@ -123,6 +126,7 @@ execute_process(
|
|||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
# If there's no upstream set or the command failed, check remote.pushDefault
|
||||
if (GIT_REMOTE_RESULT OR GIT_REMOTE_NAME STREQUAL "")
|
||||
message("check default push")
|
||||
|
@ -134,15 +138,48 @@ if (GIT_REMOTE_RESULT OR GIT_REMOTE_NAME STREQUAL "")
|
|||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
endif()
|
||||
|
||||
# If running in GitHub Actions and the above fails
|
||||
if (GIT_REMOTE_RESULT OR GIT_REMOTE_NAME STREQUAL "")
|
||||
message("check github")
|
||||
set(GIT_REMOTE_NAME "origin")
|
||||
|
||||
if (DEFINED ENV{GITHUB_HEAD_REF}) # PR branch name
|
||||
set(GIT_BRANCH "pr-$ENV{GITHUB_HEAD_REF}")
|
||||
elseif (DEFINED ENV{GITHUB_REF}) # Normal branch name
|
||||
string(REGEX REPLACE "^refs/[^/]*/" "" GIT_BRANCH "$ENV{GITHUB_REF}")
|
||||
# Retrieve environment variables
|
||||
if (DEFINED ENV{GITHUB_HEAD_REF} AND NOT "$ENV{GITHUB_HEAD_REF}" STREQUAL "")
|
||||
message("github head ref: $ENV{GITHUB_HEAD_REF}")
|
||||
set(GITHUB_HEAD_REF "$ENV{GITHUB_HEAD_REF}")
|
||||
else()
|
||||
set(GITHUB_HEAD_REF "")
|
||||
endif()
|
||||
|
||||
if (DEFINED ENV{GITHUB_REF} AND NOT "$ENV{GITHUB_REF}" STREQUAL "")
|
||||
message("github ref: $ENV{GITHUB_REF}")
|
||||
string(REGEX REPLACE "^refs/[^/]*/" "" GITHUB_BRANCH "$ENV{GITHUB_REF}")
|
||||
string(REGEX MATCH "refs/pull/([0-9]+)/merge" MATCHED_REF "$ENV{GITHUB_REF}")
|
||||
if (MATCHED_REF)
|
||||
set(PR_NUMBER "${CMAKE_MATCH_1}")
|
||||
set(GITHUB_BRANCH "")
|
||||
message("PR number: ${PR_NUMBER}")
|
||||
else()
|
||||
set(PR_NUMBER "")
|
||||
endif()
|
||||
else()
|
||||
set(GITHUB_BRANCH "")
|
||||
set(PR_NUMBER "")
|
||||
endif()
|
||||
|
||||
if (NOT "${PR_NUMBER}" STREQUAL "" AND NOT "${GITHUB_HEAD_REF}" STREQUAL "")
|
||||
set(GIT_BRANCH "pr-${PR_NUMBER}-${GITHUB_HEAD_REF}")
|
||||
elseif (NOT "${PR_NUMBER}" STREQUAL "" AND NOT "${GITHUB_BRANCH}" STREQUAL "")
|
||||
set(GIT_BRANCH "pr-${PR_NUMBER}-${GITHUB_BRANCH}")
|
||||
elseif (NOT "${PR_NUMBER}" STREQUAL "")
|
||||
set(GIT_BRANCH "pr-${PR_NUMBER}")
|
||||
elseif ("${PR_NUMBER}" STREQUAL "" AND NOT "${GITHUB_HEAD_REF}" STREQUAL "")
|
||||
set(GIT_BRANCH "${GITHUB_HEAD_REF}")
|
||||
elseif ("${PR_NUMBER}" STREQUAL "" AND NOT "${GITHUB_BRANCH}" STREQUAL "")
|
||||
set(GIT_BRANCH "${GITHUB_BRANCH}")
|
||||
elseif ("${PR_NUMBER}" STREQUAL "" AND NOT "${GITHUB_REF}" STREQUAL "")
|
||||
set(GIT_BRANCH "${GITHUB_REF}")
|
||||
else()
|
||||
message("couldn't find branch")
|
||||
set(GIT_BRANCH "detached-head")
|
||||
|
@ -166,6 +203,8 @@ execute_process(
|
|||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
set(APP_VERSION "0.7.1 WIP")
|
||||
set(APP_IS_RELEASE false)
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/common/scm_rev.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/src/common/scm_rev.cpp" @ONLY)
|
||||
|
||||
message("end git things, remote: ${GIT_REMOTE_NAME}, branch: ${GIT_BRANCH}")
|
||||
|
@ -182,17 +221,14 @@ find_package(SDL3 3.1.2 CONFIG)
|
|||
find_package(stb MODULE)
|
||||
find_package(toml11 4.2.0 CONFIG)
|
||||
find_package(tsl-robin-map 1.3.0 CONFIG)
|
||||
find_package(VulkanHeaders 1.4.305 CONFIG)
|
||||
find_package(VulkanHeaders 1.4.309 CONFIG)
|
||||
find_package(VulkanMemoryAllocator 3.1.0 CONFIG)
|
||||
find_package(xbyak 7.07 CONFIG)
|
||||
find_package(xxHash 0.8.2 MODULE)
|
||||
find_package(ZLIB 1.3 MODULE)
|
||||
find_package(Zydis 5.0.0 CONFIG)
|
||||
find_package(pugixml 1.14 CONFIG)
|
||||
|
||||
if (NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR NOT MSVC)
|
||||
find_package(cryptopp 8.9.0 MODULE)
|
||||
endif()
|
||||
find_package(libusb 1.0.27 MODULE)
|
||||
|
||||
if (APPLE)
|
||||
find_package(date 3.0.1 CONFIG)
|
||||
|
@ -299,6 +335,8 @@ set(KERNEL_LIB src/core/libraries/kernel/sync/mutex.cpp
|
|||
src/core/libraries/kernel/threads/thread_state.h
|
||||
src/core/libraries/kernel/process.cpp
|
||||
src/core/libraries/kernel/process.h
|
||||
src/core/libraries/kernel/debug.cpp
|
||||
src/core/libraries/kernel/debug.h
|
||||
src/core/libraries/kernel/equeue.cpp
|
||||
src/core/libraries/kernel/equeue.h
|
||||
src/core/libraries/kernel/file_system.cpp
|
||||
|
@ -544,6 +582,8 @@ set(MISC_LIBS src/core/libraries/screenshot/screenshot.cpp
|
|||
src/core/libraries/screenshot/screenshot.h
|
||||
src/core/libraries/move/move.cpp
|
||||
src/core/libraries/move/move.h
|
||||
src/core/libraries/ulobjmgr/ulobjmgr.cpp
|
||||
src/core/libraries/ulobjmgr/ulobjmgr.h
|
||||
)
|
||||
|
||||
set(DEV_TOOLS src/core/devtools/layer.cpp
|
||||
|
@ -634,7 +674,6 @@ set(COMMON src/common/logging/backend.cpp
|
|||
src/common/uint128.h
|
||||
src/common/unique_function.h
|
||||
src/common/va_ctx.h
|
||||
src/common/version.h
|
||||
src/common/ntapi.h
|
||||
src/common/ntapi.cpp
|
||||
src/common/number_utils.h
|
||||
|
@ -1024,7 +1063,7 @@ endif()
|
|||
create_target_directory_groups(shadps4)
|
||||
|
||||
target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt toml11::toml11 tsl::robin_map xbyak::xbyak Tracy::TracyClient RenderDoc::API FFmpeg::ffmpeg Dear_ImGui gcn half::half ZLIB::ZLIB PNG::PNG)
|
||||
target_link_libraries(shadps4 PRIVATE Boost::headers GPUOpen::VulkanMemoryAllocator LibAtrac9 sirit Vulkan::Headers xxHash::xxhash Zydis::Zydis glslang::glslang SDL3::SDL3 pugixml::pugixml stb::headers)
|
||||
target_link_libraries(shadps4 PRIVATE Boost::headers GPUOpen::VulkanMemoryAllocator LibAtrac9 sirit Vulkan::Headers xxHash::xxhash Zydis::Zydis glslang::glslang SDL3::SDL3 pugixml::pugixml stb::headers libusb::usb)
|
||||
|
||||
target_compile_definitions(shadps4 PRIVATE IMGUI_USER_CONFIG="imgui/imgui_config.h")
|
||||
target_compile_definitions(Dear_ImGui PRIVATE IMGUI_USER_CONFIG="${PROJECT_SOURCE_DIR}/src/imgui/imgui_config.h")
|
||||
|
@ -1156,8 +1195,8 @@ if (ENABLE_QT_GUI)
|
|||
MACOSX_BUNDLE ON
|
||||
MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/dist/MacOSBundleInfo.plist.in"
|
||||
MACOSX_BUNDLE_ICON_FILE "shadPS4.icns"
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING "0.4.1"
|
||||
)
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING "${APP_VERSION}"
|
||||
)
|
||||
|
||||
set_source_files_properties(src/images/shadPS4.icns PROPERTIES
|
||||
MACOSX_PACKAGE_LOCATION Resources)
|
||||
|
|
23
README.md
23
README.md
|
@ -71,7 +71,7 @@ Check the build instructions for [**Linux**](https://github.com/shadps4-emu/shad
|
|||
Check the build instructions for [**macOS**](https://github.com/shadps4-emu/shadPS4/blob/main/documents/building-macos.md).
|
||||
|
||||
> [!IMPORTANT]
|
||||
> macOS users need at least macOS 15 on Apple Silicon-based Mac devices and at least macOS 14 on Intel-based Mac devices.
|
||||
> macOS users need at least macOS 15.4 to run shadPS4. Due to GPU issues there are currently heavy bugs on Intel Macs.
|
||||
|
||||
# Debugging and reporting issues
|
||||
|
||||
|
@ -122,6 +122,27 @@ R3 | M |
|
|||
Keyboard and mouse inputs can be customized in the settings menu by clicking the Controller button, and further details and help on controls are also found there. Custom bindings are saved per-game. Inputs support up to three keys per binding, mouse buttons, mouse movement mapped to joystick input, and more.
|
||||
|
||||
|
||||
# Firmware files
|
||||
|
||||
shadPS4 can load some PlayStation 4 firmware files, these must be dumped from your legally owned PlayStation 4 console.\
|
||||
The following firmware modules are supported and must be placed in shadPS4's `user/sys_modules` folder.
|
||||
|
||||
<div align="center">
|
||||
|
||||
| Modules | Modules | Modules | Modules |
|
||||
|-------------------------|-------------------------|-------------------------|-------------------------|
|
||||
| libSceCesCs.sprx | libSceFont.sprx | libSceFontFt.sprx | libSceFreeTypeOt.sprx |
|
||||
| libSceJson.sprx | libSceJson2.sprx | libSceLibcInternal.sprx | libSceNgs2.sprx |
|
||||
| libSceRtc.sprx | libSceUlt.sprx | | |
|
||||
|
||||
</div>
|
||||
|
||||
> [!Caution]
|
||||
> The above modules are required to run the games properly and must be extracted from your PlayStation 4.\
|
||||
> **We do not provide any information or support on how to do this**.
|
||||
|
||||
|
||||
|
||||
# Main team
|
||||
|
||||
- [**georgemoralis**](https://github.com/georgemoralis)
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
# SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_search_module(CRYPTOPP QUIET IMPORTED_TARGET libcryptopp)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(cryptopp
|
||||
REQUIRED_VARS CRYPTOPP_LINK_LIBRARIES
|
||||
VERSION_VAR CRYPTOPP_VERSION
|
||||
)
|
||||
|
||||
if (cryptopp_FOUND AND NOT TARGET cryptopp::cryptopp)
|
||||
add_library(cryptopp::cryptopp ALIAS PkgConfig::CRYPTOPP)
|
||||
endif()
|
15
cmake/Findlibusb.cmake
Normal file
15
cmake/Findlibusb.cmake
Normal file
|
@ -0,0 +1,15 @@
|
|||
# SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_search_module(LIBUSB QUIET IMPORTED_TARGET libusb-1.0)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(libusb
|
||||
REQUIRED_VARS LIBUSB_LINK_LIBRARIES
|
||||
VERSION_VAR LIBUSB_VERSION
|
||||
)
|
||||
|
||||
if (libusb_FOUND AND NOT TARGET libusb::usb)
|
||||
add_library(libusb::usb ALIAS PkgConfig::LIBUSB)
|
||||
endif()
|
|
@ -24,7 +24,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
|||
- A CPU supporting the following instruction sets: MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, F16C, CLMUL, AES, BMI1, MOVBE, XSAVE, ABM
|
||||
- **Intel**: Haswell generation or newer
|
||||
- **AMD**: Jaguar generation or newer
|
||||
- **Apple**: Rosetta 2 on macOS 15 or newer
|
||||
- **Apple**: Rosetta 2 on macOS 15.4 or newer
|
||||
|
||||
### GPU
|
||||
|
||||
|
|
6
externals/CMakeLists.txt
vendored
6
externals/CMakeLists.txt
vendored
|
@ -201,6 +201,12 @@ if (NOT TARGET pugixml::pugixml)
|
|||
add_subdirectory(pugixml)
|
||||
endif()
|
||||
|
||||
# libusb
|
||||
if (NOT TARGET libusb::usb)
|
||||
add_subdirectory(libusb)
|
||||
add_library(libusb::usb ALIAS usb-1.0)
|
||||
endif()
|
||||
|
||||
# Discord RPC
|
||||
if (ENABLE_DISCORD_RPC)
|
||||
add_subdirectory(discord-rpc)
|
||||
|
|
2
externals/MoltenVK/MoltenVK
vendored
2
externals/MoltenVK/MoltenVK
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 2048427e50f9eb20f2b8f98d316ecaee398c9b91
|
||||
Subproject commit 83510e0f3835c3c43651dda087305abc42572e17
|
2
externals/MoltenVK/SPIRV-Cross
vendored
2
externals/MoltenVK/SPIRV-Cross
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 2c32b6bf86f3c4a5539aa1f0bacbd59fe61759cf
|
||||
Subproject commit cb71abe3063094bf383379b15473d39cb1144120
|
2
externals/discord-rpc
vendored
2
externals/discord-rpc
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 51b09d426a4a1bcfa6ee6d4894e57d669f4a2e65
|
||||
Subproject commit d3b5af8827031f3bccbf8c15d5dc1bfdc9467f17
|
1
externals/libusb
vendored
Submodule
1
externals/libusb
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 8f0b4a38fc3eefa2b26a99dff89e1c12bf37afd4
|
2
externals/sirit
vendored
2
externals/sirit
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 8b9b12c2089505ac8b10fa56bf56b3ed49d9d7b0
|
||||
Subproject commit 427a42c9ed99b38204d9107bc3dc14e92458acf1
|
2
externals/vulkan-headers
vendored
2
externals/vulkan-headers
vendored
|
@ -1 +1 @@
|
|||
Subproject commit a03d2f6d5753b365d704d58161825890baad0755
|
||||
Subproject commit 952f776f6573aafbb62ea717d871cd1d6816c387
|
|
@ -7,10 +7,10 @@
|
|||
#include <fmt/xchar.h> // for wstring support
|
||||
#include <toml.hpp>
|
||||
|
||||
#include "common/config.h"
|
||||
#include "common/logging/formatter.h"
|
||||
#include "common/path_util.h"
|
||||
#include "config.h"
|
||||
#include "logging/formatter.h"
|
||||
#include "version.h"
|
||||
#include "common/scm_rev.h"
|
||||
|
||||
namespace toml {
|
||||
template <typename TC, typename K>
|
||||
|
@ -75,7 +75,6 @@ static double trophyNotificationDuration = 6.0;
|
|||
static bool useUnifiedInputConfig = true;
|
||||
static bool overrideControllerColor = false;
|
||||
static int controllerCustomColorRGB[3] = {0, 0, 255};
|
||||
static bool separateupdatefolder = false;
|
||||
static bool compatibilityData = false;
|
||||
static bool checkCompatibilityOnStartup = false;
|
||||
static std::string trophyKey;
|
||||
|
@ -352,10 +351,6 @@ void setVkGuestMarkersEnabled(bool enable) {
|
|||
vkGuestMarkers = enable;
|
||||
}
|
||||
|
||||
bool getSeparateUpdateEnabled() {
|
||||
return separateupdatefolder;
|
||||
}
|
||||
|
||||
bool getCompatibilityEnabled() {
|
||||
return compatibilityData;
|
||||
}
|
||||
|
@ -517,10 +512,6 @@ void setIsMotionControlsEnabled(bool use) {
|
|||
isMotionControlsEnabled = use;
|
||||
}
|
||||
|
||||
void setSeparateUpdateEnabled(bool use) {
|
||||
separateupdatefolder = use;
|
||||
}
|
||||
|
||||
void setCompatibilityEnabled(bool use) {
|
||||
compatibilityData = use;
|
||||
}
|
||||
|
@ -772,7 +763,7 @@ void load(const std::filesystem::path& path) {
|
|||
logFilter = toml::find_or<std::string>(general, "logFilter", "");
|
||||
logType = toml::find_or<std::string>(general, "logType", "sync");
|
||||
userName = toml::find_or<std::string>(general, "userName", "shadPS4");
|
||||
if (Common::isRelease) {
|
||||
if (Common::g_is_release) {
|
||||
updateChannel = toml::find_or<std::string>(general, "updateChannel", "Release");
|
||||
} else {
|
||||
updateChannel = toml::find_or<std::string>(general, "updateChannel", "Nightly");
|
||||
|
@ -781,7 +772,6 @@ void load(const std::filesystem::path& path) {
|
|||
isAutoUpdate = toml::find_or<bool>(general, "autoUpdate", false);
|
||||
isAlwaysShowChangelog = toml::find_or<bool>(general, "alwaysShowChangelog", false);
|
||||
isSideTrophy = toml::find_or<std::string>(general, "sideTrophy", "right");
|
||||
separateupdatefolder = toml::find_or<bool>(general, "separateUpdateEnabled", false);
|
||||
compatibilityData = toml::find_or<bool>(general, "compatibilityEnabled", false);
|
||||
checkCompatibilityOnStartup =
|
||||
toml::find_or<bool>(general, "checkCompatibilityOnStartup", false);
|
||||
|
@ -977,7 +967,6 @@ void save(const std::filesystem::path& path) {
|
|||
data["General"]["autoUpdate"] = isAutoUpdate;
|
||||
data["General"]["alwaysShowChangelog"] = isAlwaysShowChangelog;
|
||||
data["General"]["sideTrophy"] = isSideTrophy;
|
||||
data["General"]["separateUpdateEnabled"] = separateupdatefolder;
|
||||
data["General"]["compatibilityEnabled"] = compatibilityData;
|
||||
data["General"]["checkCompatibilityOnStartup"] = checkCompatibilityOnStartup;
|
||||
data["Input"]["cursorState"] = cursorState;
|
||||
|
@ -1119,7 +1108,7 @@ void setDefaultValues() {
|
|||
logFilter = "";
|
||||
logType = "sync";
|
||||
userName = "shadPS4";
|
||||
if (Common::isRelease) {
|
||||
if (Common::g_is_release) {
|
||||
updateChannel = "Release";
|
||||
} else {
|
||||
updateChannel = "Nightly";
|
||||
|
@ -1150,7 +1139,6 @@ void setDefaultValues() {
|
|||
emulator_language = "en_US";
|
||||
m_language = 1;
|
||||
gpuId = -1;
|
||||
separateupdatefolder = false;
|
||||
compatibilityData = false;
|
||||
checkCompatibilityOnStartup = false;
|
||||
backgroundImageOpacity = 50;
|
||||
|
|
|
@ -35,7 +35,6 @@ bool getPlayBGM();
|
|||
int getBGMvolume();
|
||||
bool getisTrophyPopupDisabled();
|
||||
bool getEnableDiscordRPC();
|
||||
bool getSeparateUpdateEnabled();
|
||||
bool getCompatibilityEnabled();
|
||||
bool getCheckCompatibilityOnStartup();
|
||||
int getBackgroundImageOpacity();
|
||||
|
@ -105,7 +104,6 @@ void setNeoMode(bool enable);
|
|||
void setUserName(const std::string& type);
|
||||
void setUpdateChannel(const std::string& type);
|
||||
void setChooseHomeTab(const std::string& type);
|
||||
void setSeparateUpdateEnabled(bool use);
|
||||
void setGameInstallDirs(const std::vector<std::filesystem::path>& dirs_config);
|
||||
void setAllGameInstallDirs(const std::vector<GameInstallDir>& dirs_config);
|
||||
void setSaveDataPath(const std::filesystem::path& path);
|
||||
|
|
|
@ -3,21 +3,17 @@
|
|||
|
||||
#include "common/scm_rev.h"
|
||||
|
||||
#define GIT_REV "@GIT_REV@"
|
||||
#define GIT_BRANCH "@GIT_BRANCH@"
|
||||
#define GIT_DESC "@GIT_DESC@"
|
||||
#define GIT_REMOTE_NAME "@GIT_REMOTE_NAME@"
|
||||
#define GIT_REMOTE_URL "@GIT_REMOTE_URL@"
|
||||
#define BUILD_DATE "@BUILD_DATE@"
|
||||
|
||||
namespace Common {
|
||||
|
||||
const char g_scm_rev[] = GIT_REV;
|
||||
const char g_scm_branch[] = GIT_BRANCH;
|
||||
const char g_scm_desc[] = GIT_DESC;
|
||||
const char g_scm_remote_name[] = GIT_REMOTE_NAME;
|
||||
const char g_scm_remote_url[] = GIT_REMOTE_URL;
|
||||
const char g_scm_date[] = BUILD_DATE;
|
||||
constexpr char g_version[] = "@APP_VERSION@";
|
||||
constexpr bool g_is_release = @APP_IS_RELEASE@;
|
||||
|
||||
constexpr char g_scm_rev[] = "@GIT_REV@";
|
||||
constexpr char g_scm_branch[] = "@GIT_BRANCH@";
|
||||
constexpr char g_scm_desc[] = "@GIT_DESC@";
|
||||
constexpr char g_scm_remote_name[] = "@GIT_REMOTE_NAME@";
|
||||
constexpr char g_scm_remote_url[] = "@GIT_REMOTE_URL@";
|
||||
constexpr char g_scm_date[] = "@BUILD_DATE@";
|
||||
|
||||
} // namespace
|
||||
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
|
||||
namespace Common {
|
||||
|
||||
extern const char g_version[];
|
||||
extern const bool g_is_release;
|
||||
|
||||
extern const char g_scm_rev[];
|
||||
extern const char g_scm_branch[];
|
||||
extern const char g_scm_desc[];
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
namespace Common {
|
||||
|
||||
constexpr char VERSION[] = "0.7.1 WIP";
|
||||
constexpr bool isRelease = false;
|
||||
|
||||
} // namespace Common
|
|
@ -22,10 +22,6 @@
|
|||
#include <windows.h>
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#ifdef __APPLE__
|
||||
#include <half.hpp>
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
using namespace Xbyak::util;
|
||||
|
@ -81,538 +77,6 @@ static Xbyak::Address ZydisToXbyakMemoryOperand(const ZydisDecodedOperand& opera
|
|||
return ptr[expression];
|
||||
}
|
||||
|
||||
static u64 ZydisToXbyakImmediateOperand(const ZydisDecodedOperand& operand) {
|
||||
ASSERT_MSG(operand.type == ZYDIS_OPERAND_TYPE_IMMEDIATE,
|
||||
"Expected immediate operand, got type: {}", static_cast<u32>(operand.type));
|
||||
return operand.imm.value.u;
|
||||
}
|
||||
|
||||
static std::unique_ptr<Xbyak::Operand> ZydisToXbyakOperand(const ZydisDecodedOperand& operand) {
|
||||
switch (operand.type) {
|
||||
case ZYDIS_OPERAND_TYPE_REGISTER: {
|
||||
return std::make_unique<Xbyak::Reg>(ZydisToXbyakRegisterOperand(operand));
|
||||
}
|
||||
case ZYDIS_OPERAND_TYPE_MEMORY: {
|
||||
return std::make_unique<Xbyak::Address>(ZydisToXbyakMemoryOperand(operand));
|
||||
}
|
||||
default:
|
||||
UNREACHABLE_MSG("Unsupported operand type: {}", static_cast<u32>(operand.type));
|
||||
}
|
||||
}
|
||||
|
||||
static bool OperandUsesRegister(const Xbyak::Operand* operand, int index) {
|
||||
if (operand->isREG()) {
|
||||
return operand->getIdx() == index;
|
||||
}
|
||||
if (operand->isMEM()) {
|
||||
const Xbyak::RegExp& reg_exp = operand->getAddress().getRegExp();
|
||||
return reg_exp.getBase().getIdx() == index || reg_exp.getIndex().getIdx() == index;
|
||||
}
|
||||
UNREACHABLE_MSG("Unsupported operand kind: {}", static_cast<u32>(operand->getKind()));
|
||||
}
|
||||
|
||||
static bool IsRegisterAllocated(
|
||||
const std::initializer_list<const Xbyak::Operand*>& allocated_registers, const int index) {
|
||||
return std::ranges::find_if(allocated_registers.begin(), allocated_registers.end(),
|
||||
[index](const Xbyak::Operand* operand) {
|
||||
return OperandUsesRegister(operand, index);
|
||||
}) != allocated_registers.end();
|
||||
}
|
||||
|
||||
static Xbyak::Reg AllocateScratchRegister(
|
||||
const std::initializer_list<const Xbyak::Operand*> allocated_registers, const u32 bits) {
|
||||
for (int index = Xbyak::Operand::R8; index <= Xbyak::Operand::R15; index++) {
|
||||
if (!IsRegisterAllocated(allocated_registers, index)) {
|
||||
return Xbyak::Reg32e(index, static_cast<int>(bits));
|
||||
}
|
||||
}
|
||||
UNREACHABLE_MSG("Out of scratch registers!");
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
static pthread_key_t stack_pointer_slot;
|
||||
static pthread_key_t patch_stack_slot;
|
||||
static std::once_flag patch_context_slots_init_flag;
|
||||
static constexpr u32 patch_stack_size = 0x1000;
|
||||
|
||||
static_assert(sizeof(void*) == sizeof(u64),
|
||||
"Cannot fit a register inside a thread local storage slot.");
|
||||
|
||||
static void FreePatchStack(void* patch_stack) {
|
||||
// Subtract back to the bottom of the stack for free.
|
||||
std::free(static_cast<u8*>(patch_stack) - patch_stack_size);
|
||||
}
|
||||
|
||||
static void InitializePatchContextSlots() {
|
||||
ASSERT_MSG(pthread_key_create(&stack_pointer_slot, nullptr) == 0,
|
||||
"Unable to allocate thread-local register for stack pointer.");
|
||||
ASSERT_MSG(pthread_key_create(&patch_stack_slot, FreePatchStack) == 0,
|
||||
"Unable to allocate thread-local register for patch stack.");
|
||||
}
|
||||
|
||||
void InitializeThreadPatchStack() {
|
||||
std::call_once(patch_context_slots_init_flag, InitializePatchContextSlots);
|
||||
|
||||
pthread_setspecific(patch_stack_slot,
|
||||
static_cast<u8*>(std::malloc(patch_stack_size)) + patch_stack_size);
|
||||
}
|
||||
|
||||
/// Saves the stack pointer to thread local storage and loads the patch stack.
|
||||
static void SaveStack(Xbyak::CodeGenerator& c) {
|
||||
std::call_once(patch_context_slots_init_flag, InitializePatchContextSlots);
|
||||
|
||||
// Save original stack pointer and load patch stack.
|
||||
c.putSeg(gs);
|
||||
c.mov(qword[reinterpret_cast<void*>(stack_pointer_slot * sizeof(void*))], rsp);
|
||||
c.putSeg(gs);
|
||||
c.mov(rsp, qword[reinterpret_cast<void*>(patch_stack_slot * sizeof(void*))]);
|
||||
}
|
||||
|
||||
/// Restores the stack pointer from thread local storage.
|
||||
static void RestoreStack(Xbyak::CodeGenerator& c) {
|
||||
std::call_once(patch_context_slots_init_flag, InitializePatchContextSlots);
|
||||
|
||||
// Save patch stack pointer and load original stack.
|
||||
c.putSeg(gs);
|
||||
c.mov(qword[reinterpret_cast<void*>(patch_stack_slot * sizeof(void*))], rsp);
|
||||
c.putSeg(gs);
|
||||
c.mov(rsp, qword[reinterpret_cast<void*>(stack_pointer_slot * sizeof(void*))]);
|
||||
}
|
||||
|
||||
/// Validates that the dst register is supported given the SaveStack/RestoreStack implementation.
|
||||
static void ValidateDst(const Xbyak::Reg& dst) {
|
||||
// No restrictions.
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void InitializeThreadPatchStack() {
|
||||
// No-op
|
||||
}
|
||||
|
||||
// NOTE: Since stack pointer here is subtracted through safe zone and not saved anywhere,
|
||||
// it must not be modified during the instruction. Otherwise, we will not be able to find
|
||||
// and load registers back from where they were saved. Thus, a limitation is placed on
|
||||
// instructions, that they must not use the stack pointer register as a destination.
|
||||
|
||||
/// Saves the stack pointer to thread local storage and loads the patch stack.
|
||||
static void SaveStack(Xbyak::CodeGenerator& c) {
|
||||
c.lea(rsp, ptr[rsp - 128]); // red zone
|
||||
}
|
||||
|
||||
/// Restores the stack pointer from thread local storage.
|
||||
static void RestoreStack(Xbyak::CodeGenerator& c) {
|
||||
c.lea(rsp, ptr[rsp + 128]); // red zone
|
||||
}
|
||||
|
||||
/// Validates that the dst register is supported given the SaveStack/RestoreStack implementation.
|
||||
static void ValidateDst(const Xbyak::Reg& dst) {
|
||||
// Stack pointer is not preserved, so it can't be used as a dst.
|
||||
ASSERT_MSG(dst.getIdx() != rsp.getIdx(), "Stack pointer not supported as destination.");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/// Switches to the patch stack, saves registers, and restores the original stack.
|
||||
static void SaveRegisters(Xbyak::CodeGenerator& c, const std::initializer_list<Xbyak::Reg> regs) {
|
||||
// Uses a more robust solution for saving registers on MacOS to avoid potential stack corruption
|
||||
// if games decide to not follow the ABI and use the red zone.
|
||||
SaveStack(c);
|
||||
for (const auto& reg : regs) {
|
||||
c.push(reg.cvt64());
|
||||
}
|
||||
RestoreStack(c);
|
||||
}
|
||||
|
||||
/// Switches to the patch stack, restores registers, and restores the original stack.
|
||||
static void RestoreRegisters(Xbyak::CodeGenerator& c,
|
||||
const std::initializer_list<Xbyak::Reg> regs) {
|
||||
SaveStack(c);
|
||||
for (const auto& reg : regs) {
|
||||
c.pop(reg.cvt64());
|
||||
}
|
||||
RestoreStack(c);
|
||||
}
|
||||
|
||||
/// Switches to the patch stack and stores all registers.
|
||||
static void SaveContext(Xbyak::CodeGenerator& c, bool save_flags = false) {
|
||||
SaveStack(c);
|
||||
for (int reg = Xbyak::Operand::RAX; reg <= Xbyak::Operand::R15; reg++) {
|
||||
c.push(Xbyak::Reg64(reg));
|
||||
}
|
||||
c.lea(rsp, ptr[rsp - 32 * 16]);
|
||||
for (int reg = 0; reg <= 15; reg++) {
|
||||
c.vmovdqu(ptr[rsp + 32 * reg], Xbyak::Ymm(reg));
|
||||
}
|
||||
if (save_flags) {
|
||||
c.pushfq();
|
||||
}
|
||||
}
|
||||
|
||||
/// Restores all registers and restores the original stack.
|
||||
/// If the destination is a register, it is not restored to preserve the output.
|
||||
static void RestoreContext(Xbyak::CodeGenerator& c, const Xbyak::Operand& dst,
|
||||
bool restore_flags = false) {
|
||||
if (restore_flags) {
|
||||
c.popfq();
|
||||
}
|
||||
for (int reg = 15; reg >= 0; reg--) {
|
||||
if ((!dst.isXMM() && !dst.isYMM()) || dst.getIdx() != reg) {
|
||||
c.vmovdqu(Xbyak::Ymm(reg), ptr[rsp + 32 * reg]);
|
||||
}
|
||||
}
|
||||
c.lea(rsp, ptr[rsp + 32 * 16]);
|
||||
for (int reg = Xbyak::Operand::R15; reg >= Xbyak::Operand::RAX; reg--) {
|
||||
if (!dst.isREG() || dst.getIdx() != reg) {
|
||||
c.pop(Xbyak::Reg64(reg));
|
||||
} else {
|
||||
c.lea(rsp, ptr[rsp + 8]);
|
||||
}
|
||||
}
|
||||
RestoreStack(c);
|
||||
}
|
||||
|
||||
static void GenerateANDN(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
||||
const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
|
||||
const auto src1 = ZydisToXbyakRegisterOperand(operands[1]);
|
||||
const auto src2 = ZydisToXbyakOperand(operands[2]);
|
||||
ValidateDst(dst);
|
||||
|
||||
// Check if src2 is a memory operand or a register different to dst.
|
||||
// In those cases, we don't need to use a temporary register and are free to modify dst.
|
||||
// In cases where dst and src2 are the same register, a temporary needs to be used to avoid
|
||||
// modifying src2.
|
||||
bool src2_uses_dst = false;
|
||||
if (src2->isMEM()) {
|
||||
const auto base = src2->getAddress().getRegExp().getBase().getIdx();
|
||||
const auto index = src2->getAddress().getRegExp().getIndex().getIdx();
|
||||
src2_uses_dst = base == dst.getIdx() || index == dst.getIdx();
|
||||
} else {
|
||||
ASSERT(src2->isREG());
|
||||
src2_uses_dst = src2->getReg() == dst;
|
||||
}
|
||||
|
||||
if (!src2_uses_dst) {
|
||||
if (dst != src1)
|
||||
c.mov(dst, src1);
|
||||
c.not_(dst);
|
||||
c.and_(dst, *src2);
|
||||
} else {
|
||||
const auto scratch = AllocateScratchRegister({&dst, &src1, src2.get()}, dst.getBit());
|
||||
|
||||
SaveRegisters(c, {scratch});
|
||||
|
||||
c.mov(scratch, src1);
|
||||
c.not_(scratch);
|
||||
c.and_(scratch, *src2);
|
||||
c.mov(dst, scratch);
|
||||
|
||||
RestoreRegisters(c, {scratch});
|
||||
}
|
||||
}
|
||||
|
||||
static void GenerateBEXTR(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
||||
const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
|
||||
const auto src = ZydisToXbyakOperand(operands[1]);
|
||||
const auto start_len = ZydisToXbyakRegisterOperand(operands[2]);
|
||||
ValidateDst(dst);
|
||||
|
||||
const Xbyak::Reg32e shift(Xbyak::Operand::RCX, static_cast<int>(start_len.getBit()));
|
||||
const auto scratch1 =
|
||||
AllocateScratchRegister({&dst, src.get(), &start_len, &shift}, dst.getBit());
|
||||
const auto scratch2 =
|
||||
AllocateScratchRegister({&dst, src.get(), &start_len, &shift, &scratch1}, dst.getBit());
|
||||
|
||||
if (dst.getIdx() == shift.getIdx()) {
|
||||
SaveRegisters(c, {scratch1, scratch2});
|
||||
} else {
|
||||
SaveRegisters(c, {scratch1, scratch2, shift});
|
||||
}
|
||||
|
||||
c.mov(scratch1, *src);
|
||||
if (shift.getIdx() != start_len.getIdx()) {
|
||||
c.mov(shift, start_len);
|
||||
}
|
||||
|
||||
c.shr(scratch1, shift.cvt8());
|
||||
c.shr(shift, 8);
|
||||
c.mov(scratch2, 1);
|
||||
c.shl(scratch2, shift.cvt8());
|
||||
c.dec(scratch2);
|
||||
|
||||
c.mov(dst, scratch1);
|
||||
c.and_(dst, scratch2);
|
||||
|
||||
if (dst.getIdx() == shift.getIdx()) {
|
||||
RestoreRegisters(c, {scratch2, scratch1});
|
||||
} else {
|
||||
RestoreRegisters(c, {shift, scratch2, scratch1});
|
||||
}
|
||||
}
|
||||
|
||||
static void GenerateBLSI(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
||||
const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
|
||||
const auto src = ZydisToXbyakOperand(operands[1]);
|
||||
ValidateDst(dst);
|
||||
|
||||
const auto scratch = AllocateScratchRegister({&dst, src.get()}, dst.getBit());
|
||||
|
||||
SaveRegisters(c, {scratch});
|
||||
|
||||
// BLSI sets CF to zero if source is zero, otherwise it sets CF to one.
|
||||
Xbyak::Label clear_carry, end;
|
||||
|
||||
c.mov(scratch, *src);
|
||||
c.neg(scratch); // NEG, like BLSI, clears CF if the source is zero and sets it otherwise
|
||||
c.jnc(clear_carry);
|
||||
|
||||
c.and_(scratch, *src);
|
||||
c.stc(); // setting/clearing carry needs to happen after the AND because that clears CF
|
||||
c.jmp(end);
|
||||
|
||||
c.L(clear_carry);
|
||||
c.and_(scratch, *src);
|
||||
// We don't need to clear carry here since AND does that for us
|
||||
|
||||
c.L(end);
|
||||
c.mov(dst, scratch);
|
||||
|
||||
RestoreRegisters(c, {scratch});
|
||||
}
|
||||
|
||||
static void GenerateBLSMSK(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
||||
const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
|
||||
const auto src = ZydisToXbyakOperand(operands[1]);
|
||||
ValidateDst(dst);
|
||||
|
||||
const auto scratch = AllocateScratchRegister({&dst, src.get()}, dst.getBit());
|
||||
|
||||
SaveRegisters(c, {scratch});
|
||||
|
||||
Xbyak::Label clear_carry, end;
|
||||
|
||||
// BLSMSK sets CF to zero if source is NOT zero, otherwise it sets CF to one.
|
||||
c.mov(scratch, *src);
|
||||
c.test(scratch, scratch);
|
||||
c.jnz(clear_carry);
|
||||
|
||||
c.dec(scratch);
|
||||
c.xor_(scratch, *src);
|
||||
c.stc();
|
||||
c.jmp(end);
|
||||
|
||||
c.L(clear_carry);
|
||||
c.dec(scratch);
|
||||
c.xor_(scratch, *src);
|
||||
// We don't need to clear carry here since XOR does that for us
|
||||
|
||||
c.L(end);
|
||||
c.mov(dst, scratch);
|
||||
|
||||
RestoreRegisters(c, {scratch});
|
||||
}
|
||||
|
||||
static void GenerateTZCNT(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
||||
const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
|
||||
const auto src = ZydisToXbyakOperand(operands[1]);
|
||||
ValidateDst(dst);
|
||||
|
||||
Xbyak::Label src_zero, end;
|
||||
|
||||
c.cmp(*src, 0);
|
||||
c.je(src_zero);
|
||||
|
||||
// If src is not zero, functions like a BSF, but also clears the CF
|
||||
c.bsf(dst, *src);
|
||||
c.clc();
|
||||
c.jmp(end);
|
||||
|
||||
c.L(src_zero);
|
||||
c.mov(dst, operands[0].size);
|
||||
// Since dst is not zero, also set ZF to zero. Testing dst with itself when we know
|
||||
// it isn't zero is a good way to do this.
|
||||
// Use cvt32 to avoid REX/Operand size prefixes.
|
||||
c.test(dst.cvt32(), dst.cvt32());
|
||||
// When source is zero, TZCNT also sets CF.
|
||||
c.stc();
|
||||
|
||||
c.L(end);
|
||||
}
|
||||
|
||||
static void GenerateBLSR(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
||||
const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
|
||||
const auto src = ZydisToXbyakOperand(operands[1]);
|
||||
ValidateDst(dst);
|
||||
|
||||
const auto scratch = AllocateScratchRegister({&dst, src.get()}, dst.getBit());
|
||||
|
||||
SaveRegisters(c, {scratch});
|
||||
|
||||
Xbyak::Label clear_carry, end;
|
||||
|
||||
// BLSR sets CF to zero if source is NOT zero, otherwise it sets CF to one.
|
||||
c.mov(scratch, *src);
|
||||
c.test(scratch, scratch);
|
||||
c.jnz(clear_carry);
|
||||
|
||||
c.dec(scratch);
|
||||
c.and_(scratch, *src);
|
||||
c.stc();
|
||||
c.jmp(end);
|
||||
|
||||
c.L(clear_carry);
|
||||
c.dec(scratch);
|
||||
c.and_(scratch, *src);
|
||||
// We don't need to clear carry here since AND does that for us
|
||||
|
||||
c.L(end);
|
||||
c.mov(dst, scratch);
|
||||
|
||||
RestoreRegisters(c, {scratch});
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
static __attribute__((sysv_abi)) void PerformVCVTPH2PS(float* out, const half_float::half* in,
|
||||
const u32 count) {
|
||||
for (u32 i = 0; i < count; i++) {
|
||||
out[i] = half_float::half_cast<float>(in[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void GenerateVCVTPH2PS(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
||||
const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
|
||||
const auto src = ZydisToXbyakOperand(operands[1]);
|
||||
|
||||
const auto float_count = dst.getBit() / 32;
|
||||
const auto byte_count = float_count * 4;
|
||||
|
||||
SaveContext(c, true);
|
||||
|
||||
// Allocate stack space for outputs and load into first parameter.
|
||||
c.sub(rsp, byte_count);
|
||||
c.mov(rdi, rsp);
|
||||
|
||||
if (src->isXMM()) {
|
||||
// Allocate stack space for inputs and load into second parameter.
|
||||
c.sub(rsp, byte_count);
|
||||
c.mov(rsi, rsp);
|
||||
|
||||
// Move input to the allocated space.
|
||||
c.movdqu(ptr[rsp], *reinterpret_cast<Xbyak::Xmm*>(src.get()));
|
||||
} else {
|
||||
c.lea(rsi, src->getAddress());
|
||||
}
|
||||
|
||||
// Load float count into third parameter.
|
||||
c.mov(rdx, float_count);
|
||||
|
||||
c.mov(rax, reinterpret_cast<u64>(PerformVCVTPH2PS));
|
||||
c.call(rax);
|
||||
|
||||
if (src->isXMM()) {
|
||||
// Clean up after inputs space.
|
||||
c.add(rsp, byte_count);
|
||||
}
|
||||
|
||||
// Load outputs into destination register and clean up space.
|
||||
if (dst.isYMM()) {
|
||||
c.vmovdqu(*reinterpret_cast<const Xbyak::Ymm*>(&dst), ptr[rsp]);
|
||||
} else {
|
||||
c.movdqu(*reinterpret_cast<const Xbyak::Xmm*>(&dst), ptr[rsp]);
|
||||
}
|
||||
c.add(rsp, byte_count);
|
||||
|
||||
RestoreContext(c, dst, true);
|
||||
}
|
||||
|
||||
using SingleToHalfFloatConverter = half_float::half (*)(float);
|
||||
static const SingleToHalfFloatConverter SingleToHalfFloatConverters[4] = {
|
||||
half_float::half_cast<half_float::half, std::round_to_nearest, float>,
|
||||
half_float::half_cast<half_float::half, std::round_toward_neg_infinity, float>,
|
||||
half_float::half_cast<half_float::half, std::round_toward_infinity, float>,
|
||||
half_float::half_cast<half_float::half, std::round_toward_zero, float>,
|
||||
};
|
||||
|
||||
static __attribute__((sysv_abi)) void PerformVCVTPS2PH(half_float::half* out, const float* in,
|
||||
const u32 count, const u8 rounding_mode) {
|
||||
const auto conversion_func = SingleToHalfFloatConverters[rounding_mode];
|
||||
|
||||
for (u32 i = 0; i < count; i++) {
|
||||
out[i] = conversion_func(in[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void GenerateVCVTPS2PH(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
||||
const auto dst = ZydisToXbyakOperand(operands[0]);
|
||||
const auto src = ZydisToXbyakRegisterOperand(operands[1]);
|
||||
const auto ctrl = ZydisToXbyakImmediateOperand(operands[2]);
|
||||
|
||||
const auto float_count = src.getBit() / 32;
|
||||
const auto byte_count = float_count * 4;
|
||||
|
||||
SaveContext(c, true);
|
||||
|
||||
if (dst->isXMM()) {
|
||||
// Allocate stack space for outputs and load into first parameter.
|
||||
c.sub(rsp, byte_count);
|
||||
c.mov(rdi, rsp);
|
||||
} else {
|
||||
c.lea(rdi, dst->getAddress());
|
||||
}
|
||||
|
||||
// Allocate stack space for inputs and load into second parameter.
|
||||
c.sub(rsp, byte_count);
|
||||
c.mov(rsi, rsp);
|
||||
|
||||
// Move input to the allocated space.
|
||||
if (src.isYMM()) {
|
||||
c.vmovdqu(ptr[rsp], *reinterpret_cast<const Xbyak::Ymm*>(&src));
|
||||
} else {
|
||||
c.movdqu(ptr[rsp], *reinterpret_cast<const Xbyak::Xmm*>(&src));
|
||||
}
|
||||
|
||||
// Load float count into third parameter.
|
||||
c.mov(rdx, float_count);
|
||||
|
||||
// Load rounding mode into fourth parameter.
|
||||
if (ctrl & 4) {
|
||||
// Load from MXCSR.RC.
|
||||
c.stmxcsr(ptr[rsp - 4]);
|
||||
c.mov(rcx, ptr[rsp - 4]);
|
||||
c.shr(rcx, 13);
|
||||
c.and_(rcx, 3);
|
||||
} else {
|
||||
c.mov(rcx, ctrl & 3);
|
||||
}
|
||||
|
||||
c.mov(rax, reinterpret_cast<u64>(PerformVCVTPS2PH));
|
||||
c.call(rax);
|
||||
|
||||
// Clean up after inputs space.
|
||||
c.add(rsp, byte_count);
|
||||
|
||||
if (dst->isXMM()) {
|
||||
// Load outputs into destination register and clean up space.
|
||||
c.movdqu(*reinterpret_cast<Xbyak::Xmm*>(dst.get()), ptr[rsp]);
|
||||
c.add(rsp, byte_count);
|
||||
}
|
||||
|
||||
RestoreContext(c, *dst, true);
|
||||
}
|
||||
|
||||
static bool FilterRosetta2Only(const ZydisDecodedOperand*) {
|
||||
int ret = 0;
|
||||
size_t size = sizeof(ret);
|
||||
if (sysctlbyname("sysctl.proc_translated", &ret, &size, nullptr, 0) != 0) {
|
||||
return false;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else // __APPLE__
|
||||
|
||||
static bool FilterTcbAccess(const ZydisDecodedOperand* operands) {
|
||||
const auto& dst_op = operands[0];
|
||||
const auto& src_op = operands[1];
|
||||
|
@ -657,18 +121,11 @@ static void GenerateTcbAccess(const ZydisDecodedOperand* operands, Xbyak::CodeGe
|
|||
#endif
|
||||
}
|
||||
|
||||
#endif // __APPLE__
|
||||
|
||||
static bool FilterNoSSE4a(const ZydisDecodedOperand*) {
|
||||
Cpu cpu;
|
||||
return !cpu.has(Cpu::tSSE4a);
|
||||
}
|
||||
|
||||
static bool FilterNoBMI1(const ZydisDecodedOperand*) {
|
||||
Cpu cpu;
|
||||
return !cpu.has(Cpu::tBMI1);
|
||||
}
|
||||
|
||||
static void GenerateEXTRQ(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
||||
bool immediateForm = operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
|
||||
operands[2].type == ZYDIS_OPERAND_TYPE_IMMEDIATE;
|
||||
|
@ -940,30 +397,16 @@ struct PatchInfo {
|
|||
};
|
||||
|
||||
static const std::unordered_map<ZydisMnemonic, PatchInfo> Patches = {
|
||||
// SSE4a
|
||||
{ZYDIS_MNEMONIC_EXTRQ, {FilterNoSSE4a, GenerateEXTRQ, true}},
|
||||
{ZYDIS_MNEMONIC_INSERTQ, {FilterNoSSE4a, GenerateINSERTQ, true}},
|
||||
|
||||
#if defined(_WIN32)
|
||||
// Windows needs a trampoline.
|
||||
{ZYDIS_MNEMONIC_MOV, {FilterTcbAccess, GenerateTcbAccess, true}},
|
||||
#elif !defined(__APPLE__)
|
||||
{ZYDIS_MNEMONIC_MOV, {FilterTcbAccess, GenerateTcbAccess, false}},
|
||||
#endif
|
||||
|
||||
{ZYDIS_MNEMONIC_EXTRQ, {FilterNoSSE4a, GenerateEXTRQ, true}},
|
||||
{ZYDIS_MNEMONIC_INSERTQ, {FilterNoSSE4a, GenerateINSERTQ, true}},
|
||||
|
||||
// BMI1
|
||||
{ZYDIS_MNEMONIC_ANDN, {FilterNoBMI1, GenerateANDN, true}},
|
||||
{ZYDIS_MNEMONIC_BEXTR, {FilterNoBMI1, GenerateBEXTR, true}},
|
||||
{ZYDIS_MNEMONIC_BLSI, {FilterNoBMI1, GenerateBLSI, true}},
|
||||
{ZYDIS_MNEMONIC_BLSMSK, {FilterNoBMI1, GenerateBLSMSK, true}},
|
||||
{ZYDIS_MNEMONIC_BLSR, {FilterNoBMI1, GenerateBLSR, true}},
|
||||
{ZYDIS_MNEMONIC_TZCNT, {FilterNoBMI1, GenerateTZCNT, true}},
|
||||
|
||||
#ifdef __APPLE__
|
||||
// Patches for instruction sets not supported by Rosetta 2.
|
||||
// F16C
|
||||
{ZYDIS_MNEMONIC_VCVTPH2PS, {FilterRosetta2Only, GenerateVCVTPH2PS, true}},
|
||||
{ZYDIS_MNEMONIC_VCVTPS2PH, {FilterRosetta2Only, GenerateVCVTPS2PH, true}},
|
||||
#endif
|
||||
};
|
||||
|
||||
static std::once_flag init_flag;
|
||||
|
@ -1280,18 +723,7 @@ void RegisterPatchModule(void* module_ptr, u64 module_size, void* trampoline_are
|
|||
}
|
||||
|
||||
void PrePatchInstructions(u64 segment_addr, u64 segment_size) {
|
||||
#if defined(__APPLE__)
|
||||
// HACK: For some reason patching in the signal handler at the start of a page does not work
|
||||
// under Rosetta 2. Patch any instructions at the start of a page ahead of time.
|
||||
if (!Patches.empty()) {
|
||||
auto* code_page = reinterpret_cast<u8*>(Common::AlignUp(segment_addr, 0x1000));
|
||||
const auto* end_page = code_page + Common::AlignUp(segment_size, 0x1000);
|
||||
while (code_page < end_page) {
|
||||
TryPatchJit(code_page);
|
||||
code_page += 0x1000;
|
||||
}
|
||||
}
|
||||
#elif !defined(_WIN32)
|
||||
#if !defined(_WIN32) && !defined(__APPLE__)
|
||||
// Linux and others have an FS segment pointing to valid memory, so continue to do full
|
||||
// ahead-of-time patching for now until a better solution is worked out.
|
||||
if (!Patches.empty()) {
|
||||
|
|
|
@ -7,12 +7,6 @@
|
|||
|
||||
namespace Core {
|
||||
|
||||
/// Initializes a stack for the current thread for use by patch implementations.
|
||||
void InitializeThreadPatchStack();
|
||||
|
||||
/// Cleans up the patch stack for the current thread.
|
||||
void CleanupThreadPatchStack();
|
||||
|
||||
/// Registers a module for patching, providing an area to generate trampoline code.
|
||||
void RegisterPatchModule(void* module_ptr, u64 module_size, void* trampoline_area_ptr,
|
||||
u64 trampoline_area_size);
|
||||
|
|
20
src/core/libraries/kernel/debug.cpp
Normal file
20
src/core/libraries/kernel/debug.cpp
Normal file
|
@ -0,0 +1,20 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "core/libraries/kernel/file_system.h"
|
||||
#include "core/libraries/kernel/orbis_error.h"
|
||||
#include "core/libraries/libs.h"
|
||||
|
||||
namespace Libraries::Kernel {
|
||||
|
||||
void PS4_SYSV_ABI sceKernelDebugOutText(void* unk, char* text) {
|
||||
sceKernelWrite(1, text, strlen(text));
|
||||
return;
|
||||
}
|
||||
|
||||
void RegisterDebug(Core::Loader::SymbolsResolver* sym) {
|
||||
LIB_FUNCTION("9JYNqN6jAKI", "libkernel", 1, "libkernel", 1, 1, sceKernelDebugOutText);
|
||||
}
|
||||
|
||||
} // namespace Libraries::Kernel
|
14
src/core/libraries/kernel/debug.h
Normal file
14
src/core/libraries/kernel/debug.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Core::Loader {
|
||||
class SymbolsResolver;
|
||||
}
|
||||
|
||||
namespace Libraries::Kernel {
|
||||
|
||||
void RegisterDebug(Core::Loader::SymbolsResolver* sym);
|
||||
|
||||
} // namespace Libraries::Kernel
|
|
@ -190,16 +190,16 @@ s32 PS4_SYSV_ABI sceKernelOpen(const char* path, s32 flags, /* SceKernelMode*/ u
|
|||
}
|
||||
|
||||
s32 PS4_SYSV_ABI close(s32 fd) {
|
||||
if (fd < 3) {
|
||||
// This is technically possible, but it's usually caused by some stubbed function instead.
|
||||
LOG_WARNING(Kernel_Fs, "called on an std handle, fd = {}", fd);
|
||||
}
|
||||
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
|
||||
auto* file = h->GetFile(fd);
|
||||
if (file == nullptr) {
|
||||
*__Error() = POSIX_EBADF;
|
||||
return -1;
|
||||
}
|
||||
if (fd < 3) {
|
||||
// This is technically possible, but it's usually caused by some stubbed function instead.
|
||||
LOG_WARNING(Kernel_Fs, "called on an std handle, fd = {}", fd);
|
||||
}
|
||||
if (file->type == Core::FileSys::FileType::Regular) {
|
||||
file->f.Close();
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "common/va_ctx.h"
|
||||
#include "core/file_sys/fs.h"
|
||||
#include "core/libraries/error_codes.h"
|
||||
#include "core/libraries/kernel/debug.h"
|
||||
#include "core/libraries/kernel/equeue.h"
|
||||
#include "core/libraries/kernel/file_system.h"
|
||||
#include "core/libraries/kernel/kernel.h"
|
||||
|
@ -219,6 +220,7 @@ void RegisterKernel(Core::Loader::SymbolsResolver* sym) {
|
|||
Libraries::Kernel::RegisterProcess(sym);
|
||||
Libraries::Kernel::RegisterException(sym);
|
||||
Libraries::Kernel::RegisterAio(sym);
|
||||
Libraries::Kernel::RegisterDebug(sym);
|
||||
|
||||
LIB_OBJ("f7uOxY9mM1U", "libkernel", 1, "libkernel", 1, 1, &g_stack_chk_guard);
|
||||
LIB_FUNCTION("PfccT7qURYE", "libkernel", 1, "libkernel", 1, 1, kernel_ioctl);
|
||||
|
|
|
@ -127,6 +127,11 @@ int PS4_SYSV_ABI sceKernelGetModuleInfoFromAddr(VAddr addr, int flags,
|
|||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI exit(s32 status) {
|
||||
UNREACHABLE_MSG("Exiting with status code {}", status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void RegisterProcess(Core::Loader::SymbolsResolver* sym) {
|
||||
LIB_FUNCTION("WB66evu8bsU", "libkernel", 1, "libkernel", 1, 1, sceKernelGetCompiledSdkVersion);
|
||||
LIB_FUNCTION("WslcK1FQcGI", "libkernel", 1, "libkernel", 1, 1, sceKernelIsNeoMode);
|
||||
|
@ -136,6 +141,7 @@ void RegisterProcess(Core::Loader::SymbolsResolver* sym) {
|
|||
LIB_FUNCTION("LwG8g3niqwA", "libkernel", 1, "libkernel", 1, 1, sceKernelDlsym);
|
||||
LIB_FUNCTION("RpQJJVKTiFM", "libkernel", 1, "libkernel", 1, 1, sceKernelGetModuleInfoForUnwind);
|
||||
LIB_FUNCTION("f7KBOafysXo", "libkernel", 1, "libkernel", 1, 1, sceKernelGetModuleInfoFromAddr);
|
||||
LIB_FUNCTION("6Z83sYWFlA8", "libkernel", 1, "libkernel", 1, 1, exit);
|
||||
}
|
||||
|
||||
} // namespace Libraries::Kernel
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "core/libraries/kernel/orbis_error.h"
|
||||
#include "core/libraries/kernel/threads/exception.h"
|
||||
#include "core/libraries/kernel/threads/pthread.h"
|
||||
#include "core/libraries/libs.h"
|
||||
|
@ -148,13 +149,19 @@ int PS4_SYSV_ABI sceKernelRaiseException(PthreadT thread, int signum) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceKernelDebugRaiseException() {
|
||||
UNREACHABLE();
|
||||
s32 PS4_SYSV_ABI sceKernelDebugRaiseException(s32 error, s64 unk) {
|
||||
if (unk != 0) {
|
||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
UNREACHABLE_MSG("error {:#x}", error);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceKernelDebugRaiseExceptionOnReleaseMode() {
|
||||
UNREACHABLE();
|
||||
s32 PS4_SYSV_ABI sceKernelDebugRaiseExceptionOnReleaseMode(s32 error, s64 unk) {
|
||||
if (unk != 0) {
|
||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
UNREACHABLE_MSG("error {:#x}", error);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -163,7 +170,7 @@ void RegisterException(Core::Loader::SymbolsResolver* sym) {
|
|||
LIB_FUNCTION("WkwEd3N7w0Y", "libkernel_unity", 1, "libkernel", 1, 1,
|
||||
sceKernelInstallExceptionHandler);
|
||||
LIB_FUNCTION("Qhv5ARAoOEc", "libkernel_unity", 1, "libkernel", 1, 1,
|
||||
sceKernelRemoveExceptionHandler)
|
||||
sceKernelRemoveExceptionHandler);
|
||||
LIB_FUNCTION("OMDRKKAZ8I4", "libkernel", 1, "libkernel", 1, 1, sceKernelDebugRaiseException);
|
||||
LIB_FUNCTION("zE-wXIZjLoM", "libkernel", 1, "libkernel", 1, 1,
|
||||
sceKernelDebugRaiseExceptionOnReleaseMode);
|
||||
|
|
|
@ -147,6 +147,11 @@ void RegisterSpec(Core::Loader::SymbolsResolver* sym) {
|
|||
LIB_FUNCTION("0-KXaS70xy4", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_getspecific);
|
||||
LIB_FUNCTION("WrOLvHU0yQM", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_setspecific);
|
||||
|
||||
// Posix-Kernel
|
||||
LIB_FUNCTION("mqULNdimTn0", "libkernel", 1, "libkernel", 1, 1, posix_pthread_key_create);
|
||||
LIB_FUNCTION("0-KXaS70xy4", "libkernel", 1, "libkernel", 1, 1, posix_pthread_getspecific);
|
||||
LIB_FUNCTION("WrOLvHU0yQM", "libkernel", 1, "libkernel", 1, 1, posix_pthread_setspecific);
|
||||
|
||||
// Orbis
|
||||
LIB_FUNCTION("geDaqgH9lTg", "libkernel", 1, "libkernel", 1, 1, ORBIS(posix_pthread_key_create));
|
||||
LIB_FUNCTION("PrdHuuDekhY", "libkernel", 1, "libkernel", 1, 1, ORBIS(posix_pthread_key_delete));
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include "core/libraries/system/sysmodule.h"
|
||||
#include "core/libraries/system/systemservice.h"
|
||||
#include "core/libraries/system/userservice.h"
|
||||
#include "core/libraries/ulobjmgr/ulobjmgr.h"
|
||||
#include "core/libraries/usbd/usbd.h"
|
||||
#include "core/libraries/videodec/videodec.h"
|
||||
#include "core/libraries/videodec/videodec2.h"
|
||||
|
@ -116,6 +117,7 @@ void InitHLELibs(Core::Loader::SymbolsResolver* sym) {
|
|||
Libraries::Zlib::RegisterlibSceZlib(sym);
|
||||
Libraries::Hmd::RegisterlibSceHmd(sym);
|
||||
Libraries::DiscMap::RegisterlibSceDiscMap(sym);
|
||||
Libraries::Ulobjmgr::RegisterlibSceUlobjmgr(sym);
|
||||
}
|
||||
|
||||
} // namespace Libraries
|
||||
|
|
|
@ -18,36 +18,32 @@ namespace Libraries::Ngs2 {
|
|||
|
||||
s32 PS4_SYSV_ABI sceNgs2CalcWaveformBlock(const OrbisNgs2WaveformFormat* format, u32 samplePos,
|
||||
u32 numSamples, OrbisNgs2WaveformBlock* outBlock) {
|
||||
LOG_INFO(Lib_Ngs2, "samplePos = {}, numSamples = {}", samplePos, numSamples);
|
||||
LOG_ERROR(Lib_Ngs2, "samplePos = {}, numSamples = {}", samplePos, numSamples);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2GetWaveformFrameInfo(const OrbisNgs2WaveformFormat* format,
|
||||
u32* outFrameSize, u32* outNumFrameSamples,
|
||||
u32* outUnitsPerFrame, u32* outNumDelaySamples) {
|
||||
LOG_INFO(Lib_Ngs2, "called");
|
||||
LOG_ERROR(Lib_Ngs2, "called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2ParseWaveformData(const void* data, size_t dataSize,
|
||||
OrbisNgs2WaveformInfo* outInfo) {
|
||||
LOG_INFO(Lib_Ngs2, "dataSize = {}", dataSize);
|
||||
LOG_ERROR(Lib_Ngs2, "dataSize = {}", dataSize);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2ParseWaveformFile(const char* path, u64 offset,
|
||||
OrbisNgs2WaveformInfo* outInfo) {
|
||||
LOG_INFO(Lib_Ngs2, "path = {}, offset = {}", path, offset);
|
||||
LOG_ERROR(Lib_Ngs2, "path = {}, offset = {}", path, offset);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2ParseWaveformUser(OrbisNgs2ParseReadHandler handler, uintptr_t userData,
|
||||
OrbisNgs2WaveformInfo* outInfo) {
|
||||
LOG_INFO(Lib_Ngs2, "userData = {}", userData);
|
||||
if (!handler) {
|
||||
LOG_ERROR(Lib_Ngs2, "handler is nullptr");
|
||||
return ORBIS_NGS2_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
LOG_ERROR(Lib_Ngs2, "userData = {}", userData);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
|
@ -55,7 +51,7 @@ s32 PS4_SYSV_ABI sceNgs2RackCreate(OrbisNgs2Handle systemHandle, u32 rackId,
|
|||
const OrbisNgs2RackOption* option,
|
||||
const OrbisNgs2ContextBufferInfo* bufferInfo,
|
||||
OrbisNgs2Handle* outHandle) {
|
||||
LOG_INFO(Lib_Ngs2, "rackId = {}", rackId);
|
||||
LOG_ERROR(Lib_Ngs2, "rackId = {}", rackId);
|
||||
if (!systemHandle) {
|
||||
LOG_ERROR(Lib_Ngs2, "systemHandle is nullptr");
|
||||
return ORBIS_NGS2_ERROR_INVALID_SYSTEM_HANDLE;
|
||||
|
@ -67,7 +63,7 @@ s32 PS4_SYSV_ABI sceNgs2RackCreateWithAllocator(OrbisNgs2Handle systemHandle, u3
|
|||
const OrbisNgs2RackOption* option,
|
||||
const OrbisNgs2BufferAllocator* allocator,
|
||||
OrbisNgs2Handle* outHandle) {
|
||||
LOG_INFO(Lib_Ngs2, "rackId = {}", rackId);
|
||||
LOG_ERROR(Lib_Ngs2, "rackId = {}", rackId);
|
||||
if (!systemHandle) {
|
||||
LOG_ERROR(Lib_Ngs2, "systemHandle is nullptr");
|
||||
return ORBIS_NGS2_ERROR_INVALID_SYSTEM_HANDLE;
|
||||
|
@ -77,73 +73,45 @@ s32 PS4_SYSV_ABI sceNgs2RackCreateWithAllocator(OrbisNgs2Handle systemHandle, u3
|
|||
|
||||
s32 PS4_SYSV_ABI sceNgs2RackDestroy(OrbisNgs2Handle rackHandle,
|
||||
OrbisNgs2ContextBufferInfo* outBufferInfo) {
|
||||
if (!rackHandle) {
|
||||
LOG_ERROR(Lib_Ngs2, "rackHandle is nullptr");
|
||||
return ORBIS_NGS2_ERROR_INVALID_RACK_HANDLE;
|
||||
}
|
||||
LOG_INFO(Lib_Ngs2, "called");
|
||||
LOG_ERROR(Lib_Ngs2, "called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2RackGetInfo(OrbisNgs2Handle rackHandle, OrbisNgs2RackInfo* outInfo,
|
||||
size_t infoSize) {
|
||||
LOG_INFO(Lib_Ngs2, "infoSize = {}", infoSize);
|
||||
if (!rackHandle) {
|
||||
LOG_ERROR(Lib_Ngs2, "rackHandle is nullptr");
|
||||
return ORBIS_NGS2_ERROR_INVALID_RACK_HANDLE;
|
||||
}
|
||||
LOG_ERROR(Lib_Ngs2, "infoSize = {}", infoSize);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2RackGetUserData(OrbisNgs2Handle rackHandle, uintptr_t* outUserData) {
|
||||
if (!rackHandle) {
|
||||
LOG_ERROR(Lib_Ngs2, "rackHandle is nullptr");
|
||||
return ORBIS_NGS2_ERROR_INVALID_RACK_HANDLE;
|
||||
}
|
||||
LOG_INFO(Lib_Ngs2, "called");
|
||||
LOG_ERROR(Lib_Ngs2, "called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2RackGetVoiceHandle(OrbisNgs2Handle rackHandle, u32 voiceIndex,
|
||||
OrbisNgs2Handle* outHandle) {
|
||||
LOG_INFO(Lib_Ngs2, "voiceIndex = {}", voiceIndex);
|
||||
if (!rackHandle) {
|
||||
LOG_ERROR(Lib_Ngs2, "rackHandle is nullptr");
|
||||
return ORBIS_NGS2_ERROR_INVALID_RACK_HANDLE;
|
||||
}
|
||||
LOG_DEBUG(Lib_Ngs2, "(STUBBED) voiceIndex = {}", voiceIndex);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2RackLock(OrbisNgs2Handle rackHandle) {
|
||||
if (!rackHandle) {
|
||||
LOG_ERROR(Lib_Ngs2, "rackHandle is nullptr");
|
||||
return ORBIS_NGS2_ERROR_INVALID_RACK_HANDLE;
|
||||
}
|
||||
LOG_INFO(Lib_Ngs2, "called");
|
||||
LOG_ERROR(Lib_Ngs2, "called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2RackQueryBufferSize(u32 rackId, const OrbisNgs2RackOption* option,
|
||||
OrbisNgs2ContextBufferInfo* outBufferInfo) {
|
||||
LOG_INFO(Lib_Ngs2, "rackId = {}", rackId);
|
||||
LOG_ERROR(Lib_Ngs2, "rackId = {}", rackId);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2RackSetUserData(OrbisNgs2Handle rackHandle, uintptr_t userData) {
|
||||
LOG_INFO(Lib_Ngs2, "userData = {}", userData);
|
||||
if (!rackHandle) {
|
||||
LOG_ERROR(Lib_Ngs2, "rackHandle is nullptr");
|
||||
return ORBIS_NGS2_ERROR_INVALID_RACK_HANDLE;
|
||||
}
|
||||
LOG_ERROR(Lib_Ngs2, "userData = {}", userData);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2RackUnlock(OrbisNgs2Handle rackHandle) {
|
||||
if (!rackHandle) {
|
||||
LOG_ERROR(Lib_Ngs2, "rackHandle is nullptr");
|
||||
return ORBIS_NGS2_ERROR_INVALID_RACK_HANDLE;
|
||||
}
|
||||
LOG_INFO(Lib_Ngs2, "called");
|
||||
LOG_ERROR(Lib_Ngs2, "called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
|
@ -188,17 +156,17 @@ s32 PS4_SYSV_ABI sceNgs2SystemCreateWithAllocator(const OrbisNgs2SystemOption* o
|
|||
OrbisNgs2BufferAllocHandler hostAlloc = allocator->allocHandler;
|
||||
if (outHandle) {
|
||||
OrbisNgs2BufferFreeHandler hostFree = allocator->freeHandler;
|
||||
OrbisNgs2ContextBufferInfo* bufferInfo = 0;
|
||||
result = SystemSetup(option, bufferInfo, 0, 0);
|
||||
OrbisNgs2ContextBufferInfo bufferInfo;
|
||||
result = SystemSetup(option, &bufferInfo, 0, 0);
|
||||
if (result >= 0) {
|
||||
uintptr_t sysUserData = allocator->userData;
|
||||
result = hostAlloc(bufferInfo);
|
||||
result = Core::ExecuteGuest(hostAlloc, &bufferInfo);
|
||||
if (result >= 0) {
|
||||
OrbisNgs2Handle* handleCopy = outHandle;
|
||||
result = SystemSetup(option, bufferInfo, hostFree, handleCopy);
|
||||
result = SystemSetup(option, &bufferInfo, hostFree, handleCopy);
|
||||
if (result < 0) {
|
||||
if (hostFree) {
|
||||
hostFree(bufferInfo);
|
||||
Core::ExecuteGuest(hostFree, &bufferInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -226,13 +194,13 @@ s32 PS4_SYSV_ABI sceNgs2SystemDestroy(OrbisNgs2Handle systemHandle,
|
|||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2SystemEnumHandles(OrbisNgs2Handle* aOutHandle, u32 maxHandles) {
|
||||
LOG_INFO(Lib_Ngs2, "maxHandles = {}", maxHandles);
|
||||
LOG_ERROR(Lib_Ngs2, "maxHandles = {}", maxHandles);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2SystemEnumRackHandles(OrbisNgs2Handle systemHandle,
|
||||
OrbisNgs2Handle* aOutHandle, u32 maxHandles) {
|
||||
LOG_INFO(Lib_Ngs2, "maxHandles = {}", maxHandles);
|
||||
LOG_ERROR(Lib_Ngs2, "maxHandles = {}", maxHandles);
|
||||
if (!systemHandle) {
|
||||
LOG_ERROR(Lib_Ngs2, "systemHandle is nullptr");
|
||||
return ORBIS_NGS2_ERROR_INVALID_SYSTEM_HANDLE;
|
||||
|
@ -242,11 +210,7 @@ s32 PS4_SYSV_ABI sceNgs2SystemEnumRackHandles(OrbisNgs2Handle systemHandle,
|
|||
|
||||
s32 PS4_SYSV_ABI sceNgs2SystemGetInfo(OrbisNgs2Handle rackHandle, OrbisNgs2SystemInfo* outInfo,
|
||||
size_t infoSize) {
|
||||
LOG_INFO(Lib_Ngs2, "infoSize = {}", infoSize);
|
||||
if (!rackHandle) {
|
||||
LOG_ERROR(Lib_Ngs2, "rackHandle is nullptr");
|
||||
return ORBIS_NGS2_ERROR_INVALID_RACK_HANDLE;
|
||||
}
|
||||
LOG_ERROR(Lib_Ngs2, "infoSize = {}", infoSize);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
|
@ -255,7 +219,7 @@ s32 PS4_SYSV_ABI sceNgs2SystemGetUserData(OrbisNgs2Handle systemHandle, uintptr_
|
|||
LOG_ERROR(Lib_Ngs2, "systemHandle is nullptr");
|
||||
return ORBIS_NGS2_ERROR_INVALID_SYSTEM_HANDLE;
|
||||
}
|
||||
LOG_INFO(Lib_Ngs2, "called");
|
||||
LOG_ERROR(Lib_Ngs2, "called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
|
@ -264,7 +228,7 @@ s32 PS4_SYSV_ABI sceNgs2SystemLock(OrbisNgs2Handle systemHandle) {
|
|||
LOG_ERROR(Lib_Ngs2, "systemHandle is nullptr");
|
||||
return ORBIS_NGS2_ERROR_INVALID_SYSTEM_HANDLE;
|
||||
}
|
||||
LOG_INFO(Lib_Ngs2, "called");
|
||||
LOG_ERROR(Lib_Ngs2, "called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
|
@ -285,7 +249,7 @@ s32 PS4_SYSV_ABI sceNgs2SystemQueryBufferSize(const OrbisNgs2SystemOption* optio
|
|||
s32 PS4_SYSV_ABI sceNgs2SystemRender(OrbisNgs2Handle systemHandle,
|
||||
const OrbisNgs2RenderBufferInfo* aBufferInfo,
|
||||
u32 numBufferInfo) {
|
||||
LOG_INFO(Lib_Ngs2, "numBufferInfo = {}", numBufferInfo);
|
||||
LOG_DEBUG(Lib_Ngs2, "(STUBBED) numBufferInfo = {}", numBufferInfo);
|
||||
if (!systemHandle) {
|
||||
LOG_ERROR(Lib_Ngs2, "systemHandle is nullptr");
|
||||
return ORBIS_NGS2_ERROR_INVALID_SYSTEM_HANDLE;
|
||||
|
@ -308,7 +272,7 @@ static s32 PS4_SYSV_ABI sceNgs2SystemResetOption(OrbisNgs2SystemOption* outOptio
|
|||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2SystemSetGrainSamples(OrbisNgs2Handle systemHandle, u32 numSamples) {
|
||||
LOG_INFO(Lib_Ngs2, "numSamples = {}", numSamples);
|
||||
LOG_ERROR(Lib_Ngs2, "numSamples = {}", numSamples);
|
||||
if (!systemHandle) {
|
||||
LOG_ERROR(Lib_Ngs2, "systemHandle is nullptr");
|
||||
return ORBIS_NGS2_ERROR_INVALID_SYSTEM_HANDLE;
|
||||
|
@ -317,7 +281,7 @@ s32 PS4_SYSV_ABI sceNgs2SystemSetGrainSamples(OrbisNgs2Handle systemHandle, u32
|
|||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2SystemSetSampleRate(OrbisNgs2Handle systemHandle, u32 sampleRate) {
|
||||
LOG_INFO(Lib_Ngs2, "sampleRate = {}", sampleRate);
|
||||
LOG_ERROR(Lib_Ngs2, "sampleRate = {}", sampleRate);
|
||||
if (!systemHandle) {
|
||||
LOG_ERROR(Lib_Ngs2, "systemHandle is nullptr");
|
||||
return ORBIS_NGS2_ERROR_INVALID_SYSTEM_HANDLE;
|
||||
|
@ -326,7 +290,7 @@ s32 PS4_SYSV_ABI sceNgs2SystemSetSampleRate(OrbisNgs2Handle systemHandle, u32 sa
|
|||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2SystemSetUserData(OrbisNgs2Handle systemHandle, uintptr_t userData) {
|
||||
LOG_INFO(Lib_Ngs2, "userData = {}", userData);
|
||||
LOG_ERROR(Lib_Ngs2, "userData = {}", userData);
|
||||
if (!systemHandle) {
|
||||
LOG_ERROR(Lib_Ngs2, "systemHandle is nullptr");
|
||||
return ORBIS_NGS2_ERROR_INVALID_SYSTEM_HANDLE;
|
||||
|
@ -339,66 +303,42 @@ s32 PS4_SYSV_ABI sceNgs2SystemUnlock(OrbisNgs2Handle systemHandle) {
|
|||
LOG_ERROR(Lib_Ngs2, "systemHandle is nullptr");
|
||||
return ORBIS_NGS2_ERROR_INVALID_SYSTEM_HANDLE;
|
||||
}
|
||||
LOG_INFO(Lib_Ngs2, "called");
|
||||
LOG_ERROR(Lib_Ngs2, "called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2VoiceControl(OrbisNgs2Handle voiceHandle,
|
||||
const OrbisNgs2VoiceParamHeader* paramList) {
|
||||
if (!voiceHandle) {
|
||||
LOG_ERROR(Lib_Ngs2, "voiceHandle is nullptr");
|
||||
return ORBIS_NGS2_ERROR_INVALID_VOICE_HANDLE;
|
||||
}
|
||||
LOG_INFO(Lib_Ngs2, "called");
|
||||
LOG_ERROR(Lib_Ngs2, "called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2VoiceGetMatrixInfo(OrbisNgs2Handle voiceHandle, u32 matrixId,
|
||||
OrbisNgs2VoiceMatrixInfo* outInfo, size_t outInfoSize) {
|
||||
LOG_INFO(Lib_Ngs2, "matrixId = {}, outInfoSize = {}", matrixId, outInfoSize);
|
||||
if (!voiceHandle) {
|
||||
LOG_ERROR(Lib_Ngs2, "voiceHandle is nullptr");
|
||||
return ORBIS_NGS2_ERROR_INVALID_VOICE_HANDLE;
|
||||
}
|
||||
LOG_ERROR(Lib_Ngs2, "matrixId = {}, outInfoSize = {}", matrixId, outInfoSize);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2VoiceGetOwner(OrbisNgs2Handle voiceHandle, OrbisNgs2Handle* outRackHandle,
|
||||
u32* outVoiceId) {
|
||||
if (!voiceHandle) {
|
||||
LOG_ERROR(Lib_Ngs2, "voiceHandle is nullptr");
|
||||
return ORBIS_NGS2_ERROR_INVALID_VOICE_HANDLE;
|
||||
}
|
||||
LOG_INFO(Lib_Ngs2, "called");
|
||||
LOG_ERROR(Lib_Ngs2, "called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2VoiceGetPortInfo(OrbisNgs2Handle voiceHandle, u32 port,
|
||||
OrbisNgs2VoicePortInfo* outInfo, size_t outInfoSize) {
|
||||
LOG_INFO(Lib_Ngs2, "port = {}, outInfoSize = {}", port, outInfoSize);
|
||||
if (!voiceHandle) {
|
||||
LOG_ERROR(Lib_Ngs2, "voiceHandle is nullptr");
|
||||
return ORBIS_NGS2_ERROR_INVALID_VOICE_HANDLE;
|
||||
}
|
||||
LOG_ERROR(Lib_Ngs2, "port = {}, outInfoSize = {}", port, outInfoSize);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2VoiceGetState(OrbisNgs2Handle voiceHandle, OrbisNgs2VoiceState* outState,
|
||||
size_t stateSize) {
|
||||
LOG_INFO(Lib_Ngs2, "stateSize = {}", stateSize);
|
||||
if (!voiceHandle) {
|
||||
LOG_ERROR(Lib_Ngs2, "voiceHandle is nullptr");
|
||||
return ORBIS_NGS2_ERROR_INVALID_VOICE_HANDLE;
|
||||
}
|
||||
LOG_ERROR(Lib_Ngs2, "stateSize = {}", stateSize);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2VoiceGetStateFlags(OrbisNgs2Handle voiceHandle, u32* outStateFlags) {
|
||||
if (!voiceHandle) {
|
||||
LOG_ERROR(Lib_Ngs2, "voiceHandle is nullptr");
|
||||
return ORBIS_NGS2_ERROR_INVALID_VOICE_HANDLE;
|
||||
}
|
||||
LOG_INFO(Lib_Ngs2, "called");
|
||||
LOG_ERROR(Lib_Ngs2, "called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
|
@ -407,36 +347,32 @@ s32 PS4_SYSV_ABI sceNgs2VoiceGetStateFlags(OrbisNgs2Handle voiceHandle, u32* out
|
|||
s32 PS4_SYSV_ABI sceNgs2CustomRackGetModuleInfo(OrbisNgs2Handle rackHandle, u32 moduleIndex,
|
||||
OrbisNgs2CustomModuleInfo* outInfo,
|
||||
size_t infoSize) {
|
||||
LOG_INFO(Lib_Ngs2, "moduleIndex = {}, infoSize = {}", moduleIndex, infoSize);
|
||||
if (!rackHandle) {
|
||||
LOG_ERROR(Lib_Ngs2, "rackHandle is nullptr");
|
||||
return ORBIS_NGS2_ERROR_INVALID_RACK_HANDLE;
|
||||
}
|
||||
LOG_ERROR(Lib_Ngs2, "moduleIndex = {}, infoSize = {}", moduleIndex, infoSize);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
// Ngs2Geom
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2GeomResetListenerParam(OrbisNgs2GeomListenerParam* outListenerParam) {
|
||||
LOG_INFO(Lib_Ngs2, "called");
|
||||
LOG_ERROR(Lib_Ngs2, "called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2GeomResetSourceParam(OrbisNgs2GeomSourceParam* outSourceParam) {
|
||||
LOG_INFO(Lib_Ngs2, "called");
|
||||
LOG_ERROR(Lib_Ngs2, "called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2GeomCalcListener(const OrbisNgs2GeomListenerParam* param,
|
||||
OrbisNgs2GeomListenerWork* outWork, u32 flags) {
|
||||
LOG_INFO(Lib_Ngs2, "flags = {}", flags);
|
||||
LOG_ERROR(Lib_Ngs2, "flags = {}", flags);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2GeomApply(const OrbisNgs2GeomListenerWork* listener,
|
||||
const OrbisNgs2GeomSourceParam* source,
|
||||
OrbisNgs2GeomAttribute* outAttrib, u32 flags) {
|
||||
LOG_INFO(Lib_Ngs2, "flags = {}", flags);
|
||||
LOG_ERROR(Lib_Ngs2, "flags = {}", flags);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
|
@ -444,15 +380,15 @@ s32 PS4_SYSV_ABI sceNgs2GeomApply(const OrbisNgs2GeomListenerWork* listener,
|
|||
|
||||
s32 PS4_SYSV_ABI sceNgs2PanInit(OrbisNgs2PanWork* work, const float* aSpeakerAngle, float unitAngle,
|
||||
u32 numSpeakers) {
|
||||
LOG_INFO(Lib_Ngs2, "aSpeakerAngle = {}, unitAngle = {}, numSpeakers = {}", *aSpeakerAngle,
|
||||
unitAngle, numSpeakers);
|
||||
LOG_ERROR(Lib_Ngs2, "aSpeakerAngle = {}, unitAngle = {}, numSpeakers = {}", *aSpeakerAngle,
|
||||
unitAngle, numSpeakers);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2PanGetVolumeMatrix(OrbisNgs2PanWork* work, const OrbisNgs2PanParam* aParam,
|
||||
u32 numParams, u32 matrixFormat,
|
||||
float* outVolumeMatrix) {
|
||||
LOG_INFO(Lib_Ngs2, "numParams = {}, matrixFormat = {}", numParams, matrixFormat);
|
||||
LOG_ERROR(Lib_Ngs2, "numParams = {}, matrixFormat = {}", numParams, matrixFormat);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,8 @@ class SymbolsResolver;
|
|||
|
||||
namespace Libraries::Ngs2 {
|
||||
|
||||
typedef s32 (*OrbisNgs2ParseReadHandler)(uintptr_t userData, u32 offset, void* data, size_t size);
|
||||
using OrbisNgs2ParseReadHandler = s32 PS4_SYSV_ABI (*)(uintptr_t user_data, u32 offset, void* data,
|
||||
size_t size);
|
||||
|
||||
enum class OrbisNgs2HandleType : u32 {
|
||||
Invalid = 0,
|
||||
|
@ -90,7 +91,7 @@ struct OrbisNgs2UserFxProcessContext {
|
|||
u32 sampleRate;
|
||||
};
|
||||
|
||||
typedef s32 (*OrbisNgs2UserFxProcessHandler)(OrbisNgs2UserFxProcessContext* context);
|
||||
using OrbisNgs2UserFxProcessHandler = s32 PS4_SYSV_ABI (*)(OrbisNgs2UserFxProcessContext* context);
|
||||
|
||||
struct OrbisNgs2UserFx2SetupContext {
|
||||
void* common;
|
||||
|
@ -102,7 +103,7 @@ struct OrbisNgs2UserFx2SetupContext {
|
|||
u64 reserved[4];
|
||||
};
|
||||
|
||||
typedef s32 (*OrbisNgs2UserFx2SetupHandler)(OrbisNgs2UserFx2SetupContext* context);
|
||||
using OrbisNgs2UserFx2SetupHandler = s32 PS4_SYSV_ABI (*)(OrbisNgs2UserFx2SetupContext* context);
|
||||
|
||||
struct OrbisNgs2UserFx2CleanupContext {
|
||||
void* common;
|
||||
|
@ -114,7 +115,8 @@ struct OrbisNgs2UserFx2CleanupContext {
|
|||
u64 reserved[4];
|
||||
};
|
||||
|
||||
typedef s32 (*OrbisNgs2UserFx2CleanupHandler)(OrbisNgs2UserFx2CleanupContext* context);
|
||||
using OrbisNgs2UserFx2CleanupHandler =
|
||||
s32 PS4_SYSV_ABI (*)(OrbisNgs2UserFx2CleanupContext* context);
|
||||
|
||||
struct OrbisNgs2UserFx2ControlContext {
|
||||
const void* data;
|
||||
|
@ -125,7 +127,8 @@ struct OrbisNgs2UserFx2ControlContext {
|
|||
u64 reserved[4];
|
||||
};
|
||||
|
||||
typedef s32 (*OrbisNgs2UserFx2ControlHandler)(OrbisNgs2UserFx2ControlContext* context);
|
||||
using OrbisNgs2UserFx2ControlHandler =
|
||||
s32 PS4_SYSV_ABI (*)(OrbisNgs2UserFx2ControlContext* context);
|
||||
|
||||
struct OrbisNgs2UserFx2ProcessContext {
|
||||
float** aChannelData;
|
||||
|
@ -143,7 +146,8 @@ struct OrbisNgs2UserFx2ProcessContext {
|
|||
u64 reserved2[4];
|
||||
};
|
||||
|
||||
typedef s32 (*OrbisNgs2UserFx2ProcessHandler)(OrbisNgs2UserFx2ProcessContext* context);
|
||||
using OrbisNgs2UserFx2ProcessHandler =
|
||||
s32 PS4_SYSV_ABI (*)(OrbisNgs2UserFx2ProcessContext* context);
|
||||
|
||||
struct OrbisNgs2BufferAllocator {
|
||||
OrbisNgs2BufferAllocHandler allocHandler;
|
||||
|
@ -237,7 +241,7 @@ struct OrbisNgs2VoiceCallbackInfo {
|
|||
} param;
|
||||
};
|
||||
|
||||
typedef void (*OrbisNgs2VoiceCallbackHandler)(const OrbisNgs2VoiceCallbackInfo* info);
|
||||
using OrbisNgs2VoiceCallbackHandler = void PS4_SYSV_ABI (*)(const OrbisNgs2VoiceCallbackInfo* info);
|
||||
|
||||
struct OrbisNgs2VoiceCallbackParam {
|
||||
OrbisNgs2VoiceParamHeader header;
|
||||
|
|
|
@ -30,8 +30,9 @@ struct OrbisNgs2SystemOption {
|
|||
u32 aReserved[6];
|
||||
};
|
||||
|
||||
typedef s32 (*OrbisNgs2BufferAllocHandler)(OrbisNgs2ContextBufferInfo* ioBufferInfo);
|
||||
typedef s32 (*OrbisNgs2BufferFreeHandler)(OrbisNgs2ContextBufferInfo* ioBufferInfo);
|
||||
using OrbisNgs2BufferAllocHandler =
|
||||
s32 PS4_SYSV_ABI (*)(OrbisNgs2ContextBufferInfo* io_buffer_info);
|
||||
using OrbisNgs2BufferFreeHandler = s32 PS4_SYSV_ABI (*)(OrbisNgs2ContextBufferInfo* io_buffer_info);
|
||||
|
||||
struct OrbisNgs2SystemInfo {
|
||||
char name[ORBIS_NGS2_SYSTEM_NAME_LENGTH]; // 0
|
||||
|
|
|
@ -18,7 +18,8 @@ struct OrbisNgs2ReportDataHeader {
|
|||
s32 result;
|
||||
};
|
||||
|
||||
typedef void (*OrbisNgs2ReportHandler)(const OrbisNgs2ReportDataHeader* data, uintptr_t userData);
|
||||
using OrbisNgs2ReportHandler = void PS4_SYSV_ABI (*)(const OrbisNgs2ReportDataHeader* data,
|
||||
uintptr_t user_data);
|
||||
|
||||
struct OrbisNgs2ReportMessageData {
|
||||
OrbisNgs2ReportDataHeader header;
|
||||
|
|
45
src/core/libraries/ulobjmgr/ulobjmgr.cpp
Normal file
45
src/core/libraries/ulobjmgr/ulobjmgr.cpp
Normal file
|
@ -0,0 +1,45 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 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/kernel/posix_error.h"
|
||||
#include "core/libraries/libs.h"
|
||||
#include "core/libraries/ulobjmgr/ulobjmgr.h"
|
||||
|
||||
namespace Libraries::Ulobjmgr {
|
||||
|
||||
s32 PS4_SYSV_ABI Func_046DBA8411A2365C(u64 arg0, s32 arg1, u32* arg2) {
|
||||
if (arg0 == 0 || arg1 == 0 || arg2 == nullptr) {
|
||||
return POSIX_EINVAL;
|
||||
}
|
||||
*arg2 = 0;
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI Func_1D9F50D9CFB8054E() {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI Func_4A67FE7D435B94F7(u32 arg0) {
|
||||
if (arg0 >= 0x4000) {
|
||||
return POSIX_EINVAL;
|
||||
}
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI Func_4B07893BBB77A649(u64 arg0) {
|
||||
if (arg0 == 0) {
|
||||
return POSIX_EINVAL;
|
||||
}
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
void RegisterlibSceUlobjmgr(Core::Loader::SymbolsResolver* sym) {
|
||||
LIB_FUNCTION("BG26hBGiNlw", "ulobjmgr", 1, "ulobjmgr", 1, 1, Func_046DBA8411A2365C);
|
||||
LIB_FUNCTION("HZ9Q2c+4BU4", "ulobjmgr", 1, "ulobjmgr", 1, 1, Func_1D9F50D9CFB8054E);
|
||||
LIB_FUNCTION("Smf+fUNblPc", "ulobjmgr", 1, "ulobjmgr", 1, 1, Func_4A67FE7D435B94F7);
|
||||
LIB_FUNCTION("SweJO7t3pkk", "ulobjmgr", 1, "ulobjmgr", 1, 1, Func_4B07893BBB77A649);
|
||||
};
|
||||
|
||||
} // namespace Libraries::Ulobjmgr
|
14
src/core/libraries/ulobjmgr/ulobjmgr.h
Normal file
14
src/core/libraries/ulobjmgr/ulobjmgr.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/types.h"
|
||||
|
||||
namespace Core::Loader {
|
||||
class SymbolsResolver;
|
||||
}
|
||||
|
||||
namespace Libraries::Ulobjmgr {
|
||||
void RegisterlibSceUlobjmgr(Core::Loader::SymbolsResolver* sym);
|
||||
} // namespace Libraries::Ulobjmgr
|
|
@ -7,311 +7,455 @@
|
|||
#include "core/libraries/libs.h"
|
||||
#include "usbd.h"
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <libusb.h>
|
||||
|
||||
namespace Libraries::Usbd {
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdAllocTransfer() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
s32 libusb_to_orbis_error(int retVal) {
|
||||
if (retVal == LIBUSB_ERROR_OTHER)
|
||||
return 0x802400FF;
|
||||
if (retVal < 0) {
|
||||
LOG_ERROR(Lib_Usbd, "libusb returned: {}", libusb_error_name(retVal));
|
||||
return 0x80240000 - retVal;
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdAttachKernelDriver() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
libusb_context* g_libusb_context;
|
||||
|
||||
#if defined(_WIN32)
|
||||
bool s_has_removed_driver = false;
|
||||
#endif
|
||||
|
||||
s32 PS4_SYSV_ABI sceUsbdInit() {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_to_orbis_error(libusb_init(&g_libusb_context));
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdBulkTransfer() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
void PS4_SYSV_ABI sceUsbdExit() {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
libusb_exit(g_libusb_context);
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdCancelTransfer() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
s64 PS4_SYSV_ABI sceUsbdGetDeviceList(SceUsbdDevice*** list) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_to_orbis_error(libusb_get_device_list(g_libusb_context, list));
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdCheckConnected() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
void PS4_SYSV_ABI sceUsbdFreeDeviceList(SceUsbdDevice** list, s32 unref_devices) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
libusb_free_device_list(list, unref_devices);
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdClaimInterface() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
SceUsbdDevice* PS4_SYSV_ABI sceUsbdRefDevice(SceUsbdDevice* device) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_ref_device(device);
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdClearHalt() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
void PS4_SYSV_ABI sceUsbdUnrefDevice(SceUsbdDevice* device) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
libusb_unref_device(device);
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdClose() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
s32 PS4_SYSV_ABI sceUsbdGetConfiguration(SceUsbdDeviceHandle* dev_handle, s32* config) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_to_orbis_error(libusb_get_configuration(dev_handle, config));
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdControlTransfer() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
s32 PS4_SYSV_ABI sceUsbdGetDeviceDescriptor(SceUsbdDevice* device, SceUsbdDeviceDescriptor* desc) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_to_orbis_error(libusb_get_device_descriptor(device, desc));
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdControlTransferGetData() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
s32 PS4_SYSV_ABI sceUsbdGetActiveConfigDescriptor(SceUsbdDevice* device,
|
||||
SceUsbdConfigDescriptor** config) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_to_orbis_error(libusb_get_active_config_descriptor(device, config));
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdControlTransferGetSetup() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
s32 PS4_SYSV_ABI sceUsbdGetConfigDescriptor(SceUsbdDevice* device, u8 config_index,
|
||||
SceUsbdConfigDescriptor** config) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_to_orbis_error(libusb_get_config_descriptor(device, config_index, config));
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdDetachKernelDriver() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
s32 PS4_SYSV_ABI sceUsbdGetConfigDescriptorByValue(SceUsbdDevice* device, u8 bConfigurationValue,
|
||||
SceUsbdConfigDescriptor** config) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_to_orbis_error(
|
||||
libusb_get_config_descriptor_by_value(device, bConfigurationValue, config));
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdEventHandlerActive() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
void PS4_SYSV_ABI sceUsbdFreeConfigDescriptor(SceUsbdConfigDescriptor* config) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
libusb_free_config_descriptor(config);
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdEventHandlingOk() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
u8 PS4_SYSV_ABI sceUsbdGetBusNumber(SceUsbdDevice* device) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_get_bus_number(device);
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdExit() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
u8 PS4_SYSV_ABI sceUsbdGetDeviceAddress(SceUsbdDevice* device) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_get_device_address(device);
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdFillBulkTransfer() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
SceUsbdSpeed PS4_SYSV_ABI sceUsbdGetDeviceSpeed(SceUsbdDevice* device) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return static_cast<SceUsbdSpeed>(libusb_get_device_speed(device));
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdFillControlSetup() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
s32 PS4_SYSV_ABI sceUsbdGetMaxPacketSize(SceUsbdDevice* device, u8 endpoint) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_to_orbis_error(libusb_get_max_packet_size(device, endpoint));
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdFillControlTransfer() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
s32 PS4_SYSV_ABI sceUsbdGetMaxIsoPacketSize(SceUsbdDevice* device, u8 endpoint) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_to_orbis_error(libusb_get_max_iso_packet_size(device, endpoint));
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdFillInterruptTransfer() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
s32 PS4_SYSV_ABI sceUsbdOpen(SceUsbdDevice* device, SceUsbdDeviceHandle** dev_handle) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_to_orbis_error(libusb_open(device, dev_handle));
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdFillIsoTransfer() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
void PS4_SYSV_ABI sceUsbdClose(SceUsbdDeviceHandle* dev_handle) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
libusb_close(dev_handle);
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdFreeConfigDescriptor() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
SceUsbdDevice* PS4_SYSV_ABI sceUsbdGetDevice(SceUsbdDeviceHandle* dev_handle) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_get_device(dev_handle);
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdFreeDeviceList() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
s32 PS4_SYSV_ABI sceUsbdSetConfiguration(SceUsbdDeviceHandle* dev_handle, s32 config) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_to_orbis_error(libusb_set_configuration(dev_handle, config));
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdFreeTransfer() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
s32 PS4_SYSV_ABI sceUsbdClaimInterface(SceUsbdDeviceHandle* dev_handle, s32 interface_number) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
if (sceUsbdKernelDriverActive(dev_handle, interface_number)) {
|
||||
sceUsbdDetachKernelDriver(dev_handle, interface_number);
|
||||
}
|
||||
|
||||
return libusb_to_orbis_error(libusb_claim_interface(dev_handle, interface_number));
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdGetActiveConfigDescriptor() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
s32 PS4_SYSV_ABI sceUsbdReleaseInterface(SceUsbdDeviceHandle* dev_handle, s32 interface_number) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_to_orbis_error(libusb_release_interface(dev_handle, interface_number));
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdGetBusNumber() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
SceUsbdDeviceHandle* PS4_SYSV_ABI sceUsbdOpenDeviceWithVidPid(u16 vendor_id, u16 product_id) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_open_device_with_vid_pid(g_libusb_context, vendor_id, product_id);
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdGetConfigDescriptor() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
s32 PS4_SYSV_ABI sceUsbdSetInterfaceAltSetting(SceUsbdDeviceHandle* dev_handle,
|
||||
int interface_number, int alternate_setting) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_to_orbis_error(
|
||||
libusb_set_interface_alt_setting(dev_handle, interface_number, alternate_setting));
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdGetConfigDescriptorByValue() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
s32 PS4_SYSV_ABI sceUsbdClearHalt(SceUsbdDeviceHandle* dev_handle, uint8_t endpoint) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_to_orbis_error(libusb_clear_halt(dev_handle, endpoint));
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdGetConfiguration() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
s32 PS4_SYSV_ABI sceUsbdResetDevice(SceUsbdDeviceHandle* dev_handle) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_to_orbis_error(libusb_reset_device(dev_handle));
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdGetDescriptor() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
s32 PS4_SYSV_ABI sceUsbdKernelDriverActive(SceUsbdDeviceHandle* dev_handle, int interface_number) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
#if defined(_WIN32)
|
||||
if (!s_has_removed_driver)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
return libusb_to_orbis_error(libusb_kernel_driver_active(dev_handle, interface_number));
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdGetDevice() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
s32 PS4_SYSV_ABI sceUsbdDetachKernelDriver(SceUsbdDeviceHandle* dev_handle, int interface_number) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
#if defined(_WIN32)
|
||||
s_has_removed_driver = true;
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
return libusb_to_orbis_error(libusb_detach_kernel_driver(dev_handle, interface_number));
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdGetDeviceAddress() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
s32 PS4_SYSV_ABI sceUsbdAttachKernelDriver(SceUsbdDeviceHandle* dev_handle, int interface_number) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
#if defined(_WIN32)
|
||||
s_has_removed_driver = false;
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
return libusb_to_orbis_error(libusb_attach_kernel_driver(dev_handle, interface_number));
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdGetDeviceDescriptor() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
u8* PS4_SYSV_ABI sceUsbdControlTransferGetData(SceUsbdTransfer* transfer) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_control_transfer_get_data(transfer);
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdGetDeviceList() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
SceUsbdControlSetup* PS4_SYSV_ABI sceUsbdControlTransferGetSetup(SceUsbdTransfer* transfer) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_control_transfer_get_setup(transfer);
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdGetDeviceSpeed() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
void PS4_SYSV_ABI sceUsbdFillControlSetup(u8* buf, u8 bmRequestType, u8 bRequest, u16 wValue,
|
||||
u16 wIndex, u16 wLength) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_fill_control_setup(buf, bmRequestType, bRequest, wValue, wIndex, wLength);
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdGetIsoPacketBuffer() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
SceUsbdTransfer* PS4_SYSV_ABI sceUsbdAllocTransfer(int iso_packets) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_alloc_transfer(iso_packets);
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdGetMaxIsoPacketSize() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
s32 PS4_SYSV_ABI sceUsbdSubmitTransfer(SceUsbdTransfer* transfer) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_to_orbis_error(libusb_submit_transfer(transfer));
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdGetMaxPacketSize() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
s32 PS4_SYSV_ABI sceUsbdCancelTransfer(SceUsbdTransfer* transfer) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_to_orbis_error(libusb_cancel_transfer(transfer));
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdGetStringDescriptor() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
void PS4_SYSV_ABI sceUsbdFreeTransfer(SceUsbdTransfer* transfer) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
libusb_free_transfer(transfer);
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdGetStringDescriptorAscii() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
void PS4_SYSV_ABI sceUsbdFillControlTransfer(SceUsbdTransfer* transfer,
|
||||
SceUsbdDeviceHandle* dev_handle, u8* buffer,
|
||||
SceUsbdTransferCallback callback, void* user_data,
|
||||
u32 timeout) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
libusb_fill_control_transfer(transfer, dev_handle, buffer, callback, user_data, timeout);
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdHandleEvents() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
void PS4_SYSV_ABI sceUsbdFillBulkTransfer(SceUsbdTransfer* transfer,
|
||||
SceUsbdDeviceHandle* dev_handle, uint8_t endpoint,
|
||||
u8* buffer, s32 length, SceUsbdTransferCallback callback,
|
||||
void* user_data, u32 timeout) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
libusb_fill_bulk_transfer(transfer, dev_handle, endpoint, buffer, length, callback, user_data,
|
||||
timeout);
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdHandleEventsLocked() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
void PS4_SYSV_ABI sceUsbdFillInterruptTransfer(SceUsbdTransfer* transfer,
|
||||
SceUsbdDeviceHandle* dev_handle, uint8_t endpoint,
|
||||
u8* buffer, s32 length,
|
||||
SceUsbdTransferCallback callback, void* user_data,
|
||||
u32 timeout) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
libusb_fill_interrupt_transfer(transfer, dev_handle, endpoint, buffer, length, callback,
|
||||
user_data, timeout);
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdHandleEventsTimeout() {
|
||||
LOG_DEBUG(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
void PS4_SYSV_ABI sceUsbdFillIsoTransfer(SceUsbdTransfer* transfer, SceUsbdDeviceHandle* dev_handle,
|
||||
uint8_t endpoint, u8* buffer, s32 length,
|
||||
s32 num_iso_packets, SceUsbdTransferCallback callback,
|
||||
void* user_data, u32 timeout) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
libusb_fill_iso_transfer(transfer, dev_handle, endpoint, buffer, length, num_iso_packets,
|
||||
callback, user_data, timeout);
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdInit() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return 0x80240005; // Skip
|
||||
void PS4_SYSV_ABI sceUsbdSetIsoPacketLengths(SceUsbdTransfer* transfer, u32 length) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
libusb_set_iso_packet_lengths(transfer, length);
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdInterruptTransfer() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
u8* PS4_SYSV_ABI sceUsbdGetIsoPacketBuffer(SceUsbdTransfer* transfer, u32 packet) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_get_iso_packet_buffer(transfer, packet);
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdKernelDriverActive() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
s32 PS4_SYSV_ABI sceUsbdControlTransfer(SceUsbdDeviceHandle* dev_handle, u8 request_type,
|
||||
u8 bRequest, u16 wValue, u16 wIndex, u8* data, s32 wLength,
|
||||
u32 timeout) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_to_orbis_error(libusb_control_transfer(dev_handle, request_type, bRequest, wValue,
|
||||
wIndex, data, wLength, timeout));
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdLockEvents() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
s32 PS4_SYSV_ABI sceUsbdBulkTransfer(SceUsbdDeviceHandle* dev_handle, u8 endpoint, u8* data,
|
||||
s32 length, s32* actual_length, u32 timeout) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_to_orbis_error(
|
||||
libusb_bulk_transfer(dev_handle, endpoint, data, length, actual_length, timeout));
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdLockEventWaiters() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
s32 PS4_SYSV_ABI sceUsbdInterruptTransfer(SceUsbdDeviceHandle* dev_handle, u8 endpoint, u8* data,
|
||||
s32 length, s32* actual_length, u32 timeout) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_to_orbis_error(
|
||||
libusb_interrupt_transfer(dev_handle, endpoint, data, length, actual_length, timeout));
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdOpen() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
s32 PS4_SYSV_ABI sceUsbdGetDescriptor(SceUsbdDeviceHandle* dev_handle, u8 descType, u8 descIndex,
|
||||
u8* data, s32 length) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_to_orbis_error(
|
||||
libusb_get_descriptor(dev_handle, descType, descIndex, data, length));
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdOpenDeviceWithVidPid() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
s32 PS4_SYSV_ABI sceUsbdGetStringDescriptor(SceUsbdDeviceHandle* dev_handle, u8 desc_index,
|
||||
u16 langid, u8* data, s32 length) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_to_orbis_error(
|
||||
libusb_get_string_descriptor(dev_handle, desc_index, langid, data, length));
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdRefDevice() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
s32 PS4_SYSV_ABI sceUsbdGetStringDescriptorAscii(SceUsbdDeviceHandle* dev_handle, u8 desc_index,
|
||||
u8* data, s32 length) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_to_orbis_error(
|
||||
libusb_get_string_descriptor_ascii(dev_handle, desc_index, data, length));
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdReleaseInterface() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
s32 PS4_SYSV_ABI sceUsbdTryLockEvents() {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_try_lock_events(g_libusb_context);
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdResetDevice() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
void PS4_SYSV_ABI sceUsbdLockEvents() {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
libusb_lock_events(g_libusb_context);
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdSetConfiguration() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
void PS4_SYSV_ABI sceUsbdUnlockEvents() {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
libusb_unlock_events(g_libusb_context);
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdSetInterfaceAltSetting() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
s32 PS4_SYSV_ABI sceUsbdEventHandlingOk() {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_event_handling_ok(g_libusb_context);
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdSetIsoPacketLengths() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
s32 PS4_SYSV_ABI sceUsbdEventHandlerActive() {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_event_handler_active(g_libusb_context);
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdSubmitTransfer() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
void PS4_SYSV_ABI sceUsbdLockEventWaiters() {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
libusb_lock_event_waiters(g_libusb_context);
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdTryLockEvents() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
void PS4_SYSV_ABI sceUsbdUnlockEventWaiters() {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
libusb_unlock_event_waiters(g_libusb_context);
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdUnlockEvents() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
s32 PS4_SYSV_ABI sceUsbdWaitForEvent(timeval* tv) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_to_orbis_error(libusb_wait_for_event(g_libusb_context, tv));
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdUnlockEventWaiters() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
s32 PS4_SYSV_ABI sceUsbdHandleEventsTimeout(timeval* tv) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_to_orbis_error(libusb_handle_events_timeout(g_libusb_context, tv));
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdUnrefDevice() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
s32 PS4_SYSV_ABI sceUsbdHandleEvents() {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_to_orbis_error(libusb_handle_events(g_libusb_context));
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdWaitForEvent() {
|
||||
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
s32 PS4_SYSV_ABI sceUsbdHandleEventsLocked(timeval* tv) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
return libusb_to_orbis_error(libusb_handle_events_locked(g_libusb_context, tv));
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceUsbdCheckConnected(SceUsbdDeviceHandle* dev_handle) {
|
||||
LOG_DEBUG(Lib_Usbd, "called");
|
||||
|
||||
// There's no libusb version of this function.
|
||||
// Simulate by querying data.
|
||||
|
||||
int config;
|
||||
int r = libusb_get_configuration(dev_handle, &config);
|
||||
|
||||
return libusb_to_orbis_error(r);
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI Func_65F6EF33E38FFF50() {
|
||||
|
@ -406,4 +550,4 @@ void RegisterlibSceUsbd(Core::Loader::SymbolsResolver* sym) {
|
|||
LIB_FUNCTION("1WtDBgcgseA", "libSceUsbd", 1, "libSceUsbd", 1, 1, Func_D56B43060720B1E0);
|
||||
};
|
||||
|
||||
} // namespace Libraries::Usbd
|
||||
} // namespace Libraries::Usbd
|
|
@ -1,76 +1,150 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX - FileCopyrightText : Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/types.h"
|
||||
|
||||
extern "C" {
|
||||
struct libusb_device;
|
||||
struct libusb_device_handle;
|
||||
struct libusb_device_descriptor;
|
||||
struct libusb_config_descriptor;
|
||||
struct libusb_transfer;
|
||||
struct libusb_control_setup;
|
||||
struct timeval;
|
||||
}
|
||||
|
||||
namespace Core::Loader {
|
||||
class SymbolsResolver;
|
||||
}
|
||||
|
||||
namespace Libraries::Usbd {
|
||||
|
||||
int PS4_SYSV_ABI sceUsbdAllocTransfer();
|
||||
int PS4_SYSV_ABI sceUsbdAttachKernelDriver();
|
||||
int PS4_SYSV_ABI sceUsbdBulkTransfer();
|
||||
int PS4_SYSV_ABI sceUsbdCancelTransfer();
|
||||
int PS4_SYSV_ABI sceUsbdCheckConnected();
|
||||
int PS4_SYSV_ABI sceUsbdClaimInterface();
|
||||
int PS4_SYSV_ABI sceUsbdClearHalt();
|
||||
int PS4_SYSV_ABI sceUsbdClose();
|
||||
int PS4_SYSV_ABI sceUsbdControlTransfer();
|
||||
int PS4_SYSV_ABI sceUsbdControlTransferGetData();
|
||||
int PS4_SYSV_ABI sceUsbdControlTransferGetSetup();
|
||||
int PS4_SYSV_ABI sceUsbdDetachKernelDriver();
|
||||
int PS4_SYSV_ABI sceUsbdEventHandlerActive();
|
||||
int PS4_SYSV_ABI sceUsbdEventHandlingOk();
|
||||
int PS4_SYSV_ABI sceUsbdExit();
|
||||
int PS4_SYSV_ABI sceUsbdFillBulkTransfer();
|
||||
int PS4_SYSV_ABI sceUsbdFillControlSetup();
|
||||
int PS4_SYSV_ABI sceUsbdFillControlTransfer();
|
||||
int PS4_SYSV_ABI sceUsbdFillInterruptTransfer();
|
||||
int PS4_SYSV_ABI sceUsbdFillIsoTransfer();
|
||||
int PS4_SYSV_ABI sceUsbdFreeConfigDescriptor();
|
||||
int PS4_SYSV_ABI sceUsbdFreeDeviceList();
|
||||
int PS4_SYSV_ABI sceUsbdFreeTransfer();
|
||||
int PS4_SYSV_ABI sceUsbdGetActiveConfigDescriptor();
|
||||
int PS4_SYSV_ABI sceUsbdGetBusNumber();
|
||||
int PS4_SYSV_ABI sceUsbdGetConfigDescriptor();
|
||||
int PS4_SYSV_ABI sceUsbdGetConfigDescriptorByValue();
|
||||
int PS4_SYSV_ABI sceUsbdGetConfiguration();
|
||||
int PS4_SYSV_ABI sceUsbdGetDescriptor();
|
||||
int PS4_SYSV_ABI sceUsbdGetDevice();
|
||||
int PS4_SYSV_ABI sceUsbdGetDeviceAddress();
|
||||
int PS4_SYSV_ABI sceUsbdGetDeviceDescriptor();
|
||||
int PS4_SYSV_ABI sceUsbdGetDeviceList();
|
||||
int PS4_SYSV_ABI sceUsbdGetDeviceSpeed();
|
||||
int PS4_SYSV_ABI sceUsbdGetIsoPacketBuffer();
|
||||
int PS4_SYSV_ABI sceUsbdGetMaxIsoPacketSize();
|
||||
int PS4_SYSV_ABI sceUsbdGetMaxPacketSize();
|
||||
int PS4_SYSV_ABI sceUsbdGetStringDescriptor();
|
||||
int PS4_SYSV_ABI sceUsbdGetStringDescriptorAscii();
|
||||
int PS4_SYSV_ABI sceUsbdHandleEvents();
|
||||
int PS4_SYSV_ABI sceUsbdHandleEventsLocked();
|
||||
int PS4_SYSV_ABI sceUsbdHandleEventsTimeout();
|
||||
int PS4_SYSV_ABI sceUsbdInit();
|
||||
int PS4_SYSV_ABI sceUsbdInterruptTransfer();
|
||||
int PS4_SYSV_ABI sceUsbdKernelDriverActive();
|
||||
int PS4_SYSV_ABI sceUsbdLockEvents();
|
||||
int PS4_SYSV_ABI sceUsbdLockEventWaiters();
|
||||
int PS4_SYSV_ABI sceUsbdOpen();
|
||||
int PS4_SYSV_ABI sceUsbdOpenDeviceWithVidPid();
|
||||
int PS4_SYSV_ABI sceUsbdRefDevice();
|
||||
int PS4_SYSV_ABI sceUsbdReleaseInterface();
|
||||
int PS4_SYSV_ABI sceUsbdResetDevice();
|
||||
int PS4_SYSV_ABI sceUsbdSetConfiguration();
|
||||
int PS4_SYSV_ABI sceUsbdSetInterfaceAltSetting();
|
||||
int PS4_SYSV_ABI sceUsbdSetIsoPacketLengths();
|
||||
int PS4_SYSV_ABI sceUsbdSubmitTransfer();
|
||||
int PS4_SYSV_ABI sceUsbdTryLockEvents();
|
||||
int PS4_SYSV_ABI sceUsbdUnlockEvents();
|
||||
int PS4_SYSV_ABI sceUsbdUnlockEventWaiters();
|
||||
int PS4_SYSV_ABI sceUsbdUnrefDevice();
|
||||
int PS4_SYSV_ABI sceUsbdWaitForEvent();
|
||||
using SceUsbdDevice = libusb_device;
|
||||
using SceUsbdDeviceHandle = libusb_device_handle;
|
||||
using SceUsbdDeviceDescriptor = libusb_device_descriptor;
|
||||
using SceUsbdConfigDescriptor = libusb_config_descriptor;
|
||||
using SceUsbdTransfer = libusb_transfer;
|
||||
using SceUsbdControlSetup = libusb_control_setup;
|
||||
using SceUsbdTransferCallback = void (*)(SceUsbdTransfer* transfer);
|
||||
|
||||
enum class SceUsbdSpeed : u32 {
|
||||
UNKNOWN = 0,
|
||||
LOW = 1,
|
||||
FULL = 2,
|
||||
HIGH = 3,
|
||||
SUPER = 4,
|
||||
SUPER_PLUS = 5
|
||||
};
|
||||
|
||||
s32 PS4_SYSV_ABI sceUsbdInit();
|
||||
void PS4_SYSV_ABI sceUsbdExit();
|
||||
|
||||
s64 PS4_SYSV_ABI sceUsbdGetDeviceList(SceUsbdDevice*** list);
|
||||
void PS4_SYSV_ABI sceUsbdFreeDeviceList(SceUsbdDevice** list, s32 unref_devices);
|
||||
|
||||
SceUsbdDevice* PS4_SYSV_ABI sceUsbdRefDevice(SceUsbdDevice* device);
|
||||
void PS4_SYSV_ABI sceUsbdUnrefDevice(SceUsbdDevice* device);
|
||||
|
||||
s32 PS4_SYSV_ABI sceUsbdGetConfiguration(SceUsbdDeviceHandle* dev_handle, s32* config);
|
||||
s32 PS4_SYSV_ABI sceUsbdGetDeviceDescriptor(SceUsbdDevice* device, SceUsbdDeviceDescriptor* desc);
|
||||
s32 PS4_SYSV_ABI sceUsbdGetActiveConfigDescriptor(SceUsbdDevice* device,
|
||||
SceUsbdConfigDescriptor** config);
|
||||
s32 PS4_SYSV_ABI sceUsbdGetConfigDescriptor(SceUsbdDevice* device, u8 config_index,
|
||||
SceUsbdConfigDescriptor** config);
|
||||
s32 PS4_SYSV_ABI sceUsbdGetConfigDescriptorByValue(SceUsbdDevice* device, u8 bConfigurationValue,
|
||||
SceUsbdConfigDescriptor** config);
|
||||
void PS4_SYSV_ABI sceUsbdFreeConfigDescriptor(SceUsbdConfigDescriptor* config);
|
||||
|
||||
u8 PS4_SYSV_ABI sceUsbdGetBusNumber(SceUsbdDevice* device);
|
||||
u8 PS4_SYSV_ABI sceUsbdGetDeviceAddress(SceUsbdDevice* device);
|
||||
|
||||
SceUsbdSpeed PS4_SYSV_ABI sceUsbdGetDeviceSpeed(SceUsbdDevice* device);
|
||||
s32 PS4_SYSV_ABI sceUsbdGetMaxPacketSize(SceUsbdDevice* device, u8 endpoint);
|
||||
s32 PS4_SYSV_ABI sceUsbdGetMaxIsoPacketSize(SceUsbdDevice* device, u8 endpoint);
|
||||
|
||||
s32 PS4_SYSV_ABI sceUsbdOpen(SceUsbdDevice* device, SceUsbdDeviceHandle** dev_handle);
|
||||
void PS4_SYSV_ABI sceUsbdClose(SceUsbdDeviceHandle* dev_handle);
|
||||
SceUsbdDevice* PS4_SYSV_ABI sceUsbdGetDevice(SceUsbdDeviceHandle* dev_handle);
|
||||
|
||||
s32 PS4_SYSV_ABI sceUsbdSetConfiguration(SceUsbdDeviceHandle* dev_handle, s32 config);
|
||||
s32 PS4_SYSV_ABI sceUsbdClaimInterface(SceUsbdDeviceHandle* dev_handle, s32 interface_number);
|
||||
s32 PS4_SYSV_ABI sceUsbdReleaseInterface(SceUsbdDeviceHandle* dev_handle, s32 interface_number);
|
||||
|
||||
SceUsbdDeviceHandle* PS4_SYSV_ABI sceUsbdOpenDeviceWithVidPid(u16 vendor_id, u16 product_id);
|
||||
|
||||
s32 PS4_SYSV_ABI sceUsbdSetInterfaceAltSetting(SceUsbdDeviceHandle* dev_handle,
|
||||
int interface_number, int alternate_setting);
|
||||
s32 PS4_SYSV_ABI sceUsbdClearHalt(SceUsbdDeviceHandle* dev_handle, u8 endpoint);
|
||||
s32 PS4_SYSV_ABI sceUsbdResetDevice(SceUsbdDeviceHandle* dev_handle);
|
||||
|
||||
s32 PS4_SYSV_ABI sceUsbdKernelDriverActive(SceUsbdDeviceHandle* dev_handle, int interface_number);
|
||||
s32 PS4_SYSV_ABI sceUsbdDetachKernelDriver(SceUsbdDeviceHandle* dev_handle, int interface_number);
|
||||
s32 PS4_SYSV_ABI sceUsbdAttachKernelDriver(SceUsbdDeviceHandle* dev_handle, int interface_number);
|
||||
|
||||
u8* PS4_SYSV_ABI sceUsbdControlTransferGetData(SceUsbdTransfer* transfer);
|
||||
SceUsbdControlSetup* PS4_SYSV_ABI sceUsbdControlTransferGetSetup(SceUsbdTransfer* transfer);
|
||||
|
||||
void PS4_SYSV_ABI sceUsbdFillControlSetup(u8* buf, u8 bmRequestType, u8 bRequest, u16 wValue,
|
||||
u16 wIndex, u16 wLength);
|
||||
|
||||
SceUsbdTransfer* PS4_SYSV_ABI sceUsbdAllocTransfer(int iso_packets);
|
||||
s32 PS4_SYSV_ABI sceUsbdSubmitTransfer(SceUsbdTransfer* transfer);
|
||||
s32 PS4_SYSV_ABI sceUsbdCancelTransfer(SceUsbdTransfer* transfer);
|
||||
void PS4_SYSV_ABI sceUsbdFreeTransfer(SceUsbdTransfer* transfer);
|
||||
|
||||
void PS4_SYSV_ABI sceUsbdFillControlTransfer(SceUsbdTransfer* transfer,
|
||||
SceUsbdDeviceHandle* dev_handle, u8* buffer,
|
||||
SceUsbdTransferCallback callback, void* user_data,
|
||||
u32 timeout);
|
||||
void PS4_SYSV_ABI sceUsbdFillBulkTransfer(SceUsbdTransfer* transfer,
|
||||
SceUsbdDeviceHandle* dev_handle, u8 endpoint, u8* buffer,
|
||||
s32 length, SceUsbdTransferCallback callback,
|
||||
void* user_data, u32 timeout);
|
||||
void PS4_SYSV_ABI sceUsbdFillInterruptTransfer(SceUsbdTransfer* transfer,
|
||||
SceUsbdDeviceHandle* dev_handle, u8 endpoint,
|
||||
u8* buffer, s32 length,
|
||||
SceUsbdTransferCallback callback, void* user_data,
|
||||
u32 timeout);
|
||||
void PS4_SYSV_ABI sceUsbdFillIsoTransfer(SceUsbdTransfer* transfer, SceUsbdDeviceHandle* dev_handle,
|
||||
u8 endpoint, u8* buffer, s32 length, s32 num_iso_packets,
|
||||
SceUsbdTransferCallback callback, void* userData,
|
||||
u32 timeout);
|
||||
|
||||
void PS4_SYSV_ABI sceUsbdSetIsoPacketLengths(SceUsbdTransfer* transfer, u32 length);
|
||||
u8* PS4_SYSV_ABI sceUsbdGetIsoPacketBuffer(SceUsbdTransfer* transfer, u32 packet);
|
||||
|
||||
s32 PS4_SYSV_ABI sceUsbdControlTransfer(SceUsbdDeviceHandle* dev_handle, u8 request_type,
|
||||
u8 bRequest, u16 wValue, u16 wIndex, u8* data, s32 wLength,
|
||||
u32 timeout);
|
||||
s32 PS4_SYSV_ABI sceUsbdBulkTransfer(SceUsbdDeviceHandle* dev_handle, u8 endpoint, u8* data,
|
||||
s32 length, s32* actual_length, u32 timeout);
|
||||
s32 PS4_SYSV_ABI sceUsbdInterruptTransfer(SceUsbdDeviceHandle* dev_handle, u8 endpoint, u8* data,
|
||||
s32 length, s32* actual_length, u32 timeout);
|
||||
|
||||
s32 PS4_SYSV_ABI sceUsbdGetDescriptor(SceUsbdDeviceHandle* dev_handle, u8 descType, u8 descIndex,
|
||||
u8* data, s32 length);
|
||||
s32 PS4_SYSV_ABI sceUsbdGetStringDescriptor(SceUsbdDeviceHandle* dev_handle, u8 desc_index,
|
||||
u16 langid, u8* data, s32 length);
|
||||
s32 PS4_SYSV_ABI sceUsbdGetStringDescriptorAscii(SceUsbdDeviceHandle* dev_handle, u8 desc_index,
|
||||
u8* data, s32 length);
|
||||
|
||||
s32 PS4_SYSV_ABI sceUsbdTryLockEvents();
|
||||
void PS4_SYSV_ABI sceUsbdLockEvents();
|
||||
void PS4_SYSV_ABI sceUsbdUnlockEvents();
|
||||
s32 PS4_SYSV_ABI sceUsbdEventHandlingOk();
|
||||
s32 PS4_SYSV_ABI sceUsbdEventHandlerActive();
|
||||
void PS4_SYSV_ABI sceUsbdLockEventWaiters();
|
||||
void PS4_SYSV_ABI sceUsbdUnlockEventWaiters();
|
||||
s32 PS4_SYSV_ABI sceUsbdWaitForEvent(timeval* tv);
|
||||
|
||||
s32 PS4_SYSV_ABI sceUsbdHandleEventsTimeout(timeval* tv);
|
||||
s32 PS4_SYSV_ABI sceUsbdHandleEvents();
|
||||
s32 PS4_SYSV_ABI sceUsbdHandleEventsLocked(timeval* tv);
|
||||
|
||||
s32 PS4_SYSV_ABI sceUsbdCheckConnected(SceUsbdDeviceHandle* dev_handle);
|
||||
|
||||
int PS4_SYSV_ABI Func_65F6EF33E38FFF50();
|
||||
int PS4_SYSV_ABI Func_97F056BAD90AADE7();
|
||||
int PS4_SYSV_ABI Func_C55104A33B35B264();
|
||||
|
|
|
@ -101,6 +101,17 @@ void Linker::Execute(const std::vector<std::string> args) {
|
|||
|
||||
memory->SetupMemoryRegions(fmem_size, use_extended_mem1, use_extended_mem2);
|
||||
|
||||
// Simulate sceKernelInternalMemory mapping, a mapping usually performed during libkernel init.
|
||||
// Due to the large size of this mapping, failing to emulate it causes issues in some titles.
|
||||
// This mapping belongs in the system reserved area, which starts at address 0x880000000.
|
||||
static constexpr VAddr KernelAllocBase = 0x880000000ULL;
|
||||
static constexpr s64 InternalMemorySize = 0x1000000;
|
||||
void* addr_out{reinterpret_cast<void*>(KernelAllocBase)};
|
||||
|
||||
const s32 ret = Libraries::Kernel::sceKernelMapNamedFlexibleMemory(
|
||||
&addr_out, InternalMemorySize, 3, 0, "SceKernelInternalMemory");
|
||||
ASSERT_MSG(ret == 0, "Unable to perform sceKernelInternalMemory mapping");
|
||||
|
||||
main_thread.Run([this, module, args](std::stop_token) {
|
||||
Common::SetCurrentThreadName("GAME_MainThread");
|
||||
LoadSharedLibraries();
|
||||
|
@ -372,7 +383,8 @@ void* Linker::AllocateTlsForThread(bool is_primary) {
|
|||
|
||||
// If sceKernelMapNamedFlexibleMemory is being called from libkernel and addr = 0
|
||||
// it automatically places mappings in system reserved area instead of managed.
|
||||
static constexpr VAddr KernelAllocBase = 0x880000000ULL;
|
||||
// Since the system reserved area already has a mapping in it, this address is slightly higher.
|
||||
static constexpr VAddr KernelAllocBase = 0x881000000ULL;
|
||||
|
||||
// The kernel module has a few different paths for TLS allocation.
|
||||
// For SDK < 1.7 it allocates both main and secondary thread blocks using libc mspace/malloc.
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#include "common/arch.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/types.h"
|
||||
#include "core/cpu_patches.h"
|
||||
#include "core/libraries/kernel/threads/pthread.h"
|
||||
#include "core/tls.h"
|
||||
|
||||
|
@ -197,12 +196,7 @@ Tcb* GetTcbBase() {
|
|||
thread_local std::once_flag init_tls_flag;
|
||||
|
||||
void EnsureThreadInitialized() {
|
||||
std::call_once(init_tls_flag, [] {
|
||||
#ifdef ARCH_X86_64
|
||||
InitializeThreadPatchStack();
|
||||
#endif
|
||||
SetTcbBase(Libraries::Kernel::g_curthread->tcb);
|
||||
});
|
||||
std::call_once(init_tls_flag, [] { SetTcbBase(Libraries::Kernel::g_curthread->tcb); });
|
||||
}
|
||||
|
||||
} // namespace Core
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include "common/polyfill_thread.h"
|
||||
#include "common/scm_rev.h"
|
||||
#include "common/singleton.h"
|
||||
#include "common/version.h"
|
||||
#include "core/file_format/psf.h"
|
||||
#include "core/file_format/trp.h"
|
||||
#include "core/file_sys/fs.h"
|
||||
|
@ -123,7 +122,7 @@ void Emulator::Run(const std::filesystem::path& file, const std::vector<std::str
|
|||
Common::Log::Initialize(id + ".log");
|
||||
Common::Log::Start();
|
||||
}
|
||||
LOG_INFO(Loader, "Starting shadps4 emulator v{} ", Common::VERSION);
|
||||
LOG_INFO(Loader, "Starting shadps4 emulator v{} ", Common::g_version);
|
||||
LOG_INFO(Loader, "Revision {}", Common::g_scm_rev);
|
||||
LOG_INFO(Loader, "Branch {}", Common::g_scm_branch);
|
||||
LOG_INFO(Loader, "Description {}", Common::g_scm_desc);
|
||||
|
@ -197,8 +196,8 @@ void Emulator::Run(const std::filesystem::path& file, const std::vector<std::str
|
|||
|
||||
std::string game_title = fmt::format("{} - {} <{}>", id, title, app_version);
|
||||
std::string window_title = "";
|
||||
if (Common::isRelease) {
|
||||
window_title = fmt::format("shadPS4 v{} | {}", Common::VERSION, game_title);
|
||||
if (Common::g_is_release) {
|
||||
window_title = fmt::format("shadPS4 v{} | {}", Common::g_version, game_title);
|
||||
} else {
|
||||
std::string remote_url(Common::g_scm_remote_url);
|
||||
std::string remote_host;
|
||||
|
@ -208,10 +207,10 @@ void Emulator::Run(const std::filesystem::path& file, const std::vector<std::str
|
|||
remote_host = "unknown";
|
||||
}
|
||||
if (remote_host == "shadps4-emu" || remote_url.length() == 0) {
|
||||
window_title = fmt::format("shadPS4 v{} {} {} | {}", Common::VERSION,
|
||||
window_title = fmt::format("shadPS4 v{} {} {} | {}", Common::g_version,
|
||||
Common::g_scm_branch, Common::g_scm_desc, game_title);
|
||||
} else {
|
||||
window_title = fmt::format("shadPS4 v{} {}/{} {} | {}", Common::VERSION, remote_host,
|
||||
window_title = fmt::format("shadPS4 v{} {}/{} {} | {}", Common::g_version, remote_host,
|
||||
Common::g_scm_branch, Common::g_scm_desc, game_title);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include "common/elf_info.h"
|
||||
#include "common/io_file.h"
|
||||
#include "common/path_util.h"
|
||||
#include "common/version.h"
|
||||
#include "input/controller.h"
|
||||
#include "input/input_mouse.h"
|
||||
|
||||
|
@ -551,18 +550,18 @@ void ControllerOutput::FinalizeUpdate() {
|
|||
break;
|
||||
case Axis::TriggerLeft:
|
||||
ApplyDeadzone(new_param, lefttrigger_deadzone);
|
||||
controller->Axis(0, c_axis, GetAxis(0x0, 0x80, *new_param));
|
||||
controller->Axis(0, c_axis, GetAxis(0x0, 0x7f, *new_param));
|
||||
controller->CheckButton(0, OrbisPadButtonDataOffset::L2, *new_param > 0x20);
|
||||
return;
|
||||
case Axis::TriggerRight:
|
||||
ApplyDeadzone(new_param, righttrigger_deadzone);
|
||||
controller->Axis(0, c_axis, GetAxis(0x0, 0x80, *new_param));
|
||||
controller->Axis(0, c_axis, GetAxis(0x0, 0x7f, *new_param));
|
||||
controller->CheckButton(0, OrbisPadButtonDataOffset::R2, *new_param > 0x20);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
controller->Axis(0, c_axis, GetAxis(-0x80, 0x80, *new_param * multiplier));
|
||||
controller->Axis(0, c_axis, GetAxis(-0x80, 0x7f, *new_param * multiplier));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -61,11 +61,11 @@ Uint32 MousePolling(void* param, Uint32 id, Uint32 interval) {
|
|||
float a_x = cos(angle) * output_speed, a_y = sin(angle) * output_speed;
|
||||
|
||||
if (d_x != 0 && d_y != 0) {
|
||||
controller->Axis(0, axis_x, GetAxis(-0x80, 0x80, a_x));
|
||||
controller->Axis(0, axis_y, GetAxis(-0x80, 0x80, a_y));
|
||||
controller->Axis(0, axis_x, GetAxis(-0x80, 0x7f, a_x));
|
||||
controller->Axis(0, axis_y, GetAxis(-0x80, 0x7f, a_y));
|
||||
} else {
|
||||
controller->Axis(0, axis_x, GetAxis(-0x80, 0x80, 0));
|
||||
controller->Axis(0, axis_y, GetAxis(-0x80, 0x80, 0));
|
||||
controller->Axis(0, axis_x, GetAxis(-0x80, 0x7f, 0));
|
||||
controller->Axis(0, axis_y, GetAxis(-0x80, 0x7f, 0));
|
||||
}
|
||||
|
||||
return interval;
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include <common/config.h>
|
||||
#include <common/path_util.h>
|
||||
#include <common/scm_rev.h>
|
||||
#include <common/version.h>
|
||||
#include "check_update.h"
|
||||
|
||||
using namespace Common::FS;
|
||||
|
@ -52,7 +51,7 @@ void CheckUpdate::CheckForUpdates(const bool showMessage) {
|
|||
url = QUrl("https://api.github.com/repos/shadps4-emu/shadPS4/releases/latest");
|
||||
checkName = false;
|
||||
} else {
|
||||
if (Common::isRelease) {
|
||||
if (Common::g_is_release) {
|
||||
Config::setUpdateChannel("Release");
|
||||
} else {
|
||||
Config::setUpdateChannel("Nightly");
|
||||
|
@ -162,7 +161,7 @@ tr("The Auto Updater allows up to 60 update checks per hour.\\nYou have reached
|
|||
|
||||
QString currentRev = (updateChannel == "Nightly")
|
||||
? QString::fromStdString(Common::g_scm_rev)
|
||||
: "v." + QString::fromStdString(Common::VERSION);
|
||||
: "v." + QString::fromStdString(Common::g_version);
|
||||
QString currentDate = Common::g_scm_date;
|
||||
|
||||
QDateTime dateTime = QDateTime::fromString(latestDate, Qt::ISODate);
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
#include "cheats_patches.h"
|
||||
#include "common/config.h"
|
||||
#include "common/path_util.h"
|
||||
#include "common/version.h"
|
||||
#include "common/scm_rev.h"
|
||||
#include "compatibility_info.h"
|
||||
#include "game_info.h"
|
||||
#include "trophy_viewer.h"
|
||||
|
@ -115,14 +115,15 @@ public:
|
|||
|
||||
compatibilityMenu->addAction(updateCompatibility);
|
||||
compatibilityMenu->addAction(viewCompatibilityReport);
|
||||
if (Common::isRelease) {
|
||||
if (Common::g_is_release) {
|
||||
compatibilityMenu->addAction(submitCompatibilityReport);
|
||||
}
|
||||
|
||||
menu.addMenu(compatibilityMenu);
|
||||
|
||||
compatibilityMenu->setEnabled(Config::getCompatibilityEnabled());
|
||||
viewCompatibilityReport->setEnabled(!m_games[itemID].compatibility.url.isEmpty());
|
||||
viewCompatibilityReport->setEnabled(m_games[itemID].compatibility.status !=
|
||||
CompatibilityStatus::Unknown);
|
||||
|
||||
// Show menu.
|
||||
auto selected = menu.exec(global_pos);
|
||||
|
@ -140,12 +141,12 @@ public:
|
|||
QString open_update_path;
|
||||
Common::FS::PathToQString(open_update_path, m_games[itemID].path);
|
||||
open_update_path += "-UPDATE";
|
||||
if (!std::filesystem::exists(Common::FS::PathFromQString(open_update_path))) {
|
||||
if (std::filesystem::exists(Common::FS::PathFromQString(open_update_path))) {
|
||||
QDesktopServices::openUrl(QUrl::fromLocalFile(open_update_path));
|
||||
} else {
|
||||
Common::FS::PathToQString(open_update_path, m_games[itemID].path);
|
||||
open_update_path += "-patch";
|
||||
if (!std::filesystem::exists(Common::FS::PathFromQString(open_update_path))) {
|
||||
if (std::filesystem::exists(Common::FS::PathFromQString(open_update_path))) {
|
||||
QDesktopServices::openUrl(QUrl::fromLocalFile(open_update_path));
|
||||
} else {
|
||||
QMessageBox::critical(nullptr, tr("Error"),
|
||||
|
@ -557,24 +558,36 @@ public:
|
|||
}
|
||||
|
||||
if (selected == viewCompatibilityReport) {
|
||||
if (!m_games[itemID].compatibility.url.isEmpty())
|
||||
QDesktopServices::openUrl(QUrl(m_games[itemID].compatibility.url));
|
||||
if (m_games[itemID].compatibility.issue_number != "") {
|
||||
auto url_issues =
|
||||
"https://github.com/shadps4-emu/shadps4-game-compatibility/issues/";
|
||||
QDesktopServices::openUrl(
|
||||
QUrl(url_issues + m_games[itemID].compatibility.issue_number));
|
||||
}
|
||||
}
|
||||
|
||||
if (selected == submitCompatibilityReport) {
|
||||
QUrl url = QUrl("https://github.com/shadps4-emu/shadps4-game-compatibility/issues/new");
|
||||
QUrlQuery query;
|
||||
query.addQueryItem("template", QString("game_compatibility.yml"));
|
||||
query.addQueryItem(
|
||||
"title", QString("%1 - %2").arg(QString::fromStdString(m_games[itemID].serial),
|
||||
QString::fromStdString(m_games[itemID].name)));
|
||||
query.addQueryItem("game-name", QString::fromStdString(m_games[itemID].name));
|
||||
query.addQueryItem("game-serial", QString::fromStdString(m_games[itemID].serial));
|
||||
query.addQueryItem("game-version", QString::fromStdString(m_games[itemID].version));
|
||||
query.addQueryItem("emulator-version", QString(Common::VERSION));
|
||||
url.setQuery(query);
|
||||
if (m_games[itemID].compatibility.issue_number == "") {
|
||||
QUrl url =
|
||||
QUrl("https://github.com/shadps4-emu/shadps4-game-compatibility/issues/new");
|
||||
QUrlQuery query;
|
||||
query.addQueryItem("template", QString("game_compatibility.yml"));
|
||||
query.addQueryItem(
|
||||
"title", QString("%1 - %2").arg(QString::fromStdString(m_games[itemID].serial),
|
||||
QString::fromStdString(m_games[itemID].name)));
|
||||
query.addQueryItem("game-name", QString::fromStdString(m_games[itemID].name));
|
||||
query.addQueryItem("game-serial", QString::fromStdString(m_games[itemID].serial));
|
||||
query.addQueryItem("game-version", QString::fromStdString(m_games[itemID].version));
|
||||
query.addQueryItem("emulator-version", QString(Common::g_version));
|
||||
url.setQuery(query);
|
||||
|
||||
QDesktopServices::openUrl(url);
|
||||
QDesktopServices::openUrl(url);
|
||||
} else {
|
||||
auto url_issues =
|
||||
"https://github.com/shadps4-emu/shadps4-game-compatibility/issues/";
|
||||
QDesktopServices::openUrl(
|
||||
QUrl(url_issues + m_games[itemID].compatibility.issue_number));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#include "common/path_util.h"
|
||||
#include "common/scm_rev.h"
|
||||
#include "common/string_util.h"
|
||||
#include "common/version.h"
|
||||
#include "control_settings.h"
|
||||
#include "game_install_dialog.h"
|
||||
#include "kbm_gui.h"
|
||||
|
@ -45,11 +44,11 @@ MainWindow::~MainWindow() {
|
|||
bool MainWindow::Init() {
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
// setup ui
|
||||
LoadTranslation();
|
||||
AddUiWidgets();
|
||||
CreateActions();
|
||||
CreateRecentGameActions();
|
||||
ConfigureGuiFromSettings();
|
||||
LoadTranslation();
|
||||
CreateDockWindows();
|
||||
CreateConnects();
|
||||
SetLastUsedTheme();
|
||||
|
@ -58,8 +57,8 @@ bool MainWindow::Init() {
|
|||
// show ui
|
||||
setMinimumSize(720, 405);
|
||||
std::string window_title = "";
|
||||
if (Common::isRelease) {
|
||||
window_title = fmt::format("shadPS4 v{}", Common::VERSION);
|
||||
if (Common::g_is_release) {
|
||||
window_title = fmt::format("shadPS4 v{}", Common::g_version);
|
||||
} else {
|
||||
std::string remote_url(Common::g_scm_remote_url);
|
||||
std::string remote_host;
|
||||
|
@ -69,10 +68,10 @@ bool MainWindow::Init() {
|
|||
remote_host = "unknown";
|
||||
}
|
||||
if (remote_host == "shadps4-emu" || remote_url.length() == 0) {
|
||||
window_title = fmt::format("shadPS4 v{} {} {}", Common::VERSION, Common::g_scm_branch,
|
||||
window_title = fmt::format("shadPS4 v{} {} {}", Common::g_version, Common::g_scm_branch,
|
||||
Common::g_scm_desc);
|
||||
} else {
|
||||
window_title = fmt::format("shadPS4 v{} {}/{} {}", Common::VERSION, remote_host,
|
||||
window_title = fmt::format("shadPS4 v{} {}/{} {}", Common::g_version, remote_host,
|
||||
Common::g_scm_branch, Common::g_scm_desc);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include <fmt/format.h>
|
||||
|
||||
#include "common/config.h"
|
||||
#include "common/version.h"
|
||||
#include "common/scm_rev.h"
|
||||
#include "qt_gui/compatibility_info.h"
|
||||
#ifdef ENABLE_DISCORD_RPC
|
||||
#include "common/discord_rpc_handler.h"
|
||||
|
@ -318,7 +318,6 @@ SettingsDialog::SettingsDialog(std::span<const QString> physical_devices,
|
|||
// General
|
||||
ui->consoleLanguageGroupBox->installEventFilter(this);
|
||||
ui->emulatorLanguageGroupBox->installEventFilter(this);
|
||||
ui->separateUpdatesCheckBox->installEventFilter(this);
|
||||
ui->showSplashCheckBox->installEventFilter(this);
|
||||
ui->discordRPCCheckbox->installEventFilter(this);
|
||||
ui->userName->installEventFilter(this);
|
||||
|
@ -450,8 +449,6 @@ void SettingsDialog::LoadValuesFromConfig() {
|
|||
QString translatedText_FullscreenMode =
|
||||
screenModeMap.key(QString::fromStdString(Config::getFullscreenMode()));
|
||||
ui->displayModeComboBox->setCurrentText(translatedText_FullscreenMode);
|
||||
ui->separateUpdatesCheckBox->setChecked(
|
||||
toml::find_or<bool>(data, "General", "separateUpdateEnabled", false));
|
||||
ui->gameSizeCheckBox->setChecked(toml::find_or<bool>(data, "GUI", "loadGameSizeEnabled", true));
|
||||
ui->showSplashCheckBox->setChecked(toml::find_or<bool>(data, "General", "showSplash", false));
|
||||
QString translatedText_logType = logTypeMap.key(QString::fromStdString(Config::getLogType()));
|
||||
|
@ -494,7 +491,7 @@ void SettingsDialog::LoadValuesFromConfig() {
|
|||
QString updateChannel = QString::fromStdString(Config::getUpdateChannel());
|
||||
ui->updateComboBox->setCurrentText(
|
||||
channelMap.key(updateChannel != "Release" && updateChannel != "Nightly"
|
||||
? (Common::isRelease ? "Release" : "Nightly")
|
||||
? (Common::g_is_release ? "Release" : "Nightly")
|
||||
: updateChannel));
|
||||
#endif
|
||||
|
||||
|
@ -600,8 +597,6 @@ void SettingsDialog::updateNoteTextEdit(const QString& elementName) {
|
|||
text = tr("Console Language:\\nSets the language that the PS4 game uses.\\nIt's recommended to set this to a language the game supports, which will vary by region.");
|
||||
} else if (elementName == "emulatorLanguageGroupBox") {
|
||||
text = tr("Emulator Language:\\nSets the language of the emulator's user interface.");
|
||||
} else if (elementName == "separateUpdatesCheckBox") {
|
||||
text = tr("Enable Separate Update Folder:\\nEnables installing game updates into a separate folder for easy management.\\nThis can be manually created by adding the extracted update to the game folder with the name \"CUSA00000-UPDATE\" where the CUSA ID matches the game's ID.");
|
||||
} else if (elementName == "showSplashCheckBox") {
|
||||
text = tr("Show Splash Screen:\\nShows the game's splash screen (a special image) while the game is starting.");
|
||||
} else if (elementName == "discordRPCCheckbox") {
|
||||
|
@ -760,7 +755,6 @@ void SettingsDialog::UpdateSettings() {
|
|||
Config::setVblankDiv(ui->vblankSpinBox->value());
|
||||
Config::setDumpShaders(ui->dumpShadersCheckBox->isChecked());
|
||||
Config::setNullGpu(ui->nullGpuCheckBox->isChecked());
|
||||
Config::setSeparateUpdateEnabled(ui->separateUpdatesCheckBox->isChecked());
|
||||
Config::setLoadGameSizeEnabled(ui->gameSizeCheckBox->isChecked());
|
||||
Config::setShowSplash(ui->showSplashCheckBox->isChecked());
|
||||
Config::setDebugDump(ui->debugDump->isChecked());
|
||||
|
|
|
@ -135,13 +135,6 @@
|
|||
<property name="spacing">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="separateUpdatesCheckBox">
|
||||
<property name="text">
|
||||
<string>Enable Separate Update Folder</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="showSplashCheckBox">
|
||||
<property name="text">
|
||||
|
|
|
@ -1126,7 +1126,7 @@
|
|||
</message>
|
||||
<message>
|
||||
<source>Deadzone Offset (def 0.50):</source>
|
||||
<translation type="unfinished">Deadzone Offset (def 0.50):</translation>
|
||||
<translation> إزاحة المدى الغير فعال (الأصل ٠.٥٠).</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Speed Multiplier (def 1.0):</source>
|
||||
|
@ -1138,7 +1138,7 @@
|
|||
</message>
|
||||
<message>
|
||||
<source>This button copies mappings from the Common Config to the currently selected profile, and cannot be used when the currently selected profile is the Common Config.</source>
|
||||
<translation type="unfinished">This button copies mappings from the Common Config to the currently selected profile, and cannot be used when the currently selected profile is the Common Config.</translation>
|
||||
<translation>هذا الزر يقوم بنسخ تعيينات الأزرار من إعدادات المستخدم العامة لإعدادات المستخدم المحددة حالياً، ولا يمكن استعماله عندما تكون الإعدادات المستخدمة هي الإعدادات العامة.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Copy values from Common Config</source>
|
||||
|
@ -1146,7 +1146,7 @@
|
|||
</message>
|
||||
<message>
|
||||
<source>Do you want to overwrite existing mappings with the mappings from the Common Config?</source>
|
||||
<translation type="unfinished">Do you want to overwrite existing mappings with the mappings from the Common Config?</translation>
|
||||
<translation>هل تريد استبدال التعيينات الحالية بالتعيينات العامة؟</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Unable to Save</source>
|
||||
|
@ -1474,10 +1474,6 @@
|
|||
<source>Emulator</source>
|
||||
<translation>المحاكي</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder</source>
|
||||
<translation type="unfinished">Enable Separate Update Folder</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Default tab when opening settings</source>
|
||||
<translation>علامة التبويب الافتراضية عند فتح الإعدادات</translation>
|
||||
|
@ -1500,7 +1496,7 @@
|
|||
</message>
|
||||
<message>
|
||||
<source>Trophy Key</source>
|
||||
<translation type="unfinished">Trophy Key</translation>
|
||||
<translation>زر الميداليات</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Trophy</source>
|
||||
|
@ -1508,7 +1504,7 @@
|
|||
</message>
|
||||
<message>
|
||||
<source>Open the custom trophy images/sounds folder</source>
|
||||
<translation type="unfinished">Open the custom trophy images/sounds folder</translation>
|
||||
<translation>افتح مجلد تخصيص اصوات/صور الميداليات</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Logger</source>
|
||||
|
@ -1544,7 +1540,7 @@
|
|||
</message>
|
||||
<message>
|
||||
<source>s</source>
|
||||
<translation type="unfinished">s</translation>
|
||||
<translation>س</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Controller</source>
|
||||
|
@ -1588,7 +1584,7 @@
|
|||
</message>
|
||||
<message>
|
||||
<source>Enable HDR</source>
|
||||
<translation type="unfinished">Enable HDR</translation>
|
||||
<translation>تشغيل HDR</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Paths</source>
|
||||
|
@ -1628,23 +1624,23 @@
|
|||
</message>
|
||||
<message>
|
||||
<source>Enable Crash Diagnostics</source>
|
||||
<translation type="unfinished">Enable Crash Diagnostics</translation>
|
||||
<translation>تشغيل تشخيص الأعطال</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Collect Shaders</source>
|
||||
<translation type="unfinished">Collect Shaders</translation>
|
||||
<translation>اجمع برامج التظليل</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Copy GPU Buffers</source>
|
||||
<translation type="unfinished">Copy GPU Buffers</translation>
|
||||
<translation>انسخ التخزين المؤقت لوحدة معالجة الرُسوم</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Host Debug Markers</source>
|
||||
<translation type="unfinished">Host Debug Markers</translation>
|
||||
<translation>استضافة علامات التصحيح</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Guest Debug Markers</source>
|
||||
<translation type="unfinished">Guest Debug Markers</translation>
|
||||
<translation>ضيف علامات التصحيح</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Update</source>
|
||||
|
@ -1656,7 +1652,7 @@
|
|||
</message>
|
||||
<message>
|
||||
<source>Always Show Changelog</source>
|
||||
<translation type="unfinished">Always Show Changelog</translation>
|
||||
<translation>اظهر سجل التغيرات دائماً</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Update Channel</source>
|
||||
|
@ -1672,23 +1668,23 @@
|
|||
</message>
|
||||
<message>
|
||||
<source>Title Music</source>
|
||||
<translation type="unfinished">Title Music</translation>
|
||||
<translation>موسيقى الشاشة الرئيسية</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Disable Trophy Notification</source>
|
||||
<translation type="unfinished">Disable Trophy Notification</translation>
|
||||
<translation>إغلاق إشعارات الميداليات</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Background Image</source>
|
||||
<translation type="unfinished">Background Image</translation>
|
||||
<translation>صورة الخلفية</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show Background Image</source>
|
||||
<translation type="unfinished">Show Background Image</translation>
|
||||
<translation>إظهار صورة الخلفية</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Opacity</source>
|
||||
<translation type="unfinished">Opacity</translation>
|
||||
<translation>درجة السواد</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Play title music</source>
|
||||
|
@ -1696,19 +1692,19 @@
|
|||
</message>
|
||||
<message>
|
||||
<source>Update Compatibility Database On Startup</source>
|
||||
<translation type="unfinished">Update Compatibility Database On Startup</translation>
|
||||
<translation>تحديث قاعدة بيانات التوافق عند التشغيل</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Game Compatibility</source>
|
||||
<translation type="unfinished">Game Compatibility</translation>
|
||||
<translation>توافق الألعاب</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Display Compatibility Data</source>
|
||||
<translation type="unfinished">Display Compatibility Data</translation>
|
||||
<translation>إظهار معلومات التوافق</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Update Compatibility Database</source>
|
||||
<translation type="unfinished">Update Compatibility Database</translation>
|
||||
<translation>تحديث قاعدة بيانات التوافق</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Volume</source>
|
||||
|
@ -1742,10 +1738,6 @@
|
|||
<source>Emulator Language:\nSets the language of the emulator's user interface.</source>
|
||||
<translation>لغة المحاكي:\nتحدد لغة واجهة المستخدم الخاصة بالمحاكي.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID.</source>
|
||||
<translation>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting.</source>
|
||||
<translation>إظهار شاشة البداية:\nيعرض شاشة البداية الخاصة باللعبة (صورة خاصة) أثناء بدء التشغيل.</translation>
|
||||
|
@ -1760,7 +1752,7 @@
|
|||
</message>
|
||||
<message>
|
||||
<source>Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters.</source>
|
||||
<translation type="unfinished">Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters.</translation>
|
||||
<translation>مفتاح الميداليات:\nمفتاح يستخدم لفتح تشفير الميداليات. يجب أن يكون من جهاز مكسور الحماية.\nيجي أن يحتوي على أحرف نظام العد السداسي.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Log Type:\nSets whether to synchronize the output of the log window for performance. May have adverse effects on emulation.</source>
|
||||
|
@ -1776,7 +1768,7 @@
|
|||
</message>
|
||||
<message>
|
||||
<source>Background Image:\nControl the opacity of the game background image.</source>
|
||||
<translation type="unfinished">Background Image:\nControl the opacity of the game background image.</translation>
|
||||
<translation>صورة الخلفية:\nيتحكم في درجة سواد صورة خلفية اللعبة.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Play Title Music:\nIf a game supports it, enable playing special music when selecting the game in the GUI.</source>
|
||||
|
@ -1784,7 +1776,7 @@
|
|||
</message>
|
||||
<message>
|
||||
<source>Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window).</source>
|
||||
<translation type="unfinished">Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window).</translation>
|
||||
<translation>إغلاق نوافذ الميداليات المنبثقة:\n إغلاق إشعارات الميداليات داخل اللعبة. تقدم الميداليات يمكن تتبعه باستخدام عارض الميداليات (قم بالضغط على زر الفأرة الأيمن داخل النافذة الرئيسية).</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Hide Cursor:\nChoose when the cursor will disappear:\nNever: You will always see the mouse.\nidle: Set a time for it to disappear after being idle.\nAlways: you will never see the mouse.</source>
|
||||
|
@ -1800,15 +1792,15 @@
|
|||
</message>
|
||||
<message>
|
||||
<source>Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information.</source>
|
||||
<translation type="unfinished">Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information.</translation>
|
||||
<translation>عرض بيانات التوافق:\nيقوم بإظهار معلومات توافق اللعبة في طريقة عرض الطاولة. تشغيل"تحديث التوافق عند التشغيل" للحصول على معلومات محدثة.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts.</source>
|
||||
<translation type="unfinished">Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts.</translation>
|
||||
<translation>تحديث التوافق عند التشغيل:\nتحديث قاعدة بيانات التوافق تلقائياً عند تشغيل shadps4.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Update Compatibility Database:\nImmediately update the compatibility database.</source>
|
||||
<translation type="unfinished">Update Compatibility Database:\nImmediately update the compatibility database.</translation>
|
||||
<translation>تحديث قاعدة بيانات التوافق:\nقم بتحديث قاعدة بيانات التوافق حالاً.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Never</source>
|
||||
|
@ -1860,7 +1852,7 @@
|
|||
</message>
|
||||
<message>
|
||||
<source>Enable HDR:\nEnables HDR in games that support it.\nYour monitor must have support for the BT2020 PQ color space and the RGB10A2 swapchain format.</source>
|
||||
<translation type="unfinished">Enable HDR:\nEnables HDR in games that support it.\nYour monitor must have support for the BT2020 PQ color space and the RGB10A2 swapchain format.</translation>
|
||||
<translation>تشغيل HDR:\n يقوم بتشغيل HDR في الألعاب المدعومة.\nيجب أن تدعم شاشتك أطياف ألوان BT2020 PQ و صيغة تنسيق المبادلة RGB10A2.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Game Folders:\nThe list of folders to check for installed games.</source>
|
||||
|
@ -1892,11 +1884,11 @@
|
|||
</message>
|
||||
<message>
|
||||
<source>Collect Shaders:\nYou need this enabled to edit shaders with the debug menu (Ctrl + F10).</source>
|
||||
<translation type="unfinished">Collect Shaders:\nYou need this enabled to edit shaders with the debug menu (Ctrl + F10).</translation>
|
||||
<translation>تجميع برامج التظليل:\n يجب أن تقوم بتشغيل هذا لتعديل برامج التظليل باستخدام قائمة تصحيح الأخطاء (Ctrl + F10).</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Crash Diagnostics:\nCreates a .yaml file with info about the Vulkan state at the time of crashing.\nUseful for debugging 'Device lost' errors. If you have this enabled, you should enable Host AND Guest Debug Markers.\nDoes not work on Intel GPUs.\nYou need Vulkan Validation Layers enabled and the Vulkan SDK for this to work.</source>
|
||||
<translation type="unfinished">Crash Diagnostics:\nCreates a .yaml file with info about the Vulkan state at the time of crashing.\nUseful for debugging 'Device lost' errors. If you have this enabled, you should enable Host AND Guest Debug Markers.\nDoes not work on Intel GPUs.\nYou need Vulkan Validation Layers enabled and the Vulkan SDK for this to work.</translation>
|
||||
<translation>تشخيص الأعطال:\nيقوم بإنشاء ملف بصيغة .yaml يحتوي على معلومات عن حالة Vulkan في وقت حدوث العطل.\nمفيد لتصحيح أخطاء 'فصل الجهاز'. إذا قمت بتشغيل هذا من الأفضل أن تقوم بتشغيل "استضافة علامات تصحيح الأخطاء" و "ضيف علامات تصحيح الأخطاء".\nلا يعمل على وحدة معالجة رسوم إنتل.\nتحتاج لتشغيل التحقق من طبقات Vulkan و مجموعة تطوير البرامج الخاصة بـVulkan من أجل أن يعمل هذا.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Copy GPU Buffers:\nGets around race conditions involving GPU submits.\nMay or may not help with PM4 type 0 crashes.</source>
|
||||
|
|
|
@ -1474,10 +1474,6 @@
|
|||
<source>Emulator</source>
|
||||
<translation type="unfinished">Emulator</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder</source>
|
||||
<translation type="unfinished">Enable Separate Update Folder</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Default tab when opening settings</source>
|
||||
<translation>Standardfaneblad ved åbning af indstillinger</translation>
|
||||
|
@ -1742,10 +1738,6 @@
|
|||
<source>Emulator Language:\nSets the language of the emulator's user interface.</source>
|
||||
<translation>Emulatorsprog:\nIndstiller sproget i emulatorens brugergrænseflade.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID.</source>
|
||||
<translation>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting.</source>
|
||||
<translation>Vis startskærm:\nViser en startskærm (speciel grafik) under opstarten.</translation>
|
||||
|
|
|
@ -1277,11 +1277,11 @@
|
|||
</message>
|
||||
<message>
|
||||
<source>Trophy Viewer</source>
|
||||
<translation type="unfinished">Trophy Viewer</translation>
|
||||
<translation>Trophäenansicht</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>No games found. Please add your games to your library first.</source>
|
||||
<translation type="unfinished">No games found. Please add your games to your library first.</translation>
|
||||
<translation>Keine Spiele gefunden. Bitte fügen Sie zuerst Ihre Spiele zu Ihrer Bibliothek hinzu.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Search...</source>
|
||||
|
@ -1409,43 +1409,43 @@
|
|||
</message>
|
||||
<message>
|
||||
<source>Play</source>
|
||||
<translation type="unfinished">Play</translation>
|
||||
<translation>Spielen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Pause</source>
|
||||
<translation type="unfinished">Pause</translation>
|
||||
<translation>Pause</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Stop</source>
|
||||
<translation type="unfinished">Stop</translation>
|
||||
<translation>Stopp</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Restart</source>
|
||||
<translation type="unfinished">Restart</translation>
|
||||
<translation>Neustarten</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Full Screen</source>
|
||||
<translation type="unfinished">Full Screen</translation>
|
||||
<translation>Vollbild</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Controllers</source>
|
||||
<translation type="unfinished">Controllers</translation>
|
||||
<translation>Controller</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Keyboard</source>
|
||||
<translation type="unfinished">Keyboard</translation>
|
||||
<translation>Tastatur</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Refresh List</source>
|
||||
<translation type="unfinished">Refresh List</translation>
|
||||
<translation>Liste aktualisieren</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Resume</source>
|
||||
<translation type="unfinished">Resume</translation>
|
||||
<translation>Fortsetzen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show Labels Under Icons</source>
|
||||
<translation type="unfinished">Show Labels Under Icons</translation>
|
||||
<translation>Etiketten unter Symbolen anzeigen</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
|
@ -1474,10 +1474,6 @@
|
|||
<source>Emulator</source>
|
||||
<translation>Emulator</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder</source>
|
||||
<translation>Separaten Update-Ordner aktivieren</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Default tab when opening settings</source>
|
||||
<translation>Standardregisterkarte beim Öffnen der Einstellungen</translation>
|
||||
|
@ -1742,10 +1738,6 @@
|
|||
<source>Emulator Language:\nSets the language of the emulator's user interface.</source>
|
||||
<translation>Emulatorsprache:\nLegt die Sprache der Emulator-Benutzeroberfläche fest.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID.</source>
|
||||
<translation>Separaten Update-Ordner aktivieren:\nErmöglicht die Installation von Spielaktualiserungen in einem separaten Ordner zur einfachen Verwaltung.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting.</source>
|
||||
<translation>Startbildschirm anzeigen:\nZeigt beim Start einen speziellen Bildschirm (Splash) des Spiels an.</translation>
|
||||
|
@ -2056,7 +2048,11 @@
|
|||
</message>
|
||||
<message>
|
||||
<source>Open the custom trophy images/sounds folder:\nYou can add custom images to the trophies and an audio.\nAdd the files to custom_trophy with the following names:\ntrophy.wav OR trophy.mp3, bronze.png, gold.png, platinum.png, silver.png\nNote: The sound will only work in QT versions.</source>
|
||||
<translation type="unfinished">Open the custom trophy images/sounds folder:\nYou can add custom images to the trophies and an audio.\nAdd the files to custom_trophy with the following names:\ntrophy.wav OR trophy.mp3, bronze.png, gold.png, platinum.png, silver.png\nNote: The sound will only work in QT versions.</translation>
|
||||
<translation>Öffnen Sie den Ordner für benutzerdefinierte Trophäenbilder/-sounds:\n
|
||||
Sie können benutzerdefinierte Bilder zu den Trophäen hinzufügen und einen Ton hinzufügen.\n
|
||||
Fügen Sie die Dateien dem Ordner custom_trophy mit folgenden Namen hinzu:\n
|
||||
trophy.wav ODER trophy.mp3, bronze.png, gold.png, platinum.png, silver.png\n
|
||||
Hinweis: Der Sound funktioniert nur in Qt-Versionen.</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
|
@ -2067,23 +2063,23 @@
|
|||
</message>
|
||||
<message>
|
||||
<source>Select Game:</source>
|
||||
<translation type="unfinished">Select Game:</translation>
|
||||
<translation>Spiel auswählen:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Progress</source>
|
||||
<translation type="unfinished">Progress</translation>
|
||||
<translation>Fortschritt</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show Earned Trophies</source>
|
||||
<translation type="unfinished">Show Earned Trophies</translation>
|
||||
<translation>Verdiente Trophäen anzeigen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show Not Earned Trophies</source>
|
||||
<translation type="unfinished">Show Not Earned Trophies</translation>
|
||||
<translation>Nicht verdiente Trophäen anzeigen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show Hidden Trophies</source>
|
||||
<translation type="unfinished">Show Hidden Trophies</translation>
|
||||
<translation>Verborgene Trophäen anzeigen</translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
|
|
|
@ -1474,10 +1474,6 @@
|
|||
<source>Emulator</source>
|
||||
<translation type="unfinished">Emulator</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder</source>
|
||||
<translation type="unfinished">Enable Separate Update Folder</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Default tab when opening settings</source>
|
||||
<translation>Προεπιλεγμένη καρτέλα κατά την ανοίγμα των ρυθμίσεων</translation>
|
||||
|
@ -1742,10 +1738,6 @@
|
|||
<source>Emulator Language:\nSets the language of the emulator's user interface.</source>
|
||||
<translation>Γλώσσα Εξομοιωτή:\nΡυθμίζει τη γλώσσα του γραφικού περιβάλλοντος του εξομοιωτή.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID.</source>
|
||||
<translation type="unfinished">Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting.</source>
|
||||
<translation>Εμφάνιση Splash Screen:\nΕμφανίζει ειδική γραφική οθόνη κατά την εκκίνηση.</translation>
|
||||
|
|
|
@ -1474,10 +1474,6 @@
|
|||
<source>Emulator</source>
|
||||
<translation>Emulator</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder</source>
|
||||
<translation>Enable Separate Update Folder</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Default tab when opening settings</source>
|
||||
<translation>Default tab when opening settings</translation>
|
||||
|
@ -1742,10 +1738,6 @@
|
|||
<source>Emulator Language:\nSets the language of the emulator's user interface.</source>
|
||||
<translation>Emulator Language:\nSets the language of the emulator's user interface.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID.</source>
|
||||
<translation>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting.</source>
|
||||
<translation>Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting.</translation>
|
||||
|
|
|
@ -1474,10 +1474,6 @@
|
|||
<source>Emulator</source>
|
||||
<translation>Emulador</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder</source>
|
||||
<translation>Habilitar Carpeta Independiente de Actualizaciones</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Default tab when opening settings</source>
|
||||
<translation>Pestaña predeterminada al abrir la configuración</translation>
|
||||
|
@ -1742,10 +1738,6 @@
|
|||
<source>Emulator Language:\nSets the language of the emulator's user interface.</source>
|
||||
<translation>Idioma del Emulador:\nConfigura el idioma de la interfaz de usuario del emulador.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID.</source>
|
||||
<translation>Habilitar Carpeta Independiente de Actualizaciónes:\nHabilita el instalar actualizaciones del juego en una carpeta separada para mas facilidad en la gestión.\nPuede crearse manualmente añadiendo la actualización extraída a la carpeta del juego con el nombre "CUSA00000-UPDATE" donde el CUSA ID coincide con el ID del juego.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting.</source>
|
||||
<translation>Mostrar Pantalla de Inicio:\nMuestra la pantalla de inicio del juego (una imagen especial) mientras el juego se está iniciando.</translation>
|
||||
|
|
|
@ -1474,10 +1474,6 @@
|
|||
<source>Emulator</source>
|
||||
<translation>شبیه ساز</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder</source>
|
||||
<translation>فعالسازی پوشه جداگانه برای بهروزرسانی</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Default tab when opening settings</source>
|
||||
<translation>زبان پیشفرض هنگام باز کردن تنظیمات</translation>
|
||||
|
@ -1742,10 +1738,6 @@
|
|||
<source>Emulator Language:\nSets the language of the emulator's user interface.</source>
|
||||
<translation>زبان شبیهساز:\nزبان رابط کاربری شبیهساز را انتخاب میکند.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID.</source>
|
||||
<translation>فعالسازی پوشه جداگانه برای بهروزرسانی:\nامکان نصب بهروزرسانیهای بازی در یک پوشه جداگانه برای مدیریت راحتتر را فراهم میکند.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting.</source>
|
||||
<translation>نمایش صفحه شروع:\nصفحه شروع بازی (تصویری ویژه) را هنگام بارگذاری بازی نمایش میدهد.</translation>
|
||||
|
|
|
@ -1474,10 +1474,6 @@
|
|||
<source>Emulator</source>
|
||||
<translation>Emulaattori</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder</source>
|
||||
<translation>Ota Käyttöön Erillinen Päivityshakemisto</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Default tab when opening settings</source>
|
||||
<translation>Oletusvälilehti avattaessa asetuksia</translation>
|
||||
|
@ -1742,10 +1738,6 @@
|
|||
<source>Emulator Language:\nSets the language of the emulator's user interface.</source>
|
||||
<translation>Emulaattorin Kieli:\nAsettaa emulaattorin käyttöliittymän kielen.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID.</source>
|
||||
<translation>Ota Käyttöön Erillinen Päivityskansio:\nOttaa käyttöön päivitysten asennuksen erilliseen kansioon helpottamaan niiden hallintaa.\nTämä on tehtävissä manuaalisesti lisäämällä puretun päivityksen pelikansioon "CUSA00000-UPDATE" nimellä, missä CUSA ID vastaa pelin ID:tä.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting.</source>
|
||||
<translation>Näytä Aloitusnäyttö:\nNäyttää pelin aloitusnäytön (erityinen kuva) pelin käynnistyessä.</translation>
|
||||
|
|
|
@ -1474,10 +1474,6 @@
|
|||
<source>Emulator</source>
|
||||
<translation>Émulateur</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder</source>
|
||||
<translation>Dossier séparé pour les mises à jour</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Default tab when opening settings</source>
|
||||
<translation>Onglet par défaut lors de l'ouverture des paramètres</translation>
|
||||
|
@ -1742,10 +1738,6 @@
|
|||
<source>Emulator Language:\nSets the language of the emulator's user interface.</source>
|
||||
<translation>Langue de l'émulateur:\nDéfinit la langue de l'interface utilisateur de l'émulateur.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID.</source>
|
||||
<translation>Dossier séparé pour les mises à jour:\nInstalle les mises à jours des jeux dans un dossier séparé pour une gestion plus facile.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting.</source>
|
||||
<translation>Afficher l'écran de démarrage:\nAffiche l'écran de démarrage du jeu (une image spéciale) lors du démarrage du jeu.</translation>
|
||||
|
|
|
@ -1474,10 +1474,6 @@
|
|||
<source>Emulator</source>
|
||||
<translation>Emulátor</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder</source>
|
||||
<translation>Külön Frissítési Mappa Engedélyezése</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Default tab when opening settings</source>
|
||||
<translation>Alapértelmezett fül a beállítások megnyitásakor</translation>
|
||||
|
@ -1742,10 +1738,6 @@
|
|||
<source>Emulator Language:\nSets the language of the emulator's user interface.</source>
|
||||
<translation>Emulátor nyelve:\nBeállítja az emulátor felhasználói felületének nyelvét.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID.</source>
|
||||
<translation>Külön Frissítéi Mappa Engedélyezése:\nEngedélyezi a frissítések külön mappába helyezését, a könnyű kezelésük érdekében.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting.</source>
|
||||
<translation>Indítóképernyő megjelenítése:\nMegjeleníti a játék indítóképernyőjét (különleges képet) a játék elindításakor.</translation>
|
||||
|
|
|
@ -1474,10 +1474,6 @@
|
|||
<source>Emulator</source>
|
||||
<translation type="unfinished">Emulator</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder</source>
|
||||
<translation type="unfinished">Enable Separate Update Folder</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Default tab when opening settings</source>
|
||||
<translation>Tab default saat membuka pengaturan</translation>
|
||||
|
@ -1742,10 +1738,6 @@
|
|||
<source>Emulator Language:\nSets the language of the emulator's user interface.</source>
|
||||
<translation>Bahasa Emulator:\nMenetapkan bahasa antarmuka pengguna emulator.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID.</source>
|
||||
<translation>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting.</source>
|
||||
<translation>Tampilkan Layar Pembuka:\nMenampilkan layar pembuka permainan (gambar khusus) saat permainan dimulai.</translation>
|
||||
|
|
|
@ -1409,43 +1409,43 @@
|
|||
</message>
|
||||
<message>
|
||||
<source>Play</source>
|
||||
<translation type="unfinished">Play</translation>
|
||||
<translation>Riproduci</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Pause</source>
|
||||
<translation type="unfinished">Pause</translation>
|
||||
<translation>Pausa</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Stop</source>
|
||||
<translation type="unfinished">Stop</translation>
|
||||
<translation>Arresta</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Restart</source>
|
||||
<translation type="unfinished">Restart</translation>
|
||||
<translation>Riavvia</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Full Screen</source>
|
||||
<translation type="unfinished">Full Screen</translation>
|
||||
<translation>Schermo Intero</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Controllers</source>
|
||||
<translation type="unfinished">Controllers</translation>
|
||||
<translation>Controller</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Keyboard</source>
|
||||
<translation type="unfinished">Keyboard</translation>
|
||||
<translation>Tastiera</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Refresh List</source>
|
||||
<translation type="unfinished">Refresh List</translation>
|
||||
<translation>Aggiorna Lista</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Resume</source>
|
||||
<translation type="unfinished">Resume</translation>
|
||||
<translation>Riprendi</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show Labels Under Icons</source>
|
||||
<translation type="unfinished">Show Labels Under Icons</translation>
|
||||
<translation>Mostra Etichette Sotto Icone</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
|
@ -1474,10 +1474,6 @@
|
|||
<source>Emulator</source>
|
||||
<translation>Emulatore</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder</source>
|
||||
<translation>Abilita Cartella Aggiornamenti Separata</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Default tab when opening settings</source>
|
||||
<translation>Scheda predefinita all'apertura delle impostazioni</translation>
|
||||
|
@ -1742,10 +1738,6 @@
|
|||
<source>Emulator Language:\nSets the language of the emulator's user interface.</source>
|
||||
<translation>Lingua dell'Emulatore:\nImposta la lingua dell'interfaccia utente dell'emulatore.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID.</source>
|
||||
<translation>Abilita Cartella Aggiornamenti Separata:\nAbilita l'installazione degli aggiornamenti in una cartella separata per una più facile gestione.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting.</source>
|
||||
<translation>Mostra Schermata di Avvio:\nMostra la schermata di avvio del gioco (un'immagine speciale) mentre il gioco si sta avviando.</translation>
|
||||
|
|
|
@ -1474,10 +1474,6 @@
|
|||
<source>Emulator</source>
|
||||
<translation>エミュレーター</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder</source>
|
||||
<translation>アップデートフォルダの分離を有効化</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Default tab when opening settings</source>
|
||||
<translation>設定を開くときのデフォルトタブ</translation>
|
||||
|
@ -1742,10 +1738,6 @@
|
|||
<source>Emulator Language:\nSets the language of the emulator's user interface.</source>
|
||||
<translation>エミュレーターの言語:\nエミュレーターのユーザーインターフェースの言語を設定します。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID.</source>
|
||||
<translation>Enable Separate Update Folder:\nゲームのアップデートを別のフォルダにインストールすることで、管理が容易になります。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting.</source>
|
||||
<translation>スプラッシュスクリーンを表示:\nゲーム起動中にゲームのスプラッシュスクリーン(特別な画像)を表示します。</translation>
|
||||
|
|
|
@ -1474,10 +1474,6 @@
|
|||
<source>Emulator</source>
|
||||
<translation type="unfinished">Emulator</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder</source>
|
||||
<translation type="unfinished">Enable Separate Update Folder</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Default tab when opening settings</source>
|
||||
<translation>설정 열기 시 기본 탭</translation>
|
||||
|
@ -1742,10 +1738,6 @@
|
|||
<source>Emulator Language:\nSets the language of the emulator's user interface.</source>
|
||||
<translation type="unfinished">Emulator Language:\nSets the language of the emulator's user interface.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID.</source>
|
||||
<translation type="unfinished">Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting.</source>
|
||||
<translation type="unfinished">Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting.</translation>
|
||||
|
|
|
@ -1474,10 +1474,6 @@
|
|||
<source>Emulator</source>
|
||||
<translation type="unfinished">Emulator</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder</source>
|
||||
<translation type="unfinished">Enable Separate Update Folder</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Default tab when opening settings</source>
|
||||
<translation>Numatytoji kortelė atidarius nustatymus</translation>
|
||||
|
@ -1742,10 +1738,6 @@
|
|||
<source>Emulator Language:\nSets the language of the emulator's user interface.</source>
|
||||
<translation>Emuliatoriaus kalba:\nNustato emuliatoriaus vartotojo sąsajos kalbą.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID.</source>
|
||||
<translation type="unfinished">Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting.</source>
|
||||
<translation>Rodyti paleidimo ekraną:\nPaleidimo metu rodo žaidimo paleidimo ekraną (ypatingą vaizdą).</translation>
|
||||
|
|
|
@ -1474,10 +1474,6 @@
|
|||
<source>Emulator</source>
|
||||
<translation>Emulator</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder</source>
|
||||
<translation>Bruk separat oppdateringsmappe</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Default tab when opening settings</source>
|
||||
<translation>Standardfanen når innstillingene åpnes</translation>
|
||||
|
@ -1742,10 +1738,6 @@
|
|||
<source>Emulator Language:\nSets the language of the emulator's user interface.</source>
|
||||
<translation>Emulatorspråket:\nAngir språket for emulatorens brukergrensesnitt.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID.</source>
|
||||
<translation>Bruk separat oppdateringsmappe:\n Gjør det mulig å installere spilloppdateringer i en egen mappe for enkel administrasjon.\nDette kan gjøres manuelt ved å legge til den utpakkede oppdateringen, til spillmappa med navnet "CUSA00000-UPDATE" der CUSA-ID-en samsvarer med spillets-ID.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting.</source>
|
||||
<translation>Vis velkomstbilde:\nViser spillets velkomstbilde (et spesialbilde) når spillet starter.</translation>
|
||||
|
|
|
@ -1474,10 +1474,6 @@
|
|||
<source>Emulator</source>
|
||||
<translation type="unfinished">Emulator</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder</source>
|
||||
<translation type="unfinished">Enable Separate Update Folder</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Default tab when opening settings</source>
|
||||
<translation>Standaardtabblad bij het openen van instellingen</translation>
|
||||
|
@ -1742,10 +1738,6 @@
|
|||
<source>Emulator Language:\nSets the language of the emulator's user interface.</source>
|
||||
<translation>Emulator Taal:\nStelt de taal van de gebruikersinterface van de emulator in.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID.</source>
|
||||
<translation>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting.</source>
|
||||
<translation>Opstartscherm weergeven:\nToont het opstartscherm van het spel (een speciale afbeelding) tijdens het starten van het spel.</translation>
|
||||
|
|
|
@ -1474,10 +1474,6 @@
|
|||
<source>Emulator</source>
|
||||
<translation>Emulator</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder</source>
|
||||
<translation>Włącz oddzielny folder aktualizacji</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Default tab when opening settings</source>
|
||||
<translation>Domyślna zakładka podczas otwierania ustawień</translation>
|
||||
|
@ -1742,10 +1738,6 @@
|
|||
<source>Emulator Language:\nSets the language of the emulator's user interface.</source>
|
||||
<translation>Język emulatora:\nUstala język interfejsu użytkownika emulatora.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID.</source>
|
||||
<translation>Włącz oddzielny folder aktualizacji:\nUmożliwia instalowanie aktualizacji gier w oddzielnym folderze w celu łatwego zarządzania.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting.</source>
|
||||
<translation>Wyświetl ekran powitalny:\nPodczas uruchamiania gry wyświetla ekran powitalny (specjalny obraz).</translation>
|
||||
|
|
|
@ -1474,10 +1474,6 @@
|
|||
<source>Emulator</source>
|
||||
<translation>Emulador</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder</source>
|
||||
<translation>Ativar Pasta de Atualização Separada</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Default tab when opening settings</source>
|
||||
<translation>Aba padrão ao abrir as configurações</translation>
|
||||
|
@ -1742,10 +1738,6 @@
|
|||
<source>Emulator Language:\nSets the language of the emulator's user interface.</source>
|
||||
<translation>Idioma do Emulador:\nDefine o idioma da interface do emulador.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID.</source>
|
||||
<translation>Ativar Pasta de Atualização Separada:\nPermite instalar atualizações de jogos em uma pasta separada para fácil gerenciamento.\nIsso pode ser manualmente criado adicionando a atualização extraída à pasta do jogo com o nome "CUSA00000-UPDATE" onde o ID do CUSA corresponde ao ID do jogo.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting.</source>
|
||||
<translation>Mostrar Splash Inicial:\nExibe a tela inicial do jogo (imagem especial) ao iniciar o jogo.</translation>
|
||||
|
|
|
@ -1474,10 +1474,6 @@
|
|||
<source>Emulator</source>
|
||||
<translation>Emulador</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder</source>
|
||||
<translation>Ativar Pasta de Atualizações Separada</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Default tab when opening settings</source>
|
||||
<translation>Aba padrão ao abrir as definições</translation>
|
||||
|
@ -1742,10 +1738,6 @@
|
|||
<source>Emulator Language:\nSets the language of the emulator's user interface.</source>
|
||||
<translation>Idioma do Emulador:\nDefine o idioma da interface gráfica do emulador.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID.</source>
|
||||
<translation>Ativar Pasta de Atualização Separada:\nPermite instalar as atualizações dos jogos numa pasta separada para uma fácil gestão.\nIsto pode ser manualmente criado adicionando a atualização extraída à pasta do jogo com o nome "CUSA00000-UPDATE" onde o ID do CUSA corresponde ao ID do jogo.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting.</source>
|
||||
<translation>Mostrar Splash Inicial:\nExibe o ecrã inicial do jogo (uma imagem especial) enquanto o jogo inicia.</translation>
|
||||
|
|
|
@ -1474,10 +1474,6 @@
|
|||
<source>Emulator</source>
|
||||
<translation type="unfinished">Emulator</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder</source>
|
||||
<translation type="unfinished">Enable Separate Update Folder</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Default tab when opening settings</source>
|
||||
<translation>Tab-ul implicit la deschiderea setărilor</translation>
|
||||
|
@ -1742,10 +1738,6 @@
|
|||
<source>Emulator Language:\nSets the language of the emulator's user interface.</source>
|
||||
<translation>Limba emulatorului:\nSetează limba interfeței utilizatorului a emulatorului.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID.</source>
|
||||
<translation type="unfinished">Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting.</source>
|
||||
<translation>Afișează ecranul de încărcare:\nAfișează ecranul de încărcare al jocului (o imagine specială) în timp ce jocul pornește.</translation>
|
||||
|
|
|
@ -1474,10 +1474,6 @@
|
|||
<source>Emulator</source>
|
||||
<translation>Эмулятор</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder</source>
|
||||
<translation>Отдельная папка обновлений</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Default tab when opening settings</source>
|
||||
<translation>Вкладка по умолчанию при открытии настроек</translation>
|
||||
|
@ -1742,10 +1738,6 @@
|
|||
<source>Emulator Language:\nSets the language of the emulator's user interface.</source>
|
||||
<translation>Язык эмулятора:\nУстанавливает язык пользовательского интерфейса эмулятора.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID.</source>
|
||||
<translation>Отдельная папка обновлений:\nПозволяет устанавливать обновления игры в отдельную папку для удобства.\nМожно создать вручную, добавив извлеченное обновление в папку с игрой с именем "CUSA00000-UPDATE", где идентификатор CUSA совпадает с идентификатором игры.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting.</source>
|
||||
<translation>Показывать заставку:\nОтображает заставку игры (специальное изображение) во время запуска.</translation>
|
||||
|
|
|
@ -1409,43 +1409,43 @@
|
|||
</message>
|
||||
<message>
|
||||
<source>Play</source>
|
||||
<translation type="unfinished">Play</translation>
|
||||
<translation>Luaj</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Pause</source>
|
||||
<translation type="unfinished">Pause</translation>
|
||||
<translation>Pezullo</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Stop</source>
|
||||
<translation type="unfinished">Stop</translation>
|
||||
<translation>Ndalo</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Restart</source>
|
||||
<translation type="unfinished">Restart</translation>
|
||||
<translation>Rinis</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Full Screen</source>
|
||||
<translation type="unfinished">Full Screen</translation>
|
||||
<translation>Ekran i Plotë</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Controllers</source>
|
||||
<translation type="unfinished">Controllers</translation>
|
||||
<translation>Dorezat</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Keyboard</source>
|
||||
<translation type="unfinished">Keyboard</translation>
|
||||
<translation>Tastiera</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Refresh List</source>
|
||||
<translation type="unfinished">Refresh List</translation>
|
||||
<translation>Rifresko Listën</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Resume</source>
|
||||
<translation type="unfinished">Resume</translation>
|
||||
<translation>Rifillo</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show Labels Under Icons</source>
|
||||
<translation type="unfinished">Show Labels Under Icons</translation>
|
||||
<translation>Shfaq Etiketat Poshtë Ikonave</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
|
@ -1474,10 +1474,6 @@
|
|||
<source>Emulator</source>
|
||||
<translation>Emulatori</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder</source>
|
||||
<translation>Aktivizo dosjen e ndarë të përditësimit</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Default tab when opening settings</source>
|
||||
<translation>Skeda e paracaktuar kur hapen cilësimet</translation>
|
||||
|
@ -1742,10 +1738,6 @@
|
|||
<source>Emulator Language:\nSets the language of the emulator's user interface.</source>
|
||||
<translation>Gjuha e emulatorit:\nPërcakton gjuhën e ndërfaqes së përdoruesit të emulatorit.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID.</source>
|
||||
<translation>Aktivizo dosjen e ndarë të përditësimit:\nAktivizon instalimin e përditësimeve të lojërave në dosje të veçanta për menaxhim më të lehtë.\nKjo mund të krijohet manualisht duke shtuar përditësimin e shpaketuar në dosjen e lojës me emrin "CUSA00000-UPDATE" ku ID-ja CUSA përputhet me ID-në e lojës.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting.</source>
|
||||
<translation>Shfaq ekranin e ngarkesës:\nShfaq ekranin e ngarkesës së lojës (një pamje e veçantë) gjatë fillimit të lojës.</translation>
|
||||
|
|
|
@ -1474,10 +1474,6 @@
|
|||
<source>Emulator</source>
|
||||
<translation>Emulator</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder</source>
|
||||
<translation>Aktivera separat uppdateringsmapp</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Default tab when opening settings</source>
|
||||
<translation>Standardflik när inställningar öppnas</translation>
|
||||
|
@ -1742,10 +1738,6 @@
|
|||
<source>Emulator Language:\nSets the language of the emulator's user interface.</source>
|
||||
<translation>Emulatorspråk:\nStäller in språket för emulatorns användargränssnitt</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID.</source>
|
||||
<translation>Aktivera separat uppdateringsmapp:\nAktiverar installation av speluppdateringar i en separat mapp för enkel hantering.\nDetta kan skapas manuellt genom att lägga till uppackad uppdatering till spelmappen med namnet "CUSA00000-UPDATE" där CUSA ID matchar spelets id</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting.</source>
|
||||
<translation>Visa startskärm:\nVisar spelets startskärm (en speciell bild) när spelet startas</translation>
|
||||
|
|
|
@ -1474,10 +1474,6 @@
|
|||
<source>Emulator</source>
|
||||
<translation>Emülatör</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder</source>
|
||||
<translation>Ayrı Güncelleme Klasörünü Etkinleştir</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Default tab when opening settings</source>
|
||||
<translation>Ayarlar açıldığında varsayılan sekme</translation>
|
||||
|
@ -1742,10 +1738,6 @@
|
|||
<source>Emulator Language:\nSets the language of the emulator's user interface.</source>
|
||||
<translation>Emülatör Dili:\nEmülatörün kullanıcı arayüzünün dilini ayarlar.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID.</source>
|
||||
<translation>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting.</source>
|
||||
<translation>Açılış Ekranını Göster:\nOyun açılırken (özel bir görüntü) açılış ekranını gösterir.</translation>
|
||||
|
|
|
@ -1277,11 +1277,11 @@
|
|||
</message>
|
||||
<message>
|
||||
<source>Trophy Viewer</source>
|
||||
<translation type="unfinished">Trophy Viewer</translation>
|
||||
<translation>Переглядач трофеїв</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>No games found. Please add your games to your library first.</source>
|
||||
<translation type="unfinished">No games found. Please add your games to your library first.</translation>
|
||||
<translation>Не знайдено жодної гри. Будь ласка, спочатку додайте свої ігри до бібліотеки.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Search...</source>
|
||||
|
@ -1409,43 +1409,43 @@
|
|||
</message>
|
||||
<message>
|
||||
<source>Play</source>
|
||||
<translation type="unfinished">Play</translation>
|
||||
<translation>Грати</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Pause</source>
|
||||
<translation type="unfinished">Pause</translation>
|
||||
<translation>Пауза</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Stop</source>
|
||||
<translation type="unfinished">Stop</translation>
|
||||
<translation>Стоп</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Restart</source>
|
||||
<translation type="unfinished">Restart</translation>
|
||||
<translation>Перезапуск</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Full Screen</source>
|
||||
<translation type="unfinished">Full Screen</translation>
|
||||
<translation>На повний екран</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Controllers</source>
|
||||
<translation type="unfinished">Controllers</translation>
|
||||
<translation>Контролери</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Keyboard</source>
|
||||
<translation type="unfinished">Keyboard</translation>
|
||||
<translation>Клавіатура</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Refresh List</source>
|
||||
<translation type="unfinished">Refresh List</translation>
|
||||
<translation>Оновити список</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Resume</source>
|
||||
<translation type="unfinished">Resume</translation>
|
||||
<translation>Продовжити</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show Labels Under Icons</source>
|
||||
<translation type="unfinished">Show Labels Under Icons</translation>
|
||||
<translation>Показати найменування під іконками</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
|
@ -1474,10 +1474,6 @@
|
|||
<source>Emulator</source>
|
||||
<translation>Емулятор</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder</source>
|
||||
<translation>Увімкнути окрему папку оновлень</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Default tab when opening settings</source>
|
||||
<translation>Вкладка за замовчуванням при відкритті налаштувань</translation>
|
||||
|
@ -1742,10 +1738,6 @@
|
|||
<source>Emulator Language:\nSets the language of the emulator's user interface.</source>
|
||||
<translation>Мова емулятора:\nВстановіть мову користувацького інтерфейсу емулятора.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID.</source>
|
||||
<translation>Окрема папка для оновлень:\nДає змогу встановлювати оновлення гри в окрему папку для зручності.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting.</source>
|
||||
<translation>Показувати заставку:\nВідображає заставку гри (спеціальне зображення) під час запуску гри.</translation>
|
||||
|
@ -2067,7 +2059,7 @@
|
|||
</message>
|
||||
<message>
|
||||
<source>Select Game:</source>
|
||||
<translation type="unfinished">Select Game:</translation>
|
||||
<translation>Виберіть гру:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Progress</source>
|
||||
|
|
|
@ -1474,10 +1474,6 @@
|
|||
<source>Emulator</source>
|
||||
<translation>Trình giả lập</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder</source>
|
||||
<translation>Bật thư mục cập nhật riêng</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Default tab when opening settings</source>
|
||||
<translation>Tab mặc định khi mở cài đặt</translation>
|
||||
|
@ -1742,10 +1738,6 @@
|
|||
<source>Emulator Language:\nSets the language of the emulator's user interface.</source>
|
||||
<translation>Ngôn ngữ của trình giả lập:\nChọn ngôn ngữ của giao diện người dùng của trình giả lập.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID.</source>
|
||||
<translation>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting.</source>
|
||||
<translation>Hiển thị màn hình khởi động:\nHiển thị màn hình khởi động của trò chơi (một hình ảnh đặc biệt) trong khi trò chơi khởi động.</translation>
|
||||
|
|
|
@ -1474,10 +1474,6 @@
|
|||
<source>Emulator</source>
|
||||
<translation>模拟器</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder</source>
|
||||
<translation>启用单独的更新目录</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Default tab when opening settings</source>
|
||||
<translation>打开设置时的默认选项卡</translation>
|
||||
|
@ -1742,10 +1738,6 @@
|
|||
<source>Emulator Language:\nSets the language of the emulator's user interface.</source>
|
||||
<translation>模拟器语言:\n设置模拟器用户界面的语言。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID.</source>
|
||||
<translation>启用单独的更新目录:\n启用安装游戏更新到一个单独的目录中以更便于管理。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting.</source>
|
||||
<translation>显示启动画面:\n在游戏启动时显示游戏的启动画面(特殊图像)。</translation>
|
||||
|
|
|
@ -1474,10 +1474,6 @@
|
|||
<source>Emulator</source>
|
||||
<translation type="unfinished">Emulator</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder</source>
|
||||
<translation type="unfinished">Enable Separate Update Folder</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Default tab when opening settings</source>
|
||||
<translation>打開設置時的默認選項卡</translation>
|
||||
|
@ -1742,10 +1738,6 @@
|
|||
<source>Emulator Language:\nSets the language of the emulator's user interface.</source>
|
||||
<translation>模擬器語言:\n設定模擬器的用戶介面的語言。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.\nThis can be manually created by adding the extracted update to the game folder with the name "CUSA00000-UPDATE" where the CUSA ID matches the game's ID.</source>
|
||||
<translation>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting.</source>
|
||||
<translation>顯示啟動畫面:\n在遊戲啟動時顯示遊戲的啟動畫面(特殊圖片)。</translation>
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include "common/assert.h"
|
||||
#include "common/config.h"
|
||||
#include "common/elf_info.h"
|
||||
#include "common/version.h"
|
||||
#include "core/debug_state.h"
|
||||
#include "core/libraries/kernel/time.h"
|
||||
#include "core/libraries/pad/pad.h"
|
||||
|
|
|
@ -75,6 +75,28 @@ Id EmitFPMin64(EmitContext& ctx, Id a, Id b) {
|
|||
return ctx.OpFMin(ctx.F64[1], a, b);
|
||||
}
|
||||
|
||||
Id EmitFPMinTri32(EmitContext& ctx, Id a, Id b, Id c) {
|
||||
if (ctx.profile.supports_trinary_minmax) {
|
||||
return ctx.OpFMin3AMD(ctx.F32[1], a, b, c);
|
||||
}
|
||||
return ctx.OpFMin(ctx.F32[1], a, ctx.OpFMin(ctx.F32[1], b, c));
|
||||
}
|
||||
|
||||
Id EmitFPMaxTri32(EmitContext& ctx, Id a, Id b, Id c) {
|
||||
if (ctx.profile.supports_trinary_minmax) {
|
||||
return ctx.OpFMax3AMD(ctx.F32[1], a, b, c);
|
||||
}
|
||||
return ctx.OpFMax(ctx.F32[1], a, ctx.OpFMax(ctx.F32[1], b, c));
|
||||
}
|
||||
|
||||
Id EmitFPMedTri32(EmitContext& ctx, Id a, Id b, Id c) {
|
||||
if (ctx.profile.supports_trinary_minmax) {
|
||||
return ctx.OpFMid3AMD(ctx.F32[1], a, b, c);
|
||||
}
|
||||
const Id mmx{ctx.OpFMin(ctx.F32[1], ctx.OpFMax(ctx.F32[1], a, b), c)};
|
||||
return ctx.OpFMax(ctx.F32[1], ctx.OpFMin(ctx.F32[1], a, b), mmx);
|
||||
}
|
||||
|
||||
Id EmitFPMul16(EmitContext& ctx, IR::Inst* inst, Id a, Id b) {
|
||||
return Decorate(ctx, inst, ctx.OpFMul(ctx.F16[1], a, b));
|
||||
}
|
||||
|
|
|
@ -247,6 +247,9 @@ Id EmitFPMax32(EmitContext& ctx, Id a, Id b, bool is_legacy = false);
|
|||
Id EmitFPMax64(EmitContext& ctx, Id a, Id b);
|
||||
Id EmitFPMin32(EmitContext& ctx, Id a, Id b, bool is_legacy = false);
|
||||
Id EmitFPMin64(EmitContext& ctx, Id a, Id b);
|
||||
Id EmitFPMinTri32(EmitContext& ctx, Id a, Id b, Id c);
|
||||
Id EmitFPMaxTri32(EmitContext& ctx, Id a, Id b, Id c);
|
||||
Id EmitFPMedTri32(EmitContext& ctx, Id a, Id b, Id c);
|
||||
Id EmitFPMul16(EmitContext& ctx, IR::Inst* inst, Id a, Id b);
|
||||
Id EmitFPMul32(EmitContext& ctx, IR::Inst* inst, Id a, Id b);
|
||||
Id EmitFPMul64(EmitContext& ctx, IR::Inst* inst, Id a, Id b);
|
||||
|
@ -372,6 +375,12 @@ Id EmitSMin32(EmitContext& ctx, Id a, Id b);
|
|||
Id EmitUMin32(EmitContext& ctx, Id a, Id b);
|
||||
Id EmitSMax32(EmitContext& ctx, Id a, Id b);
|
||||
Id EmitUMax32(EmitContext& ctx, Id a, Id b);
|
||||
Id EmitSMinTri32(EmitContext& ctx, Id a, Id b, Id c);
|
||||
Id EmitUMinTri32(EmitContext& ctx, Id a, Id b, Id c);
|
||||
Id EmitSMaxTri32(EmitContext& ctx, Id a, Id b, Id c);
|
||||
Id EmitUMaxTri32(EmitContext& ctx, Id a, Id b, Id c);
|
||||
Id EmitSMedTri32(EmitContext& ctx, Id a, Id b, Id c);
|
||||
Id EmitUMedTri32(EmitContext& ctx, Id a, Id b, Id c);
|
||||
Id EmitSClamp32(EmitContext& ctx, IR::Inst* inst, Id value, Id min, Id max);
|
||||
Id EmitUClamp32(EmitContext& ctx, IR::Inst* inst, Id value, Id min, Id max);
|
||||
Id EmitSLessThan32(EmitContext& ctx, Id lhs, Id rhs);
|
||||
|
|
|
@ -256,6 +256,50 @@ Id EmitUMax32(EmitContext& ctx, Id a, Id b) {
|
|||
return ctx.OpUMax(ctx.U32[1], a, b);
|
||||
}
|
||||
|
||||
Id EmitSMinTri32(EmitContext& ctx, Id a, Id b, Id c) {
|
||||
if (ctx.profile.supports_trinary_minmax) {
|
||||
return ctx.OpSMin3AMD(ctx.U32[1], a, b, c);
|
||||
}
|
||||
return ctx.OpSMin(ctx.U32[1], a, ctx.OpSMin(ctx.U32[1], b, c));
|
||||
}
|
||||
|
||||
Id EmitUMinTri32(EmitContext& ctx, Id a, Id b, Id c) {
|
||||
if (ctx.profile.supports_trinary_minmax) {
|
||||
return ctx.OpUMin3AMD(ctx.U32[1], a, b, c);
|
||||
}
|
||||
return ctx.OpUMin(ctx.U32[1], a, ctx.OpUMin(ctx.U32[1], b, c));
|
||||
}
|
||||
|
||||
Id EmitSMaxTri32(EmitContext& ctx, Id a, Id b, Id c) {
|
||||
if (ctx.profile.supports_trinary_minmax) {
|
||||
return ctx.OpSMax3AMD(ctx.U32[1], a, b, c);
|
||||
}
|
||||
return ctx.OpSMax(ctx.U32[1], a, ctx.OpSMax(ctx.U32[1], b, c));
|
||||
}
|
||||
|
||||
Id EmitUMaxTri32(EmitContext& ctx, Id a, Id b, Id c) {
|
||||
if (ctx.profile.supports_trinary_minmax) {
|
||||
return ctx.OpUMax3AMD(ctx.U32[1], a, b, c);
|
||||
}
|
||||
return ctx.OpUMax(ctx.U32[1], a, ctx.OpUMax(ctx.U32[1], b, c));
|
||||
}
|
||||
|
||||
Id EmitSMedTri32(EmitContext& ctx, Id a, Id b, Id c) {
|
||||
if (ctx.profile.supports_trinary_minmax) {
|
||||
return ctx.OpSMid3AMD(ctx.U32[1], a, b, c);
|
||||
}
|
||||
const Id mmx{ctx.OpSMin(ctx.U32[1], ctx.OpSMax(ctx.U32[1], a, b), c)};
|
||||
return ctx.OpSMax(ctx.U32[1], ctx.OpSMin(ctx.U32[1], a, b), mmx);
|
||||
}
|
||||
|
||||
Id EmitUMedTri32(EmitContext& ctx, Id a, Id b, Id c) {
|
||||
if (ctx.profile.supports_trinary_minmax) {
|
||||
return ctx.OpUMid3AMD(ctx.U32[1], a, b, c);
|
||||
}
|
||||
const Id mmx{ctx.OpUMin(ctx.U32[1], ctx.OpUMax(ctx.U32[1], a, b), c)};
|
||||
return ctx.OpUMax(ctx.U32[1], ctx.OpUMin(ctx.U32[1], a, b), mmx);
|
||||
}
|
||||
|
||||
Id EmitSClamp32(EmitContext& ctx, IR::Inst* inst, Id value, Id min, Id max) {
|
||||
Id result{};
|
||||
if (ctx.profile.has_broken_spirv_clamp) {
|
||||
|
|
|
@ -13,6 +13,9 @@ void Translator::EmitFlowControl(u32 pc, const GcnInst& inst) {
|
|||
case Opcode::S_TTRACEDATA:
|
||||
LOG_WARNING(Render_Vulkan, "S_TTRACEDATA instruction!");
|
||||
return;
|
||||
case Opcode::S_SETPRIO:
|
||||
LOG_WARNING(Render_Vulkan, "S_SETPRIO instruction!");
|
||||
return;
|
||||
case Opcode::S_GETPC_B64:
|
||||
return S_GETPC_B64(pc, inst);
|
||||
case Opcode::S_WAITCNT:
|
||||
|
|
|
@ -238,13 +238,11 @@ public:
|
|||
void V_FMA_F32(const GcnInst& inst);
|
||||
void V_FMA_F64(const GcnInst& inst);
|
||||
void V_MIN3_F32(const GcnInst& inst);
|
||||
void V_MIN3_I32(const GcnInst& inst);
|
||||
void V_MIN3_U32(const GcnInst& inst);
|
||||
void V_MIN3_U32(bool is_signed, const GcnInst& inst);
|
||||
void V_MAX3_F32(const GcnInst& inst);
|
||||
void V_MAX3_U32(bool is_signed, const GcnInst& inst);
|
||||
void V_MED3_F32(const GcnInst& inst);
|
||||
void V_MED3_I32(const GcnInst& inst);
|
||||
void V_MED3_U32(const GcnInst& inst);
|
||||
void V_MED3_U32(bool is_signed, const GcnInst& inst);
|
||||
void V_SAD(const GcnInst& inst);
|
||||
void V_SAD_U32(const GcnInst& inst);
|
||||
void V_CVT_PK_U16_U32(const GcnInst& inst);
|
||||
|
|
|
@ -359,9 +359,9 @@ void Translator::EmitVectorAlu(const GcnInst& inst) {
|
|||
case Opcode::V_MIN3_F32:
|
||||
return V_MIN3_F32(inst);
|
||||
case Opcode::V_MIN3_I32:
|
||||
return V_MIN3_I32(inst);
|
||||
return V_MIN3_U32(true, inst);
|
||||
case Opcode::V_MIN3_U32:
|
||||
return V_MIN3_U32(inst);
|
||||
return V_MIN3_U32(false, inst);
|
||||
case Opcode::V_MAX3_F32:
|
||||
return V_MAX3_F32(inst);
|
||||
case Opcode::V_MAX3_I32:
|
||||
|
@ -371,9 +371,9 @@ void Translator::EmitVectorAlu(const GcnInst& inst) {
|
|||
case Opcode::V_MED3_F32:
|
||||
return V_MED3_F32(inst);
|
||||
case Opcode::V_MED3_I32:
|
||||
return V_MED3_I32(inst);
|
||||
return V_MED3_U32(true, inst);
|
||||
case Opcode::V_MED3_U32:
|
||||
return V_MED3_U32(inst);
|
||||
return V_MED3_U32(false, inst);
|
||||
case Opcode::V_SAD_U32:
|
||||
return V_SAD_U32(inst);
|
||||
case Opcode::V_CVT_PK_U16_U32:
|
||||
|
@ -1166,59 +1166,42 @@ void Translator::V_MIN3_F32(const GcnInst& inst) {
|
|||
const IR::F32 src0{GetSrc<IR::F32>(inst.src[0])};
|
||||
const IR::F32 src1{GetSrc<IR::F32>(inst.src[1])};
|
||||
const IR::F32 src2{GetSrc<IR::F32>(inst.src[2])};
|
||||
SetDst(inst.dst[0], ir.FPMin(src0, ir.FPMin(src1, src2)));
|
||||
SetDst(inst.dst[0], ir.FPMinTri(src0, src1, src2));
|
||||
}
|
||||
|
||||
void Translator::V_MIN3_I32(const GcnInst& inst) {
|
||||
void Translator::V_MIN3_U32(bool is_signed, const GcnInst& inst) {
|
||||
const IR::U32 src0{GetSrc(inst.src[0])};
|
||||
const IR::U32 src1{GetSrc(inst.src[1])};
|
||||
const IR::U32 src2{GetSrc(inst.src[2])};
|
||||
SetDst(inst.dst[0], ir.SMin(src0, ir.SMin(src1, src2)));
|
||||
}
|
||||
|
||||
void Translator::V_MIN3_U32(const GcnInst& inst) {
|
||||
const IR::U32 src0{GetSrc(inst.src[0])};
|
||||
const IR::U32 src1{GetSrc(inst.src[1])};
|
||||
const IR::U32 src2{GetSrc(inst.src[2])};
|
||||
SetDst(inst.dst[0], ir.UMin(src0, ir.UMin(src1, src2)));
|
||||
SetDst(inst.dst[0], ir.IMinTri(src0, src1, src2, is_signed));
|
||||
}
|
||||
|
||||
void Translator::V_MAX3_F32(const GcnInst& inst) {
|
||||
const IR::F32 src0{GetSrc<IR::F32>(inst.src[0])};
|
||||
const IR::F32 src1{GetSrc<IR::F32>(inst.src[1])};
|
||||
const IR::F32 src2{GetSrc<IR::F32>(inst.src[2])};
|
||||
SetDst(inst.dst[0], ir.FPMax(src0, ir.FPMax(src1, src2)));
|
||||
SetDst(inst.dst[0], ir.FPMaxTri(src0, src1, src2));
|
||||
}
|
||||
|
||||
void Translator::V_MAX3_U32(bool is_signed, const GcnInst& inst) {
|
||||
const IR::U32 src0{GetSrc(inst.src[0])};
|
||||
const IR::U32 src1{GetSrc(inst.src[1])};
|
||||
const IR::U32 src2{GetSrc(inst.src[2])};
|
||||
SetDst(inst.dst[0], ir.IMax(src0, ir.IMax(src1, src2, is_signed), is_signed));
|
||||
SetDst(inst.dst[0], ir.IMaxTri(src0, src1, src2, is_signed));
|
||||
}
|
||||
|
||||
void Translator::V_MED3_F32(const GcnInst& inst) {
|
||||
const IR::F32 src0{GetSrc<IR::F32>(inst.src[0])};
|
||||
const IR::F32 src1{GetSrc<IR::F32>(inst.src[1])};
|
||||
const IR::F32 src2{GetSrc<IR::F32>(inst.src[2])};
|
||||
const IR::F32 mmx = ir.FPMin(ir.FPMax(src0, src1), src2);
|
||||
SetDst(inst.dst[0], ir.FPMax(ir.FPMin(src0, src1), mmx));
|
||||
SetDst(inst.dst[0], ir.FPMedTri(src0, src1, src2));
|
||||
}
|
||||
|
||||
void Translator::V_MED3_I32(const GcnInst& inst) {
|
||||
void Translator::V_MED3_U32(bool is_signed, const GcnInst& inst) {
|
||||
const IR::U32 src0{GetSrc(inst.src[0])};
|
||||
const IR::U32 src1{GetSrc(inst.src[1])};
|
||||
const IR::U32 src2{GetSrc(inst.src[2])};
|
||||
const IR::U32 mmx = ir.SMin(ir.SMax(src0, src1), src2);
|
||||
SetDst(inst.dst[0], ir.SMax(ir.SMin(src0, src1), mmx));
|
||||
}
|
||||
|
||||
void Translator::V_MED3_U32(const GcnInst& inst) {
|
||||
const IR::U32 src0{GetSrc(inst.src[0])};
|
||||
const IR::U32 src1{GetSrc(inst.src[1])};
|
||||
const IR::U32 src2{GetSrc(inst.src[2])};
|
||||
const IR::U32 mmx = ir.UMin(ir.UMax(src0, src1), src2);
|
||||
SetDst(inst.dst[0], ir.UMax(ir.UMin(src0, src1), mmx));
|
||||
SetDst(inst.dst[0], ir.IMedTri(src0, src1, src2, is_signed));
|
||||
}
|
||||
|
||||
void Translator::V_SAD(const GcnInst& inst) {
|
||||
|
|
|
@ -1336,6 +1336,18 @@ F32F64 IREmitter::FPMin(const F32F64& lhs, const F32F64& rhs, bool is_legacy) {
|
|||
}
|
||||
}
|
||||
|
||||
F32F64 IREmitter::FPMinTri(const F32F64& a, const F32F64& b, const F32F64& c) {
|
||||
return Inst<F32>(Opcode::FPMinTri32, a, b, c);
|
||||
}
|
||||
|
||||
F32F64 IREmitter::FPMaxTri(const F32F64& a, const F32F64& b, const F32F64& c) {
|
||||
return Inst<F32>(Opcode::FPMaxTri32, a, b, c);
|
||||
}
|
||||
|
||||
F32F64 IREmitter::FPMedTri(const F32F64& a, const F32F64& b, const F32F64& c) {
|
||||
return Inst<F32>(Opcode::FPMedTri32, a, b, c);
|
||||
}
|
||||
|
||||
U32U64 IREmitter::IAdd(const U32U64& a, const U32U64& b) {
|
||||
if (a.Type() != b.Type()) {
|
||||
UNREACHABLE_MSG("Mismatching types {} and {}", a.Type(), b.Type());
|
||||
|
@ -1567,6 +1579,42 @@ U32 IREmitter::IMax(const U32& a, const U32& b, bool is_signed) {
|
|||
return is_signed ? SMax(a, b) : UMax(a, b);
|
||||
}
|
||||
|
||||
U32 IREmitter::SMinTri(const U32& a, const U32& b, const U32& c) {
|
||||
return Inst<U32>(Opcode::SMinTri32, a, b, c);
|
||||
}
|
||||
|
||||
U32 IREmitter::UMinTri(const U32& a, const U32& b, const U32& c) {
|
||||
return Inst<U32>(Opcode::UMinTri32, a, b, c);
|
||||
}
|
||||
|
||||
U32 IREmitter::IMinTri(const U32& a, const U32& b, const U32& c, bool is_signed) {
|
||||
return is_signed ? SMinTri(a, b, c) : UMinTri(a, b, c);
|
||||
}
|
||||
|
||||
U32 IREmitter::SMaxTri(const U32& a, const U32& b, const U32& c) {
|
||||
return Inst<U32>(Opcode::SMaxTri32, a, b, c);
|
||||
}
|
||||
|
||||
U32 IREmitter::UMaxTri(const U32& a, const U32& b, const U32& c) {
|
||||
return Inst<U32>(Opcode::UMaxTri32, a, b, c);
|
||||
}
|
||||
|
||||
U32 IREmitter::IMaxTri(const U32& a, const U32& b, const U32& c, bool is_signed) {
|
||||
return is_signed ? SMaxTri(a, b, c) : UMaxTri(a, b, c);
|
||||
}
|
||||
|
||||
U32 IREmitter::SMedTri(const U32& a, const U32& b, const U32& c) {
|
||||
return Inst<U32>(Opcode::SMedTri32, a, b, c);
|
||||
}
|
||||
|
||||
U32 IREmitter::UMedTri(const U32& a, const U32& b, const U32& c) {
|
||||
return Inst<U32>(Opcode::UMedTri32, a, b, c);
|
||||
}
|
||||
|
||||
U32 IREmitter::IMedTri(const U32& a, const U32& b, const U32& c, bool is_signed) {
|
||||
return is_signed ? SMedTri(a, b, c) : UMedTri(a, b, c);
|
||||
}
|
||||
|
||||
U32 IREmitter::SClamp(const U32& value, const U32& min, const U32& max) {
|
||||
return Inst<U32>(Opcode::SClamp32, value, min, max);
|
||||
}
|
||||
|
|
|
@ -233,6 +233,9 @@ public:
|
|||
[[nodiscard]] U1 FPUnordered(const F32F64& lhs, const F32F64& rhs);
|
||||
[[nodiscard]] F32F64 FPMax(const F32F64& lhs, const F32F64& rhs, bool is_legacy = false);
|
||||
[[nodiscard]] F32F64 FPMin(const F32F64& lhs, const F32F64& rhs, bool is_legacy = false);
|
||||
[[nodiscard]] F32F64 FPMinTri(const F32F64& a, const F32F64& b, const F32F64& c);
|
||||
[[nodiscard]] F32F64 FPMaxTri(const F32F64& a, const F32F64& b, const F32F64& c);
|
||||
[[nodiscard]] F32F64 FPMedTri(const F32F64& a, const F32F64& b, const F32F64& c);
|
||||
|
||||
[[nodiscard]] U32U64 IAdd(const U32U64& a, const U32U64& b);
|
||||
[[nodiscard]] Value IAddCary(const U32& a, const U32& b);
|
||||
|
@ -266,6 +269,15 @@ public:
|
|||
[[nodiscard]] U32 SMax(const U32& a, const U32& b);
|
||||
[[nodiscard]] U32 UMax(const U32& a, const U32& b);
|
||||
[[nodiscard]] U32 IMax(const U32& a, const U32& b, bool is_signed);
|
||||
[[nodiscard]] U32 SMinTri(const U32& a, const U32& b, const U32& c);
|
||||
[[nodiscard]] U32 UMinTri(const U32& a, const U32& b, const U32& c);
|
||||
[[nodiscard]] U32 IMinTri(const U32& a, const U32& b, const U32& c, bool is_signed);
|
||||
[[nodiscard]] U32 SMaxTri(const U32& a, const U32& b, const U32& c);
|
||||
[[nodiscard]] U32 UMaxTri(const U32& a, const U32& b, const U32& c);
|
||||
[[nodiscard]] U32 IMaxTri(const U32& a, const U32& b, const U32& c, bool is_signed);
|
||||
[[nodiscard]] U32 SMedTri(const U32& a, const U32& b, const U32& c);
|
||||
[[nodiscard]] U32 UMedTri(const U32& a, const U32& b, const U32& c);
|
||||
[[nodiscard]] U32 IMedTri(const U32& a, const U32& b, const U32& c, bool is_signed);
|
||||
[[nodiscard]] U32 SClamp(const U32& value, const U32& min, const U32& max);
|
||||
[[nodiscard]] U32 UClamp(const U32& value, const U32& min, const U32& max);
|
||||
|
||||
|
|
|
@ -241,6 +241,9 @@ OPCODE(FPMax32, F32, F32,
|
|||
OPCODE(FPMax64, F64, F64, F64, )
|
||||
OPCODE(FPMin32, F32, F32, F32, U1, )
|
||||
OPCODE(FPMin64, F64, F64, F64, )
|
||||
OPCODE(FPMinTri32, F32, F32, F32, F32, )
|
||||
OPCODE(FPMaxTri32, F32, F32, F32, F32, )
|
||||
OPCODE(FPMedTri32, F32, F32, F32, F32, )
|
||||
OPCODE(FPMul32, F32, F32, F32, )
|
||||
OPCODE(FPMul64, F64, F64, F64, )
|
||||
OPCODE(FPDiv32, F32, F32, F32, )
|
||||
|
@ -350,6 +353,12 @@ OPCODE(SMin32, U32, U32,
|
|||
OPCODE(UMin32, U32, U32, U32, )
|
||||
OPCODE(SMax32, U32, U32, U32, )
|
||||
OPCODE(UMax32, U32, U32, U32, )
|
||||
OPCODE(SMinTri32, U32, U32, U32, U32, )
|
||||
OPCODE(UMinTri32, U32, U32, U32, U32, )
|
||||
OPCODE(SMaxTri32, U32, U32, U32, U32, )
|
||||
OPCODE(UMaxTri32, U32, U32, U32, U32, )
|
||||
OPCODE(SMedTri32, U32, U32, U32, U32, )
|
||||
OPCODE(UMedTri32, U32, U32, U32, U32, )
|
||||
OPCODE(SClamp32, U32, U32, U32, U32, )
|
||||
OPCODE(UClamp32, U32, U32, U32, U32, )
|
||||
OPCODE(SLessThan32, U1, U32, U32, )
|
||||
|
|
|
@ -26,6 +26,7 @@ struct Profile {
|
|||
bool support_legacy_vertex_attributes{};
|
||||
bool supports_image_load_store_lod{};
|
||||
bool supports_native_cube_calc{};
|
||||
bool supports_trinary_minmax{};
|
||||
bool supports_robust_buffer_access{};
|
||||
bool has_broken_spirv_clamp{};
|
||||
bool lower_left_origin_mode{};
|
||||
|
|
|
@ -1423,6 +1423,10 @@ struct Liverpool {
|
|||
return num_samples;
|
||||
}
|
||||
|
||||
bool IsClipDisabled() const {
|
||||
return clipper_control.clip_disable || primitive_type == PrimitiveType::RectList;
|
||||
}
|
||||
|
||||
void SetDefaults();
|
||||
};
|
||||
|
||||
|
|
|
@ -77,8 +77,8 @@ GraphicsPipeline::GraphicsPipeline(
|
|||
|
||||
auto prim_restart = key.enable_primitive_restart != 0;
|
||||
if (prim_restart && IsPrimitiveListTopology() && !instance.IsListRestartSupported()) {
|
||||
LOG_WARNING(Render_Vulkan,
|
||||
"Primitive restart is enabled for list topology but not supported by driver.");
|
||||
LOG_DEBUG(Render_Vulkan,
|
||||
"Primitive restart is enabled for list topology but not supported by driver.");
|
||||
prim_restart = false;
|
||||
}
|
||||
const vk::PipelineInputAssemblyStateCreateInfo input_assembly = {
|
||||
|
@ -105,7 +105,6 @@ GraphicsPipeline::GraphicsPipeline(
|
|||
.frontFace = key.front_face == Liverpool::FrontFace::Clockwise
|
||||
? vk::FrontFace::eClockwise
|
||||
: vk::FrontFace::eCounterClockwise,
|
||||
.depthBiasEnable = key.depth_bias_enable,
|
||||
.lineWidth = 1.0f,
|
||||
};
|
||||
|
||||
|
@ -123,18 +122,20 @@ GraphicsPipeline::GraphicsPipeline(
|
|||
.pNext = instance.IsDepthClipControlSupported() ? &clip_control : nullptr,
|
||||
};
|
||||
|
||||
boost::container::static_vector<vk::DynamicState, 14> dynamic_states = {
|
||||
vk::DynamicState::eViewportWithCountEXT,
|
||||
vk::DynamicState::eScissorWithCountEXT,
|
||||
vk::DynamicState::eBlendConstants,
|
||||
vk::DynamicState::eDepthBounds,
|
||||
vk::DynamicState::eDepthBias,
|
||||
vk::DynamicState::eStencilReference,
|
||||
vk::DynamicState::eStencilCompareMask,
|
||||
vk::DynamicState::eStencilWriteMask,
|
||||
boost::container::static_vector<vk::DynamicState, 17> dynamic_states = {
|
||||
vk::DynamicState::eViewportWithCountEXT, vk::DynamicState::eScissorWithCountEXT,
|
||||
vk::DynamicState::eBlendConstants, vk::DynamicState::eDepthTestEnableEXT,
|
||||
vk::DynamicState::eDepthWriteEnableEXT, vk::DynamicState::eDepthCompareOpEXT,
|
||||
vk::DynamicState::eDepthBiasEnableEXT, vk::DynamicState::eDepthBias,
|
||||
vk::DynamicState::eStencilTestEnableEXT, vk::DynamicState::eStencilReference,
|
||||
vk::DynamicState::eStencilCompareMask, vk::DynamicState::eStencilWriteMask,
|
||||
vk::DynamicState::eStencilOpEXT,
|
||||
};
|
||||
|
||||
if (instance.IsDepthBoundsSupported()) {
|
||||
dynamic_states.push_back(vk::DynamicState::eDepthBoundsTestEnableEXT);
|
||||
dynamic_states.push_back(vk::DynamicState::eDepthBounds);
|
||||
}
|
||||
if (instance.IsDynamicColorWriteMaskSupported()) {
|
||||
dynamic_states.push_back(vk::DynamicState::eColorWriteMaskEXT);
|
||||
}
|
||||
|
@ -149,14 +150,6 @@ GraphicsPipeline::GraphicsPipeline(
|
|||
.pDynamicStates = dynamic_states.data(),
|
||||
};
|
||||
|
||||
const vk::PipelineDepthStencilStateCreateInfo depth_info = {
|
||||
.depthTestEnable = key.depth_test_enable,
|
||||
.depthWriteEnable = key.depth_write_enable,
|
||||
.depthCompareOp = key.depth_compare_op,
|
||||
.depthBoundsTestEnable = key.depth_bounds_test_enable,
|
||||
.stencilTestEnable = key.stencil_test_enable,
|
||||
};
|
||||
|
||||
boost::container::static_vector<vk::PipelineShaderStageCreateInfo, MaxShaderStages>
|
||||
shader_stages;
|
||||
auto stage = u32(Shader::LogicalStage::Vertex);
|
||||
|
@ -292,7 +285,6 @@ GraphicsPipeline::GraphicsPipeline(
|
|||
.pViewportState = &viewport_info,
|
||||
.pRasterizationState = &raster_state,
|
||||
.pMultisampleState = &multisampling,
|
||||
.pDepthStencilState = &depth_info,
|
||||
.pColorBlendState = &color_blending,
|
||||
.pDynamicState = &dynamic_info,
|
||||
.layout = *pipeline_layout,
|
||||
|
|
|
@ -39,18 +39,6 @@ struct GraphicsPipelineKey {
|
|||
vk::Format depth_format;
|
||||
vk::Format stencil_format;
|
||||
|
||||
struct {
|
||||
bool clip_disable : 1;
|
||||
bool depth_test_enable : 1;
|
||||
bool depth_write_enable : 1;
|
||||
bool depth_bounds_test_enable : 1;
|
||||
bool depth_bias_enable : 1;
|
||||
bool stencil_test_enable : 1;
|
||||
// Must be named to be zero-initialized.
|
||||
u8 _unused : 2;
|
||||
};
|
||||
vk::CompareOp depth_compare_op;
|
||||
|
||||
u32 num_samples;
|
||||
u32 mrt_mask;
|
||||
AmdGpu::PrimitiveType prim_type;
|
||||
|
@ -94,10 +82,6 @@ public:
|
|||
return key.mrt_mask;
|
||||
}
|
||||
|
||||
auto IsClipDisabled() const {
|
||||
return key.clip_disable;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsPrimitiveListTopology() const {
|
||||
return key.prim_type == AmdGpu::PrimitiveType::PointList ||
|
||||
key.prim_type == AmdGpu::PrimitiveType::LineList ||
|
||||
|
|
|
@ -247,6 +247,7 @@ bool Instance::CreateDevice() {
|
|||
add_extension(VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME);
|
||||
add_extension(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
|
||||
add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
|
||||
add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
|
||||
add_extension(VK_EXT_TOOLING_INFO_EXTENSION_NAME);
|
||||
const bool maintenance4 = add_extension(VK_KHR_MAINTENANCE_4_EXTENSION_NAME);
|
||||
|
||||
|
@ -276,6 +277,7 @@ bool Instance::CreateDevice() {
|
|||
shader_stencil_export = add_extension(VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME);
|
||||
image_load_store_lod = add_extension(VK_AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME);
|
||||
amd_gcn_shader = add_extension(VK_AMD_GCN_SHADER_EXTENSION_NAME);
|
||||
amd_shader_trinary_minmax = add_extension(VK_AMD_SHADER_TRINARY_MINMAX_EXTENSION_NAME);
|
||||
const bool calibrated_timestamps =
|
||||
TRACY_GPU_ENABLED ? add_extension(VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME) : false;
|
||||
|
||||
|
@ -379,6 +381,9 @@ bool Instance::CreateDevice() {
|
|||
vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT{
|
||||
.extendedDynamicState = true,
|
||||
},
|
||||
vk::PhysicalDeviceExtendedDynamicState2FeaturesEXT{
|
||||
.extendedDynamicState2 = true,
|
||||
},
|
||||
vk::PhysicalDeviceMaintenance4FeaturesKHR{
|
||||
.maintenance4 = true,
|
||||
},
|
||||
|
|
|
@ -84,6 +84,11 @@ public:
|
|||
return features.samplerAnisotropy;
|
||||
}
|
||||
|
||||
/// Returns true if depth bounds testing is supported
|
||||
bool IsDepthBoundsSupported() const {
|
||||
return features.depthBounds;
|
||||
}
|
||||
|
||||
/// Returns true when VK_EXT_custom_border_color is supported
|
||||
bool IsCustomBorderColorSupported() const {
|
||||
return custom_border_color;
|
||||
|
@ -145,6 +150,11 @@ public:
|
|||
return amd_gcn_shader;
|
||||
}
|
||||
|
||||
/// Returns true when VK_AMD_shader_trinary_minmax is supported.
|
||||
bool IsAmdShaderTrinaryMinMaxSupported() const {
|
||||
return amd_shader_trinary_minmax;
|
||||
}
|
||||
|
||||
/// Returns true when geometry shaders are supported by the device
|
||||
bool IsGeometryStageSupported() const {
|
||||
return features.geometryShader;
|
||||
|
@ -333,6 +343,7 @@ private:
|
|||
bool shader_stencil_export{};
|
||||
bool image_load_store_lod{};
|
||||
bool amd_gcn_shader{};
|
||||
bool amd_shader_trinary_minmax{};
|
||||
bool portability_subset{};
|
||||
};
|
||||
|
||||
|
|
|
@ -123,7 +123,7 @@ const Shader::RuntimeInfo& PipelineCache::BuildRuntimeInfo(Stage stage, LogicalS
|
|||
info.vs_info.emulate_depth_negative_one_to_one =
|
||||
!instance.IsDepthClipControlSupported() &&
|
||||
regs.clipper_control.clip_space == Liverpool::ClipSpace::MinusWToW;
|
||||
info.vs_info.clip_disable = graphics_key.clip_disable;
|
||||
info.vs_info.clip_disable = regs.IsClipDisabled();
|
||||
if (l_stage == LogicalStage::TessellationEval) {
|
||||
info.vs_info.tess_type = regs.tess_config.type;
|
||||
info.vs_info.tess_topology = regs.tess_config.topology;
|
||||
|
@ -201,6 +201,7 @@ PipelineCache::PipelineCache(const Instance& instance_, Scheduler& scheduler_,
|
|||
.support_legacy_vertex_attributes = instance_.IsLegacyVertexAttributesSupported(),
|
||||
.supports_image_load_store_lod = instance_.IsImageLoadStoreLodSupported(),
|
||||
.supports_native_cube_calc = instance_.IsAmdGcnShaderSupported(),
|
||||
.supports_trinary_minmax = instance_.IsAmdShaderTrinaryMinMaxSupported(),
|
||||
.supports_robust_buffer_access = instance_.IsRobustBufferAccess2Supported(),
|
||||
.needs_manual_interpolation = instance.IsFragmentShaderBarycentricSupported() &&
|
||||
instance.GetDriverID() == vk::DriverId::eNvidiaProprietary,
|
||||
|
@ -266,16 +267,6 @@ bool PipelineCache::RefreshGraphicsKey() {
|
|||
auto& regs = liverpool->regs;
|
||||
auto& key = graphics_key;
|
||||
|
||||
key.clip_disable =
|
||||
regs.clipper_control.clip_disable || regs.primitive_type == AmdGpu::PrimitiveType::RectList;
|
||||
key.depth_test_enable = regs.depth_control.depth_enable;
|
||||
key.depth_write_enable =
|
||||
regs.depth_control.depth_write_enable && !regs.depth_render_control.depth_clear_enable;
|
||||
key.depth_bounds_test_enable = regs.depth_control.depth_bounds_enable;
|
||||
key.depth_bias_enable = regs.polygon_control.NeedsBias();
|
||||
key.depth_compare_op = LiverpoolToVK::CompareOp(regs.depth_control.depth_func);
|
||||
key.stencil_test_enable = regs.depth_control.stencil_enable;
|
||||
|
||||
const auto depth_format = instance.GetSupportedFormat(
|
||||
LiverpoolToVK::DepthFormat(regs.depth_buffer.z_info.format,
|
||||
regs.depth_buffer.stencil_info.format),
|
||||
|
@ -284,13 +275,11 @@ bool PipelineCache::RefreshGraphicsKey() {
|
|||
key.depth_format = depth_format;
|
||||
} else {
|
||||
key.depth_format = vk::Format::eUndefined;
|
||||
key.depth_test_enable = false;
|
||||
}
|
||||
if (regs.depth_buffer.StencilValid()) {
|
||||
key.stencil_format = depth_format;
|
||||
} else {
|
||||
key.stencil_format = vk::Format::eUndefined;
|
||||
key.stencil_test_enable = false;
|
||||
}
|
||||
|
||||
key.prim_type = regs.primitive_type;
|
||||
|
|
|
@ -278,7 +278,6 @@ vk::UniqueInstance CreateInstance(Frontend::WindowSystemType window_type, bool e
|
|||
vk::Bool32 enable_force_barriers = vk::True;
|
||||
#ifdef __APPLE__
|
||||
const vk::Bool32 mvk_debug_mode = enable_crash_diagnostic ? vk::True : vk::False;
|
||||
constexpr vk::Bool32 mvk_use_mtlheap = vk::True;
|
||||
#endif
|
||||
|
||||
const std::array layer_setings = {
|
||||
|
@ -355,15 +354,6 @@ vk::UniqueInstance CreateInstance(Frontend::WindowSystemType window_type, bool e
|
|||
.valueCount = 1,
|
||||
.pValues = &mvk_debug_mode,
|
||||
},
|
||||
// Use MTLHeap to back device memory, which among other things allows us to
|
||||
// use VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT via memory aliasing.
|
||||
vk::LayerSettingEXT{
|
||||
.pLayerName = "MoltenVK",
|
||||
.pSettingName = "MVK_CONFIG_USE_MTLHEAP",
|
||||
.type = vk::LayerSettingTypeEXT::eBool32,
|
||||
.valueCount = 1,
|
||||
.pValues = &mvk_use_mtlheap,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
@ -946,82 +946,19 @@ void Rasterizer::UnmapMemory(VAddr addr, u64 size) {
|
|||
mapped_ranges -= boost::icl::interval<VAddr>::right_open(addr, addr + size);
|
||||
}
|
||||
|
||||
void Rasterizer::UpdateDynamicState(const GraphicsPipeline& pipeline) {
|
||||
UpdateViewportScissorState(pipeline);
|
||||
void Rasterizer::UpdateDynamicState(const GraphicsPipeline& pipeline) const {
|
||||
UpdateViewportScissorState();
|
||||
UpdateDepthStencilState();
|
||||
|
||||
auto& regs = liverpool->regs;
|
||||
const auto cmdbuf = scheduler.CommandBuffer();
|
||||
cmdbuf.setBlendConstants(®s.blend_constants.red);
|
||||
auto& dynamic_state = scheduler.GetDynamicState();
|
||||
dynamic_state.SetBlendConstants(&liverpool->regs.blend_constants.red);
|
||||
dynamic_state.SetColorWriteMasks(pipeline.GetWriteMasks());
|
||||
|
||||
if (instance.IsDynamicColorWriteMaskSupported()) {
|
||||
cmdbuf.setColorWriteMaskEXT(0, pipeline.GetWriteMasks());
|
||||
}
|
||||
if (regs.depth_control.depth_bounds_enable) {
|
||||
cmdbuf.setDepthBounds(regs.depth_bounds_min, regs.depth_bounds_max);
|
||||
}
|
||||
if (regs.polygon_control.enable_polygon_offset_front) {
|
||||
cmdbuf.setDepthBias(regs.poly_offset.front_offset, regs.poly_offset.depth_bias,
|
||||
regs.poly_offset.front_scale / 16.f);
|
||||
} else if (regs.polygon_control.enable_polygon_offset_back) {
|
||||
cmdbuf.setDepthBias(regs.poly_offset.back_offset, regs.poly_offset.depth_bias,
|
||||
regs.poly_offset.back_scale / 16.f);
|
||||
}
|
||||
|
||||
if (regs.depth_control.stencil_enable) {
|
||||
const auto front_fail_op =
|
||||
LiverpoolToVK::StencilOp(regs.stencil_control.stencil_fail_front);
|
||||
const auto front_pass_op =
|
||||
LiverpoolToVK::StencilOp(regs.stencil_control.stencil_zpass_front);
|
||||
const auto front_depth_fail_op =
|
||||
LiverpoolToVK::StencilOp(regs.stencil_control.stencil_zfail_front);
|
||||
const auto front_compare_op = LiverpoolToVK::CompareOp(regs.depth_control.stencil_ref_func);
|
||||
if (regs.depth_control.backface_enable) {
|
||||
const auto back_fail_op =
|
||||
LiverpoolToVK::StencilOp(regs.stencil_control.stencil_fail_back);
|
||||
const auto back_pass_op =
|
||||
LiverpoolToVK::StencilOp(regs.stencil_control.stencil_zpass_back);
|
||||
const auto back_depth_fail_op =
|
||||
LiverpoolToVK::StencilOp(regs.stencil_control.stencil_zfail_back);
|
||||
const auto back_compare_op =
|
||||
LiverpoolToVK::CompareOp(regs.depth_control.stencil_bf_func);
|
||||
cmdbuf.setStencilOpEXT(vk::StencilFaceFlagBits::eFront, front_fail_op, front_pass_op,
|
||||
front_depth_fail_op, front_compare_op);
|
||||
cmdbuf.setStencilOpEXT(vk::StencilFaceFlagBits::eBack, back_fail_op, back_pass_op,
|
||||
back_depth_fail_op, back_compare_op);
|
||||
} else {
|
||||
cmdbuf.setStencilOpEXT(vk::StencilFaceFlagBits::eFrontAndBack, front_fail_op,
|
||||
front_pass_op, front_depth_fail_op, front_compare_op);
|
||||
}
|
||||
|
||||
const auto front = regs.stencil_ref_front;
|
||||
const auto back = regs.stencil_ref_back;
|
||||
if (front.stencil_test_val == back.stencil_test_val) {
|
||||
cmdbuf.setStencilReference(vk::StencilFaceFlagBits::eFrontAndBack,
|
||||
front.stencil_test_val);
|
||||
} else {
|
||||
cmdbuf.setStencilReference(vk::StencilFaceFlagBits::eFront, front.stencil_test_val);
|
||||
cmdbuf.setStencilReference(vk::StencilFaceFlagBits::eBack, back.stencil_test_val);
|
||||
}
|
||||
|
||||
if (front.stencil_write_mask == back.stencil_write_mask) {
|
||||
cmdbuf.setStencilWriteMask(vk::StencilFaceFlagBits::eFrontAndBack,
|
||||
front.stencil_write_mask);
|
||||
} else {
|
||||
cmdbuf.setStencilWriteMask(vk::StencilFaceFlagBits::eFront, front.stencil_write_mask);
|
||||
cmdbuf.setStencilWriteMask(vk::StencilFaceFlagBits::eBack, back.stencil_write_mask);
|
||||
}
|
||||
|
||||
if (front.stencil_mask == back.stencil_mask) {
|
||||
cmdbuf.setStencilCompareMask(vk::StencilFaceFlagBits::eFrontAndBack,
|
||||
front.stencil_mask);
|
||||
} else {
|
||||
cmdbuf.setStencilCompareMask(vk::StencilFaceFlagBits::eFront, front.stencil_mask);
|
||||
cmdbuf.setStencilCompareMask(vk::StencilFaceFlagBits::eBack, back.stencil_mask);
|
||||
}
|
||||
}
|
||||
// Commit new dynamic state to the command buffer.
|
||||
dynamic_state.Commit(instance, scheduler.CommandBuffer());
|
||||
}
|
||||
|
||||
void Rasterizer::UpdateViewportScissorState(const GraphicsPipeline& pipeline) {
|
||||
void Rasterizer::UpdateViewportScissorState() const {
|
||||
const auto& regs = liverpool->regs;
|
||||
|
||||
const auto combined_scissor_value_tl = [](s16 scr, s16 win, s16 gen, s16 win_offset) {
|
||||
|
@ -1072,7 +1009,7 @@ void Rasterizer::UpdateViewportScissorState(const GraphicsPipeline& pipeline) {
|
|||
|
||||
const auto zoffset = vp_ctl.zoffset_enable ? vp.zoffset : 0.f;
|
||||
const auto zscale = vp_ctl.zscale_enable ? vp.zscale : 1.f;
|
||||
if (pipeline.IsClipDisabled()) {
|
||||
if (regs.IsClipDisabled()) {
|
||||
// In case if clipping is disabled we patch the shader to convert vertex position
|
||||
// from screen space coordinates to NDC by defining a render space as full hardware
|
||||
// window range [0..16383, 0..16383] and setting the viewport to its size.
|
||||
|
@ -1134,9 +1071,65 @@ void Rasterizer::UpdateViewportScissorState(const GraphicsPipeline& pipeline) {
|
|||
scissors.push_back(empty_scissor);
|
||||
}
|
||||
|
||||
const auto cmdbuf = scheduler.CommandBuffer();
|
||||
cmdbuf.setViewportWithCountEXT(viewports);
|
||||
cmdbuf.setScissorWithCountEXT(scissors);
|
||||
auto& dynamic_state = scheduler.GetDynamicState();
|
||||
dynamic_state.SetViewports(viewports);
|
||||
dynamic_state.SetScissors(scissors);
|
||||
}
|
||||
|
||||
void Rasterizer::UpdateDepthStencilState() const {
|
||||
const auto& regs = liverpool->regs;
|
||||
auto& dynamic_state = scheduler.GetDynamicState();
|
||||
|
||||
const auto depth_test_enabled =
|
||||
regs.depth_control.depth_enable && regs.depth_buffer.DepthValid();
|
||||
dynamic_state.SetDepthTestEnabled(depth_test_enabled);
|
||||
if (depth_test_enabled) {
|
||||
dynamic_state.SetDepthWriteEnabled(regs.depth_control.depth_write_enable &&
|
||||
!regs.depth_render_control.depth_clear_enable);
|
||||
dynamic_state.SetDepthCompareOp(LiverpoolToVK::CompareOp(regs.depth_control.depth_func));
|
||||
}
|
||||
|
||||
const auto depth_bounds_test_enabled = regs.depth_control.depth_bounds_enable;
|
||||
dynamic_state.SetDepthBoundsTestEnabled(depth_bounds_test_enabled);
|
||||
if (depth_bounds_test_enabled) {
|
||||
dynamic_state.SetDepthBounds(regs.depth_bounds_min, regs.depth_bounds_max);
|
||||
}
|
||||
|
||||
const auto depth_bias_enabled = regs.polygon_control.NeedsBias();
|
||||
dynamic_state.SetDepthBiasEnabled(depth_bias_enabled);
|
||||
if (depth_bias_enabled) {
|
||||
const bool front = regs.polygon_control.enable_polygon_offset_front;
|
||||
dynamic_state.SetDepthBias(
|
||||
front ? regs.poly_offset.front_offset : regs.poly_offset.back_offset,
|
||||
regs.poly_offset.depth_bias,
|
||||
(front ? regs.poly_offset.front_scale : regs.poly_offset.back_scale) / 16.f);
|
||||
}
|
||||
|
||||
const auto stencil_test_enabled =
|
||||
regs.depth_control.stencil_enable && regs.depth_buffer.StencilValid();
|
||||
dynamic_state.SetStencilTestEnabled(stencil_test_enabled);
|
||||
if (stencil_test_enabled) {
|
||||
const StencilOps front_ops{
|
||||
.fail_op = LiverpoolToVK::StencilOp(regs.stencil_control.stencil_fail_front),
|
||||
.pass_op = LiverpoolToVK::StencilOp(regs.stencil_control.stencil_zpass_front),
|
||||
.depth_fail_op = LiverpoolToVK::StencilOp(regs.stencil_control.stencil_zfail_front),
|
||||
.compare_op = LiverpoolToVK::CompareOp(regs.depth_control.stencil_ref_func),
|
||||
};
|
||||
const StencilOps back_ops = regs.depth_control.backface_enable ? StencilOps{
|
||||
.fail_op = LiverpoolToVK::StencilOp(regs.stencil_control.stencil_fail_back),
|
||||
.pass_op = LiverpoolToVK::StencilOp(regs.stencil_control.stencil_zpass_back),
|
||||
.depth_fail_op = LiverpoolToVK::StencilOp(regs.stencil_control.stencil_zfail_back),
|
||||
.compare_op = LiverpoolToVK::CompareOp(regs.depth_control.stencil_bf_func),
|
||||
} : front_ops;
|
||||
dynamic_state.SetStencilOps(front_ops, back_ops);
|
||||
|
||||
const auto front = regs.stencil_ref_front;
|
||||
const auto back =
|
||||
regs.depth_control.backface_enable ? regs.stencil_ref_back : regs.stencil_ref_front;
|
||||
dynamic_state.SetStencilReferences(front.stencil_test_val, back.stencil_test_val);
|
||||
dynamic_state.SetStencilWriteMasks(front.stencil_write_mask, back.stencil_write_mask);
|
||||
dynamic_state.SetStencilCompareMasks(front.stencil_mask, back.stencil_mask);
|
||||
}
|
||||
}
|
||||
|
||||
void Rasterizer::ScopeMarkerBegin(const std::string_view& str, bool from_guest) {
|
||||
|
|
|
@ -75,8 +75,9 @@ private:
|
|||
void DepthStencilCopy(bool is_depth, bool is_stencil);
|
||||
void EliminateFastClear();
|
||||
|
||||
void UpdateDynamicState(const GraphicsPipeline& pipeline);
|
||||
void UpdateViewportScissorState(const GraphicsPipeline& pipeline);
|
||||
void UpdateDynamicState(const GraphicsPipeline& pipeline) const;
|
||||
void UpdateViewportScissorState() const;
|
||||
void UpdateDepthStencilState() const;
|
||||
|
||||
bool FilterDraw();
|
||||
|
||||
|
|
|
@ -97,6 +97,9 @@ void Scheduler::AllocateWorkerCommandBuffers() {
|
|||
ASSERT_MSG(begin_result == vk::Result::eSuccess, "Failed to begin command buffer: {}",
|
||||
vk::to_string(begin_result));
|
||||
|
||||
// Invalidate dynamic state so it gets applied to the new command buffer.
|
||||
dynamic_state.Invalidate();
|
||||
|
||||
#if TRACY_GPU_ENABLED
|
||||
auto* profiler_ctx = instance.GetProfilerContext();
|
||||
if (profiler_ctx) {
|
||||
|
@ -164,4 +167,137 @@ void Scheduler::SubmitExecution(SubmitInfo& info) {
|
|||
}
|
||||
}
|
||||
|
||||
void DynamicState::Commit(const Instance& instance, const vk::CommandBuffer& cmdbuf) {
|
||||
if (dirty_state.viewports) {
|
||||
dirty_state.viewports = false;
|
||||
cmdbuf.setViewportWithCountEXT(viewports);
|
||||
}
|
||||
if (dirty_state.scissors) {
|
||||
dirty_state.scissors = false;
|
||||
cmdbuf.setScissorWithCountEXT(scissors);
|
||||
}
|
||||
if (dirty_state.depth_test_enabled) {
|
||||
dirty_state.depth_test_enabled = false;
|
||||
cmdbuf.setDepthTestEnableEXT(depth_test_enabled);
|
||||
}
|
||||
if (dirty_state.depth_write_enabled) {
|
||||
dirty_state.depth_write_enabled = false;
|
||||
// Note that this must be set in a command buffer even if depth test is disabled.
|
||||
cmdbuf.setDepthWriteEnableEXT(depth_write_enabled);
|
||||
}
|
||||
if (depth_test_enabled && dirty_state.depth_compare_op) {
|
||||
dirty_state.depth_compare_op = false;
|
||||
cmdbuf.setDepthCompareOpEXT(depth_compare_op);
|
||||
}
|
||||
if (dirty_state.depth_bounds_test_enabled) {
|
||||
dirty_state.depth_bounds_test_enabled = false;
|
||||
if (instance.IsDepthBoundsSupported()) {
|
||||
cmdbuf.setDepthBoundsTestEnableEXT(depth_bounds_test_enabled);
|
||||
}
|
||||
}
|
||||
if (depth_bounds_test_enabled && dirty_state.depth_bounds) {
|
||||
dirty_state.depth_bounds = false;
|
||||
if (instance.IsDepthBoundsSupported()) {
|
||||
cmdbuf.setDepthBounds(depth_bounds_min, depth_bounds_max);
|
||||
}
|
||||
}
|
||||
if (dirty_state.depth_bias_enabled) {
|
||||
dirty_state.depth_bias_enabled = false;
|
||||
cmdbuf.setDepthBiasEnableEXT(depth_bias_enabled);
|
||||
}
|
||||
if (depth_bias_enabled && dirty_state.depth_bias) {
|
||||
dirty_state.depth_bias = false;
|
||||
cmdbuf.setDepthBias(depth_bias_constant, depth_bias_clamp, depth_bias_slope);
|
||||
}
|
||||
if (dirty_state.stencil_test_enabled) {
|
||||
dirty_state.stencil_test_enabled = false;
|
||||
cmdbuf.setStencilTestEnableEXT(stencil_test_enabled);
|
||||
}
|
||||
if (stencil_test_enabled) {
|
||||
if (dirty_state.stencil_front_ops && dirty_state.stencil_back_ops &&
|
||||
stencil_front_ops == stencil_back_ops) {
|
||||
dirty_state.stencil_front_ops = false;
|
||||
dirty_state.stencil_back_ops = false;
|
||||
cmdbuf.setStencilOpEXT(vk::StencilFaceFlagBits::eFrontAndBack,
|
||||
stencil_front_ops.fail_op, stencil_front_ops.pass_op,
|
||||
stencil_front_ops.depth_fail_op, stencil_front_ops.compare_op);
|
||||
} else {
|
||||
if (dirty_state.stencil_front_ops) {
|
||||
dirty_state.stencil_front_ops = false;
|
||||
cmdbuf.setStencilOpEXT(vk::StencilFaceFlagBits::eFront, stencil_front_ops.fail_op,
|
||||
stencil_front_ops.pass_op, stencil_front_ops.depth_fail_op,
|
||||
stencil_front_ops.compare_op);
|
||||
}
|
||||
if (dirty_state.stencil_back_ops) {
|
||||
dirty_state.stencil_back_ops = false;
|
||||
cmdbuf.setStencilOpEXT(vk::StencilFaceFlagBits::eBack, stencil_back_ops.fail_op,
|
||||
stencil_back_ops.pass_op, stencil_back_ops.depth_fail_op,
|
||||
stencil_back_ops.compare_op);
|
||||
}
|
||||
}
|
||||
if (dirty_state.stencil_front_reference && dirty_state.stencil_back_reference &&
|
||||
stencil_front_reference == stencil_back_reference) {
|
||||
dirty_state.stencil_front_reference = false;
|
||||
dirty_state.stencil_back_reference = false;
|
||||
cmdbuf.setStencilReference(vk::StencilFaceFlagBits::eFrontAndBack,
|
||||
stencil_front_reference);
|
||||
} else {
|
||||
if (dirty_state.stencil_front_reference) {
|
||||
dirty_state.stencil_front_reference = false;
|
||||
cmdbuf.setStencilReference(vk::StencilFaceFlagBits::eFront,
|
||||
stencil_front_reference);
|
||||
}
|
||||
if (dirty_state.stencil_back_reference) {
|
||||
dirty_state.stencil_back_reference = false;
|
||||
cmdbuf.setStencilReference(vk::StencilFaceFlagBits::eBack, stencil_back_reference);
|
||||
}
|
||||
}
|
||||
if (dirty_state.stencil_front_write_mask && dirty_state.stencil_back_write_mask &&
|
||||
stencil_front_write_mask == stencil_back_write_mask) {
|
||||
dirty_state.stencil_front_write_mask = false;
|
||||
dirty_state.stencil_back_write_mask = false;
|
||||
cmdbuf.setStencilWriteMask(vk::StencilFaceFlagBits::eFrontAndBack,
|
||||
stencil_front_write_mask);
|
||||
} else {
|
||||
if (dirty_state.stencil_front_write_mask) {
|
||||
dirty_state.stencil_front_write_mask = false;
|
||||
cmdbuf.setStencilWriteMask(vk::StencilFaceFlagBits::eFront,
|
||||
stencil_front_write_mask);
|
||||
}
|
||||
if (dirty_state.stencil_back_write_mask) {
|
||||
dirty_state.stencil_back_write_mask = false;
|
||||
cmdbuf.setStencilWriteMask(vk::StencilFaceFlagBits::eBack, stencil_back_write_mask);
|
||||
}
|
||||
}
|
||||
if (dirty_state.stencil_front_compare_mask && dirty_state.stencil_back_compare_mask &&
|
||||
stencil_front_compare_mask == stencil_back_compare_mask) {
|
||||
dirty_state.stencil_front_compare_mask = false;
|
||||
dirty_state.stencil_back_compare_mask = false;
|
||||
cmdbuf.setStencilCompareMask(vk::StencilFaceFlagBits::eFrontAndBack,
|
||||
stencil_front_compare_mask);
|
||||
} else {
|
||||
if (dirty_state.stencil_front_compare_mask) {
|
||||
dirty_state.stencil_front_compare_mask = false;
|
||||
cmdbuf.setStencilCompareMask(vk::StencilFaceFlagBits::eFront,
|
||||
stencil_front_compare_mask);
|
||||
}
|
||||
if (dirty_state.stencil_back_compare_mask) {
|
||||
dirty_state.stencil_back_compare_mask = false;
|
||||
cmdbuf.setStencilCompareMask(vk::StencilFaceFlagBits::eBack,
|
||||
stencil_back_compare_mask);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dirty_state.blend_constants) {
|
||||
dirty_state.blend_constants = false;
|
||||
cmdbuf.setBlendConstants(blend_constants);
|
||||
}
|
||||
if (dirty_state.color_write_masks) {
|
||||
dirty_state.color_write_masks = false;
|
||||
if (instance.IsDynamicColorWriteMaskSupported()) {
|
||||
cmdbuf.setColorWriteMaskEXT(0, color_write_masks);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Vulkan
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <boost/container/static_vector.hpp>
|
||||
#include "common/types.h"
|
||||
#include "common/unique_function.h"
|
||||
#include "video_core/amdgpu/liverpool.h"
|
||||
#include "video_core/renderer_vulkan/vk_master_semaphore.h"
|
||||
#include "video_core/renderer_vulkan/vk_resource_pool.h"
|
||||
|
||||
|
@ -55,6 +56,219 @@ struct SubmitInfo {
|
|||
}
|
||||
};
|
||||
|
||||
using Viewports = boost::container::static_vector<vk::Viewport, AmdGpu::Liverpool::NumViewports>;
|
||||
using Scissors = boost::container::static_vector<vk::Rect2D, AmdGpu::Liverpool::NumViewports>;
|
||||
using ColorWriteMasks = std::array<vk::ColorComponentFlags, AmdGpu::Liverpool::NumColorBuffers>;
|
||||
struct StencilOps {
|
||||
vk::StencilOp fail_op{};
|
||||
vk::StencilOp pass_op{};
|
||||
vk::StencilOp depth_fail_op{};
|
||||
vk::CompareOp compare_op{};
|
||||
|
||||
bool operator==(const StencilOps& other) const {
|
||||
return fail_op == other.fail_op && pass_op == other.pass_op &&
|
||||
depth_fail_op == other.depth_fail_op && compare_op == other.compare_op;
|
||||
}
|
||||
};
|
||||
struct DynamicState {
|
||||
struct {
|
||||
bool viewports : 1;
|
||||
bool scissors : 1;
|
||||
|
||||
bool depth_test_enabled : 1;
|
||||
bool depth_write_enabled : 1;
|
||||
bool depth_compare_op : 1;
|
||||
|
||||
bool depth_bounds_test_enabled : 1;
|
||||
bool depth_bounds : 1;
|
||||
|
||||
bool depth_bias_enabled : 1;
|
||||
bool depth_bias : 1;
|
||||
|
||||
bool stencil_test_enabled : 1;
|
||||
bool stencil_front_ops : 1;
|
||||
bool stencil_front_reference : 1;
|
||||
bool stencil_front_write_mask : 1;
|
||||
bool stencil_front_compare_mask : 1;
|
||||
bool stencil_back_ops : 1;
|
||||
bool stencil_back_reference : 1;
|
||||
bool stencil_back_write_mask : 1;
|
||||
bool stencil_back_compare_mask : 1;
|
||||
|
||||
bool blend_constants : 1;
|
||||
bool color_write_masks : 1;
|
||||
} dirty_state{};
|
||||
|
||||
Viewports viewports{};
|
||||
Scissors scissors{};
|
||||
|
||||
bool depth_test_enabled{};
|
||||
bool depth_write_enabled{};
|
||||
vk::CompareOp depth_compare_op{};
|
||||
|
||||
bool depth_bounds_test_enabled{};
|
||||
float depth_bounds_min{};
|
||||
float depth_bounds_max{};
|
||||
|
||||
bool depth_bias_enabled{};
|
||||
float depth_bias_constant{};
|
||||
float depth_bias_clamp{};
|
||||
float depth_bias_slope{};
|
||||
|
||||
bool stencil_test_enabled{};
|
||||
StencilOps stencil_front_ops{};
|
||||
u32 stencil_front_reference{};
|
||||
u32 stencil_front_write_mask{};
|
||||
u32 stencil_front_compare_mask{};
|
||||
StencilOps stencil_back_ops{};
|
||||
u32 stencil_back_reference{};
|
||||
u32 stencil_back_write_mask{};
|
||||
u32 stencil_back_compare_mask{};
|
||||
|
||||
float blend_constants[4]{};
|
||||
ColorWriteMasks color_write_masks{};
|
||||
|
||||
/// Commits the dynamic state to the provided command buffer.
|
||||
void Commit(const Instance& instance, const vk::CommandBuffer& cmdbuf);
|
||||
|
||||
/// Invalidates all dynamic state to be flushed into the next command buffer.
|
||||
void Invalidate() {
|
||||
std::memset(&dirty_state, 0xFF, sizeof(dirty_state));
|
||||
}
|
||||
|
||||
void SetViewports(const Viewports& viewports_) {
|
||||
if (!std::ranges::equal(viewports, viewports_)) {
|
||||
viewports = viewports_;
|
||||
dirty_state.viewports = true;
|
||||
}
|
||||
}
|
||||
|
||||
void SetScissors(const Scissors& scissors_) {
|
||||
if (!std::ranges::equal(scissors, scissors_)) {
|
||||
scissors = scissors_;
|
||||
dirty_state.scissors = true;
|
||||
}
|
||||
}
|
||||
|
||||
void SetDepthTestEnabled(const bool enabled) {
|
||||
if (depth_test_enabled != enabled) {
|
||||
depth_test_enabled = enabled;
|
||||
dirty_state.depth_test_enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
void SetDepthWriteEnabled(const bool enabled) {
|
||||
if (depth_write_enabled != enabled) {
|
||||
depth_write_enabled = enabled;
|
||||
dirty_state.depth_write_enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
void SetDepthCompareOp(const vk::CompareOp compare_op) {
|
||||
if (depth_compare_op != compare_op) {
|
||||
depth_compare_op = compare_op;
|
||||
dirty_state.depth_compare_op = true;
|
||||
}
|
||||
}
|
||||
|
||||
void SetDepthBoundsTestEnabled(const bool enabled) {
|
||||
if (depth_bounds_test_enabled != enabled) {
|
||||
depth_bounds_test_enabled = enabled;
|
||||
dirty_state.depth_bounds_test_enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
void SetDepthBounds(const float min, const float max) {
|
||||
if (depth_bounds_min != min || depth_bounds_max != max) {
|
||||
depth_bounds_min = min;
|
||||
depth_bounds_max = max;
|
||||
dirty_state.depth_bounds = true;
|
||||
}
|
||||
}
|
||||
|
||||
void SetDepthBiasEnabled(const bool enabled) {
|
||||
if (depth_bias_enabled != enabled) {
|
||||
depth_bias_enabled = enabled;
|
||||
dirty_state.depth_bias_enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
void SetDepthBias(const float constant, const float clamp, const float slope) {
|
||||
if (depth_bias_constant != constant || depth_bias_clamp != clamp ||
|
||||
depth_bias_slope != slope) {
|
||||
depth_bias_constant = constant;
|
||||
depth_bias_clamp = clamp;
|
||||
depth_bias_slope = slope;
|
||||
dirty_state.depth_bias = true;
|
||||
}
|
||||
}
|
||||
|
||||
void SetStencilTestEnabled(const bool enabled) {
|
||||
if (stencil_test_enabled != enabled) {
|
||||
stencil_test_enabled = enabled;
|
||||
dirty_state.stencil_test_enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
void SetStencilOps(const StencilOps& front_ops, const StencilOps& back_ops) {
|
||||
if (stencil_front_ops != front_ops) {
|
||||
stencil_front_ops = front_ops;
|
||||
dirty_state.stencil_front_ops = true;
|
||||
}
|
||||
if (stencil_back_ops != back_ops) {
|
||||
stencil_back_ops = back_ops;
|
||||
dirty_state.stencil_back_ops = true;
|
||||
}
|
||||
}
|
||||
|
||||
void SetStencilReferences(const u32 front_reference, const u32 back_reference) {
|
||||
if (stencil_front_reference != front_reference) {
|
||||
stencil_front_reference = front_reference;
|
||||
dirty_state.stencil_front_reference = true;
|
||||
}
|
||||
if (stencil_back_reference != back_reference) {
|
||||
stencil_back_reference = back_reference;
|
||||
dirty_state.stencil_back_reference = true;
|
||||
}
|
||||
}
|
||||
|
||||
void SetStencilWriteMasks(const u32 front_write_mask, const u32 back_write_mask) {
|
||||
if (stencil_front_write_mask != front_write_mask) {
|
||||
stencil_front_write_mask = front_write_mask;
|
||||
dirty_state.stencil_front_write_mask = true;
|
||||
}
|
||||
if (stencil_back_write_mask != back_write_mask) {
|
||||
stencil_back_write_mask = back_write_mask;
|
||||
dirty_state.stencil_back_write_mask = true;
|
||||
}
|
||||
}
|
||||
|
||||
void SetStencilCompareMasks(const u32 front_compare_mask, const u32 back_compare_mask) {
|
||||
if (stencil_front_compare_mask != front_compare_mask) {
|
||||
stencil_front_compare_mask = front_compare_mask;
|
||||
dirty_state.stencil_front_compare_mask = true;
|
||||
}
|
||||
if (stencil_back_compare_mask != back_compare_mask) {
|
||||
stencil_back_compare_mask = back_compare_mask;
|
||||
dirty_state.stencil_back_compare_mask = true;
|
||||
}
|
||||
}
|
||||
|
||||
void SetBlendConstants(const float blend_constants_[4]) {
|
||||
if (!std::equal(blend_constants, std::end(blend_constants), blend_constants_)) {
|
||||
std::memcpy(blend_constants, blend_constants_, sizeof(blend_constants));
|
||||
dirty_state.blend_constants = true;
|
||||
}
|
||||
}
|
||||
|
||||
void SetColorWriteMasks(const ColorWriteMasks& color_write_masks_) {
|
||||
if (!std::ranges::equal(color_write_masks, color_write_masks_)) {
|
||||
color_write_masks = color_write_masks_;
|
||||
dirty_state.color_write_masks = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class Scheduler {
|
||||
public:
|
||||
explicit Scheduler(const Instance& instance);
|
||||
|
@ -81,6 +295,10 @@ public:
|
|||
return render_state;
|
||||
}
|
||||
|
||||
DynamicState& GetDynamicState() {
|
||||
return dynamic_state;
|
||||
}
|
||||
|
||||
/// Returns the current command buffer.
|
||||
vk::CommandBuffer CommandBuffer() const {
|
||||
return current_cmdbuf;
|
||||
|
@ -125,6 +343,7 @@ private:
|
|||
};
|
||||
std::queue<PendingOp> pending_ops;
|
||||
RenderState render_state;
|
||||
DynamicState dynamic_state;
|
||||
bool is_rendering = false;
|
||||
tracy::VkCtxScope* profiler_scope{};
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue