From 8122f8ecbfc8d8a26ef616530befd381057ec59e Mon Sep 17 00:00:00 2001 From: kalaposfos13 <153381648+kalaposfos13@users.noreply.github.com> Date: Sat, 29 Mar 2025 11:30:59 +0100 Subject: [PATCH 01/34] Diplay PR actions as `pr-{number}-{branchname}` (#2713) --- CMakeLists.txt | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bd458f04e..804d5528f 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -114,6 +114,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 +124,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 +136,38 @@ 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}) + set(GITHUB_HEAD_REF "$ENV{GITHUB_HEAD_REF}") + else() + set(GITHUB_HEAD_REF "") + endif() + + if (DEFINED ENV{GITHUB_REF}) + string(REGEX REPLACE "^refs/[^/]*/" "" GITHUB_BRANCH "$ENV{GITHUB_REF}") + else() + set(GITHUB_BRANCH "") + endif() + + if (DEFINED ENV{GITHUB_EVENT_PATH}) + file(READ "$ENV{GITHUB_EVENT_PATH}" GITHUB_EVENT_JSON) + string(JSON PR_NUMBER GET ${GITHUB_EVENT_JSON} "number") + else() + 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}") else() message("couldn't find branch") set(GIT_BRANCH "detached-head") From 064c3161c3e0a4ddc2cbdf70fe4d307ad9d188c1 Mon Sep 17 00:00:00 2001 From: Missake212 Date: Sat, 29 Mar 2025 15:58:10 +0000 Subject: [PATCH 02/34] real fix this time ? (#2717) --- src/qt_gui/gui_context_menus.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qt_gui/gui_context_menus.h b/src/qt_gui/gui_context_menus.h index c13388bbc..b5732d0ca 100644 --- a/src/qt_gui/gui_context_menus.h +++ b/src/qt_gui/gui_context_menus.h @@ -140,12 +140,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"), From faae1218fa0b590e4e3f55b7d41780eec8c281f9 Mon Sep 17 00:00:00 2001 From: Missake212 Date: Sat, 29 Mar 2025 22:50:22 +0000 Subject: [PATCH 03/34] Getting rid of the "Separate Update Folder" option (#2719) * real fix this time ? * should be all of it * Update en_US.ts --- src/common/config.cpp | 12 ------------ src/common/config.h | 2 -- src/qt_gui/settings_dialog.cpp | 6 ------ src/qt_gui/settings_dialog.ui | 7 ------- src/qt_gui/translations/en_US.ts | 8 -------- 5 files changed, 35 deletions(-) diff --git a/src/common/config.cpp b/src/common/config.cpp index d1bb89897..2657cd12a 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -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; } @@ -781,7 +772,6 @@ void load(const std::filesystem::path& path) { isAutoUpdate = toml::find_or(general, "autoUpdate", false); isAlwaysShowChangelog = toml::find_or(general, "alwaysShowChangelog", false); isSideTrophy = toml::find_or(general, "sideTrophy", "right"); - separateupdatefolder = toml::find_or(general, "separateUpdateEnabled", false); compatibilityData = toml::find_or(general, "compatibilityEnabled", false); checkCompatibilityOnStartup = toml::find_or(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; @@ -1150,7 +1139,6 @@ void setDefaultValues() { emulator_language = "en_US"; m_language = 1; gpuId = -1; - separateupdatefolder = false; compatibilityData = false; checkCompatibilityOnStartup = false; backgroundImageOpacity = 50; diff --git a/src/common/config.h b/src/common/config.h index d040aa337..aba23621c 100644 --- a/src/common/config.h +++ b/src/common/config.h @@ -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& dirs_config); void setAllGameInstallDirs(const std::vector& dirs_config); void setSaveDataPath(const std::filesystem::path& path); diff --git a/src/qt_gui/settings_dialog.cpp b/src/qt_gui/settings_dialog.cpp index 383cad8fa..25c27fef3 100644 --- a/src/qt_gui/settings_dialog.cpp +++ b/src/qt_gui/settings_dialog.cpp @@ -318,7 +318,6 @@ SettingsDialog::SettingsDialog(std::span 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(data, "General", "separateUpdateEnabled", false)); ui->gameSizeCheckBox->setChecked(toml::find_or(data, "GUI", "loadGameSizeEnabled", true)); ui->showSplashCheckBox->setChecked(toml::find_or(data, "General", "showSplash", false)); QString translatedText_logType = logTypeMap.key(QString::fromStdString(Config::getLogType())); @@ -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()); diff --git a/src/qt_gui/settings_dialog.ui b/src/qt_gui/settings_dialog.ui index 5600a0db7..20e26775d 100644 --- a/src/qt_gui/settings_dialog.ui +++ b/src/qt_gui/settings_dialog.ui @@ -135,13 +135,6 @@ 10 - - - - Enable Separate Update Folder - - - diff --git a/src/qt_gui/translations/en_US.ts b/src/qt_gui/translations/en_US.ts index 28d31b200..780f089e8 100644 --- a/src/qt_gui/translations/en_US.ts +++ b/src/qt_gui/translations/en_US.ts @@ -1474,10 +1474,6 @@ Emulator Emulator - - Enable Separate Update Folder - Enable Separate Update Folder - Default tab when opening settings Default tab when opening settings @@ -1742,10 +1738,6 @@ Emulator Language:\nSets the language of the emulator's user interface. Emulator Language:\nSets the language of the emulator's user interface. - - 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. - 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. - Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. From bad82e72046b137d6592d7ebfb769d4ec3b1e257 Mon Sep 17 00:00:00 2001 From: DanielSvoboda Date: Sat, 29 Mar 2025 19:50:41 -0300 Subject: [PATCH 04/34] Fix Translation on Button in MainWindow (#2720) --- src/qt_gui/main_window.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt_gui/main_window.cpp b/src/qt_gui/main_window.cpp index 5d8f8e717..072ad70e5 100644 --- a/src/qt_gui/main_window.cpp +++ b/src/qt_gui/main_window.cpp @@ -45,11 +45,11 @@ MainWindow::~MainWindow() { bool MainWindow::Init() { auto start = std::chrono::steady_clock::now(); // setup ui + LoadTranslation(); AddUiWidgets(); CreateActions(); CreateRecentGameActions(); ConfigureGuiFromSettings(); - LoadTranslation(); CreateDockWindows(); CreateConnects(); SetLastUsedTheme(); From 99b90cbd5c5b8e24b0aa45630a4f8658267e8a6f Mon Sep 17 00:00:00 2001 From: Stephen Miller <56742918+StevenMiller123@users.noreply.github.com> Date: Sat, 29 Mar 2025 18:27:33 -0500 Subject: [PATCH 05/34] Minor libkernel changes (#2721) * sceKernelDebugOutText Some homebrew use this for logging, and these logs do show up in console klogs. I wasn't sure where the most suitable place for this function would be, so I made a separate file for these debug functions. * Implement kernel exit Some homebrew I have use this exit when an error occurs. Since actually closing the emulator isn't implemented yet, I've used an unreachable message that logs the status code. I've placed it in process.cpp for now, let me know if I should change that. * Improved implementations for sceKernelDebugRaiseException functions These functions take in two parameters, an error code and some other value that I have no idea what is for. If that second parameter is not zero, they return ORBIS_KERNEL_ERROR_EINVAL before any calls to mdbg_service. These improved implementations add the early error return and a message with the error code to the unreachable. * Add missing exports Homebrew apps like to use these kernel exports of posix functions instead. * Clang --- CMakeLists.txt | 2 ++ src/core/libraries/kernel/debug.cpp | 20 +++++++++++++++++++ src/core/libraries/kernel/debug.h | 14 +++++++++++++ src/core/libraries/kernel/kernel.cpp | 2 ++ src/core/libraries/kernel/process.cpp | 6 ++++++ .../libraries/kernel/threads/exception.cpp | 17 +++++++++++----- .../libraries/kernel/threads/pthread_spec.cpp | 5 +++++ 7 files changed, 61 insertions(+), 5 deletions(-) create mode 100644 src/core/libraries/kernel/debug.cpp create mode 100644 src/core/libraries/kernel/debug.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 804d5528f..73a0e2c4c 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -324,6 +324,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 diff --git a/src/core/libraries/kernel/debug.cpp b/src/core/libraries/kernel/debug.cpp new file mode 100644 index 000000000..0de67b8b5 --- /dev/null +++ b/src/core/libraries/kernel/debug.cpp @@ -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 \ No newline at end of file diff --git a/src/core/libraries/kernel/debug.h b/src/core/libraries/kernel/debug.h new file mode 100644 index 000000000..177046862 --- /dev/null +++ b/src/core/libraries/kernel/debug.h @@ -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 \ No newline at end of file diff --git a/src/core/libraries/kernel/kernel.cpp b/src/core/libraries/kernel/kernel.cpp index 9227cf45a..33602bfe8 100644 --- a/src/core/libraries/kernel/kernel.cpp +++ b/src/core/libraries/kernel/kernel.cpp @@ -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); diff --git a/src/core/libraries/kernel/process.cpp b/src/core/libraries/kernel/process.cpp index d61ee37ac..02f8a538d 100644 --- a/src/core/libraries/kernel/process.cpp +++ b/src/core/libraries/kernel/process.cpp @@ -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 diff --git a/src/core/libraries/kernel/threads/exception.cpp b/src/core/libraries/kernel/threads/exception.cpp index 5e2f35d69..e257cbea0 100644 --- a/src/core/libraries/kernel/threads/exception.cpp +++ b/src/core/libraries/kernel/threads/exception.cpp @@ -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); diff --git a/src/core/libraries/kernel/threads/pthread_spec.cpp b/src/core/libraries/kernel/threads/pthread_spec.cpp index 9e625da32..b36e302d4 100644 --- a/src/core/libraries/kernel/threads/pthread_spec.cpp +++ b/src/core/libraries/kernel/threads/pthread_spec.cpp @@ -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)); From 3f33d218b35fcf7af7ca445c80a1f711eb77e474 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Sun, 30 Mar 2025 01:28:02 +0200 Subject: [PATCH 06/34] New Crowdin updates (#2715) * New translations en_us.ts (Italian) * New translations en_us.ts (Ukrainian) * New translations en_us.ts (Ukrainian) --- src/qt_gui/translations/it_IT.ts | 20 ++++++++++---------- src/qt_gui/translations/uk_UA.ts | 26 +++++++++++++------------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/qt_gui/translations/it_IT.ts b/src/qt_gui/translations/it_IT.ts index af321bd92..895908193 100644 --- a/src/qt_gui/translations/it_IT.ts +++ b/src/qt_gui/translations/it_IT.ts @@ -1409,43 +1409,43 @@ Play - Play + Riproduci Pause - Pause + Pausa Stop - Stop + Arresta Restart - Restart + Riavvia Full Screen - Full Screen + Schermo Intero Controllers - Controllers + Controller Keyboard - Keyboard + Tastiera Refresh List - Refresh List + Aggiorna Lista Resume - Resume + Riprendi Show Labels Under Icons - Show Labels Under Icons + Mostra Etichette Sotto Icone diff --git a/src/qt_gui/translations/uk_UA.ts b/src/qt_gui/translations/uk_UA.ts index 890fa163e..5e2572449 100644 --- a/src/qt_gui/translations/uk_UA.ts +++ b/src/qt_gui/translations/uk_UA.ts @@ -1277,11 +1277,11 @@ Trophy Viewer - Trophy Viewer + Переглядач трофеїв No games found. Please add your games to your library first. - No games found. Please add your games to your library first. + Не знайдено жодної гри. Будь ласка, спочатку додайте свої ігри до бібліотеки. Search... @@ -1409,43 +1409,43 @@ Play - Play + Грати Pause - Pause + Пауза Stop - Stop + Стоп Restart - Restart + Перезапуск Full Screen - Full Screen + На повний екран Controllers - Controllers + Контролери Keyboard - Keyboard + Клавіатура Refresh List - Refresh List + Оновити список Resume - Resume + Продовжити Show Labels Under Icons - Show Labels Under Icons + Показати найменування під іконками @@ -2067,7 +2067,7 @@ Select Game: - Select Game: + Виберіть гру: Progress From f1e0a096d54ca2db48da67fb5210b3542fc1b858 Mon Sep 17 00:00:00 2001 From: kalaposfos13 <153381648+kalaposfos13@users.noreply.github.com> Date: Sun, 30 Mar 2025 14:37:00 +0200 Subject: [PATCH 07/34] casually testing in production (#2718) --- CMakeLists.txt | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 73a0e2c4c..021167d58 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -143,22 +143,26 @@ if (GIT_REMOTE_RESULT OR GIT_REMOTE_NAME STREQUAL "") set(GIT_REMOTE_NAME "origin") # Retrieve environment variables - if (DEFINED ENV{GITHUB_HEAD_REF}) + 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}) + 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 "") - endif() - - if (DEFINED ENV{GITHUB_EVENT_PATH}) - file(READ "$ENV{GITHUB_EVENT_PATH}" GITHUB_EVENT_JSON) - string(JSON PR_NUMBER GET ${GITHUB_EVENT_JSON} "number") - else() set(PR_NUMBER "") endif() @@ -168,6 +172,12 @@ if (GIT_REMOTE_RESULT OR GIT_REMOTE_NAME 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") From a707d31a4c23fdd8aefb146ae04d25ecbca246d0 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Sun, 30 Mar 2025 15:37:16 +0300 Subject: [PATCH 08/34] New Crowdin updates (#2722) * New translations en_us.ts (Albanian) * New translations en_us.ts (Swedish) * New translations en_us.ts (Polish) * New translations en_us.ts (Portuguese, Brazilian) * New translations en_us.ts (Spanish) * New translations en_us.ts (Romanian) * New translations en_us.ts (French) * New translations en_us.ts (Arabic) * New translations en_us.ts (Danish) * New translations en_us.ts (German) * New translations en_us.ts (Greek) * New translations en_us.ts (Finnish) * New translations en_us.ts (Hungarian) * New translations en_us.ts (Italian) * New translations en_us.ts (Japanese) * New translations en_us.ts (Korean) * New translations en_us.ts (Lithuanian) * New translations en_us.ts (Dutch) * New translations en_us.ts (Portuguese) * New translations en_us.ts (Russian) * New translations en_us.ts (Turkish) * New translations en_us.ts (Ukrainian) * New translations en_us.ts (Chinese Simplified) * New translations en_us.ts (Chinese Traditional) * New translations en_us.ts (Vietnamese) * New translations en_us.ts (Indonesian) * New translations en_us.ts (Persian) * New translations en_us.ts (Norwegian Bokmal) * New translations en_us.ts (Arabic) --- src/qt_gui/translations/ar_SA.ts | 56 ++++++++++++++------------------ src/qt_gui/translations/da_DK.ts | 8 ----- src/qt_gui/translations/de_DE.ts | 8 ----- src/qt_gui/translations/el_GR.ts | 8 ----- src/qt_gui/translations/es_ES.ts | 8 ----- src/qt_gui/translations/fa_IR.ts | 8 ----- src/qt_gui/translations/fi_FI.ts | 8 ----- src/qt_gui/translations/fr_FR.ts | 8 ----- src/qt_gui/translations/hu_HU.ts | 8 ----- src/qt_gui/translations/id_ID.ts | 8 ----- src/qt_gui/translations/it_IT.ts | 8 ----- src/qt_gui/translations/ja_JP.ts | 8 ----- src/qt_gui/translations/ko_KR.ts | 8 ----- src/qt_gui/translations/lt_LT.ts | 8 ----- src/qt_gui/translations/nb_NO.ts | 8 ----- src/qt_gui/translations/nl_NL.ts | 8 ----- src/qt_gui/translations/pl_PL.ts | 8 ----- src/qt_gui/translations/pt_BR.ts | 8 ----- src/qt_gui/translations/pt_PT.ts | 8 ----- src/qt_gui/translations/ro_RO.ts | 8 ----- src/qt_gui/translations/ru_RU.ts | 8 ----- src/qt_gui/translations/sq_AL.ts | 8 ----- src/qt_gui/translations/sv_SE.ts | 8 ----- src/qt_gui/translations/tr_TR.ts | 8 ----- src/qt_gui/translations/uk_UA.ts | 8 ----- src/qt_gui/translations/vi_VN.ts | 8 ----- src/qt_gui/translations/zh_CN.ts | 8 ----- src/qt_gui/translations/zh_TW.ts | 8 ----- 28 files changed, 24 insertions(+), 248 deletions(-) diff --git a/src/qt_gui/translations/ar_SA.ts b/src/qt_gui/translations/ar_SA.ts index f5503e189..c130a374c 100644 --- a/src/qt_gui/translations/ar_SA.ts +++ b/src/qt_gui/translations/ar_SA.ts @@ -1126,7 +1126,7 @@ Deadzone Offset (def 0.50): - Deadzone Offset (def 0.50): + : Speed Multiplier (def 1.0): @@ -1138,7 +1138,7 @@ 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. - 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. + هذا الزر يقوم بنسخ تعيينات الأزرار من إعدادات المستخدم العامة لإعدادات المستخدم المحددة حالياً، ولا يمكن استعماله عندما تكون الإعدادات المستخدمة هي الإعدادات العامة. Copy values from Common Config @@ -1146,7 +1146,7 @@ Do you want to overwrite existing mappings with the mappings from the Common Config? - Do you want to overwrite existing mappings with the mappings from the Common Config? + هل تريد استبدال التعيينات الحالية بالتعيينات العامة؟ Unable to Save @@ -1474,10 +1474,6 @@ Emulator المحاكي - - Enable Separate Update Folder - Enable Separate Update Folder - Default tab when opening settings علامة التبويب الافتراضية عند فتح الإعدادات @@ -1500,7 +1496,7 @@ Trophy Key - Trophy Key + زر الميداليات Trophy @@ -1508,7 +1504,7 @@ Open the custom trophy images/sounds folder - Open the custom trophy images/sounds folder + افتح مجلد تخصيص اصوات/صور الميداليات Logger @@ -1544,7 +1540,7 @@ s - s + س Controller @@ -1588,7 +1584,7 @@ Enable HDR - Enable HDR + تشغيل HDR Paths @@ -1628,23 +1624,23 @@ Enable Crash Diagnostics - Enable Crash Diagnostics + تشغيل تشخيص الأعطال Collect Shaders - Collect Shaders + اجمع برامج التظليل Copy GPU Buffers - Copy GPU Buffers + انسخ التخزين المؤقت لوحدة معالجة الرُسوم Host Debug Markers - Host Debug Markers + استضافة علامات التصحيح Guest Debug Markers - Guest Debug Markers + ضيف علامات التصحيح Update @@ -1656,7 +1652,7 @@ Always Show Changelog - Always Show Changelog + اظهر سجل التغيرات دائماً Update Channel @@ -1672,23 +1668,23 @@ Title Music - Title Music + موسيقى الشاشة الرئيسية Disable Trophy Notification - Disable Trophy Notification + إغلاق إشعارات الميداليات Background Image - Background Image + صورة الخلفية Show Background Image - Show Background Image + إظهار صورة الخلفية Opacity - Opacity + درجة السواد Play title music @@ -1696,15 +1692,15 @@ Update Compatibility Database On Startup - Update Compatibility Database On Startup + تحديث قاعدة بيانات التوافق عند التشغيل Game Compatibility - Game Compatibility + توافق الألعاب Display Compatibility Data - Display Compatibility Data + إظهار معلومات التوافق Update Compatibility Database @@ -1742,10 +1738,6 @@ Emulator Language:\nSets the language of the emulator's user interface. لغة المحاكي:\nتحدد لغة واجهة المستخدم الخاصة بالمحاكي. - - 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. - Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management. - Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. إظهار شاشة البداية:\nيعرض شاشة البداية الخاصة باللعبة (صورة خاصة) أثناء بدء التشغيل. @@ -1760,7 +1752,7 @@ Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. - Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + مفتاح الميداليات:\nمفتاح يستخدم لفتح تشفير الميداليات. يجب أن يكون من جهاز مكسور الحماية.\nيجي أن يحتوي على أحرف نظام العد السداسي. Log Type:\nSets whether to synchronize the output of the log window for performance. May have adverse effects on emulation. @@ -1776,7 +1768,7 @@ Background Image:\nControl the opacity of the game background image. - Background Image:\nControl the opacity of the game background image. + صورة الخلفية:\nيتحكم في درجة سواد صورة خلفية اللعبة. Play Title Music:\nIf a game supports it, enable playing special music when selecting the game in the GUI. @@ -1784,7 +1776,7 @@ 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). - 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). + إغلاق نوافذ الميداليات المنبثقة:\n إغلاق إشعارات الميداليات داخل اللعبة. تقدم الميداليات يمكن تتبعه باستخدام عارض الميداليات (قم بالضغط على زر الفأرة الأيمن داخل النافذة الرئيسية). 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. diff --git a/src/qt_gui/translations/da_DK.ts b/src/qt_gui/translations/da_DK.ts index 658ac118f..131a989e1 100644 --- a/src/qt_gui/translations/da_DK.ts +++ b/src/qt_gui/translations/da_DK.ts @@ -1474,10 +1474,6 @@ Emulator Emulator - - Enable Separate Update Folder - Enable Separate Update Folder - Default tab when opening settings Standardfaneblad ved åbning af indstillinger @@ -1742,10 +1738,6 @@ Emulator Language:\nSets the language of the emulator's user interface. Emulatorsprog:\nIndstiller sproget i emulatorens brugergrænseflade. - - 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. - Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management. - Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. Vis startskærm:\nViser en startskærm (speciel grafik) under opstarten. diff --git a/src/qt_gui/translations/de_DE.ts b/src/qt_gui/translations/de_DE.ts index b6cd3105f..9642cd500 100644 --- a/src/qt_gui/translations/de_DE.ts +++ b/src/qt_gui/translations/de_DE.ts @@ -1474,10 +1474,6 @@ Emulator Emulator - - Enable Separate Update Folder - Separaten Update-Ordner aktivieren - Default tab when opening settings Standardregisterkarte beim Öffnen der Einstellungen @@ -1742,10 +1738,6 @@ Emulator Language:\nSets the language of the emulator's user interface. Emulatorsprache:\nLegt die Sprache der Emulator-Benutzeroberfläche fest. - - 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. - Separaten Update-Ordner aktivieren:\nErmöglicht die Installation von Spielaktualiserungen in einem separaten Ordner zur einfachen Verwaltung. - Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. Startbildschirm anzeigen:\nZeigt beim Start einen speziellen Bildschirm (Splash) des Spiels an. diff --git a/src/qt_gui/translations/el_GR.ts b/src/qt_gui/translations/el_GR.ts index d1cf0d4a6..c91e0c731 100644 --- a/src/qt_gui/translations/el_GR.ts +++ b/src/qt_gui/translations/el_GR.ts @@ -1474,10 +1474,6 @@ Emulator Emulator - - Enable Separate Update Folder - Enable Separate Update Folder - Default tab when opening settings Προεπιλεγμένη καρτέλα κατά την ανοίγμα των ρυθμίσεων @@ -1742,10 +1738,6 @@ Emulator Language:\nSets the language of the emulator's user interface. Γλώσσα Εξομοιωτή:\nΡυθμίζει τη γλώσσα του γραφικού περιβάλλοντος του εξομοιωτή. - - 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. - 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. - Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. Εμφάνιση Splash Screen:\nΕμφανίζει ειδική γραφική οθόνη κατά την εκκίνηση. diff --git a/src/qt_gui/translations/es_ES.ts b/src/qt_gui/translations/es_ES.ts index bbd49f61d..035aac6a3 100644 --- a/src/qt_gui/translations/es_ES.ts +++ b/src/qt_gui/translations/es_ES.ts @@ -1474,10 +1474,6 @@ Emulator Emulador - - Enable Separate Update Folder - Habilitar Carpeta Independiente de Actualizaciones - Default tab when opening settings Pestaña predeterminada al abrir la configuración @@ -1742,10 +1738,6 @@ Emulator Language:\nSets the language of the emulator's user interface. Idioma del Emulador:\nConfigura el idioma de la interfaz de usuario del emulador. - - 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. - 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. - Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. Mostrar Pantalla de Inicio:\nMuestra la pantalla de inicio del juego (una imagen especial) mientras el juego se está iniciando. diff --git a/src/qt_gui/translations/fa_IR.ts b/src/qt_gui/translations/fa_IR.ts index f1f2c62ab..552a0ff23 100644 --- a/src/qt_gui/translations/fa_IR.ts +++ b/src/qt_gui/translations/fa_IR.ts @@ -1474,10 +1474,6 @@ Emulator شبیه ساز - - Enable Separate Update Folder - فعال‌سازی پوشه جداگانه برای به‌روزرسانی - Default tab when opening settings زبان پیش‌فرض هنگام باز کردن تنظیمات @@ -1742,10 +1738,6 @@ Emulator Language:\nSets the language of the emulator's user interface. زبان شبیه‌ساز:\nزبان رابط کاربری شبیه‌ساز را انتخاب می‌کند. - - 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. - فعال‌سازی پوشه جداگانه برای به‌روزرسانی:\nامکان نصب به‌روزرسانی‌های بازی در یک پوشه جداگانه برای مدیریت راحت‌تر را فراهم می‌کند. - Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. نمایش صفحه شروع:\nصفحه شروع بازی (تصویری ویژه) را هنگام بارگذاری بازی نمایش می‌دهد. diff --git a/src/qt_gui/translations/fi_FI.ts b/src/qt_gui/translations/fi_FI.ts index d07f82bd5..44c668560 100644 --- a/src/qt_gui/translations/fi_FI.ts +++ b/src/qt_gui/translations/fi_FI.ts @@ -1474,10 +1474,6 @@ Emulator Emulaattori - - Enable Separate Update Folder - Ota Käyttöön Erillinen Päivityshakemisto - Default tab when opening settings Oletusvälilehti avattaessa asetuksia @@ -1742,10 +1738,6 @@ Emulator Language:\nSets the language of the emulator's user interface. Emulaattorin Kieli:\nAsettaa emulaattorin käyttöliittymän kielen. - - 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. - 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ä. - Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. Näytä Aloitusnäyttö:\nNäyttää pelin aloitusnäytön (erityinen kuva) pelin käynnistyessä. diff --git a/src/qt_gui/translations/fr_FR.ts b/src/qt_gui/translations/fr_FR.ts index 89599e32c..13e1be9f5 100644 --- a/src/qt_gui/translations/fr_FR.ts +++ b/src/qt_gui/translations/fr_FR.ts @@ -1474,10 +1474,6 @@ Emulator Émulateur - - Enable Separate Update Folder - Dossier séparé pour les mises à jour - Default tab when opening settings Onglet par défaut lors de l'ouverture des paramètres @@ -1742,10 +1738,6 @@ Emulator Language:\nSets the language of the emulator's user interface. Langue de l'émulateur:\nDéfinit la langue de l'interface utilisateur de l'émulateur. - - 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. - Dossier séparé pour les mises à jour:\nInstalle les mises à jours des jeux dans un dossier séparé pour une gestion plus facile. - Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. Afficher l'écran de démarrage:\nAffiche l'écran de démarrage du jeu (une image spéciale) lors du démarrage du jeu. diff --git a/src/qt_gui/translations/hu_HU.ts b/src/qt_gui/translations/hu_HU.ts index 85b6f2c95..58857d0d7 100644 --- a/src/qt_gui/translations/hu_HU.ts +++ b/src/qt_gui/translations/hu_HU.ts @@ -1474,10 +1474,6 @@ Emulator Emulátor - - Enable Separate Update Folder - Külön Frissítési Mappa Engedélyezése - Default tab when opening settings Alapértelmezett fül a beállítások megnyitásakor @@ -1742,10 +1738,6 @@ Emulator Language:\nSets the language of the emulator's user interface. Emulátor nyelve:\nBeállítja az emulátor felhasználói felületének nyelvét. - - 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. - 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. - Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. 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. diff --git a/src/qt_gui/translations/id_ID.ts b/src/qt_gui/translations/id_ID.ts index 1858da2a7..de19824f7 100644 --- a/src/qt_gui/translations/id_ID.ts +++ b/src/qt_gui/translations/id_ID.ts @@ -1474,10 +1474,6 @@ Emulator Emulator - - Enable Separate Update Folder - Enable Separate Update Folder - Default tab when opening settings Tab default saat membuka pengaturan @@ -1742,10 +1738,6 @@ Emulator Language:\nSets the language of the emulator's user interface. Bahasa Emulator:\nMenetapkan bahasa antarmuka pengguna emulator. - - 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. - Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management. - Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. Tampilkan Layar Pembuka:\nMenampilkan layar pembuka permainan (gambar khusus) saat permainan dimulai. diff --git a/src/qt_gui/translations/it_IT.ts b/src/qt_gui/translations/it_IT.ts index 895908193..908013004 100644 --- a/src/qt_gui/translations/it_IT.ts +++ b/src/qt_gui/translations/it_IT.ts @@ -1474,10 +1474,6 @@ Emulator Emulatore - - Enable Separate Update Folder - Abilita Cartella Aggiornamenti Separata - Default tab when opening settings Scheda predefinita all'apertura delle impostazioni @@ -1742,10 +1738,6 @@ Emulator Language:\nSets the language of the emulator's user interface. Lingua dell'Emulatore:\nImposta la lingua dell'interfaccia utente dell'emulatore. - - 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. - Abilita Cartella Aggiornamenti Separata:\nAbilita l'installazione degli aggiornamenti in una cartella separata per una più facile gestione. - Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. Mostra Schermata di Avvio:\nMostra la schermata di avvio del gioco (un'immagine speciale) mentre il gioco si sta avviando. diff --git a/src/qt_gui/translations/ja_JP.ts b/src/qt_gui/translations/ja_JP.ts index d4b8fa5b7..146caa515 100644 --- a/src/qt_gui/translations/ja_JP.ts +++ b/src/qt_gui/translations/ja_JP.ts @@ -1474,10 +1474,6 @@ Emulator エミュレーター - - Enable Separate Update Folder - アップデートフォルダの分離を有効化 - Default tab when opening settings 設定を開くときのデフォルトタブ @@ -1742,10 +1738,6 @@ Emulator Language:\nSets the language of the emulator's user interface. エミュレーターの言語:\nエミュレーターのユーザーインターフェースの言語を設定します。 - - 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. - Enable Separate Update Folder:\nゲームのアップデートを別のフォルダにインストールすることで、管理が容易になります。 - Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. スプラッシュスクリーンを表示:\nゲーム起動中にゲームのスプラッシュスクリーン(特別な画像)を表示します。 diff --git a/src/qt_gui/translations/ko_KR.ts b/src/qt_gui/translations/ko_KR.ts index 9d4b58c79..b79959d38 100644 --- a/src/qt_gui/translations/ko_KR.ts +++ b/src/qt_gui/translations/ko_KR.ts @@ -1474,10 +1474,6 @@ Emulator Emulator - - Enable Separate Update Folder - Enable Separate Update Folder - Default tab when opening settings 설정 열기 시 기본 탭 @@ -1742,10 +1738,6 @@ Emulator Language:\nSets the language of the emulator's user interface. Emulator Language:\nSets the language of the emulator's user interface. - - 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. - 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. - Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. diff --git a/src/qt_gui/translations/lt_LT.ts b/src/qt_gui/translations/lt_LT.ts index 55a9fac0c..03ff5a003 100644 --- a/src/qt_gui/translations/lt_LT.ts +++ b/src/qt_gui/translations/lt_LT.ts @@ -1474,10 +1474,6 @@ Emulator Emulator - - Enable Separate Update Folder - Enable Separate Update Folder - Default tab when opening settings Numatytoji kortelė atidarius nustatymus @@ -1742,10 +1738,6 @@ Emulator Language:\nSets the language of the emulator's user interface. Emuliatoriaus kalba:\nNustato emuliatoriaus vartotojo sąsajos kalbą. - - 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. - 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. - Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. Rodyti paleidimo ekraną:\nPaleidimo metu rodo žaidimo paleidimo ekraną (ypatingą vaizdą). diff --git a/src/qt_gui/translations/nb_NO.ts b/src/qt_gui/translations/nb_NO.ts index 4a0835c1c..e937287fd 100644 --- a/src/qt_gui/translations/nb_NO.ts +++ b/src/qt_gui/translations/nb_NO.ts @@ -1474,10 +1474,6 @@ Emulator Emulator - - Enable Separate Update Folder - Bruk separat oppdateringsmappe - Default tab when opening settings Standardfanen når innstillingene åpnes @@ -1742,10 +1738,6 @@ Emulator Language:\nSets the language of the emulator's user interface. Emulatorspråket:\nAngir språket for emulatorens brukergrensesnitt. - - 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. - 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. - Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. Vis velkomstbilde:\nViser spillets velkomstbilde (et spesialbilde) når spillet starter. diff --git a/src/qt_gui/translations/nl_NL.ts b/src/qt_gui/translations/nl_NL.ts index 918da6a67..66872455e 100644 --- a/src/qt_gui/translations/nl_NL.ts +++ b/src/qt_gui/translations/nl_NL.ts @@ -1474,10 +1474,6 @@ Emulator Emulator - - Enable Separate Update Folder - Enable Separate Update Folder - Default tab when opening settings Standaardtabblad bij het openen van instellingen @@ -1742,10 +1738,6 @@ Emulator Language:\nSets the language of the emulator's user interface. Emulator Taal:\nStelt de taal van de gebruikersinterface van de emulator in. - - 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. - Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management. - Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. Opstartscherm weergeven:\nToont het opstartscherm van het spel (een speciale afbeelding) tijdens het starten van het spel. diff --git a/src/qt_gui/translations/pl_PL.ts b/src/qt_gui/translations/pl_PL.ts index 39950d6ec..bd59a1894 100644 --- a/src/qt_gui/translations/pl_PL.ts +++ b/src/qt_gui/translations/pl_PL.ts @@ -1474,10 +1474,6 @@ Emulator Emulator - - Enable Separate Update Folder - Włącz oddzielny folder aktualizacji - Default tab when opening settings Domyślna zakładka podczas otwierania ustawień @@ -1742,10 +1738,6 @@ Emulator Language:\nSets the language of the emulator's user interface. Język emulatora:\nUstala język interfejsu użytkownika emulatora. - - 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. - Włącz oddzielny folder aktualizacji:\nUmożliwia instalowanie aktualizacji gier w oddzielnym folderze w celu łatwego zarządzania. - Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. Wyświetl ekran powitalny:\nPodczas uruchamiania gry wyświetla ekran powitalny (specjalny obraz). diff --git a/src/qt_gui/translations/pt_BR.ts b/src/qt_gui/translations/pt_BR.ts index 5d1582b5a..584d6dc19 100644 --- a/src/qt_gui/translations/pt_BR.ts +++ b/src/qt_gui/translations/pt_BR.ts @@ -1474,10 +1474,6 @@ Emulator Emulador - - Enable Separate Update Folder - Ativar Pasta de Atualização Separada - Default tab when opening settings Aba padrão ao abrir as configurações @@ -1742,10 +1738,6 @@ Emulator Language:\nSets the language of the emulator's user interface. Idioma do Emulador:\nDefine o idioma da interface do emulador. - - 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. - 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. - Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. Mostrar Splash Inicial:\nExibe a tela inicial do jogo (imagem especial) ao iniciar o jogo. diff --git a/src/qt_gui/translations/pt_PT.ts b/src/qt_gui/translations/pt_PT.ts index a155a6324..70a73afe7 100644 --- a/src/qt_gui/translations/pt_PT.ts +++ b/src/qt_gui/translations/pt_PT.ts @@ -1474,10 +1474,6 @@ Emulator Emulador - - Enable Separate Update Folder - Ativar Pasta de Atualizações Separada - Default tab when opening settings Aba padrão ao abrir as definições @@ -1742,10 +1738,6 @@ Emulator Language:\nSets the language of the emulator's user interface. Idioma do Emulador:\nDefine o idioma da interface gráfica do emulador. - - 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. - 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. - Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. Mostrar Splash Inicial:\nExibe o ecrã inicial do jogo (uma imagem especial) enquanto o jogo inicia. diff --git a/src/qt_gui/translations/ro_RO.ts b/src/qt_gui/translations/ro_RO.ts index 18121a204..78dd79c53 100644 --- a/src/qt_gui/translations/ro_RO.ts +++ b/src/qt_gui/translations/ro_RO.ts @@ -1474,10 +1474,6 @@ Emulator Emulator - - Enable Separate Update Folder - Enable Separate Update Folder - Default tab when opening settings Tab-ul implicit la deschiderea setărilor @@ -1742,10 +1738,6 @@ Emulator Language:\nSets the language of the emulator's user interface. Limba emulatorului:\nSetează limba interfeței utilizatorului a emulatorului. - - 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. - 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. - Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. Afișează ecranul de încărcare:\nAfișează ecranul de încărcare al jocului (o imagine specială) în timp ce jocul pornește. diff --git a/src/qt_gui/translations/ru_RU.ts b/src/qt_gui/translations/ru_RU.ts index 3944af589..0f16efc2c 100644 --- a/src/qt_gui/translations/ru_RU.ts +++ b/src/qt_gui/translations/ru_RU.ts @@ -1474,10 +1474,6 @@ Emulator Эмулятор - - Enable Separate Update Folder - Отдельная папка обновлений - Default tab when opening settings Вкладка по умолчанию при открытии настроек @@ -1742,10 +1738,6 @@ Emulator Language:\nSets the language of the emulator's user interface. Язык эмулятора:\nУстанавливает язык пользовательского интерфейса эмулятора. - - 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. - Отдельная папка обновлений:\nПозволяет устанавливать обновления игры в отдельную папку для удобства.\nМожно создать вручную, добавив извлеченное обновление в папку с игрой с именем "CUSA00000-UPDATE", где идентификатор CUSA совпадает с идентификатором игры. - Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. Показывать заставку:\nОтображает заставку игры (специальное изображение) во время запуска. diff --git a/src/qt_gui/translations/sq_AL.ts b/src/qt_gui/translations/sq_AL.ts index d59fd8c3e..311633a99 100644 --- a/src/qt_gui/translations/sq_AL.ts +++ b/src/qt_gui/translations/sq_AL.ts @@ -1474,10 +1474,6 @@ Emulator Emulatori - - Enable Separate Update Folder - Aktivizo dosjen e ndarë të përditësimit - Default tab when opening settings Skeda e paracaktuar kur hapen cilësimet @@ -1742,10 +1738,6 @@ Emulator Language:\nSets the language of the emulator's user interface. Gjuha e emulatorit:\nPërcakton gjuhën e ndërfaqes së përdoruesit të emulatorit. - - 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. - 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. - Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. Shfaq ekranin e ngarkesës:\nShfaq ekranin e ngarkesës së lojës (një pamje e veçantë) gjatë fillimit të lojës. diff --git a/src/qt_gui/translations/sv_SE.ts b/src/qt_gui/translations/sv_SE.ts index b570c420e..ce0da785c 100644 --- a/src/qt_gui/translations/sv_SE.ts +++ b/src/qt_gui/translations/sv_SE.ts @@ -1474,10 +1474,6 @@ Emulator Emulator - - Enable Separate Update Folder - Aktivera separat uppdateringsmapp - Default tab when opening settings Standardflik när inställningar öppnas @@ -1742,10 +1738,6 @@ Emulator Language:\nSets the language of the emulator's user interface. Emulatorspråk:\nStäller in språket för emulatorns användargränssnitt - - 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. - 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 - Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. Visa startskärm:\nVisar spelets startskärm (en speciell bild) när spelet startas diff --git a/src/qt_gui/translations/tr_TR.ts b/src/qt_gui/translations/tr_TR.ts index d2d018116..f5f7b65e5 100644 --- a/src/qt_gui/translations/tr_TR.ts +++ b/src/qt_gui/translations/tr_TR.ts @@ -1474,10 +1474,6 @@ Emulator Emülatör - - Enable Separate Update Folder - Ayrı Güncelleme Klasörünü Etkinleştir - Default tab when opening settings Ayarlar açıldığında varsayılan sekme @@ -1742,10 +1738,6 @@ Emulator Language:\nSets the language of the emulator's user interface. Emülatör Dili:\nEmülatörün kullanıcı arayüzünün dilini ayarlar. - - 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. - Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management. - Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. Açılış Ekranını Göster:\nOyun açılırken (özel bir görüntü) açılış ekranını gösterir. diff --git a/src/qt_gui/translations/uk_UA.ts b/src/qt_gui/translations/uk_UA.ts index 5e2572449..3eb88bcab 100644 --- a/src/qt_gui/translations/uk_UA.ts +++ b/src/qt_gui/translations/uk_UA.ts @@ -1474,10 +1474,6 @@ Emulator Емулятор - - Enable Separate Update Folder - Увімкнути окрему папку оновлень - Default tab when opening settings Вкладка за замовчуванням при відкритті налаштувань @@ -1742,10 +1738,6 @@ Emulator Language:\nSets the language of the emulator's user interface. Мова емулятора:\nВстановіть мову користувацького інтерфейсу емулятора. - - 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. - Окрема папка для оновлень:\nДає змогу встановлювати оновлення гри в окрему папку для зручності. - Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. Показувати заставку:\nВідображає заставку гри (спеціальне зображення) під час запуску гри. diff --git a/src/qt_gui/translations/vi_VN.ts b/src/qt_gui/translations/vi_VN.ts index b8c1759be..e0bc7e4fe 100644 --- a/src/qt_gui/translations/vi_VN.ts +++ b/src/qt_gui/translations/vi_VN.ts @@ -1474,10 +1474,6 @@ Emulator Trình giả lập - - Enable Separate Update Folder - Bật thư mục cập nhật riêng - Default tab when opening settings Tab mặc định khi mở cài đặt @@ -1742,10 +1738,6 @@ Emulator Language:\nSets the language of the emulator's user interface. 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. - - 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. - Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management. - Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. 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. diff --git a/src/qt_gui/translations/zh_CN.ts b/src/qt_gui/translations/zh_CN.ts index 7d414a493..120310810 100644 --- a/src/qt_gui/translations/zh_CN.ts +++ b/src/qt_gui/translations/zh_CN.ts @@ -1474,10 +1474,6 @@ Emulator 模拟器 - - Enable Separate Update Folder - 启用单独的更新目录 - Default tab when opening settings 打开设置时的默认选项卡 @@ -1742,10 +1738,6 @@ Emulator Language:\nSets the language of the emulator's user interface. 模拟器语言:\n设置模拟器用户界面的语言。 - - 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. - 启用单独的更新目录:\n启用安装游戏更新到一个单独的目录中以更便于管理。 - Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. 显示启动画面:\n在游戏启动时显示游戏的启动画面(特殊图像)。 diff --git a/src/qt_gui/translations/zh_TW.ts b/src/qt_gui/translations/zh_TW.ts index 08aa812fb..077455558 100644 --- a/src/qt_gui/translations/zh_TW.ts +++ b/src/qt_gui/translations/zh_TW.ts @@ -1474,10 +1474,6 @@ Emulator Emulator - - Enable Separate Update Folder - Enable Separate Update Folder - Default tab when opening settings 打開設置時的默認選項卡 @@ -1742,10 +1738,6 @@ Emulator Language:\nSets the language of the emulator's user interface. 模擬器語言:\n設定模擬器的用戶介面的語言。 - - 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. - Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management. - Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. 顯示啟動畫面:\n在遊戲啟動時顯示遊戲的啟動畫面(特殊圖片)。 From f85d8df71e770741768bb9c6e60123e2fe3019f7 Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Sun, 30 Mar 2025 12:02:33 -0700 Subject: [PATCH 09/34] vulkan: Lower list primitive restart warning to debug log. (#2725) --- src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 901096259..c528258fb 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -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 = { From 374b66ad8eae5c5d8a452f10973a321038aea451 Mon Sep 17 00:00:00 2001 From: Stephen Miller <56742918+StevenMiller123@users.noreply.github.com> Date: Sun, 30 Mar 2025 16:27:12 -0500 Subject: [PATCH 10/34] Emulate sceKernelInternalMemory mapping (#2726) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Emulate sceKernelInternalMemory mapping This fixes the early crash in CUSA07820 (The Last of Us™ Part II). * Fix name --- src/core/linker.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/core/linker.cpp b/src/core/linker.cpp index 18ae62f4b..4ccb9d943 100644 --- a/src/core/linker.cpp +++ b/src/core/linker.cpp @@ -101,6 +101,17 @@ void Linker::Execute(const std::vector 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(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. From b0a12c02e16c02379385f675dd4c6318c0b7fd69 Mon Sep 17 00:00:00 2001 From: Stephen Miller <56742918+StevenMiller123@users.noreply.github.com> Date: Mon, 31 Mar 2025 04:55:14 -0500 Subject: [PATCH 11/34] Add S_SETPRIO to EmitFlowControl (#2727) By squidbus' suggestion, I've added a warning log for this case. --- src/shader_recompiler/frontend/translate/scalar_flow.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/shader_recompiler/frontend/translate/scalar_flow.cpp b/src/shader_recompiler/frontend/translate/scalar_flow.cpp index ef8bab789..0e02b77a2 100644 --- a/src/shader_recompiler/frontend/translate/scalar_flow.cpp +++ b/src/shader_recompiler/frontend/translate/scalar_flow.cpp @@ -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: From 7533206d89ceb028221a9e094c6eb9a0cc019cab Mon Sep 17 00:00:00 2001 From: Joshua de Reeper Date: Mon, 31 Mar 2025 17:55:21 +0200 Subject: [PATCH 12/34] usbd: Implement libusb passthrough (#2271) * usbd: Implement libusb passthrough * clang-format * only do kernel activities on non-windows * use variable to represent "fake" windows kernel driver --------- Co-authored-by: georgemoralis --- .gitmodules | 3 + CMakeLists.txt | 3 +- externals/CMakeLists.txt | 5 + externals/libusb | 1 + src/core/libraries/usbd/usbd.cpp | 512 ++++++++++++++++++++----------- src/core/libraries/usbd/usbd.h | 198 ++++++++---- 6 files changed, 475 insertions(+), 247 deletions(-) create mode 160000 externals/libusb diff --git a/.gitmodules b/.gitmodules index 98fba2098..065a4570f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -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 diff --git a/CMakeLists.txt b/CMakeLists.txt index 021167d58..74d555adc 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -224,6 +224,7 @@ 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) +find_package(usb-1.0 1.0.27 CONFIG) if (NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR NOT MSVC) find_package(cryptopp 8.9.0 MODULE) @@ -1061,7 +1062,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 usb-1.0) 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") diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index d6bdda023..ef75e8f3e 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -201,6 +201,11 @@ if (NOT TARGET pugixml::pugixml) add_subdirectory(pugixml) endif() +# libusb +if (NOT TARGET usb-1.0) + add_subdirectory(libusb) +endif() + # Discord RPC if (ENABLE_DISCORD_RPC) add_subdirectory(discord-rpc) diff --git a/externals/libusb b/externals/libusb new file mode 160000 index 000000000..8f0b4a38f --- /dev/null +++ b/externals/libusb @@ -0,0 +1 @@ +Subproject commit 8f0b4a38fc3eefa2b26a99dff89e1c12bf37afd4 diff --git a/src/core/libraries/usbd/usbd.cpp b/src/core/libraries/usbd/usbd.cpp index fdfa50b23..e5f6151eb 100644 --- a/src/core/libraries/usbd/usbd.cpp +++ b/src/core/libraries/usbd/usbd.cpp @@ -7,311 +7,455 @@ #include "core/libraries/libs.h" #include "usbd.h" +#include +#include + 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(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 \ No newline at end of file diff --git a/src/core/libraries/usbd/usbd.h b/src/core/libraries/usbd/usbd.h index 4ed153587..3bd8134a7 100644 --- a/src/core/libraries/usbd/usbd.h +++ b/src/core/libraries/usbd/usbd.h @@ -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(); From a5958bf7f0da207e02065a88355b8afae0b5e256 Mon Sep 17 00:00:00 2001 From: Alexandre Bouvier Date: Mon, 31 Mar 2025 19:29:24 +0000 Subject: [PATCH 13/34] cmake: remove leftover from #2707 (#2730) --- CMakeLists.txt | 4 ---- cmake/Findcryptopp.cmake | 15 --------------- 2 files changed, 19 deletions(-) delete mode 100644 cmake/Findcryptopp.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 74d555adc..20b0f70d7 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -226,10 +226,6 @@ find_package(Zydis 5.0.0 CONFIG) find_package(pugixml 1.14 CONFIG) find_package(usb-1.0 1.0.27 CONFIG) -if (NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR NOT MSVC) - find_package(cryptopp 8.9.0 MODULE) -endif() - if (APPLE) find_package(date 3.0.1 CONFIG) endif() diff --git a/cmake/Findcryptopp.cmake b/cmake/Findcryptopp.cmake deleted file mode 100644 index d57c0bc54..000000000 --- a/cmake/Findcryptopp.cmake +++ /dev/null @@ -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() From a2a1ecde0a00bbcece1dc51c14db16ae44b00fc6 Mon Sep 17 00:00:00 2001 From: Alexandre Bouvier Date: Mon, 31 Mar 2025 19:29:52 +0000 Subject: [PATCH 14/34] cmake: fix system libusb discovery (#2731) --- CMakeLists.txt | 4 ++-- cmake/Findlibusb.cmake | 15 +++++++++++++++ externals/CMakeLists.txt | 3 ++- 3 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 cmake/Findlibusb.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 20b0f70d7..d50dc187d 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -224,7 +224,7 @@ 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) -find_package(usb-1.0 1.0.27 CONFIG) +find_package(libusb 1.0.27 MODULE) if (APPLE) find_package(date 3.0.1 CONFIG) @@ -1058,7 +1058,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 usb-1.0) +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") diff --git a/cmake/Findlibusb.cmake b/cmake/Findlibusb.cmake new file mode 100644 index 000000000..c8b35e979 --- /dev/null +++ b/cmake/Findlibusb.cmake @@ -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() diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index ef75e8f3e..b92e13795 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -202,8 +202,9 @@ if (NOT TARGET pugixml::pugixml) endif() # libusb -if (NOT TARGET usb-1.0) +if (NOT TARGET libusb::usb) add_subdirectory(libusb) + add_library(libusb::usb ALIAS usb-1.0) endif() # Discord RPC From 01243fb8e59710ce9a3dd1b58d663d9a28d5db66 Mon Sep 17 00:00:00 2001 From: Stephen Miller <56742918+StevenMiller123@users.noreply.github.com> Date: Tue, 1 Apr 2025 00:57:47 -0500 Subject: [PATCH 15/34] Fix libSceNgs2 HLE regressions (#2732) * Fix sceNgs2SystemCreateWithAllocator The cause of the exceptions without libraries. * Remove error handling for unimplemented functions Since nothing exists to create any VoiceHandle or RackHandle, we were consistently hitting those error returns. Also promotes logs for stubbed functions back to LOG_ERROR, with the exception of two functions that get spammed pretty frequently. * Use Core::ExecuteGuest to execute allocator alloc and free * Clang * Fix function definitions in ngs2.h These should be using the SYSV ABI * Fix function defs in ngs2_impl.h This will (hopefully) fix compilation * Clang * Clang again --- src/core/libraries/ngs2/ngs2.cpp | 152 ++++++++------------------ src/core/libraries/ngs2/ngs2.h | 18 +-- src/core/libraries/ngs2/ngs2_impl.h | 5 +- src/core/libraries/ngs2/ngs2_report.h | 3 +- 4 files changed, 60 insertions(+), 118 deletions(-) diff --git a/src/core/libraries/ngs2/ngs2.cpp b/src/core/libraries/ngs2/ngs2.cpp index 0b42e2471..743be5fd6 100644 --- a/src/core/libraries/ngs2/ngs2.cpp +++ b/src/core/libraries/ngs2/ngs2.cpp @@ -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; } diff --git a/src/core/libraries/ngs2/ngs2.h b/src/core/libraries/ngs2/ngs2.h index a34bf21d4..6c499d974 100644 --- a/src/core/libraries/ngs2/ngs2.h +++ b/src/core/libraries/ngs2/ngs2.h @@ -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; diff --git a/src/core/libraries/ngs2/ngs2_impl.h b/src/core/libraries/ngs2/ngs2_impl.h index 7be0f89cc..a433e84fd 100644 --- a/src/core/libraries/ngs2/ngs2_impl.h +++ b/src/core/libraries/ngs2/ngs2_impl.h @@ -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 diff --git a/src/core/libraries/ngs2/ngs2_report.h b/src/core/libraries/ngs2/ngs2_report.h index 88f6d1df0..0f46f5081 100644 --- a/src/core/libraries/ngs2/ngs2_report.h +++ b/src/core/libraries/ngs2/ngs2_report.h @@ -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; From 9ee5d066a228b37558a0eb6b0b1aa963a9fd9079 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Tue, 1 Apr 2025 13:22:32 +0300 Subject: [PATCH 16/34] hotfix: issue with cmake 4 --- externals/discord-rpc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/externals/discord-rpc b/externals/discord-rpc index 51b09d426..d3b5af882 160000 --- a/externals/discord-rpc +++ b/externals/discord-rpc @@ -1 +1 @@ -Subproject commit 51b09d426a4a1bcfa6ee6d4894e57d669f4a2e65 +Subproject commit d3b5af8827031f3bccbf8c15d5dc1bfdc9467f17 From f6cc245e4019d1e2f3dfc435f27197ee1c2874a3 Mon Sep 17 00:00:00 2001 From: Stephen Miller <56742918+StevenMiller123@users.noreply.github.com> Date: Tue, 1 Apr 2025 15:36:31 -0500 Subject: [PATCH 17/34] Only log fd warning if there's a file getting closed (#2737) --- src/core/libraries/kernel/file_system.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/libraries/kernel/file_system.cpp b/src/core/libraries/kernel/file_system.cpp index 3321559ed..bc34dff98 100644 --- a/src/core/libraries/kernel/file_system.cpp +++ b/src/core/libraries/kernel/file_system.cpp @@ -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::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(); } From eb300d0aa726e340df0feda1dfa688669642bcc4 Mon Sep 17 00:00:00 2001 From: Stephen Miller <56742918+StevenMiller123@users.noreply.github.com> Date: Tue, 1 Apr 2025 19:41:40 -0500 Subject: [PATCH 18/34] libraries: Proper ulobjmgr stubs (#2740) * Better ulobjmgr stubs Main goal is to stop all the Unknown stub spam in titles using libSceUlt. * Address review comments * Update ulobjmgr.cpp --- CMakeLists.txt | 2 ++ src/core/libraries/libs.cpp | 2 ++ src/core/libraries/ulobjmgr/ulobjmgr.cpp | 45 ++++++++++++++++++++++++ src/core/libraries/ulobjmgr/ulobjmgr.h | 14 ++++++++ 4 files changed, 63 insertions(+) create mode 100644 src/core/libraries/ulobjmgr/ulobjmgr.cpp create mode 100644 src/core/libraries/ulobjmgr/ulobjmgr.h diff --git a/CMakeLists.txt b/CMakeLists.txt index d50dc187d..b3aba5d13 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -578,6 +578,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 diff --git a/src/core/libraries/libs.cpp b/src/core/libraries/libs.cpp index cd0fe650b..d0f82556e 100644 --- a/src/core/libraries/libs.cpp +++ b/src/core/libraries/libs.cpp @@ -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 diff --git a/src/core/libraries/ulobjmgr/ulobjmgr.cpp b/src/core/libraries/ulobjmgr/ulobjmgr.cpp new file mode 100644 index 000000000..cad6feda9 --- /dev/null +++ b/src/core/libraries/ulobjmgr/ulobjmgr.cpp @@ -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 diff --git a/src/core/libraries/ulobjmgr/ulobjmgr.h b/src/core/libraries/ulobjmgr/ulobjmgr.h new file mode 100644 index 000000000..9a1440e5c --- /dev/null +++ b/src/core/libraries/ulobjmgr/ulobjmgr.h @@ -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 \ No newline at end of file From afd0251dd2b5db3f663efa0d3630cff0e1b120f3 Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Wed, 2 Apr 2025 13:36:54 -0700 Subject: [PATCH 19/34] shader_recompiler: Use VK_AMD_shader_trinary_minmax when available. (#2739) * shader_recompiler: Use VK_AMD_shader_trinary_minmax when available. * shader_recompiler: Simplify signed/unsigned trinary instruction variants. --- externals/sirit | 2 +- .../spirv/emit_spirv_floating_point.cpp | 22 +++++++++ .../backend/spirv/emit_spirv_instructions.h | 9 ++++ .../backend/spirv/emit_spirv_integer.cpp | 44 +++++++++++++++++ .../frontend/translate/translate.h | 6 +-- .../frontend/translate/vector_alu.cpp | 41 +++++----------- src/shader_recompiler/ir/ir_emitter.cpp | 48 +++++++++++++++++++ src/shader_recompiler/ir/ir_emitter.h | 12 +++++ src/shader_recompiler/ir/opcodes.inc | 9 ++++ src/shader_recompiler/profile.h | 1 + .../renderer_vulkan/vk_instance.cpp | 1 + src/video_core/renderer_vulkan/vk_instance.h | 6 +++ .../renderer_vulkan/vk_pipeline_cache.cpp | 1 + 13 files changed, 168 insertions(+), 34 deletions(-) diff --git a/externals/sirit b/externals/sirit index 8b9b12c20..427a42c9e 160000 --- a/externals/sirit +++ b/externals/sirit @@ -1 +1 @@ -Subproject commit 8b9b12c2089505ac8b10fa56bf56b3ed49d9d7b0 +Subproject commit 427a42c9ed99b38204d9107bc3dc14e92458acf1 diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp index a63be87e2..8de903ce6 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp @@ -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)); } diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h index aaa2bb526..fb37799f5 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h @@ -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); diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp index 9f8784797..36726b6df 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp @@ -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) { diff --git a/src/shader_recompiler/frontend/translate/translate.h b/src/shader_recompiler/frontend/translate/translate.h index 2fd48a051..6803cda25 100644 --- a/src/shader_recompiler/frontend/translate/translate.h +++ b/src/shader_recompiler/frontend/translate/translate.h @@ -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); diff --git a/src/shader_recompiler/frontend/translate/vector_alu.cpp b/src/shader_recompiler/frontend/translate/vector_alu.cpp index 56e903052..22020d59f 100644 --- a/src/shader_recompiler/frontend/translate/vector_alu.cpp +++ b/src/shader_recompiler/frontend/translate/vector_alu.cpp @@ -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(inst.src[0])}; const IR::F32 src1{GetSrc(inst.src[1])}; const IR::F32 src2{GetSrc(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(inst.src[0])}; const IR::F32 src1{GetSrc(inst.src[1])}; const IR::F32 src2{GetSrc(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(inst.src[0])}; const IR::F32 src1{GetSrc(inst.src[1])}; const IR::F32 src2{GetSrc(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) { diff --git a/src/shader_recompiler/ir/ir_emitter.cpp b/src/shader_recompiler/ir/ir_emitter.cpp index 3615e8cbb..a171d32a2 100644 --- a/src/shader_recompiler/ir/ir_emitter.cpp +++ b/src/shader_recompiler/ir/ir_emitter.cpp @@ -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(Opcode::FPMinTri32, a, b, c); +} + +F32F64 IREmitter::FPMaxTri(const F32F64& a, const F32F64& b, const F32F64& c) { + return Inst(Opcode::FPMaxTri32, a, b, c); +} + +F32F64 IREmitter::FPMedTri(const F32F64& a, const F32F64& b, const F32F64& c) { + return Inst(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(Opcode::SMinTri32, a, b, c); +} + +U32 IREmitter::UMinTri(const U32& a, const U32& b, const U32& c) { + return Inst(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(Opcode::SMaxTri32, a, b, c); +} + +U32 IREmitter::UMaxTri(const U32& a, const U32& b, const U32& c) { + return Inst(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(Opcode::SMedTri32, a, b, c); +} + +U32 IREmitter::UMedTri(const U32& a, const U32& b, const U32& c) { + return Inst(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(Opcode::SClamp32, value, min, max); } diff --git a/src/shader_recompiler/ir/ir_emitter.h b/src/shader_recompiler/ir/ir_emitter.h index 7ac75bf70..48cc02725 100644 --- a/src/shader_recompiler/ir/ir_emitter.h +++ b/src/shader_recompiler/ir/ir_emitter.h @@ -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); diff --git a/src/shader_recompiler/ir/opcodes.inc b/src/shader_recompiler/ir/opcodes.inc index d5e17631b..93d759b74 100644 --- a/src/shader_recompiler/ir/opcodes.inc +++ b/src/shader_recompiler/ir/opcodes.inc @@ -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, ) diff --git a/src/shader_recompiler/profile.h b/src/shader_recompiler/profile.h index 1ceaea664..3b2854d59 100644 --- a/src/shader_recompiler/profile.h +++ b/src/shader_recompiler/profile.h @@ -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{}; diff --git a/src/video_core/renderer_vulkan/vk_instance.cpp b/src/video_core/renderer_vulkan/vk_instance.cpp index ab8f074cd..1f0125791 100644 --- a/src/video_core/renderer_vulkan/vk_instance.cpp +++ b/src/video_core/renderer_vulkan/vk_instance.cpp @@ -276,6 +276,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; diff --git a/src/video_core/renderer_vulkan/vk_instance.h b/src/video_core/renderer_vulkan/vk_instance.h index 3ccf89276..013003b9b 100644 --- a/src/video_core/renderer_vulkan/vk_instance.h +++ b/src/video_core/renderer_vulkan/vk_instance.h @@ -145,6 +145,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 +338,7 @@ private: bool shader_stencil_export{}; bool image_load_store_lod{}; bool amd_gcn_shader{}; + bool amd_shader_trinary_minmax{}; bool portability_subset{}; }; diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 4823b8ffe..d51c8fbd5 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -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, From 806b2ddc897fcc6f064ce03910de2a771c5f6400 Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Thu, 3 Apr 2025 12:39:08 -0700 Subject: [PATCH 20/34] cpu_patches: Remove CPU patches for macOS and bump minimum OS version to 15.4 (#2743) * cpu_patches: Remove CPU patches for macOS and bump minimum OS version to 15.4 * cpu_patches: Remove BMI1 patches These are now only good for very old Intel CPUs that: * Still do not currently function due to other CPU instruction issues. * Will probably be too slow to run shadPS4 well. --- CMakeLists.txt | 3 +- src/core/cpu_patches.cpp | 578 +-------------------------------------- src/core/cpu_patches.h | 6 - src/core/tls.cpp | 8 +- 4 files changed, 8 insertions(+), 587 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b3aba5d13..228a664eb 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/src/core/cpu_patches.cpp b/src/core/cpu_patches.cpp index a9f6c67a8..c8106b270 100644 --- a/src/core/cpu_patches.cpp +++ b/src/core/cpu_patches.cpp @@ -22,10 +22,6 @@ #include #else #include -#ifdef __APPLE__ -#include -#include -#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(operand.type)); - return operand.imm.value.u; -} - -static std::unique_ptr ZydisToXbyakOperand(const ZydisDecodedOperand& operand) { - switch (operand.type) { - case ZYDIS_OPERAND_TYPE_REGISTER: { - return std::make_unique(ZydisToXbyakRegisterOperand(operand)); - } - case ZYDIS_OPERAND_TYPE_MEMORY: { - return std::make_unique(ZydisToXbyakMemoryOperand(operand)); - } - default: - UNREACHABLE_MSG("Unsupported operand type: {}", static_cast(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(operand->getKind())); -} - -static bool IsRegisterAllocated( - const std::initializer_list& 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 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(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(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(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(stack_pointer_slot * sizeof(void*))], rsp); - c.putSeg(gs); - c.mov(rsp, qword[reinterpret_cast(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(patch_stack_slot * sizeof(void*))], rsp); - c.putSeg(gs); - c.mov(rsp, qword[reinterpret_cast(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 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 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(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(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(src.get())); - } else { - c.lea(rsi, src->getAddress()); - } - - // Load float count into third parameter. - c.mov(rdx, float_count); - - c.mov(rax, reinterpret_cast(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(&dst), ptr[rsp]); - } else { - c.movdqu(*reinterpret_cast(&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_cast, - half_float::half_cast, - half_float::half_cast, -}; - -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(&src)); - } else { - c.movdqu(ptr[rsp], *reinterpret_cast(&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(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(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 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(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()) { diff --git a/src/core/cpu_patches.h b/src/core/cpu_patches.h index 1ccac073a..7a0546046 100644 --- a/src/core/cpu_patches.h +++ b/src/core/cpu_patches.h @@ -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); diff --git a/src/core/tls.cpp b/src/core/tls.cpp index 9b3178171..e13c683e1 100644 --- a/src/core/tls.cpp +++ b/src/core/tls.cpp @@ -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 From 7bb49d85d3bd4a522b5976205a631fada37dec4d Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Thu, 3 Apr 2025 22:43:04 +0300 Subject: [PATCH 21/34] New Crowdin updates (#2724) * New translations en_us.ts (Arabic) * New translations en_us.ts (Albanian) * New translations en_us.ts (German) --- src/qt_gui/translations/ar_SA.ts | 16 ++++++------- src/qt_gui/translations/de_DE.ts | 40 ++++++++++++++++++-------------- src/qt_gui/translations/sq_AL.ts | 20 ++++++++-------- 3 files changed, 40 insertions(+), 36 deletions(-) diff --git a/src/qt_gui/translations/ar_SA.ts b/src/qt_gui/translations/ar_SA.ts index c130a374c..63ae733e8 100644 --- a/src/qt_gui/translations/ar_SA.ts +++ b/src/qt_gui/translations/ar_SA.ts @@ -1126,7 +1126,7 @@ Deadzone Offset (def 0.50): - : + إزاحة المدى الغير فعال (الأصل ٠.٥٠). Speed Multiplier (def 1.0): @@ -1704,7 +1704,7 @@ Update Compatibility Database - Update Compatibility Database + تحديث قاعدة بيانات التوافق Volume @@ -1792,15 +1792,15 @@ Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information. - Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information. + عرض بيانات التوافق:\nيقوم بإظهار معلومات توافق اللعبة في طريقة عرض الطاولة. تشغيل"تحديث التوافق عند التشغيل" للحصول على معلومات محدثة. Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts. - Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts. + تحديث التوافق عند التشغيل:\nتحديث قاعدة بيانات التوافق تلقائياً عند تشغيل shadps4. Update Compatibility Database:\nImmediately update the compatibility database. - Update Compatibility Database:\nImmediately update the compatibility database. + تحديث قاعدة بيانات التوافق:\nقم بتحديث قاعدة بيانات التوافق حالاً. Never @@ -1852,7 +1852,7 @@ 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. - 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. + تشغيل HDR:\n يقوم بتشغيل HDR في الألعاب المدعومة.\nيجب أن تدعم شاشتك أطياف ألوان BT2020 PQ و صيغة تنسيق المبادلة RGB10A2. Game Folders:\nThe list of folders to check for installed games. @@ -1884,11 +1884,11 @@ Collect Shaders:\nYou need this enabled to edit shaders with the debug menu (Ctrl + F10). - Collect Shaders:\nYou need this enabled to edit shaders with the debug menu (Ctrl + F10). + تجميع برامج التظليل:\n يجب أن تقوم بتشغيل هذا لتعديل برامج التظليل باستخدام قائمة تصحيح الأخطاء (Ctrl + F10). 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. - 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. + تشخيص الأعطال:\nيقوم بإنشاء ملف بصيغة .yaml يحتوي على معلومات عن حالة Vulkan في وقت حدوث العطل.\nمفيد لتصحيح أخطاء 'فصل الجهاز'. إذا قمت بتشغيل هذا من الأفضل أن تقوم بتشغيل "استضافة علامات تصحيح الأخطاء" و "ضيف علامات تصحيح الأخطاء".\nلا يعمل على وحدة معالجة رسوم إنتل.\nتحتاج لتشغيل التحقق من طبقات Vulkan و مجموعة تطوير البرامج الخاصة بـVulkan من أجل أن يعمل هذا. Copy GPU Buffers:\nGets around race conditions involving GPU submits.\nMay or may not help with PM4 type 0 crashes. diff --git a/src/qt_gui/translations/de_DE.ts b/src/qt_gui/translations/de_DE.ts index 9642cd500..c7a18dd99 100644 --- a/src/qt_gui/translations/de_DE.ts +++ b/src/qt_gui/translations/de_DE.ts @@ -1277,11 +1277,11 @@ Trophy Viewer - Trophy Viewer + Trophäenansicht No games found. Please add your games to your library first. - No games found. Please add your games to your library first. + Keine Spiele gefunden. Bitte fügen Sie zuerst Ihre Spiele zu Ihrer Bibliothek hinzu. Search... @@ -1409,43 +1409,43 @@ Play - Play + Spielen Pause - Pause + Pause Stop - Stop + Stopp Restart - Restart + Neustarten Full Screen - Full Screen + Vollbild Controllers - Controllers + Controller Keyboard - Keyboard + Tastatur Refresh List - Refresh List + Liste aktualisieren Resume - Resume + Fortsetzen Show Labels Under Icons - Show Labels Under Icons + Etiketten unter Symbolen anzeigen @@ -2048,7 +2048,11 @@ 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. - 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. + Ö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. @@ -2059,23 +2063,23 @@ Select Game: - Select Game: + Spiel auswählen: Progress - Progress + Fortschritt Show Earned Trophies - Show Earned Trophies + Verdiente Trophäen anzeigen Show Not Earned Trophies - Show Not Earned Trophies + Nicht verdiente Trophäen anzeigen Show Hidden Trophies - Show Hidden Trophies + Verborgene Trophäen anzeigen diff --git a/src/qt_gui/translations/sq_AL.ts b/src/qt_gui/translations/sq_AL.ts index 311633a99..50314a9b2 100644 --- a/src/qt_gui/translations/sq_AL.ts +++ b/src/qt_gui/translations/sq_AL.ts @@ -1409,43 +1409,43 @@ Play - Play + Luaj Pause - Pause + Pezullo Stop - Stop + Ndalo Restart - Restart + Rinis Full Screen - Full Screen + Ekran i Plotë Controllers - Controllers + Dorezat Keyboard - Keyboard + Tastiera Refresh List - Refresh List + Rifresko Listën Resume - Resume + Rifillo Show Labels Under Icons - Show Labels Under Icons + Shfaq Etiketat Poshtë Ikonave From 1ee201690280d23454d7cd3548045c3f1a9f1669 Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Thu, 3 Apr 2025 12:44:12 -0700 Subject: [PATCH 22/34] doc: Update README macOS details --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9259ab875..6462c8bd2 100644 --- a/README.md +++ b/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 From 54b4d7fc788d570c14924d21fbb1f58de0254aad Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Fri, 4 Apr 2025 05:13:13 -0700 Subject: [PATCH 23/34] build: Target same CPU architecture level as PS4. (#2745) --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 228a664eb..2af30ed46 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,8 +54,8 @@ 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 x86_64 feature set as the PS4 CPU to match requirements. + add_compile_options(-march=btver2 -mno-sse4a) endif() if (APPLE AND ARCHITECTURE STREQUAL "x86_64" AND CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "arm64") From 0c6f2b470fde23011ba3c840b6ed40f79cbee7b7 Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Sat, 5 Apr 2025 13:14:27 -0700 Subject: [PATCH 24/34] renderer_vulkan: Use more depth-stencil dynamic state. (#2749) --- src/video_core/amdgpu/liverpool.h | 4 + .../renderer_vulkan/vk_graphics_pipeline.cpp | 30 ++-- .../renderer_vulkan/vk_graphics_pipeline.h | 16 -- .../renderer_vulkan/vk_instance.cpp | 4 + src/video_core/renderer_vulkan/vk_instance.h | 5 + .../renderer_vulkan/vk_pipeline_cache.cpp | 14 +- .../renderer_vulkan/vk_rasterizer.cpp | 157 ++++++++++-------- .../renderer_vulkan/vk_rasterizer.h | 3 +- 8 files changed, 116 insertions(+), 117 deletions(-) diff --git a/src/video_core/amdgpu/liverpool.h b/src/video_core/amdgpu/liverpool.h index 474c04ec2..8f9292f1c 100644 --- a/src/video_core/amdgpu/liverpool.h +++ b/src/video_core/amdgpu/liverpool.h @@ -1423,6 +1423,10 @@ struct Liverpool { return num_samples; } + bool IsClipDisabled() const { + return clipper_control.clip_disable || primitive_type == PrimitiveType::RectList; + } + void SetDefaults(); }; diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index c528258fb..7cd4bd872 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -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 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 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 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, diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h index e6596db2f..7ffd14064 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h @@ -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 || diff --git a/src/video_core/renderer_vulkan/vk_instance.cpp b/src/video_core/renderer_vulkan/vk_instance.cpp index 1f0125791..d45889054 100644 --- a/src/video_core/renderer_vulkan/vk_instance.cpp +++ b/src/video_core/renderer_vulkan/vk_instance.cpp @@ -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); @@ -380,6 +381,9 @@ bool Instance::CreateDevice() { vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT{ .extendedDynamicState = true, }, + vk::PhysicalDeviceExtendedDynamicState2FeaturesEXT{ + .extendedDynamicState2 = true, + }, vk::PhysicalDeviceMaintenance4FeaturesKHR{ .maintenance4 = true, }, diff --git a/src/video_core/renderer_vulkan/vk_instance.h b/src/video_core/renderer_vulkan/vk_instance.h index 013003b9b..04b68c1d0 100644 --- a/src/video_core/renderer_vulkan/vk_instance.h +++ b/src/video_core/renderer_vulkan/vk_instance.h @@ -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; diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index d51c8fbd5..17a1fdec4 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -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; @@ -267,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), @@ -285,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; diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 87d07a967..ecb0c0a75 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -947,81 +947,18 @@ void Rasterizer::UnmapMemory(VAddr addr, u64 size) { } void Rasterizer::UpdateDynamicState(const GraphicsPipeline& pipeline) { - UpdateViewportScissorState(pipeline); + UpdateViewportScissorState(); + UpdateDepthStencilState(); - auto& regs = liverpool->regs; + const auto& regs = liverpool->regs; const auto cmdbuf = scheduler.CommandBuffer(); cmdbuf.setBlendConstants(®s.blend_constants.red); - 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); - } - } } -void Rasterizer::UpdateViewportScissorState(const GraphicsPipeline& pipeline) { +void Rasterizer::UpdateViewportScissorState() { 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. @@ -1139,6 +1076,90 @@ void Rasterizer::UpdateViewportScissorState(const GraphicsPipeline& pipeline) { cmdbuf.setScissorWithCountEXT(scissors); } +void Rasterizer::UpdateDepthStencilState() { + auto& regs = liverpool->regs; + const auto cmdbuf = scheduler.CommandBuffer(); + + bool depth_test = regs.depth_control.depth_enable && regs.depth_buffer.DepthValid(); + cmdbuf.setDepthTestEnableEXT(depth_test); + cmdbuf.setDepthWriteEnableEXT(regs.depth_control.depth_write_enable && + !regs.depth_render_control.depth_clear_enable); + if (depth_test) { + cmdbuf.setDepthCompareOpEXT(LiverpoolToVK::CompareOp(regs.depth_control.depth_func)); + } + + if (instance.IsDepthBoundsSupported()) { + cmdbuf.setDepthBoundsTestEnableEXT(regs.depth_control.depth_bounds_enable); + if (regs.depth_control.depth_bounds_enable) { + cmdbuf.setDepthBounds(regs.depth_bounds_min, regs.depth_bounds_max); + } + } + + cmdbuf.setDepthBiasEnableEXT(regs.polygon_control.NeedsBias()); + 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); + } + + cmdbuf.setStencilTestEnableEXT(regs.depth_control.stencil_enable && + regs.depth_buffer.StencilValid()); + 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); + } + } +} + void Rasterizer::ScopeMarkerBegin(const std::string_view& str, bool from_guest) { if ((from_guest && !Config::getVkGuestMarkersEnabled()) || (!from_guest && !Config::getVkHostMarkersEnabled())) { diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index 2fac8c8da..8e5d0065b 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h @@ -76,7 +76,8 @@ private: void EliminateFastClear(); void UpdateDynamicState(const GraphicsPipeline& pipeline); - void UpdateViewportScissorState(const GraphicsPipeline& pipeline); + void UpdateViewportScissorState(); + void UpdateDepthStencilState(); bool FilterDraw(); From 9d2175180e1dafeecefef5d7870376c199107b6c Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Mon, 7 Apr 2025 02:22:51 -0700 Subject: [PATCH 25/34] build: Move versioning to CMake file. (#2752) --- CMakeLists.txt | 7 ++++--- src/common/config.cpp | 10 +++++----- src/common/scm_rev.cpp.in | 22 +++++++++------------- src/common/scm_rev.h | 3 +++ src/common/version.h | 14 -------------- src/emulator.cpp | 11 +++++------ src/input/input_handler.cpp | 1 - src/qt_gui/check_update.cpp | 5 ++--- src/qt_gui/gui_context_menus.h | 6 +++--- src/qt_gui/main_window.cpp | 9 ++++----- src/qt_gui/settings_dialog.cpp | 4 ++-- src/sdl_window.cpp | 1 - 12 files changed, 37 insertions(+), 56 deletions(-) delete mode 100644 src/common/version.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 2af30ed46..844553340 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -202,6 +202,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}") @@ -671,7 +673,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 @@ -1193,8 +1194,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) diff --git a/src/common/config.cpp b/src/common/config.cpp index 2657cd12a..111c0cfa9 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -7,10 +7,10 @@ #include // for wstring support #include +#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 @@ -763,7 +763,7 @@ void load(const std::filesystem::path& path) { logFilter = toml::find_or(general, "logFilter", ""); logType = toml::find_or(general, "logType", "sync"); userName = toml::find_or(general, "userName", "shadPS4"); - if (Common::isRelease) { + if (Common::g_is_release) { updateChannel = toml::find_or(general, "updateChannel", "Release"); } else { updateChannel = toml::find_or(general, "updateChannel", "Nightly"); @@ -1108,7 +1108,7 @@ void setDefaultValues() { logFilter = ""; logType = "sync"; userName = "shadPS4"; - if (Common::isRelease) { + if (Common::g_is_release) { updateChannel = "Release"; } else { updateChannel = "Nightly"; diff --git a/src/common/scm_rev.cpp.in b/src/common/scm_rev.cpp.in index 2de04e0be..71c4c2d0a 100644 --- a/src/common/scm_rev.cpp.in +++ b/src/common/scm_rev.cpp.in @@ -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 diff --git a/src/common/scm_rev.h b/src/common/scm_rev.h index f38efff42..36b844e94 100644 --- a/src/common/scm_rev.h +++ b/src/common/scm_rev.h @@ -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[]; diff --git a/src/common/version.h b/src/common/version.h deleted file mode 100644 index 652f36e6d..000000000 --- a/src/common/version.h +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include -#include - -namespace Common { - -constexpr char VERSION[] = "0.7.1 WIP"; -constexpr bool isRelease = false; - -} // namespace Common diff --git a/src/emulator.cpp b/src/emulator.cpp index 5f94f008a..1a71b99cb 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -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", 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 #include #include -#include #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); diff --git a/src/qt_gui/gui_context_menus.h b/src/qt_gui/gui_context_menus.h index b5732d0ca..0aff80ccc 100644 --- a/src/qt_gui/gui_context_menus.h +++ b/src/qt_gui/gui_context_menus.h @@ -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,7 +115,7 @@ public: compatibilityMenu->addAction(updateCompatibility); compatibilityMenu->addAction(viewCompatibilityReport); - if (Common::isRelease) { + if (Common::g_is_release) { compatibilityMenu->addAction(submitCompatibilityReport); } @@ -571,7 +571,7 @@ public: 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)); + query.addQueryItem("emulator-version", QString(Common::g_version)); url.setQuery(query); QDesktopServices::openUrl(url); diff --git a/src/qt_gui/main_window.cpp b/src/qt_gui/main_window.cpp index 072ad70e5..60ab58274 100644 --- a/src/qt_gui/main_window.cpp +++ b/src/qt_gui/main_window.cpp @@ -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" @@ -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); } } diff --git a/src/qt_gui/settings_dialog.cpp b/src/qt_gui/settings_dialog.cpp index 25c27fef3..5ee802b0c 100644 --- a/src/qt_gui/settings_dialog.cpp +++ b/src/qt_gui/settings_dialog.cpp @@ -9,7 +9,7 @@ #include #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" @@ -491,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 diff --git a/src/sdl_window.cpp b/src/sdl_window.cpp index fcdde7240..e369240c6 100644 --- a/src/sdl_window.cpp +++ b/src/sdl_window.cpp @@ -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" From b8f6ef1c0b197291091af15713d48ac240fa61a9 Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Mon, 7 Apr 2025 02:23:04 -0700 Subject: [PATCH 26/34] externals: Update MoltenVK (#2754) --- CMakeLists.txt | 2 +- externals/MoltenVK/MoltenVK | 2 +- externals/MoltenVK/SPIRV-Cross | 2 +- externals/vulkan-headers | 2 +- src/video_core/renderer_vulkan/vk_platform.cpp | 10 ---------- 5 files changed, 4 insertions(+), 14 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 844553340..c5d9f7c9c 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -220,7 +220,7 @@ 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) diff --git a/externals/MoltenVK/MoltenVK b/externals/MoltenVK/MoltenVK index 2048427e5..83510e0f3 160000 --- a/externals/MoltenVK/MoltenVK +++ b/externals/MoltenVK/MoltenVK @@ -1 +1 @@ -Subproject commit 2048427e50f9eb20f2b8f98d316ecaee398c9b91 +Subproject commit 83510e0f3835c3c43651dda087305abc42572e17 diff --git a/externals/MoltenVK/SPIRV-Cross b/externals/MoltenVK/SPIRV-Cross index 2c32b6bf8..cb71abe30 160000 --- a/externals/MoltenVK/SPIRV-Cross +++ b/externals/MoltenVK/SPIRV-Cross @@ -1 +1 @@ -Subproject commit 2c32b6bf86f3c4a5539aa1f0bacbd59fe61759cf +Subproject commit cb71abe3063094bf383379b15473d39cb1144120 diff --git a/externals/vulkan-headers b/externals/vulkan-headers index a03d2f6d5..952f776f6 160000 --- a/externals/vulkan-headers +++ b/externals/vulkan-headers @@ -1 +1 @@ -Subproject commit a03d2f6d5753b365d704d58161825890baad0755 +Subproject commit 952f776f6573aafbb62ea717d871cd1d6816c387 diff --git a/src/video_core/renderer_vulkan/vk_platform.cpp b/src/video_core/renderer_vulkan/vk_platform.cpp index 716473377..e656369b2 100644 --- a/src/video_core/renderer_vulkan/vk_platform.cpp +++ b/src/video_core/renderer_vulkan/vk_platform.cpp @@ -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 }; From 473b66649f6fc4645812526eb21b520f8f88f302 Mon Sep 17 00:00:00 2001 From: kalaposfos13 <153381648+kalaposfos13@users.noreply.github.com> Date: Mon, 7 Apr 2025 11:25:49 +0200 Subject: [PATCH 27/34] Fix compatibility related issues in the GUI (#2755) Co-authored-by: georgemoralis --- src/qt_gui/gui_context_menus.h | 43 ++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/src/qt_gui/gui_context_menus.h b/src/qt_gui/gui_context_menus.h index 0aff80ccc..2fd4588d2 100644 --- a/src/qt_gui/gui_context_menus.h +++ b/src/qt_gui/gui_context_menus.h @@ -122,7 +122,8 @@ public: 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); @@ -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::g_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)); + } } } From 040fd79ef7fa3b47683a98d6cbc301c368ca6807 Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Mon, 7 Apr 2025 10:57:39 -0700 Subject: [PATCH 28/34] Revert "build: Target same CPU architecture level as PS4. (#2745)" (#2757) * Revert "build: Target same CPU architecture level as PS4. (#2745)" This reverts commit 54b4d7fc788d570c14924d21fbb1f58de0254aad. Causing issues on M1 CPUs for some reason. * build: Update architecture comments and set mtune=generic. --- CMakeLists.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c5d9f7c9c..7f3d4468f 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,8 +54,9 @@ else() endif() if (ARCHITECTURE STREQUAL "x86_64") - # Target the same x86_64 feature set as the PS4 CPU to match requirements. - add_compile_options(-march=btver2 -mno-sse4a) + # Target Sandy Bridge as a reasonable subset of instructions supported by PS4 and host CPUs. + # Note that the native PS4 architecture 'btver2' has been attempted but causes issues with M1 CPUs. + add_compile_options(-march=sandybridge -mtune=generic) endif() if (APPLE AND ARCHITECTURE STREQUAL "x86_64" AND CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "arm64") From 7fee289b66bcc650e7fd7f116a36e0976ea9cdca Mon Sep 17 00:00:00 2001 From: Missake212 Date: Mon, 7 Apr 2025 19:29:51 +0100 Subject: [PATCH 29/34] Add information about firmware files (sys modules) in the README (#2758) * Update README.md * Update README.md * Update README.md --- README.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/README.md b/README.md index 6462c8bd2..0e2248970 100644 --- a/README.md +++ b/README.md @@ -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. + +
+ +| Modules | Modules | Modules | Modules | +|-------------------------|-------------------------|-------------------------|-------------------------| +| libSceCesCs.sprx | libSceFont.sprx | libSceFontFt.sprx | libSceFreeTypeOt.sprx | +| libSceJson.sprx | libSceJson2.sprx | libSceLibcInternal.sprx | libSceNgs2.sprx | +| libSceRtc.sprx | libSceUlt.sprx | | | + +
+ +> [!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) From 08731303d857ba0d8684f77e193f2958e7691ccb Mon Sep 17 00:00:00 2001 From: kalaposfos13 <153381648+kalaposfos13@users.noreply.github.com> Date: Mon, 7 Apr 2025 22:58:00 +0200 Subject: [PATCH 30/34] Fix incorrect calculation setting the center of the joysticks one value off causing stick drift in games that assume already corrected input values (#2760) --- src/input/input_handler.cpp | 6 +++--- src/input/input_mouse.cpp | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/input/input_handler.cpp b/src/input/input_handler.cpp index f7c2ee296..3e2d66a6b 100644 --- a/src/input/input_handler.cpp +++ b/src/input/input_handler.cpp @@ -550,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)); } } diff --git a/src/input/input_mouse.cpp b/src/input/input_mouse.cpp index 11feaeebb..c84d14b3f 100644 --- a/src/input/input_mouse.cpp +++ b/src/input/input_mouse.cpp @@ -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; From 03b1fef3318ce5f972e9d1c3590556e556343345 Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Tue, 8 Apr 2025 07:22:16 -0700 Subject: [PATCH 31/34] renderer_vulkan: Only update dynamic state when changed. (#2751) --- .../renderer_vulkan/vk_rasterizer.cpp | 139 +++++------ .../renderer_vulkan/vk_rasterizer.h | 6 +- .../renderer_vulkan/vk_scheduler.cpp | 136 +++++++++++ src/video_core/renderer_vulkan/vk_scheduler.h | 219 ++++++++++++++++++ 4 files changed, 414 insertions(+), 86 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index ecb0c0a75..600c205e3 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -946,19 +946,19 @@ void Rasterizer::UnmapMemory(VAddr addr, u64 size) { mapped_ranges -= boost::icl::interval::right_open(addr, addr + size); } -void Rasterizer::UpdateDynamicState(const GraphicsPipeline& pipeline) { +void Rasterizer::UpdateDynamicState(const GraphicsPipeline& pipeline) const { UpdateViewportScissorState(); UpdateDepthStencilState(); - const auto& regs = liverpool->regs; - const auto cmdbuf = scheduler.CommandBuffer(); - cmdbuf.setBlendConstants(®s.blend_constants.red); - if (instance.IsDynamicColorWriteMaskSupported()) { - cmdbuf.setColorWriteMaskEXT(0, pipeline.GetWriteMasks()); - } + auto& dynamic_state = scheduler.GetDynamicState(); + dynamic_state.SetBlendConstants(&liverpool->regs.blend_constants.red); + dynamic_state.SetColorWriteMasks(pipeline.GetWriteMasks()); + + // Commit new dynamic state to the command buffer. + dynamic_state.Commit(instance, scheduler.CommandBuffer()); } -void Rasterizer::UpdateViewportScissorState() { +void Rasterizer::UpdateViewportScissorState() const { const auto& regs = liverpool->regs; const auto combined_scissor_value_tl = [](s16 scr, s16 win, s16 gen, s16 win_offset) { @@ -1071,92 +1071,65 @@ void Rasterizer::UpdateViewportScissorState() { 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() { - auto& regs = liverpool->regs; - const auto cmdbuf = scheduler.CommandBuffer(); +void Rasterizer::UpdateDepthStencilState() const { + const auto& regs = liverpool->regs; + auto& dynamic_state = scheduler.GetDynamicState(); - bool depth_test = regs.depth_control.depth_enable && regs.depth_buffer.DepthValid(); - cmdbuf.setDepthTestEnableEXT(depth_test); - cmdbuf.setDepthWriteEnableEXT(regs.depth_control.depth_write_enable && - !regs.depth_render_control.depth_clear_enable); - if (depth_test) { - cmdbuf.setDepthCompareOpEXT(LiverpoolToVK::CompareOp(regs.depth_control.depth_func)); + 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)); } - if (instance.IsDepthBoundsSupported()) { - cmdbuf.setDepthBoundsTestEnableEXT(regs.depth_control.depth_bounds_enable); - if (regs.depth_control.depth_bounds_enable) { - cmdbuf.setDepthBounds(regs.depth_bounds_min, regs.depth_bounds_max); - } + 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); } - cmdbuf.setDepthBiasEnableEXT(regs.polygon_control.NeedsBias()); - 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); + const auto depth_bias_enabled = regs.polygon_control.NeedsBias(); + if (depth_bias_enabled) { + dynamic_state.SetDepthBias( + regs.polygon_control.enable_polygon_offset_front ? regs.poly_offset.front_offset + : regs.poly_offset.back_offset, + regs.poly_offset.depth_bias, + (regs.polygon_control.enable_polygon_offset_front ? regs.poly_offset.front_scale + : regs.poly_offset.back_scale) / + 16.f); } - cmdbuf.setStencilTestEnableEXT(regs.depth_control.stencil_enable && - regs.depth_buffer.StencilValid()); - 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 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.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); - } + 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); } } diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index 8e5d0065b..02c24c7ec 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h @@ -75,9 +75,9 @@ private: void DepthStencilCopy(bool is_depth, bool is_stencil); void EliminateFastClear(); - void UpdateDynamicState(const GraphicsPipeline& pipeline); - void UpdateViewportScissorState(); - void UpdateDepthStencilState(); + void UpdateDynamicState(const GraphicsPipeline& pipeline) const; + void UpdateViewportScissorState() const; + void UpdateDepthStencilState() const; bool FilterDraw(); diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp index fd84c54ed..6b872bdaa 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.cpp +++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp @@ -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 diff --git a/src/video_core/renderer_vulkan/vk_scheduler.h b/src/video_core/renderer_vulkan/vk_scheduler.h index fd5e68373..880bd4b04 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.h +++ b/src/video_core/renderer_vulkan/vk_scheduler.h @@ -7,6 +7,7 @@ #include #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; +using Scissors = boost::container::static_vector; +using ColorWriteMasks = std::array; +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 pending_ops; RenderState render_state; + DynamicState dynamic_state; bool is_rendering = false; tracy::VkCtxScope* profiler_scope{}; }; From 29656563259be924e04dca02e5f2a7c63f27beee Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Wed, 9 Apr 2025 00:54:39 -0700 Subject: [PATCH 32/34] build: Target same CPU architecture level as PS4. (#2763) --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f3d4468f..37492eeb3 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,9 +54,9 @@ else() endif() if (ARCHITECTURE STREQUAL "x86_64") - # Target Sandy Bridge as a reasonable subset of instructions supported by PS4 and host CPUs. - # Note that the native PS4 architecture 'btver2' has been attempted but causes issues with M1 CPUs. - add_compile_options(-march=sandybridge -mtune=generic) + # 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") From e3b1c041d0de657795e8753cea34da8481c61c4c Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Wed, 9 Apr 2025 00:59:33 -0700 Subject: [PATCH 33/34] documents: Update macOS version in quickstart guide. --- documents/Quickstart/Quickstart.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documents/Quickstart/Quickstart.md b/documents/Quickstart/Quickstart.md index 9c6bc5a6f..55825ac7d 100644 --- a/documents/Quickstart/Quickstart.md +++ b/documents/Quickstart/Quickstart.md @@ -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 From 5abec2a2917a52cf01f2ef9f5c9e3e2656988383 Mon Sep 17 00:00:00 2001 From: Dmugetsu <168934208+diegolix29@users.noreply.github.com> Date: Wed, 9 Apr 2025 18:06:54 -0600 Subject: [PATCH 34/34] Enabling Depth Bias Explicity (#2766) --- src/video_core/renderer_vulkan/vk_rasterizer.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 600c205e3..5aae43cc8 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -1096,14 +1096,13 @@ void Rasterizer::UpdateDepthStencilState() const { } 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( - regs.polygon_control.enable_polygon_offset_front ? regs.poly_offset.front_offset - : regs.poly_offset.back_offset, + front ? regs.poly_offset.front_offset : regs.poly_offset.back_offset, regs.poly_offset.depth_bias, - (regs.polygon_control.enable_polygon_offset_front ? regs.poly_offset.front_scale - : regs.poly_offset.back_scale) / - 16.f); + (front ? regs.poly_offset.front_scale : regs.poly_offset.back_scale) / 16.f); } const auto stencil_test_enabled =