diff --git a/.ci/deploy-mac-arm64.sh b/.ci/deploy-mac-arm64.sh
index e7de472378..d556a9442b 100755
--- a/.ci/deploy-mac-arm64.sh
+++ b/.ci/deploy-mac-arm64.sh
@@ -48,24 +48,8 @@ echo "[InternetShortcut]" > Quickstart.url
echo "URL=https://rpcs3.net/quickstart" >> Quickstart.url
echo "IconIndex=0" >> Quickstart.url
-#DMG_FILEPATH="$BUILD_ARTIFACTSTAGINGDIRECTORY/rpcs3-v${COMM_TAG}-${COMM_COUNT}-${COMM_HASH}_macos_arm64.dmg"
-#"$BREW_X64_PATH/bin/create-dmg" --volname RPCS3 \
-#--window-size 800 400 \
-#--icon-size 100 \
-#--icon rpcs3.app 200 190 \
-#--add-file Quickstart.url Quickstart.url 400 20 \
-#--hide-extension rpcs3.app \
-#--hide-extension Quickstart.url \
-#--app-drop-link 600 185 \
-#--skip-jenkins \
-#--format ULMO \
-#"$DMG_FILEPATH" \
-#RPCS3.app
-#FILESIZE=$(stat -f %z "$DMG_FILEPATH")
-#SHA256SUM=$(shasum -a 256 "$DMG_FILEPATH" | awk '{ print $1 }')
-
ARCHIVE_FILEPATH="$BUILD_ARTIFACTSTAGINGDIRECTORY/rpcs3-v${COMM_TAG}-${COMM_COUNT}-${COMM_HASH}_macos_arm64.7z"
-"$BREW_PATH/bin/7z" a -mx9 "$ARCHIVE_FILEPATH" RPCS3.app Quickstart.url
+"/opt/homebrew/bin/7z" a -mx9 "$ARCHIVE_FILEPATH" RPCS3.app Quickstart.url
FILESIZE=$(stat -f %z "$ARCHIVE_FILEPATH")
SHA256SUM=$(shasum -a 256 "$ARCHIVE_FILEPATH" | awk '{ print $1 }')
diff --git a/.ci/setup-windows.sh b/.ci/setup-windows.sh
index 0924023228..f637cec9ad 100755
--- a/.ci/setup-windows.sh
+++ b/.ci/setup-windows.sh
@@ -8,7 +8,7 @@ QT_URL_VER=$(echo "$QT_VER" | sed "s/\.//g")
QT_VER_MSVC_UP=$(echo "${QT_VER_MSVC}" | tr '[:lower:]' '[:upper:]')
QT_PREFIX="online/qtsdkrepository/windows_x86/desktop/qt${QT_VER_MAIN}_${QT_URL_VER}/qt${QT_VER_MAIN}_${QT_URL_VER}/qt.qt${QT_VER_MAIN}.${QT_URL_VER}."
QT_PREFIX_2="win64_${QT_VER_MSVC}_64/${QT_VER}-0-${QT_DATE}"
-QT_SUFFIX="-Windows-Windows_11_23H2-${QT_VER_MSVC_UP}-Windows-Windows_11_23H2-X86_64.7z"
+QT_SUFFIX="-Windows-Windows_11_24H2-${QT_VER_MSVC_UP}-Windows-Windows_11_24H2-X86_64.7z"
QT_BASE_URL="${QT_HOST}${QT_PREFIX}${QT_PREFIX_2}qtbase${QT_SUFFIX}"
QT_DECL_URL="${QT_HOST}${QT_PREFIX}${QT_PREFIX_2}qtdeclarative${QT_SUFFIX}"
QT_TOOL_URL="${QT_HOST}${QT_PREFIX}${QT_PREFIX_2}qttools${QT_SUFFIX}"
diff --git a/.github/workflows/rpcs3.yml b/.github/workflows/rpcs3.yml
index 6457334be8..2d5b29acf1 100644
--- a/.github/workflows/rpcs3.yml
+++ b/.github/workflows/rpcs3.yml
@@ -212,9 +212,9 @@ jobs:
env:
COMPILER: msvc
QT_VER_MAIN: '6'
- QT_VER: '6.9.3'
+ QT_VER: '6.10.0'
QT_VER_MSVC: 'msvc2022'
- QT_DATE: '202509261208'
+ QT_DATE: '202510021201'
LLVM_VER: '19.1.7'
VULKAN_VER: '1.3.268.0'
VULKAN_SDK_SHA: '8459ef49bd06b697115ddd3d97c9aec729e849cd775f5be70897718a9b3b9db5'
diff --git a/3rdparty/7zip/7zip b/3rdparty/7zip/7zip
index 395149956d..5e96a82794 160000
--- a/3rdparty/7zip/7zip
+++ b/3rdparty/7zip/7zip
@@ -1 +1 @@
-Subproject commit 395149956d696e6e3099d8b76d797437f94a6942
+Subproject commit 5e96a8279489832924056b1fa82f29d5837c9469
diff --git a/3rdparty/CMakeLists.txt b/3rdparty/CMakeLists.txt
index 94c6069271..46307746a3 100644
--- a/3rdparty/CMakeLists.txt
+++ b/3rdparty/CMakeLists.txt
@@ -51,6 +51,14 @@ else()
add_subdirectory(pugixml EXCLUDE_FROM_ALL)
endif()
+if (USE_SYSTEM_VULKAN_MEMORY_ALLOCATOR)
+ find_package(VulkanMemoryAllocator REQUIRED GLOBAL)
+ add_library(3rdparty::vulkanmemoryallocator ALIAS GPUOpen::VulkanMemoryAllocator)
+else()
+ add_library(3rdparty_vulkanmemoryallocator INTERFACE)
+ target_include_directories(3rdparty_vulkanmemoryallocator INTERFACE GPUOpen/VulkanMemoryAllocator/include)
+ add_library(3rdparty::vulkanmemoryallocator ALIAS 3rdparty_vulkanmemoryallocator)
+endif()
# libusb
if(CMAKE_SYSTEM_NAME MATCHES "DragonFly|FreeBSD")
@@ -92,9 +100,6 @@ add_subdirectory(hidapi)
# glslang
add_subdirectory(glslang EXCLUDE_FROM_ALL)
-add_library(3rdparty_glslang INTERFACE)
-target_link_libraries(3rdparty_glslang INTERFACE SPIRV)
-
# yaml-cpp
add_subdirectory(yaml-cpp)
@@ -388,7 +393,7 @@ add_library(3rdparty::wolfssl ALIAS wolfssl)
add_library(3rdparty::libcurl ALIAS 3rdparty_libcurl)
add_library(3rdparty::soundtouch ALIAS soundtouch)
add_library(3rdparty::sdl3 ALIAS ${SDL3_TARGET})
-add_library(3rdparty::miniupnpc ALIAS libminiupnpc-static)
+add_library(3rdparty::miniupnpc ALIAS 3rdparty_miniupnpc)
add_library(3rdparty::rtmidi ALIAS rtmidi)
add_library(3rdparty::opencv ALIAS ${OPENCV_TARGET})
add_library(3rdparty::fusion ALIAS Fusion)
diff --git a/3rdparty/FAudio b/3rdparty/FAudio
index e6ddfabab2..ba876ce3be 160000
--- a/3rdparty/FAudio
+++ b/3rdparty/FAudio
@@ -1 +1 @@
-Subproject commit e6ddfabab2efbc8765750039634fe5e24ac31205
+Subproject commit ba876ce3be73eabd7094fa276a751ede8328b608
diff --git a/3rdparty/cubeb/cubeb b/3rdparty/cubeb/cubeb
index 70b4e3db78..e495bee4cd 160000
--- a/3rdparty/cubeb/cubeb
+++ b/3rdparty/cubeb/cubeb
@@ -1 +1 @@
-Subproject commit 70b4e3db7822de4d534959885cda109d6edbee36
+Subproject commit e495bee4cd630c9f99907a764e16edba37a4b564
diff --git a/3rdparty/curl/curl b/3rdparty/curl/curl
index fdb8a789d2..11b991232f 160000
--- a/3rdparty/curl/curl
+++ b/3rdparty/curl/curl
@@ -1 +1 @@
-Subproject commit fdb8a789d2b446b77bd7cdd2eff95f6cbc814cf4
+Subproject commit 11b991232fbcaa88e2b1faecac224416b0001e35
diff --git a/3rdparty/curl/libcurl.vcxproj b/3rdparty/curl/libcurl.vcxproj
index c4a96abdc4..e39805855d 100644
--- a/3rdparty/curl/libcurl.vcxproj
+++ b/3rdparty/curl/libcurl.vcxproj
@@ -70,6 +70,7 @@
+
@@ -79,6 +80,7 @@
+
@@ -86,6 +88,7 @@
+
@@ -144,7 +147,6 @@
-
@@ -199,7 +201,6 @@
-
@@ -225,7 +226,6 @@
-
@@ -233,7 +233,6 @@
-
@@ -258,6 +257,7 @@
+
@@ -271,8 +271,10 @@
+
+
@@ -280,6 +282,7 @@
+
@@ -297,6 +300,7 @@
+
@@ -345,7 +349,6 @@
-
@@ -397,7 +400,6 @@
-
@@ -415,14 +417,12 @@
-
-
diff --git a/3rdparty/curl/libcurl.vcxproj.filters b/3rdparty/curl/libcurl.vcxproj.filters
index 32eb05f40e..4bd52daddf 100644
--- a/3rdparty/curl/libcurl.vcxproj.filters
+++ b/3rdparty/curl/libcurl.vcxproj.filters
@@ -159,9 +159,6 @@
Source Files
-
- Source Files
-
Source Files
@@ -339,9 +336,6 @@
Source Files
-
- Source Files
-
Source Files
@@ -360,9 +354,6 @@
Source Files
-
- Source Files
-
Source Files
@@ -426,9 +417,6 @@
Source Files
-
- Source Files
-
Source Files
@@ -549,6 +537,15 @@
Source Files
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
@@ -758,9 +755,6 @@
Header Files
-
- Header Files
-
Header Files
@@ -899,9 +893,6 @@
Header Files
-
- Header Files
-
Header Files
@@ -917,9 +908,6 @@
Header Files
-
- Header Files
-
Header Files
@@ -989,9 +977,6 @@
Header Files
-
- Header Files
-
Header Files
@@ -1112,6 +1097,21 @@
Header Files
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
diff --git a/3rdparty/glslang/CMakeLists.txt b/3rdparty/glslang/CMakeLists.txt
index 5b6aa8e962..c86d0b384c 100644
--- a/3rdparty/glslang/CMakeLists.txt
+++ b/3rdparty/glslang/CMakeLists.txt
@@ -1,11 +1,23 @@
#glslang
-set(ENABLE_PCH OFF CACHE BOOL "Enables Precompiled header" FORCE)
-set(BUILD_EXTERNAL OFF CACHE BOOL "Build external dependencies in /External" FORCE)
-set(SKIP_GLSLANG_INSTALL ON CACHE BOOL "Skip installation" FORCE)
-set(ENABLE_SPVREMAPPER OFF CACHE BOOL "Enables building of SPVRemapper" FORCE)
-set(ENABLE_GLSLANG_BINARIES OFF CACHE BOOL "Builds glslangValidator and spirv-remap" FORCE)
-set(ENABLE_HLSL OFF CACHE BOOL "Enables HLSL input support" FORCE)
-set(ENABLE_OPT OFF CACHE BOOL "Enables spirv-opt capability if present" FORCE)
-set(ENABLE_CTEST OFF CACHE BOOL "Enables testing" FORCE)
-add_subdirectory(glslang)
+if(USE_SYSTEM_GLSLANG)
+ message(STATUS "RPCS3: using shared glslang")
+ find_package(glslang REQUIRED GLOBAL)
+ add_library(3rdparty_glslang INTERFACE)
+ target_link_libraries(3rdparty_glslang INTERFACE glslang::SPIRV)
+ get_target_property(SPIRV_INCLUDE_DIRS glslang::SPIRV INTERFACE_INCLUDE_DIRECTORIES)
+ list(TRANSFORM SPIRV_INCLUDE_DIRS APPEND "/glslang")
+ target_include_directories(3rdparty_glslang INTERFACE ${SPIRV_INCLUDE_DIRS})
+else()
+ set(ENABLE_PCH OFF CACHE BOOL "Enables Precompiled header" FORCE)
+ set(BUILD_EXTERNAL OFF CACHE BOOL "Build external dependencies in /External" FORCE)
+ set(SKIP_GLSLANG_INSTALL ON CACHE BOOL "Skip installation" FORCE)
+ set(ENABLE_SPVREMAPPER OFF CACHE BOOL "Enables building of SPVRemapper" FORCE)
+ set(ENABLE_GLSLANG_BINARIES OFF CACHE BOOL "Builds glslangValidator and spirv-remap" FORCE)
+ set(ENABLE_HLSL OFF CACHE BOOL "Enables HLSL input support" FORCE)
+ set(ENABLE_OPT OFF CACHE BOOL "Enables spirv-opt capability if present" FORCE)
+ set(ENABLE_CTEST OFF CACHE BOOL "Enables testing" FORCE)
+ add_subdirectory(glslang)
+ add_library(3rdparty_glslang INTERFACE)
+ target_link_libraries(3rdparty_glslang INTERFACE SPIRV)
+endif()
diff --git a/3rdparty/hidapi/CMakeLists.txt b/3rdparty/hidapi/CMakeLists.txt
index e1e36ac13e..2d043d6936 100644
--- a/3rdparty/hidapi/CMakeLists.txt
+++ b/3rdparty/hidapi/CMakeLists.txt
@@ -1,22 +1,30 @@
# hidapi
-set(BUILD_SHARED_LIBS FALSE CACHE BOOL "Don't build shared libs")
-set(HIDAPI_INSTALL_TARGETS FALSE CACHE BOOL "Don't install anything")
-
-if(CMAKE_SYSTEM MATCHES "Linux")
- set(HIDAPI_WITH_LIBUSB FALSE CACHE BOOL "Don't build with libusb for linux")
-endif()
-
-add_library(3rdparty_hidapi INTERFACE)
-add_subdirectory(hidapi EXCLUDE_FROM_ALL)
-
-if(APPLE)
- target_link_libraries(3rdparty_hidapi INTERFACE hidapi_darwin "-framework CoreFoundation" "-framework IOKit")
-elseif(CMAKE_SYSTEM MATCHES "Linux")
- target_link_libraries(3rdparty_hidapi INTERFACE hidapi-hidraw udev)
-elseif(WIN32)
- target_link_libraries(3rdparty_hidapi INTERFACE hidapi::hidapi hidapi::include Shlwapi.lib)
-elseif(ANDROID)
- target_link_libraries(3rdparty_hidapi INTERFACE hidapi::libusb)
+if(USE_SYSTEM_HIDAPI)
+ message(STATUS "RPCS3: using shared hidapi")
+ pkg_check_modules(hidapi-hidraw REQUIRED IMPORTED_TARGET hidapi-hidraw)
+ add_library(3rdparty_hidapi INTERFACE)
+ target_link_libraries(3rdparty_hidapi INTERFACE PkgConfig::hidapi-hidraw)
+ target_include_directories(3rdparty_hidapi INTERFACE PkgConfig::hidapi-hidraw)
else()
- target_link_libraries(3rdparty_hidapi INTERFACE hidapi-libusb usb)
+ set(BUILD_SHARED_LIBS FALSE CACHE BOOL "Don't build shared libs")
+ set(HIDAPI_INSTALL_TARGETS FALSE CACHE BOOL "Don't install anything")
+
+ if(CMAKE_SYSTEM MATCHES "Linux")
+ set(HIDAPI_WITH_LIBUSB FALSE CACHE BOOL "Don't build with libusb for linux")
+ endif()
+
+ add_library(3rdparty_hidapi INTERFACE)
+ add_subdirectory(hidapi EXCLUDE_FROM_ALL)
+
+ if(APPLE)
+ target_link_libraries(3rdparty_hidapi INTERFACE hidapi_darwin "-framework CoreFoundation" "-framework IOKit")
+ elseif(CMAKE_SYSTEM MATCHES "Linux")
+ target_link_libraries(3rdparty_hidapi INTERFACE hidapi-hidraw udev)
+ elseif(WIN32)
+ target_link_libraries(3rdparty_hidapi INTERFACE hidapi::hidapi hidapi::include Shlwapi.lib)
+ elseif(ANDROID)
+ target_link_libraries(3rdparty_hidapi INTERFACE hidapi::libusb)
+ else()
+ target_link_libraries(3rdparty_hidapi INTERFACE hidapi-libusb usb)
+ endif()
endif()
diff --git a/3rdparty/libsdl-org/SDL b/3rdparty/libsdl-org/SDL
index c9a6709bd2..a8589a8422 160000
--- a/3rdparty/libsdl-org/SDL
+++ b/3rdparty/libsdl-org/SDL
@@ -1 +1 @@
-Subproject commit c9a6709bd21750f1ad9597be21abace78c6378c9
+Subproject commit a8589a84226a6202831a3d49ff4edda4acab9acd
diff --git a/3rdparty/libsdl-org/SDL.vcxproj.filters b/3rdparty/libsdl-org/SDL.vcxproj.filters
index 44d4e4ec9f..d6a29f2faf 100644
--- a/3rdparty/libsdl-org/SDL.vcxproj.filters
+++ b/3rdparty/libsdl-org/SDL.vcxproj.filters
@@ -172,9 +172,6 @@
{f48c2b17-1bee-4fec-a7c8-24cf619abe08}
-
- {653672cc-90ae-4eba-a256-6479f2c31804}
-
{00001967ea2801028a046a722a070000}
diff --git a/3rdparty/miniupnp/CMakeLists.txt b/3rdparty/miniupnp/CMakeLists.txt
index 93c3dc55cd..c40d4a5ebd 100644
--- a/3rdparty/miniupnp/CMakeLists.txt
+++ b/3rdparty/miniupnp/CMakeLists.txt
@@ -1,8 +1,21 @@
-option (UPNPC_BUILD_STATIC "Build static library" TRUE)
-option (UPNPC_BUILD_SHARED "Build shared library" FALSE)
-option (UPNPC_BUILD_TESTS "Build test executables" FALSE)
-option (UPNPC_BUILD_SAMPLE "Build sample executables" FALSE)
-option (NO_GETADDRINFO "Define NO_GETADDRINFO" FALSE)
-option (UPNPC_NO_INSTALL "Disable installation" TRUE)
+if(USE_SYSTEM_MINIUPNPC)
+ message(STATUS "RPCS3: using shared MiniUPnPc")
+ pkg_check_modules(MiniUPnPc REQUIRED IMPORTED_TARGET miniupnpc>=2.3.3)
+ add_library(3rdparty_miniupnpc INTERFACE)
+ target_link_libraries(3rdparty_miniupnpc INTERFACE PkgConfig::MiniUPnPc)
+ target_include_directories(3rdparty_miniupnpc INTERFACE PkgConfig::MiniUPnPc)
+ list(TRANSFORM MiniUPnPc_INCLUDE_DIRS APPEND "/miniupnpc")
+ target_include_directories(3rdparty_miniupnpc INTERFACE ${MiniUPnPc_INCLUDE_DIRS})
+else()
+ option (UPNPC_BUILD_STATIC "Build static library" TRUE)
+ option (UPNPC_BUILD_SHARED "Build shared library" FALSE)
+ option (UPNPC_BUILD_TESTS "Build test executables" FALSE)
+ option (UPNPC_BUILD_SAMPLE "Build sample executables" FALSE)
+ option (NO_GETADDRINFO "Define NO_GETADDRINFO" FALSE)
+ option (UPNPC_NO_INSTALL "Disable installation" TRUE)
-add_subdirectory(miniupnp/miniupnpc EXCLUDE_FROM_ALL)
+ add_subdirectory(miniupnp/miniupnpc EXCLUDE_FROM_ALL)
+ add_library(3rdparty_miniupnpc INTERFACE)
+ target_link_libraries(3rdparty_miniupnpc INTERFACE libminiupnpc-static)
+ target_include_directories(3rdparty_miniupnpc INTERFACE libminiupnpc-static)
+endif()
diff --git a/3rdparty/opencv/opencv b/3rdparty/opencv/opencv
index 50fb5e701d..67f53c26a7 160000
--- a/3rdparty/opencv/opencv
+++ b/3rdparty/opencv/opencv
@@ -1 +1 @@
-Subproject commit 50fb5e701d8b0d3fe8262ed84668a94cc8cbf0b1
+Subproject commit 67f53c26a701c2aeefd8033ec2f2079e04c438ca
diff --git a/3rdparty/rtmidi/CMakeLists.txt b/3rdparty/rtmidi/CMakeLists.txt
index 610f858c6d..b9dd286ce0 100644
--- a/3rdparty/rtmidi/CMakeLists.txt
+++ b/3rdparty/rtmidi/CMakeLists.txt
@@ -1,4 +1,12 @@
-option(RTMIDI_API_JACK "Compile with JACK support." OFF)
-option(RTMIDI_BUILD_TESTING "Build test programs" OFF)
-set(RTMIDI_TARGETNAME_UNINSTALL "uninstall-rpcs3-rtmidi")
-add_subdirectory(rtmidi EXCLUDE_FROM_ALL)
+if(USE_SYSTEM_RTMIDI)
+ message(STATUS "RPCS3: using shared RtMidi")
+ pkg_check_modules(RtMidi REQUIRED IMPORTED_TARGET rtmidi>=6.0.0)
+ add_library(rtmidi INTERFACE)
+ target_link_libraries(rtmidi INTERFACE PkgConfig::RtMidi)
+ target_include_directories(rtmidi INTERFACE PkgConfig::RtMidi)
+else()
+ option(RTMIDI_API_JACK "Compile with JACK support." OFF)
+ option(RTMIDI_BUILD_TESTING "Build test programs" OFF)
+ set(RTMIDI_TARGETNAME_UNINSTALL "uninstall-rpcs3-rtmidi")
+ add_subdirectory(rtmidi EXCLUDE_FROM_ALL)
+endif()
diff --git a/BUILDING.md b/BUILDING.md
index 311bbddeee..2de1dc1c50 100644
--- a/BUILDING.md
+++ b/BUILDING.md
@@ -19,26 +19,26 @@ The following tools are required to build RPCS3 on Windows 10 or later:
with standalone **CMake** tool.
- [Python 3.6+](https://www.python.org/downloads/) (add to PATH)
-- [Qt 6.9.1](https://www.qt.io/download-qt-installer) In case you can't download from the official installer, you can use [Another Qt installer](https://github.com/miurahr/aqtinstall) (In that case you will need to manually add the "qtmultimedia" module when installing Qt)
+- [Qt 6.10.0](https://www.qt.io/download-qt-installer) In case you can't download from the official installer, you can use [Another Qt installer](https://github.com/miurahr/aqtinstall) (In that case you will need to manually add the "qtmultimedia" module when installing Qt)
- [Vulkan SDK 1.3.268.0](https://vulkan.lunarg.com/sdk/home) (see "Install the SDK" [here](https://vulkan.lunarg.com/doc/sdk/latest/windows/getting_started.html)) for now future SDKs don't work. You need precisely 1.3.268.0.
The `sln` solution available only on **Visual Studio** is the preferred building solution. It easily allows to build the **RPCS3** application in `Release` and `Debug` mode.
In order to build **RPCS3** with the `sln` solution (with **Visual Studio**), **Qt** libs need to be detected. To detect the libs:
-- add and set the `QTDIR` environment variable, e.g. `\6.9.1\msvc2022_64\`
+- add and set the `QTDIR` environment variable, e.g. `\6.10.0\msvc2022_64\`
- or use the [Visual Studio Qt Plugin](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.QtVisualStudioTools2022)
**NOTE:** If you have issues with the **Visual Studio Qt Plugin**, you may want to uninstall it and install the [Legacy Qt Plugin](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.LEGACYQtVisualStudioTools2022) instead.
In order to build **RPCS3** with the `CMake` solution (with both **Visual Studio** and standalone **CMake** tool):
-- add and set the `Qt6_ROOT` environment variable to the **Qt** libs path, e.g. `\6.9.1\msvc2022_64\`
+- add and set the `Qt6_ROOT` environment variable to the **Qt** libs path, e.g. `\6.10.0\msvc2022_64\`
### Linux
These are the essentials tools to build RPCS3 on Linux. Some of them can be installed through your favorite package manager:
- Clang 17+ or GCC 13+
- [CMake 3.28.0+](https://www.cmake.org/download/)
-- [Qt 6.9.1](https://www.qt.io/download-qt-installer)
+- [Qt 6.10.0](https://www.qt.io/download-qt-installer)
- [Vulkan SDK 1.3.268.0](https://vulkan.lunarg.com/sdk/home) (See "Install the SDK" [here](https://vulkan.lunarg.com/doc/sdk/latest/linux/getting_started.html)) for now future SDKs don't work. You need precisely 1.3.268.0.
- [SDL3](https://github.com/libsdl-org/SDL/releases) (for the FAudio backend)
@@ -121,7 +121,7 @@ Start **Visual Studio**, click on `Open a project or solution` and select the `r
##### Configuring the Qt Plugin (if used)
1) go to `Extensions->Qt VS Tools->Qt Versions`
-2) add the path to your Qt installation with compiler e.g. `\6.9.1\msvc2022_64`, version will fill in automatically
+2) add the path to your Qt installation with compiler e.g. `\6.10.0\msvc2022_64`, version will fill in automatically
3) go to `Extensions->Qt VS Tools->Options->Legacy Project Format`. (Only available in the **Legacy Qt Plugin**)
4) set `Build: Run pre-build setup` to `true`. (Only available in the **Legacy Qt Plugin**)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index cb3ea2e435..92be9ce329 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -22,6 +22,12 @@ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
endif()
endif()
+if(APPLE OR WIN32)
+ set(USE_SYSTEM_OPENAL_DEFAULT OFF)
+else()
+ set(USE_SYSTEM_OPENAL_DEFAULT ON)
+endif()
+
option(USE_NATIVE_INSTRUCTIONS "USE_NATIVE_INSTRUCTIONS makes rpcs3 compile with -march=native, which is useful for local builds, but not good for packages." ON)
option(WITH_LLVM "Enable usage of LLVM library" ON)
option(BUILD_LLVM "Build LLVM from git submodule" OFF)
@@ -37,20 +43,26 @@ option(USE_SYSTEM_CURL "Prefer system Curl instead of the prebuild one" ON)
option(USE_SYSTEM_FAUDIO "Prefer system FAudio instead of the builtin one" OFF)
option(USE_SYSTEM_FFMPEG "Prefer system ffmpeg instead of the prebuild one" OFF)
option(USE_SYSTEM_FLATBUFFERS "Prefer system flatbuffers instead of the builtin one" OFF)
+option(USE_SYSTEM_GLSLANG "Prefer system glslang instead of the builtin one" OFF)
+option(USE_SYSTEM_HIDAPI "Prefer system hidapi instead of the builtin one" OFF)
option(USE_SYSTEM_LIBPNG "Prefer system libpng instead of the builtin one" OFF)
option(USE_SYSTEM_LIBUSB "Prefer system libusb instead of the builtin one" OFF)
+option(USE_SYSTEM_MINIUPNPC "Prefer system MiniUPnPc instead of the builtin one" OFF)
option(USE_SYSTEM_MVK "Prefer system MoltenVK instead of the builtin one" OFF)
-option(USE_SYSTEM_OPENAL "Prefer system OpenAL instead of the prebuild one" ON)
+option(USE_SYSTEM_OPENAL "Prefer system OpenAL instead of the prebuild one" ${USE_SYSTEM_OPENAL_DEFAULT})
option(USE_SYSTEM_OPENCV "Prefer system OpenCV instead of the builtin one" ON)
option(USE_SYSTEM_PUGIXML "Prefer system pugixml instead of the builtin one" OFF)
+option(USE_SYSTEM_RTMIDI "Prefer system RtMidi instead of the builtin one" OFF)
option(USE_SYSTEM_SDL "Prefer system SDL instead of the builtin one" ON)
-option(USE_SYSTEM_WOLFSSL "Prefer system MoltenVK instead of the builtin one" OFF)
+option(USE_SYSTEM_VULKAN_MEMORY_ALLOCATOR "Prefer system Vulkan Memory Allocator instead of the builtin one" OFF)
+option(USE_SYSTEM_WOLFSSL "Prefer system wolfSSL instead of the builtin one" OFF)
option(USE_SYSTEM_ZLIB "Prefer system ZLIB instead of the builtin one" ON)
-option(USE_SYSTEM_ZSTD "Prefer system zstd instead of the prebuild one" OFF)
+option(USE_SYSTEM_ZSTD "Prefer system zstd instead of the builtin one" OFF)
option(HAS_MEMORY_BREAKPOINTS "Add support for memory breakpoints to the interpreter" OFF)
option(USE_LTO "Use LTO for building" ON)
option(BUILD_RPCS3_TESTS "Build RPCS3 unit tests." OFF)
option(RUN_RPCS3_TESTS "Run RPCS3 unit tests. Requires BUILD_RPCS3_TESTS" OFF)
+option(USE_GAMEMODE "Choose whether to enable GameMode features or not." ON)
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/buildfiles/cmake")
@@ -157,11 +169,10 @@ endif()
## Look for Gamemode if its installed on Linux
if(LINUX)
- find_program(GAMEMODE_FOUND gamemoded) ## Only works if gamemode is installed on system (might include lib32 case)
- if(GAMEMODE_FOUND)
+ ## User chooses whether to Enable GameMode features or not
+ if(USE_GAMEMODE)
add_compile_definitions(GAMEMODE_AVAILABLE)
endif()
- message(GAMEMODE_AVAILABLE="${GAMEMODE_AVAILABLE}")
endif()
# TODO: do real installation, including copying directory structure
diff --git a/Utilities/Config.cpp b/Utilities/Config.cpp
index 0c2a1fa2aa..cee928def7 100644
--- a/Utilities/Config.cpp
+++ b/Utilities/Config.cpp
@@ -166,6 +166,55 @@ bool try_to_uint64(u64* out, std::string_view value, u64 min, u64 max)
return true;
}
+bool try_to_uint128(u128* out, std::string_view value)
+{
+ if (value.empty())
+ {
+ if (out) cfg_log.error("cfg::try_to_uint128(): called with an empty string");
+ return false;
+ }
+
+ u64 result_low = 0, result_high = 0;
+ const char* start_high64 = value.data();
+ const char* end = value.data() + value.size();
+
+ if (start_high64[0] == '0' && value.size() >= 2 && (start_high64[1] == 'x' || start_high64[1] == 'X'))
+ {
+ // Hex support
+ start_high64 += 2;
+ }
+
+ const char* start_low64 = end - std::min(end - start_high64, 16);
+
+ // Hexadecimal-only
+ constexpr int base = 16;
+
+ auto ret = std::from_chars(start_low64, end, result_low, base);
+
+ if (ret.ec != std::errc() || ret.ptr != end)
+ {
+ if (out) cfg_log.error("cfg::try_to_uint128('%s'): invalid integer", value);
+ return false;
+ }
+
+ if (start_high64 == start_low64)
+ {
+ if (out) *out = result_low;
+ return true;
+ }
+
+ ret = std::from_chars(start_high64, start_low64, result_high, base);
+
+ if (ret.ec != std::errc() || ret.ptr != start_low64)
+ {
+ if (out) cfg_log.error("cfg::try_to_uint128('%s'): invalid integer", value);
+ return false;
+ }
+
+ if (out) *out = result_low + (u128{result_high} << 64);
+ return true;
+}
+
std::vector cfg::make_float_range(f64 min, f64 max)
{
return {std::to_string(min), std::to_string(max)};
@@ -278,6 +327,19 @@ bool cfg::try_to_enum_value(u64* out, decltype(&fmt_class_string::format) f
return true;
}
+std::string cfg::uint128::to_string(u128 value) noexcept
+{
+ std::string result = "0x";
+ result.resize(result.size() + 32);
+
+ for (u32 i = 0; i < 32; i++)
+ {
+ result[result.size() - 1 - i] = "0123456789ABCDEF"[static_cast(value >> (i * 4)) % 16];
+ }
+
+ return result;
+}
+
std::vector cfg::try_to_enum_list(decltype(&fmt_class_string::format) func)
{
std::vector result;
@@ -553,19 +615,12 @@ void cfg::node::from_default()
}
}
-void cfg::_bool::from_default()
+void cfg::node::restore_defaults()
{
- m_value = def;
-}
-
-void cfg::string::from_default()
-{
- m_value = def;
-}
-
-void cfg::set_entry::from_default()
-{
- m_set = {};
+ for (auto& node : m_nodes)
+ {
+ node->restore_defaults();
+ }
}
std::string cfg::map_entry::get_value(std::string_view key)
diff --git a/Utilities/Config.h b/Utilities/Config.h
index bd05c25220..35dcddc1a6 100644
--- a/Utilities/Config.h
+++ b/Utilities/Config.h
@@ -38,6 +38,7 @@ namespace cfg
_enum, // cfg::_enum type
_int, // cfg::_int type
uint, // cfg::uint type
+ uint128, // cfg::uint128 type
string, // cfg::string type
set, // cfg::set_entry type
map, // cfg::map_entry type
@@ -90,6 +91,9 @@ namespace cfg
// Reset defaults
virtual void from_default() = 0;
+ // Restore default members
+ virtual void restore_defaults() = 0;
+
// Convert to string (optional)
virtual std::string to_string() const
{
@@ -151,11 +155,15 @@ namespace cfg
// Set default values
void from_default() override;
+
+ // Restore default members
+ void restore_defaults() override;
};
class _bool final : public _base
{
atomic_t m_value;
+ bool original_def;
public:
bool def;
@@ -163,6 +171,7 @@ namespace cfg
_bool(node* owner, std::string name, bool def = false, bool dynamic = false)
: _base(type::_bool, owner, std::move(name), dynamic)
, m_value(def)
+ , original_def(def)
, def(def)
{
}
@@ -177,7 +186,15 @@ namespace cfg
return m_value;
}
- void from_default() override;
+ void from_default() override
+ {
+ m_value = def;
+ }
+
+ void restore_defaults() override
+ {
+ def = original_def;
+ }
std::string to_string() const override
{
@@ -220,14 +237,16 @@ namespace cfg
class _enum : public _base
{
atomic_t m_value;
+ T original_def;
public:
- const T def;
+ T def;
- _enum(node* owner, const std::string& name, T value = {}, bool dynamic = false)
+ _enum(node* owner, const std::string& name, T def = {}, bool dynamic = false)
: _base(type::_enum, owner, name, dynamic)
- , m_value(value)
- , def(value)
+ , m_value(def)
+ , original_def(def)
+ , def(def)
{
}
@@ -256,6 +275,11 @@ namespace cfg
m_value = def;
}
+ void restore_defaults() override
+ {
+ def = original_def;
+ }
+
std::string to_string() const override
{
std::string result;
@@ -300,6 +324,7 @@ namespace cfg
using int_type = std::conditional_t= s32{smin} && Max <= s32{smax}, s32, s64>;
atomic_t m_value;
+ int_type original_def;
public:
int_type def;
@@ -311,6 +336,7 @@ namespace cfg
_int(node* owner, const std::string& name, int_type def = std::min(Max, std::max(Min, 0)), bool dynamic = false)
: _base(type::_int, owner, name, dynamic)
, m_value(def)
+ , original_def(def)
, def(def)
{
}
@@ -330,6 +356,11 @@ namespace cfg
m_value = def;
}
+ void restore_defaults() override
+ {
+ def = original_def;
+ }
+
std::string to_string() const override
{
return std::to_string(m_value);
@@ -372,6 +403,7 @@ namespace cfg
using float_type = f64;
atomic_t m_value;
+ float_type original_def;
public:
float_type def;
@@ -383,6 +415,7 @@ namespace cfg
_float(node* owner, const std::string& name, float_type def = std::min(Max, std::max(Min, 0)), bool dynamic = false)
: _base(type::_int, owner, name, dynamic)
, m_value(def)
+ , original_def(def)
, def(def)
{
}
@@ -402,6 +435,11 @@ namespace cfg
m_value = def;
}
+ void restore_defaults() override
+ {
+ def = original_def;
+ }
+
std::string to_string() const override
{
std::string result;
@@ -464,6 +502,7 @@ namespace cfg
using int_type = std::conditional_t;
atomic_t m_value;
+ int_type original_def;
public:
int_type def;
@@ -475,6 +514,7 @@ namespace cfg
uint(node* owner, const std::string& name, int_type def = std::max(Min, 0), bool dynamic = false)
: _base(type::uint, owner, name, dynamic)
, m_value(def)
+ , original_def(def)
, def(def)
{
}
@@ -494,6 +534,11 @@ namespace cfg
m_value = def;
}
+ void restore_defaults() override
+ {
+ def = original_def;
+ }
+
std::string to_string() const override
{
return std::to_string(m_value);
@@ -534,10 +579,91 @@ namespace cfg
// Alias for 64 bit int
using uint64 = uint<0, u64{umax}>;
+ // Unsigned 128-bit integer entry.
+ class uint128 final : public _base
+ {
+ using int_type = u128;
+
+ atomic_t m_value{};
+ int_type original_def = 0;
+
+ public:
+ int_type def;
+
+ uint128(node* owner, const std::string& name, int_type def = 0, bool dynamic = false)
+ : _base(type::uint128, owner, name, dynamic)
+ , m_value(def)
+ , original_def(def)
+ , def(def)
+ {
+ }
+
+ operator int_type() const
+ {
+ return m_value;
+ }
+
+ operator ullong() const
+ {
+ return static_cast(m_value.load());
+ }
+
+ int_type get() const
+ {
+ return m_value;
+ }
+
+ void from_default() override
+ {
+ m_value = def;
+ }
+
+ void restore_defaults() override
+ {
+ def = original_def;
+ }
+
+ static std::string to_string(u128 value) noexcept;
+
+ std::string to_string() const override
+ {
+ return to_string(m_value.load());
+ }
+
+ std::string def_to_string() const override
+ {
+ return to_string(def);
+ }
+
+ bool from_string(std::string_view value, bool /*dynamic*/ = false) override
+ {
+ u128 result;
+ if (try_to_uint128(&result, value))
+ {
+ m_value = result;
+ return true;
+ }
+
+ return false;
+ }
+
+ void set(u128 value)
+ {
+ m_value = value;
+ }
+
+ std::vector to_list() const override
+ {
+ // Should not be used
+ return make_uint_range(0, 1);
+ }
+ };
+
// Simple string entry with mutex
class string : public _base
{
atomic_ptr m_value;
+ std::string original_def;
public:
std::string def;
@@ -545,6 +671,7 @@ namespace cfg
string(node* owner, std::string name, std::string def = {}, bool dynamic = false)
: _base(type::string, owner, std::move(name), dynamic)
, m_value(def)
+ , original_def(def)
, def(std::move(def))
{
}
@@ -554,7 +681,15 @@ namespace cfg
return *m_value.load().get();
}
- void from_default() override;
+ void from_default() override
+ {
+ m_value = def;
+ }
+
+ void restore_defaults() override
+ {
+ def = original_def;
+ }
std::string to_string() const override
{
@@ -595,7 +730,14 @@ namespace cfg
m_set = std::move(set);
}
- void from_default() override;
+ void from_default() override
+ {
+ m_set = {};
+ }
+
+ void restore_defaults() override
+ {
+ }
std::vector to_list() const override
{
@@ -636,6 +778,10 @@ namespace cfg
void erase(std::string_view key);
void from_default() override;
+
+ void restore_defaults() override
+ {
+ }
};
class node_map_entry final : public map_entry
@@ -665,6 +811,10 @@ namespace cfg
void set_map(map_of_type&& map);
void from_default() override;
+
+ void restore_defaults() override
+ {
+ }
};
struct device_info
@@ -702,5 +852,9 @@ namespace cfg
void set_map(map_of_type&& map);
void from_default() override;
+
+ void restore_defaults() override
+ {
+ }
};
}
diff --git a/Utilities/StrUtil.h b/Utilities/StrUtil.h
index c28efda863..285718ac21 100644
--- a/Utilities/StrUtil.h
+++ b/Utilities/StrUtil.h
@@ -28,6 +28,9 @@ bool try_to_int64(s64* out, std::string_view value, s64 min, s64 max);
// Convert string to unsigned integer
bool try_to_uint64(u64* out, std::string_view value, u64 min, u64 max);
+// Convert string to unsigned int128_t
+bool try_to_uint128(u128* out, std::string_view value);
+
// Convert string to float
bool try_to_float(f64* out, std::string_view value, f64 min, f64 max);
diff --git a/bin/GuiConfigs/Windows 11 (Dark Mode) by GustavoGraziano.qss b/bin/GuiConfigs/Windows 11 (Dark Mode) by GustavoGraziano.qss
new file mode 100644
index 0000000000..20b8638862
--- /dev/null
+++ b/bin/GuiConfigs/Windows 11 (Dark Mode) by GustavoGraziano.qss
@@ -0,0 +1,1090 @@
+/*
+ Windows 11 (Dark Mode)
+ by GustavoGraziano
+ GitHub: "https://github.com/GustavoGraziano"
+ (2025/09/18)
+*/
+
+
+
+
+
+/* ----- GLOBAL QWIDGET ----- */
+
+/* RESET */
+QWidget {
+ font-family: "Segoe UI";
+ color: #FFFFFF;
+ background-color: transparent;
+ alternate-background-color: #2B2B2B;
+ border: none;
+}
+
+QDockWidget QWidget, QTabWidget::pane {
+ border: none;
+}
+
+QMainWindow {
+ background-color: #191919;
+}
+
+QDialog {
+ background-color: #191919;
+}
+
+
+QWidget#cg_disasm, QWidget#trophy_manager {
+ background-color: #222222;
+}
+
+QWidget#trophy_notification_frame {
+ background-color: #191919;
+ color: #FFFFFF;
+}
+
+
+/* TOOLTIP */
+QToolTip {
+ background-color: #2C2C2C;
+ color: #FFFFFF;
+ border: 1px solid #1C1C1C;
+ padding: 2px 6px;
+}
+
+
+/* DOCK */
+QDockWidget {
+ color: #FFFFFF;
+ titlebar-normal-icon: url("GuiConfigs/dark/window-undock.svg");
+ titlebar-close-icon: url("GuiConfigs/dark/window-close.svg");
+}
+
+QDockWidget::title {
+ background-color: #222222;
+ border-width: 1px 0px;
+ border-style: solid;
+ border-color: #3A3A3A;
+ padding: 6px 0px;
+}
+
+QDockWidget::float-button, QDockWidget::close-button {
+ background-color: transparent;
+}
+
+QDockWidget::float-button:hover {
+ background-color: #424242;
+ border: none;
+ border-radius: 4px;
+}
+
+QDockWidget::close-button:hover {
+ background-color: #E81123;
+ border: none;
+ border-radius: 4px;
+}
+
+
+/* TAB BAR */
+QTabBar::tab {
+ color: #FFFFFF;
+ padding: 8px 16px;
+ border: none;
+ border-radius: 6px;
+ margin: 0 8px 16px 0;
+ min-width: 65px;
+}
+
+QTabBar::tab:hover {
+ background-color: #2D2D2D;
+}
+
+QTabBar::tab:selected {
+ font-weight: bold;
+ color: #4CC2FF;
+ background-color: #2D2D2D;
+}
+
+QTabBar::tab:selected:hover {
+ background-color: #292929;
+}
+
+
+/* SCROOL BAR */
+QScrollBar:vertical {
+ background-color: transparent;
+ width: 6px;
+ margin: 0px;
+}
+
+QScrollBar::groove:vertical {
+ background-color: transparent;
+ border-radius: 3px;
+ margin: 0px;
+ width: 6px;
+}
+
+QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {
+ height: 0px;
+ width: 0px;
+ background: none;
+ border: none;
+}
+
+QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {
+ background-color: transparent;
+}
+
+QScrollBar::handle:vertical {
+ background-color: #959595;
+ min-height: 20px;
+ border-radius: 2px;
+ border: none;
+ margin: 0px 1px;
+}
+
+QScrollBar::handle:vertical:hover {
+ background-color: #959595;
+ border-radius: 3px;
+ min-width: 12px;
+ margin: 0px;
+}
+
+
+QScrollBar:horizontal {
+ background-color: transparent;
+ height: 6px;
+ margin: 0px;
+}
+
+QScrollBar::groove:horizontal {
+ background-color: transparent;
+ border-radius: 3px;
+ margin: 0px;
+ height: 6px;
+}
+
+QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal {
+ height: 0px;
+ width: 0px;
+ background: none;
+ border: none;
+}
+
+QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal {
+ background-color: transparent;
+}
+
+QScrollBar::handle:horizontal {
+ background-color: #959595;
+ min-width: 20px;
+ border-radius: 2px;
+ border: none;
+ margin: 1px 0px;
+}
+
+QScrollBar::handle:horizontal:hover {
+ background-color: #959595;
+ border-radius: 3px;
+ min-height: 12px;
+ margin: 0px;
+}
+
+
+/* PROGRESS BAR */
+QProgressBar {
+ font-size: 10px;
+ font-weight: bold;
+ color: #FFFFFF;
+ background-color: #373737;
+ border-radius: 4px;
+ text-align: center;
+}
+
+QProgressBar::chunk {
+ background-color: #4CAF50;
+ border-radius: 4px;
+}
+
+QProgressBar:disabled {
+ background-color: #3F3F3F;
+ border: 1px solid transparent;
+ color: #7E7E7E;
+}
+
+QProgressBar::chunk:disabled {
+ background-color: #555555;
+}
+
+QProgressBar:indeterminate {
+ background-color: #373737;
+}
+
+QProgressBar::chunk:indeterminate {
+ background-color: #4CAF50;
+}
+
+
+/* CALENDAR */
+QCalendarWidget QWidget#qt_calendar_navigationbar {
+ background: #222222;
+ border-bottom: 1px solid #3A3A3A;
+}
+
+QCalendarWidget QToolButton {
+ background-color: transparent;
+ border: none;
+ border-radius: 4px;
+}
+
+QCalendarWidget QToolButton:hover {
+ color: #FFFFFF;
+ background-color: #383838;
+}
+
+QCalendarWidget QToolButton#qt_calendar_prevmonth, QCalendarWidget QToolButton#qt_calendar_nextmonth {
+ width: 6px;
+ height: 6px;
+ padding: 0px 10px;
+}
+
+QCalendarWidget QToolButton#qt_calendar_prevmonth {
+ qproperty-icon: url("GuiConfigs/dark/arrow-prev.svg");
+}
+
+QCalendarWidget QToolButton#qt_calendar_nextmonth {
+ qproperty-icon: url("GuiConfigs/dark/arrow-next.svg");
+}
+
+QCalendarWidget QAbstractItemView {
+ color: #FFFFFF;
+ background-color: #222222;
+ alternate-background-color: #222222;
+}
+
+QCalendarWidget QAbstractItemView::item:selected {
+ color: #4CC2FF;
+ background-color: #383838;
+}
+
+QCalendarWidget QAbstractItemView::item:hover {
+ color: #4CC2FF;
+}
+
+QCalendarWidget QAbstractItemView:focus {
+ outline: none;
+}
+
+QCalendarWidget QToolButton#qt_calendar_monthbutton::menu-indicator, QCalendarWidget QToolButton#qt_calendar_yearbutton::menu-indicator {
+ image: none;
+}
+
+
+/* TABLE / TABLE HEADER */
+QTableView {
+ color: #FFFFFF;
+ background-color: #191919;
+ border: none;
+ border-radius: 6px;
+ selection-background-color: #4D4D4D;
+}
+
+QTableView::item:selected {
+ color: #FFFFFF;
+ background-color: #4D4D4D;
+}
+
+
+QHeaderView::section {
+ color: #DEDEDE;
+ background-color: #191919;
+ border: none;
+ padding: 6px 8px 0px;
+ border-left: 1px solid #636363;
+}
+
+QHeaderView::section:first {
+ border-left: none;
+ border-top-left-radius: 6px;
+}
+
+QHeaderView::section:hover {
+ background-color: #4D4D4D;
+}
+
+QHeaderView::section:last {
+ border-top-right-radius: 6px;
+}
+
+
+
+
+
+/* ----- GLOBAL FORM ----- */
+
+/* BUTTONS */
+QPushButton {
+ color: #FFFFFF;
+ background-color: #373737;
+ border: 2px solid #3F3F3F;
+ border-radius: 4px;
+ min-width: 120px;
+ padding: 4px 8px;
+}
+
+QPushButton:hover {
+ background-color: #3C3C3C;
+ border-color: #3F3F3F;
+}
+
+QPushButton:pressed {
+ color: #D0D0D0;
+ background-color: #323232;
+ border-color: #3A3A3A;
+}
+
+QPushButton:disabled {
+ color: #7E7E7E;
+ background-color: #343434;
+ border-color: #3A3A3A;
+}
+
+
+QDialog QDialogButtonBox QPushButton {
+ color: #000000;
+ background-color: #4CC2FF;
+ border-color: #5AC7FF;
+}
+
+QDialog QDialogButtonBox QPushButton:hover {
+ background-color: #48B2E9;
+ border-color: #56B8EB;
+}
+
+QDialog QDialogButtonBox QPushButton:pressed {
+ color: #22526A;
+ background-color: #45A4D5;
+ border-color: #45A4D5;
+}
+
+QDialog QDialogButtonBox QPushButton:disabled {
+ color: #ABABAB;
+ background-color: #4C4C4C;
+ border-color: #4C4C4C;
+}
+
+
+/* RADIO BUTTON / CHECKBOX / LIST / TREE VIEW */
+QRadioButton,
+QCheckBox,
+QListWidget {
+ spacing: 6px;
+}
+
+
+QRadioButton::indicator,
+QCheckBox::indicator,
+QListWidget::indicator {
+ width: 14px;
+ height: 14px;
+}
+
+
+QListWidget,
+QTreeView {
+ background-color: #222222;
+ border: 1px solid #555555;
+ border-radius: 4px;
+ padding: 4px;
+ outline: none;
+}
+
+QListWidget::item,
+QTreeWidget::item {
+ color: #FFFFFF;
+ border-radius: 4px;
+ padding: 4px;
+}
+
+QListWidget::item:selected, QListWidget::item:selected:hover,
+QTreeWidget::item:selected, QTreeWidget::item:selected:hover {
+ color: #FFFFFF;
+ background-color: #555555;
+}
+
+QListWidget::item:hover,
+QTreeWidget::item:hover {
+ background-color: #333333;
+}
+
+QListWidget::item:disabled,
+QTreeWidget::item:disabled {
+ color: #7E7E7E;
+}
+
+QListWidget::item:alternate,
+QTreeWidget::item:alternate {
+ background-color: #2A2A2A;
+}
+
+
+QTreeView::branch {
+ background: #222222;
+}
+
+
+QRadioButton::indicator:unchecked {
+ image: url("GuiConfigs/dark/radio-unchecked.svg");
+}
+
+QRadioButton::indicator:unchecked:hover {
+ image: url("GuiConfigs/dark/radio-unchecked-hover.svg");
+}
+
+QRadioButton::indicator:unchecked:pressed {
+ image: url("GuiConfigs/dark/radio-unchecked-pressed.svg");
+}
+
+QRadioButton::indicator:checked {
+ image: url("GuiConfigs/dark/radio-checked.svg");
+}
+
+QRadioButton::indicator:checked:hover {
+ image: url("GuiConfigs/dark/radio-checked-hover.svg");
+}
+
+QRadioButton::indicator:checked:pressed {
+ image: url("GuiConfigs/dark/radio-checked-pressed.svg");
+}
+
+QRadioButton::indicator:unchecked:disabled {
+ image: url("GuiConfigs/dark/radio-disabled.svg");
+}
+
+QRadioButton::indicator:checked:disabled {
+ image: url("GuiConfigs/dark/radio-checked-disabled.svg");
+}
+
+
+QCheckBox::indicator:unchecked,
+QListWidget::indicator:unchecked {
+ image: url("GuiConfigs/dark/checkbox-unchecked.svg");
+}
+
+QCheckBox::indicator:unchecked:hover,
+QListWidget::indicator:unchecked:hover {
+ image: url("GuiConfigs/dark/checkbox-unchecked-hover.svg");
+}
+
+QCheckBox::indicator:unchecked:pressed,
+QListWidget::indicator:unchecked:pressed {
+ image: url("GuiConfigs/dark/checkbox-unchecked-pressed.svg");
+}
+
+QCheckBox::indicator:checked,
+QListWidget::indicator:checked {
+ image: url("GuiConfigs/dark/checkbox-checked.svg");
+}
+
+QCheckBox::indicator:checked:hover,
+QListWidget::indicator:checked:hover {
+ image: url("GuiConfigs/dark/checkbox-checked-hover.svg");
+}
+
+QCheckBox::indicator:checked:pressed,
+QListWidget::indicator:checked:pressed {
+ image: url("GuiConfigs/dark/checkbox-checked-pressed.svg");
+}
+
+QCheckBox::indicator:indeterminate,
+QListWidget::indicator:indeterminate {
+ image: url("GuiConfigs/dark/checkbox-indeterminate.svg");
+}
+
+QCheckBox::indicator:indeterminate:hover,
+QListWidget::indicator:indeterminate:hover {
+ image: url("GuiConfigs/dark/checkbox-indeterminate-hover.svg");
+}
+
+QCheckBox::indicator:indeterminate:pressed,
+QListWidget::indicator:indeterminate:pressed {
+ image: url("GuiConfigs/dark/checkbox-indeterminate-pressed.svg");
+}
+
+QCheckBox::indicator:unchecked:disabled,
+QListWidget::indicator:unchecked:disabled {
+ image: url("GuiConfigs/dark/checkbox-disabled.svg");
+}
+
+QCheckBox::indicator:checked:disabled,
+QListWidget::indicator:checked:disabled {
+ image: url("GuiConfigs/dark/checkbox-checked-disabled.svg");
+}
+
+QCheckBox::indicator:indeterminate:disabled,
+QListWidget::indicator:indeterminate:disabled {
+ image: url("GuiConfigs/dark/checkbox-indeterminate-disabled.svg");
+}
+
+
+QTreeView::branch:has-children:!has-siblings:closed,
+QTreeView::branch:closed:has-children:has-siblings {
+ image: url("GuiConfigs/dark/list-arrow-closed.svg");
+}
+
+QTreeView::branch:open:has-children:!has-siblings,
+QTreeView::branch:open:has-children:has-siblings {
+ image: url("GuiConfigs/dark/list-arrow-open.svg");
+}
+
+QTreeView:disabled::branch:has-children:!has-siblings:closed,
+QTreeView:disabled::branch:closed:has-children:has-siblings {
+ image: url("GuiConfigs/dark/list-arrow-closed-disabled.svg");
+}
+
+QTreeView:disabled::branch:open:has-children:!has-siblings,
+QTreeView:disabled::branch:open:has-children:has-siblings {
+ image: url("GuiConfigs/dark/list-arrow-open-disabled.svg");
+}
+
+
+/* COMBO BOX / DATE TIME */
+QComboBox,
+QDateTimeEdit {
+ color: #FFFFFF;
+ background-color: #3E3E3E;
+ border: 1px solid #454545;
+ border-radius: 4px;
+ padding: 4px 8px;
+}
+
+QComboBox:hover,
+QDateTimeEdit:hover {
+ background-color: #434343;
+ border: 1px solid #454545;
+}
+
+QComboBox:pressed,
+QDateTimeEdit:pressed {
+ color: #D2D2D2;
+ background-color: #383838;
+ border: 1px solid #404040;
+ border-bottom: none;
+ border-bottom-left-radius: 0px;
+ border-bottom-right-radius: 0px;
+}
+
+QComboBox:disabled,
+QDateTimeEdit:disabled {
+ color: #7E7E7E;
+ background-color: #343434;
+ border: 1px solid #3A3A3A;
+}
+
+QComboBox::drop-down,
+QDateTimeEdit::drop-down {
+ subcontrol-origin: padding;
+ subcontrol-position: center right;
+ width: 10px;
+ height: 10px;
+ background: none;
+ border: none;
+ padding-right: 8px;
+ image: url("GuiConfigs/dark/arrow-down.svg");
+}
+
+QComboBox::drop-down:on,
+QDateTimeEdit::drop-down:on {
+ image: url("GuiConfigs/dark/arrow-up.svg");
+}
+
+QComboBox::drop-down:disabled,
+QDateTimeEdit::drop-down:disabled {
+ image: url("GuiConfigs/dark/arrow-down-disabled.svg");
+}
+
+
+QComboBox QAbstractItemView {
+ color: #FFFFFF;
+ background-color: #222222;
+ border: 1px solid #3A3A3A;
+ border-radius: 4px;
+ padding: 4px;
+}
+
+QComboBox QAbstractItemView::item {
+ color: #FFFFFF;
+ padding: 4px 6px;
+ background-color: transparent;
+ border-radius: 4px;
+}
+
+QComboBox QAbstractItemView::item:selected {
+ background-color: #383838;
+}
+
+QComboBox QAbstractItemView:focus {
+ outline: none;
+}
+
+
+/* SPIN BOX / DOUBLE SPIN BOX */
+QSpinBox,
+QDoubleSpinBox {
+ color: #FFFFFF;
+ background-color: #3E3E3E;
+ border: 1px solid #454545;
+ border-radius: 4px;
+ padding: 5px 8px;
+}
+
+QSpinBox::up-button, QSpinBox::down-button,
+QDoubleSpinBox::up-button, QDoubleSpinBox::down-button {
+ border-radius: 4px;
+ width: 8px;
+ height: 8px;
+ padding: 3px 4px;
+}
+
+QSpinBox::up-button:hover, QSpinBox::down-button:hover,
+QDoubleSpinBox::up-button:hover, QDoubleSpinBox::down-button:hover {
+ background-color: #383838;
+}
+
+QSpinBox:disabled,
+QDoubleSpinBox:disabled {
+ color: #7E7E7E;
+ background-color: #343434;
+ border: 1px solid #3A3A3A;
+}
+
+QSpinBox::up-button,
+QDoubleSpinBox::up-button {
+ image: url("GuiConfigs/dark/arrow-up.svg");
+}
+
+QSpinBox::down-button,
+QDoubleSpinBox::down-button {
+ image: url("GuiConfigs/dark/arrow-down.svg");
+}
+
+QSpinBox::up-button:disabled,
+QDoubleSpinBox::up-button:disabled {
+ image: url("GuiConfigs/dark/arrow-up-disabled.svg");
+}
+
+QSpinBox::down-button:disabled,
+QDoubleSpinBox::down-button:disabled {
+ image: url("GuiConfigs/dark/arrow-down-disabled.svg");
+}
+
+
+/* SLIDER */
+QSlider::groove:horizontal {
+ background-color: #9F9F9F;
+ border-radius: 2px;
+ height: 4px;
+}
+
+QSlider::groove:horizontal:disabled {
+ background-color: #5F5F5F;
+}
+
+QSlider::handle:horizontal {
+ border-radius: 9px;
+ width: 18px;
+ height: 18px;
+ margin: -7px 0px;
+ image: url("GuiConfigs/dark/slider-handle.svg");
+}
+
+QSlider::handle:horizontal:hover {
+ image: url("GuiConfigs/dark/slider-handle-hover.svg");
+}
+
+QSlider::handle:horizontal:pressed {
+ image: url("GuiConfigs/dark/slider-handle-pressed.svg");
+}
+
+QSlider::handle:horizontal:disabled {
+ image: url("GuiConfigs/dark/slider-handle-disabled.svg");
+}
+
+
+/* LINE EDIT */
+QLineEdit {
+ color: #FFFFFF;
+ background-color: #383838;
+ border: 1px solid transparent;
+ border-radius: 4px;
+ padding: 5px 8px;
+}
+
+QLineEdit:hover {
+ background-color: #3D3D3D;
+ border-color: transparent;
+}
+
+QLineEdit:focus {
+ background-color: #222222;
+ border: 1px solid #3A3A3A;
+ border-bottom: 2px solid #4CC2FF;
+}
+
+
+QDockWidget QLineEdit {
+ border: 1px solid transparent;
+ border-radius: 0;
+}
+
+QDockWidget QLineEdit:focus {
+ background: #383838;
+ border: none;
+}
+
+
+/* GROUP BOX */
+QGroupBox {
+ background-color: #2B2B2B;
+ border: 1px solid #1D1D1D;
+ border-radius: 6px;
+ padding-top: 32px;
+}
+
+QGroupBox::title {
+ subcontrol-origin: margin;
+ subcontrol-position: top center;
+ background-color: transparent;
+ border-bottom: 1px solid #1D1D1D;
+ padding: 8px 16px;
+ min-width: 9999px;
+}
+
+QGroupBox QGroupBox::title {
+ border: none;
+}
+
+
+
+
+
+/* ----- MAIN WINDOW ----- */
+
+/* MENU BAR / MENU*/
+QMenuBar {
+ background-color: #2C2C2C;
+}
+
+QMenuBar::item {
+ color: #FFFFFF;
+ background-color: transparent;
+ padding: 4px 8px;
+}
+
+QMenuBar::item:selected {
+ background-color: #383838;
+}
+
+QMenuBar::item:pressed {
+ background-color: #343434;
+}
+
+
+QMenu {
+ background-color: #2C2C2C;
+ border: 1px solid #131313;
+ padding: 4px 0px;
+}
+
+QMenu::item {
+ color: #FFFFFF;
+ background-color: transparent;
+ border-radius: 4px;
+ padding: 8px 20px;
+ margin: 0px 4px;
+}
+
+QMenu::item:selected {
+ background-color: #383838;
+}
+
+QMenu::item:disabled {
+ color: #666666;
+ background-color: transparent;
+}
+
+QMenu::separator {
+ height: 1px;
+ background: #131313;
+ margin: 4px 0px;
+}
+
+QMenu::indicator, QMenu::right-arrow {
+ width: 8px;
+ height: 8px;
+}
+
+QMenu::indicator {
+ padding-left: 6px;
+}
+
+QMenu::indicator:checked {
+ image: url("GuiConfigs/dark/check-mark.svg");
+}
+
+QMenu::indicator:unchecked {
+ image: url("GuiConfigs/dark/empty.svg");
+}
+
+QMenu::right-arrow {
+ image: url("GuiConfigs/dark/arrow-right.svg");
+ padding-right: 6px;
+}
+
+
+/* TOOLBAR */
+QToolBar {
+ background-color: #2C2C2C;
+ border-width: 1px 0px;
+ border-style: solid;
+ border-color: #3A3A3A;
+}
+
+
+/* TOOLBAR BUTTON */
+QToolButton {
+ color: #FFFFFF;
+ background-color: transparent;
+ border: none;
+ border-radius: 6px;
+ padding: 4px 0px;
+ margin: 4px;
+}
+
+QToolButton:hover {
+ background-color: #383838;
+}
+
+QToolButton:pressed {
+ background-color: #343434;
+}
+
+QToolButton:disabled {
+ color: #666666;
+}
+
+
+/* TOOLBAR SLIDER */
+QToolBar#mw_toolbar QSlider {
+ border: 1px solid transparent;
+ border-radius: 6px;
+ margin: 16px 0px;
+ padding: 0px 16px;
+}
+
+QToolBar#mw_toolbar QSlider:hover {
+ background-color: #383838;
+ border-color: transparent;
+}
+
+QToolBar#mw_toolbar QSlider:pressed {
+ background-color: #343434;
+ border-color: transparent;
+}
+
+QSlider#sizeSlider::groove:horizontal {
+ background-color: #9F9F9F;
+ border-radius: 2px;
+ height: 4px;
+}
+
+QSlider#sizeSlider::handle:horizontal {
+ image: url("GuiConfigs/dark/slider-handle.svg");
+ border-radius: 9px;
+ width: 18px;
+ height: 18px;
+ margin: -7px 0px;
+}
+
+QSlider#sizeSlider::handle:horizontal:hover {
+ image: url("GuiConfigs/dark/slider-handle-hover.svg");
+}
+
+QSlider#sizeSlider::handle:horizontal:pressed {
+ image: url("GuiConfigs/dark/slider-handle-pressed.svg");
+}
+
+
+/* TOOLBAR SEARCH */
+QLineEdit#mw_searchbar {
+ color: #FFFFFF;
+ background-color: #383838;
+ border: 1px solid transparent;
+ border-radius: 6px;
+ padding: 6px 12px;
+ margin: 16px 0px;
+}
+
+QLineEdit#mw_searchbar:hover {
+ background-color: #3D3D3D;
+ border-color: transparent;
+}
+
+QLineEdit#mw_searchbar:focus {
+ background-color: #222222;
+ border-color: #3A3A3A;
+ border-bottom: 2px solid #4CC2FF;
+}
+
+
+/* GAME LIST TABLE */
+QMainWindow QTableView,
+QMainWindow QHeaderView::section:first,
+QMainWindow QHeaderView::section:last {
+ border-radius: 0px;
+}
+
+
+/* GAME GRID BODY */
+#game_list_grid_item {
+ background-color: transparent;
+ border-radius: 6px;
+}
+
+#game_list_grid_item:hover {
+ background-color: #4D4D4D;
+}
+
+#game_list_grid_item:focus {
+ background-color: #292929;
+}
+
+#game_list_grid_item_title_label {
+ background-color: transparent;
+}
+
+
+/* LOG TAB */
+QTabBar#tab_bar_log::tab {
+ text-transform: uppercase;
+ color: #FFFFFF;
+ background-color: transparent;
+ border: none;
+ border-top-left-radius: 6px;
+ border-top-right-radius: 6px;
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 0;
+ min-width: 80px;
+ padding: 8px 16px;
+ margin: 0;
+ margin-top: 8px;
+}
+
+QTabBar#tab_bar_log::tab:selected, QTabBar#tab_bar_log::tab:selected:hover {
+ font-weight: normal;
+ color: #FFFFFF;
+ background-color: #0C0C0C;
+}
+
+QTabBar#tab_bar_log::tab:hover {
+ background-color: #252525;
+}
+
+
+/* LOG CONSOLE / TTY CONSOLE */
+QPlainTextEdit#log_frame, QPlainTextEdit#tty_frame {
+ background-color: #0C0C0C;
+ border: none;
+ padding: 8px;
+}
+
+
+/* LOG CONSOLE TEXT */
+QLabel#log_level_fatal {
+ color: #D61A1B;
+}
+
+QLabel#log_level_error {
+ color: #FF6D7E;
+}
+
+QLabel#log_level_warning {
+ color: #FFED72;
+}
+
+QLabel#log_level_todo {
+ color: #FFB270;
+}
+
+QLabel#log_level_notice {
+ color: #BAA0F8;
+}
+
+QLabel#log_level_success {
+ color: #A2E57B;
+}
+
+QLabel#log_level_always {
+ color: #7CD5F1;
+}
+
+QLabel#log_level_trace {
+ color: #576265;
+}
+
+QLabel#log_stack {
+ color: #F2FFFC;
+}
+
+
+
+
+
+/* ----- SETTINGS DIALOG ----- */
+QDialog#settings_dialog QTabWidget::pane {
+ margin-left: -8px;
+}
+
+
+
+
+
+/* ----- PAD SETTINGS DIALOG ----- */
+QDialog#pad_settings_dialog QTabWidget::pane {
+ margin-left: -4px;
+}
+
+
+/* SOME CONTROLLER BUTTONS GROUP BOX */
+QGroupBox#gb_l1, QGroupBox#gb_select, QGroupBox#gb_start, QGroupBox#gb_r1, QGroupBox#gb_l3, QGroupBox#gb_r3, QGroupBox#gb_choose_class, QGroupBox#gb_battery {
+ margin-bottom: 6px;
+}
+
+
+/* CONTROLLER ICON */
+#l_controller {
+ color: #FFFFFF;
+ padding: 20px 0;
+}
+
+
+
+
+
+/* PATCH MANAGER DIALOG */
+QGroupBox#gb_patch_info QGroupBox {
+ background-color: #202020;
+ border: none;
+ border-radius: 6px;
+ padding-top: 0;
+ margin-top: 32px;
+}
+
+QGroupBox#gb_patch_info QGroupBox::title {
+ subcontrol-origin: margin;
+ subcontrol-position: top left;
+ background-color: transparent;
+ border: none;
+ padding: 0;
+ min-width: 0;
+ margin-top: 12px;
+}
diff --git a/bin/GuiConfigs/Windows 11 (Light Mode) by GustavoGraziano.qss b/bin/GuiConfigs/Windows 11 (Light Mode) by GustavoGraziano.qss
new file mode 100644
index 0000000000..692691856f
--- /dev/null
+++ b/bin/GuiConfigs/Windows 11 (Light Mode) by GustavoGraziano.qss
@@ -0,0 +1,1090 @@
+/*
+ Windows 11 (Light Mode)
+ by GustavoGraziano
+ GitHub: "https://github.com/GustavoGraziano"
+ (2025/09/18)
+*/
+
+
+
+
+
+/* ----- GLOBAL QWIDGET ----- */
+
+/* RESET */
+QWidget {
+ font-family: "Segoe UI";
+ color: #1B1B1B;
+ background-color: transparent;
+ alternate-background-color: #EDEDED;
+ border: none;
+}
+
+QDockWidget QWidget, QTabWidget::pane {
+ border: none;
+}
+
+QMainWindow {
+ background-color: #FFFFFF;
+}
+
+QDialog {
+ background-color: #F3F3F3;
+}
+
+
+QWidget#cg_disasm, QWidget#trophy_manager {
+ background-color: #F3F3F3;
+}
+
+QWidget#trophy_notification_frame {
+ background-color: #F3F3F3;
+ color: #1B1B1B;
+}
+
+
+/* TOOLTIP */
+QToolTip {
+ background-color: #F9F9F9;
+ color: #1A1A1A;
+ border: 1px solid #DEDEDE;
+ padding: 2px 6px;
+}
+
+
+/* DOCK */
+QDockWidget {
+ color: #1B1B1B;
+ titlebar-normal-icon: url("GuiConfigs/light/window-undock.svg");
+ titlebar-close-icon: url("GuiConfigs/light/window-close.svg");
+}
+
+QDockWidget::title {
+ background-color: #EEEEEE;
+ border-width: 1px 0px;
+ border-style: solid;
+ border-color: #DEDEDE;
+ padding: 6px 0px;
+}
+
+QDockWidget::float-button, QDockWidget::close-button {
+ background-color: transparent;
+}
+
+QDockWidget::float-button:hover {
+ background-color: #DDDDDD;
+ border: none;
+ border-radius: 4px;
+}
+
+QDockWidget::close-button:hover {
+ background-color: #FF4B3A;
+ border: none;
+ border-radius: 4px;
+}
+
+
+/* TAB BAR */
+QTabBar::tab {
+ color: #1A1A1A;
+ padding: 8px 16px;
+ border: none;
+ border-radius: 6px;
+ margin: 0 8px 16px 0;
+ min-width: 65px;
+}
+
+QTabBar::tab:hover {
+ background-color: #EAEAEA;
+}
+
+QTabBar::tab:selected {
+ font-weight: bold;
+ color: #0067C0;
+ background-color: #EAEAEA;
+}
+
+QTabBar::tab:selected:hover {
+ background-color: #EDEDED;
+}
+
+
+/* SCROOL BAR */
+QScrollBar:vertical {
+ background-color: transparent;
+ width: 6px;
+ margin: 0px;
+}
+
+QScrollBar::groove:vertical {
+ background-color: transparent;
+ border-radius: 3px;
+ margin: 0px;
+ width: 6px;
+}
+
+QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {
+ height: 0px;
+ width: 0px;
+ background: none;
+ border: none;
+}
+
+QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {
+ background-color: transparent;
+}
+
+QScrollBar::handle:vertical {
+ background-color: #858585;
+ min-height: 20px;
+ border-radius: 2px;
+ border: none;
+ margin: 0px 1px;
+}
+
+QScrollBar::handle:vertical:hover {
+ background-color: #858585;
+ border-radius: 3px;
+ min-width: 12px;
+ margin: 0px;
+}
+
+
+QScrollBar:horizontal {
+ background-color: transparent;
+ height: 6px;
+ margin: 0px;
+}
+
+QScrollBar::groove:horizontal {
+ background-color: transparent;
+ border-radius: 3px;
+ margin: 0px;
+ height: 6px;
+}
+
+QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal {
+ height: 0px;
+ width: 0px;
+ background: none;
+ border: none;
+}
+
+QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal {
+ background-color: transparent;
+}
+
+QScrollBar::handle:horizontal {
+ background-color: #858585;
+ min-width: 20px;
+ border-radius: 2px;
+ border: none;
+ margin: 1px 0px;
+}
+
+QScrollBar::handle:horizontal:hover {
+ background-color: #858585;
+ border-radius: 3px;
+ min-height: 12px;
+ margin: 0px;
+}
+
+
+/* PROGRESS BAR */
+QProgressBar {
+ font-size: 10px;
+ font-weight: bold;
+ color: #1B1B1B;
+ background-color: #EDEDED;
+ border-radius: 4px;
+ text-align: center;
+}
+
+QProgressBar::chunk {
+ background-color: #4CAF50;
+ border-radius: 4px;
+}
+
+QProgressBar:disabled {
+ background-color: #FAFAFA;
+ border: 1px solid #ECECEC;
+ color: #A0A0A0;
+}
+
+QProgressBar::chunk:disabled {
+ background-color: #579c7e;
+}
+
+QProgressBar:indeterminate {
+ background-color: #373737;
+}
+
+QProgressBar::chunk:indeterminate {
+ background-color: #4CAF50;
+}
+
+
+/* CALENDAR */
+QCalendarWidget QWidget#qt_calendar_navigationbar {
+ background-color: #F9F9F9;
+ border-bottom: 1px solid #E5E5E5;
+}
+
+QCalendarWidget QToolButton {
+ background-color: transparent;
+ border: none;
+ border-radius: 4px;
+}
+
+QCalendarWidget QToolButton:hover {
+ color: #1B1B1B;
+ background-color: #F0F0F0;
+}
+
+QCalendarWidget QToolButton#qt_calendar_prevmonth, QCalendarWidget QToolButton#qt_calendar_nextmonth {
+ width: 6px;
+ height: 6px;
+ padding: 0px 10px;
+}
+
+QCalendarWidget QToolButton#qt_calendar_prevmonth {
+ qproperty-icon: url("GuiConfigs/light/arrow-prev.svg");
+}
+
+QCalendarWidget QToolButton#qt_calendar_nextmonth {
+ qproperty-icon: url("GuiConfigs/light/arrow-next.svg");
+}
+
+QCalendarWidget QAbstractItemView {
+ color: #1B1B1B;
+ background-color: #F9F9F9;
+ alternate-background-color: #F9F9F9;
+}
+
+QCalendarWidget QAbstractItemView::item:selected {
+ color: #0067C0;
+ background-color: #F0F0F0;
+}
+
+QCalendarWidget QAbstractItemView::item:hover {
+ color: #0067C0;
+}
+
+QCalendarWidget QAbstractItemView:focus {
+ outline: none;
+}
+
+QCalendarWidget QToolButton#qt_calendar_monthbutton::menu-indicator, QCalendarWidget QToolButton#qt_calendar_yearbutton::menu-indicator {
+ image: none;
+}
+
+
+/* TABLE / TABLE HEADER */
+QTableView {
+ color: #1B1B1B;
+ background-color: #FFFFFF;
+ border: none;
+ border-radius: 6px;
+ selection-background-color: #CCE8FF;
+}
+
+QTableView::item:selected {
+ color: #1B1B1B;
+ background-color: #CCE8FF;
+}
+
+
+QHeaderView::section {
+ background-color: #FFFFFF;
+ color: #4C607A;
+ padding: 6px 8px 0px;
+ border: none;
+ border-left: 1px solid #E5E5E5;
+}
+
+QHeaderView::section:hover {
+ background-color: #D9EBF9;
+}
+
+QHeaderView::section:first {
+ border-left: none;
+ border-top-left-radius: 6px;
+}
+
+QHeaderView::section:last {
+ border-top-right-radius: 6px;
+}
+
+
+
+
+
+/* ----- GLOBAL FORM ----- */
+
+/* BUTTONS */
+QPushButton {
+ color: #1B1B1B;
+ background-color: #FEFEFE;
+ border: 2px solid #ECECEC;
+ border-radius: 4px;
+ min-width: 120px;
+ padding: 4px 8px;
+}
+
+QPushButton:hover {
+ background-color: #FAFAFA;
+ border-color: #ECECEC;
+}
+
+QPushButton:pressed {
+ color: #5F5F5F;
+ background-color: #FAFAFA;
+ border-color: #ECECEC;
+}
+
+QPushButton:disabled {
+ color: #A0A0A0;
+ background-color: #FAFAFA;
+ border-color: #ECECEC;
+}
+
+
+QDialog QDialogButtonBox QPushButton {
+ color: #FFFFFF;
+ background-color: #0067C0;
+ border-color: #1473C5;
+}
+
+QDialog QDialogButtonBox QPushButton:hover {
+ background-color: #1A76C6;
+ border-color: #2C80CA;
+}
+
+QDialog QDialogButtonBox QPushButton:pressed {
+ color: #C2DAEF;
+ background-color: #3284CB;
+ border-color: #3284CB;
+}
+
+QDialog QDialogButtonBox QPushButton:disabled {
+ color: #FFFFFF;
+ background-color: #C5C5C5;
+ border-color: #C5C5C5;
+}
+
+
+/* RADIO BUTTON / CHECKBOX / LIST / TREE VIEW */
+QRadioButton,
+QCheckBox,
+QListWidget {
+ spacing: 6px;
+}
+
+
+QRadioButton::indicator,
+QCheckBox::indicator,
+QListWidget::indicator {
+ width: 14px;
+ height: 14px;
+}
+
+
+QListWidget,
+QTreeView {
+ background-color: #F9F9F9;
+ border: 1px solid #EEEEEE;
+ border-radius: 4px;
+ padding: 4px;
+ outline: none;
+}
+
+QListWidget::item,
+QTreeWidget::item {
+ color: #1B1B1B;
+ border-radius: 4px;
+ padding: 4px;
+}
+
+QListWidget::item:selected, QListWidget::item:selected:hover,
+QTreeWidget::item:selected, QTreeWidget::item:selected:hover {
+ color: #1B1B1B;
+ background-color: #CCE8FF;
+}
+
+QListWidget::item:hover,
+QTreeWidget::item:hover {
+ background-color: #E5F3FF;
+}
+
+QListWidget::item:disabled,
+QTreeWidget::item:disabled {
+ color: #A0A0A0;
+}
+
+QListWidget::item:alternate,
+QTreeWidget::item:alternate {
+ background-color: #F5F5F5;
+}
+
+
+QTreeView::branch {
+ background: #F9F9F9;
+}
+
+
+QRadioButton::indicator:unchecked {
+ image: url("GuiConfigs/light/radio-unchecked.svg");
+}
+
+QRadioButton::indicator:unchecked:hover {
+ image: url("GuiConfigs/light/radio-unchecked-hover.svg");
+}
+
+QRadioButton::indicator:unchecked:pressed {
+ image: url("GuiConfigs/light/radio-unchecked-pressed.svg");
+}
+
+QRadioButton::indicator:checked {
+ image: url("GuiConfigs/light/radio-checked.svg");
+}
+
+QRadioButton::indicator:checked:hover {
+ image: url("GuiConfigs/light/radio-checked-hover.svg");
+}
+
+QRadioButton::indicator:checked:pressed {
+ image: url("GuiConfigs/light/radio-checked-pressed.svg");
+}
+
+QRadioButton::indicator:unchecked:disabled {
+ image: url("GuiConfigs/light/radio-disabled.svg");
+}
+
+QRadioButton::indicator:checked:disabled {
+ image: url("GuiConfigs/light/radio-checked-disabled.svg");
+}
+
+
+QCheckBox::indicator:unchecked,
+QListWidget::indicator:unchecked {
+ image: url("GuiConfigs/light/checkbox-unchecked.svg");
+}
+
+QCheckBox::indicator:unchecked:hover,
+QListWidget::indicator:unchecked:hover {
+ image: url("GuiConfigs/light/checkbox-unchecked-hover.svg");
+}
+
+QCheckBox::indicator:unchecked:pressed,
+QListWidget::indicator:unchecked:pressed {
+ image: url("GuiConfigs/light/checkbox-unchecked-pressed.svg");
+}
+
+QCheckBox::indicator:checked,
+QListWidget::indicator:checked {
+ image: url("GuiConfigs/light/checkbox-checked.svg");
+}
+
+QCheckBox::indicator:checked:hover,
+QListWidget::indicator:checked:hover {
+ image: url("GuiConfigs/light/checkbox-checked-hover.svg");
+}
+
+QCheckBox::indicator:checked:pressed,
+QListWidget::indicator:checked:pressed {
+ image: url("GuiConfigs/light/checkbox-checked-pressed.svg");
+}
+
+QCheckBox::indicator:indeterminate,
+QListWidget::indicator:indeterminate {
+ image: url("GuiConfigs/light/checkbox-indeterminate.svg");
+}
+
+QCheckBox::indicator:indeterminate:hover,
+QListWidget::indicator:indeterminate:hover {
+ image: url("GuiConfigs/light/checkbox-indeterminate-hover.svg");
+}
+
+QCheckBox::indicator:indeterminate:pressed,
+QListWidget::indicator:indeterminate:pressed {
+ image: url("GuiConfigs/light/checkbox-indeterminate-pressed.svg");
+}
+
+QCheckBox::indicator:unchecked:disabled,
+QListWidget::indicator:unchecked:disabled {
+ image: url("GuiConfigs/light/checkbox-disabled.svg");
+}
+
+QCheckBox::indicator:checked:disabled,
+QListWidget::indicator:checked:disabled {
+ image: url("GuiConfigs/light/checkbox-checked-disabled.svg");
+}
+
+QCheckBox::indicator:indeterminate:disabled,
+QListWidget::indicator:indeterminate:disabled {
+ image: url("GuiConfigs/light/checkbox-indeterminate-disabled.svg");
+}
+
+
+QTreeView::branch:has-children:!has-siblings:closed,
+QTreeView::branch:closed:has-children:has-siblings {
+ image: url("GuiConfigs/light/list-arrow-closed.svg");
+}
+
+QTreeView::branch:open:has-children:!has-siblings,
+QTreeView::branch:open:has-children:has-siblings {
+ image: url("GuiConfigs/light/list-arrow-open.svg");
+}
+
+QTreeView:disabled::branch:has-children:!has-siblings:closed,
+QTreeView:disabled::branch:closed:has-children:has-siblings {
+ image: url("GuiConfigs/light/list-arrow-closed-disabled.svg");
+}
+
+QTreeView:disabled::branch:open:has-children:!has-siblings,
+QTreeView:disabled::branch:open:has-children:has-siblings {
+ image: url("GuiConfigs/light/list-arrow-open-disabled.svg");
+}
+
+
+/* COMBO BOX / DATE TIME */
+QComboBox,
+QDateTimeEdit {
+ color: #1B1B1B;
+ background-color: #FEFEFE;
+ border: 1px solid #E5E5E5;
+ border-radius: 4px;
+ padding: 4px 8px;
+}
+
+QComboBox:hover,
+QDateTimeEdit:hover {
+ background-color: #F8F8F8;
+ border: 1px solid #E8E8E8;
+}
+
+QComboBox:pressed,
+QDateTimeEdit:pressed {
+ color: #5E5E5E;
+ background-color: #F7F7F7;
+ border: 1px solid #E8E8E8;
+ border-bottom: none;
+ border-bottom-left-radius: 0px;
+ border-bottom-right-radius: 0px;
+}
+
+QComboBox:disabled,
+QDateTimeEdit:disabled {
+ color: #A0A0A0;
+ background-color: #FAFAFA;
+ border: 1px solid #ECECEC;
+}
+
+QComboBox::drop-down,
+QDateTimeEdit::drop-down {
+ subcontrol-origin: padding;
+ subcontrol-position: center right;
+ width: 10px;
+ height: 10px;
+ background: none;
+ border: none;
+ padding-right: 8px;
+ image: url("GuiConfigs/light/arrow-down.svg");
+}
+
+QComboBox::drop-down:on,
+QDateTimeEdit::drop-down:on {
+ image: url("GuiConfigs/light/arrow-up.svg");
+}
+
+QComboBox::drop-down:disabled,
+QDateTimeEdit::drop-down:disabled {
+ image: url("GuiConfigs/light/arrow-down-disabled.svg");
+}
+
+
+QComboBox QAbstractItemView {
+ color: #1B1B1B;
+ background-color: #F9F9F9;
+ border: 1px solid #E5E5E5;
+ border-radius: 4px;
+ padding: 4px;
+}
+
+QComboBox QAbstractItemView::item {
+ color: #1B1B1B;
+ padding: 4px 6px;
+ background-color: transparent;
+ border-radius: 4px;
+}
+
+QComboBox QAbstractItemView::item:selected {
+ background-color: #F0F0F0;
+}
+
+QComboBox QAbstractItemView:focus {
+ outline: none;
+}
+
+
+/* SPIN BOX / DOUBLE SPIN BOX */
+QSpinBox,
+QDoubleSpinBox {
+ color: #1B1B1B;
+ background-color: #FEFEFE;
+ border: 1px solid #ECECEC;
+ border-radius: 4px;
+ padding: 5px 8px;
+}
+
+QSpinBox::up-button, QSpinBox::down-button,
+QDoubleSpinBox::up-button, QDoubleSpinBox::down-button {
+ border-radius: 4px;
+ width: 8px;
+ height: 8px;
+ padding: 3px 4px;
+}
+
+QSpinBox::up-button:hover, QSpinBox::down-button:hover,
+QDoubleSpinBox::up-button:hover, QDoubleSpinBox::down-button:hover {
+ background-color: #ECECEC;
+}
+
+QSpinBox:disabled,
+QDoubleSpinBox:disabled {
+ color: #A0A0A0;
+ background-color: #FAFAFA;
+ border: 1px solid #ECECEC;
+}
+
+QSpinBox::up-button,
+QDoubleSpinBox::up-button {
+ image: url("GuiConfigs/light/arrow-up.svg");
+}
+
+QSpinBox::down-button,
+QDoubleSpinBox::down-button {
+ image: url("GuiConfigs/light/arrow-down.svg");
+}
+
+QSpinBox::up-button:disabled,
+QDoubleSpinBox::up-button:disabled {
+ image: url("GuiConfigs/light/arrow-up-disabled.svg");
+}
+
+QSpinBox::down-button:disabled,
+QDoubleSpinBox::down-button:disabled {
+ image: url("GuiConfigs/light/arrow-down-disabled.svg");
+}
+
+
+/* SLIDER */
+QSlider::groove:horizontal {
+ background-color: #8B8B8B;
+ border-radius: 2px;
+ height: 4px;
+}
+
+QSlider::groove:horizontal:disabled {
+ background-color: #ABABAB;
+}
+
+QSlider::handle:horizontal {
+ image: url("GuiConfigs/light/slider-handle.svg");
+ border-radius: 9px;
+ width: 18px;
+ height: 18px;
+ margin: -7px 0px;
+}
+
+QSlider::handle:horizontal:hover {
+ image: url("GuiConfigs/light/slider-handle-hover.svg");
+}
+
+QSlider::handle:horizontal:pressed {
+ image: url("GuiConfigs/light/slider-handle-pressed.svg");
+}
+
+QSlider::handle:horizontal:disabled {
+ image: url("GuiConfigs/light/slider-handle-disabled.svg");
+}
+
+
+/* LINE EDIT */
+QLineEdit {
+ color: #1B1B1B;
+ background-color: #FDFDFD;
+ border: 1px solid #EAEAEA;
+ border-radius: 4px;
+ padding: 5px 8px;
+}
+
+QLineEdit:hover {
+ background-color: #F9F9F9;
+ border-color: #EAEAEA;
+}
+
+QLineEdit:focus {
+ background-color: #FFFFFF;
+ border-color: #EAEAEA;
+ border-bottom: 2px solid #0067C0;
+}
+
+
+QDockWidget QLineEdit {
+ border: 1px solid transparent;
+ border-radius: 0;
+}
+
+QDockWidget QLineEdit:focus {
+ background: #FDFDFD;
+ border: none;
+}
+
+
+/* GROUP BOX */
+QGroupBox {
+ background-color: #FBFBFB;
+ border: 1px solid #E5E5E5;
+ border-radius: 6px;
+ padding-top: 32px;
+}
+
+QGroupBox::title {
+ subcontrol-origin: margin;
+ subcontrol-position: top center;
+ background-color: transparent;
+ border-bottom: 1px solid #E5E5E5;
+ padding: 8px 16px;
+ min-width: 9999px;
+}
+
+QGroupBox QGroupBox::title {
+ border: none;
+}
+
+
+
+
+
+/* ----- MAIN WINDOW ----- */
+
+/* MENU BAR / MENU */
+QMenuBar {
+ background-color: #F8F8F8;
+}
+
+QMenuBar::item {
+ color: #1B1B1B;
+ background-color: transparent;
+ padding: 4px 8px;
+}
+
+QMenuBar::item:selected {
+ background-color: #EFEFEF;
+}
+
+QMenuBar::item:pressed {
+ background-color: #F2F2F2;
+}
+
+
+QMenu {
+ background-color: #F9F9F9;
+ border: 1px solid #EEEEEE;
+ padding: 4px 0px;
+}
+
+QMenu::item {
+ color: #1B1B1B;
+ background-color: transparent;
+ border-radius: 4px;
+ padding: 8px 20px;
+ margin: 0px 4px;
+}
+
+QMenu::item:selected {
+ background-color: #F0F0F0;
+}
+
+QMenu::item:disabled {
+ color: #A0A0A0;
+ background-color: transparent;
+}
+
+QMenu::separator {
+ height: 1px;
+ background: #EEEEEE;
+ margin: 4px 0px;
+}
+
+QMenu::indicator, QMenu::right-arrow {
+ width: 8px;
+ height: 8px;
+}
+
+QMenu::indicator {
+ padding-left: 6px;
+}
+
+QMenu::indicator:checked {
+ image: url("GuiConfigs/light/check-mark.svg");
+}
+
+QMenu::indicator:unchecked {
+ image: url("GuiConfigs/light/empty.svg");
+}
+
+QMenu::right-arrow {
+ image: url("GuiConfigs/light/arrow-right.svg");
+ padding-right: 6px;
+}
+
+
+/* TOOLBAR */
+QToolBar {
+ background-color: #F8F8F8;
+ border-width: 1px 0px;
+ border-style: solid;
+ border-color: #DEDEDE;
+}
+
+
+/* TOOLBAR BUTTON */
+QToolButton {
+ color: #1B1B1B;
+ background-color: transparent;
+ border: none;
+ border-radius: 6px;
+ padding: 4px 0px;
+ margin: 4px;
+}
+
+QToolButton:hover {
+ background-color: #EFEFEF;
+}
+
+QToolButton:pressed {
+ background-color: #F2F2F2;
+}
+
+QToolButton:disabled {
+ color: #A0A0A0;
+}
+
+
+/* TOOLBAR SLIDER */
+QToolBar#mw_toolbar QSlider {
+ border: 1px solid transparent;
+ border-radius: 6px;
+ margin: 16px 0px;
+ padding: 0px 16px;
+}
+
+QToolBar#mw_toolbar QSlider:hover {
+ background-color: #FDFDFD;
+ border-color: #EAEAEA;
+}
+
+QToolBar#mw_toolbar QSlider:pressed {
+ background-color: #F9F9F9;
+ border-color: #EAEAEA;
+}
+
+QSlider#sizeSlider::groove:horizontal {
+ background-color: #8B8B8B;
+ border-radius: 2px;
+ height: 4px;
+}
+
+QSlider#sizeSlider::handle:horizontal {
+ image: url("GuiConfigs/light/slider-handle.svg");
+ border-radius: 9px;
+ width: 18px;
+ height: 18px;
+ margin: -7px 0px;
+}
+
+QSlider#sizeSlider::handle:horizontal:hover {
+ image: url("GuiConfigs/light/slider-handle-hover.svg");
+}
+
+QSlider#sizeSlider::handle:horizontal:pressed {
+ image: url("GuiConfigs/light/slider-handle-pressed.svg");
+}
+
+
+/* TOOLBAR SEARCH */
+QLineEdit#mw_searchbar {
+ color: #1B1B1B;
+ background-color: #FDFDFD;
+ border: 1px solid transparent;
+ border-radius: 6px;
+ padding: 6px 12px;
+ margin: 16px 0px;
+}
+
+QLineEdit#mw_searchbar:hover {
+ background-color: #F9F9F9;
+ border-color: #EAEAEA;
+}
+
+QLineEdit#mw_searchbar:focus {
+ background-color: #FFFFFF;
+ border-color: #EAEAEA;
+ border-bottom: 2px solid #0067C0;
+}
+
+
+/* GAME LIST TABLE */
+QMainWindow QTableView,
+QMainWindow QHeaderView::section:first,
+QMainWindow QHeaderView::section:last {
+ border-radius: 0px;
+}
+
+
+/* GAME GRID BODY */
+#game_list_grid_item {
+ background-color: transparent;
+ border-radius: 6px;
+}
+
+#game_list_grid_item:hover {
+ background-color: #E5F3FF;
+}
+
+#game_list_grid_item:focus {
+ background-color: #CCE8FF;
+}
+
+#game_list_grid_item_title_label {
+ background-color: transparent;
+}
+
+
+/* LOG TAB */
+QTabBar#tab_bar_log::tab {
+ text-transform: uppercase;
+ color: #1B1B1B;
+ background-color: transparent;
+ border: none;
+ border-top-left-radius: 6px;
+ border-top-right-radius: 6px;
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 0;
+ min-width: 80px;
+ padding: 8px 16px;
+ margin: 0;
+ margin-top: 8px;
+}
+
+QTabBar#tab_bar_log::tab:selected, QTabBar#tab_bar_log::tab:selected:hover {
+ font-weight: normal;
+ color: #1B1B1B;
+ background-color: #FAF4F2;
+}
+
+QTabBar#tab_bar_log::tab:hover {
+ background-color: #ede5e7;
+}
+
+
+/* LOG CONSOLE / TTY CONSOLE */
+QPlainTextEdit#log_frame, QPlainTextEdit#tty_frame {
+ background-color: #FAF4F2;
+ border: none;
+ padding: 8px;
+}
+
+
+/* LOG CONSOLE TEXT */
+QLabel#log_level_fatal {
+ color: #FC3D3C;
+}
+
+QLabel#log_level_error {
+ color: #E14775;
+}
+
+QLabel#log_level_warning {
+ color: #CC7A0A;
+}
+
+QLabel#log_level_todo {
+ color: #E16032;
+}
+
+QLabel#log_level_notice {
+ color: #7058BE;
+}
+
+QLabel#log_level_success {
+ color: #269D69;
+}
+
+QLabel#log_level_always {
+ color: #1C8CA8;
+}
+
+QLabel#log_level_trace {
+ color: #A59FA0;
+}
+
+QLabel#log_stack {
+ color: #29242A;
+}
+
+
+
+
+
+/* ----- SETTINGS DIALOG ----- */
+QDialog#settings_dialog QTabWidget::pane {
+ margin-left: -8px;
+}
+
+
+
+
+
+/* ----- PAD SETTINGS DIALOG ----- */
+QDialog#pad_settings_dialog QTabWidget::pane {
+ margin-left: -4px;
+}
+
+
+/* SOME CONTROLLER BUTTONS GROUP BOX */
+QGroupBox#gb_l1, QGroupBox#gb_select, QGroupBox#gb_start, QGroupBox#gb_r1, QGroupBox#gb_l3, QGroupBox#gb_r3, QGroupBox#gb_choose_class, QGroupBox#gb_battery {
+ margin-bottom: 6px;
+}
+
+
+/* CONTROLLER ICON */
+#l_controller {
+ color: #1B1B1B;
+ padding: 20px 0;
+}
+
+
+
+
+
+/* PATCH MANAGER DIALOG */
+QGroupBox#gb_patch_info QGroupBox {
+ background-color: #F3F3F3;
+ border: none;
+ border-radius: 6px;
+ padding-top: 0;
+ margin-top: 32px;
+}
+
+QGroupBox#gb_patch_info QGroupBox::title {
+ subcontrol-origin: margin;
+ subcontrol-position: top left;
+ background-color: transparent;
+ border: none;
+ padding: 0;
+ min-width: 0;
+ margin-top: 12px;
+}
diff --git a/bin/GuiConfigs/YoRHa by Ani.qss b/bin/GuiConfigs/YoRHa by Ani.qss
index c3345d4cd9..bcfd059c2e 100644
--- a/bin/GuiConfigs/YoRHa by Ani.qss
+++ b/bin/GuiConfigs/YoRHa by Ani.qss
@@ -4,24 +4,28 @@ by Ani @ https://github.com/AniLeo
r1 (2018.02.27)
r2 (2021.08.28)
r3 (2022.08.20)
+r4 (2025.09.14)
*/
/*
Color Scheme
- Pod Programs
-8c806a
-bd9d86
-c1b398
-eadfb1
-ebe4d2
+#8c806a
+#bd9d86
+#c1b398
+#eadfb1
+#ebe4d2
- Light
-b3ac98
-aea993
+#b3ac98
+#aea993
- Dark
-4d4940
+#4d4940
+
+- Disabled
+#828790
*/
@@ -55,31 +59,6 @@ QTextEdit, QPlainTextEdit {
font-size: 8.50pt;
}
-/*
- QListWidget, QTreeWidget: Style checkboxes and rows
-
- RPCS3: LLE/HLE Selector, Debugger
-*/
-QListWidget::item {
- margin-top: 0.05em;
- margin-bottom: 0.05em;
-}
-QListWidget::indicator, QTreeWidget::indicator {
- border: 0.05em solid #4d4940;
-}
-QListWidget::indicator::unchecked, QTreeWidget::indicator::unchecked {
- background-color: #b3ac98;
-}
-QListWidget::indicator::checked, QTreeWidget::indicator::checked {
- background-color: #4d4940;
-}
-QListWidget::indicator::disabled, QTreeWidget::indicator::disabled {
- background-color: #828790;
-}
-QListWidget::item::selected, QTreeWidget::item::selected {
- background-color: #4d4940;
-}
-
/*
QTableView: Style selected row
@@ -141,31 +120,38 @@ QTabBar::tab::selected {
color: #aea993;
}
-/* Checkboxes */
-QCheckBox::indicator {
+/* Checkboxes
+ Radio Buttons
+
+ QListWidget, QTreeWidget: Style indicators (checkboxes) and selected rows
+
+ RPCS3: LLE/HLE Selector, Debugger, Game Patches
+*/
+QCheckBox::indicator, QListWidget::indicator, QTreeWidget::indicator {
border-radius: 0.1em;
}
-/* Radio Buttons */
QRadioButton::indicator {
border-radius: 0.4em;
}
-/* Checkboxes and Radio Buttons */
-QCheckBox::indicator, QRadioButton::indicator {
+QCheckBox::indicator, QRadioButton::indicator, QListWidget::indicator, QTreeWidget::indicator {
border: 0.05em solid #4d4940;
margin-top: 0.05em;
margin-bottom: 0.05em;
width: 0.8em;
height: 0.8em;
}
-QCheckBox::indicator:checked, QRadioButton::indicator:checked {
+QCheckBox::indicator:checked, QRadioButton::indicator:checked, QListWidget::indicator::checked, QTreeWidget::indicator::checked{
background-color: #4d4940; /* Dark */
}
-QCheckBox::indicator:unchecked, QRadioButton::indicator:unchecked {
+QCheckBox::indicator:unchecked, QRadioButton::indicator:unchecked, QListWidget::indicator::unchecked, QTreeWidget::indicator::unchecked {
background-color: #b3ac98; /* Light */
}
-QCheckBox::indicator::disabled, QRadioButton::indicator::disabled {
+QCheckBox::indicator::disabled, QRadioButton::indicator::disabled, QListWidget::indicator::disabled, QTreeWidget::indicator::disabled {
background-color: #828790; /* Gray */
}
+QListWidget::item::selected, QTreeWidget::item::selected {
+ background-color: #4d4940;
+}
/* Combo Boxes, Datetime dropdown */
QComboBox, QDateTimeEdit, QLineEdit {
@@ -215,6 +201,7 @@ QPushButton::disabled {
/* QSpinBox (Settings -> Emulator -> width/height) */
/* QDoubleSpinBox (Pads -> Mouse Acceleration -> x/y) */
QSpinBox, QDoubleSpinBox {
+ height: 0.1em;
background-color: #b3ac98;
}
QSpinBox::disabled, QDoubleSpinBox::disabled {
@@ -247,6 +234,7 @@ QDockWidget {
QDockWidget::title {
background: #4d4940;
padding-top: 0.2em;
+ padding-left: 0.2em;
}
QDockWidget::close-button, QDockWidget::float-button {
background-color: #b3ac98;
@@ -262,7 +250,7 @@ QTabWidget::tab-bar {
}
/* Top menu bar */
-QMenuBar {
+QMenuBar#menuBar {
height:1.50em;
text-transform: uppercase;
}
@@ -314,12 +302,27 @@ QCalendarWidget QWidget{
color: #4d4940;
}
+/* Scrollbars */
+QScrollBar::handle, QTableView QScrollBar::handle {
+ background: #4d4940;
+}
+QScrollBar::handle:disabled {
+ background: #828790;
+}
+QScrollBar::add-page, QScrollBar::sub-page {
+ background: #8c806a;
+}
+QScrollBar::up-arrow, QScrollBar::down-arrow, QScrollBar::up-button:vertical, QScrollBar::down-button, QScrollBar::sub-line, QScrollBar::add-line {
+ background: transparent;
+ color: transparent;
+}
+
/*** RPCS3 Specifics ***/
/* Main Window, Dialogs and some Dialogs that are actually widgets */
-QWidget#trophy_manager, QWidget#cg_disasm, QWidget#log_viewer, QMainWindow#main_window {
+QWidget#trophy_manager, QWidget#cg_disasm, QWidget#log_viewer, QWidget#savestate_manager, QMainWindow#main_window {
border-image: url("GuiConfigs/YoRHa-background.jpg");
}
diff --git a/bin/GuiConfigs/dark/arrow-down-disabled.svg b/bin/GuiConfigs/dark/arrow-down-disabled.svg
new file mode 100644
index 0000000000..c057e16738
--- /dev/null
+++ b/bin/GuiConfigs/dark/arrow-down-disabled.svg
@@ -0,0 +1,3 @@
+
diff --git a/bin/GuiConfigs/dark/arrow-down.svg b/bin/GuiConfigs/dark/arrow-down.svg
new file mode 100644
index 0000000000..10ce5497fd
--- /dev/null
+++ b/bin/GuiConfigs/dark/arrow-down.svg
@@ -0,0 +1,3 @@
+
diff --git a/bin/GuiConfigs/dark/arrow-left-disabled.svg b/bin/GuiConfigs/dark/arrow-left-disabled.svg
new file mode 100644
index 0000000000..0303633436
--- /dev/null
+++ b/bin/GuiConfigs/dark/arrow-left-disabled.svg
@@ -0,0 +1,3 @@
+
diff --git a/bin/GuiConfigs/dark/arrow-left.svg b/bin/GuiConfigs/dark/arrow-left.svg
new file mode 100644
index 0000000000..6d85039905
--- /dev/null
+++ b/bin/GuiConfigs/dark/arrow-left.svg
@@ -0,0 +1,3 @@
+
diff --git a/bin/GuiConfigs/dark/arrow-next.svg b/bin/GuiConfigs/dark/arrow-next.svg
new file mode 100644
index 0000000000..d70f87f999
--- /dev/null
+++ b/bin/GuiConfigs/dark/arrow-next.svg
@@ -0,0 +1,10 @@
+
diff --git a/bin/GuiConfigs/dark/arrow-prev.svg b/bin/GuiConfigs/dark/arrow-prev.svg
new file mode 100644
index 0000000000..afa3358313
--- /dev/null
+++ b/bin/GuiConfigs/dark/arrow-prev.svg
@@ -0,0 +1,10 @@
+
diff --git a/bin/GuiConfigs/dark/arrow-right-disabled.svg b/bin/GuiConfigs/dark/arrow-right-disabled.svg
new file mode 100644
index 0000000000..eaa0f2487c
--- /dev/null
+++ b/bin/GuiConfigs/dark/arrow-right-disabled.svg
@@ -0,0 +1,3 @@
+
diff --git a/bin/GuiConfigs/dark/arrow-right.svg b/bin/GuiConfigs/dark/arrow-right.svg
new file mode 100644
index 0000000000..b6e2fac21e
--- /dev/null
+++ b/bin/GuiConfigs/dark/arrow-right.svg
@@ -0,0 +1,3 @@
+
diff --git a/bin/GuiConfigs/dark/arrow-up-disabled.svg b/bin/GuiConfigs/dark/arrow-up-disabled.svg
new file mode 100644
index 0000000000..05e0ab2406
--- /dev/null
+++ b/bin/GuiConfigs/dark/arrow-up-disabled.svg
@@ -0,0 +1,3 @@
+
diff --git a/bin/GuiConfigs/dark/arrow-up.svg b/bin/GuiConfigs/dark/arrow-up.svg
new file mode 100644
index 0000000000..95657aa0d0
--- /dev/null
+++ b/bin/GuiConfigs/dark/arrow-up.svg
@@ -0,0 +1,3 @@
+
diff --git a/bin/GuiConfigs/dark/check-mark-disabled.svg b/bin/GuiConfigs/dark/check-mark-disabled.svg
new file mode 100644
index 0000000000..dbe8f7e724
--- /dev/null
+++ b/bin/GuiConfigs/dark/check-mark-disabled.svg
@@ -0,0 +1,3 @@
+
diff --git a/bin/GuiConfigs/dark/check-mark.svg b/bin/GuiConfigs/dark/check-mark.svg
new file mode 100644
index 0000000000..3768cda4c1
--- /dev/null
+++ b/bin/GuiConfigs/dark/check-mark.svg
@@ -0,0 +1,3 @@
+
diff --git a/bin/GuiConfigs/dark/checkbox-checked-disabled.svg b/bin/GuiConfigs/dark/checkbox-checked-disabled.svg
new file mode 100644
index 0000000000..a6323d57d0
--- /dev/null
+++ b/bin/GuiConfigs/dark/checkbox-checked-disabled.svg
@@ -0,0 +1,11 @@
+
diff --git a/bin/GuiConfigs/dark/checkbox-checked-hover.svg b/bin/GuiConfigs/dark/checkbox-checked-hover.svg
new file mode 100644
index 0000000000..9279168411
--- /dev/null
+++ b/bin/GuiConfigs/dark/checkbox-checked-hover.svg
@@ -0,0 +1,11 @@
+
diff --git a/bin/GuiConfigs/dark/checkbox-checked-pressed.svg b/bin/GuiConfigs/dark/checkbox-checked-pressed.svg
new file mode 100644
index 0000000000..4ad4e0f10c
--- /dev/null
+++ b/bin/GuiConfigs/dark/checkbox-checked-pressed.svg
@@ -0,0 +1,11 @@
+
diff --git a/bin/GuiConfigs/dark/checkbox-checked.svg b/bin/GuiConfigs/dark/checkbox-checked.svg
new file mode 100644
index 0000000000..860b73323e
--- /dev/null
+++ b/bin/GuiConfigs/dark/checkbox-checked.svg
@@ -0,0 +1,11 @@
+
diff --git a/bin/GuiConfigs/dark/checkbox-disabled.svg b/bin/GuiConfigs/dark/checkbox-disabled.svg
new file mode 100644
index 0000000000..4c0e28af8d
--- /dev/null
+++ b/bin/GuiConfigs/dark/checkbox-disabled.svg
@@ -0,0 +1,4 @@
+
diff --git a/bin/GuiConfigs/dark/checkbox-indeterminate-disabled.svg b/bin/GuiConfigs/dark/checkbox-indeterminate-disabled.svg
new file mode 100644
index 0000000000..28ffa34410
--- /dev/null
+++ b/bin/GuiConfigs/dark/checkbox-indeterminate-disabled.svg
@@ -0,0 +1,11 @@
+
diff --git a/bin/GuiConfigs/dark/checkbox-indeterminate-hover.svg b/bin/GuiConfigs/dark/checkbox-indeterminate-hover.svg
new file mode 100644
index 0000000000..b43d5384b0
--- /dev/null
+++ b/bin/GuiConfigs/dark/checkbox-indeterminate-hover.svg
@@ -0,0 +1,11 @@
+
diff --git a/bin/GuiConfigs/dark/checkbox-indeterminate-pressed.svg b/bin/GuiConfigs/dark/checkbox-indeterminate-pressed.svg
new file mode 100644
index 0000000000..e46ae55ddc
--- /dev/null
+++ b/bin/GuiConfigs/dark/checkbox-indeterminate-pressed.svg
@@ -0,0 +1,11 @@
+
diff --git a/bin/GuiConfigs/dark/checkbox-indeterminate.svg b/bin/GuiConfigs/dark/checkbox-indeterminate.svg
new file mode 100644
index 0000000000..55a4824043
--- /dev/null
+++ b/bin/GuiConfigs/dark/checkbox-indeterminate.svg
@@ -0,0 +1,11 @@
+
diff --git a/bin/GuiConfigs/dark/checkbox-unchecked-hover.svg b/bin/GuiConfigs/dark/checkbox-unchecked-hover.svg
new file mode 100644
index 0000000000..5159b70312
--- /dev/null
+++ b/bin/GuiConfigs/dark/checkbox-unchecked-hover.svg
@@ -0,0 +1,4 @@
+
diff --git a/bin/GuiConfigs/dark/checkbox-unchecked-pressed.svg b/bin/GuiConfigs/dark/checkbox-unchecked-pressed.svg
new file mode 100644
index 0000000000..4b1b2a3639
--- /dev/null
+++ b/bin/GuiConfigs/dark/checkbox-unchecked-pressed.svg
@@ -0,0 +1,4 @@
+
diff --git a/bin/GuiConfigs/dark/checkbox-unchecked.svg b/bin/GuiConfigs/dark/checkbox-unchecked.svg
new file mode 100644
index 0000000000..24b1b1b211
--- /dev/null
+++ b/bin/GuiConfigs/dark/checkbox-unchecked.svg
@@ -0,0 +1,4 @@
+
diff --git a/bin/GuiConfigs/dark/empty.svg b/bin/GuiConfigs/dark/empty.svg
new file mode 100644
index 0000000000..d216ff7f65
--- /dev/null
+++ b/bin/GuiConfigs/dark/empty.svg
@@ -0,0 +1,2 @@
+
diff --git a/bin/GuiConfigs/dark/list-arrow-closed-disabled.svg b/bin/GuiConfigs/dark/list-arrow-closed-disabled.svg
new file mode 100644
index 0000000000..60843e0801
--- /dev/null
+++ b/bin/GuiConfigs/dark/list-arrow-closed-disabled.svg
@@ -0,0 +1,3 @@
+
diff --git a/bin/GuiConfigs/dark/list-arrow-closed.svg b/bin/GuiConfigs/dark/list-arrow-closed.svg
new file mode 100644
index 0000000000..674c19e989
--- /dev/null
+++ b/bin/GuiConfigs/dark/list-arrow-closed.svg
@@ -0,0 +1,3 @@
+
diff --git a/bin/GuiConfigs/dark/list-arrow-open-disabled.svg b/bin/GuiConfigs/dark/list-arrow-open-disabled.svg
new file mode 100644
index 0000000000..af22abdb93
--- /dev/null
+++ b/bin/GuiConfigs/dark/list-arrow-open-disabled.svg
@@ -0,0 +1,3 @@
+
diff --git a/bin/GuiConfigs/dark/list-arrow-open.svg b/bin/GuiConfigs/dark/list-arrow-open.svg
new file mode 100644
index 0000000000..3f8652412c
--- /dev/null
+++ b/bin/GuiConfigs/dark/list-arrow-open.svg
@@ -0,0 +1,3 @@
+
diff --git a/bin/GuiConfigs/dark/radio-checked-disabled.svg b/bin/GuiConfigs/dark/radio-checked-disabled.svg
new file mode 100644
index 0000000000..7314ca7e58
--- /dev/null
+++ b/bin/GuiConfigs/dark/radio-checked-disabled.svg
@@ -0,0 +1,4 @@
+
diff --git a/bin/GuiConfigs/dark/radio-checked-hover.svg b/bin/GuiConfigs/dark/radio-checked-hover.svg
new file mode 100644
index 0000000000..4a1a733688
--- /dev/null
+++ b/bin/GuiConfigs/dark/radio-checked-hover.svg
@@ -0,0 +1,4 @@
+
diff --git a/bin/GuiConfigs/dark/radio-checked-pressed.svg b/bin/GuiConfigs/dark/radio-checked-pressed.svg
new file mode 100644
index 0000000000..6c08461297
--- /dev/null
+++ b/bin/GuiConfigs/dark/radio-checked-pressed.svg
@@ -0,0 +1,5 @@
+
diff --git a/bin/GuiConfigs/dark/radio-checked.svg b/bin/GuiConfigs/dark/radio-checked.svg
new file mode 100644
index 0000000000..40226c2ec9
--- /dev/null
+++ b/bin/GuiConfigs/dark/radio-checked.svg
@@ -0,0 +1,4 @@
+
diff --git a/bin/GuiConfigs/dark/radio-disabled.svg b/bin/GuiConfigs/dark/radio-disabled.svg
new file mode 100644
index 0000000000..d9b45f6275
--- /dev/null
+++ b/bin/GuiConfigs/dark/radio-disabled.svg
@@ -0,0 +1,4 @@
+
diff --git a/bin/GuiConfigs/dark/radio-unchecked-hover.svg b/bin/GuiConfigs/dark/radio-unchecked-hover.svg
new file mode 100644
index 0000000000..301d8c3414
--- /dev/null
+++ b/bin/GuiConfigs/dark/radio-unchecked-hover.svg
@@ -0,0 +1,4 @@
+
diff --git a/bin/GuiConfigs/dark/radio-unchecked-pressed.svg b/bin/GuiConfigs/dark/radio-unchecked-pressed.svg
new file mode 100644
index 0000000000..a8334fde9e
--- /dev/null
+++ b/bin/GuiConfigs/dark/radio-unchecked-pressed.svg
@@ -0,0 +1,5 @@
+
diff --git a/bin/GuiConfigs/dark/radio-unchecked.svg b/bin/GuiConfigs/dark/radio-unchecked.svg
new file mode 100644
index 0000000000..334ce6ca2c
--- /dev/null
+++ b/bin/GuiConfigs/dark/radio-unchecked.svg
@@ -0,0 +1,4 @@
+
diff --git a/bin/GuiConfigs/dark/slider-handle-disabled.svg b/bin/GuiConfigs/dark/slider-handle-disabled.svg
new file mode 100644
index 0000000000..2d3d865bb4
--- /dev/null
+++ b/bin/GuiConfigs/dark/slider-handle-disabled.svg
@@ -0,0 +1,3 @@
+
diff --git a/bin/GuiConfigs/dark/slider-handle-hover.svg b/bin/GuiConfigs/dark/slider-handle-hover.svg
new file mode 100644
index 0000000000..2f0f8abb98
--- /dev/null
+++ b/bin/GuiConfigs/dark/slider-handle-hover.svg
@@ -0,0 +1,3 @@
+
diff --git a/bin/GuiConfigs/dark/slider-handle-pressed.svg b/bin/GuiConfigs/dark/slider-handle-pressed.svg
new file mode 100644
index 0000000000..9ca2a54ad6
--- /dev/null
+++ b/bin/GuiConfigs/dark/slider-handle-pressed.svg
@@ -0,0 +1,3 @@
+
diff --git a/bin/GuiConfigs/dark/slider-handle.svg b/bin/GuiConfigs/dark/slider-handle.svg
new file mode 100644
index 0000000000..c49e8e25aa
--- /dev/null
+++ b/bin/GuiConfigs/dark/slider-handle.svg
@@ -0,0 +1,3 @@
+
diff --git a/bin/GuiConfigs/dark/window-close.svg b/bin/GuiConfigs/dark/window-close.svg
new file mode 100644
index 0000000000..337b067f44
--- /dev/null
+++ b/bin/GuiConfigs/dark/window-close.svg
@@ -0,0 +1,3 @@
+
diff --git a/bin/GuiConfigs/dark/window-undock.svg b/bin/GuiConfigs/dark/window-undock.svg
new file mode 100644
index 0000000000..684a8f87fe
--- /dev/null
+++ b/bin/GuiConfigs/dark/window-undock.svg
@@ -0,0 +1,3 @@
+
diff --git a/bin/GuiConfigs/light/arrow-down-disabled.svg b/bin/GuiConfigs/light/arrow-down-disabled.svg
new file mode 100644
index 0000000000..6a35cff63b
--- /dev/null
+++ b/bin/GuiConfigs/light/arrow-down-disabled.svg
@@ -0,0 +1,3 @@
+
diff --git a/bin/GuiConfigs/light/arrow-down.svg b/bin/GuiConfigs/light/arrow-down.svg
new file mode 100644
index 0000000000..0820bdb8c9
--- /dev/null
+++ b/bin/GuiConfigs/light/arrow-down.svg
@@ -0,0 +1,3 @@
+
diff --git a/bin/GuiConfigs/light/arrow-left-disabled.svg b/bin/GuiConfigs/light/arrow-left-disabled.svg
new file mode 100644
index 0000000000..02e5395fbf
--- /dev/null
+++ b/bin/GuiConfigs/light/arrow-left-disabled.svg
@@ -0,0 +1,3 @@
+
diff --git a/bin/GuiConfigs/light/arrow-left.svg b/bin/GuiConfigs/light/arrow-left.svg
new file mode 100644
index 0000000000..6502056f9f
--- /dev/null
+++ b/bin/GuiConfigs/light/arrow-left.svg
@@ -0,0 +1,3 @@
+
diff --git a/bin/GuiConfigs/light/arrow-next.svg b/bin/GuiConfigs/light/arrow-next.svg
new file mode 100644
index 0000000000..58a8176040
--- /dev/null
+++ b/bin/GuiConfigs/light/arrow-next.svg
@@ -0,0 +1,15 @@
+
diff --git a/bin/GuiConfigs/light/arrow-prev.svg b/bin/GuiConfigs/light/arrow-prev.svg
new file mode 100644
index 0000000000..233a70c3f5
--- /dev/null
+++ b/bin/GuiConfigs/light/arrow-prev.svg
@@ -0,0 +1,15 @@
+
diff --git a/bin/GuiConfigs/light/arrow-right-disabled.svg b/bin/GuiConfigs/light/arrow-right-disabled.svg
new file mode 100644
index 0000000000..486e6c0691
--- /dev/null
+++ b/bin/GuiConfigs/light/arrow-right-disabled.svg
@@ -0,0 +1,3 @@
+
diff --git a/bin/GuiConfigs/light/arrow-right.svg b/bin/GuiConfigs/light/arrow-right.svg
new file mode 100644
index 0000000000..651e7adf4f
--- /dev/null
+++ b/bin/GuiConfigs/light/arrow-right.svg
@@ -0,0 +1,3 @@
+
diff --git a/bin/GuiConfigs/light/arrow-up-disabled.svg b/bin/GuiConfigs/light/arrow-up-disabled.svg
new file mode 100644
index 0000000000..1651415127
--- /dev/null
+++ b/bin/GuiConfigs/light/arrow-up-disabled.svg
@@ -0,0 +1,3 @@
+
diff --git a/bin/GuiConfigs/light/arrow-up.svg b/bin/GuiConfigs/light/arrow-up.svg
new file mode 100644
index 0000000000..8b1065f702
--- /dev/null
+++ b/bin/GuiConfigs/light/arrow-up.svg
@@ -0,0 +1,3 @@
+
diff --git a/bin/GuiConfigs/light/check-mark-disabled.svg b/bin/GuiConfigs/light/check-mark-disabled.svg
new file mode 100644
index 0000000000..5d42a7aa9e
--- /dev/null
+++ b/bin/GuiConfigs/light/check-mark-disabled.svg
@@ -0,0 +1,3 @@
+
diff --git a/bin/GuiConfigs/light/check-mark.svg b/bin/GuiConfigs/light/check-mark.svg
new file mode 100644
index 0000000000..f0dd920b06
--- /dev/null
+++ b/bin/GuiConfigs/light/check-mark.svg
@@ -0,0 +1,3 @@
+
diff --git a/bin/GuiConfigs/light/checkbox-checked-disabled.svg b/bin/GuiConfigs/light/checkbox-checked-disabled.svg
new file mode 100644
index 0000000000..49dd8ce5e7
--- /dev/null
+++ b/bin/GuiConfigs/light/checkbox-checked-disabled.svg
@@ -0,0 +1,12 @@
+
diff --git a/bin/GuiConfigs/light/checkbox-checked-hover.svg b/bin/GuiConfigs/light/checkbox-checked-hover.svg
new file mode 100644
index 0000000000..183bf80fc7
--- /dev/null
+++ b/bin/GuiConfigs/light/checkbox-checked-hover.svg
@@ -0,0 +1,11 @@
+
diff --git a/bin/GuiConfigs/light/checkbox-checked-pressed.svg b/bin/GuiConfigs/light/checkbox-checked-pressed.svg
new file mode 100644
index 0000000000..e71a14b93a
--- /dev/null
+++ b/bin/GuiConfigs/light/checkbox-checked-pressed.svg
@@ -0,0 +1,11 @@
+
diff --git a/bin/GuiConfigs/light/checkbox-checked.svg b/bin/GuiConfigs/light/checkbox-checked.svg
new file mode 100644
index 0000000000..7a2acc4fb7
--- /dev/null
+++ b/bin/GuiConfigs/light/checkbox-checked.svg
@@ -0,0 +1,11 @@
+
diff --git a/bin/GuiConfigs/light/checkbox-disabled.svg b/bin/GuiConfigs/light/checkbox-disabled.svg
new file mode 100644
index 0000000000..700da26462
--- /dev/null
+++ b/bin/GuiConfigs/light/checkbox-disabled.svg
@@ -0,0 +1,4 @@
+
diff --git a/bin/GuiConfigs/light/checkbox-indeterminate-disabled.svg b/bin/GuiConfigs/light/checkbox-indeterminate-disabled.svg
new file mode 100644
index 0000000000..a430d6a8c0
--- /dev/null
+++ b/bin/GuiConfigs/light/checkbox-indeterminate-disabled.svg
@@ -0,0 +1,12 @@
+
diff --git a/bin/GuiConfigs/light/checkbox-indeterminate-hover.svg b/bin/GuiConfigs/light/checkbox-indeterminate-hover.svg
new file mode 100644
index 0000000000..c4fbf20574
--- /dev/null
+++ b/bin/GuiConfigs/light/checkbox-indeterminate-hover.svg
@@ -0,0 +1,11 @@
+
diff --git a/bin/GuiConfigs/light/checkbox-indeterminate-pressed.svg b/bin/GuiConfigs/light/checkbox-indeterminate-pressed.svg
new file mode 100644
index 0000000000..b8c4d2644a
--- /dev/null
+++ b/bin/GuiConfigs/light/checkbox-indeterminate-pressed.svg
@@ -0,0 +1,11 @@
+
diff --git a/bin/GuiConfigs/light/checkbox-indeterminate.svg b/bin/GuiConfigs/light/checkbox-indeterminate.svg
new file mode 100644
index 0000000000..0a89706c5e
--- /dev/null
+++ b/bin/GuiConfigs/light/checkbox-indeterminate.svg
@@ -0,0 +1,11 @@
+
diff --git a/bin/GuiConfigs/light/checkbox-unchecked-hover.svg b/bin/GuiConfigs/light/checkbox-unchecked-hover.svg
new file mode 100644
index 0000000000..4789c03a08
--- /dev/null
+++ b/bin/GuiConfigs/light/checkbox-unchecked-hover.svg
@@ -0,0 +1,4 @@
+
diff --git a/bin/GuiConfigs/light/checkbox-unchecked-pressed.svg b/bin/GuiConfigs/light/checkbox-unchecked-pressed.svg
new file mode 100644
index 0000000000..709e2686c5
--- /dev/null
+++ b/bin/GuiConfigs/light/checkbox-unchecked-pressed.svg
@@ -0,0 +1,4 @@
+
diff --git a/bin/GuiConfigs/light/checkbox-unchecked.svg b/bin/GuiConfigs/light/checkbox-unchecked.svg
new file mode 100644
index 0000000000..2a4cfd581e
--- /dev/null
+++ b/bin/GuiConfigs/light/checkbox-unchecked.svg
@@ -0,0 +1,4 @@
+
diff --git a/bin/GuiConfigs/light/empty.svg b/bin/GuiConfigs/light/empty.svg
new file mode 100644
index 0000000000..d216ff7f65
--- /dev/null
+++ b/bin/GuiConfigs/light/empty.svg
@@ -0,0 +1,2 @@
+
diff --git a/bin/GuiConfigs/light/list-arrow-closed-disabled.svg b/bin/GuiConfigs/light/list-arrow-closed-disabled.svg
new file mode 100644
index 0000000000..d4fbdf3b40
--- /dev/null
+++ b/bin/GuiConfigs/light/list-arrow-closed-disabled.svg
@@ -0,0 +1,3 @@
+
diff --git a/bin/GuiConfigs/light/list-arrow-closed.svg b/bin/GuiConfigs/light/list-arrow-closed.svg
new file mode 100644
index 0000000000..94f388d3e3
--- /dev/null
+++ b/bin/GuiConfigs/light/list-arrow-closed.svg
@@ -0,0 +1,3 @@
+
diff --git a/bin/GuiConfigs/light/list-arrow-open-disabled.svg b/bin/GuiConfigs/light/list-arrow-open-disabled.svg
new file mode 100644
index 0000000000..243df7618d
--- /dev/null
+++ b/bin/GuiConfigs/light/list-arrow-open-disabled.svg
@@ -0,0 +1,3 @@
+
diff --git a/bin/GuiConfigs/light/list-arrow-open.svg b/bin/GuiConfigs/light/list-arrow-open.svg
new file mode 100644
index 0000000000..9ee4cfb85b
--- /dev/null
+++ b/bin/GuiConfigs/light/list-arrow-open.svg
@@ -0,0 +1,3 @@
+
diff --git a/bin/GuiConfigs/light/radio-checked-disabled.svg b/bin/GuiConfigs/light/radio-checked-disabled.svg
new file mode 100644
index 0000000000..13084c94a7
--- /dev/null
+++ b/bin/GuiConfigs/light/radio-checked-disabled.svg
@@ -0,0 +1,5 @@
+
diff --git a/bin/GuiConfigs/light/radio-checked-hover.svg b/bin/GuiConfigs/light/radio-checked-hover.svg
new file mode 100644
index 0000000000..abfd016a75
--- /dev/null
+++ b/bin/GuiConfigs/light/radio-checked-hover.svg
@@ -0,0 +1,4 @@
+
diff --git a/bin/GuiConfigs/light/radio-checked-pressed.svg b/bin/GuiConfigs/light/radio-checked-pressed.svg
new file mode 100644
index 0000000000..f842bd4701
--- /dev/null
+++ b/bin/GuiConfigs/light/radio-checked-pressed.svg
@@ -0,0 +1,5 @@
+
diff --git a/bin/GuiConfigs/light/radio-checked.svg b/bin/GuiConfigs/light/radio-checked.svg
new file mode 100644
index 0000000000..18e8c3bfc4
--- /dev/null
+++ b/bin/GuiConfigs/light/radio-checked.svg
@@ -0,0 +1,4 @@
+
diff --git a/bin/GuiConfigs/light/radio-disabled.svg b/bin/GuiConfigs/light/radio-disabled.svg
new file mode 100644
index 0000000000..c7a50333c9
--- /dev/null
+++ b/bin/GuiConfigs/light/radio-disabled.svg
@@ -0,0 +1,4 @@
+
diff --git a/bin/GuiConfigs/light/radio-unchecked-hover.svg b/bin/GuiConfigs/light/radio-unchecked-hover.svg
new file mode 100644
index 0000000000..61ac41e26c
--- /dev/null
+++ b/bin/GuiConfigs/light/radio-unchecked-hover.svg
@@ -0,0 +1,4 @@
+
diff --git a/bin/GuiConfigs/light/radio-unchecked-pressed.svg b/bin/GuiConfigs/light/radio-unchecked-pressed.svg
new file mode 100644
index 0000000000..909797e62d
--- /dev/null
+++ b/bin/GuiConfigs/light/radio-unchecked-pressed.svg
@@ -0,0 +1,5 @@
+
diff --git a/bin/GuiConfigs/light/radio-unchecked.svg b/bin/GuiConfigs/light/radio-unchecked.svg
new file mode 100644
index 0000000000..41a5f5a1d7
--- /dev/null
+++ b/bin/GuiConfigs/light/radio-unchecked.svg
@@ -0,0 +1,4 @@
+
diff --git a/bin/GuiConfigs/light/slider-handle-disabled.svg b/bin/GuiConfigs/light/slider-handle-disabled.svg
new file mode 100644
index 0000000000..0d2ddb8d7b
--- /dev/null
+++ b/bin/GuiConfigs/light/slider-handle-disabled.svg
@@ -0,0 +1,5 @@
+
diff --git a/bin/GuiConfigs/light/slider-handle-hover.svg b/bin/GuiConfigs/light/slider-handle-hover.svg
new file mode 100644
index 0000000000..9eea790adf
--- /dev/null
+++ b/bin/GuiConfigs/light/slider-handle-hover.svg
@@ -0,0 +1,5 @@
+
diff --git a/bin/GuiConfigs/light/slider-handle-pressed.svg b/bin/GuiConfigs/light/slider-handle-pressed.svg
new file mode 100644
index 0000000000..7989e9d376
--- /dev/null
+++ b/bin/GuiConfigs/light/slider-handle-pressed.svg
@@ -0,0 +1,5 @@
+
diff --git a/bin/GuiConfigs/light/slider-handle.svg b/bin/GuiConfigs/light/slider-handle.svg
new file mode 100644
index 0000000000..2c5df2c491
--- /dev/null
+++ b/bin/GuiConfigs/light/slider-handle.svg
@@ -0,0 +1,5 @@
+
diff --git a/bin/GuiConfigs/light/window-close.svg b/bin/GuiConfigs/light/window-close.svg
new file mode 100644
index 0000000000..5a1ef8d6e9
--- /dev/null
+++ b/bin/GuiConfigs/light/window-close.svg
@@ -0,0 +1,10 @@
+
diff --git a/bin/GuiConfigs/light/window-undock.svg b/bin/GuiConfigs/light/window-undock.svg
new file mode 100644
index 0000000000..df9a297b96
--- /dev/null
+++ b/bin/GuiConfigs/light/window-undock.svg
@@ -0,0 +1,10 @@
+
diff --git a/rpcs3/Emu/Audio/AudioBackend.cpp b/rpcs3/Emu/Audio/AudioBackend.cpp
index e0d96c8c2b..80af260414 100644
--- a/rpcs3/Emu/Audio/AudioBackend.cpp
+++ b/rpcs3/Emu/Audio/AudioBackend.cpp
@@ -2,6 +2,8 @@
#include "AudioBackend.h"
#include "Emu/IdManager.h"
#include "Emu//Cell/Modules/cellAudioOut.h"
+#include
+#include
AudioBackend::AudioBackend() {}
@@ -57,15 +59,25 @@ f32 AudioBackend::apply_volume(const VolumeParam& param, u32 sample_cnt, const f
{
ensure(param.ch_cnt > 1 && param.ch_cnt % 2 == 0); // Tends to produce faster code
+ // Fast path when no volume change is needed
+ if (param.current_volume == param.target_volume)
+ {
+ apply_volume_static(param.target_volume, sample_cnt, src, dst);
+ return param.target_volume;
+ }
+
const f32 vol_incr = (param.target_volume - param.initial_volume) / (VOLUME_CHANGE_DURATION * param.freq);
f32 crnt_vol = param.current_volume;
u32 sample_idx = 0;
+ // Use epsilon for float comparison to avoid infinite loops
+ constexpr f32 epsilon = 1e-6f;
+
if (vol_incr >= 0)
{
- for (sample_idx = 0; sample_idx < sample_cnt && crnt_vol != param.target_volume; sample_idx += param.ch_cnt)
+ for (sample_idx = 0; sample_idx < sample_cnt && (param.target_volume - crnt_vol) > epsilon; sample_idx += param.ch_cnt)
{
- crnt_vol = std::min(param.current_volume + (sample_idx + 1) / param.ch_cnt * vol_incr, param.target_volume);
+ crnt_vol = std::min(crnt_vol + vol_incr, param.target_volume);
for (u32 i = 0; i < param.ch_cnt; i++)
{
@@ -75,9 +87,9 @@ f32 AudioBackend::apply_volume(const VolumeParam& param, u32 sample_cnt, const f
}
else
{
- for (sample_idx = 0; sample_idx < sample_cnt && crnt_vol != param.target_volume; sample_idx += param.ch_cnt)
+ for (sample_idx = 0; sample_idx < sample_cnt && (crnt_vol - param.target_volume) > epsilon; sample_idx += param.ch_cnt)
{
- crnt_vol = std::max(param.current_volume + (sample_idx + 1) / param.ch_cnt * vol_incr, param.target_volume);
+ crnt_vol = std::max(crnt_vol + vol_incr, param.target_volume);
for (u32 i = 0; i < param.ch_cnt; i++)
{
@@ -96,6 +108,25 @@ f32 AudioBackend::apply_volume(const VolumeParam& param, u32 sample_cnt, const f
void AudioBackend::apply_volume_static(f32 vol, u32 sample_cnt, const f32* src, f32* dst)
{
+ // Improved volume application with better precision
+ if (vol == 1.0f)
+ {
+ // Fast path for unity gain - no multiplication needed
+ if (src != dst)
+ {
+ std::memcpy(dst, src, sample_cnt * sizeof(f32));
+ }
+ return;
+ }
+
+ if (vol == 0.0f)
+ {
+ // Fast path for mute
+ std::memset(dst, 0, sample_cnt * sizeof(f32));
+ return;
+ }
+
+ // Process samples with improved precision
for (u32 i = 0; i < sample_cnt; i++)
{
dst[i] = src[i] * vol;
@@ -104,9 +135,37 @@ void AudioBackend::apply_volume_static(f32 vol, u32 sample_cnt, const f32* src,
void AudioBackend::normalize(u32 sample_cnt, const f32* src, f32* dst)
{
+ // Improved normalization with soft clipping and better dynamic range handling
+ constexpr f32 soft_clip_threshold = 0.95f;
+ constexpr f32 hard_clip_limit = 1.0f;
+
for (u32 i = 0; i < sample_cnt; i++)
{
- dst[i] = std::clamp(src[i], -1.0f, 1.0f);
+ f32 sample = src[i];
+ f32 abs_sample = std::abs(sample);
+
+ if (abs_sample > soft_clip_threshold)
+ {
+ // Apply soft clipping for smoother distortion
+ f32 sign = std::copysign(1.0f, sample);
+ if (abs_sample > hard_clip_limit)
+ {
+ // Hard limit to prevent overflow
+ dst[i] = sign * hard_clip_limit;
+ }
+ else
+ {
+ // Soft clipping using tanh-like curve
+ f32 excess = (abs_sample - soft_clip_threshold) / (hard_clip_limit - soft_clip_threshold);
+ f32 soft_factor = soft_clip_threshold + (hard_clip_limit - soft_clip_threshold) * std::tanh(excess);
+ dst[i] = sign * soft_factor;
+ }
+ }
+ else
+ {
+ // No clipping needed
+ dst[i] = sample;
+ }
}
}
diff --git a/rpcs3/Emu/Audio/AudioBackend.h b/rpcs3/Emu/Audio/AudioBackend.h
index cbd8e045c9..bc07a1e46f 100644
--- a/rpcs3/Emu/Audio/AudioBackend.h
+++ b/rpcs3/Emu/Audio/AudioBackend.h
@@ -17,11 +17,11 @@ enum : u32
enum class AudioFreq : u32
{
- FREQ_32K = 32000,
- FREQ_44K = 44100,
- FREQ_48K = 48000,
- FREQ_88K = 88200,
- FREQ_96K = 96000,
+ FREQ_32K = 32000,
+ FREQ_44K = 44100,
+ FREQ_48K = 48000,
+ FREQ_88K = 88200,
+ FREQ_96K = 96000,
FREQ_176K = 176400,
FREQ_192K = 192000,
};
@@ -35,7 +35,7 @@ enum class AudioSampleSize : u32
// This enum is only used for emulation
enum class AudioChannelCnt : u32
{
- STEREO = 2,
+ STEREO = 2,
SURROUND_5_1 = 6,
SURROUND_7_1 = 8,
};
@@ -49,7 +49,6 @@ enum class AudioStateEvent : u32
class AudioBackend
{
public:
-
struct VolumeParam
{
f32 initial_volume = 1.0f;
@@ -93,7 +92,10 @@ public:
virtual f64 GetCallbackFrameLen() = 0;
// Returns true if audio is currently being played, false otherwise. Reflects end result of Play() and Pause() calls.
- virtual bool IsPlaying() { return m_playing; }
+ virtual bool IsPlaying()
+ {
+ return m_playing;
+ }
// Start playing enqueued data.
virtual void Play() = 0;
@@ -105,17 +107,26 @@ public:
* This virtual method should be reimplemented if backend can fail to be initialized under non-error conditions
* eg. when there is no audio devices attached
*/
- virtual bool Initialized() { return true; }
+ virtual bool Initialized()
+ {
+ return true;
+ }
/*
* This virtual method should be reimplemented if backend can fail during normal operation
*/
- virtual bool Operational() { return true; }
+ virtual bool Operational()
+ {
+ return true;
+ }
/*
* This virtual method should be reimplemented if backend can report device changes
*/
- virtual bool DefaultDeviceChanged() { return false; }
+ virtual bool DefaultDeviceChanged()
+ {
+ return false;
+ }
/*
* Helper methods
@@ -180,20 +191,21 @@ public:
/*
* Downmix audio stream.
*/
- template
+ template
static void downmix(u32 sample_cnt, const f32* src, f32* dst)
{
const u32 dst_ch_cnt = default_layout_channel_count(dst_layout);
- if (static_cast(src_ch_cnt) <= dst_ch_cnt) fmt::throw_exception("src channel count must be bigger than dst channel count");
+ if (static_cast(src_ch_cnt) <= dst_ch_cnt)
+ fmt::throw_exception("src channel count must be bigger than dst channel count");
static constexpr f32 center_coef = std::numbers::sqrt2_v / 2;
static constexpr f32 surround_coef = std::numbers::sqrt2_v / 2;
for (u32 src_sample = 0, dst_sample = 0; src_sample < sample_cnt; src_sample += static_cast(src_ch_cnt), dst_sample += dst_ch_cnt)
{
- const f32 left = src[src_sample + 0];
+ const f32 left = src[src_sample + 0];
const f32 right = src[src_sample + 1];
-
+
if constexpr (src_ch_cnt == AudioChannelCnt::STEREO)
{
if constexpr (dst_layout == audio_channel_layout::mono)
@@ -203,9 +215,9 @@ public:
}
else if constexpr (src_ch_cnt == AudioChannelCnt::SURROUND_5_1)
{
- const f32 center = src[src_sample + 2];
- const f32 low_freq = src[src_sample + 3];
- const f32 side_left = src[src_sample + 4];
+ const f32 center = src[src_sample + 2];
+ const f32 low_freq = src[src_sample + 3];
+ const f32 side_left = src[src_sample + 4];
const f32 side_right = src[src_sample + 5];
if constexpr (dst_layout == audio_channel_layout::quadraphonic || dst_layout == audio_channel_layout::quadraphonic_lfe)
@@ -239,11 +251,11 @@ public:
}
else if constexpr (src_ch_cnt == AudioChannelCnt::SURROUND_7_1)
{
- const f32 center = src[src_sample + 2];
- const f32 low_freq = src[src_sample + 3];
- const f32 rear_left = src[src_sample + 4];
+ const f32 center = src[src_sample + 2];
+ const f32 low_freq = src[src_sample + 3];
+ const f32 rear_left = src[src_sample + 4];
const f32 rear_right = src[src_sample + 5];
- const f32 side_left = src[src_sample + 6];
+ const f32 side_left = src[src_sample + 6];
const f32 side_right = src[src_sample + 7];
if constexpr (dst_layout == audio_channel_layout::surround_5_1)
@@ -372,12 +384,12 @@ protected:
void setup_channel_layout(u32 input_channel_count, u32 output_channel_count, audio_channel_layout layout, logs::channel& log);
AudioSampleSize m_sample_size = AudioSampleSize::FLOAT;
- AudioFreq m_sampling_rate = AudioFreq::FREQ_48K;
- u32 m_channels = 2;
+ AudioFreq m_sampling_rate = AudioFreq::FREQ_48K;
+ u32 m_channels = 2;
audio_channel_layout m_layout = audio_channel_layout::automatic;
std::timed_mutex m_cb_mutex{};
- std::function m_write_callback{};
+ std::function m_write_callback{};
shared_mutex m_state_cb_mutex{};
std::function m_state_callback{};
@@ -385,6 +397,5 @@ protected:
bool m_playing = false;
private:
-
- static constexpr f32 VOLUME_CHANGE_DURATION = 0.016f; // sec
+ static constexpr f32 VOLUME_CHANGE_DURATION = 0.032f; // sec - Increased for smoother transitions
};
diff --git a/rpcs3/Emu/Audio/Cubeb/CubebBackend.cpp b/rpcs3/Emu/Audio/Cubeb/CubebBackend.cpp
index dbaf4aa8db..fc5b24da45 100644
--- a/rpcs3/Emu/Audio/Cubeb/CubebBackend.cpp
+++ b/rpcs3/Emu/Audio/Cubeb/CubebBackend.cpp
@@ -90,11 +90,6 @@ bool CubebBackend::DefaultDeviceChanged()
}
device_handle device = GetDevice();
- if (!device.handle)
- {
- Cubeb.error("Selected device not found. Trying alternative approach...");
- device = GetDefaultDeviceAlt(m_sampling_rate, m_sample_size, m_channels);
- }
return !device.handle || device.id != m_default_device;
}
@@ -119,20 +114,9 @@ bool CubebBackend::Open(std::string_view dev_id, AudioFreq freq, AudioSampleSize
if (!device.handle)
{
- if (use_default_device)
- {
- device = GetDefaultDeviceAlt(freq, sample_size, static_cast(ch_cnt));
-
- if (!device.handle)
- {
- Cubeb.error("Cannot detect default device. Channel count detection unavailable.");
- }
- }
- else
- {
- Cubeb.error("Device with id=%s not found", dev_id);
- return false;
- }
+ if (use_default_device) Cubeb.error("Opening default device failed");
+ else Cubeb.error("Device with id=%s not found", dev_id);
+ return false;
}
if (device.ch_cnt == 0)
@@ -358,68 +342,6 @@ CubebBackend::device_handle CubebBackend::GetDevice(std::string_view dev_id)
return result;
};
-CubebBackend::device_handle CubebBackend::GetDefaultDeviceAlt(AudioFreq freq, AudioSampleSize sample_size, u32 ch_cnt)
-{
- Cubeb.notice("Starting alternative search for default device with freq=%d, sample_size=%d and ch_cnt=%d", static_cast(freq), static_cast(sample_size), static_cast(ch_cnt));
-
- cubeb_stream_params param =
- {
- .format = sample_size == AudioSampleSize::S16 ? CUBEB_SAMPLE_S16NE : CUBEB_SAMPLE_FLOAT32NE,
- .rate = static_cast(freq),
- .channels = static_cast(ch_cnt),
- .layout = CUBEB_LAYOUT_UNDEFINED,
- .prefs = CUBEB_STREAM_PREF_DISABLE_DEVICE_SWITCHING
- };
-
- u32 min_latency{};
- if (int err = cubeb_get_min_latency(m_ctx, ¶m, &min_latency))
- {
- Cubeb.error("cubeb_get_min_latency() failed: %i", err);
- min_latency = 100;
- }
-
- cubeb_stream* tmp_stream{};
- static auto dummy_data_cb = [](cubeb_stream*, void*, void const*, void*, long) -> long { return 0; };
- static auto dummy_state_cb = [](cubeb_stream*, void*, cubeb_state) {};
-
- if (int err = cubeb_stream_init(m_ctx, &tmp_stream, "Default device detector", nullptr, nullptr, nullptr, ¶m, min_latency, dummy_data_cb, dummy_state_cb, nullptr))
- {
- Cubeb.error("cubeb_stream_init() failed: %i", err);
- return {};
- }
-
- cubeb_device* crnt_dev{};
-
- if (int err = cubeb_stream_get_current_device(tmp_stream, &crnt_dev); err != CUBEB_OK || !crnt_dev)
- {
- Cubeb.error("cubeb_stream_get_current_device() failed: err=%i, crnt_dev=%d", err, !!crnt_dev);
- cubeb_stream_destroy(tmp_stream);
- return {};
- }
-
- std::string out_dev_name;
-
- if (crnt_dev->output_name)
- {
- out_dev_name = crnt_dev->output_name;
- }
-
- if (int err = cubeb_stream_device_destroy(tmp_stream, crnt_dev))
- {
- Cubeb.error("cubeb_stream_device_destroy() failed: %i", err);
- }
-
- cubeb_stream_destroy(tmp_stream);
-
- if (out_dev_name.empty())
- {
- Cubeb.notice("No default device available");
- return {};
- }
-
- return GetDevice(out_dev_name);
-}
-
long CubebBackend::data_cb(cubeb_stream* stream, void* user_ptr, void const* /* input_buffer */, void* output_buffer, long nframes)
{
if (nframes <= 0)
diff --git a/rpcs3/Emu/Audio/Cubeb/CubebBackend.h b/rpcs3/Emu/Audio/Cubeb/CubebBackend.h
index 1f230ec238..9641b46006 100644
--- a/rpcs3/Emu/Audio/Cubeb/CubebBackend.h
+++ b/rpcs3/Emu/Audio/Cubeb/CubebBackend.h
@@ -61,5 +61,4 @@ private:
};
device_handle GetDevice(std::string_view dev_id = "");
- device_handle GetDefaultDeviceAlt(AudioFreq freq, AudioSampleSize sample_size, u32 ch_cnt);
};
diff --git a/rpcs3/Emu/Audio/audio_resampler.cpp b/rpcs3/Emu/Audio/audio_resampler.cpp
index 32c7109b4c..108c63e66d 100644
--- a/rpcs3/Emu/Audio/audio_resampler.cpp
+++ b/rpcs3/Emu/Audio/audio_resampler.cpp
@@ -4,8 +4,12 @@
audio_resampler::audio_resampler()
{
- resampler.setSetting(SETTING_SEQUENCE_MS, 20); // Resampler frame size (reduce latency at cost of slight sound quality degradation)
- resampler.setSetting(SETTING_USE_QUICKSEEK, 1); // Use fast quick seeking algorithm (substantally reduces computation time)
+ // Improved quality settings for better audio output
+ resampler.setSetting(SETTING_SEQUENCE_MS, 40); // Increased sequence length for better quality (was 20)
+ resampler.setSetting(SETTING_SEEKWINDOW_MS, 15); // Better seeking window for smoother transitions
+ resampler.setSetting(SETTING_OVERLAP_MS, 8); // Improved overlap for better quality
+ resampler.setSetting(SETTING_USE_QUICKSEEK, 0); // Disable quick seek for higher quality (was 1)
+ resampler.setSetting(SETTING_USE_AA_FILTER, 1); // Enable anti-aliasing filter for cleaner sound
}
audio_resampler::~audio_resampler()
@@ -35,7 +39,7 @@ std::pair audio_resampler::get_samples(u32
{
// NOTE: Make sure to get the buffer first because receiveSamples advances its position internally
// and std::make_pair evaluates the second parameter first...
- f32 *const buf = resampler.bufBegin();
+ f32* const buf = resampler.bufBegin();
return std::make_pair(buf, resampler.receiveSamples(sample_cnt));
}
diff --git a/rpcs3/Emu/Audio/audio_utils.cpp b/rpcs3/Emu/Audio/audio_utils.cpp
index bcff7bf947..2db2e1a0ed 100644
--- a/rpcs3/Emu/Audio/audio_utils.cpp
+++ b/rpcs3/Emu/Audio/audio_utils.cpp
@@ -4,6 +4,7 @@
#include "Emu/System.h"
#include "Emu/IdManager.h"
#include "Emu/RSX/Overlays/overlay_message.h"
+#include
namespace audio
{
@@ -24,16 +25,33 @@ namespace audio
void change_volume(s32 delta)
{
// Ignore if muted
- if (g_fxo->get().audio_muted) return;
+ if (g_fxo->get().audio_muted)
+ return;
const s32 old_volume = g_cfg.audio.volume;
- const s32 new_volume = old_volume + delta;
- if (old_volume == new_volume) return;
+ // Apply non-linear volume scaling for better perceived volume control
+ // Use smaller steps at lower volumes for finer control
+ s32 adjusted_delta = delta;
+ if (old_volume < 25 && abs(delta) > 1)
+ {
+ // Smaller steps at low volume for better control
+ adjusted_delta = delta > 0 ? 1 : -1;
+ }
+ else if (old_volume > 75 && abs(delta) < 5)
+ {
+ // Larger steps at high volume for faster adjustment
+ adjusted_delta = delta > 0 ? std::min(delta * 2, 5) : std::max(delta * 2, -5);
+ }
+
+ const s32 new_volume = old_volume + adjusted_delta;
+
+ if (old_volume == new_volume)
+ return;
g_cfg.audio.volume.set(std::clamp(new_volume, g_cfg.audio.volume.min, g_cfg.audio.volume.max));
Emu.GetCallbacks().update_emu_settings();
rsx::overlays::queue_message(get_localized_string(localized_string_id::AUDIO_CHANGED, fmt::format("%d%%", g_cfg.audio.volume.get()).c_str()), 3'000'000);
}
-}
+} // namespace audio
diff --git a/rpcs3/Emu/CMakeLists.txt b/rpcs3/Emu/CMakeLists.txt
index 1a9e95a44d..ad310ba1e0 100644
--- a/rpcs3/Emu/CMakeLists.txt
+++ b/rpcs3/Emu/CMakeLists.txt
@@ -578,6 +578,7 @@ if(TARGET 3rdparty_vulkan)
RSX/VK/vkutils/buffer_object.cpp
RSX/VK/vkutils/chip_class.cpp
RSX/VK/vkutils/commands.cpp
+ RSX/VK/vkutils/ex.cpp
RSX/VK/vkutils/data_heap.cpp
RSX/VK/vkutils/descriptors.cpp
RSX/VK/vkutils/image.cpp
@@ -643,6 +644,7 @@ target_link_libraries(rpcs3_emu
3rdparty::libevdev
3rdparty::flatbuffers
3rdparty::pugixml
+ 3rdparty::vulkanmemoryallocator
Threads::Threads
PRIVATE
3rdparty::glslang
diff --git a/rpcs3/Emu/CPU/CPUThread.cpp b/rpcs3/Emu/CPU/CPUThread.cpp
index 242dcb9d9f..9710af94f5 100644
--- a/rpcs3/Emu/CPU/CPUThread.cpp
+++ b/rpcs3/Emu/CPU/CPUThread.cpp
@@ -1158,7 +1158,7 @@ cpu_thread& cpu_thread::operator=(thread_state)
{
if (u32 resv = atomic_storage::load(thread->raddr))
{
- vm::reservation_notifier_notify(resv);
+ vm::reservation_notifier_notify(resv, thread->rtime);
}
}
}
diff --git a/rpcs3/Emu/Cell/Modules/cellAvconfExt.cpp b/rpcs3/Emu/Cell/Modules/cellAvconfExt.cpp
index b4508ada5b..4851895537 100644
--- a/rpcs3/Emu/Cell/Modules/cellAvconfExt.cpp
+++ b/rpcs3/Emu/Cell/Modules/cellAvconfExt.cpp
@@ -520,7 +520,7 @@ error_code cellVideoOutGetScreenSize(u32 videoOut, vm::ptr screenSize)
return CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT;
}
- if (g_cfg.video.stereo_render_mode != stereo_render_mode_options::disabled)
+ if (g_cfg.video.stereo_enabled)
{
// Return Playstation 3D display value
// Some games call this function when 3D is enabled
diff --git a/rpcs3/Emu/Cell/Modules/cellGem.cpp b/rpcs3/Emu/Cell/Modules/cellGem.cpp
index ba796be28e..9d39b3c7eb 100644
--- a/rpcs3/Emu/Cell/Modules/cellGem.cpp
+++ b/rpcs3/Emu/Cell/Modules/cellGem.cpp
@@ -3482,7 +3482,7 @@ error_code cellGemSetRumble(u32 gem_num, u8 rumble)
{
if (!binding.device || binding.device->player_id != pad_index) continue;
- handler->SetRumble(pad_index, rumble, rumble > 0);
+ handler->SetRumble(pad_index, rumble, rumble);
break;
}
}
diff --git a/rpcs3/Emu/Cell/Modules/cellL10n.cpp b/rpcs3/Emu/Cell/Modules/cellL10n.cpp
index 6b3ffc4448..0f47c682e6 100644
--- a/rpcs3/Emu/Cell/Modules/cellL10n.cpp
+++ b/rpcs3/Emu/Cell/Modules/cellL10n.cpp
@@ -2498,7 +2498,7 @@ s32 UCS2stoSBCSs(vm::cptr src, vm::ptr src_len, vm::ptr dst, vm::p
for (u32 src_pos = 0; src_pos < *src_len; src_pos++)
{
- const s16 ucs2 = src[src_pos];
+ const u16 ucs2 = src[src_pos];
if (ucs2 >= 0xfffe)
{
diff --git a/rpcs3/Emu/Cell/Modules/cellMic.cpp b/rpcs3/Emu/Cell/Modules/cellMic.cpp
index a5ece1be59..0724b48927 100644
--- a/rpcs3/Emu/Cell/Modules/cellMic.cpp
+++ b/rpcs3/Emu/Cell/Modules/cellMic.cpp
@@ -11,7 +11,7 @@
#include
#ifndef WITHOUT_OPENAL
-#include "3rdparty/OpenAL/openal-soft/include/AL/alext.h"
+#include "alext.h"
#endif
LOG_CHANNEL(cellMic);
diff --git a/rpcs3/Emu/Cell/Modules/cellMic.h b/rpcs3/Emu/Cell/Modules/cellMic.h
index e4b416fa6a..88a2f4d937 100644
--- a/rpcs3/Emu/Cell/Modules/cellMic.h
+++ b/rpcs3/Emu/Cell/Modules/cellMic.h
@@ -1,9 +1,10 @@
#pragma once
#include "Utilities/Thread.h"
-#include "3rdparty/OpenAL/openal-soft/include/AL/alc.h"
#include "Utilities/mutex.h"
+#include "alc.h"
+
// Error Codes
enum CellMicInError : u32
{
diff --git a/rpcs3/Emu/Cell/Modules/cellMouse.cpp b/rpcs3/Emu/Cell/Modules/cellMouse.cpp
index 8bf550a633..750b463c0c 100644
--- a/rpcs3/Emu/Cell/Modules/cellMouse.cpp
+++ b/rpcs3/Emu/Cell/Modules/cellMouse.cpp
@@ -1,8 +1,9 @@
#include "stdafx.h"
#include "Emu/IdManager.h"
+#include "Emu/system_config.h"
#include "Emu/Cell/PPUModule.h"
-
#include "Emu/Io/MouseHandler.h"
+#include "Emu/RSX/Overlays/overlay_debug_overlay.h"
#include "cellMouse.h"
@@ -13,6 +14,54 @@ extern bool is_input_allowed();
LOG_CHANNEL(cellMouse);
+void show_debug_overlay(const CellMouseData& data, const MouseData* _mouse)
+{
+ // The cell mouse can be set empty without any new mouse input.
+ // Only update our mouse input if there is new data.
+ static MouseData mouse {};
+ if (_mouse)
+ {
+ mouse = *_mouse;
+ }
+
+ std::string text = fmt::format(
+ "> Name: Raw Value Pixel\n"
+ ">\n"
+ "> Update: %5d %5d\n"
+ "> Wheel: %5d %5d\n"
+ "> Tilt: %5d %5d\n"
+ "> X: %5d %5d %5d\n"
+ "> Y: %5d %5d %5d\n"
+ ">\n"
+ "> Buttons: 0x%04x 0x%04x\n"
+ "> Button 1: %5d %5d\n"
+ "> Button 2: %5d %5d\n"
+ "> Button 3: %5d %5d\n"
+ "> Button 4: %5d %5d\n"
+ "> Button 5: %5d %5d\n"
+ "> Button 6: %5d %5d\n"
+ "> Button 7: %5d %5d\n"
+ "> Button 8: %5d %5d\n"
+ ,
+ mouse.update, data.update,
+ mouse.wheel, data.wheel,
+ mouse.tilt, data.tilt,
+ mouse.x_axis, data.x_axis, mouse.pixel_x,
+ mouse.y_axis, data.y_axis, mouse.pixel_y,
+ mouse.buttons, data.buttons,
+ !!(mouse.buttons & CELL_MOUSE_BUTTON_1), !!(data.buttons & CELL_MOUSE_BUTTON_1),
+ !!(mouse.buttons & CELL_MOUSE_BUTTON_2), !!(data.buttons & CELL_MOUSE_BUTTON_2),
+ !!(mouse.buttons & CELL_MOUSE_BUTTON_3), !!(data.buttons & CELL_MOUSE_BUTTON_3),
+ !!(mouse.buttons & CELL_MOUSE_BUTTON_4), !!(data.buttons & CELL_MOUSE_BUTTON_4),
+ !!(mouse.buttons & CELL_MOUSE_BUTTON_5), !!(data.buttons & CELL_MOUSE_BUTTON_5),
+ !!(mouse.buttons & CELL_MOUSE_BUTTON_6), !!(data.buttons & CELL_MOUSE_BUTTON_6),
+ !!(mouse.buttons & CELL_MOUSE_BUTTON_7), !!(data.buttons & CELL_MOUSE_BUTTON_7),
+ !!(mouse.buttons & CELL_MOUSE_BUTTON_8), !!(data.buttons & CELL_MOUSE_BUTTON_8)
+ );
+
+ rsx::overlays::set_debug_overlay_text(std::move(text));
+}
+
template<>
void fmt_class_string::format(std::string& out, u64 arg)
{
@@ -214,10 +263,16 @@ error_code cellMouseGetData(u32 port_no, vm::ptr data)
if (data_list.empty() || current_info.is_null_handler || (current_info.info & CELL_MOUSE_INFO_INTERCEPTED) || !is_input_allowed())
{
data_list.clear();
+
+ if (port_no == 0 && g_cfg.io.mouse_debug_overlay && !g_cfg.io.pad_debug_overlay && !g_cfg.video.debug_overlay)
+ {
+ show_debug_overlay(*data, nullptr);
+ }
+
return CELL_OK;
}
- const MouseData current_data = data_list.front();
+ const MouseData& current_data = data_list.front();
data->update = current_data.update;
data->buttons = current_data.buttons;
data->x_axis = current_data.x_axis;
@@ -225,6 +280,11 @@ error_code cellMouseGetData(u32 port_no, vm::ptr data)
data->wheel = current_data.wheel;
data->tilt = current_data.tilt;
+ if (port_no == 0 && g_cfg.io.mouse_debug_overlay && !g_cfg.io.pad_debug_overlay && !g_cfg.video.debug_overlay)
+ {
+ show_debug_overlay(*data, ¤t_data);
+ }
+
data_list.pop_front();
return CELL_OK;
@@ -264,20 +324,31 @@ error_code cellMouseGetDataList(u32 port_no, vm::ptr data)
if (list.empty() || current_info.is_null_handler || (current_info.info & CELL_MOUSE_INFO_INTERCEPTED) || !is_input_allowed())
{
list.clear();
+
+ if (port_no == 0 && g_cfg.io.mouse_debug_overlay && !g_cfg.io.pad_debug_overlay && !g_cfg.video.debug_overlay)
+ {
+ show_debug_overlay(data->list[0], nullptr);
+ }
+
return CELL_OK;
}
data->list_num = std::min(CELL_MOUSE_MAX_DATA_LIST_NUM, static_cast(list.size()));
- int i = 0;
- for (auto it = list.begin(); it != list.end() && i < CELL_MOUSE_MAX_DATA_LIST_NUM; ++it, ++i)
+ for (size_t i = 0; i < list.size() && i < CELL_MOUSE_MAX_DATA_LIST_NUM; ++i)
{
- data->list[i].update = it->update;
- data->list[i].buttons = it->buttons;
- data->list[i].x_axis = it->x_axis;
- data->list[i].y_axis = it->y_axis;
- data->list[i].wheel = it->wheel;
- data->list[i].tilt = it->tilt;
+ const MouseData& current_data = list[i];
+ data->list[i].update = current_data.update;
+ data->list[i].buttons = current_data.buttons;
+ data->list[i].x_axis = current_data.x_axis;
+ data->list[i].y_axis = current_data.y_axis;
+ data->list[i].wheel = current_data.wheel;
+ data->list[i].tilt = current_data.tilt;
+
+ if (port_no == 0 && g_cfg.io.mouse_debug_overlay && !g_cfg.io.pad_debug_overlay && !g_cfg.video.debug_overlay)
+ {
+ show_debug_overlay(data->list[i], ¤t_data);
+ }
}
list.clear();
diff --git a/rpcs3/Emu/Cell/Modules/cellPad.cpp b/rpcs3/Emu/Cell/Modules/cellPad.cpp
index 086a341854..a217a37313 100644
--- a/rpcs3/Emu/Cell/Modules/cellPad.cpp
+++ b/rpcs3/Emu/Cell/Modules/cellPad.cpp
@@ -76,6 +76,9 @@ void pad_info::save(utils::serial& ar)
void show_debug_overlay(const CellPadData& data, const Pad& pad, const pad_info& config)
{
const u32 setting = config.port_setting[pad.m_player_id];
+ const CellPadData& raw = pad.data;
+ const u16 raw_d1 = raw.button[CELL_PAD_BTN_OFFSET_DIGITAL1];
+ const u16 raw_d2 = raw.button[CELL_PAD_BTN_OFFSET_DIGITAL2];
const u16 d1 = data.button[CELL_PAD_BTN_OFFSET_DIGITAL1];
const u16 d2 = data.button[CELL_PAD_BTN_OFFSET_DIGITAL2];
@@ -86,6 +89,8 @@ void show_debug_overlay(const CellPadData& data, const Pad& pad, const pad_info&
"> Digital: %5s %5s\n"
"> Press: %5s %5s\n"
"> Sensor: %5s %5s\n"
+ "> Large Motor: %5d %5d\n"
+ "> Small Motor: %5d %5d\n"
">\n"
"> Digital 1: 0x%04x 0x%04x\n"
"> Digital 2: 0x%04x 0x%04x\n"
@@ -126,33 +131,35 @@ void show_debug_overlay(const CellPadData& data, const Pad& pad, const pad_info&
"on", data.len >= CELL_PAD_LEN_CHANGE_DEFAULT ? "on" : "off",
(setting & CELL_PAD_SETTING_PRESS_ON) ? "on" : "off", data.len >= CELL_PAD_LEN_CHANGE_PRESS_ON ? "on" : "off",
(setting & CELL_PAD_SETTING_SENSOR_ON) ? "on" : "off", data.len >= CELL_PAD_LEN_CHANGE_SENSOR_ON ? "on" : "off",
- pad.m_digital_1, d1,
- pad.m_digital_2, d2,
- pad.m_press_up, !!(d1 & CELL_PAD_CTRL_UP), data.button[CELL_PAD_BTN_OFFSET_PRESS_UP],
- pad.m_press_down, !!(d1 & CELL_PAD_CTRL_DOWN), data.button[CELL_PAD_BTN_OFFSET_PRESS_DOWN],
- pad.m_press_left, !!(d1 & CELL_PAD_CTRL_LEFT), data.button[CELL_PAD_BTN_OFFSET_PRESS_LEFT],
- pad.m_press_right, !!(d1 & CELL_PAD_CTRL_RIGHT), data.button[CELL_PAD_BTN_OFFSET_PRESS_RIGHT],
- pad.m_press_cross, !!(d2 & CELL_PAD_CTRL_CROSS), data.button[CELL_PAD_BTN_OFFSET_PRESS_CROSS],
- pad.m_press_square, !!(d2 & CELL_PAD_CTRL_SQUARE), data.button[CELL_PAD_BTN_OFFSET_PRESS_SQUARE],
- pad.m_press_circle, !!(d2 & CELL_PAD_CTRL_CIRCLE), data.button[CELL_PAD_BTN_OFFSET_PRESS_CIRCLE],
- pad.m_press_triangle, !!(d2 & CELL_PAD_CTRL_TRIANGLE), data.button[CELL_PAD_BTN_OFFSET_PRESS_TRIANGLE],
- !!(pad.m_digital_1 & CELL_PAD_CTRL_START), !!(d1 & CELL_PAD_CTRL_START),
- !!(pad.m_digital_1 & CELL_PAD_CTRL_SELECT), !!(d1 & CELL_PAD_CTRL_SELECT),
- !!(pad.m_digital_1 & CELL_PAD_CTRL_PS), !!(d1 & CELL_PAD_CTRL_PS),
- pad.m_press_L1, !!(d2 & CELL_PAD_CTRL_L1), data.button[CELL_PAD_BTN_OFFSET_PRESS_L1],
- pad.m_press_L2, !!(d2 & CELL_PAD_CTRL_L2), data.button[CELL_PAD_BTN_OFFSET_PRESS_L2],
- !!(pad.m_digital_1 & CELL_PAD_CTRL_L3), !!(d1 & CELL_PAD_CTRL_L3),
- pad.m_press_R1, !!(d2 & CELL_PAD_CTRL_R1), data.button[CELL_PAD_BTN_OFFSET_PRESS_R1],
- pad.m_press_R2, !!(d2 & CELL_PAD_CTRL_R2), data.button[CELL_PAD_BTN_OFFSET_PRESS_R2],
- !!(pad.m_digital_1 & CELL_PAD_CTRL_R3), !!(d1 & CELL_PAD_CTRL_R3),
- pad.m_analog_left_x, data.button[CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X],
- pad.m_analog_left_y, data.button[CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y],
- pad.m_analog_right_x, data.button[CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X],
- pad.m_analog_right_y, data.button[CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y],
- pad.m_sensor_x, data.button[CELL_PAD_BTN_OFFSET_SENSOR_X],
- pad.m_sensor_y, data.button[CELL_PAD_BTN_OFFSET_SENSOR_Y],
- pad.m_sensor_z, data.button[CELL_PAD_BTN_OFFSET_SENSOR_Z],
- pad.m_sensor_g, data.button[CELL_PAD_BTN_OFFSET_SENSOR_G],
+ pad.m_vibrate_motors[0].value, pad.m_vibrate_motors[0].adjusted_value,
+ pad.m_vibrate_motors[1].value, pad.m_vibrate_motors[1].adjusted_value,
+ raw_d1, d1,
+ raw_d2, d2,
+ raw.button[CELL_PAD_BTN_OFFSET_PRESS_UP], !!(d1 & CELL_PAD_CTRL_UP), data.button[CELL_PAD_BTN_OFFSET_PRESS_UP],
+ raw.button[CELL_PAD_BTN_OFFSET_PRESS_DOWN], !!(d1 & CELL_PAD_CTRL_DOWN), data.button[CELL_PAD_BTN_OFFSET_PRESS_DOWN],
+ raw.button[CELL_PAD_BTN_OFFSET_PRESS_LEFT], !!(d1 & CELL_PAD_CTRL_LEFT), data.button[CELL_PAD_BTN_OFFSET_PRESS_LEFT],
+ raw.button[CELL_PAD_BTN_OFFSET_PRESS_RIGHT], !!(d1 & CELL_PAD_CTRL_RIGHT), data.button[CELL_PAD_BTN_OFFSET_PRESS_RIGHT],
+ raw.button[CELL_PAD_BTN_OFFSET_PRESS_CROSS], !!(d2 & CELL_PAD_CTRL_CROSS), data.button[CELL_PAD_BTN_OFFSET_PRESS_CROSS],
+ raw.button[CELL_PAD_BTN_OFFSET_PRESS_SQUARE], !!(d2 & CELL_PAD_CTRL_SQUARE), data.button[CELL_PAD_BTN_OFFSET_PRESS_SQUARE],
+ raw.button[CELL_PAD_BTN_OFFSET_PRESS_CIRCLE], !!(d2 & CELL_PAD_CTRL_CIRCLE), data.button[CELL_PAD_BTN_OFFSET_PRESS_CIRCLE],
+ raw.button[CELL_PAD_BTN_OFFSET_PRESS_TRIANGLE], !!(d2 & CELL_PAD_CTRL_TRIANGLE), data.button[CELL_PAD_BTN_OFFSET_PRESS_TRIANGLE],
+ !!(raw_d1 & CELL_PAD_CTRL_START), !!(d1 & CELL_PAD_CTRL_START),
+ !!(raw_d1 & CELL_PAD_CTRL_SELECT), !!(d1 & CELL_PAD_CTRL_SELECT),
+ !!(raw_d1 & CELL_PAD_CTRL_PS), !!(d1 & CELL_PAD_CTRL_PS),
+ raw.button[CELL_PAD_BTN_OFFSET_PRESS_L1], !!(d2 & CELL_PAD_CTRL_L1), data.button[CELL_PAD_BTN_OFFSET_PRESS_L1],
+ raw.button[CELL_PAD_BTN_OFFSET_PRESS_L2], !!(d2 & CELL_PAD_CTRL_L2), data.button[CELL_PAD_BTN_OFFSET_PRESS_L2],
+ !!(raw_d1 & CELL_PAD_CTRL_L3), !!(d1 & CELL_PAD_CTRL_L3),
+ raw.button[CELL_PAD_BTN_OFFSET_PRESS_R1], !!(d2 & CELL_PAD_CTRL_R1), data.button[CELL_PAD_BTN_OFFSET_PRESS_R1],
+ raw.button[CELL_PAD_BTN_OFFSET_PRESS_R2], !!(d2 & CELL_PAD_CTRL_R2), data.button[CELL_PAD_BTN_OFFSET_PRESS_R2],
+ !!(raw_d1 & CELL_PAD_CTRL_R3), !!(d1 & CELL_PAD_CTRL_R3),
+ raw.button[CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X], data.button[CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X],
+ raw.button[CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y], data.button[CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y],
+ raw.button[CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X], data.button[CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X],
+ raw.button[CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y], data.button[CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y],
+ raw.button[CELL_PAD_BTN_OFFSET_SENSOR_X], data.button[CELL_PAD_BTN_OFFSET_SENSOR_X],
+ raw.button[CELL_PAD_BTN_OFFSET_SENSOR_Y], data.button[CELL_PAD_BTN_OFFSET_SENSOR_Y],
+ raw.button[CELL_PAD_BTN_OFFSET_SENSOR_Z], data.button[CELL_PAD_BTN_OFFSET_SENSOR_Z],
+ raw.button[CELL_PAD_BTN_OFFSET_SENSOR_G], data.button[CELL_PAD_BTN_OFFSET_SENSOR_G],
pad.m_product_id,
pad.m_vendor_id,
pad.m_device_type,
@@ -305,17 +312,15 @@ void clear_pad_buffer(const std::shared_ptr& pad)
// might as well also reset everything in our pad 'buffer' to nothing as well
pad->m_buffer_cleared = true;
- pad->m_analog_left_x = pad->m_analog_left_y = pad->m_analog_right_x = pad->m_analog_right_y = 128;
-
- pad->m_digital_1 = pad->m_digital_2 = 0;
- pad->m_press_right = pad->m_press_left = pad->m_press_up = pad->m_press_down = 0;
- pad->m_press_triangle = pad->m_press_circle = pad->m_press_cross = pad->m_press_square = 0;
- pad->m_press_L1 = pad->m_press_L2 = pad->m_press_R1 = pad->m_press_R2 = 0;
-
- pad->m_sensor_x = DEFAULT_MOTION_X;
- pad->m_sensor_y = DEFAULT_MOTION_Y;
- pad->m_sensor_z = DEFAULT_MOTION_Z;
- pad->m_sensor_g = DEFAULT_MOTION_G;
+ pad->data = {};
+ pad->data.button[CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X] = 128;
+ pad->data.button[CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y] = 128;
+ pad->data.button[CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X] = 128;
+ pad->data.button[CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y] = 128;
+ pad->data.button[CELL_PAD_BTN_OFFSET_SENSOR_X] = DEFAULT_MOTION_X;
+ pad->data.button[CELL_PAD_BTN_OFFSET_SENSOR_Y] = DEFAULT_MOTION_Y;
+ pad->data.button[CELL_PAD_BTN_OFFSET_SENSOR_Z] = DEFAULT_MOTION_Z;
+ pad->data.button[CELL_PAD_BTN_OFFSET_SENSOR_G] = DEFAULT_MOTION_G;
}
error_code cellPadClearBuf(u32 port_no)
@@ -363,6 +368,8 @@ void pad_get_data(u32 port_no, CellPadData* data, bool get_periph_data = false)
const u32 setting = config.port_setting[port_no];
bool btnChanged = false;
+ CellPadData& output = pad->data;
+
if (rinfo.ignore_input || !is_input_allowed())
{
// Needed for Hotline Miami and Ninja Gaiden Sigma after dialogs were closed and buttons are still pressed.
@@ -380,14 +387,14 @@ void pad_get_data(u32 port_no, CellPadData* data, bool get_periph_data = false)
}
else
{
- const u16 d1Initial = pad->m_digital_1;
- const u16 d2Initial = pad->m_digital_2;
+ const u16 d1_initial = output.button[CELL_PAD_BTN_OFFSET_DIGITAL1];
+ const u16 d2_initial = output.button[CELL_PAD_BTN_OFFSET_DIGITAL2];
// Check if this pad is configured as a skateboard which ignores sticks and pressure button values.
// Curiously it maps infrared on the press value of the face buttons for some reason.
const bool use_piggyback = pad->m_class_type == CELL_PAD_PCLASS_TYPE_SKATEBOARD;
- const auto set_value = [&btnChanged, use_piggyback, &pad](u16& value, u16 new_value, bool force_processing = false, u16 old_max_value = 255, u16 new_max_value = 255)
+ const auto set_value = [&btnChanged, use_piggyback, &pad](auto& value, u16 new_value, bool force_processing = false, u16 old_max_value = 255, u16 new_max_value = 255)
{
if (use_piggyback)
{
@@ -421,16 +428,16 @@ void pad_get_data(u32 port_no, CellPadData* data, bool get_periph_data = false)
case CELL_PAD_BTN_OFFSET_DIGITAL1:
{
if (button.m_pressed)
- pad->m_digital_1 |= button.m_outKeyCode;
+ output.button[CELL_PAD_BTN_OFFSET_DIGITAL1] |= button.m_outKeyCode;
else
- pad->m_digital_1 &= ~button.m_outKeyCode;
+ output.button[CELL_PAD_BTN_OFFSET_DIGITAL1] &= ~button.m_outKeyCode;
switch (button.m_outKeyCode)
{
- case CELL_PAD_CTRL_LEFT: set_value(pad->m_press_left, button.m_value); break;
- case CELL_PAD_CTRL_DOWN: set_value(pad->m_press_down, button.m_value); break;
- case CELL_PAD_CTRL_RIGHT: set_value(pad->m_press_right, button.m_value); break;
- case CELL_PAD_CTRL_UP: set_value(pad->m_press_up, button.m_value); break;
+ case CELL_PAD_CTRL_LEFT: set_value(output.button[CELL_PAD_BTN_OFFSET_PRESS_LEFT], button.m_value); break;
+ case CELL_PAD_CTRL_DOWN: set_value(output.button[CELL_PAD_BTN_OFFSET_PRESS_DOWN], button.m_value); break;
+ case CELL_PAD_CTRL_RIGHT: set_value(output.button[CELL_PAD_BTN_OFFSET_PRESS_RIGHT], button.m_value); break;
+ case CELL_PAD_CTRL_UP: set_value(output.button[CELL_PAD_BTN_OFFSET_PRESS_UP], button.m_value); break;
// These aren't pressure btns
case CELL_PAD_CTRL_R3:
case CELL_PAD_CTRL_L3:
@@ -443,20 +450,20 @@ void pad_get_data(u32 port_no, CellPadData* data, bool get_periph_data = false)
case CELL_PAD_BTN_OFFSET_DIGITAL2:
{
if (button.m_pressed)
- pad->m_digital_2 |= button.m_outKeyCode;
+ output.button[CELL_PAD_BTN_OFFSET_DIGITAL2] |= button.m_outKeyCode;
else
- pad->m_digital_2 &= ~button.m_outKeyCode;
+ output.button[CELL_PAD_BTN_OFFSET_DIGITAL2] &= ~button.m_outKeyCode;
switch (button.m_outKeyCode)
{
- case CELL_PAD_CTRL_SQUARE: set_value(pad->m_press_square, button.m_value); break;
- case CELL_PAD_CTRL_CROSS: set_value(pad->m_press_cross, button.m_value); break;
- case CELL_PAD_CTRL_CIRCLE: set_value(pad->m_press_circle, button.m_value); break;
- case CELL_PAD_CTRL_TRIANGLE: set_value(pad->m_press_triangle, button.m_value); break;
- case CELL_PAD_CTRL_R1: set_value(pad->m_press_R1, button.m_value); break;
- case CELL_PAD_CTRL_L1: set_value(pad->m_press_L1, button.m_value); break;
- case CELL_PAD_CTRL_R2: set_value(pad->m_press_R2, button.m_value); break;
- case CELL_PAD_CTRL_L2: set_value(pad->m_press_L2, button.m_value); break;
+ case CELL_PAD_CTRL_SQUARE: set_value(output.button[CELL_PAD_BTN_OFFSET_PRESS_SQUARE], button.m_value); break;
+ case CELL_PAD_CTRL_CROSS: set_value(output.button[CELL_PAD_BTN_OFFSET_PRESS_CROSS], button.m_value); break;
+ case CELL_PAD_CTRL_CIRCLE: set_value(output.button[CELL_PAD_BTN_OFFSET_PRESS_CIRCLE], button.m_value); break;
+ case CELL_PAD_CTRL_TRIANGLE: set_value(output.button[CELL_PAD_BTN_OFFSET_PRESS_TRIANGLE], button.m_value); break;
+ case CELL_PAD_CTRL_R1: set_value(output.button[CELL_PAD_BTN_OFFSET_PRESS_R1], button.m_value); break;
+ case CELL_PAD_CTRL_L1: set_value(output.button[CELL_PAD_BTN_OFFSET_PRESS_L1], button.m_value); break;
+ case CELL_PAD_CTRL_R2: set_value(output.button[CELL_PAD_BTN_OFFSET_PRESS_R2], button.m_value); break;
+ case CELL_PAD_CTRL_L2: set_value(output.button[CELL_PAD_BTN_OFFSET_PRESS_L2], button.m_value); break;
default: break;
}
break;
@@ -465,18 +472,22 @@ void pad_get_data(u32 port_no, CellPadData* data, bool get_periph_data = false)
{
switch (button.m_outKeyCode)
{
- case CELL_PAD_CTRL_PRESS_RIGHT: set_value(pad->m_press_right, button.m_value, true); break;
- case CELL_PAD_CTRL_PRESS_LEFT: set_value(pad->m_press_left, button.m_value, true); break;
- case CELL_PAD_CTRL_PRESS_UP: set_value(pad->m_press_up, button.m_value, true); break;
- case CELL_PAD_CTRL_PRESS_DOWN: set_value(pad->m_press_down, button.m_value, true); break;
- case CELL_PAD_CTRL_PRESS_TRIANGLE: set_value(pad->m_press_triangle, button.m_value, true, 255, 63); break; // Infrared on RIDE Skateboard
- case CELL_PAD_CTRL_PRESS_CIRCLE: set_value(pad->m_press_circle, button.m_value, true, 255, 63); break; // Infrared on RIDE Skateboard
- case CELL_PAD_CTRL_PRESS_CROSS: set_value(pad->m_press_cross, button.m_value, true, 255, 63); break; // Infrared on RIDE Skateboard
- case CELL_PAD_CTRL_PRESS_SQUARE: set_value(pad->m_press_square, button.m_value, true, 255, 63); break; // Infrared on RIDE Skateboard
- case CELL_PAD_CTRL_PRESS_L1: set_value(pad->m_press_L1, button.m_value, true); break;
- case CELL_PAD_CTRL_PRESS_R1: set_value(pad->m_press_R1, button.m_value, true); break;
- case CELL_PAD_CTRL_PRESS_L2: set_value(pad->m_press_L2, button.m_value, true); break;
- case CELL_PAD_CTRL_PRESS_R2: set_value(pad->m_press_R2, button.m_value, true); break;
+ case CELL_PAD_CTRL_PRESS_RIGHT:
+ case CELL_PAD_CTRL_PRESS_LEFT:
+ case CELL_PAD_CTRL_PRESS_UP:
+ case CELL_PAD_CTRL_PRESS_DOWN:
+ case CELL_PAD_CTRL_PRESS_L1:
+ case CELL_PAD_CTRL_PRESS_R1:
+ case CELL_PAD_CTRL_PRESS_L2:
+ case CELL_PAD_CTRL_PRESS_R2:
+ set_value(output.button[button.m_outKeyCode], button.m_value, true);
+ break;
+ case CELL_PAD_CTRL_PRESS_TRIANGLE:
+ case CELL_PAD_CTRL_PRESS_CIRCLE:
+ case CELL_PAD_CTRL_PRESS_CROSS:
+ case CELL_PAD_CTRL_PRESS_SQUARE:
+ set_value(output.button[button.m_outKeyCode], button.m_value, true, 255, 63); // Infrared on RIDE Skateboard
+ break;
default: break;
}
break;
@@ -490,11 +501,14 @@ void pad_get_data(u32 port_no, CellPadData* data, bool get_periph_data = false)
{
switch (stick.m_offset)
{
- case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X: set_value(pad->m_analog_left_x, stick.m_value); break;
- case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y: set_value(pad->m_analog_left_y, stick.m_value); break;
- case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X: set_value(pad->m_analog_right_x, stick.m_value); break;
- case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y: set_value(pad->m_analog_right_y, stick.m_value); break;
- default: break;
+ case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X:
+ case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y:
+ case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X:
+ case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y:
+ set_value(output.button[stick.m_offset], stick.m_value);
+ break;
+ default:
+ break;
}
}
@@ -504,16 +518,19 @@ void pad_get_data(u32 port_no, CellPadData* data, bool get_periph_data = false)
{
switch (sensor.m_offset)
{
- case CELL_PAD_BTN_OFFSET_SENSOR_X: set_value(pad->m_sensor_x, sensor.m_value, true); break;
- case CELL_PAD_BTN_OFFSET_SENSOR_Y: set_value(pad->m_sensor_y, sensor.m_value, true); break;
- case CELL_PAD_BTN_OFFSET_SENSOR_Z: set_value(pad->m_sensor_z, sensor.m_value, true); break;
- case CELL_PAD_BTN_OFFSET_SENSOR_G: set_value(pad->m_sensor_g, sensor.m_value, true); break;
- default: break;
+ case CELL_PAD_BTN_OFFSET_SENSOR_X:
+ case CELL_PAD_BTN_OFFSET_SENSOR_Y:
+ case CELL_PAD_BTN_OFFSET_SENSOR_Z:
+ case CELL_PAD_BTN_OFFSET_SENSOR_G:
+ set_value(output.button[sensor.m_offset], sensor.m_value, true);
+ break;
+ default:
+ break;
}
}
}
- if (d1Initial != pad->m_digital_1 || d2Initial != pad->m_digital_2)
+ if (d1_initial != output.button[CELL_PAD_BTN_OFFSET_DIGITAL1] || d2_initial != output.button[CELL_PAD_BTN_OFFSET_DIGITAL2])
{
btnChanged = true;
}
@@ -556,41 +573,25 @@ void pad_get_data(u32 port_no, CellPadData* data, bool get_periph_data = false)
// bits 15-8 reserved, 7-4 = 0x7, 3-0: data->len/2;
data->button[1] = (0x7 << 4) | std::min(data->len / 2, 15);
- data->button[CELL_PAD_BTN_OFFSET_DIGITAL1] = pad->m_digital_1;
- data->button[CELL_PAD_BTN_OFFSET_DIGITAL2] = pad->m_digital_2;
- data->button[CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X] = pad->m_analog_right_x;
- data->button[CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y] = pad->m_analog_right_y;
- data->button[CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X] = pad->m_analog_left_x;
- data->button[CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y] = pad->m_analog_left_y;
-
if (setting & CELL_PAD_SETTING_PRESS_ON)
{
- data->button[CELL_PAD_BTN_OFFSET_PRESS_RIGHT] = pad->m_press_right;
- data->button[CELL_PAD_BTN_OFFSET_PRESS_LEFT] = pad->m_press_left;
- data->button[CELL_PAD_BTN_OFFSET_PRESS_UP] = pad->m_press_up;
- data->button[CELL_PAD_BTN_OFFSET_PRESS_DOWN] = pad->m_press_down;
- data->button[CELL_PAD_BTN_OFFSET_PRESS_TRIANGLE] = pad->m_press_triangle;
- data->button[CELL_PAD_BTN_OFFSET_PRESS_CIRCLE] = pad->m_press_circle;
- data->button[CELL_PAD_BTN_OFFSET_PRESS_CROSS] = pad->m_press_cross;
- data->button[CELL_PAD_BTN_OFFSET_PRESS_SQUARE] = pad->m_press_square;
- data->button[CELL_PAD_BTN_OFFSET_PRESS_L1] = pad->m_press_L1;
- data->button[CELL_PAD_BTN_OFFSET_PRESS_R1] = pad->m_press_R1;
- data->button[CELL_PAD_BTN_OFFSET_PRESS_L2] = pad->m_press_L2;
- data->button[CELL_PAD_BTN_OFFSET_PRESS_R2] = pad->m_press_R2;
+ constexpr u32 copy_size = (static_cast(CELL_PAD_LEN_CHANGE_PRESS_ON) - static_cast(CELL_PAD_BTN_OFFSET_DIGITAL1)) * sizeof(u16);
+ std::memcpy(&data->button[CELL_PAD_BTN_OFFSET_DIGITAL1], &output.button[CELL_PAD_BTN_OFFSET_DIGITAL1], copy_size);
}
else
{
+ constexpr u32 copy_size = (static_cast(CELL_PAD_LEN_CHANGE_DEFAULT) - static_cast(CELL_PAD_BTN_OFFSET_DIGITAL1)) * sizeof(u16);
+ std::memcpy(&data->button[CELL_PAD_BTN_OFFSET_DIGITAL1], &output.button[CELL_PAD_BTN_OFFSET_DIGITAL1], copy_size);
+
// Clear area if setting is not used
- constexpr u32 area_lengh = (CELL_PAD_LEN_CHANGE_PRESS_ON - CELL_PAD_LEN_CHANGE_DEFAULT) * sizeof(u16);
- std::memset(&data->button[CELL_PAD_LEN_CHANGE_DEFAULT], 0, area_lengh);
+ constexpr u32 area_size = (CELL_PAD_LEN_CHANGE_PRESS_ON - CELL_PAD_LEN_CHANGE_DEFAULT) * sizeof(u16);
+ std::memset(&data->button[CELL_PAD_LEN_CHANGE_DEFAULT], 0, area_size);
}
if (data->len == CELL_PAD_LEN_CHANGE_SENSOR_ON)
{
- data->button[CELL_PAD_BTN_OFFSET_SENSOR_X] = pad->m_sensor_x;
- data->button[CELL_PAD_BTN_OFFSET_SENSOR_Y] = pad->m_sensor_y;
- data->button[CELL_PAD_BTN_OFFSET_SENSOR_Z] = pad->m_sensor_z;
- data->button[CELL_PAD_BTN_OFFSET_SENSOR_G] = pad->m_sensor_g;
+ constexpr u32 copy_size = (static_cast(CELL_PAD_LEN_CHANGE_SENSOR_ON) - static_cast(CELL_PAD_BTN_OFFSET_SENSOR_X)) * sizeof(u16);
+ std::memcpy(&data->button[CELL_PAD_BTN_OFFSET_SENSOR_X], &output.button[CELL_PAD_BTN_OFFSET_SENSOR_X], copy_size);
}
}
@@ -717,7 +718,7 @@ error_code cellPadGetData(u32 port_no, vm::ptr data)
pad_get_data(port_no, data.get_ptr());
- if (g_cfg.io.debug_overlay && !g_cfg.video.debug_overlay && port_no == 0)
+ if (g_cfg.io.pad_debug_overlay && !g_cfg.video.debug_overlay && port_no == 0)
{
show_debug_overlay(*data, *pad, config);
}
@@ -834,6 +835,7 @@ error_code cellPadGetRawData(u32 port_no, vm::ptr data)
return not_an_error(CELL_PAD_ERROR_NO_DEVICE);
// ?
+ // std::memcpy(data.get_ptr(), &pad->data, sizeof(CellPadData));
return CELL_OK;
}
@@ -901,7 +903,7 @@ error_code cellPadSetActDirect(u32 port_no, vm::ptr param)
if (!(pad->m_device_capability & CELL_PAD_CAPABILITY_ACTUATOR))
return CELL_PAD_ERROR_UNSUPPORTED_GAMEPAD;
- handler->SetRumble(port_no, param->motor[1], param->motor[0] > 0);
+ handler->SetRumble(port_no, param->motor[1], param->motor[0]);
return CELL_OK;
}
diff --git a/rpcs3/Emu/Cell/Modules/cellSysutil.cpp b/rpcs3/Emu/Cell/Modules/cellSysutil.cpp
index a7d15af2d5..13e4b0dd83 100644
--- a/rpcs3/Emu/Cell/Modules/cellSysutil.cpp
+++ b/rpcs3/Emu/Cell/Modules/cellSysutil.cpp
@@ -426,11 +426,11 @@ error_code cellSysutilGetSystemParamInt(CellSysutilParamId id, vm::ptr valu
break;
case CELL_SYSUTIL_SYSTEMPARAM_ID_DATE_FORMAT:
- *value = CELL_SYSUTIL_DATE_FMT_DDMMYYYY;
+ *value = static_cast(g_cfg.sys.date_fmt.get());
break;
case CELL_SYSUTIL_SYSTEMPARAM_ID_TIME_FORMAT:
- *value = CELL_SYSUTIL_TIME_FMT_CLOCK24;
+ *value = static_cast(g_cfg.sys.time_fmt.get());
break;
case CELL_SYSUTIL_SYSTEMPARAM_ID_TIMEZONE:
diff --git a/rpcs3/Emu/Cell/Modules/cellVideoOut.cpp b/rpcs3/Emu/Cell/Modules/cellVideoOut.cpp
index e0db365933..a51ffbf756 100644
--- a/rpcs3/Emu/Cell/Modules/cellVideoOut.cpp
+++ b/rpcs3/Emu/Cell/Modules/cellVideoOut.cpp
@@ -202,7 +202,7 @@ error_code cellVideoOutConfigure(u32 videoOut, vm::ptrresolutionId, &res) != CELL_OK ||
- (config->resolutionId >= CELL_VIDEO_OUT_RESOLUTION_720_3D_FRAME_PACKING && g_cfg.video.stereo_render_mode == stereo_render_mode_options::disabled))
+ (config->resolutionId >= CELL_VIDEO_OUT_RESOLUTION_720_3D_FRAME_PACKING && !g_cfg.video.stereo_enabled))
{
// Resolution not supported
cellSysutil.error("Unusual resolution requested: 0x%x", config->resolutionId);
@@ -211,7 +211,7 @@ error_code cellVideoOutConfigure(u32 videoOut, vm::ptrget();
conf.resolution_id = config->resolutionId;
- conf.stereo_mode = (config->resolutionId >= CELL_VIDEO_OUT_RESOLUTION_720_3D_FRAME_PACKING) ? g_cfg.video.stereo_render_mode.get() : stereo_render_mode_options::disabled;
+ conf.stereo_enabled = (config->resolutionId >= CELL_VIDEO_OUT_RESOLUTION_720_3D_FRAME_PACKING) && g_cfg.video.stereo_enabled;
conf.aspect = config->aspect;
conf.format = config->format;
conf.scanline_pitch = config->pitch;
@@ -393,7 +393,7 @@ error_code cellVideoOutGetDeviceInfo(u32 videoOut, u32 deviceIndex, vm::ptr| myLanguages)
return SCE_NP_ERROR_INVALID_STATE;
}
- myLanguages->language1 = SCE_NP_LANG_ENGLISH_US;
- myLanguages->language2 = g_cfg.sys.language != CELL_SYSUTIL_LANG_ENGLISH_US ? g_cfg.sys.language : -1;
+ myLanguages->language1 = g_cfg.sys.language;
+ myLanguages->language2 = g_cfg.sys.language != CELL_SYSUTIL_LANG_ENGLISH_US ? CELL_SYSUTIL_LANG_ENGLISH_US : -1;
myLanguages->language3 = -1;
return CELL_OK;
@@ -3968,7 +3968,7 @@ error_code sceNpManagerGetAccountRegion(vm::ptr countryCode, v
ensure(ccode.size() == sizeof(SceNpCountryCode::data));
std::memcpy(countryCode->data, ccode.data(), sizeof(SceNpCountryCode::data));
- *language = CELL_SYSUTIL_LANG_ENGLISH_US;
+ *language = g_cfg.sys.language;
return CELL_OK;
}
diff --git a/rpcs3/Emu/Cell/PPUAnalyser.h b/rpcs3/Emu/Cell/PPUAnalyser.h
index 693ad8c7ea..8d6486c9a4 100644
--- a/rpcs3/Emu/Cell/PPUAnalyser.h
+++ b/rpcs3/Emu/Cell/PPUAnalyser.h
@@ -145,6 +145,7 @@ struct ppu_module : public Type
std::shared_ptr> jit_bounds; // JIT instance modules addresses range
std::unordered_map imports; // Imports information for release upon unload (TODO: OVL implementation!)
std::map>> stub_addr_to_constant_state_of_registers; // Tells possible constant states of registers of functions
+ std::vector excluded_funcs; // Function code not be overwritten
bool is_relocatable = false; // Is code relocatable(?)
template
diff --git a/rpcs3/Emu/Cell/PPUInterpreter.cpp b/rpcs3/Emu/Cell/PPUInterpreter.cpp
index 69d11864d1..cc39eadadd 100644
--- a/rpcs3/Emu/Cell/PPUInterpreter.cpp
+++ b/rpcs3/Emu/Cell/PPUInterpreter.cpp
@@ -7659,8 +7659,8 @@ ppu_interpreter_rt_base::ppu_interpreter_rt_base() noexcept
INIT(LBZUX);
INIT_RC(NOR);
INIT(STVEBX);
- INIT_OV(SUBFE);
- INIT_OV(ADDE);
+ INIT_RC_OV(SUBFE);
+ INIT_RC_OV(ADDE);
INIT(MTOCRF);
INIT(STDX);
INIT(STWCX);
diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp
index 312cfad783..64a989a9bf 100644
--- a/rpcs3/Emu/Cell/PPUThread.cpp
+++ b/rpcs3/Emu/Cell/PPUThread.cpp
@@ -195,17 +195,17 @@ const auto ppu_gateway = build_function_asm("ppu_gateway",
c.push(x86::rdi);
c.push(x86::rbp);
c.push(x86::rbx);
- c.sub(x86::rsp, 0xa8);
- c.movaps(x86::oword_ptr(x86::rsp, 0x90), x86::xmm15);
- c.movaps(x86::oword_ptr(x86::rsp, 0x80), x86::xmm14);
- c.movaps(x86::oword_ptr(x86::rsp, 0x70), x86::xmm13);
- c.movaps(x86::oword_ptr(x86::rsp, 0x60), x86::xmm12);
- c.movaps(x86::oword_ptr(x86::rsp, 0x50), x86::xmm11);
- c.movaps(x86::oword_ptr(x86::rsp, 0x40), x86::xmm10);
- c.movaps(x86::oword_ptr(x86::rsp, 0x30), x86::xmm9);
- c.movaps(x86::oword_ptr(x86::rsp, 0x20), x86::xmm8);
- c.movaps(x86::oword_ptr(x86::rsp, 0x10), x86::xmm7);
- c.movaps(x86::oword_ptr(x86::rsp, 0), x86::xmm6);
+ c.sub(x86::rsp, 0xc8);
+ c.movaps(x86::oword_ptr(x86::rsp, 0xb0), x86::xmm15);
+ c.movaps(x86::oword_ptr(x86::rsp, 0xa0), x86::xmm14);
+ c.movaps(x86::oword_ptr(x86::rsp, 0x90), x86::xmm13);
+ c.movaps(x86::oword_ptr(x86::rsp, 0x80), x86::xmm12);
+ c.movaps(x86::oword_ptr(x86::rsp, 0x70), x86::xmm11);
+ c.movaps(x86::oword_ptr(x86::rsp, 0x60), x86::xmm10);
+ c.movaps(x86::oword_ptr(x86::rsp, 0x50), x86::xmm9);
+ c.movaps(x86::oword_ptr(x86::rsp, 0x40), x86::xmm8);
+ c.movaps(x86::oword_ptr(x86::rsp, 0x30), x86::xmm7);
+ c.movaps(x86::oword_ptr(x86::rsp, 0x20), x86::xmm6);
#else
c.push(x86::rbp);
c.push(x86::r15);
@@ -252,17 +252,17 @@ const auto ppu_gateway = build_function_asm("ppu_gateway",
}
#ifdef _WIN32
- c.movaps(x86::xmm6, x86::oword_ptr(x86::rsp, 0));
- c.movaps(x86::xmm7, x86::oword_ptr(x86::rsp, 0x10));
- c.movaps(x86::xmm8, x86::oword_ptr(x86::rsp, 0x20));
- c.movaps(x86::xmm9, x86::oword_ptr(x86::rsp, 0x30));
- c.movaps(x86::xmm10, x86::oword_ptr(x86::rsp, 0x40));
- c.movaps(x86::xmm11, x86::oword_ptr(x86::rsp, 0x50));
- c.movaps(x86::xmm12, x86::oword_ptr(x86::rsp, 0x60));
- c.movaps(x86::xmm13, x86::oword_ptr(x86::rsp, 0x70));
- c.movaps(x86::xmm14, x86::oword_ptr(x86::rsp, 0x80));
- c.movaps(x86::xmm15, x86::oword_ptr(x86::rsp, 0x90));
- c.add(x86::rsp, 0xa8);
+ c.movaps(x86::xmm6, x86::oword_ptr(x86::rsp, 0x20));
+ c.movaps(x86::xmm7, x86::oword_ptr(x86::rsp, 0x30));
+ c.movaps(x86::xmm8, x86::oword_ptr(x86::rsp, 0x40));
+ c.movaps(x86::xmm9, x86::oword_ptr(x86::rsp, 0x50));
+ c.movaps(x86::xmm10, x86::oword_ptr(x86::rsp, 0x60));
+ c.movaps(x86::xmm11, x86::oword_ptr(x86::rsp, 0x70));
+ c.movaps(x86::xmm12, x86::oword_ptr(x86::rsp, 0x80));
+ c.movaps(x86::xmm13, x86::oword_ptr(x86::rsp, 0x90));
+ c.movaps(x86::xmm14, x86::oword_ptr(x86::rsp, 0xa0));
+ c.movaps(x86::xmm15, x86::oword_ptr(x86::rsp, 0xb0));
+ c.add(x86::rsp, 0xc8);
c.pop(x86::rbx);
c.pop(x86::rbp);
c.pop(x86::rdi);
@@ -934,13 +934,40 @@ struct ppu_far_jumps_t
ppu_far_jumps_t(int) noexcept {}
std::map vals;
+ std::pair vals_range{0, 0};
::jit_runtime rt;
mutable shared_mutex mutex;
+ void add_value(u32 addr, all_info_t info)
+ {
+ vals.insert_or_assign(addr, std::move(info));
+
+ if (vals.size() == 1)
+ {
+ vals_range.first = addr;
+ vals_range.second = addr;
+ }
+ else
+ {
+ vals_range.first = std::min(vals_range.first, addr);
+ vals_range.second = std::max(vals_range.second, addr);
+ }
+ }
+
// Get target address, 'ppu' is used in ppu_far_jump in order to modify registers
u32 get_target(u32 pc, ppu_thread* ppu = nullptr)
{
+ if (vals_range.first > pc)
+ {
+ return 0;
+ }
+
+ if (vals_range.second < pc)
+ {
+ return 0;
+ }
+
reader_lock lock(mutex);
if (auto it = vals.find(pc); it != vals.end())
@@ -949,7 +976,7 @@ struct ppu_far_jumps_t
return all_info.get_target(pc, ppu);
}
- return {};
+ return 0;
}
// Get function patches in range (entry -> target)
@@ -957,6 +984,16 @@ struct ppu_far_jumps_t
{
std::vector> targets;
+ if (vals_range.first >= pc + size)
+ {
+ return targets;
+ }
+
+ if (vals_range.second < pc)
+ {
+ return targets;
+ }
+
reader_lock lock(mutex);
auto it = vals.lower_bound(pc);
@@ -1005,22 +1042,21 @@ struct ppu_far_jumps_t
#ifdef ARCH_X64
c.mov(args[0], x86::rbp);
- c.mov(x86::dword_ptr(args[0], ::offset32(&ppu_thread::cia)), pc);
+ c.mov(args[2], vm::g_base_addr + pc);
c.jmp(ppu_far_jump);
#else
Label jmp_address = c.newLabel();
- Label imm_address = c.newLabel();
+ Label this_op_address = c.newLabel();
- c.ldr(args[1].w(), arm::ptr(imm_address));
- c.str(args[1].w(), arm::Mem(args[0], ::offset32(&ppu_thread::cia)));
+ c.ldr(args[2], arm::ptr(this_op_address));
c.ldr(args[1], arm::ptr(jmp_address));
c.br(args[1]);
c.align(AlignMode::kCode, 16);
c.bind(jmp_address);
c.embedUInt64(reinterpret_cast(ppu_far_jump));
- c.bind(imm_address);
- c.embedUInt32(pc);
+ c.bind(this_op_address);
+ c.embedUInt64(reinterpret_cast(vm::g_base_addr) + pc);
#endif
}, &rt);
}
@@ -1039,9 +1075,9 @@ u32 ppu_get_far_jump(u32 pc)
return g_fxo->get().get_target(pc);
}
-static void ppu_far_jump(ppu_thread& ppu, ppu_opcode_t, be_t*, ppu_intrp_func*)
+static void ppu_far_jump(ppu_thread& ppu, ppu_opcode_t, be_t* this_op, ppu_intrp_func*)
{
- const u32 cia = g_fxo->get().get_target(ppu.cia, &ppu);
+ const u32 cia = g_fxo->get().get_target(vm::get_addr(this_op), &ppu);
if (!vm::check_addr(cia, vm::page_executable))
{
@@ -1110,7 +1146,7 @@ bool ppu_form_branch_to_code(u32 entry, u32 target, bool link, bool with_toc, st
auto& jumps = g_fxo->get();
std::lock_guard lock(jumps.mutex);
- jumps.vals.insert_or_assign(entry, ppu_far_jumps_t::all_info_t{target, link, with_toc, std::move(module_name)});
+ jumps.add_value(entry, ppu_far_jumps_t::all_info_t{target, link, with_toc, std::move(module_name)});
ppu_register_function_at(entry, 4, g_cfg.core.ppu_decoder == ppu_decoder_type::_static ? &ppu_far_jump : ensure(g_fxo->get().gen_jump(entry)));
return true;
@@ -2326,10 +2362,11 @@ void ppu_thread::cpu_wait(bs_t old)
if (u32 addr = res_notify)
{
res_notify = 0;
+ res_notify_postpone_streak = 0;
- if (res_notify_time == vm::reservation_notifier_count_index(addr).second)
+ if (res_notify_time + 128 == (vm::reservation_acquire(addr) & -128))
{
- vm::reservation_notifier_notify(addr);
+ vm::reservation_notifier_notify(addr, res_notify_time);
}
}
@@ -3117,7 +3154,6 @@ static T ppu_load_acquire_reservation(ppu_thread& ppu, u32 addr)
{
// Reload "cached" reservation of previous succeeded conditional store
// This seems like a hardware feature according to cellSpursAddUrgentCommand function
- ppu.rtime -= 128;
}
else
{
@@ -3614,67 +3650,70 @@ static bool ppu_store_reservation(ppu_thread& ppu, u32 addr, u64 reg_value)
{
extern atomic_t liblv2_begin, liblv2_end;
+ u32 notify = ppu.res_notify;
+
// Avoid notifications from lwmutex or sys_spinlock
- if (new_data != old_data && (ppu.cia < liblv2_begin || ppu.cia >= liblv2_end))
+ const bool is_liblv2_or_null = (ppu.cia >= liblv2_begin && ppu.cia < liblv2_end);
+
+ if (!is_liblv2_or_null)
{
- u32 notify = ppu.res_notify;
+ // Try to postpone notification to when PPU is asleep or join notifications on the same address
+ // This also optimizes a mutex - won't notify after lock is aqcuired (prolonging the critical section duration), only notifies on unlock
+ const u32 count = vm::reservation_notifier_count(addr, rtime);
- if (notify)
+ switch (count)
{
- if (ppu.res_notify_time == vm::reservation_notifier_count_index(notify).second)
- {
- ppu.state += cpu_flag::wait;
- vm::reservation_notifier_notify(notify);
- }
- else
- {
- notify = 0;
- }
-
- ppu.res_notify = 0;
+ case 0:
+ {
+ // Nothing to do
+ break;
}
-
- if ((addr ^ notify) & -128)
+ case 1:
{
- // Try to postpone notification to when PPU is asleep or join notifications on the same address
- // This also optimizes a mutex - won't notify after lock is aqcuired (prolonging the critical section duration), only notifies on unlock
- const auto [count, index] = vm::reservation_notifier_count_index(addr);
-
- switch (count)
+ // Postpone notifications if there is no pending one OR if there is likely a complex operation on reservation going on
+ // Which consists of multiple used addresses
+ if (ppu.res_notify_postpone_streak <= 4)
{
- case 0:
- {
- // Nothing to do
- break;
- }
- case 1:
- {
- if (!notify)
+ if (!notify || ((notify & -128) == (addr & -128) && new_data != old_data))
{
ppu.res_notify = addr;
- ppu.res_notify_time = index;
+ ppu.res_notify_time = rtime;
+ ppu.res_notify_postpone_streak++;
+ notify = 0;
break;
}
-
- // Notify both
- [[fallthrough]];
}
- default:
+
+ // Notify both
+ [[fallthrough]];
+ }
+ default:
+ {
+ if (cpu_flag::wait - ppu.state)
{
- if (!notify)
- {
- ppu.state += cpu_flag::wait;
- }
+ ppu.state += cpu_flag::wait;
+ }
- vm::reservation_notifier_notify(addr);
- break;
- }
- }
+ vm::reservation_notifier_notify(addr, rtime);
+ break;
+ }
+ }
+ }
+
+ if (notify)
+ {
+ if (auto waiter = vm::reservation_notifier_notify(notify, ppu.res_notify_time, true))
+ {
+ ppu.state += cpu_flag::wait;
+ waiter->notify_all();
}
- static_cast(ppu.test_stopped());
+ ppu.res_notify = 0;
+ ppu.res_notify_postpone_streak = 0;
}
+ static_cast(ppu.test_stopped());
+
if (addr == ppu.last_faddr)
{
ppu.last_succ++;
@@ -3682,7 +3721,6 @@ static bool ppu_store_reservation(ppu_thread& ppu, u32 addr, u64 reg_value)
ppu.last_faddr = 0;
ppu.res_cached = ppu.raddr;
- ppu.rtime += 128;
ppu.raddr = 0;
return true;
}
@@ -3693,14 +3731,15 @@ static bool ppu_store_reservation(ppu_thread& ppu, u32 addr, u64 reg_value)
// And on failure it has some time to do something else
if (notify && ((addr ^ notify) & -128))
{
- if (ppu.res_notify_time == vm::reservation_notifier_count_index(notify).second)
+ if (auto waiter = vm::reservation_notifier_notify(notify, ppu.res_notify_time, true))
{
ppu.state += cpu_flag::wait;
- vm::reservation_notifier_notify(notify);
+ waiter->notify_all();
static_cast(ppu.test_stopped());
}
ppu.res_notify = 0;
+ ppu.res_notify_postpone_streak = 0;
}
ppu.raddr = 0;
@@ -5211,6 +5250,7 @@ bool ppu_initialize(const ppu_module& info, bool check_only, u64 file_s
{
// Replace the function with ppu_far_jump
fpos++;
+ part.excluded_funcs.emplace_back(func.addr);
continue;
}
}
@@ -5243,6 +5283,11 @@ bool ppu_initialize(const ppu_module& info, bool check_only, u64 file_s
continue;
}
+ if (std::count(part.excluded_funcs.begin(), part.excluded_funcs.end(), func.addr))
+ {
+ continue;
+ }
+
const be_t addr = func.addr - reloc;
const be_t size = func.size;
sha1_update(&ctx, reinterpret_cast(&addr), sizeof(addr));
@@ -5340,6 +5385,13 @@ bool ppu_initialize(const ppu_module& info, bool check_only, u64 file_s
continue;
}
+ if (g_fxo->is_init() && !g_fxo->get().get_targets(func.addr, func.size).empty())
+ {
+ // Filter out functions with patches
+ part.excluded_funcs.emplace_back(func.addr);
+ continue;
+ }
+
addrs.emplace_back(func.addr - reloc);
}
@@ -5780,6 +5832,11 @@ static void ppu_initialize2(jit_compiler& jit, const ppu_module& module
{
if (func.size)
{
+ if (std::count(module_part.excluded_funcs.begin(), module_part.excluded_funcs.end(), func.addr))
+ {
+ continue;
+ }
+
const auto f = cast(_module->getOrInsertFunction(fmt::format("__0x%x", func.addr - reloc), _func).getCallee());
f->setCallingConv(CallingConv::GHC);
f->addParamAttr(1, llvm::Attribute::NoAlias);
@@ -5835,6 +5892,11 @@ static void ppu_initialize2(jit_compiler& jit, const ppu_module& module
if (mod_func.size)
{
+ if (std::count(module_part.excluded_funcs.begin(), module_part.excluded_funcs.end(), mod_func.addr))
+ {
+ continue;
+ }
+
num_func++;
guest_code_size += mod_func.size;
max_addr = std::max(max_addr, mod_func.addr + mod_func.size);
diff --git a/rpcs3/Emu/Cell/PPUThread.h b/rpcs3/Emu/Cell/PPUThread.h
index 322cc13ebe..97c705aed5 100644
--- a/rpcs3/Emu/Cell/PPUThread.h
+++ b/rpcs3/Emu/Cell/PPUThread.h
@@ -267,6 +267,7 @@ public:
u32 res_cached{0}; // Reservation "cached" addresss
u32 res_notify{0};
u64 res_notify_time{0};
+ u32 res_notify_postpone_streak{0};
union ppu_prio_t
{
diff --git a/rpcs3/Emu/Cell/PPUTranslator.cpp b/rpcs3/Emu/Cell/PPUTranslator.cpp
index 7380d8123f..0a17de2d0f 100644
--- a/rpcs3/Emu/Cell/PPUTranslator.cpp
+++ b/rpcs3/Emu/Cell/PPUTranslator.cpp
@@ -364,6 +364,12 @@ Function* PPUTranslator::GetSymbolResolver(const ppu_module& info)
continue;
}
+ if (std::count(info.excluded_funcs.begin(), info.excluded_funcs.end(), f.addr))
+ {
+ // Excluded function (possibly patched)
+ continue;
+ }
+
vec_addrs.push_back(static_cast(f.addr - base));
functions.push_back(cast(m_module->getOrInsertFunction(fmt::format("__0x%x", f.addr - base), ftype).getCallee()));
}
@@ -413,12 +419,11 @@ Function* PPUTranslator::GetSymbolResolver(const ppu_module& info)
const auto faddr_int = m_ir->CreatePtrToInt(faddr, get_type());
const auto pos_32 = m_reloc ? m_ir->CreateAdd(func_pc, m_seg0) : func_pc;
const auto pos = m_ir->CreateShl(pos_32, 1);
- const auto ptr = dyn_cast(m_ir->CreateGEP(get_type(), m_exec, pos));
+ const auto ptr = m_ir->CreatePtrAdd(m_exec, pos);
- const auto seg_base_ptr = m_ir->CreateIntToPtr(m_ir->CreateAdd(
- m_ir->CreatePtrToInt(m_exec, get_type()), m_ir->getInt64(vm::g_exec_addr_seg_offset)), m_exec->getType());
+ const auto seg_base_ptr = m_ir->CreatePtrAdd(m_exec, m_ir->getInt64(vm::g_exec_addr_seg_offset));
const auto seg_pos = m_ir->CreateLShr(pos_32, 1);
- const auto seg_ptr = dyn_cast(m_ir->CreateGEP(get_type(), seg_base_ptr, seg_pos));
+ const auto seg_ptr = m_ir->CreatePtrAdd(seg_base_ptr, seg_pos);
const auto seg_val = m_ir->CreateTrunc(m_ir->CreateLShr(m_seg0, 13), get_type());
// Store to jumptable
@@ -610,15 +615,14 @@ void PPUTranslator::CallFunction(u64 target, Value* indirect)
}
const auto pos = m_ir->CreateShl(indirect, 1);
- const auto ptr = dyn_cast(m_ir->CreateGEP(get_type(), m_exec, pos));
+ const auto ptr = m_ir->CreatePtrAdd(m_exec, pos);
const auto val = m_ir->CreateLoad(get_type(), ptr);
callee = FunctionCallee(type, m_ir->CreateIntToPtr(val, m_ir->getPtrTy()));
// Load new segment address
- const auto seg_base_ptr = m_ir->CreateIntToPtr(m_ir->CreateAdd(
- m_ir->CreatePtrToInt(m_exec, get_type()), m_ir->getInt64(vm::g_exec_addr_seg_offset)), m_exec->getType());
+ const auto seg_base_ptr = m_ir->CreatePtrAdd(m_exec, m_ir->getInt64(vm::g_exec_addr_seg_offset));
const auto seg_pos = m_ir->CreateLShr(indirect, 1);
- const auto seg_ptr = dyn_cast(m_ir->CreateGEP(get_type(), seg_base_ptr, seg_pos));
+ const auto seg_ptr = m_ir->CreatePtrAdd(seg_base_ptr, seg_pos);
const auto seg_val = m_ir->CreateZExt(m_ir->CreateLoad(get_type(), seg_ptr), get_type());
seg0 = m_ir->CreateShl(seg_val, 13);
}
@@ -824,7 +828,7 @@ void PPUTranslator::UseCondition(MDNode* hint, Value* cond)
llvm::Value* PPUTranslator::GetMemory(llvm::Value* addr)
{
- return m_ir->CreateGEP(get_type(), m_base, addr);
+ return m_ir->CreatePtrAdd(m_base, addr);
}
void PPUTranslator::TestAborted()
@@ -2794,8 +2798,8 @@ void PPUTranslator::MFOCRF(ppu_opcode_t op)
else if (std::none_of(m_cr + 0, m_cr + 32, [](auto* p) { return p; }))
{
// MFCR (optimized)
- Value* ln0 = m_ir->CreateIntToPtr(m_ir->CreatePtrToInt(m_ir->CreateStructGEP(m_thread_type, m_thread, 99), GetType()), m_ir->getPtrTy());
- Value* ln1 = m_ir->CreateIntToPtr(m_ir->CreatePtrToInt(m_ir->CreateStructGEP(m_thread_type, m_thread, 115), GetType()), m_ir->getPtrTy());
+ Value* ln0 = m_ir->CreateStructGEP(m_thread_type, m_thread, 99);
+ Value* ln1 = m_ir->CreateStructGEP(m_thread_type, m_thread, 115);
ln0 = m_ir->CreateLoad(GetType(), ln0);
ln1 = m_ir->CreateLoad(GetType(), ln1);
diff --git a/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp b/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp
index 41e81ac4e2..3531285042 100644
--- a/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp
+++ b/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp
@@ -305,17 +305,17 @@ DECLARE(spu_runtime::g_gateway) = build_function_asm("spu_gatewa
c.push(x86::rdi);
c.push(x86::rbp);
c.push(x86::rbx);
- c.sub(x86::rsp, 0xa8);
- c.movaps(x86::oword_ptr(x86::rsp, 0x90), x86::xmm15);
- c.movaps(x86::oword_ptr(x86::rsp, 0x80), x86::xmm14);
- c.movaps(x86::oword_ptr(x86::rsp, 0x70), x86::xmm13);
- c.movaps(x86::oword_ptr(x86::rsp, 0x60), x86::xmm12);
- c.movaps(x86::oword_ptr(x86::rsp, 0x50), x86::xmm11);
- c.movaps(x86::oword_ptr(x86::rsp, 0x40), x86::xmm10);
- c.movaps(x86::oword_ptr(x86::rsp, 0x30), x86::xmm9);
- c.movaps(x86::oword_ptr(x86::rsp, 0x20), x86::xmm8);
- c.movaps(x86::oword_ptr(x86::rsp, 0x10), x86::xmm7);
- c.movaps(x86::oword_ptr(x86::rsp, 0), x86::xmm6);
+ c.sub(x86::rsp, 0xc8);
+ c.movaps(x86::oword_ptr(x86::rsp, 0xb0), x86::xmm15);
+ c.movaps(x86::oword_ptr(x86::rsp, 0xa0), x86::xmm14);
+ c.movaps(x86::oword_ptr(x86::rsp, 0x90), x86::xmm13);
+ c.movaps(x86::oword_ptr(x86::rsp, 0x80), x86::xmm12);
+ c.movaps(x86::oword_ptr(x86::rsp, 0x70), x86::xmm11);
+ c.movaps(x86::oword_ptr(x86::rsp, 0x60), x86::xmm10);
+ c.movaps(x86::oword_ptr(x86::rsp, 0x50), x86::xmm9);
+ c.movaps(x86::oword_ptr(x86::rsp, 0x40), x86::xmm8);
+ c.movaps(x86::oword_ptr(x86::rsp, 0x30), x86::xmm7);
+ c.movaps(x86::oword_ptr(x86::rsp, 0x20), x86::xmm6);
#else
c.push(x86::rbp);
c.push(x86::r15);
@@ -348,17 +348,17 @@ DECLARE(spu_runtime::g_gateway) = build_function_asm("spu_gatewa
}
#ifdef _WIN32
- c.movaps(x86::xmm6, x86::oword_ptr(x86::rsp, 0));
- c.movaps(x86::xmm7, x86::oword_ptr(x86::rsp, 0x10));
- c.movaps(x86::xmm8, x86::oword_ptr(x86::rsp, 0x20));
- c.movaps(x86::xmm9, x86::oword_ptr(x86::rsp, 0x30));
- c.movaps(x86::xmm10, x86::oword_ptr(x86::rsp, 0x40));
- c.movaps(x86::xmm11, x86::oword_ptr(x86::rsp, 0x50));
- c.movaps(x86::xmm12, x86::oword_ptr(x86::rsp, 0x60));
- c.movaps(x86::xmm13, x86::oword_ptr(x86::rsp, 0x70));
- c.movaps(x86::xmm14, x86::oword_ptr(x86::rsp, 0x80));
- c.movaps(x86::xmm15, x86::oword_ptr(x86::rsp, 0x90));
- c.add(x86::rsp, 0xa8);
+ c.movaps(x86::xmm6, x86::oword_ptr(x86::rsp, 0x20));
+ c.movaps(x86::xmm7, x86::oword_ptr(x86::rsp, 0x30));
+ c.movaps(x86::xmm8, x86::oword_ptr(x86::rsp, 0x40));
+ c.movaps(x86::xmm9, x86::oword_ptr(x86::rsp, 0x50));
+ c.movaps(x86::xmm10, x86::oword_ptr(x86::rsp, 0x60));
+ c.movaps(x86::xmm11, x86::oword_ptr(x86::rsp, 0x70));
+ c.movaps(x86::xmm12, x86::oword_ptr(x86::rsp, 0x80));
+ c.movaps(x86::xmm13, x86::oword_ptr(x86::rsp, 0x90));
+ c.movaps(x86::xmm14, x86::oword_ptr(x86::rsp, 0xa0));
+ c.movaps(x86::xmm15, x86::oword_ptr(x86::rsp, 0xb0));
+ c.add(x86::rsp, 0xc8);
c.pop(x86::rbx);
c.pop(x86::rbp);
c.pop(x86::rdi);
diff --git a/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp b/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp
index 9bc50f7ea2..169d01a09d 100644
--- a/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp
+++ b/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp
@@ -329,9 +329,9 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
if (!m_finfo->fn && !m_block)
{
- lr = m_ir->CreateLoad(get_type(), spu_ptr(&spu_thread::gpr, +s_reg_lr, &v128::_u32, 3));
- sp = m_ir->CreateLoad(get_type(), spu_ptr(&spu_thread::gpr, +s_reg_sp));
- r3 = m_ir->CreateLoad(get_type(), spu_ptr(&spu_thread::gpr, 3));
+ lr = m_ir->CreateLoad(get_type(), spu_ptr(&spu_thread::gpr, +s_reg_lr, &v128::_u32, 3));
+ sp = m_ir->CreateLoad(get_type(), spu_ptr(&spu_thread::gpr, +s_reg_sp));
+ r3 = m_ir->CreateLoad(get_type(), spu_ptr(&spu_thread::gpr, 3));
}
else
{
@@ -348,8 +348,8 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
if (!m_finfo->fn)
{
lr = m_ir->CreateAnd(lr, 0x3fffc);
- m_ir->CreateStore(lr, spu_ptr(&spu_thread::pc));
- m_ir->CreateStore(_call, spu_ptr(&spu_thread::gpr, 3));
+ m_ir->CreateStore(lr, spu_ptr(&spu_thread::pc));
+ m_ir->CreateStore(_call, spu_ptr(&spu_thread::gpr, 3));
m_ir->CreateBr(add_block_indirect({}, value(lr)));
}
else if (tail)
@@ -392,7 +392,7 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
m_blocks.clear();
m_block_queue.clear();
m_ir->SetInsertPoint(llvm::BasicBlock::Create(m_context, "", m_function));
- m_memptr = m_ir->CreateLoad(get_type(), spu_ptr(&spu_thread::memory_base_addr));
+ m_memptr = m_ir->CreateLoad(get_type(), spu_ptr(&spu_thread::memory_base_addr));
}
// Add block with current block as a predecessor
@@ -415,7 +415,7 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
m_lsptr = fn->getArg(1);
m_base_pc = fn->getArg(2);
m_ir->SetInsertPoint(llvm::BasicBlock::Create(m_context, "", fn));
- m_memptr = m_ir->CreateLoad(get_type(), spu_ptr(&spu_thread::memory_base_addr));
+ m_memptr = m_ir->CreateLoad(get_type(), spu_ptr(&spu_thread::memory_base_addr));
// Load registers at the entry chunk
for (u32 i = 0; i < s_reg_max; i++)
@@ -452,7 +452,7 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
const auto fail = llvm::BasicBlock::Create(m_context, "", m_function);
m_ir->CreateCondBr(m_ir->CreateICmpEQ(m_base_pc, m_ir->getInt32(m_base)), next, fail);
m_ir->SetInsertPoint(fail);
- m_ir->CreateStore(m_ir->getInt32(target), spu_ptr(&spu_thread::pc));
+ m_ir->CreateStore(m_ir->getInt32(target), spu_ptr(&spu_thread::pc));
tail_chunk(nullptr);
m_ir->SetInsertPoint(next);
}
@@ -490,7 +490,7 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
{
ensure(!m_finfo->fn);
- m_ir->CreateStore(m_ir->getInt32(target), spu_ptr(&spu_thread::pc));
+ m_ir->CreateStore(m_ir->getInt32(target), spu_ptr(&spu_thread::pc));
}
else
{
@@ -527,29 +527,26 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
return result;
}
- template
llvm::Value* _ptr(llvm::Value* base, u32 offset)
{
- return m_ir->CreateGEP(get_type(), base, m_ir->getInt64(offset));
+ return m_ir->CreatePtrAdd(base, m_ir->getInt64(offset));
}
- template
llvm::Value* _ptr(llvm::Value* base, llvm::Value* offset)
{
- return m_ir->CreateGEP(get_type(), base, offset);
+ return m_ir->CreatePtrAdd(base, offset);
}
- template
+ template
+ llvm::Value* _ptr(llvm::Value* base, Args... offset_args)
+ {
+ return m_ir->CreatePtrAdd(base, m_ir->getInt64(::offset32(offset_args...)));
+ }
+
+ template
llvm::Value* spu_ptr(Args... offset_args)
{
- return _ptr(m_thread, ::offset32(offset_args...));
- }
-
- template
- llvm::Value* spu_ptr(value_t add, Args... offset_args)
- {
- const auto off = m_ir->CreateGEP(get_type(), m_thread, m_ir->getInt64(::offset32(offset_args...)));
- return m_ir->CreateAdd(off, add.value);
+ return _ptr(m_thread, ::offset32(offset_args...));
}
// Return default register type
@@ -596,7 +593,7 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
{
if (!m_block)
{
- return _ptr(m_thread, get_reg_offset(index));
+ return _ptr(m_thread, get_reg_offset(index));
}
auto& ptr = ::at32(m_reg_addr, index);
@@ -608,7 +605,7 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
// Emit register pointer at the beginning of the function chunk
m_ir->SetInsertPoint(m_function->getEntryBlock().getTerminator());
- ptr = _ptr(m_thread, get_reg_offset(index));
+ ptr = _ptr(m_thread, get_reg_offset(index));
m_ir->SetInsertPoint(block_cur);
}
@@ -616,7 +613,7 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
}
// Get pointer to the vector register (interpreter only)
- template
+ template
llvm::Value* init_vr(const bf_t&)
{
if (!m_interp_magn)
@@ -631,7 +628,7 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
const auto idx = m_ir->CreateAnd(I > 4 ? isr : isl, m_interp_7f0);
// Pointer to the register
- return m_ir->CreateGEP(get_type(), m_interp_regs, m_ir->CreateZExt(idx, get_type()));
+ return _ptr(m_interp_regs, m_ir->CreateZExt(idx, get_type()));
}
llvm::Value* double_as_uint64(llvm::Value* val)
@@ -758,11 +755,11 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
// Load reg
if (get_type() == get_type())
{
- r.value = xfloat_to_double(m_ir->CreateLoad(get_type(), init_vr(index)));
+ r.value = xfloat_to_double(m_ir->CreateLoad(get_type(), init_vr(index)));
}
else
{
- r.value = m_ir->CreateLoad(get_type(), init_vr(index));
+ r.value = m_ir->CreateLoad(get_type(), init_vr(index));
}
}
else
@@ -962,7 +959,7 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
const auto saved_value = is_xfloat && fixup ? xfloat_in_double(value) : value;
// Store value
- m_ir->CreateStore(is_xfloat ? double_to_xfloat(saved_value) : m_ir->CreateBitCast(value, get_type()), init_vr(index));
+ m_ir->CreateStore(is_xfloat ? double_to_xfloat(saved_value) : m_ir->CreateBitCast(value, get_type()), init_vr(index));
return;
}
@@ -1049,13 +1046,13 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
// Update PC for current or explicitly specified instruction address
void update_pc(u32 target = -1)
{
- m_ir->CreateStore(m_ir->CreateAnd(get_pc(target + 1 ? target : m_pos), 0x3fffc), spu_ptr(&spu_thread::pc))->setVolatile(true);
+ m_ir->CreateStore(m_ir->CreateAnd(get_pc(target + 1 ? target : m_pos), 0x3fffc), spu_ptr(&spu_thread::pc))->setVolatile(true);
}
// Call cpu_thread::check_state if necessary and return or continue (full check)
void check_state(u32 addr, bool may_be_unsafe_for_savestate = true)
{
- const auto pstate = spu_ptr(&spu_thread::state);
+ const auto pstate = spu_ptr(&spu_thread::state);
const auto _body = llvm::BasicBlock::Create(m_context, "", m_function);
const auto check = llvm::BasicBlock::Create(m_context, "", m_function);
m_ir->CreateCondBr(m_ir->CreateICmpEQ(m_ir->CreateLoad(get_type(), pstate, true), m_ir->getInt32(0)), _body, check, m_md_likely);
@@ -1069,14 +1066,14 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
if (may_be_unsafe_for_savestate)
{
- m_ir->CreateStore(m_ir->getInt8(1), spu_ptr(&spu_thread::unsavable))->setVolatile(true);
+ m_ir->CreateStore(m_ir->getInt8(1), spu_ptr(&spu_thread::unsavable))->setVolatile(true);
}
m_ir->CreateCall(m_test_state, {m_thread});
if (may_be_unsafe_for_savestate)
{
- m_ir->CreateStore(m_ir->getInt8(0), spu_ptr(&spu_thread::unsavable))->setVolatile(true);
+ m_ir->CreateStore(m_ir->getInt8(0), spu_ptr(&spu_thread::unsavable))->setVolatile(true);
}
m_ir->CreateBr(_body);
@@ -1145,7 +1142,7 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
const auto _final = llvm::BasicBlock::Create(m_context, "__putllc16_final", m_function);
const auto _eal = (get_reg_fixed(s_reg_mfc_eal) & -128).eval(m_ir);
- const auto _raddr = m_ir->CreateLoad(get_type(), spu_ptr(&spu_thread::raddr));
+ const auto _raddr = m_ir->CreateLoad(get_type(), spu_ptr(&spu_thread::raddr));
m_ir->CreateCondBr(m_ir->CreateAnd(m_ir->CreateICmpEQ(_eal, _raddr), m_ir->CreateIsNotNull(_raddr)), _raddr_match, _fail, m_md_likely);
m_ir->SetInsertPoint(_raddr_match);
@@ -1259,7 +1256,7 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
m_ir->SetInsertPoint(_fail);
call("PUTLLC16_fail", +on_fail, m_thread, _eal);
- m_ir->CreateStore(m_ir->getInt64(spu_channel::bit_count | MFC_PUTLLC_FAILURE), spu_ptr(&spu_thread::ch_atomic_stat));
+ m_ir->CreateStore(m_ir->getInt64(spu_channel::bit_count | MFC_PUTLLC_FAILURE), spu_ptr(&spu_thread::ch_atomic_stat));
m_ir->CreateBr(_final);
m_ir->SetInsertPoint(_final);
@@ -1268,8 +1265,8 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
const auto diff = m_ir->CreateZExt(m_ir->CreateSub(dest, _lsa), get_type());
- const auto _new = m_ir->CreateAlignedLoad(get_type(), _ptr(m_lsptr, dest), llvm::MaybeAlign{16});
- const auto _rdata = m_ir->CreateAlignedLoad(get_type(), _ptr(spu_ptr(&spu_thread::rdata), m_ir->CreateAnd(diff, 0x70)), llvm::MaybeAlign{16});
+ const auto _new = m_ir->CreateAlignedLoad(get_type(), _ptr(m_lsptr, dest), llvm::MaybeAlign{16});
+ const auto _rdata = m_ir->CreateAlignedLoad(get_type(), _ptr(spu_ptr(&spu_thread::rdata), m_ir->CreateAnd(diff, 0x70)), llvm::MaybeAlign{16});
const bool is_accurate_op = !!g_cfg.core.spu_accurate_reservations;
@@ -1287,10 +1284,10 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
m_ir->SetInsertPoint(_begin_op);
// Touch memory (on the opposite side of the page)
- m_ir->CreateAtomicRMW(llvm::AtomicRMWInst::Or, _ptr(m_memptr, m_ir->CreateXor(_eal, 4096 / 2)), m_ir->getInt8(0), llvm::MaybeAlign{16}, llvm::AtomicOrdering::SequentiallyConsistent);
+ m_ir->CreateAtomicRMW(llvm::AtomicRMWInst::Or, _ptr(m_memptr, m_ir->CreateXor(_eal, 4096 / 2)), m_ir->getInt8(0), llvm::MaybeAlign{16}, llvm::AtomicOrdering::SequentiallyConsistent);
- const auto rptr = _ptr(m_ir->CreateLoad(get_type(), spu_ptr(&spu_thread::reserv_base_addr)), ((eal_val & 0xff80) >> 1).eval(m_ir));
- const auto rtime = m_ir->CreateLoad(get_type(), spu_ptr(&spu_thread::rtime));
+ const auto rptr = _ptr(m_ir->CreateLoad(get_type(), spu_ptr(&spu_thread::reserv_base_addr)), ((eal_val & 0xff80) >> 1).eval(m_ir));
+ const auto rtime = m_ir->CreateLoad(get_type(), spu_ptr(&spu_thread::rtime));
m_ir->CreateBr(_repeat_lock);
m_ir->SetInsertPoint(_repeat_lock);
@@ -1313,10 +1310,10 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
m_ir->SetInsertPoint(_lock_success);
// Commit 16 bytes compare-exchange
- const auto sudo_ptr = _ptr(m_ir->CreateLoad(get_type(), spu_ptr(&spu_thread::memory_sudo_addr)), _eal);
+ const auto sudo_ptr = _ptr(m_ir->CreateLoad(get_type(), spu_ptr(&spu_thread::memory_sudo_addr)), _eal);
m_ir->CreateCondBr(
- m_ir->CreateExtractValue(m_ir->CreateAtomicCmpXchg(_ptr(sudo_ptr, diff), _rdata, _new, llvm::MaybeAlign{16}, llvm::AtomicOrdering::SequentiallyConsistent, llvm::AtomicOrdering::SequentiallyConsistent), 1)
+ m_ir->CreateExtractValue(m_ir->CreateAtomicCmpXchg(_ptr(sudo_ptr, diff), _rdata, _new, llvm::MaybeAlign{16}, llvm::AtomicOrdering::SequentiallyConsistent, llvm::AtomicOrdering::SequentiallyConsistent), 1)
, _success_and_unlock
, _fail_and_unlock);
@@ -1333,13 +1330,13 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
// Perform unlocked vm::reservation_update if no physical memory changes needed
m_ir->SetInsertPoint(_inc_res);
- const auto rptr2 = _ptr(m_ir->CreateLoad(get_type(), spu_ptr(&spu_thread::reserv_base_addr)), ((eal_val & 0xff80) >> 1).eval(m_ir));
+ const auto rptr2 = _ptr(m_ir->CreateLoad(get_type(), spu_ptr(&spu_thread::reserv_base_addr)), ((eal_val & 0xff80) >> 1).eval(m_ir));
llvm::Value* old_val{};
if (true || is_accurate_op)
{
- old_val = m_ir->CreateLoad(get_type(), spu_ptr(&spu_thread::rtime));
+ old_val = m_ir->CreateLoad(get_type(), spu_ptr(&spu_thread::rtime));
}
else
{
@@ -1360,8 +1357,8 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
}
m_ir->SetInsertPoint(_success);
- m_ir->CreateStore(m_ir->getInt64(spu_channel::bit_count | MFC_PUTLLC_SUCCESS), spu_ptr(&spu_thread::ch_atomic_stat));
- m_ir->CreateStore(m_ir->getInt32(0), spu_ptr(&spu_thread::raddr));
+ m_ir->CreateStore(m_ir->getInt64(spu_channel::bit_count | MFC_PUTLLC_SUCCESS), spu_ptr(&spu_thread::ch_atomic_stat));
+ m_ir->CreateStore(m_ir->getInt32(0), spu_ptr(&spu_thread::raddr));
m_ir->CreateBr(_final);
m_ir->SetInsertPoint(_fail_and_unlock);
@@ -1370,7 +1367,7 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
m_ir->SetInsertPoint(_fail);
call("PUTLLC16_fail", +on_fail, m_thread, _eal);
- m_ir->CreateStore(m_ir->getInt64(spu_channel::bit_count | MFC_PUTLLC_FAILURE), spu_ptr(&spu_thread::ch_atomic_stat));
+ m_ir->CreateStore(m_ir->getInt64(spu_channel::bit_count | MFC_PUTLLC_FAILURE), spu_ptr(&spu_thread::ch_atomic_stat));
m_ir->CreateBr(_final);
m_ir->SetInsertPoint(_final);
@@ -1410,7 +1407,7 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
const auto _final = llvm::BasicBlock::Create(m_context, "", m_function);
const auto _eal = (get_reg_fixed(s_reg_mfc_eal) & -128).eval(m_ir);
- const auto _raddr = m_ir->CreateLoad(get_type(), spu_ptr(&spu_thread::raddr));
+ const auto _raddr = m_ir->CreateLoad(get_type(), spu_ptr(&spu_thread::raddr));
m_ir->CreateCondBr(m_ir->CreateAnd(m_ir->CreateICmpEQ(_eal, _raddr), m_ir->CreateIsNotNull(_raddr)), _next, _fail, m_md_likely);
m_ir->SetInsertPoint(_next);
@@ -1418,8 +1415,8 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
value_t eal_val;
eal_val.value = _eal;
- const auto rptr = _ptr(m_ir->CreateLoad(get_type(), spu_ptr(&spu_thread::reserv_base_addr)), ((eal_val & 0xff80) >> 1).eval(m_ir));
- const auto rval = m_ir->CreateLoad(get_type(), spu_ptr(&spu_thread::rtime));
+ const auto rptr = _ptr(m_ir->CreateLoad(get_type(), spu_ptr(&spu_thread::reserv_base_addr)), ((eal_val & 0xff80) >> 1).eval(m_ir));
+ const auto rval = m_ir->CreateLoad(get_type |