Compare commits

..
Author SHA1 Message Date
lightningterror 3b0a83c1ab Qt/Fullscreenui/GS: Add Automatic blending option.
Automatic blending option will behave like basic level with the exception of gamedb if it forces a blend level then it will take that in to consideration, any other option will override the gamedb.
2025-09-02 14:47:44 +02:00
143 changed files with 2864 additions and 5591 deletions
+3 -3
View File
@@ -68,7 +68,7 @@ jobs:
mv ./release-notes.md ${GITHUB_WORKSPACE}/release-notes.md
- name: Create a GitHub Release (Manual)
uses: softprops/action-gh-release@6cbd405e2c4e67a21c47fa9e383d020e4e28b836
uses: softprops/action-gh-release@72f2c25fcb47643c292f7107632f7a47c1df5cd8
if: steps.tag_version.outputs.new_tag && github.event_name == 'workflow_dispatch'
with:
body_path: ./release-notes.md
@@ -77,7 +77,7 @@ jobs:
tag_name: ${{ steps.tag_version.outputs.new_tag }}
- name: Create a GitHub Release (Push)
uses: softprops/action-gh-release@6cbd405e2c4e67a21c47fa9e383d020e4e28b836
uses: softprops/action-gh-release@72f2c25fcb47643c292f7107632f7a47c1df5cd8
if: steps.tag_version.outputs.new_tag && github.event_name != 'workflow_dispatch'
with:
body_path: ./release-notes.md
@@ -203,7 +203,7 @@ jobs:
echo "TAG_VAL=${TAG_VAL}"
gh release edit ${TAG_VAL} --draft=false --repo PCSX2/pcsx2
- uses: actions/setup-node@v5
- uses: actions/setup-node@v4
with:
node-version: 22
@@ -1,60 +0,0 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index bace076..bfb1c66 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -21,6 +21,10 @@ endif ()
find_package(Qt${APNG_QT_VERSION} REQUIRED COMPONENTS Core Gui)
+set(CMAKE_FIND_FRAMEWORK NEVER)
+find_package(PNG 1.6.40 REQUIRED)
+find_package(ZLIB REQUIRED)
+
add_subdirectory(src)
if(APNG_TESTS)
diff --git a/cmake/FindZLib.cmake b/cmake/FindZLib.cmake
deleted file mode 100644
index f8e9220..0000000
--- a/cmake/FindZLib.cmake
+++ /dev/null
@@ -1 +0,0 @@
-add_library(ZLIB::ZLIB ALIAS zlibstatic) # use our zlib
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 697df95..0e89371 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,2 +1 @@
-add_subdirectory(3rdparty EXCLUDE_FROM_ALL)
add_subdirectory(plugins)
diff --git a/src/plugins/imageformats/apng/CMakeLists.txt b/src/plugins/imageformats/apng/CMakeLists.txt
index e1b3fd9..72164fb 100644
--- a/src/plugins/imageformats/apng/CMakeLists.txt
+++ b/src/plugins/imageformats/apng/CMakeLists.txt
@@ -14,13 +14,10 @@ target_sources(ApngImagePlugin PRIVATE ${APNG_SOURCES})
target_link_libraries(ApngImagePlugin PRIVATE
Qt${APNG_QT_VERSION}::Core
Qt${APNG_QT_VERSION}::Gui
- png_static
- zlibstatic
+ PNG::PNG
+ ZLIB::ZLIB
)
-get_target_property(_png_include png_static INCLUDE_DIRECTORIES)
-target_include_directories(ApngImagePlugin PRIVATE ${_png_include})
-
target_compile_definitions(ApngImagePlugin PRIVATE
QT_DEPRECATED_WARNINGS
QT_ASCII_CAST_WARNINGS
@@ -31,3 +28,10 @@ set_target_properties(ApngImagePlugin PROPERTIES
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/plugins/imageformats"
LIBRARY_OUTPUT_NAME qapng
)
+
+install(TARGETS ApngImagePlugin DESTINATION "plugins/imageformats")
+
+if(WIN32 AND MSVC)
+ set_target_properties(ApngImagePlugin PROPERTIES DEBUG_POSTFIX d)
+ install(FILES $<TARGET_PDB_FILE:ApngImagePlugin> DESTINATION "plugins/imageformats" OPTIONAL)
+endif()
@@ -20,9 +20,8 @@ LIBBACKTRACE=ad106d5fdd5d960bd33fae1c48a351af567fd075
LIBJPEGTURBO=3.1.1
LIBPNG=1.6.50
LIBWEBP=1.6.0
SDL=SDL3-3.2.22
SDL=SDL3-3.2.20
QT=6.9.2
QTAPNG=1.3.0
LZ4=1.10.0
ZSTD=1.5.7
KDDOCKWIDGETS=2.2.3
@@ -44,8 +43,7 @@ fd6f417fe9e3a071cf1424a5152d926a34c4a3c5070745470be6cf12a404ed79 $LIBBACKTRACE.
aadc97ea91f6ef078b0ae3a62bba69e008d9a7db19b34e4ac973b19b71b4217c libjpeg-turbo-$LIBJPEGTURBO.tar.gz
4df396518620a7aa3651443e87d1b2862e4e88cad135a8b93423e01706232307 libpng-$LIBPNG.tar.xz
e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWEBP.tar.gz
f29d00cbcee273c0a54f3f32f86bf5c595e8823a96b1d92a145aac40571ebfcc $SDL.tar.gz
687ddc0c7cb128a3ea58e159b5129252537c27ede0c32a93f11f03127f0c0165 libpng-$LIBPNG-apng.patch.gz
467600ae090dd28616fa37369faf4e3143198ff1da37729b552137e47f751a67 $SDL.tar.gz
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
44be9c9ecfe04129c4dea0a7e1b36ad476c9cc07c292016ac98e7b41514f2440 qtbase-everywhere-src-$QT.tar.xz
@@ -54,7 +52,6 @@ d984cab8f26334aa1c15e5b8f0cd9f1b7c0c1289fe0b68c1c84ab469b75605a5 qtsvg-everywhe
d8b7f7e8e970cc0b975205fd6d5832ea917ef3e751df69b97439c1cddd67a489 qttools-everywhere-src-$QT.tar.xz
c73bb6281ed365c0f954f4b1b6e1b13e1b3fefd94854f46fcd9a412f641f7ed6 qttranslations-everywhere-src-$QT.tar.xz
cad79806565568f12f9983fed69219416abcee9d5deef4abdfcf94aa2eef7781 qtwayland-everywhere-src-$QT.tar.xz
f1d3be3489f758efe1a8f12118a212febbe611aa670af32e0159fa3c1feab2a6 QtApng-$QTAPNG.tar.gz
a8e4a25e5c2686fd36981e527ed05e451fcfc226bddf350f4e76181371190937 shaderc-$SHADERC.tar.gz
9427deccbdf4bde6a269938df38c6bd75247493786a310d8d733a2c82065ef47 shaderc-glslang-$SHADERC_GLSLANG.tar.gz
c2225a49c3d7efa5c4f4ce4a6b42081e6ea3daca376f3353d9d7c2722d77a28a shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz
@@ -70,7 +67,6 @@ curl -L \
-O "https://github.com/ianlancetaylor/libbacktrace/archive/$LIBBACKTRACE.zip" \
-O "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/$LIBJPEGTURBO/libjpeg-turbo-$LIBJPEGTURBO.tar.gz" \
-O "https://downloads.sourceforge.net/project/libpng/libpng16/$LIBPNG/libpng-$LIBPNG.tar.xz" \
-O "https://download.sourceforge.net/libpng-apng/libpng-$LIBPNG-apng.patch.gz" \
-O "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-$LIBWEBP.tar.gz" \
-O "https://github.com/lz4/lz4/releases/download/v$LZ4/lz4-$LZ4.tar.gz" \
-O "https://libsdl.org/release/$SDL.tar.gz" \
@@ -81,7 +77,6 @@ curl -L \
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qttools-everywhere-src-$QT.tar.xz" \
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qttranslations-everywhere-src-$QT.tar.xz" \
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtwayland-everywhere-src-$QT.tar.xz" \
-o "QtApng-$QTAPNG.tar.gz" "https://github.com/jurplel/QtApng/archive/refs/tags/$QTAPNG.tar.gz" \
-o "shaderc-$SHADERC.tar.gz" "https://github.com/google/shaderc/archive/refs/tags/v$SHADERC.tar.gz" \
-o "shaderc-glslang-$SHADERC_GLSLANG.tar.gz" "https://github.com/KhronosGroup/glslang/archive/$SHADERC_GLSLANG.tar.gz" \
-o "shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz" "https://github.com/KhronosGroup/SPIRV-Headers/archive/$SHADERC_SPIRVHEADERS.tar.gz" \
@@ -104,9 +99,7 @@ cd ..
echo "Building libpng..."
rm -fr "libpng-$LIBPNG"
tar xf "libpng-$LIBPNG.tar.xz"
gunzip -d -f "libpng-$LIBPNG-apng.patch.gz"
cd "libpng-$LIBPNG"
patch -p1 < "../libpng-$LIBPNG-apng.patch"
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DBUILD_SHARED_LIBS=ON -DPNG_TESTS=OFF -DPNG_STATIC=OFF -DPNG_SHARED=ON -DPNG_TOOLS=OFF -B build -G Ninja
cmake --build build --parallel
ninja -C build install
@@ -257,16 +250,6 @@ cmake --build . --parallel
ninja install
cd ../../
echo "Building Qt APNG..."
rm -fr "QtApng-$QTAPNG"
tar xf "QtApng-$QTAPNG.tar.gz"
cd "QtApng-$QTAPNG"
patch -p1 < "$SCRIPTDIR/../common/qtapng-cmake.patch"
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -B build -G Ninja
cmake --build build --parallel
ninja -C build install
cd ..
echo "Building KDDockWidgets..."
rm -fr "KDDockWidgets-$KDDOCKWIDGETS"
tar xf "KDDockWidgets-$KDDOCKWIDGETS.tar.gz"
@@ -14,8 +14,8 @@
"sources": [
{
"type": "archive",
"url": "https://libsdl.org/release/SDL3-3.2.22.tar.gz",
"sha256": "f29d00cbcee273c0a54f3f32f86bf5c595e8823a96b1d92a145aac40571ebfcc"
"url": "https://libsdl.org/release/SDL3-3.2.20.tar.gz",
"sha256": "467600ae090dd28616fa37369faf4e3143198ff1da37729b552137e47f751a67"
}
],
"cleanup": [
@@ -1,46 +0,0 @@
{
"name": "libpng",
"buildsystem": "cmake-ninja",
"builddir": true,
"config-opts": [
"-DPNG_TESTS=OFF",
"-DPNG_STATIC=OFF",
"-DPNG_SHARED=ON",
"-DPNG_TOOLS=OFF"
],
"build-options": {
"strip": true
},
"sources": [
{
"type": "archive",
"url": "https://downloads.sourceforge.net/project/libpng/libpng16/1.6.50/libpng-1.6.50.tar.xz",
"sha256": "4df396518620a7aa3651443e87d1b2862e4e88cad135a8b93423e01706232307"
},
{
"type": "file",
"url": "https://download.sourceforge.net/libpng-apng/libpng-1.6.50-apng.patch.gz",
"dest-filename": "libpng-1.6.50-apng.patch.gz",
"sha256": "687ddc0c7cb128a3ea58e159b5129252537c27ede0c32a93f11f03127f0c0165"
},
{
"type": "shell",
"commands":
[
"gunzip -f libpng-1.6.50-apng.patch.gz",
"patch -p1 < \"libpng-1.6.50-apng.patch\""
]
}
],
"cleanup": [
"/bin",
"/include",
"/lib/*.a",
"/lib/*.la",
"/lib/cmake",
"/lib/libpng",
"/lib/pkgconfig",
"/share/man"
]
}
@@ -1,29 +0,0 @@
{
"name": "qtapng",
"buildsystem": "cmake-ninja",
"builddir": true,
"config-opts": [
"-DCMAKE_PREFIX_PATH=\"${FLATPAK_DEST}\""
],
"build-options": {
"strip": true
},
"sources": [
{
"type": "git",
"url": "https://github.com/jurplel/QtApng.git",
"tag": "1.3.0",
"commit": "bd15516b281204e90ecd5b80b00d1274b062f5fc"
},
{
"type": "patch",
"path": "../../../common/qtapng-cmake.patch"
}
],
"cleanup": [
"/plugins"
],
"post-install": [
"mv ${FLATPAK_DEST}/plugins/* ${FLATPAK_DEST}/bin/"
]
}
@@ -32,8 +32,6 @@
"modules/23-kddockwidgets.json",
"modules/24-plutovg.json",
"modules/25-plutosvg.json",
"modules/26-libpng.json",
"modules/27-qtapng.json",
{
"name": "pcsx2",
"buildsystem": "cmake-ninja",
@@ -47,7 +45,6 @@
"cxxflags": "",
"cxxflags-override": true,
"config-opts": [
"-DCMAKE_PREFIX_PATH=\"${FLATPAK_DEST}\"",
"-DCMAKE_BUILD_TYPE=Release",
"-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON",
"-DCMAKE_C_COMPILER=/usr/lib/sdk/llvm18/bin/clang",
@@ -40,7 +40,7 @@ fi
FREETYPE=2.13.3
HARFBUZZ=11.2.0
SDL=SDL3-3.2.22
SDL=SDL3-3.2.20
ZSTD=1.5.7
LZ4=1.10.0
LIBPNG=1.6.50
@@ -49,7 +49,6 @@ LIBWEBP=1.6.0
FFMPEG=6.0
MOLTENVK=1.2.9
QT=6.7.3
QTAPNG=1.3.0
KDDOCKWIDGETS=2.2.3
PLUTOVG=1.3.0
PLUTOSVG=0.0.7
@@ -80,12 +79,11 @@ CMAKE_ARCH_UNIVERSAL=-DCMAKE_OSX_ARCHITECTURES="x86_64;arm64"
cat > SHASUMS <<EOF
0550350666d427c74daeb85d5ac7bb353acba5f76956395995311a9c6f063289 freetype-$FREETYPE.tar.xz
16c0204704f3ebeed057aba100fe7db18d71035505cb10e595ea33d346457fc8 harfbuzz-$HARFBUZZ.tar.gz
f29d00cbcee273c0a54f3f32f86bf5c595e8823a96b1d92a145aac40571ebfcc $SDL.tar.gz
467600ae090dd28616fa37369faf4e3143198ff1da37729b552137e47f751a67 $SDL.tar.gz
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
4df396518620a7aa3651443e87d1b2862e4e88cad135a8b93423e01706232307 libpng-$LIBPNG.tar.xz
e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWEBP.tar.gz
687ddc0c7cb128a3ea58e159b5129252537c27ede0c32a93f11f03127f0c0165 libpng-$LIBPNG-apng.patch.gz
aadc97ea91f6ef078b0ae3a62bba69e008d9a7db19b34e4ac973b19b71b4217c libjpeg-turbo-$LIBJPEGTURBO.tar.gz
57be87c22d9b49c112b6d24bc67d42508660e6b718b3db89c44e47e289137082 ffmpeg-$FFMPEG.tar.xz
f415a09385030c6510a936155ce211f617c31506db5fbc563e804345f1ecf56e v$MOLTENVK.tar.gz
@@ -94,7 +92,6 @@ f415a09385030c6510a936155ce211f617c31506db5fbc563e804345f1ecf56e v$MOLTENVK.tar
40142cb71fb1e07ad612bc361b67f5d54cd9367f9979ae6b86124a064deda06b qtsvg-everywhere-src-$QT.tar.xz
f03bb7df619cd9ac9dba110e30b7bcab5dd88eb8bdc9cc752563b4367233203f qttools-everywhere-src-$QT.tar.xz
dcc762acac043b9bb5e4d369b6d6f53e0ecfcf76a408fe0db5f7ef071c9d6dc8 qttranslations-everywhere-src-$QT.tar.xz
f1d3be3489f758efe1a8f12118a212febbe611aa670af32e0159fa3c1feab2a6 QtApng-$QTAPNG.tar.gz
a8e4a25e5c2686fd36981e527ed05e451fcfc226bddf350f4e76181371190937 shaderc-$SHADERC.tar.gz
9427deccbdf4bde6a269938df38c6bd75247493786a310d8d733a2c82065ef47 shaderc-glslang-$SHADERC_GLSLANG.tar.gz
c2225a49c3d7efa5c4f4ce4a6b42081e6ea3daca376f3353d9d7c2722d77a28a shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz
@@ -111,7 +108,6 @@ curl -C - -L \
-O "https://github.com/facebook/zstd/releases/download/v$ZSTD/zstd-$ZSTD.tar.gz" \
-O "https://github.com/lz4/lz4/releases/download/v$LZ4/lz4-$LZ4.tar.gz" \
-O "https://downloads.sourceforge.net/project/libpng/libpng16/$LIBPNG/libpng-$LIBPNG.tar.xz" \
-O "https://download.sourceforge.net/libpng-apng/libpng-$LIBPNG-apng.patch.gz" \
-O "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/$LIBJPEGTURBO/libjpeg-turbo-$LIBJPEGTURBO.tar.gz" \
-O "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-$LIBWEBP.tar.gz" \
-O "https://ffmpeg.org/releases/ffmpeg-$FFMPEG.tar.xz" \
@@ -121,7 +117,6 @@ curl -C - -L \
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qtsvg-everywhere-src-$QT.tar.xz" \
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qttools-everywhere-src-$QT.tar.xz" \
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qttranslations-everywhere-src-$QT.tar.xz" \
-o "QtApng-$QTAPNG.tar.gz" "https://github.com/jurplel/QtApng/archive/refs/tags/$QTAPNG.tar.gz" \
-o "shaderc-$SHADERC.tar.gz" "https://github.com/google/shaderc/archive/refs/tags/v$SHADERC.tar.gz" \
-o "shaderc-glslang-$SHADERC_GLSLANG.tar.gz" "https://github.com/KhronosGroup/glslang/archive/$SHADERC_GLSLANG.tar.gz" \
-o "shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz" "https://github.com/KhronosGroup/SPIRV-Headers/archive/$SHADERC_SPIRVHEADERS.tar.gz" \
@@ -205,9 +200,7 @@ cd ..
echo "Installing libpng..."
rm -fr "libpng-$LIBPNG"
tar xf "libpng-$LIBPNG.tar.xz"
gunzip -d -f "libpng-$LIBPNG-apng.patch.gz"
cd "libpng-$LIBPNG"
patch -p1 < "../libpng-$LIBPNG-apng.patch"
cmake "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_X64" -DBUILD_SHARED_LIBS=ON -DPNG_TESTS=OFF -DPNG_FRAMEWORK=OFF -B build
make -C build "-j$NPROCS"
cmake "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_ARM64" -DBUILD_SHARED_LIBS=ON -DPNG_TESTS=OFF -DPNG_FRAMEWORK=OFF -DPNG_ARM_NEON=on -B build-arm64
@@ -376,16 +369,6 @@ make "-j$NPROCS"
make install
cd ../..
echo "Building Qt APNG..."
rm -fr "QtApng-$QTAPNG"
tar xf "QtApng-$QTAPNG.tar.gz"
cd "QtApng-$QTAPNG"
patch -p1 < "$SCRIPTDIR/../common/qtapng-cmake.patch"
cmake "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL" -B build
make -C build "-j$NPROCS"
make -C build install
cd ..
echo "Building KDDockWidgets..."
rm -fr "KDDockWidgets-$KDDOCKWIDGETS"
tar xf "KDDockWidgets-$KDDOCKWIDGETS.tar.gz"
@@ -22,7 +22,7 @@ fi
FREETYPE=2.13.3
HARFBUZZ=11.2.0
SDL=SDL3-3.2.22
SDL=SDL3-3.2.20
ZSTD=1.5.7
LZ4=1.10.0
LIBPNG=1.6.50
@@ -31,7 +31,6 @@ LIBWEBP=1.6.0
FFMPEG=6.0
MOLTENVK=1.2.9
QT=6.7.3
QTAPNG=1.3.0
KDDOCKWIDGETS=2.2.3
PLUTOVG=1.3.0
PLUTOSVG=0.0.7
@@ -60,12 +59,11 @@ CMAKE_COMMON=(
cat > SHASUMS <<EOF
0550350666d427c74daeb85d5ac7bb353acba5f76956395995311a9c6f063289 freetype-$FREETYPE.tar.xz
16c0204704f3ebeed057aba100fe7db18d71035505cb10e595ea33d346457fc8 harfbuzz-$HARFBUZZ.tar.gz
f29d00cbcee273c0a54f3f32f86bf5c595e8823a96b1d92a145aac40571ebfcc $SDL.tar.gz
467600ae090dd28616fa37369faf4e3143198ff1da37729b552137e47f751a67 $SDL.tar.gz
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
4df396518620a7aa3651443e87d1b2862e4e88cad135a8b93423e01706232307 libpng-$LIBPNG.tar.xz
e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWEBP.tar.gz
687ddc0c7cb128a3ea58e159b5129252537c27ede0c32a93f11f03127f0c0165 libpng-$LIBPNG-apng.patch.gz
aadc97ea91f6ef078b0ae3a62bba69e008d9a7db19b34e4ac973b19b71b4217c libjpeg-turbo-$LIBJPEGTURBO.tar.gz
57be87c22d9b49c112b6d24bc67d42508660e6b718b3db89c44e47e289137082 ffmpeg-$FFMPEG.tar.xz
f415a09385030c6510a936155ce211f617c31506db5fbc563e804345f1ecf56e v$MOLTENVK.tar.gz
@@ -74,7 +72,6 @@ f415a09385030c6510a936155ce211f617c31506db5fbc563e804345f1ecf56e v$MOLTENVK.tar
40142cb71fb1e07ad612bc361b67f5d54cd9367f9979ae6b86124a064deda06b qtsvg-everywhere-src-$QT.tar.xz
f03bb7df619cd9ac9dba110e30b7bcab5dd88eb8bdc9cc752563b4367233203f qttools-everywhere-src-$QT.tar.xz
dcc762acac043b9bb5e4d369b6d6f53e0ecfcf76a408fe0db5f7ef071c9d6dc8 qttranslations-everywhere-src-$QT.tar.xz
f1d3be3489f758efe1a8f12118a212febbe611aa670af32e0159fa3c1feab2a6 QtApng-$QTAPNG.tar.gz
a8e4a25e5c2686fd36981e527ed05e451fcfc226bddf350f4e76181371190937 shaderc-$SHADERC.tar.gz
9427deccbdf4bde6a269938df38c6bd75247493786a310d8d733a2c82065ef47 shaderc-glslang-$SHADERC_GLSLANG.tar.gz
c2225a49c3d7efa5c4f4ce4a6b42081e6ea3daca376f3353d9d7c2722d77a28a shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz
@@ -91,7 +88,6 @@ curl -L \
-O "https://github.com/facebook/zstd/releases/download/v$ZSTD/zstd-$ZSTD.tar.gz" \
-O "https://github.com/lz4/lz4/releases/download/v$LZ4/lz4-$LZ4.tar.gz" \
-O "https://downloads.sourceforge.net/project/libpng/libpng16/$LIBPNG/libpng-$LIBPNG.tar.xz" \
-O "https://download.sourceforge.net/libpng-apng/libpng-$LIBPNG-apng.patch.gz" \
-O "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/$LIBJPEGTURBO/libjpeg-turbo-$LIBJPEGTURBO.tar.gz" \
-O "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-$LIBWEBP.tar.gz" \
-O "https://ffmpeg.org/releases/ffmpeg-$FFMPEG.tar.xz" \
@@ -101,7 +97,6 @@ curl -L \
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qtsvg-everywhere-src-$QT.tar.xz" \
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qttools-everywhere-src-$QT.tar.xz" \
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qttranslations-everywhere-src-$QT.tar.xz" \
-o "QtApng-$QTAPNG.tar.gz" "https://github.com/jurplel/QtApng/archive/refs/tags/$QTAPNG.tar.gz" \
-o "shaderc-$SHADERC.tar.gz" "https://github.com/google/shaderc/archive/refs/tags/v$SHADERC.tar.gz" \
-o "shaderc-glslang-$SHADERC_GLSLANG.tar.gz" "https://github.com/KhronosGroup/glslang/archive/$SHADERC_GLSLANG.tar.gz" \
-o "shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz" "https://github.com/KhronosGroup/SPIRV-Headers/archive/$SHADERC_SPIRVHEADERS.tar.gz" \
@@ -161,9 +156,7 @@ cd ..
echo "Installing libpng..."
rm -fr "libpng-$LIBPNG"
tar xf "libpng-$LIBPNG.tar.xz"
gunzip -d -f "libpng-$LIBPNG-apng.patch.gz"
cd "libpng-$LIBPNG"
patch -p1 < "../libpng-$LIBPNG-apng.patch"
cmake "${CMAKE_COMMON[@]}" -DBUILD_SHARED_LIBS=ON -DPNG_TESTS=OFF -DPNG_FRAMEWORK=OFF -B build
make -C build "-j$NPROCS"
make -C build install
@@ -338,16 +331,6 @@ make "-j$NPROCS"
make install
cd ../..
echo "Building Qt APNG..."
rm -fr "QtApng-$QTAPNG"
tar xf "QtApng-$QTAPNG.tar.gz"
cd "QtApng-$QTAPNG"
patch -p1 < "$SCRIPTDIR/../common/qtapng-cmake.patch"
cmake "${CMAKE_COMMON[@]}" -B build
make -C build "-j$NPROCS"
make -C build install
cd ..
echo "Building KDDockWidgets..."
rm -fr "KDDockWidgets-$KDDOCKWIDGETS"
tar xf "KDDockWidgets-$KDDOCKWIDGETS.tar.gz"
@@ -46,11 +46,9 @@ set FREETYPE=2.13.3
set HARFBUZZ=11.2.0
set LIBJPEGTURBO=3.1.1
set LIBPNG=1650
set SDL=SDL3-3.2.22
set SDL=SDL3-3.2.20
set QT=6.9.2
set LIBPNGLONG=1.6.50
set QTMINOR=6.9
set QTAPNG=1.3.0
set LZ4=1.10.0
set WEBP=1.6.0
set ZLIB=1.3.1
@@ -68,16 +66,14 @@ set SHADERC_SPIRVTOOLS=33e02568181e3312f49a3cf33df470bf96ef293a
call :downloadfile "freetype-%FREETYPE%.tar.gz" https://sourceforge.net/projects/freetype/files/freetype2/%FREETYPE%/freetype-%FREETYPE%.tar.gz/download 5c3a8e78f7b24c20b25b54ee575d6daa40007a5f4eea2845861c3409b3021747 || goto error
call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip 850cb5e38e21106c0abba86c5b73f8f74b9a32d7725505901d081080b0d3f0b3 || goto error
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1650.zip 4be6938313b08d5921f9dede13f2789b653c96f4f8595d92ff3f09c9320e51c7 || goto error
call :downloadfile "lpng%LIBPNG%-apng.patch.gz" https://download.sourceforge.net/libpng-apng/libpng-%LIBPNGLONG%-apng.patch.gz 687ddc0c7cb128a3ea58e159b5129252537c27ede0c32a93f11f03127f0c0165 || goto error
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" aadc97ea91f6ef078b0ae3a62bba69e008d9a7db19b34e4ac973b19b71b4217c || goto error
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 || goto error
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 3d60068b1e5c83c66bb14c325dfef46f8fcc380735b4591de6f5e7b9738929d1 || goto error
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" d76454913ea6f5f38856fbf00578d8e39daf842887f3396c95608414680250f7 || goto error
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 97d59c78e40b4ddd018738d285a12afc320b57f8265a3f760353739a3619ccdb || goto error
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" f2fc6ff382c6f3af79493d0709dbd64847d0356313518f094f9096315f2fdb30 || goto error
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" af80bb671ea0f66c0036ce7041a56b0e550fc94fb88d2c77b5b6a3e33e42139b || goto error
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" d2f4c7a4a12630e879702353f944f96a5d8e764771b5a5f04163334ad61b39db || goto error
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" 3e168d1b081ee3a2175fe1bd97ad03bb40fe7ce38a37e99923a19f0e7ec4d81c || goto error
call :downloadfile "QtApng-%QTAPNG%.zip" "https://github.com/jurplel/QtApng/archive/refs/tags/%QTAPNG%.zip" 5176082cdd468047a7eb1ec1f106b032f57df207aa318d559b29606b00d159ac || goto error
call :downloadfile "lz4-%LZ4%.zip" "https://github.com/lz4/lz4/archive/refs/tags/v%LZ4%.zip" 3224b4c80f351f194984526ef396f6079bd6332dd9825c72ac0d7a37b3cdc565 || goto error
call :downloadfile "zlib%ZLIBSHORT%.zip" "https://zlib.net/zlib%ZLIBSHORT%.zip" 72af66d44fcc14c22013b46b814d5d2514673dda3d115e64b690c1ad636e7b17 || goto error
call :downloadfile "zstd-%ZSTD%.zip" "https://github.com/facebook/zstd/archive/refs/tags/v%ZSTD%.zip" 7897bc5d620580d9b7cd3539c44b59d78f3657d33663fe97a145e07b4ebd69a4 || goto error
@@ -111,10 +107,7 @@ cd .. || goto error
echo Building libpng...
rmdir /S /Q "lpng%LIBPNG%"
%SEVENZIP% x "lpng%LIBPNG%.zip" || goto error
rem apng not in released libpng yet
%SEVENZIP% x "lpng%LIBPNG%-apng.patch.gz" -aoa || goto error
cd "lpng%LIBPNG%" || goto error
%PATCH% -p1 < "../libpng-%LIBPNGLONG%-apng.patch" || goto error
cmake %ARM64TOOLCHAIN% -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DBUILD_SHARED_LIBS=ON -DBUILD_SHARED_LIBS=ON -DPNG_TESTS=OFF -DPNG_STATIC=OFF -DPNG_SHARED=ON -DPNG_TOOLS=OFF -B build -G Ninja || goto error
cmake --build build --parallel || goto error
ninja -C build install || goto error
@@ -253,22 +246,6 @@ cmake --build . --parallel || goto error
ninja install || goto error
cd ..\.. || goto error
if %DEBUG%==1 (
set QTAPNGBUILDSPEC=-DCMAKE_CONFIGURATION_TYPES="Release;Debug" -DCMAKE_CROSS_CONFIGS=all -DCMAKE_DEFAULT_BUILD_TYPE=Release -DCMAKE_DEFAULT_CONFIGS=all -G "Ninja Multi-Config"
) else (
set QTAPNGBUILDSPEC=-DCMAKE_BUILD_TYPE=Release -G Ninja
)
echo Building Qt APNG...
rmdir /S /Q "QtApng-%QTAPNG%"
%SEVENZIP% x "QtApng-%QTAPNG%.zip" || goto error
cd "QtApng-%QTAPNG%" || goto error
%PATCH% -p1 < "%SCRIPTDIR%\..\common\qtapng-cmake.patch" || goto error
cmake -B build -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" %FORCEPDB% %QTAPNGBUILDSPEC% || goto error
cmake --build build --parallel || goto error
ninja -C build install || goto error
cd .. || goto error
if %DEBUG%==1 (
set KDDOCKWIDGETSBUILDSPEC=-DCMAKE_CONFIGURATION_TYPES="Release;Debug" -DCMAKE_CROSS_CONFIGS=all -DCMAKE_DEFAULT_BUILD_TYPE=Release -DCMAKE_DEFAULT_CONFIGS=all -G "Ninja Multi-Config"
) else (
@@ -44,11 +44,9 @@ set FREETYPE=2.13.3
set HARFBUZZ=11.2.0
set LIBJPEGTURBO=3.1.1
set LIBPNG=1650
set SDL=SDL3-3.2.22
set LIBPNGLONG=1.6.50
set SDL=SDL3-3.2.20
set QT=6.9.2
set QTMINOR=6.9
set QTAPNG=1.3.0
set LZ4=1.10.0
set WEBP=1.6.0
set ZLIB=1.3.1
@@ -66,16 +64,14 @@ set SHADERC_SPIRVTOOLS=33e02568181e3312f49a3cf33df470bf96ef293a
call :downloadfile "freetype-%FREETYPE%.tar.gz" https://sourceforge.net/projects/freetype/files/freetype2/%FREETYPE%/freetype-%FREETYPE%.tar.gz/download 5c3a8e78f7b24c20b25b54ee575d6daa40007a5f4eea2845861c3409b3021747 || goto error
call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip 850cb5e38e21106c0abba86c5b73f8f74b9a32d7725505901d081080b0d3f0b3 || goto error
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1650.zip 4be6938313b08d5921f9dede13f2789b653c96f4f8595d92ff3f09c9320e51c7 || goto error
call :downloadfile "lpng%LIBPNG%-apng.patch.gz" https://download.sourceforge.net/libpng-apng/libpng-%LIBPNGLONG%-apng.patch.gz 687ddc0c7cb128a3ea58e159b5129252537c27ede0c32a93f11f03127f0c0165 || goto error
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" aadc97ea91f6ef078b0ae3a62bba69e008d9a7db19b34e4ac973b19b71b4217c || goto error
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 || goto error
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 3d60068b1e5c83c66bb14c325dfef46f8fcc380735b4591de6f5e7b9738929d1 || goto error
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" d76454913ea6f5f38856fbf00578d8e39daf842887f3396c95608414680250f7 || goto error
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 97d59c78e40b4ddd018738d285a12afc320b57f8265a3f760353739a3619ccdb || goto error
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" f2fc6ff382c6f3af79493d0709dbd64847d0356313518f094f9096315f2fdb30 || goto error
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" af80bb671ea0f66c0036ce7041a56b0e550fc94fb88d2c77b5b6a3e33e42139b || goto error
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" d2f4c7a4a12630e879702353f944f96a5d8e764771b5a5f04163334ad61b39db || goto error
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" 3e168d1b081ee3a2175fe1bd97ad03bb40fe7ce38a37e99923a19f0e7ec4d81c || goto error
call :downloadfile "QtApng-%QTAPNG%.zip" "https://github.com/jurplel/QtApng/archive/refs/tags/%QTAPNG%.zip" 5176082cdd468047a7eb1ec1f106b032f57df207aa318d559b29606b00d159ac || goto error
call :downloadfile "lz4-%LZ4%.zip" "https://github.com/lz4/lz4/archive/refs/tags/v%LZ4%.zip" 3224b4c80f351f194984526ef396f6079bd6332dd9825c72ac0d7a37b3cdc565 || goto error
call :downloadfile "zlib%ZLIBSHORT%.zip" "https://zlib.net/zlib%ZLIBSHORT%.zip" 72af66d44fcc14c22013b46b814d5d2514673dda3d115e64b690c1ad636e7b17 || goto error
call :downloadfile "zstd-%ZSTD%.zip" "https://github.com/facebook/zstd/archive/refs/tags/v%ZSTD%.zip" 7897bc5d620580d9b7cd3539c44b59d78f3657d33663fe97a145e07b4ebd69a4 || goto error
@@ -108,10 +104,7 @@ cd .. || goto error
echo Building libpng...
rmdir /S /Q "lpng%LIBPNG%"
%SEVENZIP% x "lpng%LIBPNG%.zip" || goto error
rem apng not in released libpng yet
%SEVENZIP% x "lpng%LIBPNG%-apng.patch.gz" -aoa || goto error
cd "lpng%LIBPNG%" || goto error
%PATCH% -p1 < "../libpng-%LIBPNGLONG%-apng.patch" || goto error
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DBUILD_SHARED_LIBS=ON -DBUILD_SHARED_LIBS=ON -DPNG_TESTS=OFF -DPNG_STATIC=OFF -DPNG_SHARED=ON -DPNG_TOOLS=OFF -B build -G Ninja || goto error
cmake --build build --parallel || goto error
ninja -C build install || goto error
@@ -254,22 +247,6 @@ cmake --build . --parallel || goto error
ninja install || goto error
cd ..\.. || goto error
if %DEBUG%==1 (
set QTAPNGBUILDSPEC=-DCMAKE_CONFIGURATION_TYPES="Release;Debug" -DCMAKE_CROSS_CONFIGS=all -DCMAKE_DEFAULT_BUILD_TYPE=Release -DCMAKE_DEFAULT_CONFIGS=all -G "Ninja Multi-Config"
) else (
set QTAPNGBUILDSPEC=-DCMAKE_BUILD_TYPE=Release -G Ninja
)
echo Building Qt APNG...
rmdir /S /Q "QtApng-%QTAPNG%"
%SEVENZIP% x "QtApng-%QTAPNG%.zip" || goto error
cd "QtApng-%QTAPNG%" || goto error
%PATCH% -p1 < "%SCRIPTDIR%\..\common\qtapng-cmake.patch" || goto error
cmake -B build -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" %FORCEPDB% %QTAPNGBUILDSPEC% || goto error
cmake --build build --parallel || goto error
ninja -C build install || goto error
cd .. || goto error
if %DEBUG%==1 (
set KDDOCKWIDGETSBUILDSPEC=-DCMAKE_CONFIGURATION_TYPES="Release;Debug" -DCMAKE_CROSS_CONFIGS=all -DCMAKE_DEFAULT_BUILD_TYPE=Release -DCMAKE_DEFAULT_CONFIGS=all -G "Ninja Multi-Config"
) else (
+1 -1
View File
@@ -8,7 +8,7 @@ jobs:
if: github.repository == 'PCSX2/pcsx2'
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@v6
- uses: actions/labeler@v5
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
-18
View File
@@ -185,24 +185,7 @@
#define ICON_PF_KEYBOARD "\xE2\x90\xBD"
#define ICON_PF_MOUSE "\xE2\x90\xBE"
#define ICON_PF_MOUSE_AND_KEYBOARD "\xE2\x90\xBF"
#define ICON_PF_DUALSHOCK2 "\xE2\x91\x81"
#define ICON_PF_DUALSHOCK2_SLASH "\xE2\x91\x82"
#define ICON_PF_GUITAR "\xE2\x91\x83"
#define ICON_PF_STEERING_WHEEL_ALT "\xE2\x91\x84"
#define ICON_PF_SEGA_SEAMIC "\xE2\x91\x85"
#define ICON_PF_JOGCON "\xE2\x91\x86"
#define ICON_PF_BUZZ_CONTROLLER "\xE2\x91\x87"
#define ICON_PF_GAMETRAK_DEVICE "\xE2\x91\x88"
#define ICON_PF_DJ_HERO_TURNTABLE "\xE2\x91\x89"
#define ICON_PF_REALPLAY_BOWLING "\xE2\x91\x8A"
#define ICON_PF_NEGCON "\xE2\x91\x8B"
#define ICON_PF_REZ_VIBRATOR "\xE2\x91\x8C"
#define ICON_PF_EYETOY_WEBCAM "\xE2\x91\x8D"
#define ICON_PF_SINGSTAR_MIC "\xE2\x91\x8E"
#define ICON_PF_GUNCON2 "\xE2\x91\x8F"
#define ICON_PF_HEADSET "\xE2\x91\x90"
#define ICON_PF_KEYBOARDMANIA "\xE2\x91\x91"
#define ICON_PF_PRINTER "\xE2\x91\x92"
#define ICON_PF_F1 "\xE2\x91\xA0"
#define ICON_PF_F2 "\xE2\x91\xA1"
#define ICON_PF_F3 "\xE2\x91\xA2"
@@ -379,7 +362,6 @@
#define ICON_PF_HEARTBEAT_MAG "\xE2\x8D\xBE"
#define ICON_PF_MONITOR_CODE "\xE2\x8D\xBF"
#define ICON_PF_SIXTY_CIRCLE "\xE2\x8E\x80"
#define ICON_PF_VIDEO_CAMERA "\xE2\x8E\x81"
#define ICON_PF_SPEAKER_ALT "\xE2\x8D\xA7"
#define ICON_PF_THUNDERBOLT "\xE2\x8D\x9C"
#define ICON_PF_BACKWARD "\xE2\x8F\x8C"
+28 -1186
View File
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -11,6 +11,7 @@ add_library(rcheevos
include/rc_hash.h
include/rc_runtime.h
include/rc_runtime_types.h
include/rc_url.h
include/rc_util.h
src/rapi/rc_api_common.c
src/rapi/rc_api_common.h
@@ -46,5 +47,5 @@ add_library(rcheevos
target_include_directories(rcheevos PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include")
target_include_directories(rcheevos INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/include")
target_compile_definitions(rcheevos PRIVATE "RC_NO_THREADS=1" "RC_HASH_NO_DISC" "RC_HASH_NO_ENCRYPTED" "RC_HASH_NO_ROM" "RC_HASH_NO_ZIP")
target_compile_definitions(rcheevos PRIVATE "RC_DISABLE_LUA=1" "RCHEEVOS_URL_SSL=1" "RC_NO_THREADS=1" "RC_HASH_NO_DISC" "RC_HASH_NO_ENCRYPTED" "RC_HASH_NO_ROM" "RC_HASH_NO_ZIP")
-31
View File
@@ -186,37 +186,6 @@ RC_EXPORT int RC_CCONV rc_api_process_update_leaderboard_response(rc_api_update_
RC_EXPORT int RC_CCONV rc_api_process_update_leaderboard_server_response(rc_api_update_leaderboard_response_t* response, const rc_api_server_response_t* server_response);
RC_EXPORT void RC_CCONV rc_api_destroy_update_leaderboard_response(rc_api_update_leaderboard_response_t* response);
/* --- Update Rich Presence --- */
/**
* API parameters for an update rich presence request.
*/
typedef struct rc_api_update_rich_presence_request_t {
/* The username of the developer */
const char* username;
/* The API token from the login request */
const char* api_token;
/* The unique identifier of the game */
uint32_t game_id;
/* The script for the rich_presence */
const char* script;
}
rc_api_update_rich_presence_request_t;
/**
* Response data for an update rich presence request.
*/
typedef struct rc_api_update_rich_presence_response_t {
/* Common server-provided response information */
rc_api_response_t response;
}
rc_api_update_rich_presence_response_t;
RC_EXPORT int RC_CCONV rc_api_init_update_rich_presence_request(rc_api_request_t* request, const rc_api_update_rich_presence_request_t* api_params);
RC_EXPORT int RC_CCONV rc_api_init_update_rich_presence_request_hosted(rc_api_request_t* request, const rc_api_update_rich_presence_request_t* api_params, const rc_api_host_t* host);
RC_EXPORT int RC_CCONV rc_api_process_update_rich_presence_server_response(rc_api_update_rich_presence_response_t* response, const rc_api_server_response_t* server_response);
RC_EXPORT void RC_CCONV rc_api_destroy_update_rich_presence_response(rc_api_update_rich_presence_response_t* response);
/* --- Fetch Badge Range --- */
/**
+1 -7
View File
@@ -211,10 +211,6 @@ typedef struct rc_client_user_game_summary_t {
uint32_t points_core;
uint32_t points_unlocked;
/* minimum version: 12.1 */
time_t beaten_time;
time_t completed_time;
} rc_client_user_game_summary_t;
/**
@@ -362,8 +358,6 @@ typedef struct rc_client_subset_t {
RC_EXPORT const rc_client_subset_t* RC_CCONV rc_client_get_subset_info(rc_client_t* client, uint32_t subset_id);
RC_EXPORT void RC_CCONV rc_client_get_user_subset_summary(const rc_client_t* client, uint32_t subset_id, rc_client_user_game_summary_t* summary);
/*****************************************************************************\
| Fetch Game Hashes |
\*****************************************************************************/
@@ -588,7 +582,7 @@ enum {
RC_EXPORT rc_client_leaderboard_list_t* RC_CCONV rc_client_create_leaderboard_list(rc_client_t* client, int grouping);
/**
* Destroys a list allocated by rc_client_create_leaderboard_list.
* Destroys a list allocated by rc_client_get_leaderboard_list.
*/
RC_EXPORT void RC_CCONV rc_client_destroy_leaderboard_list(rc_client_leaderboard_list_t* list);
+1 -1
View File
@@ -37,7 +37,7 @@
* #endif
*/
#if defined(__cplusplus) && !defined(CXX_BUILD)
#ifdef __cplusplus
#define RC_BEGIN_C_DECLS extern "C" {
#define RC_END_C_DECLS }
#else
-1
View File
@@ -154,7 +154,6 @@ typedef struct rc_hash_iterator {
uint8_t consoles[12];
int index;
const char* path;
void* userdata;
rc_hash_callbacks_t callbacks;
} rc_hash_iterator_t;
+36
View File
@@ -0,0 +1,36 @@
#ifndef RC_URL_H
#define RC_URL_H
#include "rc_export.h"
#include <stddef.h>
RC_BEGIN_C_DECLS
RC_EXPORT int RC_CCONV rc_url_award_cheevo(char* buffer, size_t size, const char* user_name, const char* login_token, unsigned cheevo_id, int hardcore, const char* game_hash);
RC_EXPORT int RC_CCONV rc_url_submit_lboard(char* buffer, size_t size, const char* user_name, const char* login_token, unsigned lboard_id, int value);
RC_EXPORT int RC_CCONV rc_url_get_lboard_entries(char* buffer, size_t size, unsigned lboard_id, unsigned first_index, unsigned count);
RC_EXPORT int RC_CCONV rc_url_get_lboard_entries_near_user(char* buffer, size_t size, unsigned lboard_id, const char* user_name, unsigned count);
RC_EXPORT int RC_CCONV rc_url_get_gameid(char* buffer, size_t size, const char* hash);
RC_EXPORT int RC_CCONV rc_url_get_patch(char* buffer, size_t size, const char* user_name, const char* login_token, unsigned gameid);
RC_EXPORT int RC_CCONV rc_url_get_badge_image(char* buffer, size_t size, const char* badge_name);
RC_EXPORT int RC_CCONV rc_url_login_with_password(char* buffer, size_t size, const char* user_name, const char* password);
RC_EXPORT int RC_CCONV rc_url_login_with_token(char* buffer, size_t size, const char* user_name, const char* login_token);
RC_EXPORT int RC_CCONV rc_url_get_unlock_list(char* buffer, size_t size, const char* user_name, const char* login_token, unsigned gameid, int hardcore);
RC_EXPORT int RC_CCONV rc_url_post_playing(char* buffer, size_t size, const char* user_name, const char* login_token, unsigned gameid);
RC_EXPORT int RC_CCONV rc_url_ping(char* url_buffer, size_t url_buffer_size, char* post_buffer, size_t post_buffer_size,
const char* user_name, const char* login_token, unsigned gameid, const char* rich_presence);
RC_END_C_DECLS
#endif /* RC_URL_H */
+3 -3
View File
@@ -273,17 +273,17 @@ static int rc_json_extract_html_error(rc_api_response_t* response, const rc_api_
iterator.json = server_response->body;
iterator.end = server_response->body + server_response->body_length;
/* assume the title contains the most appropriate message to display to the user */
/* if the title contains an HTTP status code(i.e "404 Not Found"), return the title */
if (rc_json_find_substring(&iterator, "<title>")) {
const char* title_start = iterator.json + 7;
if (rc_json_find_substring(&iterator, "</title>")) {
if (isdigit((int)*title_start) && rc_json_find_substring(&iterator, "</title>")) {
response->error_message = rc_buffer_strncpy(&response->buffer, title_start, iterator.json - title_start);
response->succeeded = 0;
return RC_INVALID_JSON;
}
}
/* title not found, return the first line of the response (up to 200 characters) */
/* title not found, or did not start with an error code, return the first line of the response */
iterator.json = server_response->body;
while (iterator.json < iterator.end && *iterator.json != '\n' &&
+1 -55
View File
@@ -100,7 +100,7 @@ int rc_api_process_fetch_code_notes_server_response(rc_api_fetch_code_notes_resp
if (!rc_json_get_required_string(&address_str, &response->response, &note_fields[0], "Address"))
return RC_MISSING_VALUE;
note->address = (uint32_t)strtoul(address_str, NULL, 16);
note->address = (unsigned)strtol(address_str, NULL, 16);
if (!rc_json_get_required_string(&note->note, &response->response, &note_fields[2], "Note"))
return RC_MISSING_VALUE;
@@ -419,60 +419,6 @@ void rc_api_destroy_update_leaderboard_response(rc_api_update_leaderboard_respon
rc_buffer_destroy(&response->response.buffer);
}
/* --- Update Rich Presence --- */
int rc_api_init_update_rich_presence_request(rc_api_request_t* request, const rc_api_update_rich_presence_request_t* api_params) {
return rc_api_init_update_rich_presence_request_hosted(request, api_params, &g_host);
}
int rc_api_init_update_rich_presence_request_hosted(rc_api_request_t* request,
const rc_api_update_rich_presence_request_t* api_params,
const rc_api_host_t* host) {
rc_api_url_builder_t builder;
rc_api_url_build_dorequest_url(request, host);
if (api_params->game_id == 0)
return RC_INVALID_STATE;
if (!api_params->script)
return RC_INVALID_STATE;
rc_url_builder_init(&builder, &request->buffer, 128);
if (!rc_api_url_build_dorequest(&builder, "submitrichpresence", api_params->username, api_params->api_token))
return builder.result;
rc_url_builder_append_unum_param(&builder, "g", api_params->game_id);
rc_url_builder_append_str_param(&builder, "d", api_params->script);
request->post_data = rc_url_builder_finalize(&builder);
request->content_type = RC_CONTENT_TYPE_URLENCODED;
return builder.result;
}
int rc_api_process_update_rich_presence_server_response(rc_api_update_rich_presence_response_t* response, const rc_api_server_response_t* server_response) {
int result;
rc_json_field_t fields[] = {
RC_JSON_NEW_FIELD("Success"),
RC_JSON_NEW_FIELD("Error"),
RC_JSON_NEW_FIELD("Code"),
};
memset(response, 0, sizeof(*response));
rc_buffer_init(&response->response.buffer);
result = rc_json_parse_server_response(&response->response, server_response, fields, sizeof(fields) / sizeof(fields[0]));
if (result != RC_OK || !response->response.succeeded)
return result;
return RC_OK;
}
void rc_api_destroy_update_rich_presence_response(rc_api_update_rich_presence_response_t* response) {
rc_buffer_destroy(&response->response.buffer);
}
/* --- Fetch Badge Range --- */
int rc_api_init_fetch_badge_range_request(rc_api_request_t* request, const rc_api_fetch_badge_range_request_t* api_params) {
+58 -128
View File
@@ -905,22 +905,11 @@ int rc_client_user_get_image_url(const rc_client_user_t* user, char buffer[], si
return rc_client_get_image_url(buffer, buffer_size, RC_IMAGE_TYPE_USER, user->display_name);
}
static void rc_client_subset_get_user_game_summary(const rc_client_t* client,
const rc_client_subset_info_t* subset, rc_client_user_game_summary_t* summary)
static void rc_client_subset_get_user_game_summary(const rc_client_subset_info_t* subset,
rc_client_user_game_summary_t* summary, const uint8_t unlock_bit)
{
rc_client_achievement_info_t* achievement = subset->achievements;
rc_client_achievement_info_t* stop = achievement + subset->public_.num_achievements;
time_t last_unlock_time = 0;
time_t last_progression_time = 0;
time_t first_win_time = 0;
int num_progression_achievements = 0;
int num_win_achievements = 0;
int num_unlocked_progression_achievements = 0;
const uint8_t unlock_bit = (client->state.hardcore) ?
RC_CLIENT_ACHIEVEMENT_UNLOCKED_HARDCORE : RC_CLIENT_ACHIEVEMENT_UNLOCKED_SOFTCORE;
rc_mutex_lock((rc_mutex_t*)&client->state.mutex); /* remove const cast for mutex access */
for (; achievement < stop; ++achievement) {
switch (achievement->public_.category) {
case RC_CLIENT_ACHIEVEMENT_CATEGORY_CORE:
@@ -930,28 +919,10 @@ static void rc_client_subset_get_user_game_summary(const rc_client_t* client,
if (achievement->public_.unlocked & unlock_bit) {
++summary->num_unlocked_achievements;
summary->points_unlocked += achievement->public_.points;
if (achievement->public_.unlock_time > last_unlock_time)
last_unlock_time = achievement->public_.unlock_time;
if (achievement->public_.type == RC_CLIENT_ACHIEVEMENT_TYPE_PROGRESSION) {
++num_unlocked_progression_achievements;
if (achievement->public_.unlock_time > last_progression_time)
last_progression_time = achievement->public_.unlock_time;
}
else if (achievement->public_.type == RC_CLIENT_ACHIEVEMENT_TYPE_WIN) {
if (first_win_time == 0 || achievement->public_.unlock_time < first_win_time)
first_win_time = achievement->public_.unlock_time;
}
}
if (achievement->public_.type == RC_CLIENT_ACHIEVEMENT_TYPE_PROGRESSION)
++num_progression_achievements;
else if (achievement->public_.type == RC_CLIENT_ACHIEVEMENT_TYPE_WIN)
++num_win_achievements;
if (achievement->public_.bucket == RC_CLIENT_ACHIEVEMENT_BUCKET_UNSUPPORTED)
if (achievement->public_.bucket == RC_CLIENT_ACHIEVEMENT_BUCKET_UNSUPPORTED) {
++summary->num_unsupported_achievements;
}
break;
@@ -963,18 +934,13 @@ static void rc_client_subset_get_user_game_summary(const rc_client_t* client,
continue;
}
}
rc_mutex_unlock((rc_mutex_t*)&client->state.mutex); /* remove const cast for mutex access */
if (summary->num_unlocked_achievements == summary->num_core_achievements)
summary->completed_time = last_unlock_time;
if ((first_win_time || num_win_achievements == 0) && num_unlocked_progression_achievements == num_progression_achievements)
summary->beaten_time = (first_win_time > last_progression_time) ? first_win_time : last_progression_time;
}
void rc_client_get_user_game_summary(const rc_client_t* client, rc_client_user_game_summary_t* summary)
{
const uint8_t unlock_bit = (client->state.hardcore) ?
RC_CLIENT_ACHIEVEMENT_UNLOCKED_HARDCORE : RC_CLIENT_ACHIEVEMENT_UNLOCKED_SOFTCORE;
if (!summary)
return;
@@ -983,47 +949,20 @@ void rc_client_get_user_game_summary(const rc_client_t* client, rc_client_user_g
return;
#ifdef RC_CLIENT_SUPPORTS_EXTERNAL
if (client->state.external_client) {
if (client->state.external_client->get_user_game_summary_v5) {
client->state.external_client->get_user_game_summary_v5(summary);
return;
}
if (client->state.external_client->get_user_game_summary) {
client->state.external_client->get_user_game_summary(summary);
return;
}
}
#endif
if (rc_client_is_game_loaded(client))
rc_client_subset_get_user_game_summary(client, client->game->subsets, summary);
}
void rc_client_get_user_subset_summary(const rc_client_t* client, uint32_t subset_id, rc_client_user_game_summary_t* summary)
{
if (!summary)
return;
memset(summary, 0, sizeof(*summary));
if (!client || !subset_id)
return;
#ifdef RC_CLIENT_SUPPORTS_EXTERNAL
if (client->state.external_client && client->state.external_client->get_user_subset_summary) {
client->state.external_client->get_user_subset_summary(subset_id, summary);
if (client->state.external_client && client->state.external_client->get_user_game_summary) {
client->state.external_client->get_user_game_summary(summary);
return;
}
#endif
if (rc_client_is_game_loaded(client)) {
const rc_client_subset_info_t* subset = client->game->subsets;
for (; subset; subset = subset->next) {
if (subset->public_.id == subset_id) {
rc_client_subset_get_user_game_summary(client, subset, summary);
break;
}
}
}
if (!rc_client_is_game_loaded(client))
return;
rc_mutex_lock((rc_mutex_t*)&client->state.mutex); /* remove const cast for mutex access */
rc_client_subset_get_user_game_summary(client->game->subsets, summary, unlock_bit);
rc_mutex_unlock((rc_mutex_t*)&client->state.mutex); /* remove const cast for mutex access */
}
typedef struct rc_client_fetch_all_user_progress_callback_data_t {
@@ -1437,34 +1376,29 @@ static uint32_t rc_client_subset_toggle_hardcore_achievements(rc_client_subset_i
break;
}
}
else {
achievement->public_.unlock_time = (active_bit == RC_CLIENT_ACHIEVEMENT_UNLOCKED_HARDCORE) ?
achievement->unlock_time_hardcore : achievement->unlock_time_softcore;
else if (achievement->public_.state == RC_CLIENT_ACHIEVEMENT_STATE_ACTIVE ||
achievement->public_.state == RC_CLIENT_ACHIEVEMENT_STATE_INACTIVE) {
if (achievement->public_.state == RC_CLIENT_ACHIEVEMENT_STATE_ACTIVE ||
achievement->public_.state == RC_CLIENT_ACHIEVEMENT_STATE_INACTIVE) {
/* if it's active despite being unlocked, and we're in encore mode, leave it active */
if (client->state.encore_mode) {
++active_count;
continue;
}
/* switch to inactive */
achievement->public_.state = RC_CLIENT_ACHIEVEMENT_STATE_UNLOCKED;
if (achievement->trigger && rc_trigger_state_active(achievement->trigger->state)) {
/* hide any active challenge indicators */
if (achievement->trigger->state == RC_TRIGGER_STATE_PRIMED) {
rc_client_event_t client_event;
memset(&client_event, 0, sizeof(client_event));
client_event.type = RC_CLIENT_EVENT_ACHIEVEMENT_CHALLENGE_INDICATOR_HIDE;
client_event.achievement = &achievement->public_;
client->callbacks.event_handler(&client_event, client);
}
achievement->trigger->state = RC_TRIGGER_STATE_TRIGGERED;
}
/* if it's active despite being unlocked, and we're in encore mode, leave it active */
if (client->state.encore_mode) {
++active_count;
continue;
}
achievement->public_.state = RC_CLIENT_ACHIEVEMENT_STATE_UNLOCKED;
achievement->public_.unlock_time = (active_bit == RC_CLIENT_ACHIEVEMENT_UNLOCKED_HARDCORE) ?
achievement->unlock_time_hardcore : achievement->unlock_time_softcore;
if (achievement->trigger && achievement->trigger->state == RC_TRIGGER_STATE_PRIMED) {
rc_client_event_t client_event;
memset(&client_event, 0, sizeof(client_event));
client_event.type = RC_CLIENT_EVENT_ACHIEVEMENT_CHALLENGE_INDICATOR_HIDE;
client_event.achievement = &achievement->public_;
client->callbacks.event_handler(&client_event, client);
}
if (achievement->trigger && rc_trigger_state_active(achievement->trigger->state))
achievement->trigger->state = RC_TRIGGER_STATE_TRIGGERED;
}
}
@@ -1794,9 +1728,7 @@ static void rc_client_activate_game(rc_client_load_state_t* load_state, rc_api_s
if (load_state->hash->hash[0] != '[') {
if (load_state->client->state.spectator_mode != RC_CLIENT_SPECTATOR_MODE_LOCKED) {
/* schedule the periodic ping */
rc_client_scheduled_callback_data_t* callback_data = (rc_client_scheduled_callback_data_t*)
rc_buffer_alloc(&load_state->game->buffer, sizeof(rc_client_scheduled_callback_data_t));
rc_client_scheduled_callback_data_t* callback_data = rc_buffer_alloc(&load_state->game->buffer, sizeof(rc_client_scheduled_callback_data_t));
memset(callback_data, 0, sizeof(*callback_data));
callback_data->callback = rc_client_ping;
callback_data->related_id = load_state->game->public_.id;
@@ -1836,9 +1768,7 @@ static void rc_client_dispatch_activate_game(struct rc_client_scheduled_callback
static void rc_client_queue_activate_game(rc_client_load_state_t* load_state)
{
rc_client_scheduled_callback_data_t* scheduled_callback_data =
(rc_client_scheduled_callback_data_t*)calloc(1, sizeof(rc_client_scheduled_callback_data_t));
rc_client_scheduled_callback_data_t* scheduled_callback_data = calloc(1, sizeof(rc_client_scheduled_callback_data_t));
if (!scheduled_callback_data) {
rc_client_load_error(load_state, RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY));
return;
@@ -1875,7 +1805,7 @@ static void rc_client_start_session_callback(const rc_api_server_response_t* ser
outstanding_requests = rc_client_end_load_state(load_state);
if (error_message) {
rc_client_load_error(load_state, result, error_message);
rc_client_load_error(callback_data, result, error_message);
}
else if (outstanding_requests < 0) {
/* previous load state was aborted, load_state was free'd */
@@ -1888,7 +1818,7 @@ static void rc_client_start_session_callback(const rc_api_server_response_t* ser
(rc_api_start_session_response_t*)malloc(sizeof(rc_api_start_session_response_t));
if (!load_state->start_session_response) {
rc_client_load_error(load_state, RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY));
rc_client_load_error(callback_data, RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY));
}
else {
/* safer to parse the response again than to try to copy it */
@@ -1981,7 +1911,7 @@ static void rc_client_copy_achievements(rc_client_load_state_t* load_state,
/* allocate the achievement array */
size = sizeof(rc_client_achievement_info_t) * num_achievements;
achievement = achievements = (rc_client_achievement_info_t*)rc_buffer_alloc(buffer, size);
achievement = achievements = rc_buffer_alloc(buffer, size);
memset(achievements, 0, size);
/* copy the achievement data */
@@ -2030,7 +1960,7 @@ static void rc_client_copy_achievements(rc_client_load_state_t* load_state,
achievement->public_.bucket = RC_CLIENT_ACHIEVEMENT_BUCKET_UNSUPPORTED;
}
else {
rc_buffer_consume(buffer, (const uint8_t*)preparse.parse.buffer, (uint8_t*)preparse.parse.buffer + preparse.parse.offset);
rc_buffer_consume(buffer, preparse.parse.buffer, (uint8_t*)preparse.parse.buffer + preparse.parse.offset);
}
rc_destroy_preparse_state(&preparse);
@@ -2123,7 +2053,7 @@ static void rc_client_copy_leaderboards(rc_client_load_state_t* load_state,
/* allocate the achievement array */
size = sizeof(rc_client_leaderboard_info_t) * num_leaderboards;
buffer = &load_state->game->buffer;
leaderboard = leaderboards = (rc_client_leaderboard_info_t*)rc_buffer_alloc(buffer, size);
leaderboard = leaderboards = rc_buffer_alloc(buffer, size);
memset(leaderboards, 0, size);
/* copy the achievement data */
@@ -2173,7 +2103,7 @@ static void rc_client_copy_leaderboards(rc_client_load_state_t* load_state,
leaderboard->public_.state = RC_CLIENT_LEADERBOARD_STATE_DISABLED;
}
else {
rc_buffer_consume(buffer, (const uint8_t*)preparse.parse.buffer, (uint8_t*)preparse.parse.buffer + preparse.parse.offset);
rc_buffer_consume(buffer, preparse.parse.buffer, (uint8_t*)preparse.parse.buffer + preparse.parse.offset);
}
rc_destroy_preparse_state(&preparse);
@@ -2688,7 +2618,7 @@ rc_client_game_hash_t* rc_client_find_game_hash(rc_client_t* client, const char*
}
if (!game_hash) {
game_hash = (rc_client_game_hash_t*)rc_buffer_alloc(&client->state.buffer, sizeof(rc_client_game_hash_t));
game_hash = rc_buffer_alloc(&client->state.buffer, sizeof(rc_client_game_hash_t));
memset(game_hash, 0, sizeof(*game_hash));
snprintf(game_hash->hash, sizeof(game_hash->hash), "%s", hash);
game_hash->game_id = RC_CLIENT_UNKNOWN_GAME_ID;
@@ -2866,14 +2796,16 @@ rc_hash_iterator_t* rc_client_get_load_state_hash_iterator(rc_client_t* client)
static void rc_client_log_hash_message_verbose(const char* message, const rc_hash_iterator_t* iterator)
{
const rc_client_load_state_t* load_state = (const rc_client_load_state_t*)iterator->userdata;
rc_client_load_state_t unused;
rc_client_load_state_t* load_state = (rc_client_load_state_t*)(((uint8_t*)iterator) - RC_OFFSETOF(unused, hash_iterator));
if (load_state->client->state.log_level >= RC_CLIENT_LOG_LEVEL_INFO)
rc_client_log_message(load_state->client, message);
}
static void rc_client_log_hash_message_error(const char* message, const rc_hash_iterator_t* iterator)
{
const rc_client_load_state_t* load_state = (const rc_client_load_state_t*)iterator->userdata;
rc_client_load_state_t unused;
rc_client_load_state_t* load_state = (rc_client_load_state_t*)(((uint8_t*)iterator) - RC_OFFSETOF(unused, hash_iterator));
if (load_state->client->state.log_level >= RC_CLIENT_LOG_LEVEL_ERROR)
rc_client_log_message(load_state->client, message);
}
@@ -2943,7 +2875,6 @@ rc_client_async_handle_t* rc_client_begin_identify_and_load_game(rc_client_t* cl
/* initialize the iterator */
rc_hash_initialize_iterator(&load_state->hash_iterator, file_path, data, data_size);
rc_hash_merge_callbacks(&load_state->hash_iterator, &client->callbacks.hash);
load_state->hash_iterator.userdata = load_state;
if (!load_state->hash_iterator.callbacks.verbose_message)
load_state->hash_iterator.callbacks.verbose_message = rc_client_log_hash_message_verbose;
@@ -3183,8 +3114,7 @@ static rc_client_async_handle_t* rc_client_begin_change_media_internal(rc_client
rc_api_request_t request;
int result;
if (game_hash->game_id != RC_CLIENT_UNKNOWN_GAME_ID || /* previously looked up */
game_hash->hash[0] == '[') { /* internal use - don't try to look up */
if (game_hash->game_id != RC_CLIENT_UNKNOWN_GAME_ID) {
rc_client_change_media_internal(client, game_hash, callback, callback_userdata);
return NULL;
}
@@ -3277,7 +3207,7 @@ static rc_client_game_info_t* rc_client_check_pending_media(rc_client_t* client,
}
/* still waiting for game data - don't call callback - it's queued */
if (pending_media)
if (pending_media)
return NULL;
return game;
@@ -3434,7 +3364,7 @@ const rc_client_game_t* rc_client_get_game_info(const rc_client_t* client)
if (client->state.external_client->get_game_info)
return rc_client_external_convert_v1_game(client, client->state.external_client->get_game_info());
}
}
#endif
return client->game ? &client->game->public_ : NULL;
@@ -4200,7 +4130,7 @@ static void rc_client_award_achievement_callback(const rc_api_server_response_t*
}
static void rc_client_award_achievement_server_call(rc_client_award_achievement_callback_data_t* ach_data)
{
{
rc_api_award_achievement_request_t api_params;
rc_api_request_t request;
int result;
@@ -4354,7 +4284,7 @@ const rc_client_leaderboard_t* rc_client_get_leaderboard_info(const rc_client_t*
if (leaderboard != NULL)
return &leaderboard->public_;
}
return NULL;
}
@@ -4438,7 +4368,7 @@ rc_client_leaderboard_list_t* rc_client_create_leaderboard_list(rc_client_t* cli
};
if (!client)
return (rc_client_leaderboard_list_t*)calloc(1, list_size);
return calloc(1, sizeof(rc_client_leaderboard_list_t));
#ifdef RC_CLIENT_SUPPORTS_EXTERNAL
if (client->state.external_client && client->state.external_client->create_leaderboard_list)
@@ -4446,7 +4376,7 @@ rc_client_leaderboard_list_t* rc_client_create_leaderboard_list(rc_client_t* cli
#endif
if (!client->game)
return (rc_client_leaderboard_list_t*)calloc(1, list_size);
return calloc(1, sizeof(rc_client_leaderboard_list_t));
memset(&bucket_counts, 0, sizeof(bucket_counts));
+1 -6
View File
@@ -35,7 +35,6 @@ typedef rc_client_async_handle_t* (RC_CCONV *rc_client_external_begin_load_subse
uint32_t subset_id, rc_client_callback_t callback, void* callback_userdata);
typedef const rc_client_game_t* (RC_CCONV *rc_client_external_get_game_info_func_t)(void);
typedef const rc_client_subset_t* (RC_CCONV *rc_client_external_get_subset_info_func_t)(uint32_t subset_id);
typedef void (RC_CCONV* rc_client_external_get_user_subset_summary_func_t)(uint32_t subset_id, rc_client_user_game_summary_t* summary);
typedef void (RC_CCONV *rc_client_external_get_user_game_summary_func_t)(rc_client_user_game_summary_t* summary);
typedef rc_client_async_handle_t* (RC_CCONV *rc_client_external_begin_change_media_func_t)(rc_client_t* client, const char* file_path,
const uint8_t* data, size_t data_size, rc_client_callback_t callback, void* callback_userdata);
@@ -140,13 +139,9 @@ typedef struct rc_client_external_t
/* VERSION 4 */
rc_client_external_set_int_func_t set_allow_background_memory_reads;
/* VERSION 5 */
rc_client_external_get_user_game_summary_func_t get_user_game_summary_v5;
rc_client_external_get_user_subset_summary_func_t get_user_subset_summary;
} rc_client_external_t;
#define RC_CLIENT_EXTERNAL_VERSION 5
#define RC_CLIENT_EXTERNAL_VERSION 4
void rc_client_add_game_hash(rc_client_t* client, const char* hash, uint32_t game_id);
void rc_client_load_unknown_game(rc_client_t* client, const char* hash);
-22
View File
@@ -144,28 +144,6 @@ typedef struct v3_rc_client_achievement_list_info_t {
rc_client_destroy_achievement_list_func_t destroy_func;
} v3_rc_client_achievement_list_info_t;
/* user_game_summary */
typedef struct v1_rc_client_user_game_summary_t {
uint32_t num_core_achievements;
uint32_t num_unofficial_achievements;
uint32_t num_unlocked_achievements;
uint32_t num_unsupported_achievements;
uint32_t points_core;
uint32_t points_unlocked;
} v1_rc_client_user_game_summary_t;
typedef struct v5_rc_client_user_game_summary_t {
uint32_t num_core_achievements;
uint32_t num_unofficial_achievements;
uint32_t num_unlocked_achievements;
uint32_t num_unsupported_achievements;
uint32_t points_core;
uint32_t points_unlocked;
time_t beaten_time;
time_t completed_time;
} v5_rc_client_user_game_summary_t;
RC_END_C_DECLS
#endif /* RC_CLIENT_EXTERNAL_CONVERSIONS_H */
-1
View File
@@ -78,7 +78,6 @@ static const rc_disallowed_setting_t _rc_disallowed_fbneo_settings[] = {
};
static const rc_disallowed_setting_t _rc_disallowed_fceumm_settings[] = {
{ "fceumm_game_genie", "!disabled" },
{ "fceumm_region", ",PAL,Dendy" },
{ NULL, NULL }
};
+2 -6
View File
@@ -343,12 +343,8 @@ rc_condset_t* rc_parse_condset(const char** memaddr, rc_parse_state_t* parse) {
if (parse->buffer) {
classification = rc_classify_condition(&condition);
if (classification == RC_CONDITION_CLASSIFICATION_COMBINING) {
if (combining_classification == RC_CONDITION_CLASSIFICATION_COMBINING) {
if (**memaddr == '_')
combining_classification = rc_find_next_classification(&(*memaddr)[1]); /* skip over '_' */
else
combining_classification = RC_CONDITION_CLASSIFICATION_OTHER;
}
if (combining_classification == RC_CONDITION_CLASSIFICATION_COMBINING)
combining_classification = rc_find_next_classification(&(*memaddr)[1]); /* skip over '_' */
classification = combining_classification;
}
+2 -3
View File
@@ -971,10 +971,9 @@ static const rc_memory_regions_t rc_memory_regions_wasm4 = { _rc_memory_regions_
/* https://wiibrew.org/wiki/Memory_map */
static const rc_memory_region_t _rc_memory_regions_wii[] = {
{ 0x00000000U, 0x017FFFFF, 0x80000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" },
{ 0x01800000U, 0x0FFFFFFF, 0x81800000U, RC_MEMORY_TYPE_UNUSED, "Unused" },
{ 0x10000000U, 0x13FFFFFF, 0x90000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }
{ 0x01800000U, 0x057FFFFF, 0x90000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }
};
static const rc_memory_regions_t rc_memory_regions_wii = { _rc_memory_regions_wii, 3 };
static const rc_memory_regions_t rc_memory_regions_wii = { _rc_memory_regions_wii, 2 };
/* ===== WonderSwan ===== */
/* http://daifukkat.su/docs/wsman/#ovr_memmap */
+1 -1
View File
@@ -328,7 +328,7 @@ static float rc_build_float(uint32_t mantissa_bits, int32_t exponent, int sign)
if (mantissa_bits == 0) {
/* infinity */
#ifdef INFINITY /* INFINITY and NAN #defines require C99 */
dbl = (double)INFINITY;
dbl = INFINITY;
#else
dbl = -log(0.0);
#endif
+3 -3
View File
@@ -380,6 +380,9 @@ int rc_operand_is_float_memref(const rc_operand_t* self) {
if (!rc_operand_is_memref(self))
return 0;
if (self->type == RC_OPERAND_RECALL)
return rc_memsize_is_float(self->memref_access_type);
if (self->value.memref->value.memref_type == RC_MEMREF_TYPE_MODIFIED_MEMREF) {
const rc_modified_memref_t* memref = (const rc_modified_memref_t*)self->value.memref;
if (memref->modifier_type != RC_OPERATOR_INDIRECT_READ)
@@ -431,9 +434,6 @@ int rc_operand_is_float(const rc_operand_t* self) {
if (self->type == RC_OPERAND_FP)
return 1;
if (self->type == RC_OPERAND_RECALL)
return rc_memsize_is_float(self->size);
return rc_operand_is_float_memref(self);
}
+11 -28
View File
@@ -174,8 +174,8 @@ static uint32_t rc_scale_value(uint32_t value, uint8_t oper, const rc_operand_t*
case RC_OPERATOR_SUB:
{
const uint32_t op_max = (operand->type == RC_OPERAND_CONST) ? operand->value.num : 0;
if (value >= op_max)
const uint32_t op_max = (operand->type == RC_OPERAND_CONST) ? operand->value.num : rc_max_value(operand);
if (value > op_max)
return value - op_max;
return 0xFFFFFFFF;
@@ -351,11 +351,11 @@ static int rc_validate_condset_internal(const rc_condset_t* condset, char result
snprintf(result, result_size, "Condition %d: Using pointer from previous frame", index);
return 0;
}
if (rc_operand_is_float(operand1) || rc_operand_is_float(&cond->operand2)) {
if (rc_operand_is_float(&cond->operand1) || rc_operand_is_float(&cond->operand2)) {
snprintf(result, result_size, "Condition %d: Using non-integer value in AddAddress calcuation", index);
return 0;
}
if (rc_operand_type_is_transform(operand1->type) && cond->oper != RC_OPERATOR_MULT) {
if (rc_operand_type_is_transform(cond->operand1.type)) {
snprintf(result, result_size, "Condition %d: Using transformed value in AddAddress calcuation", index);
return 0;
}
@@ -721,7 +721,7 @@ static int rc_validate_comparison_overlap(int comparison1, uint32_t value1, int
}
static int rc_validate_conflicting_conditions(const rc_condset_t* conditions, const rc_condset_t* compare_conditions,
int has_hits, const char* prefix, const char* compare_prefix, char result[], const size_t result_size)
const char* prefix, const char* compare_prefix, char result[], const size_t result_size)
{
int comparison1, comparison2;
uint32_t value1, value2;
@@ -895,15 +895,7 @@ static int rc_validate_conflicting_conditions(const rc_condset_t* conditions, co
{
/* only ever report the redundancy on the non-ResetIf condition. The ResetIf is allowed to
* fire when the non-ResetIf condition is not true. */
if (has_hits)
continue;
}
else if (condition->type == RC_CONDITION_RESET_IF && compare_condition->type != RC_CONDITION_RESET_IF)
{
/* if the ResetIf condition is more restrictive than the non-ResetIf condition,
and there aren't any hits to clear, ignore it */
if (has_hits)
continue;
continue;
}
else if (compare_condition->type == RC_CONDITION_MEASURED_IF || condition->type == RC_CONDITION_MEASURED_IF)
{
@@ -955,21 +947,12 @@ static int rc_validate_trigger_internal(const rc_trigger_t* trigger, char result
{
const rc_condset_t* alt;
int index;
int has_hits = (trigger->requirement && trigger->requirement->num_hittarget_conditions > 0);
if (!has_hits) {
for (alt = trigger->alternative; alt; alt = alt->next) {
if (alt->num_hittarget_conditions > 0) {
has_hits = 1;
break;
}
}
}
if (!trigger->alternative) {
if (!rc_validate_condset_internal(trigger->requirement, result, result_size, console_id, max_address))
return 0;
return rc_validate_conflicting_conditions(trigger->requirement, trigger->requirement, has_hits, "", "", result, result_size);
return rc_validate_conflicting_conditions(trigger->requirement, trigger->requirement, "", "", result, result_size);
}
snprintf(result, result_size, "Core ");
@@ -977,7 +960,7 @@ static int rc_validate_trigger_internal(const rc_trigger_t* trigger, char result
return 0;
/* compare core to itself */
if (!rc_validate_conflicting_conditions(trigger->requirement, trigger->requirement, has_hits, "Core", "Core", result, result_size))
if (!rc_validate_conflicting_conditions(trigger->requirement, trigger->requirement, "Core", "Core", result, result_size))
return 0;
index = 1;
@@ -989,15 +972,15 @@ static int rc_validate_trigger_internal(const rc_trigger_t* trigger, char result
/* compare alt to itself */
snprintf(altname, sizeof(altname), "Alt%d", index);
if (!rc_validate_conflicting_conditions(alt, alt, has_hits, altname, altname, result, result_size))
if (!rc_validate_conflicting_conditions(alt, alt, altname, altname, result, result_size))
return 0;
/* compare alt to core */
if (!rc_validate_conflicting_conditions(trigger->requirement, alt, has_hits, "Core", altname, result, result_size))
if (!rc_validate_conflicting_conditions(trigger->requirement, alt, "Core", altname, result, result_size))
return 0;
/* compare core to alt */
if (!rc_validate_conflicting_conditions(alt, trigger->requirement, has_hits, altname, "Core", result, result_size))
if (!rc_validate_conflicting_conditions(alt, trigger->requirement, altname, "Core", result, result_size))
return 0;
}
+2 -3
View File
@@ -48,9 +48,8 @@ static void rc_alloc_helper_variable_memref_value(rc_richpresence_display_part_t
condset = value->conditions;
if (condset && !condset->next) {
/* single value - if it's a single Measured clause (including any AddSource/AddAddress helpers), we can
* simplify to a memref. If there are supporting clauses like MeasuredIf or ResetIf, we can't */
if (condset->num_measured_conditions == 1 &&
/* single value - if it's only "measured" and "indirect" conditions, we can simplify to a memref */
if (condset->num_measured_conditions &&
!condset->num_pause_conditions && !condset->num_reset_conditions &&
!condset->num_other_conditions && !condset->num_hittarget_conditions) {
rc_condition_t* condition = condset->conditions;
+3 -3
View File
@@ -36,7 +36,7 @@ rc_runtime_t* rc_runtime_alloc(void) {
rc_runtime_event_handler_t unused = &rc_runtime_natvis_helper;
(void)unused;
self = (rc_runtime_t*)malloc(sizeof(rc_runtime_t));
self = malloc(sizeof(rc_runtime_t));
if (self) {
rc_runtime_init(self);
@@ -307,7 +307,7 @@ int rc_runtime_activate_lboard(rc_runtime_t* self, uint32_t id, const char* mema
rc_lboard_t* lboard;
rc_preparse_state_t preparse;
rc_runtime_lboard_t* runtime_lboard;
int32_t size;
int size;
uint32_t i;
(void)unused_L;
@@ -797,7 +797,7 @@ void rc_runtime_invalidate_address(rc_runtime_t* self, uint32_t address) {
} while (memref_list);
}
void rc_runtime_validate_addresses(rc_runtime_t* self, rc_runtime_event_handler_t event_handler,
void rc_runtime_validate_addresses(rc_runtime_t* self, rc_runtime_event_handler_t event_handler,
rc_runtime_validate_address_t validate_handler) {
int num_invalid = 0;
rc_memref_list_t* memref_list = &self->memrefs->memrefs;
+1 -1
View File
@@ -920,7 +920,7 @@ uint32_t rc_runtime_progress_size(const rc_runtime_t* runtime, void* unused_L)
int rc_runtime_serialize_progress(void* buffer, const rc_runtime_t* runtime, void* unused_L)
{
return rc_runtime_serialize_progress_sized((uint8_t*)buffer, 0xFFFFFFFF, runtime, unused_L);
return rc_runtime_serialize_progress_sized(buffer, 0xFFFFFFFF, runtime, unused_L);
}
int rc_runtime_serialize_progress_sized(uint8_t* buffer, uint32_t buffer_size, const rc_runtime_t* runtime, void* unused_L)
+13 -27
View File
@@ -61,41 +61,27 @@ static void rc_parse_legacy_value(rc_value_t* self, const char** memaddr, rc_par
char buffer[64] = "A:";
const char* buffer_ptr;
char* ptr;
int done;
char c;
/* convert legacy format into condset */
next_clause = &self->conditions;
do {
num_measured_conditions = 0;
/* count the number of joiners and add one to determine the number of clauses. */
done = 0;
num_measured_conditions = 1;
buffer_ptr = *memaddr;
do {
switch (*buffer_ptr++) {
case '_': /* add next */
++num_measured_conditions;
buffer[0] = 'A'; /* reset to AddSource */
break;
case '*': /* multiply */
if (*buffer_ptr == '-') {
/* multiplication by a negative number will convert to SubSource */
++buffer_ptr;
buffer[0] = 'B';
}
break;
case '\0': /* end of string */
case '$': /* maximum of */
case ':': /* end of leaderboard clause */
case ')': /* end of rich presence macro */
done = 1;
break;
default: /* assume everything else is valid - bad stuff will be filtered out later */
break;
while ((c = *buffer_ptr++) && c != '$') {
if (c == '_') {
++num_measured_conditions;
buffer[0] = 'A'; /* reset to AddSource */
}
} while (!done);
else if (c == '*' && *buffer_ptr == '-') {
/* multiplication by a negative number will convert to SubSource */
++buffer_ptr;
buffer[0] = 'B';
}
}
/* if last condition is SubSource, we'll need to add a dummy condition for the Measured */
if (buffer[0] == 'B')
+1 -5
View File
@@ -480,7 +480,6 @@ static int rc_hash_file_from_buffer(char hash[33], uint32_t console_id, const rc
rc_hash_iterator_t buffered_file_iterator;
memset(&buffered_file_iterator, 0, sizeof(buffered_file_iterator));
memcpy(&buffered_file_iterator.callbacks, &iterator->callbacks, sizeof(iterator->callbacks));
buffered_file_iterator.userdata = iterator->userdata;
buffered_file_iterator.callbacks.filereader.open = rc_file_open_buffered_file;
buffered_file_iterator.callbacks.filereader.close = rc_file_close_buffered_file;
@@ -651,7 +650,6 @@ int rc_hash_buffered_file(char hash[33], uint32_t console_id, const rc_hash_iter
rc_hash_iterator_t buffer_iterator;
memset(&buffer_iterator, 0, sizeof(buffer_iterator));
memcpy(&buffer_iterator.callbacks, &iterator->callbacks, sizeof(iterator->callbacks));
buffer_iterator.userdata = iterator->userdata;
buffer_iterator.path = iterator->path;
buffer_iterator.buffer = buffer;
buffer_iterator.buffer_size = (size_t)size;
@@ -775,7 +773,6 @@ static int rc_hash_generate_from_playlist(char hash[33], uint32_t console_id, co
memset(&first_file_iterator, 0, sizeof(first_file_iterator));
memcpy(&first_file_iterator.callbacks, &iterator->callbacks, sizeof(iterator->callbacks));
first_file_iterator.userdata = iterator->userdata;
first_file_iterator.path = disc_path; /* rc_hash_destory_iterator will free */
result = rc_hash_from_file(hash, console_id, &first_file_iterator);
@@ -1296,8 +1293,7 @@ static void rc_hash_initialize_iterator_from_path(rc_hash_iterator_t* iterator,
}
/* find the handler for the extension */
handler = (const rc_hash_iterator_ext_handler_entry_t*)
bsearch(&search, handlers, num_handlers, sizeof(*handler), rc_hash_iterator_find_handler);
handler = bsearch(&search, handlers, num_handlers, sizeof(*handler), rc_hash_iterator_find_handler);
if (handler) {
handler->handler(iterator, handler->data);
} else {
+1 -5
View File
@@ -21758,8 +21758,6 @@ SLES-52954:
SLES-52955:
name: "Deadly Strike"
region: "PAL-E"
roundModes:
eeDivRoundMode: 3 # Fixes grid like pattern.
SLES-52956:
name: "Action Girlz Racing"
region: "PAL-E"
@@ -30298,7 +30296,7 @@ SLES-55674:
region: "PAL-F-G"
SLES-55675:
name: "Pro Evolution Soccer 2014"
region: "PAL-GR-I"
region: "PAL-G-I"
SLES-55676:
name: "Pro Evolution Soccer 2014"
region: "PAL-P-S"
@@ -38930,8 +38928,6 @@ SLPM-62459:
name-en: "Simple 2000 Series Vol. 16 - Sengoku vs. Gendai"
region: "NTSC-J"
compat: 5
roundModes:
eeDivRoundMode: 3 # Fixes grid like pattern.
SLPM-62460:
name: "SuperLite2000 シミュレーション 箱庭鉄道 ~ブルートレイン・特急編~"
name-sort: "すーぱーらいと 2000 しみゅれーしょん はこにわてつどう ぶるーとれいんとっきゅうへん"
Binary file not shown.
+8 -13
View File
@@ -191,7 +191,6 @@
0300004112000000e500000000000000,Elecom JC-U909Z,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b8,x:b3,y:b4,platform:Windows,
03000041120000001050000000000000,Elecom JC-U911,a:b1,b:b2,back:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,start:b0,x:b4,y:b5,platform:Windows,
030000006e0500000520000000000000,Elecom P301U PlayStation Controller Adapter,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows,
03000000250900000218000000000000,Elecom PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
03000000411200004450000000000000,Elecom U1012,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows,
030000006e0500000320000000000000,Elecom U3613M,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows,
030000006e0500000e20000000000000,Elecom U3912T,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows,
@@ -253,7 +252,6 @@
03000000300f00000b01000000000000,GGE909 Recoil,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
03000000f0250000c283000000000000,Gioteck PlayStation Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
03000000f025000021c1000000000000,Gioteck PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
03000000f025000021c1000010010000,Gioteck PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
03000000f025000031c1000000000000,Gioteck PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
03000000f0250000c383000000000000,Gioteck VX2 PlayStation Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
03000000f0250000c483000000000000,Gioteck VX2 PlayStation Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
@@ -480,7 +478,6 @@
030000001008000001e5000000000000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Windows,
03000000050b00000045000000000000,Nexus,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Windows,
03000000152000000182000000000000,NGDS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Windows,
03000000ec110000e1a7000000000000,Nintendo Switch,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
030000007e0500006920000000000000,Nintendo Switch 2 Pro Controller,a:b0,b:b1,back:b14,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b12,leftstick:b15,lefttrigger:b13,leftx:a0,lefty:a1~,misc1:b17,misc2:b20,paddle1:b18,paddle2:b19,rightshoulder:b4,rightstick:b7,righttrigger:b5,rightx:a2,righty:a3~,start:b6,x:b2,y:b3,platform:Windows,
030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
030000000d0500000308000000000000,Nostromo N45,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Windows,
@@ -538,6 +535,7 @@
03000000120c00001cf1000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000120c0000f90e000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000250900000118000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
03000000250900000218000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
03000000250900000500000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows,
030000004c0500006802000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b10,lefttrigger:a3~,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:a4~,rightx:a2,righty:a5,start:b8,x:b3,y:b0,platform:Windows,
030000004f1f00000800000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
@@ -683,7 +681,6 @@
03000000c01100004150000000000000,Sanwa Micro Grip Pro,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,
03000000c01100004450000000000000,Sanwa Online Grip,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b11,righttrigger:b9,rightx:a3,righty:a2,start:b14,x:b3,y:b4,platform:Windows,
03000000730700000401000000000000,Sanwa PlayOnline Mobile,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Windows,
030000009d0d00001130000000000000,Sanwa PlayStation Adapter,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
03000000830500006120000000000000,Sanwa Smart Grip II,a:b0,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,x:b1,y:b3,platform:Windows,
03000000c01100000051000000000000,Satechi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
030000004f04000028b3000000000000,Score A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
@@ -844,7 +841,6 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000007d0400000340000000000000,Xterminator Digital Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:-a4,lefttrigger:+a4,leftx:a0,lefty:a1,paddle1:b7,paddle2:b6,rightshoulder:b5,rightstick:b9,righttrigger:b2,rightx:a3,righty:a5,start:b8,x:b3,y:b4,platform:Windows,
030000002c3600000100000000000000,Yawman Arrow,+rightx:h0.2,+righty:h0.4,-rightx:h0.8,-righty:h0.1,a:b4,b:b5,back:b6,dpdown:b15,dpleft:b14,dpright:b16,dpup:b13,leftshoulder:b10,leftstick:b0,lefttrigger:-a4,leftx:a0,lefty:a1,paddle1:b11,paddle2:b12,rightshoulder:b8,rightstick:b9,righttrigger:+a4,start:b3,x:b1,y:b2,platform:Windows,
03000000790000004f18000000000000,ZDT Android Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000073500000400000000000000,Zenaim Arcade Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
03000000120c00000500000000000000,Zeroplus Adapter,a:b2,b:b1,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b0,righttrigger:b5,rightx:a3,righty:a2,start:b8,x:b3,y:b0,platform:Windows,
03000000120c0000101e000000000000,Zeroplus P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
@@ -1022,7 +1018,6 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000632500007505000000020000,NeoGeo mini PAD Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b2,y:b3,platform:Mac OS X,
03000000921200004b46000003020000,NES 2-port Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Mac OS X,
030000001008000001e5000006010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Mac OS X,
03000000ec110000e1a7000001010000,Nintendo Switch,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
030000007e0500006920000001010000,Nintendo Switch 2 Pro Controller,a:b0,b:b1,back:b14,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b12,leftstick:b15,lefttrigger:b13,leftx:a0,lefty:a1~,misc1:b17,misc2:b20,paddle1:b18,paddle2:b19,rightshoulder:b4,rightstick:b7,righttrigger:b5,rightx:a2,righty:a3~,start:b6,x:b2,y:b3,platform:Mac OS X,
030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
030000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
@@ -1295,7 +1290,6 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000e82000006058000001010000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
03000000af1e00002400000010010000,Clockwork Pi DevTerm,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b9,x:b3,y:b0,platform:Linux,
030000000b0400003365000000010000,Competition Pro,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Linux,
03000000632500007a05000001020000,Cosmic Byte Ares Wired Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
03000000260900008888000000010000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Linux,
03000000a306000022f6000011010000,Cyborg V3 Rumble,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux,
030000005e0400008e02000002010000,Data Frog S80,a:b1,b:b0,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux,
@@ -1317,7 +1311,6 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
05000000151900004000000001000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b14,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
030000007e0500003703000000000000,GameCube Adapter,a:b0,b:b1,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux,
19000000030000000300000002030000,GameForce Controller,a:b1,b:b0,back:b8,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b14,lefttrigger:b6,leftx:a1,lefty:a0,rightshoulder:b5,rightstick:b15,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
03000000373500000b10000019010000,GameSir Cyclone 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000ac0500005b05000010010000,GameSir G3w,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
03000000bc2000000055000011010000,GameSir G3w,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000558500001b06000010010000,GameSir G4 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
@@ -1510,8 +1503,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000790000004518000010010000,Nexilux GameCube Controller Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
030000001008000001e5000010010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Linux,
060000007e0500003713000000000000,Nintendo 3DS,a:b0,b:b1,back:b8,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux,
030000007e0500003703000000016800,Nintendo GameCube Controller,a:b0,b:b2,dpdown:b6,dpleft:b4,dpright:b5,dpup:b7,lefttrigger:a4,leftx:a0,lefty:a1~,rightshoulder:b9,righttrigger:a5,rightx:a2,righty:a3~,start:b8,x:b1,y:b3,platform:Linux,
03000000790000004618000010010000,Nintendo GameCube Controller Adapter,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a5~,righty:a2~,start:b9,x:b2,y:b3,platform:Linux,
03000000ec110000e1a7000010010000,Nintendo Switch,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
030000007e0500006920000011010000,Nintendo Switch 2 Pro Controller,a:b0,b:b1,back:b14,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b12,leftstick:b15,lefttrigger:b13,leftx:a0,lefty:a1~,misc1:b17,misc2:b20,paddle1:b18,paddle2:b19,rightshoulder:b4,rightstick:b7,righttrigger:b5,rightx:a2,righty:a3~,start:b6,x:b2,y:b3,platform:Linux,
060000004e696e74656e646f20537700,Nintendo Switch Combined Joy-Cons,a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,
060000007e0500000620000000000000,Nintendo Switch Combined Joy-Cons,a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,
@@ -1663,6 +1656,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000321500000b10000011010000,Razer Wolverine PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
0300000032150000140a000001010000,Razer Wolverine Ultimate Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000000d0f0000c100000010010000,Retro Bit Legacy16,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b12,leftshoulder:b4,lefttrigger:b6,misc1:b13,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
030000000d0f0000c100000072056800,Retro Bit Legacy16,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b5,leftshoulder:b9,lefttrigger:+a4,misc1:b11,rightshoulder:b10,righttrigger:+a5,start:b6,x:b3,y:b2,platform:Linux,
03000000790000001100000010010000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Linux,
0300000003040000c197000011010000,Retrode Adapter,a:b0,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Linux,
190000004b4800000111000000010000,RetroGame Joypad,a:b1,b:b0,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
@@ -1698,10 +1692,11 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000790000001100000011010000,Sega Saturn,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b4,start:b9,x:b0,y:b3,platform:Linux,
03000000790000002201000011010000,Sega Saturn,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,start:b9,x:b2,y:b3,platform:Linux,
03000000b40400000a01000000010000,Sega Saturn,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Linux,
03000000632500002305000010010000,ShanWan Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
03000000632500002605000010010000,ShanWan Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000632500007505000010010000,ShanWan Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
03000000bc2000000055000010010000,ShanWan Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000632500002305000010010000,Shanwan Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
03000000632500002605000010010000,Shanwan Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000632500007505000010010000,Shanwan Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
03000000bc2000000055000010010000,Shanwan Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000f025000021c1000010010000,Shanwan Gioteck PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
03000000341a00000908000010010000,SL6566,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
030000004b2900000430000011000000,Snakebyte Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
050000004c050000cc09000001000000,Sony DualShock 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
+36 -34
View File
@@ -305,64 +305,64 @@ PS_OUTPUT ps_convert_rgb5a1_8i(PS_INPUT input)
uint2 pos = uint2(input.p.xy);
// Collapse separate R G B A areas into their base pixel
uint2 column = (pos & ~uint2(0u, 3u)) / uint2(1u, 2u);
uint2 column = (pos & ~uint2(0u, 3u)) / uint2(1,2);
uint2 subcolumn = (pos & uint2(0u, 1u));
column.x -= (column.x / 128u) * 64u;
column.y += (column.y / 32u) * 32u;
column.x -= (column.x / 128) * 64;
column.y += (column.y / 32) * 32;
uint PSM = uint(DOFFSET);
// Deal with swizzling differences
if ((PSM & 0x8u) != 0u) // PSMCT16S
if ((PSM & 0x8) != 0) // PSMCT16S
{
if ((pos.x & 32u) != 0u)
if ((pos.x & 32) != 0)
{
column.y += 32u; // 4 columns high times 4 to get bottom 4 blocks
column.x &= ~32u;
column.y += 32; // 4 columns high times 4 to get bottom 4 blocks
column.x &= ~32;
}
if ((pos.x & 64u) != 0u)
if ((pos.x & 64) != 0)
{
column.x -= 32u;
column.x -= 32;
}
if (((pos.x & 16u) != 0u) != ((pos.y & 16u) != 0u))
if (((pos.x & 16) != 0) != ((pos.y & 16) != 0))
{
column.x ^= 16u;
column.y ^= 8u;
column.x ^= 16;
column.y ^= 8;
}
if ((PSM & 0x30u) != 0u) // PSMZ16S - Untested but hopefully ok if anything uses it.
if ((PSM & 0x30) != 0) // PSMZ16S - Untested but hopefully ok if anything uses it.
{
column.x ^= 32u;
column.y ^= 16u;
column.x ^= 32;
column.y ^= 16;
}
}
else // PSMCT16
{
if ((pos.y & 32u) != 0u)
if ((pos.y & 32) != 0)
{
column.y -= 16u;
column.x += 32u;
column.y -= 16;
column.x += 32;
}
if ((pos.x & 96u) != 0u)
if ((pos.x & 96) != 0)
{
uint multi = (pos.x & 96u) / 32u;
column.y += 16u * multi; // 4 columns high times 4 to get bottom 4 blocks
column.x -= (pos.x & 96u);
uint multi = (pos.x & 96) / 32;
column.y += 16 * multi; // 4 columns high times 4 to get bottom 4 blocks
column.x -= (pos.x & 96);
}
if (((pos.x & 16u) != 0u) != ((pos.y & 16) != 0))
if (((pos.x & 16) != 0) != ((pos.y & 16) != 0))
{
column.x ^= 16u;
column.y ^= 8u;
column.x ^= 16;
column.y ^= 8;
}
if ((PSM & 0x30u) != 0u) // PSMZ16 - Untested but hopefully ok if anything uses it.
if ((PSM & 0x30) != 0) // PSMZ16 - Untested but hopefully ok if anything uses it.
{
column.x ^= 32u;
column.y ^= 32u;
column.x ^= 32;
column.y ^= 32;
}
}
@@ -371,10 +371,10 @@ PS_OUTPUT ps_convert_rgb5a1_8i(PS_INPUT input)
// Compensate for potentially differing page pitch.
uint SBW = uint(EMODA);
uint DBW = uint(EMODC);
uint2 block_xy = coord / uint2(64u, 64u);
uint block_num = (block_xy.y * (DBW / 128u)) + block_xy.x;
uint2 block_offset = uint2((block_num % (SBW / 64u)) * 64u, (block_num / (SBW / 64u)) * 64u);
coord = (coord % uint2(64u, 64u)) + block_offset;
uint2 block_xy = coord / uint2(64,64);
uint block_num = (block_xy.y * (DBW / 128)) + block_xy.x;
uint2 block_offset = uint2((block_num % (SBW / 64)) * 64, (block_num / (SBW / 64)) * 64);
coord = (coord % uint2(64, 64)) + block_offset;
// Apply offset to cols 1 and 2
uint is_col23 = pos.y & 4u;
@@ -394,16 +394,18 @@ PS_OUTPUT ps_convert_rgb5a1_8i(PS_INPUT input)
{
uint red = (denorm_c.r >> 3) & 0x1Fu;
uint green = (denorm_c.g >> 3) & 0x1Fu;
float sel0 = (float)(((green << 5) | red) & 0xFF) / 255.0f;
output.c = (float4)(((float)(((green << 5) | red) & 0xFFu)) / 255.0f);
output.c = (float4)(sel0);
}
else
{
uint green = (denorm_c.g >> 3) & 0x1Fu;
uint blue = (denorm_c.b >> 3) & 0x1Fu;
uint alpha = denorm_c.a & 0x80u;
float sel0 = (float)((alpha | (blue << 2) | (green >> 3)) & 0xFF) / 255.0f;
output.c = (float4)(((float)((alpha | (blue << 2) | (green >> 3)) & 0xFFu)) / 255.0f);
output.c = (float4)(sel0);
}
return output;
}
+1 -1
View File
@@ -37,7 +37,7 @@ float4 ContrastSaturationBrightness(float4 color) // Ported to HLSL
float3 conColor = lerp(AvgLumin, satColor, con);
float3 csb = conColor;
csb = exp2(log2(csb) * (1.0 / gam));
csb = pow(csb, 1.0 / gam);
color.rgb = csb;
return color;
}
+32 -30
View File
@@ -258,62 +258,62 @@ void ps_convert_rgb5a1_8i()
uvec2 pos = uvec2(gl_FragCoord.xy);
// Collapse separate R G B A areas into their base pixel
uvec2 column = (pos & ~uvec2(0u, 3u)) / uvec2(1u, 2u);
uvec2 column = (pos & ~uvec2(0u, 3u)) / uvec2(1,2);
uvec2 subcolumn = (pos & uvec2(0u, 1u));
column.x -= (column.x / 128u) * 64u;
column.y += (column.y / 32u) * 32u;
column.x -= (column.x / 128) * 64;
column.y += (column.y / 32) * 32;
// Deal with swizzling differences
if ((PSM & 0x8u) != 0u) // PSMCT16S
if ((PSM & 0x8) != 0) // PSMCT16S
{
if ((pos.x & 32u) != 0u)
if ((pos.x & 32) != 0)
{
column.y += 32u; // 4 columns high times 4 to get bottom 4 blocks
column.x &= ~32u;
column.y += 32; // 4 columns high times 4 to get bottom 4 blocks
column.x &= ~32;
}
if ((pos.x & 64u) != 0u)
if ((pos.x & 64) != 0)
{
column.x -= 32u;
column.x -= 32;
}
if (((pos.x & 16u) != 0u) != ((pos.y & 16u) != 0u))
if (((pos.x & 16) != 0) != ((pos.y & 16) != 0))
{
column.x ^= 16u;
column.y ^= 8u;
column.x ^= 16;
column.y ^= 8;
}
if ((PSM & 0x30u) != 0u) // PSMZ16S - Untested but hopefully ok if anything uses it.
if ((PSM & 0x30) != 0) // PSMZ16S - Untested but hopefully ok if anything uses it.
{
column.x ^= 32u;
column.y ^= 16u;
column.x ^= 32;
column.y ^= 16;
}
}
else // PSMCT16
{
if ((pos.y & 32u) != 0u)
if ((pos.y & 32) != 0)
{
column.y -= 16u;
column.x += 32u;
column.y -= 16;
column.x += 32;
}
if ((pos.x & 96u) != 0u)
if ((pos.x & 96) != 0)
{
uint multi = (pos.x & 96u) / 32u;
column.y += 16u * multi; // 4 columns high times 4 to get bottom 4 blocks
column.x -= (pos.x & 96u);
uint multi = (pos.x & 96) / 32;
column.y += 16 * multi; // 4 columns high times 4 to get bottom 4 blocks
column.x -= (pos.x & 96);
}
if (((pos.x & 16u) != 0u) != ((pos.y & 16u) != 0u))
if (((pos.x & 16) != 0) != ((pos.y & 16) != 0))
{
column.x ^= 16u;
column.y ^= 8u;
column.x ^= 16;
column.y ^= 8;
}
if ((PSM & 0x30u) != 0u) // PSMZ16 - Untested but hopefully ok if anything uses it.
if ((PSM & 0x30) != 0) // PSMZ16 - Untested but hopefully ok if anything uses it.
{
column.x ^= 32u;
column.y ^= 32u;
column.x ^= 32;
column.y ^= 32;
}
}
uvec2 coord = column | subcolumn;
@@ -342,16 +342,18 @@ void ps_convert_rgb5a1_8i()
{
uint red = (denorm_c.r >> 3) & 0x1Fu;
uint green = (denorm_c.g >> 3) & 0x1Fu;
float sel0 = float(((green << 5) | red) & 0xFF) / 255.0f;
SV_Target0 = vec4(float(((green << 5) | red) & 0xFFu) / 255.0f);
SV_Target0 = vec4(sel0);
}
else
{
uint green = (denorm_c.g >> 3) & 0x1Fu;
uint blue = (denorm_c.b >> 3) & 0x1Fu;
uint alpha = denorm_c.a & 0x80u;
float sel0 = float((alpha | (blue << 2) | (green >> 3)) & 0xFF) / 255.0f;
SV_Target0 = vec4(float((alpha | (blue << 2) | (green >> 3)) & 0xFFu) / 255.0f);
SV_Target0 = vec4(sel0);
}
}
#endif
+32 -31
View File
@@ -332,62 +332,62 @@ void ps_convert_rgb5a1_8i()
uvec2 pos = uvec2(gl_FragCoord.xy);
// Collapse separate R G B A areas into their base pixel
uvec2 column = (pos & ~uvec2(0u, 3u)) / uvec2(1u, 2u);
uvec2 column = (pos & ~uvec2(0u, 3u)) / uvec2(1,2);
uvec2 subcolumn = (pos & uvec2(0u, 1u));
column.x -= (column.x / 128u) * 64u;
column.y += (column.y / 32u) * 32u;
column.x -= (column.x / 128) * 64;
column.y += (column.y / 32) * 32;
// Deal with swizzling differences
if ((PSM & 0x8u) != 0u) // PSMCT16S
if ((PSM & 0x8) != 0) // PSMCT16S
{
if ((pos.x & 32u) != 0u)
if ((pos.x & 32) != 0)
{
column.y += 32u; // 4 columns high times 4 to get bottom 4 blocks
column.x &= ~32u;
column.y += 32; // 4 columns high times 4 to get bottom 4 blocks
column.x &= ~32;
}
if ((pos.x & 64u) != 0u)
if ((pos.x & 64) != 0)
{
column.x -= 32u;
column.x -= 32;
}
if (((pos.x & 16u) != 0u) != ((pos.y & 16u) != 0u))
if (((pos.x & 16) != 0) != ((pos.y & 16) != 0))
{
column.x ^= 16u;
column.y ^= 8u;
column.x ^= 16;
column.y ^= 8;
}
if ((PSM & 0x30u) != 0u) // PSMZ16S - Untested but hopefully ok if anything uses it.
if ((PSM & 0x30) != 0) // PSMZ16S - Untested but hopefully ok if anything uses it.
{
column.x ^= 32u;
column.y ^= 16u;
column.x ^= 32;
column.y ^= 16;
}
}
else // PSMCT16
{
if ((pos.y & 32u) != 0u)
if ((pos.y & 32) != 0)
{
column.y -= 16u;
column.x += 32u;
column.y -= 16;
column.x += 32;
}
if ((pos.x & 96u) != 0u)
if ((pos.x & 96) != 0)
{
uint multi = (pos.x & 96u) / 32u;
column.y += 16u * multi; // 4 columns high times 4 to get bottom 4 blocks
column.x -= (pos.x & 96u);
uint multi = (pos.x & 96) / 32;
column.y += 16 * multi; // 4 columns high times 4 to get bottom 4 blocks
column.x -= (pos.x & 96);
}
if (((pos.x & 16u) != 0u) != ((pos.y & 16u) != 0u))
if (((pos.x & 16) != 0) != ((pos.y & 16) != 0))
{
column.x ^= 16u;
column.y ^= 8u;
column.x ^= 16;
column.y ^= 8;
}
if ((PSM & 0x30u) != 0u) // PSMZ16 - Untested but hopefully ok if anything uses it.
if ((PSM & 0x30) != 0) // PSMZ16 - Untested but hopefully ok if anything uses it.
{
column.x ^= 32u;
column.y ^= 32u;
column.x ^= 32;
column.y ^= 32;
}
}
uvec2 coord = column | subcolumn;
@@ -410,22 +410,23 @@ void ps_convert_rgb5a1_8i()
coord *= uvec2(ScaleFactor);
vec4 pixel = texelFetch(samp0, ivec2(coord), 0);
uvec4 denorm_c = uvec4(pixel * 255.5f);
if ((pos.y & 2u) == 0u)
{
uint red = (denorm_c.r >> 3) & 0x1Fu;
uint green = (denorm_c.g >> 3) & 0x1Fu;
float sel0 = float(((green << 5) | red) & 0xFF) / 255.0f;
o_col0 = vec4(float(((green << 5) | red) & 0xFFu) / 255.0f);
o_col0 = vec4(sel0);
}
else
{
uint green = (denorm_c.g >> 3) & 0x1Fu;
uint blue = (denorm_c.b >> 3) & 0x1Fu;
uint alpha = denorm_c.a & 0x80u;
float sel0 = float((alpha | (blue << 2) | (green >> 3)) & 0xFF) / 255.0f;
o_col0 = vec4(float((alpha | (blue << 2) | (green >> 3)) & 0xFFu) / 255.0f);
o_col0 = vec4(sel0);
}
}
#endif
-2
View File
@@ -16,8 +16,6 @@
<DepsDLLs Include="$(DepsBinDir)libpng16.dll" />
<DepsDLLs Include="$(DepsBinDir)libsharpyuv.dll" />
<DepsDLLs Include="$(DepsBinDir)libwebp.dll" />
<DepsDLLs Include="$(DepsBinDir)libwebpdemux.dll" />
<DepsDLLs Include="$(DepsBinDir)libwebpmux.dll" />
<DepsDLLs Include="$(DepsBinDir)lz4.dll" />
<DepsDLLs Include="$(DepsBinDir)SDL3.dll" />
<DepsDLLs Include="$(DepsBinDir)shaderc_shared.dll" />
+2 -4
View File
@@ -473,8 +473,8 @@ static void PrintCommandLineHelp(const char* progname)
std::fprintf(stderr, " -help: Displays this information and exits.\n");
std::fprintf(stderr, " -version: Displays version information and exits.\n");
std::fprintf(stderr, " -dumpdir <dir>: Frame dump directory (will be dumped as filename_frameN.png).\n");
std::fprintf(stderr, " -dump [rt|tex|z|f|a|i|tr]: Enabling dumping of render target, texture, z buffer, frame, "
"alphas, and info (context, vertices, transfers (list)), transfers (images), respectively, per draw. Generates lots of data.\n");
std::fprintf(stderr, " -dump [rt|tex|z|f|a|i]: Enabling dumping of render target, texture, z buffer, frame, "
"alphas, and info (context, vertices), respectively, per draw. Generates lots of data.\n");
std::fprintf(stderr, " -dumprange N[,L,B]: Start dumping from draw N (base 0), stops after L draws, and only "
"those draws that are multiples of B (intersection of -dumprange and -dumprangef used)."
"Defaults to 0,-1,1 (all draws). Only used if -dump used.\n");
@@ -558,8 +558,6 @@ bool GSRunner::ParseCommandLineArgs(int argc, char* argv[], VMBootParameters& pa
s_settings_interface.SetBoolValue("EmuCore/GS", "SaveAlpha", true);
if (str.find("i") != std::string::npos)
s_settings_interface.SetBoolValue("EmuCore/GS", "SaveInfo", true);
if (str.find("tr") != std::string::npos)
s_settings_interface.SetBoolValue("EmuCore/GS", "SaveTransferImages", true);
continue;
}
else if (CHECK_ARG_PARAM("-dumprange"))
-148
View File
@@ -12,21 +12,16 @@
#include "common/Assertions.h"
#include "common/Console.h"
#include "common/FileSystem.h"
#include "common/Path.h"
#include "common/StringUtil.h"
#include "fmt/format.h"
#include <QtCore/QSortFilterProxyModel>
#include <QtCore/QDir>
#include <QtCore/QString>
#include <QtGui/QPainter>
#include <QtGui/QPixmap>
#include <QtGui/QPixmapCache>
#include <QtGui/QWheelEvent>
#include <QtWidgets/QApplication>
#include <QtWidgets/QFileDialog>
#include <QtWidgets/QHeaderView>
#include <QtWidgets/QMenu>
#include <QtWidgets/QScrollBar>
@@ -289,7 +284,6 @@ void GameListWidget::initialize()
m_empty_ui.supportedFormats->setText(qApp->translate("GameListWidget", SUPPORTED_FORMATS_STRING));
connect(m_empty_ui.addGameDirectory, &QPushButton::clicked, this, [this]() { emit addGameDirectoryRequested(); });
connect(m_empty_ui.scanForNewGames, &QPushButton::clicked, this, [this]() { refresh(false); });
connect(qApp, &QGuiApplication::applicationStateChanged, this, [this]() { GameListWidget::updateCustomBackgroundState(); });
m_ui.stack->insertWidget(2, m_empty_widget);
if (Host::GetBaseBoolSettingValue("UI", "GameListGridView", false))
@@ -301,135 +295,6 @@ void GameListWidget::initialize()
updateToolbar();
resizeTableViewColumnsToFit();
setCustomBackground();
}
static void resizeAndPadImage(QImage* image, int expected_width, int expected_height, bool fill_with_top_left, bool expand_to_fill)
{
const qreal dpr = image->devicePixelRatio();
const int dpr_expected_width = static_cast<int>(static_cast<qreal>(expected_width) * dpr);
const int dpr_expected_height = static_cast<int>(static_cast<qreal>(expected_height) * dpr);
if (image->width() == dpr_expected_width && image->height() == dpr_expected_height)
return;
// Resize
if (((static_cast<float>(image->width()) / static_cast<float>(image->height())) >=
(static_cast<float>(dpr_expected_width) / static_cast<float>(dpr_expected_height))) != expand_to_fill)
{
*image = image->scaledToWidth(dpr_expected_width, Qt::SmoothTransformation);
}
else
{
*image = image->scaledToHeight(dpr_expected_height, Qt::SmoothTransformation);
}
if (image->width() == dpr_expected_width && image->height() == dpr_expected_height)
return;
// Padding
int xoffs = 0;
int yoffs = 0;
const int image_width = image->width();
const int image_height = image->height();
if ((image_width < dpr_expected_width) != expand_to_fill)
xoffs = static_cast<int>(static_cast<qreal>((dpr_expected_width - image_width) / 2) / dpr);
if ((image_height < dpr_expected_height) != expand_to_fill)
yoffs = static_cast<int>(static_cast<qreal>((dpr_expected_height - image_height) / 2) / dpr);
QImage padded_image(dpr_expected_width, dpr_expected_height, QImage::Format_ARGB32);
padded_image.setDevicePixelRatio(dpr);
if (fill_with_top_left)
padded_image.fill(image->pixel(0, 0));
else
padded_image.fill(Qt::transparent);
// Painting
QPainter painter;
const float opacity = Host::GetBaseFloatSettingValue("UI", "GameListBackgroundOpacity");
if (painter.begin(&padded_image))
{
painter.setOpacity((static_cast<float>(opacity / 100.0f))); // Qt expects the range to be from 0.0 to 1.0
painter.setCompositionMode(QPainter::CompositionMode_Source);
painter.drawImage(xoffs, yoffs, *image);
painter.end();
}
*image = std::move(padded_image);
}
void GameListWidget::setCustomBackground(bool force_refresh)
{
std::string path = Host::GetBaseStringSettingValue("UI", "GameListBackgroundPath");
bool enabled = Host::GetBaseBoolSettingValue("UI", "GameListBackgroundEnabled");
bool fill = Host::GetBaseBoolSettingValue("UI", "GameListBackgroundFill");
// Cleanup old animation if it still exists on gamelist
if (m_background_movie != nullptr)
{
delete m_background_movie;
m_background_movie = nullptr;
}
if (!Path::IsAbsolute(path))
path = Path::Combine(EmuFolders::DataRoot, path);
// Only try to create background both if path are valid and custom background are enabled
if ((!path.empty() && FileSystem::FileExists(path.c_str())) && enabled)
{
QMovie* new_movie;
if (Path::GetExtension(path) == "png")
// Use apng plugin
new_movie = new QMovie(QString::fromStdString(path), "apng", this);
else
new_movie = new QMovie(QString::fromStdString(path), QByteArray(), this);
if (new_movie->isValid())
m_background_movie = new_movie;
else
{
Console.Warning("Failed to load background movie from: %s", path.c_str());
delete new_movie;
}
}
// If there is no valid background then reset fallback to UI state
if (!m_background_movie)
{
m_ui.stack->setPalette(QApplication::palette());
m_table_view->setAlternatingRowColors(true);
return;
}
// Background is valid, connect the signals and start animation in gamelist
connect(m_background_movie, &QMovie::frameChanged, this, [this, fill]() { processBackgroundFrames(fill); });
updateCustomBackgroundState(force_refresh);
m_table_view->setAlternatingRowColors(false);
}
void GameListWidget::updateCustomBackgroundState(bool force_start)
{
if (m_background_movie)
{
if ((isVisible() && (isActiveWindow() || force_start)) && qGuiApp->applicationState() == Qt::ApplicationActive)
m_background_movie->start();
else
m_background_movie->stop();
}
}
void GameListWidget::processBackgroundFrames(bool fill_area)
{
QImage img = m_background_movie->currentImage();
img.setDevicePixelRatio(devicePixelRatioF());
const int widget_width = m_ui.stack->width();
const int widget_height = m_ui.stack->height();
resizeAndPadImage(&img, widget_width, widget_height, false, fill_area);
QPalette new_palette(m_ui.stack->palette());
new_palette.setBrush(QPalette::Base, img);
m_ui.stack->setPalette(new_palette);
}
bool GameListWidget::isShowingGameList() const
@@ -690,24 +555,11 @@ void GameListWidget::updateToolbar()
m_ui.gridScale->setEnabled(grid_view);
}
void GameListWidget::showEvent(QShowEvent* event)
{
QWidget::showEvent(event);
updateCustomBackgroundState();
}
void GameListWidget::hideEvent(QHideEvent* event)
{
QWidget::hideEvent(event);
updateCustomBackgroundState();
}
void GameListWidget::resizeEvent(QResizeEvent* event)
{
QWidget::resizeEvent(event);
resizeTableViewColumnsToFit();
m_model->updateCacheSize(width(), height());
setCustomBackground();
}
bool GameListWidget::event(QEvent* event)
-8
View File
@@ -8,7 +8,6 @@
#include "pcsx2/GameList.h"
#include <QtGui/QMovie>
#include <QtWidgets/QListView>
#include <QtWidgets/QTableView>
@@ -49,9 +48,6 @@ public:
void refresh(bool invalidate_cache);
void cancelRefresh();
void reloadThemeSpecificImages();
void setCustomBackground(bool force = false);
void updateCustomBackgroundState(bool force_start = false);
void processBackgroundFrames(bool fill_area);
bool isShowingGameList() const;
bool isShowingGameGrid() const;
@@ -96,8 +92,6 @@ public Q_SLOTS:
void refreshGridCovers();
protected:
void showEvent(QShowEvent* event) override;
void hideEvent(QHideEvent* event) override;
void resizeEvent(QResizeEvent* event) override;
bool event(QEvent* event) override;
@@ -121,6 +115,4 @@ private:
Ui::EmptyGameListWidget m_empty_ui;
GameListRefreshThread* m_refresh_thread = nullptr;
QMovie* m_background_movie = nullptr;
};
-6
View File
@@ -339,8 +339,6 @@ void MainWindow::connectSignals()
connect(m_ui.actionToolbarSettings, &QAction::triggered, this, &MainWindow::onSettingsTriggeredFromToolbar);
connect(m_ui.actionToolbarControllerSettings, &QAction::triggered,
[this]() { doControllerSettings(ControllerSettingsWindow::Category::GlobalSettings); });
connect(m_ui.actionToolbarHotkeySettings, &QAction::triggered,
[this]() { doControllerSettings(ControllerSettingsWindow::Category::HotkeySettings); });
connect(m_ui.actionToolbarScreenshot, &QAction::triggered, this, &MainWindow::onScreenshotActionTriggered);
connect(m_ui.actionExit, &QAction::triggered, this, &MainWindow::close);
connect(m_ui.actionScreenshot, &QAction::triggered, this, &MainWindow::onScreenshotActionTriggered);
@@ -2148,9 +2146,6 @@ void MainWindow::changeEvent(QEvent* event)
QtHost::SetIconThemeFromStyle();
reloadThemeSpecificImages();
}
if (event->type() == QEvent::ActivationChange)
m_game_list_widget->updateCustomBackgroundState();
}
static QString getFilenameFromMimeData(const QMimeData* md)
@@ -2697,7 +2692,6 @@ SettingsWindow* MainWindow::getSettingsWindow()
m_settings_window = new SettingsWindow();
connect(m_settings_window->getInterfaceSettingsWidget(), &InterfaceSettingsWidget::themeChanged, this, &MainWindow::onThemeChanged);
connect(m_settings_window->getInterfaceSettingsWidget(), &InterfaceSettingsWidget::languageChanged, this, &MainWindow::onLanguageChanged);
connect(m_settings_window->getInterfaceSettingsWidget(), &InterfaceSettingsWidget::backgroundChanged, m_game_list_widget, [this] {m_game_list_widget->setCustomBackground(true);});
connect(m_settings_window->getGameListSettingsWidget(), &GameListSettingsWidget::preferEnglishGameListChanged, this, [] {
g_main_window->m_game_list_widget->refreshGridCovers();
});
+1 -10
View File
@@ -132,7 +132,7 @@
</property>
<widget class="QMenu" name="menuDebugSwitchRenderer">
<property name="title">
<string>&amp;Switch Graphics API</string>
<string>&amp;Switch Renderer</string>
</property>
<property name="icon">
<iconset theme="brush-line"/>
@@ -266,7 +266,6 @@
<addaction name="separator"/>
<addaction name="actionToolbarSettings"/>
<addaction name="actionToolbarControllerSettings"/>
<addaction name="actionToolbarHotkeySettings"/>
</widget>
<widget class="QStatusBar" name="statusBar"/>
<action name="actionStartFile">
@@ -459,14 +458,6 @@
<string>&amp;Hotkeys</string>
</property>
</action>
<action name="actionToolbarHotkeySettings">
<property name="icon">
<iconset theme="keyboard-line"/>
</property>
<property name="text">
<string comment="In Toolbar">Hotkeys</string>
</property>
</action>
<action name="actionGraphicsSettings">
<property name="icon">
<iconset theme="image-fill"/>
-7
View File
@@ -71,13 +71,6 @@
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="saveTransferImages">
<property name="text">
<string>Save Transfer Image Data</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
@@ -109,7 +109,6 @@ DebugSettingsWidget::DebugSettingsWidget(SettingsWindow* settings_dialog, QWidge
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_gs.saveDepth, "EmuCore/GS", "SaveDepth", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_gs.saveAlpha, "EmuCore/GS", "SaveAlpha", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_gs.saveInfo, "EmuCore/GS", "SaveInfo", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_gs.saveTransferImages, "EmuCore/GS", "SaveTransferImages", false);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_gs.saveDrawStart, "EmuCore/GS", "SaveDrawStart", 0);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_gs.saveDrawCount, "EmuCore/GS", "SaveDrawCount", 5000);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_gs.saveFrameStart, "EmuCore/GS", "SaveFrameStart", 0);
@@ -214,7 +213,6 @@ void DebugSettingsWidget::onDrawDumpingChanged()
m_gs.saveDepth->setEnabled(enabled);
m_gs.saveAlpha->setEnabled(enabled);
m_gs.saveInfo->setEnabled(enabled);
m_gs.saveTransferImages->setEnabled(enabled);
m_gs.saveDrawStart->setEnabled(enabled);
m_gs.saveDrawCount->setEnabled(enabled);
m_gs.saveFrameStart->setEnabled(enabled);
@@ -116,6 +116,11 @@
</item>
<item row="5" column="1">
<widget class="QComboBox" name="blending">
<item>
<property name="text">
<string>Automatic (Default)</string>
</property>
</item>
<item>
<property name="text">
<string>Minimum</string>
@@ -123,7 +128,7 @@
</item>
<item>
<property name="text">
<string>Basic (Recommended)</string>
<string>Basic</string>
</property>
</item>
<item>
+1 -1
View File
@@ -23,7 +23,7 @@
<item row="0" column="0">
<widget class="QLabel" name="rendererText">
<property name="text">
<string>Graphics API:</string>
<string>Renderer:</string>
</property>
</widget>
</item>
+4 -4
View File
@@ -40,7 +40,7 @@ static constexpr RendererInfo s_renderer_info[] = {
{QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "Metal"), GSRendererType::Metal},
#endif
//: Graphics backend/engine type (refers to emulating the GS in software, on the CPU). Translate accordingly.
{QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "Software Renderer"), GSRendererType::SW},
{QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "Software"), GSRendererType::SW},
//: Null here means that this is a graphics backend that will show nothing.
{QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "Null"), GSRendererType::Null},
};
@@ -121,7 +121,7 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* settings_dialog,
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_hw.dithering, "EmuCore/GS", "dithering_ps2", 2);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_hw.mipmapping, "EmuCore/GS", "hw_mipmap", true);
SettingWidgetBinder::BindWidgetToIntSetting(
sif, m_hw.blending, "EmuCore/GS", "accurate_blending_unit", static_cast<int>(AccBlendLevel::Basic));
sif, m_hw.blending, "EmuCore/GS", "accurate_blending_unit", static_cast<int>(AccBlendLevel::Automatic), -1);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_hw.enableHWFixes, "EmuCore/GS", "UserHacks", false);
connect(m_hw.upscaleMultiplier, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&GraphicsSettingsWidget::onUpscaleMultiplierChanged);
@@ -635,7 +635,7 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* settings_dialog,
dialog()->registerWidgetHelp(m_fixes.readTCOnClose, tr("Read Targets When Closing"), tr("Unchecked"),
tr("Flushes all targets in the texture cache back to local memory when shutting down. Can prevent lost visuals when saving "
"state or switching graphics APIs, but can also cause graphical corruption."));
"state or switching renderers, but can also cause graphical corruption."));
dialog()->registerWidgetHelp(m_fixes.estimateTextureRegion, tr("Estimate Texture Region"), tr("Unchecked"),
tr("Attempts to reduce the texture size when games do not set it themselves (e.g. Snowblind games)."));
@@ -828,7 +828,7 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* settings_dialog,
dialog()->registerWidgetHelp(m_advanced.useBlitSwapChain, tr("Use Blit Swap Chain"), tr("Unchecked"),
//: Blit = a data operation. You might want to write it as-is, but fully uppercased. More information: https://en.wikipedia.org/wiki/Bit_blit
tr("Uses a blit presentation model instead of flipping when using the Direct3D 11 "
"graphics API. This usually results in slower performance, but may be required for some "
"renderer. This usually results in slower performance, but may be required for some "
"streaming applications, or to uncap framerates on some systems."));
dialog()->registerWidgetHelp(m_advanced.exclusiveFullscreenControl, tr("Allow Exclusive Fullscreen"), tr("Automatic (Default)"),
+4 -12
View File
@@ -53,24 +53,16 @@ void HotkeySettingsWidget::createButtons()
auto iter = m_categories.find(category);
if (iter == m_categories.end())
{
// Top line
QLabel* top_line = new QLabel(m_container);
top_line->setFrameShape(QFrame::HLine);
top_line->setFixedHeight(12);
m_layout->addWidget(top_line);
// Category label
QLabel* label = new QLabel(category, m_container);
QFont label_font(label->font());
label_font.setPointSizeF(14.0f);
label->setFont(label_font);
m_layout->addWidget(label);
// Bottom line
QLabel* bottom_line = new QLabel(m_container);
bottom_line->setFrameShape(QFrame::HLine);
bottom_line->setFixedHeight(12);
m_layout->addWidget(bottom_line);
QLabel* line = new QLabel(m_container);
line->setFrameShape(QFrame::HLine);
line->setFixedHeight(4);
m_layout->addWidget(line);
QGridLayout* layout = new QGridLayout();
layout->setContentsMargins(0, 0, 0, 0);
+2 -53
View File
@@ -4,15 +4,11 @@
#include "InterfaceSettingsWidget.h"
#include "AutoUpdaterDialog.h"
#include "Common.h"
#include "Host.h"
#include "MainWindow.h"
#include "SettingWidgetBinder.h"
#include "SettingsWindow.h"
#include "QtHost.h"
static const char* IMAGE_FILE_FILTER = QT_TRANSLATE_NOOP(GameListWidget,
"Supported Image Types (*.bmp *.gif *.jpg *.jpeg *.png *.webp)");
const char* InterfaceSettingsWidget::THEME_NAMES[] = {
QT_TRANSLATE_NOOP("InterfaceSettingsWidget", "Native"),
//: Ignore what Crowdin says in this string about "[Light]/[Dark]" being untouchable here, these are not variables in this case and must be translated.
@@ -109,13 +105,6 @@ InterfaceSettingsWidget::InterfaceSettingsWidget(SettingsWindow* settings_dialog
QtHost::GetDefaultThemeName(), "InterfaceSettingsWidget");
connect(m_ui.theme, QOverload<int>::of(&QComboBox::currentIndexChanged), [this]() { emit themeChanged(); });
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.backgroundOpacity, "UI", "GameListBackgroundOpacity", 100);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.backgroundFill, "UI", "GameListBackgroundFill", false);
connect(m_ui.backgroundBrowse, &QPushButton::clicked, [this]() { onSetGameListBackgroundTriggered(); });
connect(m_ui.backgroundReset, &QPushButton::clicked, [this]() { onClearGameListBackgroundTriggered(); });
connect(m_ui.backgroundOpacity, &QSpinBox::valueChanged, [this]() { emit backgroundChanged(); });
connect(m_ui.backgroundFill, &QCheckBox::checkStateChanged, [this]() {emit backgroundChanged(); });
populateLanguages();
SettingWidgetBinder::BindWidgetToStringSetting(sif, m_ui.language, "UI", "Language", QtHost::GetDefaultLanguage());
connect(m_ui.language, QOverload<int>::of(&QComboBox::currentIndexChanged), [this]() { emit languageChanged(); });
@@ -150,8 +139,8 @@ InterfaceSettingsWidget::InterfaceSettingsWidget(SettingsWindow* settings_dialog
if (dialog()->isPerGameSettings())
{
// language/theme doesn't make sense to have in per-game settings
m_ui.verticalLayout->removeWidget(m_ui.appearancesGroup);
m_ui.appearancesGroup->hide();
m_ui.verticalLayout->removeWidget(m_ui.preferencesGroup);
m_ui.preferencesGroup->hide();
// start paused doesn't make sense, because settings are applied after ELF load.
m_ui.pauseOnStart->setEnabled(false);
@@ -196,19 +185,6 @@ InterfaceSettingsWidget::InterfaceSettingsWidget(SettingsWindow* settings_dialog
dialog()->registerWidgetHelp(
m_ui.startFullscreenUI, tr("Start Big Picture Mode"), tr("Unchecked"),
tr("Automatically starts Big Picture Mode instead of the regular Qt interface when PCSX2 launches."));
dialog()->registerWidgetHelp(
m_ui.backgroundBrowse, tr("Game List Background"), tr("None"),
tr("Enable an animated / static background on the game list (where you launch your games).<br>"
"This background is only visible in the library and will be hidden once a game is launched. It will also be paused when it's not in focus."));
dialog()->registerWidgetHelp(
m_ui.backgroundReset, tr("Disable/Reset Game List Background"), tr("None"),
tr("Disable and reset the currently applied game list background."));
dialog()->registerWidgetHelp(
m_ui.backgroundOpacity, tr("Game List Background Opacity"), tr("100%"),
tr("Sets the opacity of the custom background."));
dialog()->registerWidgetHelp(
m_ui.backgroundFill, tr("Fill Image"), tr("Unchecked"),
tr("Expand the image to fill all available background area."));
onRenderToSeparateWindowChanged();
}
@@ -225,30 +201,3 @@ void InterfaceSettingsWidget::populateLanguages()
for (const std::pair<QString, QString>& it : QtHost::GetAvailableLanguageList())
m_ui.language->addItem(it.first, it.second);
}
void InterfaceSettingsWidget::onSetGameListBackgroundTriggered()
{
const QString path = QDir::toNativeSeparators(
QFileDialog::getOpenFileName(this, tr("Select Background Image"), QString(), IMAGE_FILE_FILTER));
if (path.isEmpty())
return;
std::string relative_path = Path::MakeRelative(QDir::toNativeSeparators(path).toStdString(), EmuFolders::DataRoot);
Host::SetBaseBoolSettingValue("UI", "GameListBackgroundEnabled", true);
Host::SetBaseStringSettingValue("UI", "GameListBackgroundPath", relative_path.c_str());
if (!Host::ContainsBaseSettingValue("UI", "GameListBackgroundOpacity"))
Host::SetBaseFloatSettingValue("UI", "GameListBackgroundOpacity", 100.0f);
Host::CommitBaseSettingChanges();
emit backgroundChanged();
}
void InterfaceSettingsWidget::onClearGameListBackgroundTriggered()
{
Host::SetBaseBoolSettingValue("UI", "GameListBackgroundEnabled", false);
Host::RemoveBaseSettingValue("UI", "GameListBackgroundPath");
Host::CommitBaseSettingChanges();
emit backgroundChanged();
}
@@ -18,12 +18,9 @@ public:
Q_SIGNALS:
void themeChanged();
void languageChanged();
void backgroundChanged();
private Q_SLOTS:
void onRenderToSeparateWindowChanged();
void onSetGameListBackgroundTriggered();
void onClearGameListBackgroundTriggered();
private:
void populateLanguages();
+16 -98
View File
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>725</width>
<height>617</height>
<width>700</width>
<height>608</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
@@ -140,14 +140,11 @@
</widget>
</item>
<item>
<widget class="QGroupBox" name="appearancesGroup">
<widget class="QGroupBox" name="preferencesGroup">
<property name="title">
<string>Appearance</string>
<string>Preferences</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="1">
<widget class="QComboBox" name="theme"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="languageLabel">
<property name="text">
@@ -165,87 +162,8 @@
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="backgroundLabel">
<property name="text">
<string>Game List Background:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<layout class="QHBoxLayout" name="backgroundPathLayout">
<item>
<widget class="QPushButton" name="backgroundBrowse">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Browse...</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="backgroundReset">
<property name="text">
<string>Reset</string>
</property>
<property name="icon">
<iconset theme="trash-fill"/>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="backgroundOpacityLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Opacity:</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="backgroundOpacity">
<property name="wrapping">
<bool>false</bool>
</property>
<property name="buttonSymbols">
<enum>QAbstractSpinBox::ButtonSymbols::PlusMinus</enum>
</property>
<property name="showGroupSeparator" stdset="0">
<bool>false</bool>
</property>
<property name="suffix">
<string notr="true">%</string>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="singleStep">
<number>5</number>
</property>
<property name="value">
<number>100</number>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="backgroundFill">
<property name="text">
<string>Fill Image</string>
</property>
</widget>
</item>
</layout>
<item row="1" column="1">
<widget class="QComboBox" name="theme"/>
</item>
</layout>
</widget>
@@ -256,13 +174,6 @@
<string>Automatic Updater</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="updaterChannelLabel">
<property name="text">
<string>Update Channel:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="autoUpdateCurrentVersion">
<property name="text">
@@ -270,8 +181,12 @@
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="autoUpdateTag"/>
<item row="0" column="0">
<widget class="QLabel" name="updaterChannelLabel">
<property name="text">
<string>Update Channel:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="currentVersionLabel">
@@ -280,6 +195,9 @@
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="autoUpdateTag"/>
</item>
<item row="2" column="0" colspan="2">
<layout class="QHBoxLayout" name="automaticUpdaterCheckGroup" stretch="1,0">
<item>
@@ -304,7 +222,7 @@
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1294,7 +1294,7 @@ function(setup_main_executable target)
# Copy dependency libraries.
set(DEPS_BINDIR "${CMAKE_SOURCE_DIR}/deps/bin")
set(DEPS_TO_COPY freetype.dll harfbuzz.dll jpeg62.dll libpng16.dll libsharpyuv.dll libwebp.dll libwebpdemux.dll libwebpmux.dll lz4.dll SDL3.dll shaderc_shared.dll zlib1.dll zstd.dll plutovg.dll plutosvg.dll)
set(DEPS_TO_COPY freetype.dll harfbuzz.dll jpeg62.dll libpng16.dll libsharpyuv.dll libwebp.dll lz4.dll SDL3.dll shaderc_shared.dll zlib1.dll zstd.dll plutovg.dll plutosvg.dll)
set(DEPS_TO_COPY
$<IF:$<CONFIG:Debug>,kddockwidgets-qt6d.dll,kddockwidgets-qt6.dll>
${DEPS_TO_COPY}
+4 -4
View File
@@ -327,8 +327,9 @@ enum class TriFiltering : s8
Forced,
};
enum class AccBlendLevel : u8
enum class AccBlendLevel : s8
{
Automatic = -1,
Minimum,
Basic,
Medium,
@@ -711,7 +712,7 @@ struct Pcsx2Config
union
{
u64 bitset[2];
u64 bitset;
struct
{
@@ -774,7 +775,6 @@ struct Pcsx2Config
SaveDepth : 1,
SaveAlpha : 1,
SaveInfo : 1,
SaveTransferImages : 1,
DumpReplaceableTextures : 1,
DumpReplaceableMipmaps : 1,
DumpTexturesWithFMVActive : 1,
@@ -812,7 +812,7 @@ struct Pcsx2Config
GSRendererType Renderer = GSRendererType::Auto;
float UpscaleMultiplier = 1.0f;
AccBlendLevel AccurateBlendingUnit = AccBlendLevel::Basic;
AccBlendLevel AccurateBlendingUnit = AccBlendLevel::Automatic;
BiFiltering TextureFiltering = BiFiltering::PS2;
TexturePreloadingLevel TexturePreloading = TexturePreloadingLevel::Full;
GSDumpCompressionMethod GSDumpCompression = GSDumpCompressionMethod::Zstandard;
+83 -85
View File
@@ -169,123 +169,121 @@ void GSDrawingContext::Dump(const std::string& filename)
if (!fp)
return;
// Warning: The indentation must be consistent with GSDrawingEnvironment::Dump().
fprintf(fp,
"XYOFFSET:\n"
" OFX: %.4f\n"
" OFY: %.4f\n\n",
"XYOFFSET\n"
"\tOFX:%.4f\n"
"\tOFY:%.4f\n\n",
XYOFFSET.OFX / 16.0f, XYOFFSET.OFY / 16.0f);
fprintf(fp,
"MIPTBP1:\n"
" TBP1: 0x%x\n"
" TBW1: %u\n"
" TBP2: 0x%x\n"
" TBW2: %u\n"
" TBP3: 0x%x\n"
" TBW3: %u\n\n",
"MIPTBP1\n"
"\tTBP1:0x%x\n"
"\tTBW1:%u\n"
"\tTBP2:0x%x\n"
"\tTBW2:%u\n"
"\tTBP3:0x%x\n"
"\tTBW3:%u\n\n",
static_cast<uint32_t>(MIPTBP1.TBP1), static_cast<uint32_t>(MIPTBP1.TBW1), static_cast<uint32_t>(MIPTBP1.TBP2),
static_cast<uint32_t>(MIPTBP1.TBW2), static_cast<uint32_t>(MIPTBP1.TBP3), static_cast<uint32_t>(MIPTBP1.TBW3));
fprintf(fp,
"MIPTBP2:\n"
" TBP4: 0x%x\n"
" TBW4: %u\n"
" TBP5: 0x%x\n"
" TBW5: %u\n"
" TBP6: 0x%x\n"
" TBW6: %u\n\n",
"MIPTBP2\n"
"\tTBP4:0x%x\n"
"\tTBW4:%u\n"
"\tTBP5:0x%x\n"
"\tTBW5:%u\n"
"\tTBP6:0x%x\n"
"\tTBW6:%u\n\n",
static_cast<uint32_t>(MIPTBP2.TBP4), static_cast<uint32_t>(MIPTBP2.TBW4), static_cast<uint32_t>(MIPTBP2.TBP5),
static_cast<uint32_t>(MIPTBP2.TBW5), static_cast<uint32_t>(MIPTBP2.TBP6), static_cast<uint32_t>(MIPTBP2.TBW6));
fprintf(fp,
"TEX0:\n"
" TBP0: 0x%x\n"
" TBW: %u\n"
" PSM: 0x%x # %s\n"
" TW: %u\n"
" TH: %u\n"
" TCC: %u # %s\n"
" TFX: %u # %s\n"
" CBP: 0x%x\n"
" CPSM: 0x%x # %s\n"
" CSM: %u\n"
" CSA: %u\n"
" CLD: %u\n\n",
TEX0.TBP0, TEX0.TBW, TEX0.PSM, GSUtil::GetPSMName(TEX0.PSM), TEX0.TW, static_cast<uint32_t>(TEX0.TH), TEX0.TCC, GSUtil::GetTCCName(TEX0.TCC), TEX0.TFX, GSUtil::GetTFXName(TEX0.TFX), TEX0.CBP, TEX0.CPSM, GSUtil::GetPSMName(TEX0.CPSM), TEX0.CSM, TEX0.CSA, TEX0.CLD);
"TEX0\n"
"\tTBP0:0x%x\n"
"\tTBW:%u\n"
"\tPSM:0x%x (%s)\n"
"\tTW:%u\n"
"\tTH:%u\n"
"\tTCC:%u\n"
"\tTFX:%u\n"
"\tCBP:0x%x\n"
"\tCPSM:0x%x (%s)\n"
"\tCSM:%u\n"
"\tCSA:%u\n"
"\tCLD:%u\n\n",
TEX0.TBP0, TEX0.TBW, TEX0.PSM, GSUtil::GetPSMName(TEX0.PSM), TEX0.TW, static_cast<uint32_t>(TEX0.TH), TEX0.TCC, TEX0.TFX, TEX0.CBP, TEX0.CPSM, GSUtil::GetPSMName(TEX0.CPSM), TEX0.CSM,TEX0.CSA, TEX0.CLD);
fprintf(fp,
"TEX1:\n"
" LCM: %u # %s\n"
" MXL: %u\n"
" MMAG: %u # %s\n"
" MMIN: %u # %s\n"
" MTBA: %u\n"
" L: %u\n"
" K: %.4f\n\n",
TEX1.LCM, GSUtil::GetLCMName(TEX1.LCM), TEX1.MXL, TEX1.MMAG, GSUtil::GetMMAGName(TEX1.MMAG), TEX1.MMIN, GSUtil::GetMMINName(TEX1.MMIN), TEX1.MTBA, TEX1.L, static_cast<float>((static_cast<int>(TEX1.K) ^ 0x800) - 0x800) / 16.0f);
"TEX1\n"
"\tLCM:%u\n"
"\tMXL:%u\n"
"\tMMAG:%u\n"
"\tMMIN:%u\n"
"\tMTBA:%u\n"
"\tL:%u\n"
"\tK:%d\n\n",
TEX1.LCM, TEX1.MXL, TEX1.MMAG, TEX1.MMIN, TEX1.MTBA, TEX1.L, TEX1.K);
fprintf(fp,
"CLAMP:\n"
" WMS: %u # %s\n"
" WMT: %u # %s\n"
" MINU: %u\n"
" MAXU: %u\n"
" MINV: %u\n"
" MAXV: %u\n\n",
CLAMP.WMS, GSUtil::GetWMName(CLAMP.WMS), CLAMP.WMT,GSUtil::GetWMName(CLAMP.WMT), CLAMP.MINU, CLAMP.MAXU, static_cast<uint32_t>(CLAMP.MINV), CLAMP.MAXV);
"CLAMP\n"
"\tWMS:%u (%s)\n"
"\tWMT:%u (%s)\n"
"\tMINU:%u\n"
"\tMAXU:%u\n"
"\tMAXV:%u\n"
"\tMINV:%u\n\n",
CLAMP.WMS, GSUtil::GetWMName(CLAMP.WMS), CLAMP.WMT,GSUtil::GetWMName(CLAMP.WMT), CLAMP.MINU, CLAMP.MAXU, CLAMP.MAXV, static_cast<uint32_t>(CLAMP.MINV));
fprintf(fp,
"SCISSOR:\n"
" SCAX0: %u\n"
" SCAX1: %u\n"
" SCAY0: %u\n"
" SCAY1: %u\n\n",
"SCISSOR\n"
"\tSCAX0:%u\n"
"\tSCAX1:%u\n"
"\tSCAY0:%u\n"
"\tSCAY1:%u\n\n",
SCISSOR.SCAX0, SCISSOR.SCAX1, SCISSOR.SCAY0, SCISSOR.SCAY1);
fprintf(fp,
"ALPHA:\n"
" A: %u\n"
" B: %u\n"
" C: %u\n"
" D: %u\n"
" FIX: %u\n",
"ALPHA\n"
"\tA:%u\n"
"\tB:%u\n"
"\tC:%u\n"
"\tD:%u\n"
"\tFIX:%u\n",
ALPHA.A, ALPHA.B, ALPHA.C, ALPHA.D, ALPHA.FIX);
constexpr const char* col[3] = {"Cs", "Cd", "0"};
constexpr const char* alpha[3] = {"As", "Ad", "Af"};
fprintf(fp, " # => (%s - %s) * %s + %s\n\n", col[ALPHA.A], col[ALPHA.B], alpha[ALPHA.C], col[ALPHA.D]);
const char* col[3] = {"Cs", "Cd", "0"};
const char* alpha[3] = {"As", "Ad", "Af"};
fprintf(fp, "\t=> (%s - %s) * %s + %s\n\n", col[ALPHA.A], col[ALPHA.B], alpha[ALPHA.C], col[ALPHA.D]);
fprintf(fp,
"TEST:\n"
" ATE: %u\n"
" ATST: %u # %s\n"
" AREF: %u\n"
" AFAIL: %u # %s\n"
" DATE: %u\n"
" DATM: %u # %s\n"
" ZTE: %u\n"
" ZTST: %u # %s\n\n",
TEST.ATE, TEST.ATST, GSUtil::GetATSTName(TEST.ATST), TEST.AREF, TEST.AFAIL, GSUtil::GetAFAILName(TEST.AFAIL), TEST.DATE, TEST.DATM, GSUtil::GetDATMName(TEST.DATM), TEST.ZTE, TEST.ZTST, GSUtil::GetZTSTName(TEST.ZTST));
"TEST\n"
"\tATE:%u\n"
"\tATST:%u (%s)\n"
"\tAREF:%u\n"
"\tAFAIL:%u (%s)\n"
"\tDATE:%u\n"
"\tDATM:%u\n"
"\tZTE:%u\n"
"\tZTST:%u (%s)\n\n",
TEST.ATE, TEST.ATST, GSUtil::GetATSTName(TEST.ATST), TEST.AREF, TEST.AFAIL, GSUtil::GetAFAILName(TEST.AFAIL), TEST.DATE, TEST.DATM, TEST.ZTE, TEST.ZTST, GSUtil::GetZTSTName(TEST.ZTST));
fprintf(fp,
"FBA:\n"
" FBA: %u\n\n",
"FBA\n"
"\tFBA:%u\n\n",
FBA.FBA);
fprintf(fp,
"FRAME:\n"
" FBP: 0x%x # (*32)\n"
" FBW: %u\n"
" PSM: 0x%x # %s\n"
" FBMSK: 0x%x\n\n",
"FRAME\n"
"\tFBP (*32):0x%x\n"
"\tFBW:%u\n"
"\tPSM:0x%x (%s)\n"
"\tFBMSK:0x%x\n\n",
FRAME.FBP * 32, FRAME.FBW, FRAME.PSM, GSUtil::GetPSMName(FRAME.PSM), FRAME.FBMSK);
fprintf(fp,
"ZBUF:\n"
" ZBP: 0x%x # (*32)\n"
" PSM: 0x%x # %s\n"
" ZMSK: %u\n\n",
"ZBUF\n"
"\tZBP (*32):0x%x\n"
"\tPSM:0x%x (%s)\n"
"\tZMSK:%u\n\n",
ZBUF.ZBP * 32, ZBUF.PSM, GSUtil::GetPSMName(ZBUF.PSM), ZBUF.ZMSK);
fclose(fp);
+81 -83
View File
@@ -35,114 +35,112 @@ void GSDrawingEnvironment::Dump(const std::string& filename) const
if (!fp)
return;
// Warning: The indentation must be consistent with GSDrawingContext::Dump().
fprintf(fp, "PRIM:\n"
" PRIM: %u # %s\n"
" IIP: %u\n"
" TME: %u\n"
" FGE: %u\n"
" ABE: %u\n"
" AA1: %u\n"
" FST: %u\n"
" CTXT: %u\n"
" FIX: %u\n\n",
fprintf(fp, "PRIM\n"
"\tPRIM:%u (%s)\n"
"\tIIP:%u\n"
"\tTME:%u\n"
"\tFGE:%u\n"
"\tABE:%u\n"
"\tAA1:%u\n"
"\tFST:%u\n"
"\tCTXT:%u\n"
"\tFIX:%u\n\n",
PRIM.PRIM, GSUtil::GetPrimName(PRIM.PRIM), PRIM.IIP, PRIM.TME, PRIM.FGE, PRIM.ABE, PRIM.AA1, PRIM.FST, PRIM.CTXT, PRIM.FIX);
fprintf(fp, "PRMODE: # when AC=0\n"
" _PRIM: %u # %s\n"
" IIP: %u\n"
" TME: %u\n"
" FGE: %u\n"
" ABE: %u\n"
" AA1: %u\n"
" FST: %u\n"
" CTXT: %u\n"
" FIX: %u\n\n",
fprintf(fp, "PRMODE (when AC=0)\n"
"\t_PRIM:%u (%s)\n"
"\tIIP:%u\n"
"\tTME:%u\n"
"\tFGE:%u\n"
"\tABE:%u\n"
"\tAA1:%u\n"
"\tFST:%u\n"
"\tCTXT:%u\n"
"\tFIX:%u\n\n",
PRMODE._PRIM, GSUtil::GetPrimName(PRMODE._PRIM), PRMODE.IIP, PRMODE.TME, PRMODE.FGE, PRMODE.ABE, PRMODE.AA1, PRMODE.FST, PRMODE.CTXT, PRMODE.FIX);
fprintf(fp, "PRMODECONT:\n"
" AC: %u # %s\n\n",
PRMODECONT.AC, GSUtil::GetACName(PRMODECONT.AC));
fprintf(fp, "PRMODECONT\n"
"\tAC:%u\n\n",
PRMODECONT.AC);
fprintf(fp, "TEXCLUT:\n"
" CBW: %u\n"
" COU: %u\n"
" COV: %u\n\n",
TEXCLUT.CBW, TEXCLUT.COU, TEXCLUT.COV);
fprintf(fp, "TEXCLUT\n"
"\tCOU:%u\n"
"\tCBW:%u\n"
"\tCOV:%u\n\n",
TEXCLUT.COU, TEXCLUT.CBW, TEXCLUT.COV);
fprintf(fp, "SCANMSK:\n"
" MSK: %u # %s\n\n",
SCANMSK.MSK, GSUtil::GetSCANMSKName(SCANMSK.MSK));
fprintf(fp, "SCANMSK\n"
"\tMSK:%u\n\n",
SCANMSK.MSK);
fprintf(fp, "TEXA:\n"
" AEM: %u\n"
" TA0: %u\n"
" TA1: %u\n\n",
fprintf(fp, "TEXA\n"
"\tAEM:%u\n"
"\tTA0:%u\n"
"\tTA1:%u\n\n",
TEXA.AEM, TEXA.TA0, TEXA.TA1);
fprintf(fp, "FOGCOL:\n"
" FCG: %u\n"
" FCB: %u\n"
" FCR: %u\n\n",
fprintf(fp, "FOGCOL\n"
"\tFCG:%u\n"
"\tFCB:%u\n"
"\tFCR:%u\n\n",
FOGCOL.FCG, FOGCOL.FCB, FOGCOL.FCR);
fprintf(fp, "DIMX:\n"
" DM22: %d\n"
" DM23: %d\n"
" DM31: %d\n"
" DM02: %d\n"
" DM21: %d\n"
" DM12: %d\n"
" DM03: %d\n"
" DM01: %d\n"
" DM33: %d\n"
" DM30: %d\n"
" DM11: %d\n"
" DM10: %d\n"
" DM20: %d\n"
" DM32: %d\n"
" DM00: %d\n"
" DM13: %d\n\n",
fprintf(fp, "DIMX\n"
"\tDM22:%d\n"
"\tDM23:%d\n"
"\tDM31:%d\n"
"\tDM02:%d\n"
"\tDM21:%d\n"
"\tDM12:%d\n"
"\tDM03:%d\n"
"\tDM01:%d\n"
"\tDM33:%d\n"
"\tDM30:%d\n"
"\tDM11:%d\n"
"\tDM10:%d\n"
"\tDM20:%d\n"
"\tDM32:%d\n"
"\tDM00:%d\n"
"\tDM13:%d\n\n",
DIMX.DM22, DIMX.DM23, DIMX.DM31, DIMX.DM02, DIMX.DM21, DIMX.DM12, DIMX.DM03, DIMX.DM01, DIMX.DM33, DIMX.DM30, DIMX.DM11, DIMX.DM10, DIMX.DM20, DIMX.DM32, DIMX.DM00, DIMX.DM13);
fprintf(fp, "DTHE:\n"
" DTHE: %u\n\n",
fprintf(fp, "DTHE\n"
"\tDTHE:%u\n\n",
DTHE.DTHE);
fprintf(fp, "COLCLAMP:\n"
" CLAMP: %u\n\n",
fprintf(fp, "COLCLAMP\n"
"\tCLAMP:%u\n\n",
COLCLAMP.CLAMP);
fprintf(fp, "PABE:\n"
" PABE: %u\n\n",
fprintf(fp, "PABE\n"
"\tPABE:%u\n\n",
PABE.PABE);
fprintf(fp, "BITBLTBUF:\n"
" SBW: %u\n"
" SBP: 0x%x\n"
" SPSM: %u # %s\n"
" DBW: %u\n"
" DPSM: %u # %s\n"
" DBP: 0x%x\n\n",
fprintf(fp, "BITBLTBUF\n"
"\tSBW:%u\n"
"\tSBP:0x%x\n"
"\tSPSM:%u (%s)\n"
"\tDBW:%u\n"
"\tDPSM:%u (%s)\n"
"\tDBP:0x%x\n\n",
BITBLTBUF.SBW, BITBLTBUF.SBP, BITBLTBUF.SPSM, GSUtil::GetPSMName(BITBLTBUF.SPSM), BITBLTBUF.DBW, BITBLTBUF.DPSM, GSUtil::GetPSMName(BITBLTBUF.DPSM), BITBLTBUF.DBP);
fprintf(fp, "TRXDIR:\n"
" XDIR: %u\n\n",
fprintf(fp, "TRXDIR\n"
"\tXDIR:%u\n\n",
TRXDIR.XDIR);
fprintf(fp, "TRXPOS:\n"
" DIRY: %u\n"
" SSAY: %u\n"
" SSAX: %u\n"
" DIRX: %u\n"
" DSAX: %u\n"
" DSAY: %u\n\n",
fprintf(fp, "TRXPOS\n"
"\tDIRY:%u\n"
"\tSSAY:%u\n"
"\tSSAX:%u\n"
"\tDIRX:%u\n"
"\tDSAX:%u\n"
"\tDSAY:%u\n\n",
TRXPOS.DIRY, TRXPOS.SSAY, TRXPOS.SSAX, TRXPOS.DIRX, TRXPOS.DSAX, TRXPOS.DSAY);
fprintf(fp, "TRXREG:\n"
" RRH: %u\n"
" RRW: %u\n\n",
fprintf(fp, "TRXREG\n"
"\tRRH:%u\n"
"\tRRW:%u\n\n",
TRXREG.RRH, TRXREG.RRW);
fclose(fp);
+2 -2
View File
@@ -651,7 +651,7 @@ void GSLocalMemory::ReadTexture(const GSOffset& off, const GSVector4i& r, u8* ds
//
void GSLocalMemory::SaveBMP(const std::string& fn, u32 bp, u32 bw, u32 psm, int w, int h, int x, int y)
void GSLocalMemory::SaveBMP(const std::string& fn, u32 bp, u32 bw, u32 psm, int w, int h)
{
int pitch = w * 4;
int size = pitch * h;
@@ -671,7 +671,7 @@ void GSLocalMemory::SaveBMP(const std::string& fn, u32 bp, u32 bw, u32 psm, int
{
for (int i = 0; i < w; i++)
{
((u32*)p)[i] = (this->*rp)(x + i, y + j, TEX0.TBP0, TEX0.TBW);
((u32*)p)[i] = (this->*rp)(i, j, TEX0.TBP0, TEX0.TBW);
}
}
+1 -1
View File
@@ -1121,7 +1121,7 @@ public:
//
void SaveBMP(const std::string& fn, u32 bp, u32 bw, u32 psm, int w, int h, int x = 0, int y = 0);
void SaveBMP(const std::string& fn, u32 bp, u32 bw, u32 psm, int w, int h);
};
constexpr inline GSOffset GSOffset::fromKnownPSM(u32 bp, u32 bw, GS_PSM psm)
+84 -389
View File
@@ -15,7 +15,6 @@
#include <algorithm>
#include <cfloat>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <bit>
@@ -434,34 +433,6 @@ const char* GSState::GetFlushReasonString(GSFlushReason reason)
}
}
void GSState::DumpDrawInfo(bool dump_regs, bool dump_verts, bool dump_transfers)
{
std::string s;
// Dump Register state
if (dump_regs)
{
s = GetDrawDumpPath("%05d_context.txt", s_n);
m_draw_env->Dump(s);
m_context->Dump(s);
}
// Dump vertices
if (dump_verts)
{
s = GetDrawDumpPath("%05d_vertex.txt", s_n);
DumpVertices(s);
}
// Dump transfers
if (dump_transfers)
{
s = GetDrawDumpPath("%05d_transfers.txt", s_n);
DumpTransferList(s);
}
}
void GSState::DumpVertices(const std::string& filename)
{
std::ofstream file(filename);
@@ -469,370 +440,108 @@ void GSState::DumpVertices(const std::string& filename)
if (!file.is_open())
return;
file.imbue(std::locale::classic()); // Disable integer separators.
file << "FLUSH REASON: " << GetFlushReasonString(m_state_flush_reason);
constexpr const char* DEL = ", ";
constexpr const char* INDENT = " ";
constexpr const char* LIST_ITEM = "- ";
constexpr const char* OPEN_MAP = "{";
constexpr const char* CLOSE_MAP = "}";
constexpr int TRACE_INDEX_WIDTH = 10;
constexpr int XYUV_WIDTH = 9;
constexpr int Z_WIDTH = 10;
constexpr int RGBA_WIDTH = 3;
constexpr int SCI_FLOAT_WIDTH = 15;
constexpr int STQ_BITS_WIDTH = 10;
auto WriteVertexIndex = [&file](int index) {
file << std::left << std::dec << " # " << index;
};
auto WriteTraceIndex = [&file](const char* index) {
file << std::left << std::dec << std::setw(TRACE_INDEX_WIDTH) << std::setfill(' ') << index;
};
auto WriteXYZ_vec = [&file](const GSVector4& v) {
file << std::dec << std::right << std::fixed;
file << "X: " << std::setprecision(4) << std::setw(XYUV_WIDTH) << std::setfill(' ') << v.x << DEL;
file << "Y: " << std::setprecision(4) << std::setw(XYUV_WIDTH) << std::setfill(' ') << v.y << DEL;
file << "Z: " << std::setw(Z_WIDTH) << std::setfill(' ') << static_cast<u32>(v.z);
};
// Different handler because we have full precision on Z
auto WriteXYZ_vert = [this, &file](const GSVertex& v) {
const float x = (static_cast<int>(v.XYZ.X) - static_cast<int>(m_context->XYOFFSET.OFX)) / 16.0f;
const float y = (static_cast<int>(v.XYZ.Y) - static_cast<int>(m_context->XYOFFSET.OFY)) / 16.0f;
file << std::dec << std::right << std::fixed;
file << "X: " << std::setprecision(4) << std::setw(XYUV_WIDTH) << std::setfill(' ') << x << DEL;
file << "Y: " << std::setprecision(4) << std::setw(XYUV_WIDTH) << std::setfill(' ') << y << DEL;
file << "Z: " << std::setw(Z_WIDTH) << std::setfill(' ') << v.XYZ.Z;
};
auto WriteUV_vec = [this, &file](const GSVector4& v) {
file << std::right;
if (PRIM->FST)
{
file << std::fixed;
file << "U: " << std::setprecision(4) << std::setw(XYUV_WIDTH) << std::setfill(' ') << v.x << DEL;
file << "V: " << std::setprecision(4) << std::setw(XYUV_WIDTH) << std::setfill(' ') << v.y;
}
else
{
file << std::defaultfloat;
file << "U: " << std::setw(SCI_FLOAT_WIDTH) << std::setfill(' ') << v.x << DEL;
file << "V: " << std::setw(SCI_FLOAT_WIDTH) << std::setfill(' ') << v.y;
}
};
auto WriteUV_vert = [this, WriteUV_vec](const GSVertex& v) {
GSVector4 vec;
if (PRIM->FST)
vec = GSVector4(v.U / 16.0f, v.V / 16.0f);
else
vec = GSVector4(
(v.ST.S / v.RGBAQ.Q) * (1 << m_context->TEX0.TW),
(v.ST.T / v.RGBAQ.Q) * (1 << m_context->TEX0.TH)
);
WriteUV_vec(vec);
};
auto WriteRGBA_vec = [&file](const GSVector4i& v) {
file << std::dec << std::right;
file << "R: " << std::setw(RGBA_WIDTH) << std::setfill(' ') << v.r << DEL;
file << "G: " << std::setw(RGBA_WIDTH) << std::setfill(' ') << v.g << DEL;
file << "B: " << std::setw(RGBA_WIDTH) << std::setfill(' ') << v.b << DEL;
file << "A: " << std::setw(RGBA_WIDTH) << std::setfill(' ') << v.a;
};
auto WriteRGBA_vert = [WriteRGBA_vec](const GSVertex& v) {
GSVector4i vec = GSVector4i(v.RGBAQ.R, v.RGBAQ.G, v.RGBAQ.B, v.RGBAQ.A);
WriteRGBA_vec(vec);
};
auto WriteSTQ_vec = [&file](const GSVector4& v) {
file << std::defaultfloat << std::right;
file << "S: " << std::setw(SCI_FLOAT_WIDTH) << std::setfill(' ') << v.x << DEL;
file << "T: " << std::setw(SCI_FLOAT_WIDTH) << std::setfill(' ') << v.y << DEL;
file << "Q: " << std::setw(SCI_FLOAT_WIDTH) << std::setfill(' ') << v.z;
};
auto WriteSTQ_bits = [&file](const GSVector4& v) {
file << std::hex << std::showbase << std::right;
file << "Si: " << std::setw(STQ_BITS_WIDTH) << std::setfill('0') << std::bit_cast<u32>(v.x) << DEL;
file << "Ti: " << std::setw(STQ_BITS_WIDTH) << std::setfill('0') << std::bit_cast<u32>(v.y) << DEL;
file << "Qi: " << std::setw(STQ_BITS_WIDTH) << std::setfill('0') << std::bit_cast<u32>(v.z);
};
auto WriteSTQ_vert = [&file, WriteSTQ_vec, WriteSTQ_bits](const GSVertex& v) {
GSVector4 vec = GSVector4(v.ST.S, v.ST.T, v.RGBAQ.Q, v.RGBAQ.Q);
WriteSTQ_vec(vec);
file << DEL;
WriteSTQ_bits(vec);
};
auto WriteBools = [&file](std::vector<const char*> names, std::vector<u32> values) {
for (int i = 0; i < static_cast<int>(names.size()); i++)
{
if (i > 0)
file << DEL;
file << names[i] << ": " << static_cast<bool>(values[i]);
}
};
// Dump flush reason
file << "flush_reason: \"" << GetFlushReasonString(m_state_flush_reason);
if (m_state_flush_reason != GSFlushReason::CONTEXTCHANGE && m_dirty_gs_regs)
file << " AND POSSIBLE CONTEXT CHANGE";
file << "\"" << std::endl;
file << std::endl << std::endl;
const u32 count = m_index.tail;
GSVertex* buffer = &m_vertex.buff[0];
const char* DEL = ", ";
file << "VERTEX COORDS (XYZ)" << std::endl;
file << std::fixed << std::setprecision(4);
for (u32 i = 0; i < count; ++i)
{
file << "\t" << std::dec << "v" << i << ": ";
GSVertex v = buffer[m_index.buff[i]];
const float x = (v.XYZ.X - (int)m_context->XYOFFSET.OFX) / 16.0f;
const float y = (v.XYZ.Y - (int)m_context->XYOFFSET.OFY) / 16.0f;
file << x << DEL;
file << y << DEL;
file << v.XYZ.Z;
file << std::endl;
}
file << std::endl;
// Dump vertices
file << "vertex:" << std::endl;
const u32 count = m_index.tail;
GSVertex* buffer = &m_vertex.buff[0];
file << "VERTEX COLOR (RGBA)" << std::endl;
file << std::fixed << std::setprecision(6);
for (u32 i = 0; i < count; ++i)
{
file << "\t" << std::dec << "v" << i << ": ";
GSVertex v = buffer[m_index.buff[i]];
file << INDENT << LIST_ITEM << OPEN_MAP;
WriteXYZ_vert(v);
if (PRIM->TME)
{
file << DEL;
WriteUV_vert(v);
}
file << DEL;
WriteRGBA_vert(v);
file << CLOSE_MAP;
WriteVertexIndex(i);
file << std::setfill('0') << std::setw(3) << unsigned(v.RGBAQ.R) << DEL;
file << std::setfill('0') << std::setw(3) << unsigned(v.RGBAQ.G) << DEL;
file << std::setfill('0') << std::setw(3) << unsigned(v.RGBAQ.B) << DEL;
file << std::setfill('0') << std::setw(3) << unsigned(v.RGBAQ.A) << DEL;
file << "FOG: " << std::setfill('0') << std::setw(3) << unsigned(v.FOG);
file << std::endl;
}
file << std::endl;
const bool use_uv = PRIM->FST;
const std::string qualifier = use_uv ? "UV" : "STQ";
file << "TEXTURE COORDS (" << qualifier << ")" << std::endl;;
for (u32 i = 0; i < count; ++i)
{
file << "\t" << "v" << std::dec << i << ": ";
const GSVertex v = buffer[m_index.buff[i]];
// note
// Yes, technically as far as the GS is concerned Q belongs
// to RGBAQ. However, the purpose of this dump is to print
// our data in a more human readable format and typically Q
// is associated with STQ.
if (use_uv)
{
const float uv_U = v.U / 16.0f;
const float uv_V = v.V / 16.0f;
file << uv_U << DEL << uv_V;
}
else
{
float x = (v.ST.S / v.RGBAQ.Q) * (1 << m_context->TEX0.TW);
float y = (v.ST.T / v.RGBAQ.Q) * (1 << m_context->TEX0.TH);
file << v.ST.S << "(" << std::hex << std::bit_cast<u32>(v.ST.S) << ")" << DEL << v.ST.T << "(" << std::hex << std::bit_cast<u32>(v.ST.T) << ")" << DEL << v.RGBAQ.Q << "(" << std::hex << std::bit_cast<u32>(v.RGBAQ.Q) << ") - " << x << "," << y;
}
file << std::endl;
}
file << std::endl;
// Dump extra info for STQ
if (PRIM->TME && !PRIM->FST)
{
file << "vertex_stq:" << std::endl;
for (u32 i = 0; i < count; ++i)
{
file << INDENT << LIST_ITEM << OPEN_MAP;
WriteSTQ_vert(buffer[m_index.buff[i]]);
file << CLOSE_MAP;
file << "TRACER" << std::dec << std::endl;
WriteVertexIndex(i);
GSVector4i v = m_vt.m_min.c;
file << "\tmin c (r,g,b,a): " << v.x << DEL << v.y << DEL << v.z << DEL << v.w << std::endl;
v = m_vt.m_max.c;
file << "\tmax c (r,g,b,a): " << v.x << DEL << v.y << DEL << v.z << DEL << v.w << std::endl;
file << std::endl;
}
}
GSVector4 v2 = m_vt.m_min.p;
file << "\tmin p (x,y,z,f): " << v2.x << DEL << v2.y << DEL << v2.z << DEL << (u32)v2.w << std::endl;
v2 = m_vt.m_max.p;
file << "\tmax p (x,y,z,f): " << v2.x << DEL << v2.y << DEL << v2.z << DEL << (u32)v2.w << std::endl;
v2 = m_vt.m_min.t;
file << "\tmin t (u,v,q): " << v2.x << DEL << v2.y << DEL << v2.z << std::endl;
v2 = m_vt.m_max.t;
file << "\tmax t (u,v,q): " << v2.x << DEL << v2.y << DEL << v2.z << std::endl;
file << std::endl;
// Dump vertex trace
file << "vertex_trace:" << std::endl;
file << INDENT;
WriteTraceIndex("min_xyz: ");
file << OPEN_MAP;
WriteXYZ_vec(m_vt.m_min.p);
file << CLOSE_MAP << std::endl;
file << INDENT;
WriteTraceIndex("max_xyz: ");
file << OPEN_MAP;
WriteXYZ_vec(m_vt.m_max.p);
file << CLOSE_MAP << std::endl;
if (PRIM->TME)
{
if (PRIM->FST)
{
file << INDENT;
WriteTraceIndex("min_uv: ");
file << OPEN_MAP;
WriteUV_vec(m_vt.m_min.t);
file << CLOSE_MAP << std::endl;
file << INDENT;
WriteTraceIndex("max_uv: ");
file << OPEN_MAP;
WriteUV_vec(m_vt.m_max.t);
file << CLOSE_MAP << std::endl;
}
else
{
// Note: The vertex trace does not actually track the min/max of raw ST values
// hence the labels "min_uvq" and "max_uvq" are used instead of "min_stq" and "max_stq".
file << INDENT;
WriteTraceIndex("min_uvq: ");
file << OPEN_MAP;
WriteSTQ_vec(m_vt.m_min.t);
file << CLOSE_MAP << std::endl;
file << INDENT;
WriteTraceIndex("max_uvq: ");
file << OPEN_MAP;
WriteSTQ_vec(m_vt.m_max.t);
file << CLOSE_MAP << std::endl;
}
}
file << INDENT;
WriteTraceIndex("min_rgba: ");
file << OPEN_MAP;
WriteRGBA_vec(m_vt.m_min.c);
file << CLOSE_MAP << std::endl;
file << INDENT;
WriteTraceIndex("max_rgba: ");
file << OPEN_MAP;
WriteRGBA_vec(m_vt.m_max.c);
file << CLOSE_MAP << std::endl;
file << std::endl;
file << INDENT;
WriteTraceIndex("eq_xyz: ");
file << OPEN_MAP;
WriteBools({"X", "Y", "Z"}, {m_vt.m_eq.x, m_vt.m_eq.y, m_vt.m_eq.z});
file << CLOSE_MAP << std::endl;
if (PRIM->TME)
{
if (PRIM->FST)
{
file << INDENT;
WriteTraceIndex("eq_uv: ");
file << OPEN_MAP;
WriteBools({"U", "V"}, {m_vt.m_eq.s, m_vt.m_eq.t});
file << CLOSE_MAP << std::endl;
}
else
{
// Note: The vertex trace does not actually track the min/max of raw ST values
// hence the labels "eq_uvq" is used instead of "eq_stq".
file << INDENT;
WriteTraceIndex("eq_uvq: ");
file << OPEN_MAP;
WriteBools({"U", "V", "Q"}, {m_vt.m_eq.s, m_vt.m_eq.t, m_vt.m_eq.q});
file << CLOSE_MAP << std::endl;
}
}
file << INDENT;
WriteTraceIndex("eq_rgba: ");
file << OPEN_MAP;
WriteBools({"R", "G", "B", "A"}, {m_vt.m_eq.r, m_vt.m_eq.g, m_vt.m_eq.b, m_vt.m_eq.a});
file << CLOSE_MAP << std::endl;
}
void GSState::DumpTransferList(const std::string& filename)
{
// Only create the file if there are transfers to dump
std::optional<std::ofstream> file;
constexpr const char* LIST_ITEM = "- ";
constexpr const char* DEL = ", ";
constexpr const char* INDENT = " ";
constexpr const char* OPEN_MAP = "{";
constexpr const char* CLOSE_MAP = "}";
constexpr const char* COMMENT = " # ";
int n_dumped = 0; // Number of transfers dumped for this draw.
for (int i = 0; i < static_cast<int>(m_draw_transfers.size()); ++i)
{
if (m_draw_transfers[i].draw != s_n - 1)
continue; // skip transfers that did not start in the previous draw
if (!file.has_value())
{
file.emplace(filename);
if (!file->is_open())
return; // failed to open file
file->imbue(std::locale::classic()); // Disable integer separators.
}
const GSUploadQueue& transfer = m_draw_transfers[i];
if (n_dumped > 0)
(*file) << std::endl;
// EE->GS or GS->GS
(*file) << LIST_ITEM << "type: " << (transfer.ee_to_gs ? "EE_to_GS" : "GS_to_GS") << std::endl;
// Dump BITBLTBUF
(*file) << INDENT << "BITBLTBUF: " << OPEN_MAP;
if (!transfer.ee_to_gs)
{
// Transferring GS->GS so the source info is relevant
(*file) << "SBP: " << std::hex << std::showbase << transfer.blit.SBP << DEL <<
"SBW: " << std::dec << transfer.blit.SBW << DEL <<
"SPSM: " << std::hex << std::showbase << transfer.blit.SPSM << DEL;
}
(*file) << "DBP: " << std::hex << std::showbase << transfer.blit.DBP << DEL <<
"DBW: " << std::dec << transfer.blit.DBW << DEL <<
"DPSM: " << std::hex << std::showbase << transfer.blit.DPSM << CLOSE_MAP;
(*file) << COMMENT; // Write the human-readable PSM in comments
if (!transfer.ee_to_gs)
{
// Transferring GS->GS so the source info is relevant
(*file) << GSUtil::GetPSMName(transfer.blit.SPSM) << " -> ";
}
(*file) << GSUtil::GetPSMName(transfer.blit.DPSM) << std::endl;
// Dump rectangle
(*file) << INDENT << "rect: [" << std::dec << transfer.rect.x << DEL << transfer.rect.y << DEL <<
transfer.rect.z << DEL << transfer.rect.w << "]" << std::endl;
// Dump zero_clear
(*file) << INDENT << "zero_clear: " << (transfer.zero_clear ? "true" : "false") << std::endl;
n_dumped++;
}
}
void GSState::DumpTransferImages()
{
// Only create the file if there are transfers to dump
std::optional<std::ofstream> file;
int transfer_n = 0;
for (int i = 0; i < static_cast<int>(m_draw_transfers.size()); ++i)
{
if (m_draw_transfers[i].draw != s_n - 1)
continue; // skip transfers that did not start in the previous draw
const GSUploadQueue& transfer = m_draw_transfers[i];
std::string filename;
if (transfer.ee_to_gs)
{
// Transferring EE->GS then only the destination info is relevant.
filename = GetDrawDumpPath("%05d_transfer%02d_EE_to_GS_%03x_%d_%s_%d_%d_%d_%d.png",
s_n, transfer_n++, transfer.blit.DBP, transfer.blit.DBW, GSUtil::GetPSMName(transfer.blit.DPSM),
transfer.rect.x, transfer.rect.y, transfer.rect.z, transfer.rect.w);
}
else
{
// Transferring GS->GS then the source info is relevant.
filename = GetDrawDumpPath("%05d_transfer%02d_GS_to_GS_%03x_%d_%s_%03x_%d_%s_%d_%d_%d_%d.bmp",
s_n, transfer_n++, transfer.blit.SBP, transfer.blit.SBW, GSUtil::GetPSMName(transfer.blit.SPSM),
transfer.blit.DBP, transfer.blit.DBW, GSUtil::GetPSMName(transfer.blit.DPSM),
transfer.rect.x, transfer.rect.y, transfer.rect.z, transfer.rect.w);
}
m_mem.SaveBMP(filename, transfer.blit.DBP, transfer.blit.DBW, transfer.blit.DPSM,
transfer.rect.width(), transfer.rect.height(), transfer.rect.x, transfer.rect.y);
}
file << "\teq c (r,g,b,a): " << (m_vt.m_eq.r & 1) << DEL << (m_vt.m_eq.g & 1) << DEL << (m_vt.m_eq.b & 1) << DEL << (m_vt.m_eq.a & 1) << std::endl;
file << "\teq p (x,y,z,f): " << (m_vt.m_eq.x & 1) << DEL << (m_vt.m_eq.y & 1) << DEL << (m_vt.m_eq.z & 1) << DEL << (m_vt.m_eq.f & 1) << std::endl;
file << "\teq t (u,v,q) : " << (m_vt.m_eq.s & 1) << DEL << (m_vt.m_eq.t & 1) << DEL << (m_vt.m_eq.q & 1) << std::endl;
file.close();
}
__inline void GSState::CheckFlushes()
@@ -2062,20 +1771,6 @@ void GSState::FlushPrim()
const bool skip_draw = (m_context->TEST.ZTE && m_context->TEST.ZTST == ZTST_NEVER);
m_quad_check_valid = false;
if (GSConfig.ShouldDump(s_n, g_perfmon.GetFrame()))
{
if (GSConfig.SaveInfo)
{
// Only dump registers/vertices if we are drawing.
// Always dump the transfers since these are relevant for debugging regardless of
// whether the draw is skipped or not.
DumpDrawInfo(!skip_draw, !skip_draw, true);
}
if (GSConfig.SaveTransferImages)
DumpTransferImages();
}
if (!skip_draw)
Draw();
@@ -2321,7 +2016,7 @@ void GSState::Write(const u8* mem, int len)
}
else
{
const GSUploadQueue new_transfer = { blit, r, s_n, false, true };
GSUploadQueue new_transfer = { blit, r, s_n, false };
m_draw_transfers.push_back(new_transfer);
}
@@ -2512,7 +2207,7 @@ void GSState::Move()
}
else
{
const GSUploadQueue new_transfer = { m_env.BITBLTBUF, r, s_n, false, false };
GSUploadQueue new_transfer = { m_env.BITBLTBUF, r, s_n, false };
m_draw_transfers.push_back(new_transfer);
}
-4
View File
@@ -215,7 +215,6 @@ public:
GSVector4i rect;
int draw;
bool zero_clear;
bool ee_to_gs;
};
enum NoGapsType
@@ -442,10 +441,7 @@ public:
u8* GetRegsMem() const { return reinterpret_cast<u8*>(m_regs); }
void SetRegsMem(u8* basemem) { m_regs = reinterpret_cast<GSPrivRegSet*>(basemem); }
void DumpDrawInfo(bool dump_regs, bool dump_verts, bool dump_transfers);
void DumpVertices(const std::string& filename);
void DumpTransferList(const std::string& filename);
void DumpTransferImages();
bool TrianglesAreQuads(bool shuffle_check = false);
PRIM_OVERLAP PrimitiveOverlap();
-55
View File
@@ -114,61 +114,6 @@ const char* GSUtil::GetPrimName(u32 prim)
return (prim < std::size(names)) ? names[prim] : "";
}
const char* GSUtil::GetMMAGName(u32 mmag)
{
static constexpr const char* names[] = {"NEAREST", "LINEAR"};
return (mmag < std::size(names)) ? names[mmag] : "";
}
const char* GSUtil::GetMMINName(u32 mmin)
{
static constexpr const char* names[8] = {"NEAREST", "LINEAR", "NEAREST_MIPMAP_NEAREST", "NEAREST_MIPMAP_LINEAR",
"LINEAR_MIPMAP_NEAREST", "LINEAR_MIPMAP_LINEAR"};
return (mmin < std::size(names)) ? names[mmin] : "";
}
const char* GSUtil::GetMTBAName(u32 mtba)
{
static constexpr const char* names[] = {"MIPTBP1", "AUTO"};
return (mtba < std::size(names)) ? names[mtba] : "";
}
const char* GSUtil::GetLCMName(u32 lcm)
{
static constexpr const char* names[] = {"Formula", "K"};
return (lcm < std::size(names)) ? names[lcm] : "";
}
const char* GSUtil::GetSCANMSKName(u32 scanmsk)
{
static constexpr const char* names[] = {"Normal", "Reserved", "Even prohibited", "Odd prohibited"};
return (scanmsk < std::size(names)) ? names[scanmsk] : "";
}
const char* GSUtil::GetDATMName(u32 datm)
{
static constexpr const char* names[] = {"0 pass", "1 pass"};
return (datm < std::size(names)) ? names[datm] : "";
}
const char* GSUtil::GetTFXName(u32 tfx)
{
static constexpr const char* names[] = {"MODULATE", "DECAL", "HIGHLIGHT", "HIGHLIGHT2"};
return (tfx < std::size(names)) ? names[tfx] : "";
}
const char* GSUtil::GetTCCName(u32 tcc)
{
static constexpr const char* names[] = {"RGB", "RGBA"};
return (tcc < std::size(names)) ? names[tcc] : "";
}
const char* GSUtil::GetACName(u32 ac)
{
static constexpr const char* names[] = {"PRMODE", "PRIM"};
return (ac < std::size(names)) ? names[ac] : "";
}
const u32* GSUtil::HasSharedBitsPtr(u32 dpsm)
{
return s_maps.SharedBitsField[dpsm];
-9
View File
@@ -15,15 +15,6 @@ public:
static const char* GetWMName(u32 wm);
static const char* GetZTSTName(u32 ztst);
static const char* GetPrimName(u32 prim);
static const char* GetMMAGName(u32 mmag);
static const char* GetMMINName(u32 mmin);
static const char* GetMTBAName(u32 mtba);
static const char* GetLCMName(u32 lcm);
static const char* GetSCANMSKName(u32 scanmsk);
static const char* GetDATMName(u32 datm);
static const char* GetTFXName(u32 tfx);
static const char* GetTCCName(u32 tcc);
static const char* GetACName(u32 ac);
static const u32* HasSharedBitsPtr(u32 dpsm);
static bool HasSharedBits(u32 spsm, const u32* ptr);
+4
View File
@@ -985,6 +985,10 @@ public:
__forceinline GSVector4i modulate16(const GSVector4i& f) const
{
// a * f << shift
if (shift == 0)
{
return mul16hrs(f);
}
return sll16<shift + 1>().mul16hs(f);
}
+4
View File
@@ -958,6 +958,10 @@ public:
__forceinline GSVector4i modulate16(const GSVector4i& f) const
{
// a * f << shift
if (shift == 0)
{
return mul16hrs(f);
}
return sll16<shift + 1>().mul16hs(f);
}
+5
View File
@@ -798,6 +798,11 @@ public:
{
// a * f << shift
if (shift == 0)
{
return mul16hrs(f);
}
return sll16<shift + 1>().mul16hs(f);
}
-35
View File
@@ -397,41 +397,6 @@ void GSDevice::ClearDepth(GSTexture* t, float d)
t->SetClearDepth(d);
}
bool GSDevice::ProcessClearsBeforeCopy(GSTexture* sTex, GSTexture* dTex, const bool full_copy)
{
pxAssert(sTex->GetState() == GSTexture::State::Cleared && dTex->IsRenderTargetOrDepthStencil());
// Pass it forward if we're clearing the whole thing.
if (full_copy)
{
if (dTex->IsDepthStencil())
dTex->SetClearDepth(sTex->GetClearDepth());
else
dTex->SetClearColor(sTex->GetClearColor());
dTex->SetState(GSTexture::State::Cleared);
return true;
}
// Destination is cleared, if it's the same colour and rect, we can just avoid this entirely.
if (dTex->GetState() == GSTexture::State::Cleared)
{
if (dTex->IsDepthStencil())
{
if (dTex->GetClearDepth() == sTex->GetClearDepth())
return true;
}
else
{
if (dTex->GetClearColor() == sTex->GetClearColor())
return true;
}
}
return false;
}
void GSDevice::InvalidateRenderTarget(GSTexture* t)
{
t->SetState(GSTexture::State::Invalidated);
-1
View File
@@ -1022,7 +1022,6 @@ public:
void ClearRenderTarget(GSTexture* t, u32 c);
void ClearDepth(GSTexture* t, float d);
bool ProcessClearsBeforeCopy(GSTexture* sTex, GSTexture* dTex, const bool full_copy);
void InvalidateRenderTarget(GSTexture* t);
virtual void PushDebugGroup(const char* fmt, ...) = 0;
+18 -38
View File
@@ -107,20 +107,9 @@ bool GSRenderer::Merge(int field)
}
else
{
const bool use_rc1 =
PCRTCDisplays.PCRTCDisplays[0].enabled && // RC1 enabled.
(!(m_regs->PMODE.MMOD == 1 && m_regs->PMODE.ALP == 0) || // Blend RC1 with non-zero alpha.
(m_regs->PMODE.AMOD == 0) || // Use alpha of RC1.
(feedback_merge && m_regs->EXTBUF.FBIN == 0)); // Use RC1 for feedback merge.
const bool use_rc2 =
PCRTCDisplays.PCRTCDisplays[1].enabled && // RC2 enabled.
// Blending RC2 and not overwriting completely with RC1.
((m_regs->PMODE.SLBG == 0 && !(use_rc1 && m_regs->PMODE.MMOD == 1 && m_regs->PMODE.ALP == 255)) ||
(m_regs->PMODE.AMOD == 1) || // Use alpha of RC2.
(feedback_merge && m_regs->EXTBUF.FBIN == 1)); // Use RC2 for feedback merge.
if (use_rc1)
if (PCRTCDisplays.PCRTCDisplays[0].enabled)
tex[0] = GetOutput(0, tex_scale[0], y_offset[0]);
if (use_rc2)
if (PCRTCDisplays.PCRTCDisplays[1].enabled)
tex[1] = GetOutput(1, tex_scale[1], y_offset[1]);
if (feedback_merge)
tex[2] = GetFeedbackOutput(tex_scale[2]);
@@ -580,17 +569,9 @@ void GSRenderer::EndPresentFrame()
void GSRenderer::VSync(u32 field, bool registers_written, bool idle_frame)
{
if (GSConfig.ShouldDump(s_n, g_perfmon.GetFrame()))
if (GSConfig.SaveInfo && GSConfig.ShouldDump(s_n, g_perfmon.GetFrame()))
{
if (GSConfig.SaveInfo)
{
DumpGSPrivRegs(*m_regs, GetDrawDumpPath("%05d_f%05lld_vsync_gs_reg.txt", s_n, g_perfmon.GetFrame()));
DumpDrawInfo(false, false, true);
}
if (GSConfig.SaveTransferImages)
DumpTransferImages();
DumpGSPrivRegs(*m_regs, GetDrawDumpPath("%05d_f%05lld_vsync_gs_reg.txt", s_n, g_perfmon.GetFrame()));
}
const int fb_sprite_blits = g_perfmon.GetDisplayFramebufferSpriteBlits();
@@ -1107,7 +1088,7 @@ void DumpGSPrivRegs(const GSPrivRegSet& r, const std::string& filename)
if (i == 1 && !r.PMODE.EN2)
continue;
std::fprintf(fp.get(), "DISPFB%d: { BP: 0x%05x, BW: %u, PSM: %u, DBX: %u, DBY: %u }\n",
std::fprintf(fp.get(), "DISPFB[%d] BP=%05x BW=%u PSM=%u DBX=%u DBY=%u\n",
i,
r.DISP[i].DISPFB.Block(),
r.DISP[i].DISPFB.FBW,
@@ -1115,7 +1096,7 @@ void DumpGSPrivRegs(const GSPrivRegSet& r, const std::string& filename)
r.DISP[i].DISPFB.DBX,
r.DISP[i].DISPFB.DBY);
std::fprintf(fp.get(), "DISPLAY%d: { DX: %u, DY: %u, DW: %u, DH: %u, MAGH: %u, MAGV: %u }\n",
std::fprintf(fp.get(), "DISPLAY[%d] DX=%u DY=%u DW=%u DH=%u MAGH=%u MAGV=%u\n",
i,
r.DISP[i].DISPLAY.DX,
r.DISP[i].DISPLAY.DY,
@@ -1125,7 +1106,7 @@ void DumpGSPrivRegs(const GSPrivRegSet& r, const std::string& filename)
r.DISP[i].DISPLAY.MAGV);
}
std::fprintf(fp.get(), "PMODE: { EN1: %u, EN2: %u, CRTMD: %u, MMOD: %u, AMOD: %u, SLBG: %u, ALP: %u }\n",
std::fprintf(fp.get(), "PMODE EN1=%u EN2=%u CRTMD=%u MMOD=%u AMOD=%u SLBG=%u ALP=%u\n",
r.PMODE.EN1,
r.PMODE.EN2,
r.PMODE.CRTMD,
@@ -1134,8 +1115,7 @@ void DumpGSPrivRegs(const GSPrivRegSet& r, const std::string& filename)
r.PMODE.SLBG,
r.PMODE.ALP);
std::fprintf(fp.get(),
"SMODE1: { CLKSEL: %u, CMOD: %u, EX: %u, GCONT: %u, LC: %u, NVCK: %u, PCK2: %u, PEHS: %u, PEVS: %u, PHS: %u, PRST: %u, PVS: %u, RC: %u, SINT: %u, SLCK: %u, SLCK2: %u, SPML: %u, T1248: %u, VCKSEL: %u, VHP: %u, XPCK: %u }\n",
std::fprintf(fp.get(), "SMODE1 CLKSEL=%u CMOD=%u EX=%u GCONT=%u LC=%u NVCK=%u PCK2=%u PEHS=%u PEVS=%u PHS=%u PRST=%u PVS=%u RC=%u SINT=%u SLCK=%u SLCK2=%u SPML=%u T1248=%u VCKSEL=%u VHP=%u XPCK=%u\n",
r.SMODE1.CLKSEL,
r.SMODE1.CMOD,
r.SMODE1.EX,
@@ -1158,24 +1138,24 @@ void DumpGSPrivRegs(const GSPrivRegSet& r, const std::string& filename)
r.SMODE1.VHP,
r.SMODE1.XPCK);
std::fprintf(fp.get(), "SMODE2: { INT: %u, FFMD: %u, DPMS: %u }\n",
std::fprintf(fp.get(), "SMODE2 INT=%u FFMD=%u DPMS=%u\n",
r.SMODE2.INT,
r.SMODE2.FFMD,
r.SMODE2.DPMS);
std::fprintf(fp.get(), "SRFSH: { U32_0: 0x%08x, U32_1: 0x%08x }\n",
std::fprintf(fp.get(), "SRFSH %08x_%08x\n",
r.SRFSH.U32[0],
r.SRFSH.U32[1]);
std::fprintf(fp.get(), "SYNCH1: { U32_0: 0x%08x, U32_1: 0x%08x }\n",
std::fprintf(fp.get(), "SYNCH1 %08x_%08x\n",
r.SYNCH1.U32[0],
r.SYNCH1.U32[1]);
std::fprintf(fp.get(), "SYNCH2: { U32_0: 0x%08x, U32_1: 0x%08x }\n",
std::fprintf(fp.get(), "SYNCH2 %08x_%08x\n",
r.SYNCH2.U32[0],
r.SYNCH2.U32[1]);
std::fprintf(fp.get(), "SYNCV: { VBP: %u, VBPE: %u, VDP: %u, VFP: %u, VFPE: %u, VS: %u }\n",
std::fprintf(fp.get(), "SYNCV VBP=%u VBPE=%u VDP=%u VFP=%u VFPE=%u VS=%u\n",
r.SYNCV.VBP,
r.SYNCV.VBPE,
r.SYNCV.VDP,
@@ -1183,21 +1163,21 @@ void DumpGSPrivRegs(const GSPrivRegSet& r, const std::string& filename)
r.SYNCV.VFPE,
r.SYNCV.VS);
std::fprintf(fp.get(), "CSR: { U32_0: 0x%08x, U32_1: 0x%08x }\n",
std::fprintf(fp.get(), "CSR %08x_%08x\n",
r.CSR.U32[0],
r.CSR.U32[1]);
std::fprintf(fp.get(), "BGCOLOR: { B: %u, G: %u, R: %u }\n",
std::fprintf(fp.get(), "BGCOLOR B=%u G=%u R=%u\n",
r.BGCOLOR.B,
r.BGCOLOR.G,
r.BGCOLOR.R);
std::fprintf(fp.get(), "EXTBUF: { BP: 0x%05x, BW: %u, FBIN: %u, WFFMD: %u, EMODA: %u, EMODC: %u, WDX: %u, WDY: %u }\n",
std::fprintf(fp.get(), "EXTBUF BP=0x%x BW=%u FBIN=%u WFFMD=%u EMODA=%u EMODC=%u WDX=%u WDY=%u\n",
r.EXTBUF.EXBP, r.EXTBUF.EXBW, r.EXTBUF.FBIN, r.EXTBUF.WFFMD,
r.EXTBUF.EMODA, r.EXTBUF.EMODC, r.EXTBUF.WDX, r.EXTBUF.WDY);
std::fprintf(fp.get(), "EXTDATA: { SX: %u, SY: %u, SMPH: %u, SMPV: %u, WW: %u, WH: %u }\n",
std::fprintf(fp.get(), "EXTDATA SX=%u SY=%u SMPH=%u SMPV=%u WW=%u WH=%u\n",
r.EXTDATA.SX, r.EXTDATA.SY, r.EXTDATA.SMPH, r.EXTDATA.SMPV, r.EXTDATA.WW, r.EXTDATA.WH);
std::fprintf(fp.get(), "EXTWRITE: { EN: %u }\n", r.EXTWRITE.WRITE);
std::fprintf(fp.get(), "EXTWRITE EN=%u\n", r.EXTWRITE.WRITE);
}
+1 -1
View File
@@ -409,7 +409,7 @@ GSRendererType D3D::GetPreferredRenderer()
return true;
Host::AddIconOSDMessage("VKDriverUnsupported", ICON_FA_TV, TRANSLATE_STR("GS",
"The Vulkan graphics API was automatically selected, but no compatible devices were found.\n"
"The Vulkan renderer was automatically selected, but no compatible devices were found.\n"
" You should update all graphics drivers in your system, including any integrated GPUs\n"
" to use the Vulkan renderer."), Host::OSD_WARNING_DURATION);
return false;
+7 -26
View File
@@ -1229,41 +1229,22 @@ std::unique_ptr<GSDownloadTexture> GSDevice11::CreateDownloadTexture(u32 width,
void GSDevice11::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, u32 destX, u32 destY)
{
const GSVector4i dst_rect(0, 0, dTex->GetWidth(), dTex->GetHeight());
const bool full_draw_copy = sTex->IsDepthStencil() || dst_rect.eq(r);
// Source is cleared, if destination is a render target, we can carry the clear forward.
if (sTex->GetState() == GSTexture::State::Cleared)
{
if (dTex->IsRenderTargetOrDepthStencil() && ProcessClearsBeforeCopy(sTex, dTex, full_draw_copy))
return;
// Commit clear for the source texture.
CommitClear(sTex);
}
CommitClear(sTex);
CommitClear(dTex);
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
// Commit destination clear if partially overwritten (color only).
if (dTex->GetState() == GSTexture::State::Cleared && !full_draw_copy)
CommitClear(dTex);
// DX11 doesn't support partial depth copy so we need to
// either pass a nullptr D3D11_BOX for a full depth copy or use CopyResource instead.
// Optimization: Use CopyResource for depth copies or full rect color copies, it's faster than CopySubresourceRegion.
const GSVector4i src_rect(0, 0, sTex->GetWidth(), sTex->GetHeight());
const bool full_rt_copy = sTex->IsDepthStencil() || (destX == 0 && destY == 0 && r.eq(src_rect) && src_rect.eq(dst_rect));
if (full_rt_copy)
// Optimization: Use CopyResource for depth copies, it's faster than CopySubresourceRegion.
if (sTex->GetType() == GSTexture::Type::DepthStencil)
{
m_ctx->CopyResource(*static_cast<GSTexture11*>(dTex), *static_cast<GSTexture11*>(sTex));
}
else
{
const D3D11_BOX box = {static_cast<UINT>(r.left), static_cast<UINT>(r.top), 0U, static_cast<UINT>(r.right), static_cast<UINT>(r.bottom), 1U};
m_ctx->CopySubresourceRegion(*static_cast<GSTexture11*>(dTex), 0, destX, destY, 0, *static_cast<GSTexture11*>(sTex), 0, &box);
return;
}
dTex->SetState(GSTexture::State::Dirty);
D3D11_BOX box = {static_cast<UINT>(r.left), static_cast<UINT>(r.top), 0U, static_cast<UINT>(r.right), static_cast<UINT>(r.bottom), 1U};
m_ctx->CopySubresourceRegion(*static_cast<GSTexture11*>(dTex), 0, destX, destY, 0, *static_cast<GSTexture11*>(sTex), 0, &box);
}
void GSDevice11::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderConvert shader, bool linear)
+50 -39
View File
@@ -1337,66 +1337,77 @@ std::unique_ptr<GSDownloadTexture> GSDevice12::CreateDownloadTexture(u32 width,
void GSDevice12::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, u32 destX, u32 destY)
{
GSTexture12* const sTex12 = static_cast<GSTexture12*>(sTex);
GSTexture12* const dTex12 = static_cast<GSTexture12*>(dTex);
const GSVector4i dst_rect(0, 0, dTex12->GetWidth(), dTex12->GetHeight());
const bool full_draw_copy = dst_rect.eq(r);
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
// Source is cleared, if destination is a render target, we can carry the clear forward.
if (sTex12->GetState() == GSTexture::State::Cleared)
GSTexture12* const sTexVK = static_cast<GSTexture12*>(sTex);
GSTexture12* const dTexVK = static_cast<GSTexture12*>(dTex);
const GSVector4i dtex_rc(0, 0, dTexVK->GetWidth(), dTexVK->GetHeight());
if (sTexVK->GetState() == GSTexture::State::Cleared)
{
if (dTex12->IsRenderTargetOrDepthStencil() && ProcessClearsBeforeCopy(sTex, dTex, full_draw_copy))
return;
// Do an attachment clear.
EndRenderPass();
dTex12->SetState(GSTexture::State::Dirty);
if (dTex12->GetType() != GSTexture::Type::DepthStencil)
// source is cleared. if destination is a render target, we can carry the clear forward
if (dTexVK->IsRenderTargetOrDepthStencil())
{
dTex12->TransitionToState(D3D12_RESOURCE_STATE_RENDER_TARGET);
GetCommandList()->ClearRenderTargetView(
dTex12->GetWriteDescriptor(), sTex12->GetUNormClearColor().v, 0, nullptr);
}
else
{
dTex12->TransitionToState(D3D12_RESOURCE_STATE_DEPTH_WRITE);
GetCommandList()->ClearDepthStencilView(
dTex12->GetWriteDescriptor(), D3D12_CLEAR_FLAG_DEPTH, sTex12->GetClearDepth(), 0, 0, nullptr);
}
if (dtex_rc.eq(r))
{
// pass it forward if we're clearing the whole thing
if (sTexVK->IsDepthStencil())
dTexVK->SetClearDepth(sTexVK->GetClearDepth());
else
dTexVK->SetClearColor(sTexVK->GetClearColor());
return;
return;
}
else
{
// otherwise we need to do an attachment clear
EndRenderPass();
dTexVK->SetState(GSTexture::State::Dirty);
if (dTexVK->GetType() != GSTexture::Type::DepthStencil)
{
dTexVK->TransitionToState(D3D12_RESOURCE_STATE_RENDER_TARGET);
GetCommandList()->ClearRenderTargetView(
dTexVK->GetWriteDescriptor(), sTexVK->GetUNormClearColor().v, 0, nullptr);
}
else
{
dTexVK->TransitionToState(D3D12_RESOURCE_STATE_DEPTH_WRITE);
GetCommandList()->ClearDepthStencilView(
dTexVK->GetWriteDescriptor(), D3D12_CLEAR_FLAG_DEPTH, sTexVK->GetClearDepth(), 0, 0, nullptr);
}
return;
}
}
// commit the clear to the source first, then do normal copy
sTex12->CommitClear();
sTexVK->CommitClear();
}
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
// if the destination has been cleared, and we're not overwriting the whole thing, commit the clear first
// (the area outside of where we're copying to)
if (dTex12->GetState() == GSTexture::State::Cleared && !full_draw_copy)
dTex12->CommitClear();
if (dTexVK->GetState() == GSTexture::State::Cleared && !dtex_rc.eq(r))
dTexVK->CommitClear();
EndRenderPass();
sTex12->TransitionToState(D3D12_RESOURCE_STATE_COPY_SOURCE);
sTex12->SetUseFenceCounter(GetCurrentFenceValue());
if (m_tfx_textures[0] && sTex12->GetSRVDescriptor() == m_tfx_textures[0])
sTexVK->TransitionToState(D3D12_RESOURCE_STATE_COPY_SOURCE);
sTexVK->SetUseFenceCounter(GetCurrentFenceValue());
if (m_tfx_textures[0] && sTexVK->GetSRVDescriptor() == m_tfx_textures[0])
PSSetShaderResource(0, nullptr, false);
dTex12->TransitionToState(D3D12_RESOURCE_STATE_COPY_DEST);
dTex12->SetUseFenceCounter(GetCurrentFenceValue());
dTexVK->TransitionToState(D3D12_RESOURCE_STATE_COPY_DEST);
dTexVK->SetUseFenceCounter(GetCurrentFenceValue());
D3D12_TEXTURE_COPY_LOCATION srcloc;
srcloc.pResource = sTex12->GetResource();
srcloc.pResource = sTexVK->GetResource();
srcloc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
srcloc.SubresourceIndex = 0;
D3D12_TEXTURE_COPY_LOCATION dstloc;
dstloc.pResource = dTex12->GetResource();
dstloc.pResource = dTexVK->GetResource();
dstloc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
dstloc.SubresourceIndex = 0;
@@ -1404,7 +1415,7 @@ void GSDevice12::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r,
static_cast<UINT>(r.bottom), 1u};
GetCommandList()->CopyTextureRegion(&dstloc, destX, destY, 0, &srcloc, &srcbox);
dTex12->SetState(GSTexture::State::Dirty);
dTexVK->SetState(GSTexture::State::Dirty);
}
void GSDevice12::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
+22 -1
View File
@@ -2317,6 +2317,21 @@ void GSRendererHW::RoundSpriteOffset()
void GSRendererHW::Draw()
{
if (GSConfig.SaveInfo && GSConfig.ShouldDump(s_n, g_perfmon.GetFrame()))
{
std::string s;
// Dump Register state
s = GetDrawDumpPath("%05d_context.txt", s_n);
m_draw_env->Dump(s);
m_context->Dump(s);
// Dump vertices
s = GetDrawDumpPath("%05d_vertex.txt", s_n);
DumpVertices(s);
}
static u32 num_skipped_channel_shuffle_draws = 0;
// We mess with this state as an optimization, so take a copy and use that instead.
@@ -5165,6 +5180,8 @@ void GSRendererHW::EmulateTextureShuffleAndFbmask(GSTextureCache::Target* rt, GS
enable_fbmask_emulation = true;
break;
case AccBlendLevel::Basic:
case AccBlendLevel::Automatic:
default:
// Enable Fbmask emulation excluding triangle class because it is quite slow.
enable_fbmask_emulation = (m_vt.m_primclass != GS_TRIANGLE_CLASS);
break;
@@ -5769,7 +5786,7 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
const bool blend_ad = m_conf.ps.blend_c == 1;
const bool alpha_mask = (m_cached_ctx.FRAME.FBMSK & 0xFF000000) == 0xFF000000;
bool blend_ad_alpha_masked = blend_ad && alpha_mask;
const bool is_basic_blend = GSConfig.AccurateBlendingUnit >= AccBlendLevel::Basic;
const bool is_basic_blend = GSConfig.AccurateBlendingUnit != AccBlendLevel::Minimum;
if (blend_ad_alpha_masked && (((is_basic_blend || (COLCLAMP.CLAMP == 0)) && (features.texture_barrier || features.multidraw_fb_copy))
|| ((GSConfig.AccurateBlendingUnit >= AccBlendLevel::Medium) || m_conf.require_one_barrier)))
{
@@ -5879,6 +5896,8 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
sw_blending |= m_vt.m_primclass == GS_SPRITE_CLASS && m_drawlist.size() < 100;
[[fallthrough]];
case AccBlendLevel::Basic:
case AccBlendLevel::Automatic:
default:
// Prefer sw blend if possible.
color_dest_blend &= !prefer_sw_blend;
color_dest_blend2 &= !prefer_sw_blend;
@@ -5920,6 +5939,8 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
sw_blending |= !(blend_ad_alpha_masked || ad_second_pass) && (alpha_c1_high_max_one || alpha_c1_high_no_rta_correct) && no_prim_overlap;
[[fallthrough]];
case AccBlendLevel::Basic:
case AccBlendLevel::Automatic:
default:
// Prefer sw blend if possible.
color_dest_blend &= !prefer_sw_blend;
color_dest_blend2 &= !prefer_sw_blend;
+3 -3
View File
@@ -6070,13 +6070,13 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
{
if (dst->m_rt_alpha_scale)
{
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
const GSVector4 sRectF = GSVector4(sRect) / GSVector4(1, 1, sTex->GetWidth(), sTex->GetHeight());
g_gs_device->StretchRect(
sTex, sRectF, dTex, GSVector4(destX, destY, sRect.width(), sRect.height()), ShaderConvert::RTA_DECORRECTION, false);
}
else
g_gs_device->CopyRect(sTex, dTex, sRect, destX, destY);
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
#ifdef PCSX2_DEVBUILD
if (GSConfig.UseDebugDevice)
@@ -7778,14 +7778,12 @@ bool GSTextureCache::Target::ResizeTexture(int new_unscaled_width, int new_unsca
{
// Can't do partial copies in DirectX for depth textures, and it's probably not ideal in other
// APIs either. So use a fullscreen quad setting depth instead.
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
g_gs_device->StretchRect(m_texture, tex, GSVector4(rc), ShaderConvert::DEPTH_COPY, false);
}
else
{
if (require_new_rect)
{
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
g_gs_device->StretchRect(m_texture, tex, GSVector4(rc), ShaderConvert::COPY, false);
}
else
@@ -7794,6 +7792,8 @@ bool GSTextureCache::Target::ResizeTexture(int new_unscaled_width, int new_unsca
g_gs_device->CopyRect(m_texture, tex, rc, 0, 0);
}
}
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
}
else if (m_texture->GetState() == GSTexture::State::Cleared)
{
+4 -16
View File
@@ -1471,24 +1471,12 @@ void GSDeviceMTL::ClearSamplerCache()
void GSDeviceMTL::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, u32 destX, u32 destY)
{ @autoreleasepool {
GSTextureMTL* sT = static_cast<GSTextureMTL*>(sTex);
GSTextureMTL* dT = static_cast<GSTextureMTL*>(dTex);
const GSVector4i dst_rect(0, 0, dT->GetWidth(), dT->GetHeight());
const bool full_draw_copy = dst_rect.eq(r);
// Source is cleared, if destination is a render target, we can carry the clear forward.
if (sT->GetState() == GSTexture::State::Cleared)
{
if (dT->IsRenderTargetOrDepthStencil() && ProcessClearsBeforeCopy(sTex, dTex, full_draw_copy))
return;
// Commit clear for the source texture.
sT->FlushClears();
}
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
// Commit clear for the destination texture.
GSTextureMTL* sT = static_cast<GSTextureMTL*>(sTex);
GSTextureMTL* dT = static_cast<GSTextureMTL*>(dTex);
// Process clears
GSVector2i dsize = dTex->GetSize();
if (r.width() < dsize.x || r.height() < dsize.y)
dT->FlushClears();
+3 -18
View File
@@ -1430,25 +1430,12 @@ void GSDeviceOGL::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r
{
const GLuint& sid = static_cast<GSTextureOGL*>(sTex)->GetID();
const GLuint& did = static_cast<GSTextureOGL*>(dTex)->GetID();
const GSVector4i dst_rect(0, 0, dTex->GetWidth(), dTex->GetHeight());
const bool full_draw_copy = dst_rect.eq(r);
CommitClear(sTex, false);
CommitClear(dTex, false);
// Source is cleared, if destination is a render target, we can carry the clear forward.
if (sTex->GetState() == GSTexture::State::Cleared)
{
if (dTex->IsRenderTargetOrDepthStencil() && ProcessClearsBeforeCopy(sTex, dTex, full_draw_copy))
return;
// Commit clear for the source texture.
CommitClear(sTex, false);
}
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
GL_PUSH("CopyRect from %d to %d", sid, did);
// Commit destination clear if partially overwritten (color only).
if (dTex->GetState() == GSTexture::State::Cleared && !full_draw_copy)
CommitClear(dTex, false);
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
if (GLAD_GL_VERSION_4_3 || GLAD_GL_ARB_copy_image)
{
@@ -1460,8 +1447,6 @@ void GSDeviceOGL::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r
glCopyImageSubDataEXT(sid, GL_TEXTURE_2D, 0, r.x, r.y, 0, did, GL_TEXTURE_2D,
0, destX, destY, 0, r.width(), r.height(), 1);
}
dTex->SetState(GSTexture::State::Dirty);
}
void GSDeviceOGL::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderConvert shader, bool linear)
+9
View File
@@ -1293,6 +1293,15 @@ __ri void GSDrawScanline::CDrawScanline(int pixels, int left, int top, const GSV
rb = frb.lerp16<0>(rb, fog);
ga = fga.lerp16<0>(ga, fog).mix16(ga);
/*
fog = fog.srl16<7>();
VectorI ifog = VectorI::x00ff().sub16(fog);
rb = rb.mul16l(fog).add16(frb.mul16l(ifog)).srl16<8>();
ga = ga.mul16l(fog).add16(fga.mul16l(ifog)).srl16<8>().mix16(ga);
*/
}
// ReadFrame
@@ -174,8 +174,15 @@ void GSDrawScanlineCodeGenerator::broadcastGPRToVec(const XYm& vec, const Xbyak:
void GSDrawScanlineCodeGenerator::modulate16(const XYm& a, const Operand& f, u8 shift)
{
psllw(a, shift + 1);
pmulhw(a, f);
if (shift == 0)
{
pmulhrsw(a, f);
}
else
{
psllw(a, shift + 1);
pmulhw(a, f);
}
}
void GSDrawScanlineCodeGenerator::lerp16(const XYm& a, const XYm& b, const XYm& f, u8 shift)
@@ -2352,15 +2352,14 @@ void GSDrawScanlineCodeGenerator::modulate16(const VRegister& a, const VRegister
void GSDrawScanlineCodeGenerator::modulate16(const VRegister& d, const VRegister& a, const VRegister& f, u8 shift)
{
if (shift)
{
armAsm->Shl(d.V8H(), a.V8H(), shift);
armAsm->Sqdmulh(d.V8H(), d.V8H(), f.V8H());
}
// potentially going to cause issues due to saturation
armAsm->Shl(d.V8H(), a.V8H(), shift + 1);
if (shift != 0)
armAsm->Sqdmulh(a.V8H(), a.V8H(), f.V8H());
else
{
armAsm->Sqdmulh(a.V8H(), d.V8H(), f.V8H());
}
armAsm->Sqrdmulh(a.V8H(), a.V8H(), f.V8H());
armAsm->Sshr(a.V8H(), a.V8H(), 1);
}
void GSDrawScanlineCodeGenerator::lerp16(const VRegister& a, const VRegister& b, const VRegister& f, u8 shift)
+17
View File
@@ -309,6 +309,21 @@ void GSRendererSW::Draw()
{
const GSDrawingContext* context = m_context;
if (GSConfig.SaveInfo && GSConfig.ShouldDump(s_n, g_perfmon.GetFrame()))
{
std::string s;
// Dump Register state
s = GetDrawDumpPath("%05d_context.txt", s_n);
m_draw_env->Dump(s);
m_context->Dump(s);
// Dump vertices
s = GetDrawDumpPath("%05d_vertex.txt", s_n);
DumpVertices(s);
}
auto data = m_vertex_heap.make_shared<SharedData>().cast<GSRasterizerData>();
SharedData* sd = static_cast<SharedData*>(data.get());
@@ -1076,6 +1091,8 @@ bool GSRendererSW::GetScanlineGlobalData(SharedData* data)
if (gd.sel.fst)
{
pxAssert(gd.sel.lcm == 1);
pxAssert(((m_vt.m_min.t.uph(m_vt.m_max.t) == GSVector4::zero()).mask() & 3) == 3); // ratchet and clank (menu)
gd.sel.lcm = 1;
}
+50 -25
View File
@@ -2746,44 +2746,69 @@ std::unique_ptr<GSDownloadTexture> GSDeviceVK::CreateDownloadTexture(u32 width,
void GSDeviceVK::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, u32 destX, u32 destY)
{
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
GSTextureVK* const sTexVK = static_cast<GSTextureVK*>(sTex);
GSTextureVK* const dTexVK = static_cast<GSTextureVK*>(dTex);
const GSVector4i dst_rect(0, 0, dTexVK->GetWidth(), dTexVK->GetHeight());
const bool full_draw_copy = dst_rect.eq(r);
const GSVector4i dtex_rc(0, 0, dTexVK->GetWidth(), dTexVK->GetHeight());
// Source is cleared, if destination is a render target, we can carry the clear forward.
if (sTexVK->GetState() == GSTexture::State::Cleared)
{
if (dTexVK->IsRenderTargetOrDepthStencil() && ProcessClearsBeforeCopy(sTex, dTex, full_draw_copy))
// source is cleared. if destination is a render target, we can carry the clear forward
if (dTexVK->IsRenderTargetOrDepthStencil())
{
if (dtex_rc.eq(r))
{
// pass it forward if we're clearing the whole thing
if (sTexVK->IsDepthStencil())
dTexVK->SetClearDepth(sTexVK->GetClearDepth());
else
dTexVK->SetClearColor(sTexVK->GetClearColor());
return;
}
if (dTexVK->GetState() == GSTexture::State::Cleared)
{
// destination is cleared, if it's the same colour and rect, we can just avoid this entirely
if (dTexVK->IsDepthStencil())
{
if (dTexVK->GetClearDepth() == sTexVK->GetClearDepth())
return;
}
else
{
if (dTexVK->GetClearColor() == sTexVK->GetClearColor())
return;
}
}
// otherwise we need to do an attachment clear
const bool depth = (dTexVK->GetType() == GSTexture::Type::DepthStencil);
OMSetRenderTargets(depth ? nullptr : dTexVK, depth ? dTexVK : nullptr, dtex_rc);
BeginRenderPassForStretchRect(
dTexVK, dtex_rc, GSVector4i(destX, destY, destX + r.width(), destY + r.height()));
// so use an attachment clear
VkClearAttachment ca;
ca.aspectMask = depth ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
GSVector4::store<false>(ca.clearValue.color.float32, sTexVK->GetUNormClearColor());
ca.clearValue.depthStencil.depth = sTexVK->GetClearDepth();
ca.clearValue.depthStencil.stencil = 0;
ca.colorAttachment = 0;
const VkClearRect cr = {{{0, 0}, {static_cast<u32>(r.width()), static_cast<u32>(r.height())}}, 0u, 1u};
vkCmdClearAttachments(GetCurrentCommandBuffer(), 1, &ca, 1, &cr);
return;
// Do an attachment clear.
const bool depth = (dTexVK->GetType() == GSTexture::Type::DepthStencil);
OMSetRenderTargets(depth ? nullptr : dTexVK, depth ? dTexVK : nullptr, dst_rect);
BeginRenderPassForStretchRect(
dTexVK, dst_rect, GSVector4i(destX, destY, destX + r.width(), destY + r.height()));
// so use an attachment clear
VkClearAttachment ca;
ca.aspectMask = depth ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
GSVector4::store<false>(ca.clearValue.color.float32, sTexVK->GetUNormClearColor());
ca.clearValue.depthStencil.depth = sTexVK->GetClearDepth();
ca.clearValue.depthStencil.stencil = 0;
ca.colorAttachment = 0;
const VkClearRect cr = {{{0, 0}, {static_cast<u32>(r.width()), static_cast<u32>(r.height())}}, 0u, 1u};
vkCmdClearAttachments(GetCurrentCommandBuffer(), 1, &ca, 1, &cr);
return;
}
// commit the clear to the source first, then do normal copy
sTexVK->CommitClear();
}
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
// if the destination has been cleared, and we're not overwriting the whole thing, commit the clear first
// (the area outside of where we're copying to)
if (dTexVK->GetState() == GSTexture::State::Cleared && !full_draw_copy)
if (dTexVK->GetState() == GSTexture::State::Cleared && !dtex_rc.eq(r))
dTexVK->CommitClear();
// *now* we can do a normal image copy.
+10 -9
View File
@@ -664,10 +664,10 @@ bool GameDatabaseSchema::GameEntry::configMatchesHWFix(const Pcsx2Config::GSOpti
return (config.GPUPaletteConversion == ((value > 1) ? (config.TexturePreloading == TexturePreloadingLevel::Full) : (value != 0)));
case GSHWFixId::MinimumBlendingLevel:
return (static_cast<int>(config.AccurateBlendingUnit) >= value);
return (config.AccurateBlendingUnit == AccBlendLevel::Automatic || static_cast<int>(config.AccurateBlendingUnit) >= value);
case GSHWFixId::MaximumBlendingLevel:
return (static_cast<int>(config.AccurateBlendingUnit) <= value);
return (config.AccurateBlendingUnit == AccBlendLevel::Automatic || static_cast<int>(config.AccurateBlendingUnit) <= value);
case GSHWFixId::RecommendedBlendingLevel:
return true;
@@ -868,21 +868,23 @@ void GameDatabaseSchema::GameEntry::applyGSHardwareFixes(Pcsx2Config::GSOptions&
case GSHWFixId::MinimumBlendingLevel:
{
if (value >= 0 && value <= static_cast<int>(AccBlendLevel::Maximum))
config.AccurateBlendingUnit = std::max(config.AccurateBlendingUnit, static_cast<AccBlendLevel>(value));
if (value >= 0 && value <= static_cast<int>(AccBlendLevel::Maximum) && config.AccurateBlendingUnit == AccBlendLevel::Automatic)
config.AccurateBlendingUnit = static_cast<AccBlendLevel>(value);
}
break;
case GSHWFixId::MaximumBlendingLevel:
{
if (value >= 0 && value <= static_cast<int>(AccBlendLevel::Maximum))
config.AccurateBlendingUnit = std::min(config.AccurateBlendingUnit, static_cast<AccBlendLevel>(value));
if (value >= 0 && value <= static_cast<int>(AccBlendLevel::Maximum) && config.AccurateBlendingUnit == AccBlendLevel::Automatic)
config.AccurateBlendingUnit = static_cast<AccBlendLevel>(value);
}
break;
case GSHWFixId::RecommendedBlendingLevel:
{
if (!is_sw_renderer && value >= 0 && value <= static_cast<int>(AccBlendLevel::Maximum) && static_cast<int>(EmuConfig.GS.AccurateBlendingUnit) < value)
// Need to increment by 1 because Automatic is -1.
const int blend_level = static_cast<int>(config.AccurateBlendingUnit) + 1;
if (!is_sw_renderer && value >= static_cast<int>(AccBlendLevel::Automatic) && value <= static_cast<int>(AccBlendLevel::Maximum) && blend_level < value)
{
Host::AddKeyedOSDMessage("HWBlendingWarning",
fmt::format(TRANSLATE_FS("GameDatabase",
@@ -891,8 +893,7 @@ void GameDatabaseSchema::GameEntry::applyGSHardwareFixes(Pcsx2Config::GSOptions&
"You can adjust the blending level in Game Properties to improve\n"
"graphical quality, but this will increase system requirements."),
ICON_FA_PAINTBRUSH,
Pcsx2Config::GSOptions::BlendingLevelNames[static_cast<int>(
EmuConfig.GS.AccurateBlendingUnit)],
Pcsx2Config::GSOptions::BlendingLevelNames[blend_level],
Pcsx2Config::GSOptions::BlendingLevelNames[value]),
Host::OSD_WARNING_DURATION);
}
+45 -45
View File
@@ -113,37 +113,32 @@ static bool UseSavestateSelector()
}
BEGIN_HOTKEY_LIST(g_common_hotkeys)
DEFINE_HOTKEY("ToggleFullscreen", TRANSLATE_NOOP("Hotkeys", "Navigation"), TRANSLATE_NOOP("Hotkeys", "Toggle Fullscreen"),
[](s32 pressed) {
if (!pressed)
Host::SetFullscreen(!Host::IsFullscreen());
})
DEFINE_HOTKEY("OpenPauseMenu", TRANSLATE_NOOP("Hotkeys", "Navigation"), TRANSLATE_NOOP("Hotkeys", "Open Pause Menu"),
DEFINE_HOTKEY("OpenPauseMenu", TRANSLATE_NOOP("Hotkeys", "System"), TRANSLATE_NOOP("Hotkeys", "Open Pause Menu"),
[](s32 pressed) {
if (!pressed && VMManager::HasValidVM() && CanPause())
FullscreenUI::OpenPauseMenu();
})
DEFINE_HOTKEY("OpenAchievementsList", TRANSLATE_NOOP("Hotkeys", "Navigation"),
DEFINE_HOTKEY("OpenAchievementsList", TRANSLATE_NOOP("Hotkeys", "System"),
TRANSLATE_NOOP("Hotkeys", "Open Achievements List"), [](s32 pressed) {
if (!pressed && CanPause())
FullscreenUI::OpenAchievementsWindow();
})
DEFINE_HOTKEY("OpenLeaderboardsList", TRANSLATE_NOOP("Hotkeys", "Navigation"),
DEFINE_HOTKEY("OpenLeaderboardsList", TRANSLATE_NOOP("Hotkeys", "System"),
TRANSLATE_NOOP("Hotkeys", "Open Leaderboards List"), [](s32 pressed) {
if (!pressed && CanPause())
FullscreenUI::OpenLeaderboardsWindow();
})
DEFINE_HOTKEY(
"TogglePause", TRANSLATE_NOOP("Hotkeys", "Speed"), TRANSLATE_NOOP("Hotkeys", "Toggle Pause"), [](s32 pressed) {
"TogglePause", TRANSLATE_NOOP("Hotkeys", "System"), TRANSLATE_NOOP("Hotkeys", "Toggle Pause"), [](s32 pressed) {
if (!pressed && VMManager::HasValidVM() && CanPause())
VMManager::SetPaused(VMManager::GetState() != VMState::Paused);
})
DEFINE_HOTKEY(
"FrameAdvance", TRANSLATE_NOOP("Hotkeys", "Speed"), TRANSLATE_NOOP("Hotkeys", "Frame Advance"), [](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
VMManager::FrameAdvance(1);
DEFINE_HOTKEY("ToggleFullscreen", TRANSLATE_NOOP("Hotkeys", "System"), TRANSLATE_NOOP("Hotkeys", "Toggle Fullscreen"),
[](s32 pressed) {
if (!pressed)
Host::SetFullscreen(!Host::IsFullscreen());
})
DEFINE_HOTKEY("ToggleFrameLimit", TRANSLATE_NOOP("Hotkeys", "Speed"), TRANSLATE_NOOP("Hotkeys", "Toggle Frame Limit"),
DEFINE_HOTKEY("ToggleFrameLimit", TRANSLATE_NOOP("Hotkeys", "System"), TRANSLATE_NOOP("Hotkeys", "Toggle Frame Limit"),
[](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
{
@@ -152,7 +147,7 @@ DEFINE_HOTKEY("ToggleFrameLimit", TRANSLATE_NOOP("Hotkeys", "Speed"), TRANSLATE_
LimiterModeType::Nominal);
}
})
DEFINE_HOTKEY("ToggleTurbo", TRANSLATE_NOOP("Hotkeys", "Speed"),
DEFINE_HOTKEY("ToggleTurbo", TRANSLATE_NOOP("Hotkeys", "System"),
TRANSLATE_NOOP("Hotkeys", "Toggle Turbo / Fast Forward"), [](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
{
@@ -160,7 +155,15 @@ DEFINE_HOTKEY("ToggleTurbo", TRANSLATE_NOOP("Hotkeys", "Speed"),
(VMManager::GetLimiterMode() != LimiterModeType::Turbo) ? LimiterModeType::Turbo : LimiterModeType::Nominal);
}
})
DEFINE_HOTKEY("HoldTurbo", TRANSLATE_NOOP("Hotkeys", "Speed"),
DEFINE_HOTKEY("ToggleSlowMotion", TRANSLATE_NOOP("Hotkeys", "System"), TRANSLATE_NOOP("Hotkeys", "Toggle Slow Motion"),
[](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
{
VMManager::SetLimiterMode(
(VMManager::GetLimiterMode() != LimiterModeType::Slomo) ? LimiterModeType::Slomo : LimiterModeType::Nominal);
}
})
DEFINE_HOTKEY("HoldTurbo", TRANSLATE_NOOP("Hotkeys", "System"),
TRANSLATE_NOOP("Hotkeys", "Turbo / Fast Forward (Hold)"), [](s32 pressed) {
if (!VMManager::HasValidVM())
return;
@@ -177,24 +180,35 @@ DEFINE_HOTKEY("HoldTurbo", TRANSLATE_NOOP("Hotkeys", "Speed"),
s_limiter_mode_prior_to_hold_interaction.reset();
}
})
DEFINE_HOTKEY("ToggleSlowMotion", TRANSLATE_NOOP("Hotkeys", "Speed"), TRANSLATE_NOOP("Hotkeys", "Toggle Slow Motion"),
[](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
{
VMManager::SetLimiterMode(
(VMManager::GetLimiterMode() != LimiterModeType::Slomo) ? LimiterModeType::Slomo : LimiterModeType::Nominal);
}
})
DEFINE_HOTKEY("IncreaseSpeed", TRANSLATE_NOOP("Hotkeys", "Speed"), TRANSLATE_NOOP("Hotkeys", "Increase Target Speed"),
DEFINE_HOTKEY("IncreaseSpeed", TRANSLATE_NOOP("Hotkeys", "System"), TRANSLATE_NOOP("Hotkeys", "Increase Target Speed"),
[](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
HotkeyAdjustTargetSpeed(0.1);
})
DEFINE_HOTKEY("DecreaseSpeed", TRANSLATE_NOOP("Hotkeys", "Speed"), TRANSLATE_NOOP("Hotkeys", "Decrease Target Speed"),
DEFINE_HOTKEY("DecreaseSpeed", TRANSLATE_NOOP("Hotkeys", "System"), TRANSLATE_NOOP("Hotkeys", "Decrease Target Speed"),
[](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
HotkeyAdjustTargetSpeed(-0.1);
})
DEFINE_HOTKEY("IncreaseVolume", TRANSLATE_NOOP("Hotkeys", "System"), TRANSLATE_NOOP("Hotkeys", "Increase Volume"),
[](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
HotkeyAdjustVolume(-1, 5);
})
DEFINE_HOTKEY("DecreaseVolume", TRANSLATE_NOOP("Hotkeys", "System"), TRANSLATE_NOOP("Hotkeys", "Decrease Volume"),
[](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
HotkeyAdjustVolume(-1, -5);
})
DEFINE_HOTKEY("Mute", TRANSLATE_NOOP("Hotkeys", "System"), TRANSLATE_NOOP("Hotkeys", "Toggle Mute"), [](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
HotkeyAdjustVolume((SPU2::GetOutputVolume() == 0) ? SPU2::GetResetVolume() : 0, 0);
})
DEFINE_HOTKEY(
"FrameAdvance", TRANSLATE_NOOP("Hotkeys", "System"), TRANSLATE_NOOP("Hotkeys", "Frame Advance"), [](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
VMManager::FrameAdvance(1);
})
DEFINE_HOTKEY("ShutdownVM", TRANSLATE_NOOP("Hotkeys", "System"), TRANSLATE_NOOP("Hotkeys", "Shut Down Virtual Machine"),
[](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
@@ -205,6 +219,11 @@ DEFINE_HOTKEY("ResetVM", TRANSLATE_NOOP("Hotkeys", "System"), TRANSLATE_NOOP("Ho
if (!pressed && VMManager::HasValidVM())
VMManager::Reset();
})
DEFINE_HOTKEY("InputRecToggleMode", TRANSLATE_NOOP("Hotkeys", "System"),
TRANSLATE_NOOP("Hotkeys", "Toggle Input Recording Mode"), [](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
g_InputRecording.getControls().toggleRecordMode();
})
DEFINE_HOTKEY("SwapMemCards", TRANSLATE_NOOP("Hotkeys", "System"),
TRANSLATE_NOOP("Hotkeys", "Swap Memory Cards"), [](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
@@ -212,11 +231,6 @@ DEFINE_HOTKEY("SwapMemCards", TRANSLATE_NOOP("Hotkeys", "System"),
FileMcd_Swap();
});
})
DEFINE_HOTKEY("InputRecToggleMode", TRANSLATE_NOOP("Hotkeys", "System"),
TRANSLATE_NOOP("Hotkeys", "Toggle Input Recording Mode"), [](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
g_InputRecording.getControls().toggleRecordMode();
})
DEFINE_HOTKEY("PreviousSaveStateSlot", TRANSLATE_NOOP("Hotkeys", "Save States"),
TRANSLATE_NOOP("Hotkeys", "Select Previous Save Slot"), [](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
@@ -291,18 +305,4 @@ DEFINE_HOTKEY_SAVESTATE_X(10, TRANSLATE_NOOP("Hotkeys", "Save State To Slot 10")
DEFINE_HOTKEY_LOADSTATE_X(10, TRANSLATE_NOOP("Hotkeys", "Load State From Slot 10"))
#undef DEFINE_HOTKEY_SAVESTATE_X
#undef DEFINE_HOTKEY_LOADSTATE_X
DEFINE_HOTKEY("Mute", TRANSLATE_NOOP("Hotkeys", "Audio"), TRANSLATE_NOOP("Hotkeys", "Toggle Mute"), [](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
HotkeyAdjustVolume((SPU2::GetOutputVolume() == 0) ? SPU2::GetResetVolume() : 0, 0);
})
DEFINE_HOTKEY("IncreaseVolume", TRANSLATE_NOOP("Hotkeys", "Audio"), TRANSLATE_NOOP("Hotkeys", "Increase Volume"),
[](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
HotkeyAdjustVolume(-1, 5);
})
DEFINE_HOTKEY("DecreaseVolume", TRANSLATE_NOOP("Hotkeys", "Audio"), TRANSLATE_NOOP("Hotkeys", "Decrease Volume"),
[](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
HotkeyAdjustVolume(-1, -5);
})
END_HOTKEY_LIST()
+16 -61
View File
@@ -3981,7 +3981,7 @@ void FullscreenUI::DrawGraphicsSettingsPage(SettingsInterface* bsi, bool show_ad
#ifdef __APPLE__
FSUI_NSTR("Metal"),
#endif
FSUI_NSTR("Software Renderer"),
FSUI_NSTR("Software"),
FSUI_NSTR("Null"),
};
static constexpr const char* s_renderer_values[] = {
@@ -4066,8 +4066,9 @@ void FullscreenUI::DrawGraphicsSettingsPage(SettingsInterface* bsi, bool show_ad
FSUI_NSTR("Force 32bit"),
};
static constexpr const char* s_blending_options[] = {
FSUI_NSTR("Automatic (Default)"),
FSUI_NSTR("Minimum"),
FSUI_NSTR("Basic (Recommended)"),
FSUI_NSTR("Basic"),
FSUI_NSTR("Medium"),
FSUI_NSTR("High"),
FSUI_NSTR("Full (Slow)"),
@@ -4128,8 +4129,8 @@ void FullscreenUI::DrawGraphicsSettingsPage(SettingsInterface* bsi, bool show_ad
BeginMenuButtons();
MenuHeading(FSUI_CSTR("Graphics API"));
DrawStringListSetting(bsi, FSUI_ICONSTR(ICON_FA_PAINTBRUSH, "Graphics API"), FSUI_CSTR("Selects the API used to render the emulated GS."), "EmuCore/GS",
MenuHeading(FSUI_CSTR("Renderer"));
DrawStringListSetting(bsi, FSUI_ICONSTR(ICON_FA_PAINTBRUSH, "Renderer"), FSUI_CSTR("Selects the API used to render the emulated GS."), "EmuCore/GS",
"Renderer", "-1", s_renderer_names, s_renderer_values, std::size(s_renderer_names), true);
MenuHeading(FSUI_CSTR("Display"));
@@ -4199,7 +4200,7 @@ void FullscreenUI::DrawGraphicsSettingsPage(SettingsInterface* bsi, bool show_ad
"EmuCore/GS", "dithering_ps2", 2, s_dithering_options, std::size(s_dithering_options), true);
DrawIntListSetting(bsi, FSUI_ICONSTR(ICON_FA_SPLOTCH, "Blending Accuracy"),
FSUI_CSTR("Determines the level of accuracy when emulating blend modes not supported by the host graphics API."), "EmuCore/GS",
"accurate_blending_unit", static_cast<int>(AccBlendLevel::Basic), s_blending_options, std::size(s_blending_options), true);
"accurate_blending_unit", static_cast<int>(AccBlendLevel::Automatic), s_blending_options, std::size(s_blending_options), true);
DrawToggleSetting(
bsi, FSUI_ICONSTR(ICON_FA_BULLSEYE, "Mipmapping"), FSUI_CSTR("Enables emulation of the GS's texture mipmapping."), "EmuCore/GS", "hw_mipmap", true);
}
@@ -6443,44 +6444,6 @@ void FullscreenUI::DrawResumeStateSelector()
void FullscreenUI::DoLoadState(std::string path)
{
// Check for hardcore mode before loading state
if (Achievements::IsHardcoreModeActive())
{
Achievements::ConfirmHardcoreModeDisableAsync(TRANSLATE("VMManager", "Loading state"),
[path = std::move(path)](bool approved) {
if (approved)
DoLoadState(std::move(path));
});
return;
}
const std::string filename = std::string(Path::GetFileName(path));
s32 slot = -1;
bool is_backup = false;
std::string base_filename = filename;
if (filename.length() > 7 && filename.substr(filename.length() - 7) == ".backup")
{
is_backup = true;
base_filename = filename.substr(0, filename.length() - 7);
}
// Get slot number from filename (format: serial.crc.slot.p2s)
const size_t last_dot = base_filename.rfind('.');
const size_t second_last_dot = base_filename.rfind('.', last_dot - 1);
if (last_dot != std::string::npos && second_last_dot != std::string::npos)
{
const std::string slot_str = base_filename.substr(second_last_dot + 1, last_dot - second_last_dot - 1);
if (!slot_str.empty())
slot = std::atoi(slot_str.c_str());
}
const std::string message = (slot >= 0) ?
fmt::format(TRANSLATE_FS("VMManager", "Loading {} from slot {}..."), is_backup ? TRANSLATE("VMManager", "backup state") : TRANSLATE("VMManager", "state"), slot) :
TRANSLATE_STR("VMManager", "Loading save state...");
Host::AddIconOSDMessage("LoadStateFromSlot", ICON_FA_FOLDER_OPEN, message, Host::OSD_QUICK_DURATION);
Host::RunOnCPUThread([path = std::move(path)]()
{
const std::string boot_path = s_save_state_selector_game_path;
@@ -6986,19 +6949,14 @@ void FullscreenUI::DrawGameGrid(const ImVec2& heading_size)
DrawGameCover(entry, ImGui::GetWindowDrawList(), bb.Min, bb.Min + image_size);
const bool show_titles = Host::GetBaseBoolSettingValue("UI", "FullscreenUIShowGameGridTitles", true);
if (show_titles)
{
const ImRect title_bb(ImVec2(bb.Min.x, bb.Min.y + image_height + title_spacing), bb.Max);
const std::string_view title(std::string_view(entry->GetTitle(true)).substr(0, 31));
draw_title.clear();
fmt::format_to(std::back_inserter(draw_title), "{}{}", title, (title.length() == entry->GetTitle(true).length()) ? "" : "...");
ImGui::PushFont(g_medium_font.first, g_medium_font.second);
ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, draw_title.c_str(), draw_title.c_str() + draw_title.length(), nullptr,
ImVec2(0.5f, 0.0f), &title_bb);
ImGui::PopFont();
}
const ImRect title_bb(ImVec2(bb.Min.x, bb.Min.y + image_height + title_spacing), bb.Max);
const std::string_view title(std::string_view(entry->GetTitle(true)).substr(0, 31));
draw_title.clear();
fmt::format_to(std::back_inserter(draw_title), "{}{}", title, (title.length() == entry->GetTitle(true).length()) ? "" : "...");
ImGui::PushFont(g_medium_font.first, g_medium_font.second);
ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, draw_title.c_str(), draw_title.c_str() + draw_title.length(), nullptr,
ImVec2(0.5f, 0.0f), &title_bb);
ImGui::PopFont();
if (pressed)
{
@@ -7224,9 +7182,6 @@ void FullscreenUI::DrawGameListSettingsWindow()
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_ARROW_DOWN_A_Z, "Sort Reversed"),
FSUI_CSTR("Reverses the game list sort order from the default (usually ascending to descending)."), "UI",
"FullscreenUIGameSortReverse", false);
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_TAG, "Show Titles"),
FSUI_CSTR("Shows Titles for Games when in Game Grid View Mode"), "UI",
"FullscreenUIShowGameGridTitles", true);
}
MenuHeading(FSUI_CSTR("Cover Settings"));
@@ -8148,7 +8103,7 @@ TRANSLATE_NOOP("FullscreenUI", "Synchronize EE and GS threads after each frame.
TRANSLATE_NOOP("FullscreenUI", "Synchronizes frame presentation with host refresh.");
TRANSLATE_NOOP("FullscreenUI", "Speeds up emulation so that the guest refresh rate matches the host.");
TRANSLATE_NOOP("FullscreenUI", "Disables PCSX2's internal frame timing, and uses host vsync instead.");
TRANSLATE_NOOP("FullscreenUI", "Graphics API");
TRANSLATE_NOOP("FullscreenUI", "Renderer");
TRANSLATE_NOOP("FullscreenUI", "Selects the API used to render the emulated GS.");
TRANSLATE_NOOP("FullscreenUI", "Display");
TRANSLATE_NOOP("FullscreenUI", "Selects the aspect ratio to display the game content at.");
@@ -8582,7 +8537,7 @@ TRANSLATE_NOOP("FullscreenUI", "Direct3D 12 (Not Recommended)");
TRANSLATE_NOOP("FullscreenUI", "OpenGL");
TRANSLATE_NOOP("FullscreenUI", "Vulkan");
TRANSLATE_NOOP("FullscreenUI", "Metal");
TRANSLATE_NOOP("FullscreenUI", "Software Renderer");
TRANSLATE_NOOP("FullscreenUI", "Software");
TRANSLATE_NOOP("FullscreenUI", "Null");
TRANSLATE_NOOP("FullscreenUI", "Off");
TRANSLATE_NOOP("FullscreenUI", "Bilinear (Smooth)");
+1 -1
View File
@@ -467,7 +467,7 @@ ImFont* ImGuiManager::AddTextFont()
{
// Exclude FA and PF ranges
// clang-format off
static constexpr ImWchar range_exclude_icons[] = { 0x2198,0x2199,0x219e,0x21a7,0x21b0,0x21b3,0x21ba,0x21c3,0x21ce,0x21d4,0x21dc,0x21dd,0x21e0,0x21e3,0x21e6,0x21e8,0x21f3,0x21f3,0x21f7,0x21fb,0x2206,0x2208,0x221a,0x221a,0x227a,0x227d,0x22bf,0x22c8,0x2349,0x2349,0x235a,0x2361,0x2364,0x2367,0x237a,0x237f,0x23b2,0x23b5,0x23cc,0x23cc,0x23f4,0x23f7,0x2427,0x243a,0x243d,0x243e,0x2441,0x2452,0x2460,0x246b,0x248f,0x248f,0x24f5,0x24ff,0x2605,0x2605,0x2699,0x2699,0x278a,0x278e,0xff21,0xff3a,0x0,0x0 };
static constexpr ImWchar range_exclude_icons[] = { 0x2198,0x2199,0x219e,0x21a7,0x21b0,0x21b3,0x21ba,0x21c3,0x21ce,0x21d4,0x21dc,0x21dd,0x21e0,0x21e3,0x21e6,0x21e8,0x21f3,0x21f3,0x21f7,0x21fb,0x2206,0x2208,0x221a,0x221a,0x227a,0x227d,0x22bf,0x22c8,0x2349,0x2349,0x235a,0x2361,0x2364,0x2367,0x237a,0x237f,0x23b2,0x23b5,0x23cc,0x23cc,0x23f4,0x23f7,0x2427,0x243a,0x243d,0x243d,0x2443,0x2443,0x2460,0x246b,0x248f,0x248f,0x24f5,0x24ff,0x2605,0x2605,0x2699,0x2699,0x278a,0x278e,0xff21,0xff3a,0x0,0x0 };
// clang-format on
ImFontConfig cfg;
+8 -6
View File
@@ -670,7 +670,7 @@ __ri void ImGuiManager::DrawInputsOverlay(float scale, float margin, float spaci
for (u32 port = 0; port < USB::NUM_PORTS; port++)
{
if (EmuConfig.USB.Ports[port].DeviceType >= 0)
if (EmuConfig.USB.Ports[port].DeviceType >= 0 && !USB::GetDeviceBindings(port).empty())
num_ports++;
}
@@ -688,7 +688,10 @@ __ri void ImGuiManager::DrawInputsOverlay(float scale, float margin, float spaci
continue;
const Pad::ControllerInfo& cinfo = pad->GetInfo();
text.format("{} {} • {} |", ICON_FA_GAMEPAD, slot + 1u, cinfo.icon_name ? cinfo.icon_name : ICON_FA_TRIANGLE_EXCLAMATION);
if (cinfo.icon_name)
text.format("{} {}", cinfo.icon_name, slot + 1u);
else
text.format("{} |", slot + 1u);
for (u32 bind = 0; bind < static_cast<u32>(cinfo.bindings.size()); bind++)
{
@@ -741,9 +744,10 @@ __ri void ImGuiManager::DrawInputsOverlay(float scale, float margin, float spaci
continue;
const std::span<const InputBindingInfo> bindings(USB::GetDeviceBindings(port));
if (bindings.empty())
continue;
const char* icon = USB::GetDeviceIconName(port);
text.format("{} {} • {} | ", ICON_PF_USB, port + 1u, icon ? icon : ICON_FA_TRIANGLE_EXCLAMATION);
text.format("{} {} ", ICON_PF_USB, port + 1u);
for (const InputBindingInfo& bi : bindings)
{
@@ -1004,8 +1008,6 @@ void SaveStateSelectorUI::RefreshHotkeyLegend()
{
auto format_legend_entry = [](SmallString binding, std::string_view caption) {
InputManager::PrettifyInputBinding(binding);
if (binding.empty())
binding.append(TRANSLATE_STR("ImGuiOverlays", "Empty"));
return fmt::format("{} - {}", binding, caption);
};
+4 -8
View File
@@ -4,8 +4,6 @@
#pragma once
#include "vtlb.h"
#include "MemoryTypes.h"
#include "common/BitUtils.h"
// This is a table of default virtual map addresses for ps2vm components. These locations
// are provided and used to assist in debugging and possibly hacking; as it makes it possible
@@ -24,15 +22,13 @@ namespace HostMemoryMap
// Main
//////////////////////////////////////////////////////////////////////////
// PS2 main memory, SPR, and ROMs (approximately 143MB).
// Needs to be big enough to fit the EEVM_MemoryAllocMess struct
// PS2 main memory, SPR, and ROMs (approximately 138.5MB, but we round up to 139MB for simplicity).
static constexpr u32 EEmemOffset = 0x00000000;
static constexpr u32 EEmemSize = Common::AlignUp(sizeof(EEVM_MemoryAllocMess), _1mb);
static constexpr u32 EEmemSize = 0x8B00000;
// IOP main memory (approximately 3MB).
// Needs to be big enough to fit the IopVM_MemoryAllocMess struct
// IOP main memory (2MB + 64K + 256b, rounded up to 3MB for simplicity).
static constexpr u32 IOPmemOffset = EEmemOffset + EEmemSize;
static constexpr u32 IOPmemSize = Common::AlignUp(sizeof(IopVM_MemoryAllocMess), _1mb);
static constexpr u32 IOPmemSize = 0x300000;
// VU0 and VU1 memory (40KB, rounded up to 1MB for simplicity).
static constexpr u32 VUmemOffset = IOPmemOffset + IOPmemSize;
-2
View File
@@ -29,7 +29,6 @@ typedef u32 mem32_t;
typedef u64 mem64_t;
typedef u128 mem128_t;
// Needs to fit within EEmemSize of Memory.h
struct EEVM_MemoryAllocMess
{
u8 Main[Ps2MemSize::MainRam]; // Main memory (hard-wired to 32MB)
@@ -48,7 +47,6 @@ struct EEVM_MemoryAllocMess
u8 ZeroWrite[_1mb];
};
// Needs to fit within IOPmemSize of Memory.h
struct IopVM_MemoryAllocMess
{
u8 Main[Ps2MemSize::IopRam]; // Main memory (hard-wired to 2MB)
+56 -75
View File
@@ -19,7 +19,7 @@
#include "fmt/format.h"
#if defined(_WIN32)
#if _WIN32
#define read_portable(a, b, c) (recv(a, (char*)b, c, 0))
#define write_portable(a, b, c) (send(a, (const char*)b, c, 0))
#define safe_close_portable(a) \
@@ -31,23 +31,9 @@
(a) = INVALID_SOCKET; \
} \
} while (0)
#define bzero(b, len) (memset((b), '\0', (len)), (void)0)
#include "common/RedtapeWindows.h"
#include <WinSock2.h>
#elif defined(__linux__) || defined(__FreeBSD__)
#define read_portable(a, b, c) (read(a, b, c))
#define write_portable(a, b, c) (send(a, b, c, MSG_NOSIGNAL))
#define safe_close_portable(a) \
do \
{ \
if ((a) >= 0) \
{ \
close((a)); \
(a) = -1; \
} \
} while (0)
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#else
#define read_portable(a, b, c) (read(a, b, c))
#define write_portable(a, b, c) (write(a, b, c))
@@ -88,25 +74,25 @@ static bool InitializeWinsock()
namespace PINEServer
{
static std::thread s_thread;
static int s_slot;
std::thread m_thread;
int m_slot;
#ifdef _WIN32
// windows claim to have support for AF_UNIX sockets but that is a blatant lie,
// their SDK won't even run their own examples, so we go on TCP sockets.
static SOCKET s_sock = INVALID_SOCKET;
static SOCKET m_sock = INVALID_SOCKET;
// the message socket used in thread's accept().
static SOCKET s_msgsock = INVALID_SOCKET;
static SOCKET m_msgsock = INVALID_SOCKET;
#else
// absolute path of the socket. Stored in XDG_RUNTIME_DIR, if unset /tmp
static std::string s_socket_name;
static int s_sock = -1;
static std::string m_socket_name;
static int m_sock = -1;
// the message socket used in thread's accept().
static int s_msgsock = -1;
static int m_msgsock = -1;
#endif
// Whether the socket processing thread should stop executing/is stopped.
static std::atomic_bool s_end{true};
static std::atomic_bool m_end{true};
/**
* Maximum memory used by an IPC message request.
@@ -125,13 +111,13 @@ namespace PINEServer
* A preallocated buffer used to store all IPC replies.
* to the size of 50.000 MsgWrite64 IPC calls.
*/
static std::vector<u8> s_ret_buffer;
static std::vector<u8> m_ret_buffer;
/**
* IPC messages buffer.
* A preallocated buffer used to store all IPC messages.
*/
static std::vector<u8> s_ipc_buffer;
static std::vector<u8> m_ipc_buffer;
/**
* IPC Command messages opcodes.
@@ -260,8 +246,8 @@ namespace PINEServer
bool PINEServer::Initialize(int slot)
{
s_end.store(false, std::memory_order_release);
s_slot = slot;
m_end.store(false, std::memory_order_release);
m_slot = slot;
#ifdef _WIN32
if (!InitializeWinsock())
@@ -271,8 +257,8 @@ bool PINEServer::Initialize(int slot)
return false;
}
s_sock = socket(AF_INET, SOCK_STREAM, 0);
if ((s_sock == INVALID_SOCKET) || slot > 65536)
m_sock = socket(AF_INET, SOCK_STREAM, 0);
if ((m_sock == INVALID_SOCKET) || slot > 65536)
{
Console.WriteLn(Color_Red, "PINE: Cannot open socket! Shutting down...");
Deinitialize();
@@ -284,7 +270,7 @@ bool PINEServer::Initialize(int slot)
server.sin_addr.s_addr = htonl(INADDR_LOOPBACK); // localhost only
server.sin_port = htons(slot);
if (bind(s_sock, (struct sockaddr*)&server, sizeof(server)) == SOCKET_ERROR)
if (bind(m_sock, (struct sockaddr*)&server, sizeof(server)) == SOCKET_ERROR)
{
Console.WriteLn(Color_Red, "PINE: Error while binding to socket! Shutting down...");
Deinitialize();
@@ -301,32 +287,32 @@ bool PINEServer::Initialize(int slot)
// fallback in case macOS or other OSes don't implement the XDG base
// spec
if (runtime_dir == nullptr)
s_socket_name = "/tmp/" PINE_EMULATOR_NAME ".sock";
m_socket_name = "/tmp/" PINE_EMULATOR_NAME ".sock";
else
{
s_socket_name = runtime_dir;
s_socket_name += "/" PINE_EMULATOR_NAME ".sock";
m_socket_name = runtime_dir;
m_socket_name += "/" PINE_EMULATOR_NAME ".sock";
}
if (slot != PINE_DEFAULT_SLOT)
s_socket_name += "." + std::to_string(slot);
m_socket_name += "." + std::to_string(slot);
struct sockaddr_un server;
s_sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (s_sock < 0)
m_sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (m_sock < 0)
{
Console.WriteLn(Color_Red, "PINE: Cannot open socket! Shutting down...");
Deinitialize();
return false;
}
server.sun_family = AF_UNIX;
StringUtil::Strlcpy(server.sun_path, s_socket_name, sizeof(server.sun_path));
StringUtil::Strlcpy(server.sun_path, m_socket_name, sizeof(server.sun_path));
// we unlink the socket so that when releasing this thread the socket gets
// freed even if we didn't close correctly the loop
unlink(s_socket_name.c_str());
if (bind(s_sock, (struct sockaddr*)&server, sizeof(struct sockaddr_un)))
unlink(m_socket_name.c_str());
if (bind(m_sock, (struct sockaddr*)&server, sizeof(struct sockaddr_un)))
{
Console.WriteLn(Color_Red, "PINE: Error while binding to socket! Shutting down...");
Deinitialize();
@@ -337,7 +323,7 @@ bool PINEServer::Initialize(int slot)
// maximum queue of 4096 commands before refusing, approximated to the
// nearest legal value. We do not use SOMAXCONN as windows have this idea
// that a "reasonable" value is 5, which is not.
if (listen(s_sock, 4096))
if (listen(m_sock, 4096))
{
Console.WriteLn(Color_Red, "PINE: Cannot listen for connections! Shutting down...");
Deinitialize();
@@ -346,23 +332,23 @@ bool PINEServer::Initialize(int slot)
// we allocate once buffers to not have to do mallocs for each IPC
// request, as malloc is expansive when we optimize for µs.
s_ret_buffer.resize(MAX_IPC_RETURN_SIZE);
s_ipc_buffer.resize(MAX_IPC_SIZE);
m_ret_buffer.resize(MAX_IPC_RETURN_SIZE);
m_ipc_buffer.resize(MAX_IPC_SIZE);
// we start the thread
s_thread = std::thread(&PINEServer::MainLoop);
m_thread = std::thread(&PINEServer::MainLoop);
return true;
}
bool PINEServer::IsInitialized()
{
return !s_end.load(std::memory_order_acquire);
return !m_end.load(std::memory_order_acquire);
}
int PINEServer::GetSlot()
{
return s_slot;
return m_slot;
}
std::vector<u8>& PINEServer::MakeOkIPC(std::vector<u8>& ret_buffer, uint32_t size = 5)
@@ -381,29 +367,24 @@ std::vector<u8>& PINEServer::MakeFailIPC(std::vector<u8>& ret_buffer, uint32_t s
bool PINEServer::AcceptClient()
{
s_msgsock = accept(s_sock, 0, 0);
if (s_msgsock >= 0)
m_msgsock = accept(m_sock, 0, 0);
if (m_msgsock >= 0)
{
// Gross C-style cast, but SOCKET is a handle on Windows.
Console.WriteLn("PINE: New client with FD %d connected.", (int)s_msgsock);
Console.WriteLn("PINE: New client with FD %d connected.", (int)m_msgsock);
return true;
}
#ifdef __APPLE__
int nosigpipe = 1;
setsockopt(s_msgsock, SOL_SOCKET, SO_NOSIGPIPE, &nosigpipe, sizeof(nosigpipe));
#endif
// everything else is non recoverable in our scope
// we also mark as recoverable socket errors where it would block a
// non blocking socket, even though our socket is blocking, in case
// we ever have to implement a non blocking socket.
#ifdef _WIN32
const int errno_w = WSAGetLastError();
if (!(errno_w == WSAECONNRESET || errno_w == WSAEINTR || errno_w == WSAEINPROGRESS || errno_w == WSAEMFILE || errno_w == WSAEWOULDBLOCK) && s_sock != INVALID_SOCKET)
if (!(errno_w == WSAECONNRESET || errno_w == WSAEINTR || errno_w == WSAEINPROGRESS || errno_w == WSAEMFILE || errno_w == WSAEWOULDBLOCK) && m_sock != INVALID_SOCKET)
Console.Error("PINE: accept() returned error %d", errno_w);
#else
if (!(errno == ECONNABORTED || errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) && s_sock >= 0)
if (!(errno == ECONNABORTED || errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) && m_sock >= 0)
Console.Error("PINE: accept() returned error %d", errno);
#endif
@@ -414,7 +395,7 @@ void PINEServer::MainLoop()
{
Threading::SetNameOfCurrentThread("PINE Server");
while (!s_end.load(std::memory_order_acquire))
while (!m_end.load(std::memory_order_acquire))
{
if (!AcceptClient())
continue;
@@ -422,25 +403,25 @@ void PINEServer::MainLoop()
ClientLoop();
Console.WriteLn("PINE: Client disconnected.");
safe_close_portable(s_msgsock);
safe_close_portable(m_msgsock);
}
}
void PINEServer::ClientLoop()
{
while (!s_end.load(std::memory_order_acquire))
while (!m_end.load(std::memory_order_acquire))
{
// either int or ssize_t depending on the platform, so we have to
// use a bunch of auto
auto receive_length = 0;
auto end_length = 4;
const std::span<u8> ipc_buffer_span(s_ipc_buffer);
const std::span<u8> ipc_buffer_span(m_ipc_buffer);
// while we haven't received the entire packet, maybe due to
// socket datagram splittage, we continue to read
while (receive_length < end_length)
{
const auto tmp_length = read_portable(s_msgsock, &ipc_buffer_span[receive_length], MAX_IPC_SIZE - receive_length);
const auto tmp_length = read_portable(m_msgsock, &ipc_buffer_span[receive_length], MAX_IPC_SIZE - receive_length);
// we recreate the socket if an error happens
if (tmp_length <= 0)
@@ -469,10 +450,10 @@ void PINEServer::ClientLoop()
// disconnects
if (receive_length != 0)
{
res = ParseCommand(ipc_buffer_span.subspan(4), s_ret_buffer, (u32)end_length - 4);
res = ParseCommand(ipc_buffer_span.subspan(4), m_ret_buffer, (u32)end_length - 4);
// if we cannot send back our answer restart the socket
if (write_portable(s_msgsock, res.buffer.data(), res.size) < 0)
if (write_portable(m_msgsock, res.buffer.data(), res.size) < 0)
return;
}
}
@@ -480,30 +461,30 @@ void PINEServer::ClientLoop()
void PINEServer::Deinitialize()
{
s_end.store(true, std::memory_order_release);
m_end.store(true, std::memory_order_release);
#ifndef _WIN32
if (!s_socket_name.empty())
if (!m_socket_name.empty())
{
unlink(s_socket_name.c_str());
s_socket_name = {};
unlink(m_socket_name.c_str());
m_socket_name = {};
}
#endif
// shutdown() is needed, otherwise accept() will still block.
#ifdef _WIN32
if (s_sock != INVALID_SOCKET)
shutdown(s_sock, SD_BOTH);
if (m_sock != INVALID_SOCKET)
shutdown(m_sock, SD_BOTH);
#else
if (s_sock >= 0)
shutdown(s_sock, SHUT_RDWR);
if (m_sock >= 0)
shutdown(m_sock, SHUT_RDWR);
#endif
safe_close_portable(s_sock);
safe_close_portable(s_msgsock);
safe_close_portable(m_sock);
safe_close_portable(m_msgsock);
if (s_thread.joinable())
s_thread.join();
if (m_thread.joinable())
m_thread.join();
}
PINEServer::IPCBuffer PINEServer::ParseCommand(std::span<u8> buf, std::vector<u8>& ret_buffer, u32 buf_size)
+2 -3
View File
@@ -653,6 +653,7 @@ const char* Pcsx2Config::GSOptions::FMVAspectRatioSwitchNames[(size_t)FMVAspectR
nullptr};
const char* Pcsx2Config::GSOptions::BlendingLevelNames[] = {
"Automatic",
"Minimum",
"Basic",
"Medium",
@@ -708,8 +709,7 @@ std::optional<bool> Pcsx2Config::GSOptions::TriStateToOptionalBoolean(int value)
Pcsx2Config::GSOptions::GSOptions()
{
bitset[0] = 0;
bitset[1] = 0;
bitset = 0;
PCRTCAntiBlur = true;
DisableInterlaceOffset = false;
@@ -988,7 +988,6 @@ void Pcsx2Config::GSOptions::LoadSave(SettingsWrapper& wrap)
SettingsWrapBitBoolEx(SaveDepth, "SaveDepth");
SettingsWrapBitBoolEx(SaveAlpha, "SaveAlpha");
SettingsWrapBitBoolEx(SaveInfo, "SaveInfo");
SettingsWrapBitBoolEx(SaveTransferImages, "SaveTransferImages");
SettingsWrapBitBool(DumpReplaceableTextures);
SettingsWrapBitBool(DumpReplaceableMipmaps);
SettingsWrapBitBool(DumpTexturesWithFMVActive);
-4
View File
@@ -26,8 +26,6 @@ protected:
Pad::Mode currentMode = Pad::Mode::NOT_SET;
Pad::Command currentCommand = Pad::Command::NOT_SET;
size_t commandBytesReceived = 0;
bool analogLight = false;
bool analogLocked = false;
public: // Public members
PadBase(u8 unifiedSlot, size_t ejectTicks = 0);
@@ -56,8 +54,6 @@ public: // Public members
virtual std::tuple<u8, u8> GetRawRightAnalog() const = 0;
virtual u32 GetButtons() const = 0;
virtual u8 GetPressure(u32 index) const = 0;
virtual bool IsAnalogLightEnabled() const = 0;
virtual bool IsAnalogLocked() const = 0;
virtual bool Freeze(StateWrapper& sw);
+1 -11
View File
@@ -81,7 +81,7 @@ static const SettingInfo s_settings[] = {
};
const Pad::ControllerInfo PadDualshock2::ControllerInfo = {Pad::ControllerType::DualShock2, "DualShock2",
TRANSLATE_NOOP("Pad", "DualShock 2"), ICON_PF_DUALSHOCK2, s_bindings, s_settings, Pad::VibrationCapabilities::LargeSmallMotors};
TRANSLATE_NOOP("Pad", "DualShock 2"), ICON_PF_GAMEPAD_ALT, s_bindings, s_settings, Pad::VibrationCapabilities::LargeSmallMotors};
void PadDualshock2::ConfigLog()
{
@@ -853,16 +853,6 @@ u8 PadDualshock2::GetPressure(u32 index) const
}
}
bool PadDualshock2::IsAnalogLightEnabled() const
{
return this->analogLight;
}
bool PadDualshock2::IsAnalogLocked() const
{
return this->analogLocked;
}
bool PadDualshock2::Freeze(StateWrapper& sw)
{
if (!PadBase::Freeze(sw) || !sw.DoMarker("PadDualshock2"))
+2 -2
View File
@@ -63,6 +63,8 @@ private:
u32 buttons = 0xffffffffu;
Analogs analogs;
bool analogLight = false;
bool analogLocked = false;
// Analog button can be held without changing its state.
// We track here if it is currently held down, to avoid flipping in
// and out of analog mode every frame.
@@ -153,8 +155,6 @@ public:
std::tuple<u8, u8> GetRawRightAnalog() const override;
u32 GetButtons() const override;
u8 GetPressure(u32 index) const override;
bool IsAnalogLightEnabled() const override;
bool IsAnalogLocked() const override;
bool Freeze(StateWrapper& sw) override;
-10
View File
@@ -402,16 +402,6 @@ u8 PadGuitar::GetPressure(u32 index) const
return 0;
}
bool PadGuitar::IsAnalogLightEnabled() const
{
return this->analogLight;
}
bool PadGuitar::IsAnalogLocked() const
{
return this->analogLocked;
}
bool PadGuitar::Freeze(StateWrapper& sw)
{
if (!PadBase::Freeze(sw) || !sw.DoMarker("PadGuitar"))

Some files were not shown because too many files have changed in this diff Show More