Compare commits

..

1 Commits

Author SHA1 Message Date
refractionpcsx2 6b752a888e GS/HW: Add new method of rounding sprites 2026-02-03 21:03:20 +00:00
127 changed files with 2331 additions and 4562 deletions
@@ -17,7 +17,7 @@ jobs:
run: ./.github/workflows/scripts/common/update_base_translation.sh
- name: Create Pull Request
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0
uses: peter-evans/create-pull-request@98357b18bf14b5342f975ff684046ec3b2a07725
with:
title: "Qt: Update Base Translation"
commit-message: "[ci skip] Qt: Update Base Translation."
@@ -19,7 +19,7 @@ jobs:
mv ./game_controller_db.txt ${{github.workspace}}/bin/resources/game_controller_db.txt
- name: Create Pull Request
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0
uses: peter-evans/create-pull-request@98357b18bf14b5342f975ff684046ec3b2a07725
with:
title: "PAD: Update to latest controller database"
commit-message: "[ci skip] PAD: Update to latest controller database."
@@ -18,9 +18,6 @@ if [ "${INSTALLDIR:0:1}" != "/" ]; then
INSTALLDIR="$PWD/$INSTALLDIR"
fi
QT=6.10.2
QTAPNG=1.3.0
FFMPEG=8.0
FREETYPE=2.14.1
HARFBUZZ=12.2.0
@@ -30,6 +27,8 @@ LIBPNG=1.6.53
LIBWEBP=1.6.0
NVENC=13.0.19.0
SDL=SDL3-3.4.0
QT=6.10.1
QTAPNG=1.3.0
LZ4=1.10.0
VULKAN=1.4.328.1
ZSTD=1.5.7
@@ -48,14 +47,6 @@ cd deps-build
export PKG_CONFIG_PATH="$INSTALLDIR/lib/pkgconfig:$PKG_CONFIG_PATH"
cat > SHASUMS <<EOF
aeb78d29291a2b5fd53cb55950f8f5065b4978c25fb1d77f627d695ab9adf21e qtbase-everywhere-src-$QT.tar.xz
8b8f9c718638081e7b3c000e7f31910140b1202a98e98df5d1b496fe6f639d67 qtimageformats-everywhere-src-$QT.tar.xz
f07ff80f38caf235187200345392ca7479445ddf49a36c3694cd52a735dad6e1 qtsvg-everywhere-src-$QT.tar.xz
1e3d2c07c1fd76d2425c6eaeeaa62ffaff5f79210c4e1a5bc2a6a9db668d5b24 qttools-everywhere-src-$QT.tar.xz
b3b3813bc9d76b545716dc8b6e659fa71b6e2bc14569e9fab6dab8b30650a644 qttranslations-everywhere-src-$QT.tar.xz
391998eb432719df26a6a67d8efdc67f8bf2afdd76c1ee3381ebff4fe7527ee2 qtwayland-everywhere-src-$QT.tar.xz
f1d3be3489f758efe1a8f12118a212febbe611aa670af32e0159fa3c1feab2a6 QtApng-$QTAPNG.tar.gz
b2751fccb6cc4c77708113cd78b561059b6fa904b24162fa0be2d60273d27b8e ffmpeg-$FFMPEG.tar.xz
32427e8c471ac095853212a37aef816c60b42052d4d9e48230bab3bdf2936ccc freetype-$FREETYPE.tar.xz
f63fc519f150465bd0bdafcdf3d0e9c23474f4c474171cd515ea1b3a72c081fb harfbuzz-$HARFBUZZ.tar.gz
@@ -69,14 +60,20 @@ e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWE
13da39edb3a40ed9713ae390ca89faa2f1202c9dda869ef306a8d4383e242bee nv-codec-headers-$NVENC.tar.gz
c465aa56757e7746ac707f582b6e2d51546569a4a2488c1172fb543aa5fdfc2c vulkan-sdk-$VULKAN.tar.gz
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
51dbf24fe72e43dd7cb9a289d3cab47112010f1a2ed69b6fc8ac0dff31991ed2 KDDockWidgets-$KDDOCKWIDGETS.tar.gz
7bd4e79ce18b1d47517e7e91fbb7cf19d4f01942804a519bc7c0bf32b6325dd5 plutovg-$PLUTOVG.tar.gz
78561b571ac224030cdc450ca2986b4de915c2ba7616004a6d71a379bffd15f3 plutosvg-$PLUTOSVG.tar.gz
5a6226f7e23db51fdc3223121eba53f3f5447cf0cc4d6cb82a3a2df7a65d265d qtbase-everywhere-src-$QT.tar.xz
498eabdf2381db96f808942b3e3c765f6360fe6c0e9961f0a45ff7a4c68d7a72 qtimageformats-everywhere-src-$QT.tar.xz
c02f355a58f3bbcf404a628bf488b6aeb2d84a94c269afdb86f6e529343ab01f qtsvg-everywhere-src-$QT.tar.xz
8148408380ffea03101a26305c812b612ea30dbc07121e58707601522404d49b qttools-everywhere-src-$QT.tar.xz
8e49a2df88a12c376a479ae7bd272a91cf57ebb4e7c0cf7341b3565df99d2314 qttranslations-everywhere-src-$QT.tar.xz
49bf6db800227a6b2c971f4c5d03dd1e81297e7ffb296ce4a96437304f27cb13 qtwayland-everywhere-src-$QT.tar.xz
f1d3be3489f758efe1a8f12118a212febbe611aa670af32e0159fa3c1feab2a6 QtApng-$QTAPNG.tar.gz
8a89fb6612ace8954470aae004623374a8fc8b7a34a4277bee5527173b064faf shaderc-$SHADERC.tar.gz
272d2725b140e09e85b96eecdc59c2e00c1a14cda2301767e1bf3c363a44b931 shaderc-glslang-$SHADERC_GLSLANG.tar.gz
c693867f10a7760ef1bcf85419d51783586768cc2c601d03841bc6a8b2554b9c shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz
06b0a042f2e121e954badb4fd78c9e2d4bc7ed6087eceb26ab559c23cf94334f shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz
51dbf24fe72e43dd7cb9a289d3cab47112010f1a2ed69b6fc8ac0dff31991ed2 KDDockWidgets-$KDDOCKWIDGETS.tar.gz
7bd4e79ce18b1d47517e7e91fbb7cf19d4f01942804a519bc7c0bf32b6325dd5 plutovg-$PLUTOVG.tar.gz
78561b571ac224030cdc450ca2986b4de915c2ba7616004a6d71a379bffd15f3 plutosvg-$PLUTOSVG.tar.gz
EOF
curl -L \
@@ -216,7 +213,7 @@ tar xf "harfbuzz-$HARFBUZZ.tar.gz"
cd "harfbuzz-$HARFBUZZ"
# Add an SOVERSION to match system harfbuzz
sed -i 's/PROPERTIES VISIBILITY_INLINES_HIDDEN TRUE)/PROPERTIES VISIBILITY_INLINES_HIDDEN TRUE SOVERSION 0)/g' CMakeLists.txt
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DHB_BUILD_UTILS=OFF -DHB_HAVE_FREETYPE=ON -B build -G Ninja
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DHB_BUILD_UTILS=OFF -DHB_HAVE_FREETYPE=ON -DHB_HAVE_GOBJECT=ON -B build -G Ninja
cmake --build build --parallel
ninja -C build install
cd ..
@@ -250,7 +247,7 @@ tar xf "qtbase-everywhere-src-$QT.tar.xz"
cd "qtbase-everywhere-src-$QT"
mkdir build
cd build
../configure -prefix "$INSTALLDIR" -release -dbus-linked -gui -widgets -fontconfig -qt-doubleconversion -ssl -openssl-runtime -opengl desktop -qpa xcb,wayland -xkbcommon -xcb -- --log-level=STATUS -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DFEATURE_dbus=ON -DFEATURE_icu=OFF -DFEATURE_printsupport=OFF -DFEATURE_sql=OFF -DFEATURE_system_png=ON -DFEATURE_system_jpeg=ON -DFEATURE_system_zlib=ON -DFEATURE_system_freetype=ON -DFEATURE_system_harfbuzz=ON -DFEATURE_gtk3=OFF
../configure -prefix "$INSTALLDIR" -release -dbus-linked -gui -widgets -fontconfig -qt-doubleconversion -ssl -openssl-runtime -opengl desktop -qpa xcb,wayland -xkbcommon -xcb -gtk -- --log-level=STATUS -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DFEATURE_dbus=ON -DFEATURE_icu=OFF -DFEATURE_printsupport=OFF -DFEATURE_sql=OFF -DFEATURE_system_png=ON -DFEATURE_system_jpeg=ON -DFEATURE_system_zlib=ON -DFEATURE_system_freetype=ON -DFEATURE_system_harfbuzz=ON
cmake --build . --parallel
ninja install
cd ../../
@@ -38,9 +38,6 @@ if [ "${INSTALLDIR:0:1}" != "/" ]; then
INSTALLDIR="$PWD/$INSTALLDIR"
fi
QT=6.10.1
QTAPNG=1.3.0
FREETYPE=2.14.1
HARFBUZZ=12.2.0
SDL=SDL3-3.4.0
@@ -51,6 +48,8 @@ LIBJPEGTURBO=3.1.2
LIBWEBP=1.6.0
FFMPEG=8.0
MOLTENVK=1.4.1
QT=6.10.1
QTAPNG=1.3.0
KDDOCKWIDGETS=2.4.0
PLUTOVG=1.3.2
PLUTOSVG=0.0.7
@@ -79,13 +78,6 @@ CMAKE_ARCH_ARM64=-DCMAKE_OSX_ARCHITECTURES="arm64"
CMAKE_ARCH_UNIVERSAL=-DCMAKE_OSX_ARCHITECTURES="x86_64;arm64"
cat > SHASUMS <<EOF
aeb78d29291a2b5fd53cb55950f8f5065b4978c25fb1d77f627d695ab9adf21e qtbase-everywhere-src-$QT.tar.xz
8b8f9c718638081e7b3c000e7f31910140b1202a98e98df5d1b496fe6f639d67 qtimageformats-everywhere-src-$QT.tar.xz
f07ff80f38caf235187200345392ca7479445ddf49a36c3694cd52a735dad6e1 qtsvg-everywhere-src-$QT.tar.xz
1e3d2c07c1fd76d2425c6eaeeaa62ffaff5f79210c4e1a5bc2a6a9db668d5b24 qttools-everywhere-src-$QT.tar.xz
b3b3813bc9d76b545716dc8b6e659fa71b6e2bc14569e9fab6dab8b30650a644 qttranslations-everywhere-src-$QT.tar.xz
f1d3be3489f758efe1a8f12118a212febbe611aa670af32e0159fa3c1feab2a6 QtApng-$QTAPNG.tar.gz
32427e8c471ac095853212a37aef816c60b42052d4d9e48230bab3bdf2936ccc freetype-$FREETYPE.tar.xz
f63fc519f150465bd0bdafcdf3d0e9c23474f4c474171cd515ea1b3a72c081fb harfbuzz-$HARFBUZZ.tar.gz
082cbf5f429e0d80820f68dc2b507a94d4cc1b4e70817b119bbb8ec6a69584b8 $SDL.tar.gz
@@ -97,14 +89,19 @@ e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWE
8f0012234b464ce50890c490f18194f913a7b1f4e6a03d6644179fa0f867d0cf libjpeg-turbo-$LIBJPEGTURBO.tar.gz
b2751fccb6cc4c77708113cd78b561059b6fa904b24162fa0be2d60273d27b8e ffmpeg-$FFMPEG.tar.xz
9985f141902a17de818e264d17c1ce334b748e499ee02fcb4703e4dc0038f89c v$MOLTENVK.tar.gz
51dbf24fe72e43dd7cb9a289d3cab47112010f1a2ed69b6fc8ac0dff31991ed2 KDDockWidgets-$KDDOCKWIDGETS.tar.gz
7bd4e79ce18b1d47517e7e91fbb7cf19d4f01942804a519bc7c0bf32b6325dd5 plutovg-$PLUTOVG.tar.gz
78561b571ac224030cdc450ca2986b4de915c2ba7616004a6d71a379bffd15f3 plutosvg-$PLUTOSVG.tar.gz
5a6226f7e23db51fdc3223121eba53f3f5447cf0cc4d6cb82a3a2df7a65d265d qtbase-everywhere-src-$QT.tar.xz
498eabdf2381db96f808942b3e3c765f6360fe6c0e9961f0a45ff7a4c68d7a72 qtimageformats-everywhere-src-$QT.tar.xz
c02f355a58f3bbcf404a628bf488b6aeb2d84a94c269afdb86f6e529343ab01f qtsvg-everywhere-src-$QT.tar.xz
8148408380ffea03101a26305c812b612ea30dbc07121e58707601522404d49b qttools-everywhere-src-$QT.tar.xz
8e49a2df88a12c376a479ae7bd272a91cf57ebb4e7c0cf7341b3565df99d2314 qttranslations-everywhere-src-$QT.tar.xz
f1d3be3489f758efe1a8f12118a212febbe611aa670af32e0159fa3c1feab2a6 QtApng-$QTAPNG.tar.gz
8a89fb6612ace8954470aae004623374a8fc8b7a34a4277bee5527173b064faf shaderc-$SHADERC.tar.gz
272d2725b140e09e85b96eecdc59c2e00c1a14cda2301767e1bf3c363a44b931 shaderc-glslang-$SHADERC_GLSLANG.tar.gz
c693867f10a7760ef1bcf85419d51783586768cc2c601d03841bc6a8b2554b9c shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz
06b0a042f2e121e954badb4fd78c9e2d4bc7ed6087eceb26ab559c23cf94334f shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz
51dbf24fe72e43dd7cb9a289d3cab47112010f1a2ed69b6fc8ac0dff31991ed2 KDDockWidgets-$KDDOCKWIDGETS.tar.gz
7bd4e79ce18b1d47517e7e91fbb7cf19d4f01942804a519bc7c0bf32b6325dd5 plutovg-$PLUTOVG.tar.gz
78561b571ac224030cdc450ca2986b4de915c2ba7616004a6d71a379bffd15f3 plutosvg-$PLUTOSVG.tar.gz
EOF
curl -C - -L \
@@ -20,9 +20,6 @@ if [ "${INSTALLDIR:0:1}" != "/" ]; then
INSTALLDIR="$PWD/$INSTALLDIR"
fi
QT=6.10.2
QTAPNG=1.3.0
FREETYPE=2.14.1
HARFBUZZ=12.2.0
SDL=SDL3-3.4.0
@@ -33,6 +30,8 @@ LIBJPEGTURBO=3.1.2
LIBWEBP=1.6.0
FFMPEG=8.0
MOLTENVK=1.4.1
QT=6.10.1
QTAPNG=1.3.0
KDDOCKWIDGETS=2.4.0
PLUTOVG=1.3.2
PLUTOSVG=0.0.7
@@ -60,13 +59,6 @@ CMAKE_COMMON=(
)
cat > SHASUMS <<EOF
aeb78d29291a2b5fd53cb55950f8f5065b4978c25fb1d77f627d695ab9adf21e qtbase-everywhere-src-$QT.tar.xz
8b8f9c718638081e7b3c000e7f31910140b1202a98e98df5d1b496fe6f639d67 qtimageformats-everywhere-src-$QT.tar.xz
f07ff80f38caf235187200345392ca7479445ddf49a36c3694cd52a735dad6e1 qtsvg-everywhere-src-$QT.tar.xz
1e3d2c07c1fd76d2425c6eaeeaa62ffaff5f79210c4e1a5bc2a6a9db668d5b24 qttools-everywhere-src-$QT.tar.xz
b3b3813bc9d76b545716dc8b6e659fa71b6e2bc14569e9fab6dab8b30650a644 qttranslations-everywhere-src-$QT.tar.xz
f1d3be3489f758efe1a8f12118a212febbe611aa670af32e0159fa3c1feab2a6 QtApng-$QTAPNG.tar.gz
32427e8c471ac095853212a37aef816c60b42052d4d9e48230bab3bdf2936ccc freetype-$FREETYPE.tar.xz
f63fc519f150465bd0bdafcdf3d0e9c23474f4c474171cd515ea1b3a72c081fb harfbuzz-$HARFBUZZ.tar.gz
082cbf5f429e0d80820f68dc2b507a94d4cc1b4e70817b119bbb8ec6a69584b8 $SDL.tar.gz
@@ -78,14 +70,19 @@ e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWE
8f0012234b464ce50890c490f18194f913a7b1f4e6a03d6644179fa0f867d0cf libjpeg-turbo-$LIBJPEGTURBO.tar.gz
b2751fccb6cc4c77708113cd78b561059b6fa904b24162fa0be2d60273d27b8e ffmpeg-$FFMPEG.tar.xz
9985f141902a17de818e264d17c1ce334b748e499ee02fcb4703e4dc0038f89c v$MOLTENVK.tar.gz
51dbf24fe72e43dd7cb9a289d3cab47112010f1a2ed69b6fc8ac0dff31991ed2 KDDockWidgets-$KDDOCKWIDGETS.tar.gz
7bd4e79ce18b1d47517e7e91fbb7cf19d4f01942804a519bc7c0bf32b6325dd5 plutovg-$PLUTOVG.tar.gz
78561b571ac224030cdc450ca2986b4de915c2ba7616004a6d71a379bffd15f3 plutosvg-$PLUTOSVG.tar.gz
5a6226f7e23db51fdc3223121eba53f3f5447cf0cc4d6cb82a3a2df7a65d265d qtbase-everywhere-src-$QT.tar.xz
498eabdf2381db96f808942b3e3c765f6360fe6c0e9961f0a45ff7a4c68d7a72 qtimageformats-everywhere-src-$QT.tar.xz
c02f355a58f3bbcf404a628bf488b6aeb2d84a94c269afdb86f6e529343ab01f qtsvg-everywhere-src-$QT.tar.xz
8148408380ffea03101a26305c812b612ea30dbc07121e58707601522404d49b qttools-everywhere-src-$QT.tar.xz
8e49a2df88a12c376a479ae7bd272a91cf57ebb4e7c0cf7341b3565df99d2314 qttranslations-everywhere-src-$QT.tar.xz
f1d3be3489f758efe1a8f12118a212febbe611aa670af32e0159fa3c1feab2a6 QtApng-$QTAPNG.tar.gz
8a89fb6612ace8954470aae004623374a8fc8b7a34a4277bee5527173b064faf shaderc-$SHADERC.tar.gz
272d2725b140e09e85b96eecdc59c2e00c1a14cda2301767e1bf3c363a44b931 shaderc-glslang-$SHADERC_GLSLANG.tar.gz
c693867f10a7760ef1bcf85419d51783586768cc2c601d03841bc6a8b2554b9c shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz
06b0a042f2e121e954badb4fd78c9e2d4bc7ed6087eceb26ab559c23cf94334f shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz
51dbf24fe72e43dd7cb9a289d3cab47112010f1a2ed69b6fc8ac0dff31991ed2 KDDockWidgets-$KDDOCKWIDGETS.tar.gz
7bd4e79ce18b1d47517e7e91fbb7cf19d4f01942804a519bc7c0bf32b6325dd5 plutovg-$PLUTOVG.tar.gz
78561b571ac224030cdc450ca2986b4de915c2ba7616004a6d71a379bffd15f3 plutosvg-$PLUTOSVG.tar.gz
EOF
curl -L \
@@ -2,15 +2,10 @@
setlocal enabledelayedexpansion
echo Setting environment...
if exist "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" (
for /f "usebackq tokens=*" %%i in (`call "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -version "[17, 18)" -latest -property installationPath`) do set "VSINSTPATH=%%i"
if defined VSINSTPATH (
echo VSINSTPATH=!VSINSTPATH!
call "!VSINSTPATH!\VC\Auxiliary\Build\vcvarsamd64_arm64.bat" || goto error
) else (
echo Visual Studio 2022 not found.
goto error
)
if exist "%ProgramFiles%\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsamd64_arm64.bat" (
call "%ProgramFiles%\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsamd64_arm64.bat"
) else if exist "%ProgramFiles%\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsamd64_arm64.bat" (
call "%ProgramFiles%\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsamd64_arm64.bat"
) else (
echo Visual Studio 2022 not found.
goto error
@@ -47,16 +42,15 @@ echo INSTALLDIR=%INSTALLDIR%
cd "%BUILDDIR%"
set QT=6.10.2
set QTMINOR=6.10
set QTAPNG=1.3.0
set FREETYPE=2.14.1
set HARFBUZZ=12.2.0
set LIBJPEGTURBO=3.1.2
set LIBPNG=1653
set LIBPNGLONG=1.6.53
set SDL=SDL3-3.4.0
set QT=6.10.1
set QTMINOR=6.10
set QTAPNG=1.3.0
set LZ4=1.10.0
set WEBP=1.6.0
set ZLIB=1.3.1
@@ -73,13 +67,6 @@ set SHADERC_SPIRVTOOLS=971a7b6e8d7740035bbff089bbbf9f42951ecfd5
set AGILITYSDK=1.618.5
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 690e08ce807041150d388b5351de2e591febf0a0bc973b56e1197e2df9a2d96f || goto error
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" a407e489ca8d68639530e881aea797f58754e355ca06024a73358bd9cc5fca17 || goto error
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" fd9f4f6e983a55f6b0ba4c49ce13f8b014cd30d12e75a49a478a640462f9bf64 || goto error
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" a498357aed659c66aa87ceb556eacab55e3e7d7c9b9599049066de70eb7efa59 || goto error
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" cf5e04a2048c02369f579c1251f61af965f241cde2d69de3db90e6c9f0ee2bf3 || goto error
call :downloadfile "QtApng-%QTAPNG%.zip" "https://github.com/jurplel/QtApng/archive/refs/tags/%QTAPNG%.zip" 5176082cdd468047a7eb1ec1f106b032f57df207aa318d559b29606b00d159ac || goto error
call :downloadfile "freetype-%FREETYPE%.tar.gz" https://sourceforge.net/projects/freetype/files/freetype2/%FREETYPE%/freetype-%FREETYPE%.tar.gz/download 174d9e53402e1bf9ec7277e22ec199ba3e55a6be2c0740cb18c0ee9850fc8c34 || goto error
call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip 31490c781bacd2ce56862555b11c51c964977c39f14f51b817dfaecf0be089fe || goto error
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1653.zip 140566abc64bb2320cb35f1d154d1cb3eb7174a12234d33bfdffb446bdc0a1d2 || goto error
@@ -87,6 +74,12 @@ call :downloadfile "lpng%LIBPNG%-apng.patch.gz" https://download.sourceforge.net
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" 8f0012234b464ce50890c490f18194f913a7b1f4e6a03d6644179fa0f867d0cf || 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" 9ac2debb493e0d3e13dbd2729fb91f4bfeb00a0f4dff5e04b73cc9bac276b38d || goto error
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" c43f471a808b07fc541528410e94ce89c6745bdc1d744492e19911d35fbf7d33 || goto error
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" 2d828d8c999fdd18167937c071781c22321c643b04a106c714411c2356cdb26d || goto error
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" ddd74a417d2397eb085d047a9b6ba52b76e748055817f728fe691f8456035d23 || goto error
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" db8e49ed50912c3c064a4f9ada7791c09eccec5a8d53463a19608eaab17679f0 || goto error
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" 868eb651e395d48ade5932ef2c386e606e054eb5888ebe5284fbd8cb63ed935a || 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://github.com/madler/zlib/releases/download/v%ZLIB%/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
@@ -2,15 +2,10 @@
setlocal enabledelayedexpansion
echo Setting environment...
if exist "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" (
for /f "usebackq tokens=*" %%i in (`call "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -version "[17, 18)" -latest -property installationPath`) do set "VSINSTPATH=%%i"
if defined VSINSTPATH (
echo VSINSTPATH=!VSINSTPATH!
call "!VSINSTPATH!\VC\Auxiliary\Build\vcvars64.bat" || goto error
) else (
echo Visual Studio 2022 not found.
goto error
)
if exist "%ProgramFiles%\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" (
call "%ProgramFiles%\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
) else if exist "%ProgramFiles%\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" (
call "%ProgramFiles%\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat"
) else (
echo Visual Studio 2022 not found.
goto error
@@ -45,16 +40,15 @@ set "PATH=%PATH%;%INSTALLDIR%\bin"
cd "%BUILDDIR%"
set QT=6.10.2
set QTMINOR=6.10
set QTAPNG=1.3.0
set FREETYPE=2.14.1
set HARFBUZZ=12.2.0
set LIBJPEGTURBO=3.1.2
set LIBPNG=1653
set LIBPNGLONG=1.6.53
set SDL=SDL3-3.4.0
set QT=6.10.1
set QTMINOR=6.10
set QTAPNG=1.3.0
set LZ4=1.10.0
set WEBP=1.6.0
set ZLIB=1.3.1
@@ -71,13 +65,6 @@ set SHADERC_SPIRVTOOLS=971a7b6e8d7740035bbff089bbbf9f42951ecfd5
set AGILITYSDK=1.618.5
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 690e08ce807041150d388b5351de2e591febf0a0bc973b56e1197e2df9a2d96f || goto error
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" a407e489ca8d68639530e881aea797f58754e355ca06024a73358bd9cc5fca17 || goto error
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" fd9f4f6e983a55f6b0ba4c49ce13f8b014cd30d12e75a49a478a640462f9bf64 || goto error
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" a498357aed659c66aa87ceb556eacab55e3e7d7c9b9599049066de70eb7efa59 || goto error
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" cf5e04a2048c02369f579c1251f61af965f241cde2d69de3db90e6c9f0ee2bf3 || goto error
call :downloadfile "QtApng-%QTAPNG%.zip" "https://github.com/jurplel/QtApng/archive/refs/tags/%QTAPNG%.zip" 5176082cdd468047a7eb1ec1f106b032f57df207aa318d559b29606b00d159ac || goto error
call :downloadfile "freetype-%FREETYPE%.tar.gz" https://sourceforge.net/projects/freetype/files/freetype2/%FREETYPE%/freetype-%FREETYPE%.tar.gz/download 174d9e53402e1bf9ec7277e22ec199ba3e55a6be2c0740cb18c0ee9850fc8c34 || goto error
call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip 31490c781bacd2ce56862555b11c51c964977c39f14f51b817dfaecf0be089fe || goto error
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1653.zip 140566abc64bb2320cb35f1d154d1cb3eb7174a12234d33bfdffb446bdc0a1d2 || goto error
@@ -85,6 +72,12 @@ call :downloadfile "lpng%LIBPNG%-apng.patch.gz" https://download.sourceforge.net
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" 8f0012234b464ce50890c490f18194f913a7b1f4e6a03d6644179fa0f867d0cf || 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" 9ac2debb493e0d3e13dbd2729fb91f4bfeb00a0f4dff5e04b73cc9bac276b38d || goto error
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" c43f471a808b07fc541528410e94ce89c6745bdc1d744492e19911d35fbf7d33 || goto error
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" 2d828d8c999fdd18167937c071781c22321c643b04a106c714411c2356cdb26d || goto error
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" ddd74a417d2397eb085d047a9b6ba52b76e748055817f728fe691f8456035d23 || goto error
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" db8e49ed50912c3c064a4f9ada7791c09eccec5a8d53463a19608eaab17679f0 || goto error
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" 868eb651e395d48ade5932ef2c386e606e054eb5888ebe5284fbd8cb63ed935a || 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://github.com/madler/zlib/releases/download/v%ZLIB%/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
+4
View File
@@ -84,10 +84,14 @@ endif()
if(_M_ARM64)
message(WARNING "
*************** UNSUPPORTED CONFIGURATION ***************
Apple Silicon support in PCSX2 is INCOMPLETE. There are
currently no EE/VU/IOP recompilers, and games will run
VERY slow. There is no date for completion yet, you
should set -DCMAKE_OSX_ARCHITECTURES=x86_64 for now,
unless you want to work on the recompilers.
We also ask that you read https://dont-ship.it/.
*********************************************************")
endif()
+83 -79
View File
@@ -1980,8 +1980,6 @@ SCAJ-20116:
SCAJ-20117:
name: "Fu-un Bakumatsu-den"
region: "NTSC-Unk"
gsHWFixes:
halfPixelOffset: 5 # Fixes vertical lines.
SCAJ-20118:
name: "ラジアータ ストーリーズ"
name-sort: "らじあーた すとーりーず"
@@ -6270,23 +6268,19 @@ SCES-53880:
region: "PAL-E"
SCES-53881:
name: "Buzz! Le Grand Quiz"
name-en: "Buzz! The Big Quiz"
region: "PAL-F"
SCES-53882:
name: "Buzz! Il Superquiz"
name-en: "Buzz! The Big Quiz"
name: "Buzz! The Big Quiz"
region: "PAL-I"
gameFixes:
- EETimingHack # Fixes freezes.
SCES-53883:
name: "Buzz! Das große Quiz"
name-en: "Buzz! The Big Quiz"
name: "Buzz! The Big Quiz"
region: "PAL-G"
gameFixes:
- EETimingHack # Fixes freezes.
SCES-53884:
name: "Buzz! El Gran Reto"
name-en: "Buzz! The Big Quiz"
name: "Buzz! El GRAN Reto"
region: "PAL-S"
compat: 2
gameFixes:
@@ -6323,12 +6317,10 @@ SCES-53926:
name: "Buzz! The Big Quiz"
region: "PAL-SC"
SCES-53927:
name: "Buzz! Suuri Tietovisa"
name-en: "Buzz! The Big Quiz"
name: "Buzz! The Big Quiz"
region: "PAL-FI"
SCES-53929:
name: "Buzz! O Grande Quiz"
name-en: "Buzz! The Big Quiz"
name: "Buzz! The Big Quiz"
region: "PAL-P"
SCES-53931:
name: "Shinobido - Way of the Ninja"
@@ -6444,23 +6436,19 @@ SCES-54258:
name: "Buzz! The Sports Quiz"
region: "PAL-E"
SCES-54259:
name: "Buzz! Das Sport-Quiz"
name-en: "Buzz! The Sports Quiz"
name: "Buzz! The Sports Quiz"
region: "PAL-G"
SCES-54260:
name: "Buzz! Le Quiz du Sport"
name-en: "Buzz! The Sports Quiz"
region: "PAL-F"
SCES-54261:
name: "Buzz! The Sports Quiz"
region: "PAL-I"
SCES-54262:
name: "Buzz! El Gran Concurso de Deportes"
name-en: "Buzz! The Sports Quiz"
name: "Buzz! - El Gran Concurso de Deportes"
region: "PAL-S"
SCES-54263:
name: "Buzz! O Quiz Desportivo"
name-en: "Buzz! The Sports Quiz"
name: "Buzz! The Sports Quiz"
region: "PAL-P"
SCES-54264:
name: "Buzz! The Sports Quiz"
@@ -6472,8 +6460,7 @@ SCES-54266:
name: "Buzz! The Sports Quiz"
region: "PAL-SC"
SCES-54267:
name: "Buzz! Sporttivisa"
name-en: "Buzz! The Sports Quiz"
name: "Buzz! The Sports Quiz"
region: "PAL-FI"
SCES-54268:
name: "Buzz! The Sports Quiz"
@@ -6509,29 +6496,24 @@ SCES-54496:
region: "PAL-E"
SCES-54497:
name: "Buzz! Le Mega Quiz"
name-en: "Buzz! The Mega Quiz"
region: "PAL-F"
SCES-54498:
name: "Buzz! The Mega Quiz"
region: "PAL-I"
SCES-54499:
name: "Buzz! Das Mega-Quiz"
name-en: "Buzz! The Mega Quiz"
region: "PAL-G"
SCES-54500:
name: "Buzz! El Mega Concurso"
name-en: "Buzz! The Mega Quiz"
region: "PAL-S"
SCES-54501:
name: "Buzz! The Mega Quiz"
region: "PAL-A"
SCES-54503:
name: "Buzz! Megavisa"
name-en: "Buzz! The Mega Quiz"
region: "PAL-FI"
SCES-54504:
name: "Buzz! O Mega Quiz"
name-en: "Buzz! The Mega Quiz"
region: "PAL-P"
SCES-54505:
name: "Buzz! The Mega Quiz"
@@ -13235,7 +13217,9 @@ SLAJ-25018:
region: "NTSC-HK"
compat: 5
gsHWFixes:
halfPixelOffset: 5 # Fixes vertical lines.
alignSprite: 1 # Fixes vertical lines.
forceEvenSpritePosition: 1 # Improves visual clarity whilst upscaling.
roundSprite: 1 # Reduces graphics garbage on UI whilst upscaling.
SLAJ-25019:
name: "The Lord of the Rings - The Return of the King"
region: "NTSC-C"
@@ -22720,7 +22704,9 @@ SLES-53191:
name: "Kaido Racer"
region: "PAL-M5"
gsHWFixes:
halfPixelOffset: 5 # Fixes vertical lines.
halfPixelOffset: 2 # Fixes ghosting during Rain/Storm.
alignSprite: 1 # Fixes vertical lines.
forceEvenSpritePosition: 1 # De-blurs the 3D image.
SLES-53192:
name: "Tim Burton's The Nightmare Before Christmas - Oogie's Reveng"
name-sort: "Nightmare Before Christmas, The - Tim Burton's"
@@ -24983,7 +24969,9 @@ SLES-53900:
name: "Kaido Racer 2"
region: "PAL-M3"
gsHWFixes:
halfPixelOffset: 5 # Fixes vertical lines.
halfPixelOffset: 2 # Fixes ghosting during Storm.
alignSprite: 1 # Fixes black lines when upscaling.
forceEvenSpritePosition: 1 # De-blurs the 3D image.
SLES-53901:
name: "Torino 2006"
region: "PAL-M5"
@@ -31348,7 +31336,9 @@ SLKA-25063:
name-en: "Kaido Battle"
region: "NTSC-K"
gsHWFixes:
halfPixelOffset: 5 # Fixes vertical lines.
halfPixelOffset: 2 # Fixes ghosting during Rain.
alignSprite: 1 # Fixes vertical lines.
forceEvenSpritePosition: 1 # De-blurs the 3D image.
SLKA-25064:
name: "천주 3 천벌"
name-en: "Tenchu - Wrath of Heaven"
@@ -31443,7 +31433,9 @@ SLKA-25084:
region: "NTSC-K"
compat: 5
gsHWFixes:
halfPixelOffset: 5 # Fixes vertical lines.
alignSprite: 1 # Fixes vertical lines.
forceEvenSpritePosition: 1 # Improves visual clarity whilst upscaling.
roundSprite: 1 # Reduces graphics garbage on UI whilst upscaling.
SLKA-25085:
name: "진・삼국무쌍 3 맹장전"
name-en: "Jin Samguk Mussang 3 - Maengjangjeon"
@@ -31731,7 +31723,9 @@ SLKA-25146:
name-en: "Kaido Battle 2 - Chain Reaction"
region: "NTSC-K"
gsHWFixes:
halfPixelOffset: 5 # Fixes vertical lines.
halfPixelOffset: 2 # Fixes ghosting during Rain/Storm.
alignSprite: 1 # Fixes vertical lines.
forceEvenSpritePosition: 1 # De-blurs the 3D image.
SLKA-25148:
name: "MVP 베이스볼 2004"
name-en: "MVP Baseball 2004"
@@ -32318,11 +32312,9 @@ SLKA-25255:
name-en: "Mobile Suit Gundam Seed - Never Ending Tomorrow"
region: "NTSC-K"
SLKA-25257:
name: "풍운 막말전" # Undumped on ReDump as of 2025-08-28
name-en: "Fu-un Bakumatsu-den"
name: "풍운 막말전" # Undumped on ReDump as of 2025-08-28
name-en: "Fu-un Bakumatsu Den"
region: "NTSC-K"
gsHWFixes:
halfPixelOffset: 5 # Fixes vertical lines.
SLKA-25258:
name: "요시츠네 영웅전"
name-sort: "Yoshitsune Yeongungjeon"
@@ -35583,7 +35575,9 @@ SLPM-60195:
name-en: "Kaidō Battle - Nikko, Haruna, Rokko, Hakone [Trial]"
region: "NTSC-J"
gsHWFixes:
halfPixelOffset: 5 # Fixes vertical lines.
halfPixelOffset: 2 # Fixes ghosting during Rain.
alignSprite: 1 # Fixes vertical lines.
forceEvenSpritePosition: 1 # De-blurs the 3D image.
SLPM-60197:
name: "エキサイティングプロレス 4 [体験版]"
name-sort: "えきさいてぃんぐぷろれす4 [たいけんばん]"
@@ -35627,7 +35621,9 @@ SLPM-60206:
name-en: "Shutokou Battle 01 [Trial]"
region: "NTSC-J"
gsHWFixes:
halfPixelOffset: 5 # Fixes vertical lines.
alignSprite: 1 # Fixes vertical lines.
forceEvenSpritePosition: 1 # Improves visual clarity whilst upscaling.
roundSprite: 1 # Reduces graphics garbage on UI whilst upscaling.
SLPM-60207:
name: "ロックマンX7 [体験版]"
name-sort: "ろっくまんえっくす7 [たいけんばん]"
@@ -35722,12 +35718,10 @@ SLPM-60220:
name-en: "Hajime no Ippo II - Victorious Road [Trial]"
region: "NTSC-J"
SLPM-60225:
name: "風雲 新撰組 [体験版]"
name: "風雲新撰組 [体験版]"
name-sort: "ふううん しんせんぐみ [たいけんばん]"
name-en: "Fu-un Shinsen-gumi [Trial]"
name-en: "Fuuun Shinsengumi [Trial]"
region: "NTSC-J"
gsHWFixes:
halfPixelOffset: 5 # Fixes vertical lines.
SLPM-60226:
name: "シャドウハーツⅡ [体験版]"
name-sort: "しゃどうはーつ2 [たいけんばん]"
@@ -35743,7 +35737,9 @@ SLPM-60228:
name-en: "Kaidō Battle 2 - Chain Reaction [Trial]"
region: "NTSC-J"
gsHWFixes:
halfPixelOffset: 5 # Fixes vertical lines.
halfPixelOffset: 2 # Fixes ghosting during Rain/Storm.
alignSprite: 1 # Fixes vertical lines.
forceEvenSpritePosition: 1 # De-blurs the 3D image.
SLPM-60237:
name: "電車でGOFINAL [体験版]"
name-sort: "でんしゃでごーFINAL [たいけんばん]"
@@ -36493,12 +36489,10 @@ SLPM-61095:
name-en: "Dengeki PS2 / DengekiPlayStation D74"
region: "NTSC-J"
SLPM-61096:
name: "風雲 幕末伝 [体験版]"
name: "風雲幕末伝 [体験版]"
name-sort: "ふううんばくまつでん [たいけんばん]"
name-en: "Fu-un Bakumatsu-den [Trial]"
name-en: "Fuuun Bakumatsu-den [Trial]"
region: "NTSC-J"
gsHWFixes:
halfPixelOffset: 5 # Fixes vertical lines.
SLPM-61097:
name: "電撃PS2 / 電撃PlayStation D75"
name-sort: "でんげき PS2 でんげきPlayStation D75"
@@ -36607,7 +36601,8 @@ SLPM-61115:
name-en: "Racing Battle - C1 Grand Prix [Trial]"
region: "NTSC-J"
gsHWFixes:
halfPixelOffset: 5 # Fixes vertical lines.
alignSprite: 1 # Fixes vertical lines.
forceEvenSpritePosition: 1 # De-blurs the 3D image.
SLPM-61116:
name: "冒険王ビィト ダークネスセンチュリー [体験版]"
name-sort: "ぼうけんおうびぃと だーくねすせんちゅりー [たいけんばん]"
@@ -36654,7 +36649,9 @@ SLPM-61121:
name-en: "Kaido Touge no Densetsu [Trial]"
region: "NTSC-J"
gsHWFixes:
halfPixelOffset: 5 # Fixes vertical lines.
halfPixelOffset: 2 # Fixes ghosting during Rain/Storm.
alignSprite: 1 # Fixes vertical lines.
forceEvenSpritePosition: 1 # De-blurs the 3D image.
SLPM-61122:
name: "電撃PS2 / 電撃PlayStation D81"
name-sort: "でんげき PS2 でんげきPlayStation D81"
@@ -42498,7 +42495,9 @@ SLPM-65246:
name-en: "Kaidō Battle - Nikko, Haruna, Rokko, Hakone"
region: "NTSC-J"
gsHWFixes:
halfPixelOffset: 5 # Fixes vertical lines.
halfPixelOffset: 2 # Fixes ghosting during Rain.
alignSprite: 1 # Fixes vertical lines.
forceEvenSpritePosition: 1 # De-blurs the 3D image.
SLPM-65247:
name: "三國志戦記2"
name-sort: "さんごくしせんき2"
@@ -42873,7 +42872,9 @@ SLPM-65308:
region: "NTSC-J"
compat: 5
gsHWFixes:
halfPixelOffset: 5 # Fixes vertical lines.
alignSprite: 1 # Fixes vertical lines.
forceEvenSpritePosition: 1 # Improves visual clarity whilst upscaling.
roundSprite: 1 # Reduces graphics garbage on UI whilst upscaling.
SLPM-65309:
name: "Splashdown [PlayStation2 the Best]"
name-sort: "すぷらっしゅだうん [PlayStation2 the Best]"
@@ -43906,12 +43907,10 @@ SLPM-65493:
name-en: "Hurrah! Sailor [Limited Edition]"
region: "NTSC-J"
SLPM-65494:
name: "風雲 新撰組"
name: "風雲 新撰組"
name-sort: "ふううん しんせんぐみ"
name-en: "Fu-un Shinsen-gumi"
name-en: "Fuuun Shinsengumi"
region: "NTSC-J"
gsHWFixes:
halfPixelOffset: 5 # Fixes vertical lines.
SLPM-65495:
name: "モンスターハンター"
name-sort: "もんすたーはんたー"
@@ -44049,7 +44048,9 @@ SLPM-65514:
name-en: "Kaidō Battle 2 - Chain Reaction"
region: "NTSC-J"
gsHWFixes:
halfPixelOffset: 5 # Fixes vertical lines.
halfPixelOffset: 2 # Fixes ghosting during Rain/Storm.
alignSprite: 1 # Fixes vertical lines.
forceEvenSpritePosition: 1 # De-blurs the 3D image.
SLPM-65515:
name: "サクラ大戦物語 ~ミステリアス巴里~"
name-sort: "さくらたいせんものがたり ~みすてりあすぱり~"
@@ -45778,13 +45779,11 @@ SLPM-65812:
name-en: "Bakushou! Jinsei Kaidou - NOVA Usagi ga Miteruzo! [TAITO BEST]"
region: "NTSC-J"
SLPM-65813:
name: "風雲 幕末伝"
name: "風雲幕末伝"
name-sort: "ふううん ばくまつでん"
name-en: "Fu-un Bakumatsu-den"
name-en: "Fu-un Bakumatsu Den"
region: "NTSC-J"
compat: 5
gsHWFixes:
halfPixelOffset: 5 # Fixes vertical lines.
SLPM-65815:
name: "トム・クランシーシリーズ スプリンターセル パンドラトゥモロー"
name-sort: "とむくらんしーしりーず すぷりんたーせる ぱんどらとぅもろー"
@@ -46250,7 +46249,8 @@ SLPM-65897:
name-en: "Racing Battle - C1 Grand Prix"
region: "NTSC-J"
gsHWFixes:
halfPixelOffset: 5 # Fixes vertical lines.
alignSprite: 1 # Fixes vertical lines.
forceEvenSpritePosition: 1 # De-blurs the 3D image.
SLPM-65898:
name: "キャッスルファンタジア エレンシア戦記 DXパック"
name-sort: "きゃっするふぁんたじあ えれんしあせんき DXぱっく"
@@ -47001,7 +47001,9 @@ SLPM-66022:
name-en: "Kaido - Touge no Densetsu"
region: "NTSC-J"
gsHWFixes:
halfPixelOffset: 5 # Fixes vertical lines.
halfPixelOffset: 2 # Fixes ghosting during Rain/Storm.
alignSprite: 1 # Fixes vertical lines.
forceEvenSpritePosition: 1 # De-blurs the 3D image.
SLPM-66023:
name: "ふしぎ遊戯 玄武開伝 外伝 鏡の巫女 [限定版]"
name-sort: "ふしぎゆうぎ げんぶかいでん がいでん かがみのみこ [げんていばん]"
@@ -53750,12 +53752,10 @@ SLPM-74201:
- "SLPM-65286"
- "BWNETCNF"
SLPM-74202:
name: "風雲 新撰組 [PlayStation2 the Best]"
name: "風雲 新撰組 [PlayStation2 the Best]"
name-sort: "ふううん しんせんぐみ [PlayStation2 the Best]"
name-en: "Fu-un Shinsen-gumi [PlayStation2 the Best]"
name-en: "Fuuun Shinsengumi [PlayStation2 the Best]"
region: "NTSC-J"
gsHWFixes:
halfPixelOffset: 5 # Fixes vertical lines.
SLPM-74204:
name: "首都高バトル01 [PlayStation2 the Best]"
name-sort: "しゅとこうばとる01 [PlayStation2 the Best]"
@@ -53763,7 +53763,9 @@ SLPM-74204:
region: "NTSC-J"
compat: 5
gsHWFixes:
halfPixelOffset: 5 # Fixes vertical lines.
alignSprite: 1 # Fixes vertical lines.
forceEvenSpritePosition: 1 # Improves visual clarity whilst upscaling.
roundSprite: 1 # Reduces graphics garbage on UI whilst upscaling.
SLPM-74205:
name: "真・女神転生Ⅲ - NOCTURNE [PlayStation2 the Best]"
name-sort: "しんめがみてんせい3 - NOCTURNE [PlayStation2 the Best]"
@@ -53902,12 +53904,10 @@ SLPM-74227:
halfPixelOffset: 4 # Fixes misaligned lighting and bloom.
bilinearUpscale: 1 # Smooths out bloom.
SLPM-74228:
name: "風雲 幕末伝 [PlayStation2 the Best]"
name: "風雲幕末伝 [PlayStation2 the Best]"
name-sort: "ふううんばくまつでん [PlayStation2 the Best]"
name-en: "Fu-un Bakumatsu-den [PlayStation2 the Best]"
name-en: "Fuuun Bakumatsu-den [PlayStation2 the Best]"
region: "NTSC-J"
gsHWFixes:
halfPixelOffset: 5 # Fixes vertical lines.
SLPM-74229:
name: "バイオハザード4 [PlayStation2 the Best]"
name-sort: "ばいおはざーど4 [PlayStation2 the Best]"
@@ -63488,12 +63488,10 @@ SLPS-73227:
name-en: "Another Century's Episode [PlayStation2 the Best]"
region: "NTSC-J"
SLPS-73228:
name: "風雲 幕末伝 [PlayStation2 the Best]"
name: "風雲幕末伝 [PlayStation2 the Best]"
name-sort: "ふううんばくまつでん [PlayStation2 the Best]"
name-en: "Fu-un Bakumatsu-den [PlayStation2 the Best]"
name-en: "Fuuun Bakumatsu-den [PlayStation2 the Best]"
region: "NTSC-J"
gsHWFixes:
halfPixelOffset: 5 # Fixes vertical lines.
SLPS-73229:
name: "ベルウィックサーガ [PlayStation2 the Best]"
name-sort: "べるうぃっくさーが [PlayStation2 the Best]"
@@ -68133,7 +68131,9 @@ SLUS-20831:
region: "NTSC-U"
compat: 5
gsHWFixes:
halfPixelOffset: 5 # Fixes vertical lines.
alignSprite: 1 # Fixes vertical lines.
forceEvenSpritePosition: 1 # Improves visual clarity whilst upscaling.
roundSprite: 1 # Reduces graphics garbage on UI whilst upscaling.
SLUS-20833:
name: "Mega Man Anniversary Collection"
region: "NTSC-U"
@@ -70602,7 +70602,9 @@ SLUS-21236:
region: "NTSC-U"
compat: 5
gsHWFixes:
halfPixelOffset: 5 # Fixes vertical lines.
halfPixelOffset: 2 # Fixes ghosting during Rain.
alignSprite: 1 # Fixes vertical lines.
forceEvenSpritePosition: 1 # Fixes double image.
SLUS-21237:
name: "AND 1 Streetball"
region: "NTSC-U"
@@ -71784,7 +71786,9 @@ SLUS-21394:
region: "NTSC-U"
compat: 5
gsHWFixes:
halfPixelOffset: 5 # Fixes vertical lines.
halfPixelOffset: 2 # Fixes ghosting during Rain/Storm.
alignSprite: 1 # Fixes vertical lines.
forceEvenSpritePosition: 1 # De-blurs the 3D image.
SLUS-21395:
name: "Avatar - The Last Airbender"
region: "NTSC-U"
+20 -24
View File
@@ -236,9 +236,8 @@
03000000ac0500005b05000000000000,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:Windows,
03000000ac0500002d02000000000000,GameSir G4,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,
03000000ac0500004d04000000000000,GameSir G4,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:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000373500002210000000000000,GameSir G7 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:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000373500002210000000000000,GameSir G7 Pro,a:b0,b:b1,x:b3,y:b4,back:b10,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,lefty:a2,rightx:a3,righty:a4,lefttrigger:b8,righttrigger:b9,platform:Window,
03000000ac0500001a06000000000000,GameSir T3 2.02,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,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,
03000000373500000410000000000000,GameSir T4 Kaleid,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000373500009410000000000000,GameSir Tegenaria Lite,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,
030000004c0e00001035000000000000,Gamester,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
030000000d0f00001110000000000000,GameStick Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
@@ -247,6 +246,8 @@
03000000b62500000100000000000000,Gametel GT004 01,a:b3,b:b0,dpdown:b10,dpleft:b9,dpright:b8,dpup:b11,leftshoulder:b4,rightshoulder:b5,start:b7,x:b1,y:b2,platform:Windows,
030000008f0e00001411000000000000,Gamo2 Divaller,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:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000120c0000a857000000000000,Gator Claw,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,
03000000c21100000791000000000000,Nacon GC101 1.03,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,
03000000c9110000f055000000000000,Nacon GC100XF,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,
030000008305000009a0000000000000,Genius,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,
030000008305000031b0000000000000,Genius Maxfire Blaze 3,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,
03000000451300000010000000000000,Genius Maxfire Grandias 12,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,
@@ -366,7 +367,7 @@
03000000fd0500002a26000000000000,InterAct Hammerhead FX,a:b3,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b0,y:b1,platform:Windows,
03000000fd0500002f26000000000000,InterAct Hammerhead FX,a:b4,b:b5,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b1,y:b2,platform:Windows,
03000000fd0500005302000000000000,InterAct ProPad,a:b3,b:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,x:b0,y:b1,platform:Windows,
03000000ac0500002c02000000000000,Ipega Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b8,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000ac0500002c02000000000000,Ipega Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000491900000204000000000000,Ipega PG9023,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:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000491900000304000000000000,Ipega PG9087,+righty:+a5,-righty:-a4,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:a3,start:b11,x:b3,y:b4,platform:Windows,
030000007e0500000620000000000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Windows,
@@ -463,8 +464,6 @@
03000000250900006688000000000000,MP-8866 Super Dual Box,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,
03000000091200004488000000000000,MUSIA PlayStation 2 Input Display,a:b0,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b6,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b7,righttrigger:b11,rightx:a2,righty:a3,start:b5,x:b1,y:b3,platform:Windows,
03000000f70600000100000000000000,N64 Adaptoid,+rightx:b2,+righty:b1,-rightx:b4,-righty:b5,a:b0,b:b3,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,platform:Windows,
03000000c9110000f055000000000000,Nacon GC100XF,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,
03000000c21100000791000000000000,Nacon GC101 1.03,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,
030000006b140000010c000000000000,Nacon GC400ES,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:Windows,
030000006b1400001106000000000000,Nacon Revolution 3 PS4 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,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
0300000085320000170d000000000000,Nacon Revolution 5 Pro,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:Windows,
@@ -698,7 +697,7 @@
03000000730700000601000000000000,Sega Saturn Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows,
03000000b40400000a01000000000000,Sega Saturn Controller,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:Windows,
030000003b07000004a1000000000000,SFX,a:b0,b:b2,back:b7,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b5,start:b8,x:b1,y:b3,platform:Windows,
03000000632500002705000000000000,ShanWan Q36,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,righttrigger:b9,start:b11,x:b3,y:b4,platform:Windows,
03000000632500002705000000000000,ShanWan Q36,a:b0,b:b1,x:b3,y:b4,leftshoulder:b6,rightshoulder:b7,lefttrigger:b8,righttrigger:b9,back:b10,start:b11,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,platform:Windows,
03000000f82100001900000000000000,Shogun Bros Chameleon X1,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
03000000120c00001c1e000000000000,SnakeByte 4S PS4 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:Windows,
03000000140300000918000000000000,SNES Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows,
@@ -889,7 +888,6 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000c82d00000851000000010000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
03000000c82d00000660000000010000,8BitDo Pro 2,a:b1,b:b0,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:b4,y:b3,platform:Mac OS X,
03000000c82d00000660000000020000,8BitDo Pro 2,a:b1,b:b0,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:b4,y:b3,platform:Mac OS X,
03000000c82d00000960000000000000,8BitDo Pro 3,a:b1,b:b0,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,paddle1:b17,paddle2:b16,paddle3:b2,paddle4:b5,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000c82d00000131000001000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000c82d00000231000001000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000c82d00000331000001000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
@@ -1176,7 +1174,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000c82d00000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
05000000c82d00001038000000010000,8BitDo FC30 Pro,a:b1,b:b0,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:b4,y:b3,platform:Linux,
05000000c82d00006a28000000010000,8BitDo GameCube,a:b0,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b9,paddle2:b8,rightshoulder:b10,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b1,y:b4,platform:Linux,
03000000c82d00001251000011010000,8BitDo Lite 2,a:b1,b:b0,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:b4,y:b3,platform:Linux,
03000000c82d00001251000011010000,8BitDo Lite 2,a:b1,b:b0,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:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
05000000c82d00001251000000010000,8BitDo Lite 2,a:b1,b:b0,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:b4,y:b3,platform:Linux,
03000000c82d00001151000011010000,8BitDo Lite SE,a:b1,b:b0,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:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
05000000c82d00001151000000010000,8BitDo Lite SE,a:b1,b:b0,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:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
@@ -1354,7 +1352,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000280400000140000000010000,Gravis GamePad Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
030000008f0e00000610000000010000,GreenAsia Electronics Controller,a:b2,b:b1,back:b8,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:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Linux,
030000008f0e00001200000010010000,GreenAsia Joystick,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:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
0500000047532067616d657061640000,GS Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,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,
0500000047532067616d657061640000,GS gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,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,
03000000f0250000c383000010010000,GT VX2,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,
030000008a2e0000dd10000011010000,Hand Held Legend GC Ultimate,a:b0,b:b2,back:b17,dpdown:b5,dpleft:b6,dpright:b7,dpup:b4,guide:b18,leftshoulder:b10,leftstick:b8,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b19,misc2:b24,paddle1:b13,paddle2:b12,rightshoulder:b11,rightstick:b9,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b1,y:b3,platform:Linux,
030000008a2e0000df10000011010000,Hand Held Legend ProGCC,a:b1,b:b0,back:b17,dpdown:b5,dpleft:b6,dpright:b7,dpup:b4,guide:b18,leftshoulder:b10,leftstick:b8,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b19,paddle1:b13,paddle2:b12,rightshoulder:b11,rightstick:b9,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b3,y:b2,platform:Linux,
@@ -1399,12 +1397,11 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000242e00006a38000010010000,Hyperkin Trooper 2,a:b0,b:b1,back:b4,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b3,start:b5,platform:Linux,
03000000242e00008816000001010000,Hyperkin X91,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,
03000000f00300008d03000011010000,HyperX Clutch,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,
05000000f00300008d04000000010000,HyperX Clutch,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,
03000000830500006020000010010000,iBuffalo Super Famicom Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux,
03000000d80400004aea000011010000,icedragon.io STAC Dance Pad,a:b0,b:b1,back:b4,x:b2,y:b3,platform:Linux,
03000000d80400004bea000011010000,icedragon.io STAC Dance Pad,a:b0,b:b1,back:b4,x:b2,y:b3,platform:Linux,
030000008a2e0000d910000011010000,icedragon.io STAC2 Dance Pad,a:b0,b:b1,back:b4,x:b2,y:b3,platform:Linux,
030000008a2e0000e910000011010000,icedragon.io STAC2 Dance Pad,a:b8,b:b9,back:b12,x:b10,y:b11,platform:Linux,
03000000d80400004bea000011010000,icedragon.io STAC Dance Pad,a:b0,b:b1,x:b2,y:b3,back:b4,platform:Linux,
03000000d80400004aea000011010000,icedragon.io STAC Dance Pad,a:b0,b:b1,x:b2,y:b3,back:b4,platform:Linux,
030000008a2e0000d910000011010000,icedragon.io STAC2 Dance Pad,a:b0,b:b1,x:b2,y:b3,back:b4,platform:Linux,
030000008a2e0000e910000011010000,icedragon.io STAC2 Dance Pad,a:b8,b:b9,x:b10,y:b11,back:b12,platform:Linux,
030000008f0e00001330000001010000,iCode Retro Adapter,b:b3,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b9,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b1,start:b7,x:b2,y:b0,platform:Linux,
050000006964726f69643a636f6e0000,idroidcon Controller,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:a3,start:b9,x:b0,y:b3,platform:Linux,
03000000b50700001503000010010000,Impact,a:b2,b:b3,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:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,
@@ -1490,7 +1487,6 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000005e040000ea02000008040000,Microsoft Xbox One,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,
030000005e040000ea0200000f050000,Microsoft Xbox One,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,
060000005e040000120b000009050000,Microsoft Xbox One,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,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
060000005e040000120b000014050000,Microsoft Xbox One,a:b0,b:b1,x:b2,y:b3,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux
030000005e040000e302000003020000,Microsoft Xbox One Elite,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,
030000005e040000000b000007040000,Microsoft Xbox One Elite 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,paddle1:b12,paddle2:b14,paddle3:b13,paddle4:b15,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000005e040000000b000008040000,Microsoft Xbox One Elite 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,paddle1:b12,paddle2:b14,paddle3:b13,paddle4:b15,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
@@ -1508,6 +1504,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
05000000d6200000e589000001000000,Moga 2,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:b6,x:b2,y:b3,platform:Linux,
05000000d6200000ad0d000001000000,Moga Pro,a:b0,b:b1,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:b6,x:b2,y:b3,platform:Linux,
05000000d62000007162000001000000,Moga Pro 2,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:b6,x:b2,y:b3,platform:Linux,
03000000c82d00000960000000000000,8BitDo Pro 3,a:b1,b:b0,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,paddle1:b17,paddle2:b16,paddle3:b2,paddle4:b5,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000c62400002b89000011010000,MOGA XP5A Plus,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,
05000000c62400002a89000000010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b22,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,
05000000c62400001a89000000010000,MOGA XP5X Plus,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,
@@ -1515,9 +1512,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000005e0400008e02000010020000,MSI GC20 V2,a:b0,b:b1,back:b6,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,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,
03000000f70600000100000000010000,N64 Adaptoid,+rightx:b2,+righty:b1,-rightx:b4,-righty:b5,a:b0,b:b3,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,platform:Linux,
030000006b1400000906000014010000,Nacon Asymmetric Wireless PS4 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,
030000006b140000010c000010010000,Nacon GC400ES,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:Linux,
0300000085320000030c000011010000,Nacon GC100,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,
03000000853200000706000012010000,Nacon GC100,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,
030000006b140000010c000010010000,Nacon GC400ES,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:Linux,
05000000853200000503000000010000,Nacon MGX Pro,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,
0300000085320000170d000011010000,Nacon Revolution 5 Pro,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,
0300000085320000190d000011010000,Nacon Revolution 5 Pro,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,
@@ -1791,10 +1788,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
06000000f51000000870000003010000,Turtle Beach Recon,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,
03000000100800000100000010010000,Twin PS2 Adapter,a:b2,b:b1,back:b8,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:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,
03000000c0160000e105000010010000,Ultimate Atari Fight Stick,a:b1,b:b2,back:b9,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b4,righttrigger:b5,start:b8,x:b0,y:b3,platform:Linux,
03000000790000002601000011010000,SNES Controller,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:-a1,dpdown:+a1,dpleft:-a0,dpright:+a0,platform:Linux,
03000000151900005678000010010000,Uniplay U6,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,
03000000100800000300000010010000,USB Gamepad,a:b2,b:b1,back:b8,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:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,
03000000790000000600000007010000,USB 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:a3,righty:a4,start:b9,x:b3,y:b0,platform:Linux,
03000000790000000600000007010000,USB 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:a3,righty:a4,start:b9,x:b3,y:b0,platform:Linux,
03000000790000001100000000010000,USB Gamepad,a:b2,b:b1,back:b8,dpdown:a0,dpleft:a1,dpright:a2,dpup:a4,start:b9,platform:Linux,
03000000790000001a18000011010000,Venom PS4 Arcade Joystick,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,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
03000000790000001b18000011010000,Venom PS4 Arcade Joystick,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:Linux,
@@ -1804,17 +1800,17 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
05000000434f4d4d414e440000000000,VX Gaming Command Series,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
0000000058626f782033363020576900,Xbox 360 Controller,a:b0,b:b1,back:b14,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b7,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Linux,
030000005e0400001907000000010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,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,
030000005e0400008e02000000010000,Xbox 360 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,
030000005e0400008e02000002010000,Xbox 360 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,
030000005e0400008e02000010010000,Xbox 360 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,
030000005e0400008e02000014010000,Xbox 360 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,
030000005e0400008e02000047010000,Xbox 360 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,
030000005e0400008e02000072050000,Xbox 360 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,
030000005e0400009102000007010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,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,
030000005e040000a102000000010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,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,
030000005e040000a102000007010000,Xbox 360 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,
030000005e040000a102000030060000,Xbox 360 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,
030000006f0e00001503000000020000,Xbox 360 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,
030000005e0400008e02000000010000,Xbox 360 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,
030000005e0400008e02000010010000,Xbox 360 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,
030000005e0400008e02000002010000,Xbox 360 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,
030000005e0400008e02000014010000,Xbox 360 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,
030000005e0400008e02000047010000,Xbox 360 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,
030000005e0400008e02000072050000,Xbox 360 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,
030000005e040000a102000014010000,Xbox 360 Receiver,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,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,
0000000058626f782047616d65706100,Xbox 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:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,
030000005e0400000202000000010000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,
+12 -12
View File
@@ -384,14 +384,14 @@ float4x4 sample_4p(uint4 u)
return c;
}
uint fetch_raw_depth(int2 xy)
int fetch_raw_depth(int2 xy)
{
#if PS_TEX_IS_FB == 1
float4 col = RtTexture.Load(int3(xy, 0));
#else
float4 col = Texture.Load(int3(xy, 0));
#endif
return (uint)(col.r * exp2(32.0f));
return (int)(col.r * exp2(32.0f));
}
float4 fetch_raw_color(int2 xy)
@@ -466,10 +466,10 @@ float4 sample_depth(float2 st, float2 pos)
if (PS_TALES_OF_ABYSS_HLE == 1)
{
// Warning: UV can't be used in channel effect
uint depth = fetch_raw_depth(pos);
int depth = fetch_raw_depth(pos);
// Convert msb based on the palette
t = Palette.Load(int3((depth >> 8u) & 0xFFu, 0, 0)) * 255.0f;
t = Palette.Load(int3((depth >> 8) & 0xFF, 0, 0)) * 255.0f;
}
else if (PS_URBAN_CHAOS_HLE == 1)
{
@@ -480,13 +480,13 @@ float4 sample_depth(float2 st, float2 pos)
// To be faster both steps (msb&lsb) are done in a single pass.
// Warning: UV can't be used in channel effect
uint depth = fetch_raw_depth(pos);
int depth = fetch_raw_depth(pos);
// Convert lsb based on the palette
t = Palette.Load(int3(depth & 0xFFu, 0, 0)) * 255.0f;
t = Palette.Load(int3(depth & 0xFF, 0, 0)) * 255.0f;
// Msb is easier
float green = (float)((depth >> 8u) & 0xFFu) * 36.0f;
float green = (float)((depth >> 8) & 0xFF) * 36.0f;
green = min(green, 255.0f);
t.g += green;
}
@@ -538,7 +538,7 @@ float4 fetch_red(int2 xy)
if ((PS_DEPTH_FMT == 1) || (PS_DEPTH_FMT == 2))
{
uint depth = (fetch_raw_depth(xy)) & 0xFFu;
int depth = (fetch_raw_depth(xy)) & 0xFF;
rt = (float4)(depth) / 255.0f;
}
else
@@ -555,7 +555,7 @@ float4 fetch_green(int2 xy)
if ((PS_DEPTH_FMT == 1) || (PS_DEPTH_FMT == 2))
{
uint depth = (fetch_raw_depth(xy) >> 8u) & 0xFFu;
int depth = (fetch_raw_depth(xy) >> 8) & 0xFF;
rt = (float4)(depth) / 255.0f;
}
else
@@ -572,7 +572,7 @@ float4 fetch_blue(int2 xy)
if ((PS_DEPTH_FMT == 1) || (PS_DEPTH_FMT == 2))
{
uint depth = (fetch_raw_depth(xy) >> 16u) & 0xFFu;
int depth = (fetch_raw_depth(xy) >> 16) & 0xFF;
rt = (float4)(depth) / 255.0f;
}
else
@@ -600,8 +600,8 @@ float4 fetch_gXbY(int2 xy)
{
if ((PS_DEPTH_FMT == 1) || (PS_DEPTH_FMT == 2))
{
uint depth = fetch_raw_depth(xy);
uint bg = (depth >> (8u + uint(ChannelShuffle.w))) & 0xFFu;
int depth = fetch_raw_depth(xy);
int bg = (depth >> (8 + ChannelShuffle.w)) & 0xFF;
return (float4)(bg);
}
else
+13 -13
View File
@@ -313,14 +313,14 @@ mat4 sample_4p(uvec4 u)
return c;
}
uint fetch_raw_depth()
int fetch_raw_depth()
{
float multiplier = exp2(32.0f);
#if PS_TEX_IS_FB == 1
return uint(sample_from_rt().r * multiplier);
return int(sample_from_rt().r * multiplier);
#else
return uint(texelFetch(TextureSampler, ivec2(gl_FragCoord.xy + ChannelShuffleOffset), 0).r * multiplier);
return int(texelFetch(TextureSampler, ivec2(gl_FragCoord.xy + ChannelShuffleOffset), 0).r * multiplier);
#endif
}
@@ -393,10 +393,10 @@ vec4 sample_depth(vec2 st)
#if PS_TALES_OF_ABYSS_HLE == 1
// Warning: UV can't be used in channel effect
uint depth = fetch_raw_depth();
int depth = fetch_raw_depth();
// Convert msb based on the palette
t = texelFetch(PaletteSampler, ivec2((depth >> 8u) & 0xFFu, 0), 0) * 255.0f;
t = texelFetch(PaletteSampler, ivec2((depth >> 8) & 0xFF, 0), 0) * 255.0f;
#elif PS_URBAN_CHAOS_HLE == 1
// Depth buffer is read as a RGB5A1 texture. The game try to extract the green channel.
@@ -406,13 +406,13 @@ vec4 sample_depth(vec2 st)
// To be faster both steps (msb&lsb) are done in a single pass.
// Warning: UV can't be used in channel effect
uint depth = fetch_raw_depth();
int depth = fetch_raw_depth();
// Convert lsb based on the palette
t = texelFetch(PaletteSampler, ivec2((depth & 0xFFu), 0), 0) * 255.0f;
t = texelFetch(PaletteSampler, ivec2((depth & 0xFF), 0), 0) * 255.0f;
// Msb is easier
float green = float((depth >> 8u) & 0xFFu) * 36.0f;
float green = float((depth >> 8) & 0xFF) * 36.0f;
green = min(green, 255.0f);
t.g += green;
@@ -454,7 +454,7 @@ vec4 sample_depth(vec2 st)
vec4 fetch_red()
{
#if PS_DEPTH_FMT == 1 || PS_DEPTH_FMT == 2
uint depth = (fetch_raw_depth()) & 0xFFu;
int depth = (fetch_raw_depth()) & 0xFF;
vec4 rt = vec4(depth) / 255.0f;
#else
vec4 rt = fetch_raw_color();
@@ -465,7 +465,7 @@ vec4 fetch_red()
vec4 fetch_green()
{
#if PS_DEPTH_FMT == 1 || PS_DEPTH_FMT == 2
uint depth = (fetch_raw_depth() >> 8u) & 0xFFu;
int depth = (fetch_raw_depth() >> 8) & 0xFF;
vec4 rt = vec4(depth) / 255.0f;
#else
vec4 rt = fetch_raw_color();
@@ -476,7 +476,7 @@ vec4 fetch_green()
vec4 fetch_blue()
{
#if PS_DEPTH_FMT == 1 || PS_DEPTH_FMT == 2
uint depth = (fetch_raw_depth() >> 16u) & 0xFFu;
int depth = (fetch_raw_depth() >> 16) & 0xFF;
vec4 rt = vec4(depth) / 255.0f;
#else
vec4 rt = fetch_raw_color();
@@ -500,8 +500,8 @@ vec4 fetch_rgb()
vec4 fetch_gXbY()
{
#if PS_DEPTH_FMT == 1 || PS_DEPTH_FMT == 2
uint depth = fetch_raw_depth();
uint bg = (depth >> (8u + uint(ChannelShuffle.w))) & 0xFFu;
int depth = fetch_raw_depth();
int bg = (depth >> (8 + ChannelShuffle.w)) & 0xFF;
return vec4(bg);
#else
ivec4 rt = ivec4(fetch_raw_color() * 255.0f);
+12 -12
View File
@@ -556,14 +556,14 @@ mat4 sample_4p(uvec4 u)
return c;
}
uint fetch_raw_depth(ivec2 xy)
int fetch_raw_depth(ivec2 xy)
{
#if PS_TEX_IS_FB
vec4 col = sample_from_rt();
#else
vec4 col = texelFetch(Texture, xy, 0);
#endif
return uint(col.r * exp2(32.0f));
return int(col.r * exp2(32.0f));
}
vec4 fetch_raw_color(ivec2 xy)
@@ -642,10 +642,10 @@ vec4 sample_depth(vec2 st, ivec2 pos)
#if (PS_TALES_OF_ABYSS_HLE == 1)
{
// Warning: UV can't be used in channel effect
uint depth = fetch_raw_depth(pos);
int depth = fetch_raw_depth(pos);
// Convert msb based on the palette
t = texelFetch(Palette, ivec2((depth >> 8u) & 0xFFu, 0), 0) * 255.0f;
t = texelFetch(Palette, ivec2((depth >> 8) & 0xFF, 0), 0) * 255.0f;
}
#elif (PS_URBAN_CHAOS_HLE == 1)
{
@@ -656,13 +656,13 @@ vec4 sample_depth(vec2 st, ivec2 pos)
// To be faster both steps (msb&lsb) are done in a single pass.
// Warning: UV can't be used in channel effect
uint depth = fetch_raw_depth(pos);
int depth = fetch_raw_depth(pos);
// Convert lsb based on the palette
t = texelFetch(Palette, ivec2(depth & 0xFFu, 0), 0) * 255.0f;
t = texelFetch(Palette, ivec2(depth & 0xFF, 0), 0) * 255.0f;
// Msb is easier
float green = float(((depth >> 8u) & 0xFFu) * 36.0f);
float green = float(((depth >> 8) & 0xFF) * 36.0f);
green = min(green, 255.0f);
t.g += green;
}
@@ -715,7 +715,7 @@ vec4 fetch_red(ivec2 xy)
vec4 rt;
#if (PS_DEPTH_FMT == 1) || (PS_DEPTH_FMT == 2)
uint depth = (fetch_raw_depth(xy)) & 0xFFu;
int depth = (fetch_raw_depth(xy)) & 0xFF;
rt = vec4(float(depth) / 255.0f);
#else
rt = fetch_raw_color(xy);
@@ -729,7 +729,7 @@ vec4 fetch_green(ivec2 xy)
vec4 rt;
#if (PS_DEPTH_FMT == 1) || (PS_DEPTH_FMT == 2)
uint depth = (fetch_raw_depth(xy) >> 8u) & 0xFFu;
int depth = (fetch_raw_depth(xy) >> 8) & 0xFF;
rt = vec4(float(depth) / 255.0f);
#else
rt = fetch_raw_color(xy);
@@ -743,7 +743,7 @@ vec4 fetch_blue(ivec2 xy)
vec4 rt;
#if (PS_DEPTH_FMT == 1) || (PS_DEPTH_FMT == 2)
uint depth = (fetch_raw_depth(xy) >> 16u) & 0xFFu;
int depth = (fetch_raw_depth(xy) >> 16) & 0xFF;
rt = vec4(float(depth) / 255.0f);
#else
rt = fetch_raw_color(xy);
@@ -768,8 +768,8 @@ vec4 fetch_rgb(ivec2 xy)
vec4 fetch_gXbY(ivec2 xy)
{
#if (PS_DEPTH_FMT == 1) || (PS_DEPTH_FMT == 2)
uint depth = fetch_raw_depth(xy);
uint bg = (depth >> (8u + uint(ChannelShuffle.w))) & 0xFFu;
int depth = fetch_raw_depth(xy);
int bg = (depth >> (8 + ChannelShuffle.w)) & 0xFF;
return vec4(bg);
#else
ivec4 rt = ivec4(fetch_raw_color(xy) * 255.0);
+1 -1
View File
@@ -108,7 +108,7 @@ disable_compiler_warnings_for_target(speex)
# Find the Qt components that we need.
if(ENABLE_QT_UI)
find_package(Qt6 6.10.1 COMPONENTS CoreTools Core GuiTools Gui WidgetsTools Widgets LinguistTools REQUIRED)
find_package(Qt6 6.10.0 COMPONENTS CoreTools Core GuiTools Gui WidgetsTools Widgets LinguistTools REQUIRED)
if(NOT WIN32 AND NOT APPLE)
if (Qt6_VERSION VERSION_GREATER_EQUAL 6.10.0)
+7 -5
View File
@@ -3,7 +3,6 @@
#pragma once
#include "HeterogeneousContainers.h"
#include <algorithm>
#include <cstdint>
#include <map>
@@ -76,9 +75,12 @@ public:
{
while (!m_items.empty() && count > 0)
{
auto lowest = std::min_element(m_items.begin(), m_items.end(), [](const auto& a, const auto& b) {
return a.second.last_access < b.second.last_access;
});
typename MapType::iterator lowest = m_items.end();
for (auto iter = m_items.begin(); iter != m_items.end(); ++iter)
{
if (lowest == m_items.end() || iter->second.last_access < lowest->second.last_access)
lowest = iter;
}
m_items.erase(lowest);
count--;
}
@@ -119,4 +121,4 @@ private:
CounterType m_last_counter = 0;
std::size_t m_max_capacity = 0;
bool m_manual_evict = false;
};
};
+2 -4
View File
@@ -436,8 +436,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|ds|fs|hw]: Enabling dumping of render target, texture, z buffer, frame, "
"alphas, and info (context, vertices, list of transfers), transfers images, draw stats, frame stats, HW config, respectively, per draw. Generates lots of data.\n");
std::fprintf(stderr, " -dump [rt|tex|z|f|a|i|tr|ds|fs]: Enabling dumping of render target, texture, z buffer, frame, "
"alphas, and info (context, vertices, list of transfers), transfers images, draw stats, frame stats, 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");
@@ -527,8 +527,6 @@ bool GSRunner::ParseCommandLineArgs(int argc, char* argv[], VMBootParameters& pa
s_settings_interface.SetBoolValue("EmuCore/GS", "SaveDrawStats", true);
if (str.find("fs") != std::string::npos)
s_settings_interface.SetBoolValue("EmuCore/GS", "SaveFrameStats", true);
if (str.find("hw") != std::string::npos)
s_settings_interface.SetBoolValue("EmuCore/GS", "SaveHWConfig", true);
continue;
}
else if (CHECK_ARG_PARAM("-dumprange"))
+1 -1
View File
@@ -144,7 +144,7 @@ void AboutDialog::showHTMLDialog(QWidget* parent, const QString& title, const QS
{
tb->setSource(QUrl::fromLocalFile(path));
}
layout->addWidget(tb, 1);
QDialogButtonBox* bb = new QDialogButtonBox(QDialogButtonBox::Close, &dialog);
-356
View File
@@ -1,356 +0,0 @@
// SPDX-FileCopyrightText: 2002-2026 PCSX2 Dev Team
// SPDX-License-Identifier: GPL-3.0+
#include "AsyncDialogs.h"
#include "common/Assertions.h"
#include <QtWidgets/QPushButton>
template <typename Value>
static std::function<void(std::optional<Value>)> wrapValueCallback(std::function<void(Value)> callback)
{
return [callback = std::move(callback)](std::optional<Value> input) {
if (input.has_value())
callback(std::move(*input));
};
}
void AsyncDialogs::getText(
QWidget* parent,
const QString& title,
const QString& label,
const QString& text,
std::function<void(QString)> value_callback)
{
getText(parent, title, label, QLineEdit::Normal, text, {}, Qt::ImhNone, wrapValueCallback(std::move(value_callback)));
}
void AsyncDialogs::getText(
QWidget* parent,
const QString& title,
const QString& label,
QLineEdit::EchoMode echo,
const QString& text,
Qt::WindowFlags flags,
Qt::InputMethodHints input_method_hints,
std::function<void(std::optional<QString>)> callback)
{
QInputDialog* dialog = new QInputDialog(parent, flags);
dialog->setWindowTitle(title);
dialog->setLabelText(label);
dialog->setTextValue(text);
dialog->setTextEchoMode(echo);
dialog->setInputMethodHints(input_method_hints);
dialog->setAttribute(Qt::WA_DeleteOnClose);
if (callback)
{
QObject::connect(dialog, &QDialog::finished, [dialog, callback = std::move(callback)](int result) {
callback(result ? std::make_optional<QString>(dialog->textValue()) : std::nullopt);
});
}
dialog->open();
}
void AsyncDialogs::getMultiLineText(
QWidget* parent,
const QString& title,
const QString& label,
const QString& text,
std::function<void(QString)> value_callback)
{
getMultiLineText(parent, title, label, text, {}, Qt::ImhNone, wrapValueCallback(std::move(value_callback)));
}
void AsyncDialogs::getMultiLineText(
QWidget* parent,
const QString& title,
const QString& label,
const QString& text,
Qt::WindowFlags flags,
Qt::InputMethodHints input_method_hints,
std::function<void(std::optional<QString>)> callback)
{
QInputDialog* dialog = new QInputDialog(parent, flags);
dialog->setOptions(QInputDialog::UsePlainTextEditForTextInput);
dialog->setWindowTitle(title);
dialog->setLabelText(label);
dialog->setTextValue(text);
dialog->setInputMethodHints(input_method_hints);
dialog->setAttribute(Qt::WA_DeleteOnClose);
if (callback)
{
QObject::connect(dialog, &QDialog::finished, [dialog, callback = std::move(callback)](int result) {
callback(result ? std::make_optional<QString>(dialog->textValue()) : std::nullopt);
});
}
dialog->open();
}
void AsyncDialogs::getItem(
QWidget* parent,
const QString& title,
const QString& label,
const QStringList& items,
int current,
std::function<void(QString)> value_callback)
{
getItem(parent, title, label, items, current, true, {}, Qt::ImhNone, wrapValueCallback(std::move(value_callback)));
}
void AsyncDialogs::getItem(
QWidget* parent,
const QString& title,
const QString& label,
const QStringList& items,
int current,
bool editable,
Qt::WindowFlags flags,
Qt::InputMethodHints input_method_hints,
std::function<void(std::optional<QString>)> callback)
{
const QString text(items.value(current));
QInputDialog* dialog = new QInputDialog(parent, flags);
dialog->setWindowTitle(title);
dialog->setLabelText(label);
dialog->setComboBoxItems(items);
dialog->setTextValue(text);
dialog->setComboBoxEditable(editable);
dialog->setInputMethodHints(input_method_hints);
dialog->setAttribute(Qt::WA_DeleteOnClose);
if (callback)
{
QObject::connect(dialog, &QDialog::finished, [dialog, callback = std::move(callback)](int result) {
callback(result ? std::make_optional<QString>(dialog->textValue()) : std::nullopt);
});
}
dialog->open();
}
void AsyncDialogs::getInt(
QWidget* parent,
const QString& title,
const QString& label,
int value,
std::function<void(int)> value_callback)
{
getInt(parent, title, label, value, -2147483647, 2147483647, 1, {}, wrapValueCallback(std::move(value_callback)));
}
void AsyncDialogs::getInt(
QWidget* parent,
const QString& title,
const QString& label,
int value,
int min_value,
int max_value,
int step,
Qt::WindowFlags flags,
std::function<void(std::optional<int>)> callback)
{
QInputDialog* dialog = new QInputDialog(parent, flags);
dialog->setWindowTitle(title);
dialog->setLabelText(label);
dialog->setIntRange(min_value, max_value);
dialog->setIntValue(value);
dialog->setIntStep(step);
dialog->setAttribute(Qt::WA_DeleteOnClose);
if (callback)
{
QObject::connect(dialog, &QDialog::finished, [dialog, callback = std::move(callback)](int result) {
callback(result ? std::make_optional<int>(dialog->intValue()) : std::nullopt);
});
}
dialog->open();
}
void AsyncDialogs::getDouble(
QWidget* parent,
const QString& title,
const QString& label,
double value,
std::function<void(double)> callback)
{
getDouble(parent, title, label, value, -2147483647, 2147483647, 1, {}, 1, wrapValueCallback(std::move(callback)));
}
void AsyncDialogs::getDouble(
QWidget* parent,
const QString& title,
const QString& label,
double value,
double min_value,
double max_value,
int decimals,
Qt::WindowFlags flags,
double step,
std::function<void(std::optional<double>)> callback)
{
QInputDialog* dialog = new QInputDialog(parent, flags);
dialog->setWindowTitle(title);
dialog->setLabelText(label);
dialog->setDoubleDecimals(decimals);
dialog->setDoubleRange(min_value, max_value);
dialog->setDoubleValue(value);
dialog->setDoubleStep(step);
dialog->setAttribute(Qt::WA_DeleteOnClose);
if (callback)
{
QObject::connect(dialog, &QDialog::finished, [dialog, callback = std::move(callback)](int result) {
callback(result ? std::make_optional<double>(dialog->doubleValue()) : std::nullopt);
});
}
dialog->open();
}
// Based on the QMessageBoxPrivate::showNewMessageBox function from Qt Widgets.
static void openAsyncMessageBox(QWidget* parent,
QMessageBox::Icon icon,
const QString& title,
const QString& text,
QMessageBox::StandardButtons buttons,
QMessageBox::StandardButton default_button,
std::function<void(QMessageBox::StandardButton)> callback)
{
// Don't support the fallback for Qt 4.
pxAssert(!(default_button && !(buttons & default_button)));
QMessageBox* message_box = new QMessageBox(icon, title, text, QMessageBox::NoButton, parent);
message_box->setAttribute(Qt::WA_DeleteOnClose);
const QDialogButtonBox* button_box = message_box->findChild<QDialogButtonBox*>();
pxAssert(button_box);
u32 mask = QMessageBox::FirstButton;
while (mask <= QMessageBox::LastButton)
{
QMessageBox::StandardButton standard_button =
static_cast<QMessageBox::StandardButton>(static_cast<u32>(buttons) & mask);
mask <<= 1;
if (standard_button == QMessageBox::NoButton)
continue;
QPushButton* button = message_box->addButton(standard_button);
if (message_box->defaultButton())
continue;
if ((default_button == QMessageBox::NoButton &&
button_box->buttonRole(button) == QDialogButtonBox::AcceptRole) ||
(default_button != QMessageBox::NoButton &&
standard_button == default_button))
message_box->setDefaultButton(button);
}
if (callback)
{
QObject::connect(message_box, &QMessageBox::finished, [message_box, callback = std::move(callback)](int result) {
callback(message_box->standardButton(message_box->clickedButton()));
});
}
message_box->open();
}
void AsyncDialogs::information(
QWidget* parent,
const QString& title,
const QString& text,
std::function<void(QMessageBox::StandardButton)> callback)
{
information(parent, title, text, QMessageBox::Ok, QMessageBox::NoButton, std::move(callback));
}
void AsyncDialogs::information(
QWidget* parent,
const QString& title,
const QString& text,
QMessageBox::StandardButtons buttons,
QMessageBox::StandardButton default_button,
std::function<void(QMessageBox::StandardButton)> callback)
{
openAsyncMessageBox(parent, QMessageBox::Information, title, text, buttons, default_button, std::move(callback));
}
void AsyncDialogs::question(
QWidget* parent,
const QString& title,
const QString& text,
std::function<void()> yes_callback)
{
std::function<void(QMessageBox::StandardButton)> callback;
if (yes_callback)
{
callback = [yes_callback = std::move(yes_callback)](QMessageBox::StandardButton result) {
if (result == QMessageBox::Yes)
yes_callback();
};
}
const QMessageBox::StandardButtons buttons(QMessageBox::Yes | QMessageBox::No);
question(parent, title, text, buttons, QMessageBox::NoButton, std::move(callback));
}
void AsyncDialogs::question(
QWidget* parent,
const QString& title,
const QString& text,
QMessageBox::StandardButtons buttons,
QMessageBox::StandardButton default_button,
std::function<void(QMessageBox::StandardButton)> callback)
{
openAsyncMessageBox(parent, QMessageBox::Question, title, text, buttons, default_button, std::move(callback));
}
void AsyncDialogs::warning(
QWidget* parent,
const QString& title,
const QString& text,
std::function<void(QMessageBox::StandardButton)> callback)
{
warning(parent, title, text, QMessageBox::Ok, QMessageBox::NoButton, std::move(callback));
}
void AsyncDialogs::warning(
QWidget* parent,
const QString& title,
const QString& text,
QMessageBox::StandardButtons buttons,
QMessageBox::StandardButton default_button,
std::function<void(QMessageBox::StandardButton)> callback)
{
openAsyncMessageBox(parent, QMessageBox::Warning, title, text, buttons, default_button, std::move(callback));
}
void AsyncDialogs::critical(
QWidget* parent,
const QString& title,
const QString& text,
std::function<void(QMessageBox::StandardButton)> callback)
{
critical(parent, title, text, QMessageBox::Ok, QMessageBox::NoButton, std::move(callback));
}
void AsyncDialogs::critical(
QWidget* parent,
const QString& title,
const QString& text,
QMessageBox::StandardButtons buttons,
QMessageBox::StandardButton default_button,
std::function<void(QMessageBox::StandardButton)> callback)
{
openAsyncMessageBox(parent, QMessageBox::Critical, title, text, buttons, default_button, std::move(callback));
}
-178
View File
@@ -1,178 +0,0 @@
// SPDX-FileCopyrightText: 2002-2026 PCSX2 Dev Team
// SPDX-License-Identifier: GPL-3.0+
#pragma once
#include <QtWidgets/QInputDialog>
#include <QtWidgets/QMessageBox>
#include <functional>
/// A collection of helper functions for opening asynchronous dialog boxes.
/// These should be used in place of Qt's built-in blocking functions as those
/// are prone to crashing if the parent is destroyed while the dialog is open.
namespace AsyncDialogs
{
/// Replacement for QInputDialog::getText.
void getText(
QWidget* parent,
const QString& title,
const QString& label,
const QString& text,
std::function<void(QString)> value_callback);
/// Replacement for QInputDialog::getText.
void getText(
QWidget* parent,
const QString& title,
const QString& label,
QLineEdit::EchoMode echo,
const QString& text,
Qt::WindowFlags flags,
Qt::InputMethodHints input_method_hints,
std::function<void(std::optional<QString>)> callback);
/// Replacement for QInputDialog::getMultiLineText.
void getMultiLineText(
QWidget* parent,
const QString& title,
const QString& label,
const QString& text,
std::function<void(QString)> value_callback);
/// Replacement for QInputDialog::getMultiLineText.
void getMultiLineText(
QWidget* parent,
const QString& title,
const QString& label,
const QString& text,
Qt::WindowFlags flags,
Qt::InputMethodHints input_method_hints,
std::function<void(std::optional<QString>)> callback);
/// Replacement for QInputDialog::getItem.
void getItem(
QWidget* parent,
const QString& title,
const QString& label,
const QStringList& items,
int current,
std::function<void(QString)> value_callback);
/// Replacement for QInputDialog::getItem.
void getItem(
QWidget* parent,
const QString& title,
const QString& label,
const QStringList& items,
int current,
bool editable,
Qt::WindowFlags flags,
Qt::InputMethodHints input_method_hints,
std::function<void(std::optional<QString>)> callback);
/// Replacement for QInputDialog::getInt.
void getInt(
QWidget* parent,
const QString& title,
const QString& label,
int value,
std::function<void(int)> value_callback);
/// Replacement for QInputDialog::getInt.
void getInt(
QWidget* parent,
const QString& title,
const QString& label,
int value,
int min_value,
int max_value,
int step,
Qt::WindowFlags flags,
std::function<void(std::optional<int>)> callback);
/// Replacement for QInputDialog::getDouble.
void getDouble(
QWidget* parent,
const QString& title,
const QString& label,
double value,
std::function<void(double)> value_callback);
/// Replacement for QInputDialog::getDouble.
void getDouble(
QWidget* parent,
const QString& title,
const QString& label,
double value,
double min_value,
double max_value,
int decimals,
Qt::WindowFlags flags,
double step,
std::function<void(std::optional<double>)> callback);
/// Replacement for QMessageBox::information.
void information(
QWidget* parent,
const QString& title,
const QString& text,
std::function<void(QMessageBox::StandardButton)> callback = {});
/// Replacement for QMessageBox::information.
void information(
QWidget* parent,
const QString& title,
const QString& text,
QMessageBox::StandardButtons buttons,
QMessageBox::StandardButton default_button,
std::function<void(QMessageBox::StandardButton)> callback = {});
/// Replacement for QMessageBox::question.
void question(
QWidget* parent,
const QString& title,
const QString& text,
std::function<void()> yes_callback);
/// Replacement for QMessageBox::question.
void question(
QWidget* parent,
const QString& title,
const QString& text,
QMessageBox::StandardButtons buttons,
QMessageBox::StandardButton default_button,
std::function<void(QMessageBox::StandardButton)> callback);
/// Replacement for QMessageBox::warning.
void warning(
QWidget* parent,
const QString& title,
const QString& text,
std::function<void(QMessageBox::StandardButton)> callback = {});
/// Replacement for QMessageBox::warning.
void warning(
QWidget* parent,
const QString& title,
const QString& text,
QMessageBox::StandardButtons buttons,
QMessageBox::StandardButton default_button,
std::function<void(QMessageBox::StandardButton)> callback = {});
/// Replacement for QMessageBox::critical.
void critical(
QWidget* parent,
const QString& title,
const QString& text,
std::function<void(QMessageBox::StandardButton)> callback = {});
/// Replacement for QMessageBox::critical.
void critical(
QWidget* parent,
const QString& title,
const QString& text,
QMessageBox::StandardButtons buttons,
QMessageBox::StandardButton default_button,
std::function<void(QMessageBox::StandardButton)> callback = {});
} // namespace AsyncDialogs
-3
View File
@@ -10,8 +10,6 @@ target_sources(pcsx2-qt PRIVATE
AboutDialog.cpp
AboutDialog.h
AboutDialog.ui
AsyncDialogs.cpp
AsyncDialogs.h
AutoUpdaterDialog.cpp
AutoUpdaterDialog.h
AutoUpdaterDialog.ui
@@ -326,7 +324,6 @@ elseif(APPLE)
set_source_files_properties(${QM_FILE} PROPERTIES MACOSX_PACKAGE_LOCATION Resources/translations/)
endforeach()
copy_base_translations(pcsx2-qt)
extract_translation_from_ts(Translations/pcsx2-qt_en.ts source PermissionsDialogCamera PCSX2_CAMERA_USAGE_DESCRIPTION)
extract_translation_from_ts(Translations/pcsx2-qt_en.ts source PermissionsDialogMicrophone PCSX2_MICROPHONE_USAGE_DESCRIPTION)
else()
qt_add_lrelease(pcsx2-qt TS_FILES ${TS_FILES} QM_FILES_OUTPUT_VARIABLE QM_FILES)
+1 -2
View File
@@ -112,8 +112,7 @@ void CoverDownloadDialog::cancelThread()
}
CoverDownloadDialog::CoverDownloadThread::CoverDownloadThread(QWidget* parent, const QString& urls, bool use_serials)
: QtAsyncProgressThread(parent)
, m_use_serials(use_serials)
: QtAsyncProgressThread(parent), m_use_serials(use_serials)
{
for (const QString& str : urls.split(QChar('\n')))
m_urls.push_back(str.toStdString());
@@ -2,13 +2,12 @@
// SPDX-License-Identifier: GPL-3.0+
#include "BreakpointDialog.h"
#include "DebugTools/Breakpoints.h"
#include "AsyncDialogs.h"
#include "QtUtils.h"
#include "QtHost.h"
#include "Debugger/DebuggerWindow.h"
#include "DebugTools/Breakpoints.h"
#include <QtWidgets/QDialog>
#include <QtWidgets/QMessageBox>
BreakpointDialog::BreakpointDialog(QWidget* parent, DebugInterface* cpu, BreakpointModel& model)
: QDialog(parent)
@@ -101,7 +100,7 @@ void BreakpointDialog::accept()
u64 address;
if (!m_cpu->evaluateExpression(m_ui.txtAddress->text().toStdString().c_str(), address, error))
{
AsyncDialogs::warning(g_debugger_window, tr("Invalid Address"), QString::fromStdString(error));
QMessageBox::warning(this, tr("Invalid Address"), QString::fromStdString(error));
return;
}
@@ -117,7 +116,7 @@ void BreakpointDialog::accept()
if (!m_cpu->initExpression(m_ui.txtCondition->text().toStdString().c_str(), expr, error))
{
AsyncDialogs::warning(g_debugger_window, tr("Invalid Condition"), QString::fromStdString(error));
QMessageBox::warning(this, tr("Invalid Condition"), QString::fromStdString(error));
return;
}
@@ -135,14 +134,14 @@ void BreakpointDialog::accept()
u64 startAddress;
if (!m_cpu->evaluateExpression(m_ui.txtAddress->text().toStdString().c_str(), startAddress, error))
{
AsyncDialogs::warning(g_debugger_window, tr("Invalid Address"), QString::fromStdString(error));
QMessageBox::warning(this, tr("Invalid Address"), QString::fromStdString(error));
return;
}
u64 size;
if (!m_cpu->evaluateExpression(m_ui.txtSize->text().toStdString().c_str(), size, error) || !size)
{
AsyncDialogs::warning(g_debugger_window, tr("Invalid Size"), QString::fromStdString(error));
QMessageBox::warning(this, tr("Invalid Size"), QString::fromStdString(error));
return;
}
@@ -158,7 +157,7 @@ void BreakpointDialog::accept()
PostfixExpression expr;
if (!m_cpu->initExpression(m_ui.txtCondition->text().toStdString().c_str(), expr, error))
{
AsyncDialogs::warning(g_debugger_window, tr("Invalid Condition"), QString::fromStdString(error));
QMessageBox::warning(this, tr("Invalid Condition"), QString::fromStdString(error));
return;
}
@@ -3,11 +3,9 @@
#include "BreakpointModel.h"
#include "AsyncDialogs.h"
#include "QtHost.h"
#include "QtUtils.h"
#include "Debugger/DebuggerSettingsManager.h"
#include "Debugger/DebuggerWindow.h"
#include "DebugTools/DebugInterface.h"
#include "DebugTools/Breakpoints.h"
@@ -15,6 +13,7 @@
#include "common/Console.h"
#include <QtCore/QPointer>
#include <QtWidgets/QMessageBox>
#include <algorithm>
@@ -386,7 +385,7 @@ bool BreakpointModel::setData(const QModelIndex& index, const QVariant& value, i
std::string error;
if (!m_cpu.initExpression(condValue.toLocal8Bit().constData(), expr, error))
{
AsyncDialogs::warning(g_debugger_window, "Condition Error", QString::fromStdString(error));
QMessageBox::warning(nullptr, "Condition Error", QString::fromStdString(error));
return false;
}
@@ -420,7 +419,7 @@ bool BreakpointModel::setData(const QModelIndex& index, const QVariant& value, i
std::string error;
if (!m_cpu.initExpression(condValue.toLocal8Bit().constData(), expr, error))
{
AsyncDialogs::warning(g_debugger_window, "Condition Error", QString::fromStdString(error));
QMessageBox::warning(nullptr, "Condition Error", QString::fromStdString(error));
return false;
}
+10 -11
View File
@@ -3,7 +3,6 @@
#include "DebuggerWindow.h"
#include "AsyncDialogs.h"
#include "Debugger/DebuggerView.h"
#include "Debugger/Docking/DockManager.h"
@@ -16,6 +15,8 @@
#include "MainWindow.h"
#include "AnalysisOptionsDialog.h"
#include <QtWidgets/QMessageBox>
DebuggerWindow* g_debugger_window = nullptr;
DebuggerWindow::DebuggerWindow(QWidget* parent)
@@ -69,21 +70,19 @@ DebuggerWindow::DebuggerWindow(QWidget* parent)
});
connect(m_ui.actionResetAllLayouts, &QAction::triggered, this, [this]() {
const QString title = tr("Confirmation");
const QString text = tr("Are you sure you want to reset all layouts?");
QString text = tr("Are you sure you want to reset all layouts?");
if (QMessageBox::question(g_debugger_window, tr("Confirmation"), text) != QMessageBox::Yes)
return;
AsyncDialogs::question(this, title, text, [this]() {
m_dock_manager->resetAllLayouts();
});
m_dock_manager->resetAllLayouts();
});
connect(m_ui.actionResetDefaultLayouts, &QAction::triggered, this, [this]() {
const QString title = tr("Confirmation");
const QString text = tr("Are you sure you want to reset the default layouts?");
QString text = tr("Are you sure you want to reset the default layouts?");
if (QMessageBox::question(g_debugger_window, tr("Confirmation"), text) != QMessageBox::Yes)
return;
AsyncDialogs::question(this, title, text, [this]() {
m_dock_manager->resetDefaultLayouts();
});
m_dock_manager->resetDefaultLayouts();
});
connect(g_emu_thread, &EmuThread::onVMPaused, this, []() {
+52 -48
View File
@@ -3,7 +3,6 @@
#include "DisassemblyView.h"
#include "AsyncDialogs.h"
#include "Debugger/DebuggerWindow.h"
#include "Debugger/JsonValueWrapper.h"
#include "Debugger/Breakpoints/BreakpointModel.h"
@@ -19,6 +18,8 @@
#include <QtGui/QMouseEvent>
#include <QtWidgets/QMenu>
#include <QtGui/QClipboard>
#include <QtWidgets/QInputDialog>
#include <QtWidgets/QMessageBox>
#include "SymbolTree/NewSymbolDialogs.h"
#include "common/StringUtil.h"
@@ -110,7 +111,7 @@ void DisassemblyView::contextPasteInstructionText()
{
if (!cpu().isCpuPaused())
{
AsyncDialogs::warning(this, tr("Assemble Error"), tr("Unable to change assembly while core is running"));
QMessageBox::warning(this, tr("Assemble Error"), tr("Unable to change assembly while core is running"));
return;
}
@@ -129,7 +130,7 @@ void DisassemblyView::contextPasteInstructionText()
bool valid = MipsAssembleOpcode(newInstructions[instructionIdx].c_str(), &cpu(), replaceAddress, encodedInstruction, errorText);
if (!valid)
{
AsyncDialogs::warning(this, tr("Assemble Error"), QString("%1 %2").arg(errorText.c_str()).arg(newInstructions[instructionIdx].c_str()));
QMessageBox::warning(this, tr("Assemble Error"), QString("%1 %2").arg(errorText.c_str()).arg(newInstructions[instructionIdx].c_str()));
return;
}
encodedInstructions.push_back(encodedInstruction);
@@ -147,28 +148,29 @@ void DisassemblyView::contextAssembleInstruction()
{
if (!cpu().isCpuPaused())
{
AsyncDialogs::warning(this, tr("Assemble Error"), tr("Unable to change assembly while core is running"));
QMessageBox::warning(this, tr("Assemble Error"), tr("Unable to change assembly while core is running"));
return;
}
DisassemblyLineInfo line;
bool ok;
m_disassemblyManager.getLine(m_selectedAddressStart, false, line);
QString instruction = QInputDialog::getText(this, tr("Assemble Instruction"), "",
QLineEdit::Normal, QString("%1 %2").arg(line.name.c_str()).arg(line.params.c_str()), &ok);
const QString title = tr("Assemble Instruction");
const QString text = QString("%1 %2").arg(line.name.c_str()).arg(line.params.c_str());
if (!ok)
return;
AsyncDialogs::getText(this, title, "", text, [this](QString instruction) {
u32 encodedInstruction;
std::string errorText;
bool valid = MipsAssembleOpcode(instruction.toLocal8Bit().constData(), &cpu(), m_selectedAddressStart, encodedInstruction, errorText);
if (!valid)
{
AsyncDialogs::warning(this, tr("Assemble Error"), QString::fromStdString(errorText));
return;
}
u32 encodedInstruction;
std::string errorText;
bool valid = MipsAssembleOpcode(instruction.toLocal8Bit().constData(), &cpu(), m_selectedAddressStart, encodedInstruction, errorText);
if (!valid)
{
QMessageBox::warning(this, tr("Assemble Error"), QString::fromStdString(errorText));
return;
}
setInstructions(m_selectedAddressStart, m_selectedAddressEnd, encodedInstruction);
});
setInstructions(m_selectedAddressStart, m_selectedAddressEnd, encodedInstruction);
}
void DisassemblyView::contextNoopInstruction()
@@ -247,34 +249,34 @@ void DisassemblyView::contextFollowBranch()
void DisassemblyView::contextGoToAddress()
{
const QString title = tr("Go To In Disassembly");
bool ok;
const QString targetString = QInputDialog::getText(this, tr("Go To In Disassembly"), "",
QLineEdit::Normal, "", &ok);
AsyncDialogs::getText(this, title, "", "", [this](QString expression) {
u64 address = 0;
std::string error;
if (!cpu().evaluateExpression(expression.toStdString().c_str(), address, error))
{
AsyncDialogs::warning(this, tr("Cannot Go To"), QString::fromStdString(error));
return;
}
if (!ok)
return;
gotoAddressAndSetFocus(static_cast<u32>(address) & ~3);
});
u64 address = 0;
std::string error;
if (!cpu().evaluateExpression(targetString.toStdString().c_str(), address, error))
{
QMessageBox::warning(this, tr("Cannot Go To"), QString::fromStdString(error));
return;
}
gotoAddressAndSetFocus(static_cast<u32>(address) & ~3);
}
void DisassemblyView::contextAddFunction()
{
NewFunctionDialog* dialog = new NewFunctionDialog(cpu(), this);
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->setName(QString("func_%1").arg(m_selectedAddressStart, 8, 16, QChar('0')));
dialog->setAddress(m_selectedAddressStart);
dialog->setAttribute(Qt::WA_DeleteOnClose);
if (m_selectedAddressEnd != m_selectedAddressStart)
dialog->setCustomSize(m_selectedAddressEnd - m_selectedAddressStart + 4);
connect(dialog, &QDialog::accepted, this, [this]() { update(); });
dialog->open();
if (dialog->exec() == QDialog::Accepted)
update();
}
void DisassemblyView::contextCopyFunctionName()
@@ -302,26 +304,28 @@ void DisassemblyView::contextRemoveFunction()
void DisassemblyView::contextRenameFunction()
{
const FunctionInfo curFunc = cpu().GetSymbolGuardian().FunctionOverlappingAddress(m_selectedAddressStart);
if (!curFunc.address.valid())
{
AsyncDialogs::warning(this, tr("Rename Function Error"), tr("No function / symbol is currently selected."));
QMessageBox::warning(this, tr("Rename Function Error"), tr("No function / symbol is currently selected."));
return;
}
const QString title = tr("Rename Function");
const QString label = tr("Function name");
const QString oldName = QString::fromStdString(curFunc.name);
QString oldName = QString::fromStdString(curFunc.name);
AsyncDialogs::getText(this, title, label, oldName, [this, curFunc](QString newName) {
if (newName.isEmpty())
{
AsyncDialogs::warning(this, tr("Rename Function Error"), tr("Function name cannot be nothing."));
return;
}
bool ok;
QString newName = QInputDialog::getText(this, tr("Rename Function"), tr("Function name"), QLineEdit::Normal, oldName, &ok);
if (!ok)
return;
cpu().GetSymbolGuardian().ReadWrite([&](ccc::SymbolDatabase& database) {
database.functions.rename_symbol(curFunc.handle, newName.toStdString());
});
if (newName.isEmpty())
{
QMessageBox::warning(this, tr("Rename Function Error"), tr("Function name cannot be nothing."));
return;
}
cpu().GetSymbolGuardian().ReadWrite([&](ccc::SymbolDatabase& database) {
database.functions.rename_symbol(curFunc.handle, newName.toStdString());
});
}
@@ -371,7 +375,7 @@ void DisassemblyView::contextRestoreFunction()
}
else
{
AsyncDialogs::warning(this, tr("Restore Function Error"), tr("Unable to stub selected address."));
QMessageBox::warning(this, tr("Restore Function Error"), tr("Unable to stub selected address."));
}
}
+1 -1
View File
@@ -43,7 +43,7 @@ public slots:
void contextCopyInstructionHex();
void contextCopyInstructionText();
void contextCopyFunctionName();
void contextPasteInstructionText();
void contextPasteInstructionText();
void contextAssembleInstruction();
void contextNoopInstruction();
void contextRestoreInstruction();
+35 -56
View File
@@ -3,7 +3,6 @@
#include "DockManager.h"
#include "AsyncDialogs.h"
#include "Debugger/DebuggerView.h"
#include "Debugger/DebuggerWindow.h"
#include "Debugger/Docking/DockTables.h"
@@ -25,6 +24,7 @@
#include <QtCore/QTimer>
#include <QtCore/QtTranslation>
#include <QtWidgets/QMessageBox>
#include <QtWidgets/QProxyStyle>
#include <QtWidgets/QStyleFactory>
@@ -518,19 +518,17 @@ void DockManager::newLayoutClicked()
if (m_menu_bar)
m_menu_bar->onCurrentLayoutChanged(m_current_layout);
const auto name_validator = [this](const QString& name) {
auto name_validator = [this](const QString& name) {
return !hasNameConflict(name, DockLayout::INVALID_INDEX);
};
const bool can_clone_current_layout = m_current_layout != DockLayout::INVALID_INDEX;
bool can_clone_current_layout = m_current_layout != DockLayout::INVALID_INDEX;
LayoutEditorDialog* dialog = new LayoutEditorDialog(name_validator, can_clone_current_layout, g_debugger_window);
dialog->setAttribute(Qt::WA_DeleteOnClose);
connect(dialog, &QDialog::accepted, this, [this, dialog, name_validator]() {
if (!name_validator(dialog->name()))
return;
QPointer<LayoutEditorDialog> dialog = new LayoutEditorDialog(
name_validator, can_clone_current_layout, g_debugger_window);
if (dialog->exec() == QDialog::Accepted && name_validator(dialog->name()))
{
DockLayout::Index new_layout = DockLayout::INVALID_INDEX;
const auto [mode, index] = dialog->initialState();
@@ -567,9 +565,9 @@ void DockManager::newLayoutClicked()
updateLayoutSwitcher();
switchToLayout(new_layout);
}
});
}
dialog->open();
delete dialog.get();
}
void DockManager::openLayoutSwitcherContextMenu(const QPoint& pos, QTabBar* layout_switcher)
@@ -607,33 +605,26 @@ void DockManager::editLayoutClicked(DockLayout::Index layout_index)
if (layout_index >= m_layouts.size())
return;
const DockLayout& layout = m_layouts[layout_index];
DockLayout& layout = m_layouts[layout_index];
const auto name_validator = [this, layout_index](const QString& name) {
auto name_validator = [this, layout_index](const QString& name) {
return !hasNameConflict(name, layout_index);
};
LayoutEditorDialog* dialog = new LayoutEditorDialog(layout.name(), layout.cpu(), name_validator, g_debugger_window);
dialog->setAttribute(Qt::WA_DeleteOnClose);
QPointer<LayoutEditorDialog> dialog = new LayoutEditorDialog(
layout.name(), layout.cpu(), name_validator, g_debugger_window);
connect(dialog, &QDialog::accepted, this, [this, layout_index, dialog, name_validator]() {
if (layout_index >= m_layouts.size())
return;
if (dialog->exec() != QDialog::Accepted || !name_validator(dialog->name()))
return;
DockLayout& layout = m_layouts[layout_index];
layout.setName(dialog->name());
layout.setCpu(dialog->cpu());
if (!name_validator(dialog->name()))
return;
layout.save(layout_index);
layout.setName(dialog->name());
layout.setCpu(dialog->cpu());
delete dialog.get();
layout.save(layout_index);
updateLayoutSwitcher();
});
dialog->open();
updateLayoutSwitcher();
}
void DockManager::resetLayoutClicked(DockLayout::Index layout_index)
@@ -645,28 +636,20 @@ void DockManager::resetLayoutClicked(DockLayout::Index layout_index)
if (!layout.canReset())
return;
const QString title = tr("Confirmation");
const QString text = tr("Are you sure you want to reset layout '%1'?").arg(layout.name());
QString text = tr("Are you sure you want to reset layout '%1'?").arg(layout.name());
if (QMessageBox::question(g_debugger_window, tr("Confirmation"), text) != QMessageBox::Yes)
return;
AsyncDialogs::question(g_debugger_window, title, text, [this, layout_index]() {
if (layout_index >= m_layouts.size())
return;
bool current_layout = layout_index == m_current_layout;
DockLayout& layout = m_layouts[layout_index];
if (!layout.canReset())
return;
if (current_layout)
switchToLayout(DockLayout::INVALID_INDEX);
bool current_layout = layout_index == m_current_layout;
layout.reset();
layout.save(layout_index);
if (current_layout)
switchToLayout(DockLayout::INVALID_INDEX);
layout.reset();
layout.save(layout_index);
if (current_layout)
switchToLayout(layout_index);
});
if (current_layout)
switchToLayout(layout_index);
}
void DockManager::deleteLayoutClicked(DockLayout::Index layout_index)
@@ -676,16 +659,12 @@ void DockManager::deleteLayoutClicked(DockLayout::Index layout_index)
DockLayout& layout = m_layouts[layout_index];
const QString title = tr("Confirmation");
const QString text = tr("Are you sure you want to delete layout '%1'?").arg(layout.name());
QString text = tr("Are you sure you want to delete layout '%1'?").arg(layout.name());
if (QMessageBox::question(g_debugger_window, tr("Confirmation"), text) != QMessageBox::Yes)
return;
AsyncDialogs::question(g_debugger_window, title, text, [this, layout_index]() {
if (layout_index >= m_layouts.size())
return;
deleteLayout(layout_index);
updateLayoutSwitcher();
});
deleteLayout(layout_index);
updateLayoutSwitcher();
}
void DockManager::layoutSwitcherTabMoved(DockLayout::Index from_index, DockLayout::Index to_index)
+13 -15
View File
@@ -3,7 +3,6 @@
#include "DockViews.h"
#include "AsyncDialogs.h"
#include "QtUtils.h"
#include "Debugger/DebuggerView.h"
#include "Debugger/DebuggerWindow.h"
@@ -18,6 +17,8 @@
#include <QtGui/QActionGroup>
#include <QtGui/QPalette>
#include <QtWidgets/QInputDialog>
#include <QtWidgets/QMessageBox>
#include <QtWidgets/QMenu>
#include <QtWidgets/QStyleFactory>
@@ -175,22 +176,19 @@ void DockTabBar::openContextMenu(QPoint pos)
if (!widget)
return;
const QString title = tr("Rename Window");
const QString label = tr("New name:");
const QString text = widget->displayNameWithoutSuffix();
bool ok;
QString new_name = QInputDialog::getText(
this, tr("Rename Window"), tr("New name:"), QLineEdit::Normal, widget->displayNameWithoutSuffix(), &ok);
if (!ok)
return;
AsyncDialogs::getText(this, title, label, text, [this, widget = QPointer(widget)](QString name) {
if (!widget || !g_debugger_window)
return;
if (!widget->setCustomDisplayName(new_name))
{
QMessageBox::warning(this, tr("Invalid Name"), tr("The specified name is too long."));
return;
}
if (!widget->setCustomDisplayName(name))
{
AsyncDialogs::warning(this, tr("Invalid Name"), tr("The specified name is too long."));
return;
}
g_debugger_window->dockManager().updateDockWidgetTitles();
});
g_debugger_window->dockManager().updateDockWidgetTitles();
});
QAction* reset_name_action = menu->addAction(tr("Reset Name"));
+10 -10
View File
@@ -3,16 +3,16 @@
#include "MemorySearchView.h"
#include "AsyncDialogs.h"
#include "QtUtils.h"
#include "DebugTools/DebugInterface.h"
#include "QtUtils.h"
#include "common/Console.h"
#include <QtGui/QClipboard>
#include <QtWidgets/QMenu>
#include <QtWidgets/QScrollBar>
#include <QtWidgets/QMessageBox>
#include <QtConcurrent/QtConcurrent>
#include <QtCore/QFutureWatcher>
#include <QtGui/QPainter>
@@ -478,7 +478,7 @@ void MemorySearchView::onSearchButtonClicked()
if (!ok)
{
AsyncDialogs::critical(this, tr("Debugger"), tr("Invalid start address"));
QMessageBox::critical(this, tr("Debugger"), tr("Invalid start address"));
return;
}
@@ -486,13 +486,13 @@ void MemorySearchView::onSearchButtonClicked()
if (!ok)
{
AsyncDialogs::critical(this, tr("Debugger"), tr("Invalid end address"));
QMessageBox::critical(this, tr("Debugger"), tr("Invalid end address"));
return;
}
if (searchStart >= searchEnd)
{
AsyncDialogs::critical(this, tr("Debugger"), tr("Start address can't be equal to or greater than the end address"));
QMessageBox::critical(this, tr("Debugger"), tr("Start address can't be equal to or greater than the end address"));
return;
}
@@ -527,7 +527,7 @@ void MemorySearchView::onSearchButtonClicked()
if (!ok)
{
AsyncDialogs::critical(this, tr("Debugger"), tr("Invalid search value"));
QMessageBox::critical(this, tr("Debugger"), tr("Invalid search value"));
return;
}
@@ -551,7 +551,7 @@ void MemorySearchView::onSearchButtonClicked()
if (value <= std::numeric_limits<unsigned char>::max())
break;
default:
AsyncDialogs::critical(this, tr("Debugger"), tr("Value is larger than type"));
QMessageBox::critical(this, tr("Debugger"), tr("Value is larger than type"));
return;
}
}
@@ -565,7 +565,7 @@ void MemorySearchView::onSearchButtonClicked()
searchComparison == SearchComparison::IncreasedBy ||
searchComparison == SearchComparison::NotChanged))
{
AsyncDialogs::critical(this, tr("Debugger"), tr("This search comparison can only be used with filter searches."));
QMessageBox::critical(this, tr("Debugger"), tr("This search comparison can only be used with filter searches."));
return;
}
}
@@ -578,7 +578,7 @@ void MemorySearchView::onSearchButtonClicked()
searchComparison == SearchComparison::IncreasedBy ||
searchComparison == SearchComparison::NotChanged))
{
AsyncDialogs::critical(this, tr("Debugger"), tr("This search comparison can only be used with filter searches."));
QMessageBox::critical(this, tr("Debugger"), tr("This search comparison can only be used with filter searches."));
return;
}
+42 -35
View File
@@ -3,7 +3,6 @@
#include "MemoryView.h"
#include "AsyncDialogs.h"
#include "Debugger/JsonValueWrapper.h"
#include "QtHost.h"
@@ -13,6 +12,8 @@
#include <QtGui/QActionGroup>
#include <QtGui/QClipboard>
#include <QtGui/QMouseEvent>
#include <QtWidgets/QInputDialog>
#include <QtWidgets/QMessageBox>
using namespace QtUtils;
@@ -304,33 +305,36 @@ bool MemoryViewTable::InsertFloatIntoSelectedHexView(DebugInterface& cpu)
std::memcpy(&currentFloatVal, &currentIntVal, sizeof(currentFloatVal));
const QString currentfloatStr = QString("%1").arg(QString::number(currentFloatVal, 'g'), 14).trimmed();
const QString title = tr("Input New Float");
// Prompt user to enter a new float value
bool isValidInput = false;
QString newFloatStr = QInputDialog::getText(parent, tr("Input New Float"), "",
QLineEdit::Normal, currentfloatStr, &isValidInput);
if (!isValidInput)
return false;
AsyncDialogs::getText(parent, title, "", currentfloatStr, [this, &cpu](QString newFloatStr) {
// Convert string into float value
bool isValidFloat = false;
const float newFloatVal = newFloatStr.toFloat(&isValidFloat);
if (!isValidFloat)
{
AsyncDialogs::warning(parent, tr("Input Error"), tr("Invalid float value"));
return;
}
// Convert string into float value
bool isValidFloat = false;
const float newFloatVal = newFloatStr.toFloat(&isValidFloat);
if (!isValidFloat)
{
QMessageBox::warning(parent, tr("Input Error"), tr("Invalid float value"));
return false;
}
// Write new float value back to memory
u32 newIntVal = 0;
std::memcpy(&newIntVal, &newFloatVal, sizeof(newIntVal));
newIntVal = convertEndian(newIntVal);
// Write new float value back to memory
u32 newIntVal = 0;
std::memcpy(&newIntVal, &newFloatVal, sizeof(newIntVal));
newIntVal = convertEndian(newIntVal);
const QPointer<MemoryViewTable> table(this);
Host::RunOnCPUThread([table, address = selectedAddress, &cpu, val = newIntVal] {
cpu.write32(address, val);
const QPointer<MemoryViewTable> table(this);
Host::RunOnCPUThread([table, address = selectedAddress, &cpu, val = newIntVal] {
cpu.write32(address, val);
QtHost::RunOnUIThread([table] {
if (!table)
return;
QtHost::RunOnUIThread([table] {
if (!table)
return;
table->parent->update();
});
table->parent->update();
});
});
@@ -349,7 +353,7 @@ void MemoryViewTable::InsertAtCurrentSelection(const QString& text, DebugInterfa
const float newFloatVal = text.toFloat(&isValidFloat);
if (!isValidFloat)
{
AsyncDialogs::warning(parent, tr("Input Error"), tr("Invalid float value"));
QMessageBox::warning(parent, tr("Input Error"), tr("Invalid float value"));
return;
}
@@ -895,19 +899,22 @@ void MemoryView::contextPaste()
void MemoryView::contextGoToAddress()
{
const QString title = tr("Go To In Memory View");
bool ok;
QString targetString = QInputDialog::getText(this, tr("Go To In Memory View"), "",
QLineEdit::Normal, "", &ok);
AsyncDialogs::getText(this, title, "", "", [this](QString expression) {
u64 address = 0;
std::string error;
if (!cpu().evaluateExpression(expression.toStdString().c_str(), address, error))
{
AsyncDialogs::warning(this, tr("Cannot Go To"), QString::fromStdString(error));
return;
}
if (!ok)
return;
gotoAddress(static_cast<u32>(address));
});
u64 address = 0;
std::string error;
if (!cpu().evaluateExpression(targetString.toStdString().c_str(), address, error))
{
QMessageBox::warning(this, tr("Cannot Go To"), QString::fromStdString(error));
return;
}
gotoAddress(static_cast<u32>(address));
}
void MemoryView::contextFollowAddress()
@@ -30,8 +30,7 @@ SavedAddressesView::SavedAddressesView(const DebuggerViewParameters& parameters)
DebuggerSettingsManager::loadGameSettings(m_model);
});
if (m_model->rowCount() == 0)
DebuggerSettingsManager::loadGameSettings(m_model);
DebuggerSettingsManager::loadGameSettings(m_model);
for (std::size_t i = 0; auto mode : SavedAddressesModel::HeaderResizeModes)
{
+1 -1
View File
@@ -101,7 +101,7 @@ QVariant ModuleModel::headerData(int section, Qt::Orientation orientation, int r
//: Warning: short space limit. Abbreviate if needed.
return tr("NAME");
case ModuleColumns::VERSION:
//: Warning: short space limit. Abbreviate if needed.
//: Warning: short space limit. Abbreviate if needed.
return tr("VERSION");
case ModuleColumns::ENTRY:
//: Warning: short space limit. Abbreviate if needed. // Entrypoint of the executable
+57 -65
View File
@@ -3,16 +3,17 @@
#include "RegisterView.h"
#include "AsyncDialogs.h"
#include "QtUtils.h"
#include "Debugger/JsonValueWrapper.h"
#include "QtUtils.h"
#include <QtGui/QMouseEvent>
#include <QtWidgets/QTabBar>
#include <QtWidgets/QStylePainter>
#include <QtWidgets/QStyleOptionTab>
#include <QtGui/QClipboard>
#include <QtWidgets/QInputDialog>
#include <QtWidgets/QProxyStyle>
#include <QtWidgets/QMessageBox>
#include <bit>
@@ -350,11 +351,12 @@ void RegisterView::contextCopySegment()
QApplication::clipboard()->setText(FilledQStringFromValue(val._u32[3 - m_selected128Field], 16));
}
void RegisterView::fetchNewValue(u64 currentValue, bool segment, std::function<void(u64)> callback)
bool RegisterView::contextFetchNewValue(u64& out, u64 currentValue, bool segment)
{
const int categoryIndex = ui.registerTabs->currentIndex();
const bool floatingPoint = CAT_SHOW_FLOAT && segment;
const int regSize = cpu().getRegisterSize(categoryIndex);
bool ok = false;
QString existingValue("%1");
@@ -364,89 +366,79 @@ void RegisterView::fetchNewValue(u64 currentValue, bool segment, std::function<v
existingValue = existingValue.arg(std::bit_cast<float>((u32)currentValue));
//: Changing the value in a CPU register (e.g. "Change t0")
const QString title = tr("Change %1").arg(cpu().getRegisterName(categoryIndex, m_selectedRow));
QString input = QInputDialog::getText(this, tr("Change %1").arg(cpu().getRegisterName(categoryIndex, m_selectedRow)), "",
QLineEdit::Normal, existingValue, &ok);
AsyncDialogs::getText(this, title, "", existingValue, [this, callback, floatingPoint](QString input) {
u64 value;
if (!floatingPoint) // Get input as hexadecimal
{
bool ok;
value = input.toULongLong(&ok, 16);
if (!ok)
{
AsyncDialogs::warning(this, tr("Invalid register value"), tr("Invalid hexadecimal register value."));
return;
}
}
else
{
bool ok;
value = std::bit_cast<u32>(input.toFloat(&ok));
if (!ok)
{
AsyncDialogs::warning(this, tr("Invalid register value"), tr("Invalid floating-point register value."));
return;
}
}
if (!ok)
return false;
callback(value);
});
if (!floatingPoint) // Get input as hexadecimal
{
out = input.toULongLong(&ok, 16);
if (!ok)
{
QMessageBox::warning(this, tr("Invalid register value"), tr("Invalid hexadecimal register value."));
return false;
}
}
else
{
out = std::bit_cast<u32>(input.toFloat(&ok));
if (!ok)
{
QMessageBox::warning(this, tr("Invalid register value"), tr("Invalid floating-point register value."));
return false;
}
}
return true;
}
void RegisterView::contextChangeValue()
{
const int category_index = ui.registerTabs->currentIndex();
const s32 row = m_selectedRow;
const u32 old_value = cpu().getRegister(category_index, row).lo;
fetchNewValue(old_value, false, [this, category_index, row](u64 input) {
cpu().setRegister(category_index, row, u128::From64(input));
const int categoryIndex = ui.registerTabs->currentIndex();
u64 newVal;
if (contextFetchNewValue(newVal, cpu().getRegister(categoryIndex, m_selectedRow).lo))
{
cpu().setRegister(categoryIndex, m_selectedRow, u128::From64(newVal));
DebuggerView::broadcastEvent(DebuggerEvents::VMUpdate());
});
}
}
void RegisterView::contextChangeTop()
{
const int category_index = ui.registerTabs->currentIndex();
const s32 row = m_selectedRow;
const u128 old_value = cpu().getRegister(category_index, row);
fetchNewValue(old_value.hi, false, [this, category_index, row, old_value](u32 input) {
u128 new_value = old_value;
new_value.hi = input;
cpu().setRegister(category_index, row, new_value);
u64 newVal;
u128 oldVal = cpu().getRegister(ui.registerTabs->currentIndex(), m_selectedRow);
if (contextFetchNewValue(newVal, oldVal.hi))
{
oldVal.hi = newVal;
cpu().setRegister(ui.registerTabs->currentIndex(), m_selectedRow, oldVal);
DebuggerView::broadcastEvent(DebuggerEvents::VMUpdate());
});
}
}
void RegisterView::contextChangeBottom()
{
const int category_index = ui.registerTabs->currentIndex();
const s32 row = m_selectedRow;
const u128 old_value = cpu().getRegister(category_index, row);
fetchNewValue(old_value.lo, false, [this, category_index, row, old_value](u32 input) {
u128 new_value = old_value;
new_value.lo = input;
cpu().setRegister(category_index, row, new_value);
u64 newVal;
u128 oldVal = cpu().getRegister(ui.registerTabs->currentIndex(), m_selectedRow);
if (contextFetchNewValue(newVal, oldVal.lo))
{
oldVal.lo = newVal;
cpu().setRegister(ui.registerTabs->currentIndex(), m_selectedRow, oldVal);
DebuggerView::broadcastEvent(DebuggerEvents::VMUpdate());
});
}
}
void RegisterView::contextChangeSegment()
{
const int category_index = ui.registerTabs->currentIndex();
const s32 row = m_selectedRow;
const s32 field = m_selected128Field;
const u128 old_value = cpu().getRegister(category_index, row);
const u32 segment = old_value._u32[3 - field];
fetchNewValue(segment, false, [this, category_index, row, field, old_value](u32 input) {
u128 new_value = old_value;
new_value._u32[3 - field] = input;
cpu().setRegister(category_index, row, new_value);
u64 newVal;
u128 oldVal = cpu().getRegister(ui.registerTabs->currentIndex(), m_selectedRow);
if (contextFetchNewValue(newVal, oldVal._u32[3 - m_selected128Field], true))
{
oldVal._u32[3 - m_selected128Field] = (u32)newVal;
cpu().setRegister(ui.registerTabs->currentIndex(), m_selectedRow, oldVal);
DebuggerView::broadcastEvent(DebuggerEvents::VMUpdate());
});
}
}
std::optional<DebuggerEvents::GoToAddress> RegisterView::contextCreateGotoEvent()
@@ -462,7 +454,7 @@ std::optional<DebuggerEvents::GoToAddress> RegisterView::contextCreateGotoEvent(
if (!cpu().isValidAddress(addr))
{
AsyncDialogs::warning(
QMessageBox::warning(
this,
tr("Invalid target address"),
tr("This register holds an invalid address."));
+2 -1
View File
@@ -49,7 +49,8 @@ public slots:
private:
Ui::RegisterView ui;
void fetchNewValue(u64 currentValue, bool segment, std::function<void(u64)> callback);
// Returns true on success
bool contextFetchNewValue(u64& out, u64 currentValue, bool segment = false);
// Used for the height offset the tab bar creates
// because we share a widget
+2 -1
View File
@@ -25,7 +25,8 @@ public:
COLUMN_COUNT
};
static constexpr QHeaderView::ResizeMode HeaderResizeModes[StackColumns::COLUMN_COUNT] = {
static constexpr QHeaderView::ResizeMode HeaderResizeModes[StackColumns::COLUMN_COUNT] =
{
QHeaderView::ResizeMode::ResizeToContents,
QHeaderView::ResizeMode::Stretch,
QHeaderView::ResizeMode::ResizeToContents,
@@ -3,14 +3,13 @@
#include "NewSymbolDialogs.h"
#include "AsyncDialogs.h"
#include "Debugger/DebuggerWindow.h"
#include "Debugger/SymbolTree/TypeString.h"
#include <QtCore/QTimer>
#include <QtCore/QMetaMethod>
#include <QtWidgets/QMessageBox>
#include <QtWidgets/QPushButton>
#include "TypeString.h"
NewSymbolDialog::NewSymbolDialog(u32 flags, u32 alignment, DebugInterface& cpu, QWidget* parent)
: QDialog(parent)
, m_cpu(cpu)
@@ -360,7 +359,7 @@ void NewFunctionDialog::createSymbol()
});
if (!error_message.isEmpty())
AsyncDialogs::warning(g_debugger_window, tr("Cannot Create Function"), error_message);
QMessageBox::warning(this, tr("Cannot Create Function"), error_message);
}
// *****************************************************************************
@@ -417,7 +416,7 @@ void NewGlobalVariableDialog::createSymbol()
});
if (!error_message.isEmpty())
AsyncDialogs::warning(g_debugger_window, tr("Cannot Create Global Variable"), error_message);
QMessageBox::warning(this, tr("Cannot Create Global Variable"), error_message);
}
// *****************************************************************************
@@ -535,7 +534,7 @@ void NewLocalVariableDialog::createSymbol()
});
if (!error_message.isEmpty())
AsyncDialogs::warning(g_debugger_window, tr("Cannot Create Local Variable"), error_message);
QMessageBox::warning(this, tr("Cannot Create Local Variable"), error_message);
}
// *****************************************************************************
@@ -649,5 +648,5 @@ void NewParameterVariableDialog::createSymbol()
});
if (!error_message.isEmpty())
AsyncDialogs::warning(g_debugger_window, tr("Cannot Create Parameter Variable"), error_message);
QMessageBox::warning(this, tr("Cannot Create Parameter Variable"), error_message);
}
@@ -3,7 +3,6 @@
#include "SymbolTreeDelegates.h"
#include "AsyncDialogs.h"
#include "Debugger/SymbolTree/SymbolTreeModel.h"
#include "Debugger/SymbolTree/TypeString.h"
@@ -11,6 +10,7 @@
#include <QtWidgets/QComboBox>
#include <QtWidgets/QDoubleSpinBox>
#include <QtWidgets/QLineEdit>
#include <QtWidgets/QMessageBox>
SymbolTreeValueDelegate::SymbolTreeValueDelegate(
DebugInterface& cpu,
@@ -495,7 +495,7 @@ void SymbolTreeTypeDelegate::setModelData(QWidget* editor, QAbstractItemModel* m
symbol_tree_model->resetChildren(index);
}
else
AsyncDialogs::warning(editor, tr("Cannot Change Type"), error_message);
QMessageBox::warning(editor, tr("Cannot Change Type"), error_message);
}
// *****************************************************************************
@@ -19,7 +19,7 @@ struct SymbolTreeLocation
MEMORY,
NONE // Put NONE last so nodes of this type sort to the bottom.
};
Type type = NONE;
u32 address = 0;
@@ -3,14 +3,15 @@
#include "SymbolTreeViews.h"
#include "AsyncDialogs.h"
#include "Debugger/JsonValueWrapper.h"
#include "Debugger/SymbolTree/NewSymbolDialogs.h"
#include "Debugger/SymbolTree/SymbolTreeDelegates.h"
#include <QtGui/QActionGroup>
#include <QtGui/QClipboard>
#include <QtWidgets/QInputDialog>
#include <QtWidgets/QMenu>
#include <QtWidgets/QMessageBox>
#include <QtWidgets/QScrollBar>
static bool testName(const QString& name, const QString& filter);
@@ -642,16 +643,14 @@ void SymbolTreeView::onDeleteButtonPressed()
if (!node->symbol.valid())
return;
const QString title = tr("Confirm Deletion");
const QString text = tr("Delete '%1'?").arg(node->name);
if (QMessageBox::question(this, tr("Confirm Deletion"), tr("Delete '%1'?").arg(node->name)) != QMessageBox::Yes)
return;
AsyncDialogs::question(this, title, text, [this, handle = node->symbol]() {
cpu().GetSymbolGuardian().ReadWrite([&](ccc::SymbolDatabase& database) {
handle.destroy_symbol(database, true);
});
reset();
cpu().GetSymbolGuardian().ReadWrite([&](ccc::SymbolDatabase& database) {
node->symbol.destroy_symbol(database, true);
});
reset();
}
void SymbolTreeView::onCopyName()
@@ -702,10 +701,13 @@ void SymbolTreeView::onRenameSymbol()
text = QString::fromStdString(symbol->name());
});
AsyncDialogs::getText(this, title, label, text, [this, handle = node->symbol](QString new_name) {
cpu().GetSymbolGuardian().ReadWrite([&](ccc::SymbolDatabase& database) {
handle.rename_symbol(new_name.toStdString(), database);
});
bool ok;
std::string name = QInputDialog::getText(this, title, label, QLineEdit::Normal, text, &ok).toStdString();
if (!ok)
return;
cpu().GetSymbolGuardian().ReadWrite([&](ccc::SymbolDatabase& database) {
node->symbol.rename_symbol(name, database);
});
}
@@ -735,15 +737,18 @@ void SymbolTreeView::onChangeTypeTemporarily()
std::optional<QString> old_type = m_model->typeFromModelIndexToString(index);
if (!old_type.has_value())
{
AsyncDialogs::warning(this, tr("Cannot Change Type"), tr("That node cannot have a type."));
QMessageBox::warning(this, tr("Cannot Change Type"), tr("That node cannot have a type."));
return;
}
AsyncDialogs::getText(this, title, label, *old_type, [this, index](QString type_string) {
std::optional<QString> error_message = m_model->changeTypeTemporarily(index, type_string.toStdString());
if (error_message.has_value() && !error_message->isEmpty())
AsyncDialogs::warning(this, tr("Cannot Change Type"), *error_message);
});
bool ok;
QString type_string = QInputDialog::getText(this, title, label, QLineEdit::Normal, *old_type, &ok);
if (!ok)
return;
std::optional<QString> error_message = m_model->changeTypeTemporarily(index, type_string.toStdString());
if (error_message.has_value() && !error_message->isEmpty())
QMessageBox::warning(this, tr("Cannot Change Type"), *error_message);
}
void SymbolTreeView::onTreeViewClicked(const QModelIndex& index)
@@ -857,10 +862,8 @@ void FunctionTreeView::onNewButtonPressed()
{
NewFunctionDialog* dialog = new NewFunctionDialog(cpu(), this);
dialog->setAttribute(Qt::WA_DeleteOnClose);
connect(dialog, &QDialog::accepted, this, &FunctionTreeView::reset);
dialog->open();
if (dialog->exec() == QDialog::Accepted)
reset();
}
// *****************************************************************************
@@ -1002,10 +1005,8 @@ void GlobalVariableTreeView::onNewButtonPressed()
{
NewGlobalVariableDialog* dialog = new NewGlobalVariableDialog(cpu(), this);
dialog->setAttribute(Qt::WA_DeleteOnClose);
connect(dialog, &QDialog::accepted, this, &GlobalVariableTreeView::reset);
dialog->open();
if (dialog->exec() == QDialog::Accepted)
reset();
}
// *****************************************************************************
@@ -1133,10 +1134,8 @@ void LocalVariableTreeView::onNewButtonPressed()
{
NewLocalVariableDialog* dialog = new NewLocalVariableDialog(cpu(), this);
dialog->setAttribute(Qt::WA_DeleteOnClose);
connect(dialog, &QDialog::accepted, this, &LocalVariableTreeView::reset);
dialog->open();
if (dialog->exec() == QDialog::Accepted)
reset();
}
// *****************************************************************************
@@ -1262,10 +1261,8 @@ void ParameterVariableTreeView::onNewButtonPressed()
{
NewParameterVariableDialog* dialog = new NewParameterVariableDialog(cpu(), this);
dialog->setAttribute(Qt::WA_DeleteOnClose);
connect(dialog, &QDialog::accepted, this, &ParameterVariableTreeView::reset);
dialog->open();
if (dialog->exec() == QDialog::Accepted)
reset();
}
static bool testName(const QString& name, const QString& filter)
+2 -1
View File
@@ -27,7 +27,8 @@ public:
COLUMN_COUNT
};
static constexpr QHeaderView::ResizeMode HeaderResizeModes[ThreadColumns::COLUMN_COUNT] = {
static constexpr QHeaderView::ResizeMode HeaderResizeModes[ThreadColumns::COLUMN_COUNT] =
{
QHeaderView::ResizeMode::ResizeToContents,
QHeaderView::ResizeMode::ResizeToContents,
QHeaderView::ResizeMode::ResizeToContents,
+1 -8
View File
@@ -479,15 +479,8 @@ bool DisplaySurface::eventFilter(QObject* object, QEvent* event)
// macOS: When we (the display window) get focus from another window with a toolbar we update to the MainWindow toolbar.
// This is because we are a different native window from our MainWindow. So, whenever we get focus, focus our MainWindow.
// That way macOS will show the MainWindow toolbar when you click from the debugger / log window to the game.
// Don't try to steal focus when we're showing a modal dialog
// We end up ping ponging focus in a feedback loop
if (QApplication::activeModalWidget() != nullptr)
return false;
if (const auto* w = qobject_cast<QWidget*>(object))
if (auto* w = qobject_cast<QWidget*>(object))
w->window()->activateWindow();
return false;
default:
return false;
+2 -1
View File
@@ -160,6 +160,7 @@ void GameListModel::loadOrGenerateCover(const GameList::Entry* ge)
// Final check that scale is unchanged before we send out the produced image.
return m_cover_scale_counter.load(std::memory_order_acquire) == counter ? image : QPixmap();
});
// Context must be 'this' so we run on the UI thread.
@@ -220,7 +221,7 @@ QString GameListModel::formatTimespan(const time_t timespan)
const u32 hours = static_cast<u32>(timespan / 3600);
if (hours > 0)
return qApp->translate("GameList", "%n hours", "", hours);
const u32 minutes = static_cast<u32>((timespan % 3600) / 60);
if (minutes > 0)
return qApp->translate("GameList", "%n minutes", "", minutes);
+17 -68
View File
@@ -282,7 +282,7 @@ void GameListWidget::initialize()
connect(m_table_view, &QTableView::customContextMenuRequested, this,
&GameListWidget::onTableViewContextMenuRequested);
connect(m_table_view->horizontalHeader(), &QHeaderView::customContextMenuRequested, this,
&GameListWidget::onTableViewHeaderContextMenuRequested);
&GameListWidget::onTableViewHeaderContextMenuRequested);
// Save state when header state changes (hiding and showing handled within onTableViewHeaderContextMenuRequested).
connect(m_table_view->horizontalHeader(), &QHeaderView::sectionMoved, this, &GameListWidget::onTableHeaderStateChanged);
@@ -292,27 +292,13 @@ void GameListWidget::initialize()
// Load the last session's header state or create a new one.
if (Host::ContainsBaseSettingValue("GameListTableView", "HeaderState"))
{
loadTableHeaderState();
// Enforce at least one column is visible immediately after loading.
// This handles cases where a config (perhaps from an older version) has 0 columns and
// no games are visible to be changed (such as per-game config) or played as you can't click on any.
// Will automatically repair a broken header state from config (PCSX2.ini) file.
ensureMinimumOneColumnVisible();
}
else
{
applyTableHeaderDefaults();
}
// After header state load to account for user-specified sort.
m_table_view->setSortingEnabled(true);
// Safety Fallback: Ensure the header is actually visible and
// force it to stretch correctly on the first launch. This is an edgecase in case it already broke for some people or broke on older versions
m_table_view->horizontalHeader()->show();
resizeTableViewColumnsToFit();
m_ui.stack->insertWidget(0, m_table_view);
m_list_view = new GameListGridListView(m_ui.stack);
@@ -422,7 +408,7 @@ void GameListWidget::setCustomBackground()
// Selected Custom background is valid, connect the signals and start animation in gamelist
connect(m_background_movie, &QMovie::frameChanged, this, &GameListWidget::processBackgroundFrames, Qt::UniqueConnection);
m_ui.stack->setAutoFillBackground(false);
m_table_view->viewport()->setAutoFillBackground(false);
m_list_view->viewport()->setAutoFillBackground(false);
updateCustomBackgroundState(true);
@@ -576,35 +562,30 @@ void GameListWidget::onListViewContextMenuRequested(const QPoint& point)
void GameListWidget::onTableViewHeaderContextMenuRequested(const QPoint& point)
{
QHeaderView* const header = m_table_view->horizontalHeader();
QMenu menu(this);
// Iterate through all available columns defined in the model.
QMenu menu;
QHeaderView* header = m_table_view->horizontalHeader();
if (!header)
return;
int column_visual = 0;
for (int column = 0; column < GameListModel::Column_Count; column++)
{
// Skip the cover art column as it shouldn't be toggled manually.
// The "cover" column is the game grid and cannot be hidden.
if (column == GameListModel::Column_Cover)
continue;
// Create a checkable menu item for each column title.
const QString title = m_model->headerData(column, Qt::Horizontal, Qt::DisplayRole).toString();
QAction* const action = menu.addAction(title);
column_visual = header->visualIndex(column);
QAction* action = menu.addAction(m_model->getColumnDisplayName(column_visual));
action->setCheckable(true);
action->setChecked(!header->isSectionHidden(column));
// Update the GUI when the user toggles a column with left-click actions in the right-click menu on the column.
connect(action, &QAction::triggered, [this, header, column, action]() {
header->setSectionHidden(column, !action->isChecked());
// Safety check: prevent the user from hiding every single column.
ensureMinimumOneColumnVisible();
// Lastly push the new header state to settings.
action->setChecked(!m_table_view->isColumnHidden(column_visual));
connect(action, &QAction::toggled, [this, column_visual](bool enabled) {
m_table_view->setColumnHidden(column_visual, !enabled);
onTableHeaderStateChanged();
resizeTableViewColumnsToFit();
});
}
menu.addSeparator();
// Add a "panic button" that fully restores the default column layout.
// This allows users to recover without editing configuration files such as [GameListTableView] has a key with
// and variable HeaderState which you can remove the line to also do the same effect but old method is not user-friendly.
menu.addAction(tr("Reset All Columns"), this, &GameListWidget::resetTableHeaderToDefault);
menu.exec(m_table_view->viewport()->mapToGlobal(point));
menu.exec(m_table_view->mapToGlobal(point));
}
void GameListWidget::onCoverScaleChanged()
@@ -808,34 +789,6 @@ void GameListWidget::loadTableHeaderState()
header->restoreState(QByteArray::fromBase64(QByteArray::fromStdString(state_setting)));
}
void GameListWidget::ensureMinimumOneColumnVisible()
{
QHeaderView* header = m_table_view->horizontalHeader();
if (!header)
return;
bool any_visible = false;
for (int column = 0; column < GameListModel::Column_Count; column++)
{
if (column != GameListModel::Column_Cover && !header->isSectionHidden(column))
{
any_visible = true;
break;
}
}
// If absolutely everything is hidden, force the Title column to be visible.
// This ensures there is always a right-click menu on the column available to restore
// other columns or access the "Reset All Columns" option or even re-order them with drag and drop.
// By default Qt will hide everything if it sees 0 viable columns, so just enforce atleast 1 column.
// Adding ghost columns would be hacky and ugly so let's not do that.
if (!any_visible)
{
header->setSectionHidden(GameListModel::Column_Title, false);
onTableHeaderStateChanged();
}
}
void GameListWidget::onTableHeaderStateChanged()
{
QHeaderView* header = m_table_view->horizontalHeader();
@@ -871,8 +824,6 @@ void GameListWidget::applyTableHeaderDefaults()
}
// TODO (Tech): Create a button for this in the minibar. Currently unused.
// TODO (Red): Not sure if I should integrate it in the minibar for now when I made sure they can't break their order and there is a reset function now when you right-click the column.
// They could accidentaly press on it when they didn't want to, could be revised later still because people without mouses can't do it such as controller mode on the TV.
void GameListWidget::resetTableHeaderToDefault()
{
QHeaderView* header = m_table_view->horizontalHeader();
@@ -897,8 +848,6 @@ void GameListWidget::resetTableHeaderToDefault()
}
Host::SetBaseStringSettingValue("GameListTableView", "HeaderState", header->saveState().toBase64());
// This makes the columns expand to fill the window right now.
resizeTableViewColumnsToFit();
}
void GameListWidget::saveSortSettings(const int column, const Qt::SortOrder sort_order)
-1
View File
@@ -109,7 +109,6 @@ private:
void loadTableHeaderState();
void applyTableHeaderDefaults();
void resetTableHeaderToDefault();
void ensureMinimumOneColumnVisible();
void saveSortSettings(int column, Qt::SortOrder sort_order);
void listZoom(float delta);
void updateToolbar();
+12 -9
View File
@@ -52,7 +52,7 @@ void LogWindow::updateSettings()
const bool curr_enabled = Log::IsHostOutputEnabled();
const bool input_enabled = Host::GetBaseBoolSettingValue("Logging", "ShowEESIOInput");
if (g_log_window && g_log_window->m_line_input)
if(g_log_window && g_log_window->m_line_input)
{
g_log_window->m_input_widget->setVisible(input_enabled);
}
@@ -199,16 +199,18 @@ void LogWindow::createUi()
m_line_input = new QLineEdit(this);
connect(m_line_input, &QLineEdit::returnPressed, this, &LogWindow::onInputEntered);
m_local_echo_checkbox = new QCheckBox(tr("Local Echo"), this);
m_local_echo_checkbox->setChecked(m_local_echo);
connect(m_local_echo_checkbox, &QCheckBox::checkStateChanged, this, [&](Qt::CheckState state) {
connect(m_local_echo_checkbox, &QCheckBox::checkStateChanged, this, [&](Qt::CheckState state)
{
m_local_echo = state == Qt::CheckState::Checked;
});
m_newline_on_enter_checkbox = new QCheckBox(tr("Newline on send"), this);
m_newline_on_enter_checkbox->setChecked(m_newline_on_enter);
connect(m_newline_on_enter_checkbox, &QCheckBox::checkStateChanged, this, [&](Qt::CheckState state) {
connect(m_newline_on_enter_checkbox, &QCheckBox::checkStateChanged, this, [&](Qt::CheckState state)
{
m_newline_on_enter = state == Qt::CheckState::Checked;
});
@@ -241,6 +243,7 @@ void LogWindow::createUi()
vlayout->addWidget(m_text);
vlayout->addWidget(m_input_widget);
central_widget->setLayout(vlayout);
setCentralWidget(central_widget);
}
@@ -414,18 +417,18 @@ void LogWindow::onInputEntered()
if (text.isEmpty() && !m_newline_on_enter)
return;
if (m_newline_on_enter)
if(m_newline_on_enter)
text.append('\n');
std::string str = text.toUtf8().toStdString();
if (VMManager::WriteBytesToEESIORXFIFO({reinterpret_cast<const u8*>(str.data()), str.size()}))
if(VMManager::WriteBytesToEESIORXFIFO({reinterpret_cast<const u8*>(str.data()), str.size()}))
{
m_line_input->clear();
if (m_local_echo)
if(m_local_echo)
// appendMessage expects a newline to be at the end of the string
appendMessage(0, 0, m_newline_on_enter ? text : (text + '\n'));
appendMessage(0, 0, m_newline_on_enter ? text : (text + '\n') );
QTextCursor cursor(m_text->textCursor());
cursor.movePosition(QTextCursor::End);
+3 -20
View File
@@ -195,7 +195,7 @@ void EmuThread::stopFullscreenUI()
{
m_run_fullscreen_ui.store(false, std::memory_order_release);
emit onFullscreenUIStateChange(false);
// Resume and refresh background when FullscreenUI exits
QMetaObject::invokeMethod(g_main_window, "updateGameListBackground", Qt::QueuedConnection);
}
@@ -1160,7 +1160,7 @@ void Host::OpenHostFileSelectorAsync(std::string_view title, bool select_directo
if (!filters.empty())
{
filters_str.append(QStringLiteral("All File Types (%1)")
.arg(QString::fromStdString(StringUtil::JoinString(filters.begin(), filters.end(), " "))));
.arg(QString::fromStdString(StringUtil::JoinString(filters.begin(), filters.end(), " "))));
for (const std::string& filter : filters)
{
filters_str.append(
@@ -1369,6 +1369,7 @@ bool QtHost::InitializeConfig()
.arg(QString::fromStdString(error.GetDescription())));
return false;
}
}
// Setup wizard was incomplete last time?
@@ -2093,8 +2094,6 @@ void QtHost::PrintCommandLineHelp(const std::string_view progname)
std::fprintf(stderr, " -testconfig: Initializes configuration and checks version, then exits.\n");
std::fprintf(stderr, " -setupwizard: Forces initial setup wizard to run.\n");
std::fprintf(stderr, " -debugger: Open debugger and break on entry point.\n");
std::fprintf(stderr, " -turbo: Enters turbo (fast forward) mode after starting.\n");
std::fprintf(stderr, " -unlimited: Enters unlimited (fast forward) mode after starting.\n");
#ifdef ENABLE_RAINTEGRATION
std::fprintf(stderr, " -raintegration: Use RAIntegration instead of built-in achievement support.\n");
#endif
@@ -2242,16 +2241,6 @@ bool QtHost::ParseCommandLineOptions(const QStringList& args, std::shared_ptr<VM
s_cleanup_after_update = AutoUpdaterDialog::isSupported();
continue;
}
else if (CHECK_ARG(QStringLiteral("-turbo")))
{
AutoBoot(autoboot)->start_turbo = true;
continue;
}
else if (CHECK_ARG(QStringLiteral("-unlimited")))
{
AutoBoot(autoboot)->start_unlimited = true;
continue;
}
#ifdef ENABLE_RAINTEGRATION
else if (CHECK_ARG(QStringLiteral("-raintegration")))
{
@@ -2287,12 +2276,6 @@ bool QtHost::ParseCommandLineOptions(const QStringList& args, std::shared_ptr<VM
Console.Warning("Skipping autoboot due to no boot parameters.");
autoboot.reset();
}
if(autoboot && autoboot->start_turbo.value_or(false) && autoboot->start_unlimited.value_or(false))
{
Console.Warning("Both turbo and unlimited frame limit modes requested. Using unlimited.");
autoboot->start_turbo.reset();
}
// if we don't have autoboot, we definitely don't want batch mode (because that'll skip
// scanning the game list).
+58 -44
View File
@@ -1357,18 +1357,8 @@ namespace SettingWidgetBinder
widget->connect(widget, &QLineEdit::editingFinished, widget, std::move(value_changed));
}
struct DateTimeKeys
{
const char* year = nullptr;
const char* month = nullptr;
const char* day = nullptr;
const char* hour = nullptr;
const char* minute = nullptr;
const char* second = nullptr;
};
static inline void BindWidgetToDateTimeSetting(
SettingsInterface* sif, QDateTimeEdit* widget, std::string section, const DateTimeKeys& keys)
// No need to pass a section or key since this is only used once and has six keys associated with it
static inline void BindWidgetToDateTimeSetting(SettingsInterface* sif, QDateTimeEdit* widget, std::string section)
{
using Accessor = SettingAccessor<QDateTimeEdit>;
@@ -1380,36 +1370,58 @@ namespace SettingWidgetBinder
const int DEFAULT_MINUTE = 0;
const int DEFAULT_SECOND = 0;
const char* YEAR_KEY = "RtcYear";
const char* MONTH_KEY = "RtcMonth";
const char* DAY_KEY = "RtcDay";
const char* HOUR_KEY = "RtcHour";
const char* MINUTE_KEY = "RtcMinute";
const char* SECOND_KEY = "RtcSecond";
// Fetch settings from .ini
const int year_value = Host::GetBaseIntSettingValue(section.c_str(), keys.year, DEFAULT_YEAR);
const int month_value = Host::GetBaseIntSettingValue(section.c_str(), keys.month, DEFAULT_MONTH);
const int day_value = Host::GetBaseIntSettingValue(section.c_str(), keys.day, DEFAULT_DAY);
const int hour_value = Host::GetBaseIntSettingValue(section.c_str(), keys.hour, DEFAULT_HOUR);
const int minute_value = Host::GetBaseIntSettingValue(section.c_str(), keys.minute, DEFAULT_MINUTE);
const int second_value = Host::GetBaseIntSettingValue(section.c_str(), keys.second, DEFAULT_SECOND);
const s32 year_value =
Host::GetBaseIntSettingValue(section.c_str(), YEAR_KEY, static_cast<s32>(DEFAULT_YEAR));
const s32 month_value =
Host::GetBaseIntSettingValue(section.c_str(), MONTH_KEY, static_cast<s32>(DEFAULT_MONTH));
const s32 day_value =
Host::GetBaseIntSettingValue(section.c_str(), DAY_KEY, static_cast<s32>(DEFAULT_DAY));
const s32 hour_value =
Host::GetBaseIntSettingValue(section.c_str(), HOUR_KEY, static_cast<s32>(DEFAULT_HOUR));
const s32 minute_value =
Host::GetBaseIntSettingValue(section.c_str(), MINUTE_KEY, static_cast<s32>(DEFAULT_MINUTE));
const s32 second_value =
Host::GetBaseIntSettingValue(section.c_str(), SECOND_KEY, static_cast<s32>(DEFAULT_SECOND));
if (sif)
{
int sif_year_value = sif->GetIntValue(section.c_str(), keys.year, DEFAULT_YEAR);
int sif_month_value = sif->GetIntValue(section.c_str(), keys.month, DEFAULT_MONTH);
int sif_day_value = sif->GetIntValue(section.c_str(), keys.day, DEFAULT_DAY);
int sif_hour_value = sif->GetIntValue(section.c_str(), keys.hour, DEFAULT_HOUR);
int sif_minute_value = sif->GetIntValue(section.c_str(), keys.minute, DEFAULT_MINUTE);
int sif_second_value = sif->GetIntValue(section.c_str(), keys.second, DEFAULT_SECOND);
int sif_year_value = DEFAULT_YEAR;
int sif_month_value = DEFAULT_MONTH;
int sif_day_value = DEFAULT_DAY;
int sif_hour_value = DEFAULT_HOUR;
int sif_minute_value = DEFAULT_MINUTE;
int sif_second_value = DEFAULT_SECOND;
// Get Settings Interface values or default if that fails
if (!sif->GetIntValue(section.c_str(), YEAR_KEY, &sif_year_value)) { sif_year_value = DEFAULT_YEAR; }
if (!sif->GetIntValue(section.c_str(), MONTH_KEY, &sif_month_value)) { sif_month_value = DEFAULT_MONTH; }
if (!sif->GetIntValue(section.c_str(), DAY_KEY, &sif_day_value)) { sif_day_value = DEFAULT_DAY; }
if (!sif->GetIntValue(section.c_str(), HOUR_KEY, &sif_hour_value)) { sif_hour_value = DEFAULT_HOUR; }
if (!sif->GetIntValue(section.c_str(), MINUTE_KEY, &sif_minute_value)) { sif_minute_value = DEFAULT_MINUTE; }
if (!sif->GetIntValue(section.c_str(), SECOND_KEY, &sif_second_value)) { sif_second_value = DEFAULT_SECOND; }
// No need to check for valid date since QDateTime resets to minimum upon becoming invalid
QDate date(sif_year_value + YEAR_OFFSET, sif_month_value, sif_day_value);
QTime time(sif_hour_value, sif_minute_value, sif_second_value);
Accessor::setDateTime(widget, date, time);
Accessor::setDateTime(widget, QDate(static_cast<int>(sif_year_value + YEAR_OFFSET), static_cast<int>(sif_month_value), static_cast<int>(sif_day_value)),
QTime(static_cast<int>(sif_hour_value), static_cast<int>(sif_minute_value), static_cast<int>(sif_second_value)));
// Update the settings interface and reload the game settings when changed
Accessor::connectValueChanged(widget, [sif, widget, section = std::move(section), keys]() {
sif->SetIntValue(section.c_str(), keys.year, Accessor::getYear(widget) - YEAR_OFFSET);
sif->SetIntValue(section.c_str(), keys.month, Accessor::getMonth(widget));
sif->SetIntValue(section.c_str(), keys.day, Accessor::getDay(widget));
sif->SetIntValue(section.c_str(), keys.hour, Accessor::getHour(widget));
sif->SetIntValue(section.c_str(), keys.minute, Accessor::getMinute(widget));
sif->SetIntValue(section.c_str(), keys.second, Accessor::getSecond(widget));
Accessor::connectValueChanged(widget, [sif, widget, section = std::move(section), YEAR_KEY = std::move(YEAR_KEY), MONTH_KEY = std::move(MONTH_KEY),
DAY_KEY = std::move(DAY_KEY), HOUR_KEY = std::move(HOUR_KEY), MINUTE_KEY = std::move(MINUTE_KEY), SECOND_KEY = std::move(SECOND_KEY), YEAR_OFFSET = std::move(YEAR_OFFSET)]() {
sif->SetIntValue(section.c_str(), YEAR_KEY, Accessor::getYear(widget) - YEAR_OFFSET);
sif->SetIntValue(section.c_str(), MONTH_KEY, Accessor::getMonth(widget));
sif->SetIntValue(section.c_str(), DAY_KEY, Accessor::getDay(widget));
sif->SetIntValue(section.c_str(), HOUR_KEY, Accessor::getHour(widget));
sif->SetIntValue(section.c_str(), MINUTE_KEY, Accessor::getMinute(widget));
sif->SetIntValue(section.c_str(), SECOND_KEY, Accessor::getSecond(widget));
QtHost::SaveGameSettings(sif, true);
g_emu_thread->reloadGameSettings();
@@ -1419,12 +1431,13 @@ namespace SettingWidgetBinder
else
{
// No need to check for valid date since QDateTime resets to minimum upon becoming invalid
QDate date(year_value + YEAR_OFFSET, month_value, day_value);
QTime time(hour_value, minute_value, second_value);
Accessor::setDateTime(widget, date, time);
Accessor::setDateTime(widget, QDate(static_cast<int>(year_value + YEAR_OFFSET), static_cast<int>(month_value), static_cast<int>(day_value)),
QTime(static_cast<int>(hour_value), static_cast<int>(minute_value), static_cast<int>(second_value)));
// Update and apply base settings with values from widget when user changes it in UI
Accessor::connectValueChanged(widget, [widget, section = std::move(section), keys]() {
Accessor::connectValueChanged(widget, [widget, section = std::move(section), YEAR_KEY = std::move(YEAR_KEY), MONTH_KEY = std::move(MONTH_KEY),
DAY_KEY = std::move(DAY_KEY), HOUR_KEY = std::move(HOUR_KEY), MINUTE_KEY = std::move(MINUTE_KEY), SECOND_KEY = std::move(SECOND_KEY), YEAR_OFFSET = std::move(YEAR_OFFSET)]() {
const int new_year_value = Accessor::getYear(widget);
const int new_month_value = Accessor::getMonth(widget);
const int new_day_value = Accessor::getDay(widget);
@@ -1432,15 +1445,16 @@ namespace SettingWidgetBinder
const int new_minute_value = Accessor::getMinute(widget);
const int new_second_value = Accessor::getSecond(widget);
Host::SetBaseIntSettingValue(section.c_str(), keys.year, new_year_value - YEAR_OFFSET);
Host::SetBaseIntSettingValue(section.c_str(), keys.month, new_month_value);
Host::SetBaseIntSettingValue(section.c_str(), keys.day, new_day_value);
Host::SetBaseIntSettingValue(section.c_str(), keys.hour, new_hour_value);
Host::SetBaseIntSettingValue(section.c_str(), keys.minute, new_minute_value);
Host::SetBaseIntSettingValue(section.c_str(), keys.second, new_second_value);
Host::SetBaseIntSettingValue(section.c_str(), YEAR_KEY, new_year_value - YEAR_OFFSET);
Host::SetBaseIntSettingValue(section.c_str(), MONTH_KEY, new_month_value);
Host::SetBaseIntSettingValue(section.c_str(), DAY_KEY, new_day_value);
Host::SetBaseIntSettingValue(section.c_str(), HOUR_KEY, new_hour_value);
Host::SetBaseIntSettingValue(section.c_str(), MINUTE_KEY, new_minute_value);
Host::SetBaseIntSettingValue(section.c_str(), SECOND_KEY, new_second_value);
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings();
});
}
}
} // namespace SettingWidgetBinder
+5 -5
View File
@@ -133,19 +133,19 @@ void AchievementLoginDialog::processLoginResult(bool result, const QString& mess
QMessageBox::information(
this, tr("Login Successful"),
tr("Successfully logged in to RetroAchievements as %1.").arg(QString::fromStdString(username)));
m_ui.status->setText(tr("Successfully logged in as %1.").arg(QString::fromStdString(username)));
m_ui.status->setStyleSheet("color: green; font-weight: bold;");
disconnect(m_ui.buttonBox, &QDialogButtonBox::accepted, this, &AchievementLoginDialog::loginClicked);
m_login->setVisible(false);
QPushButton* dismissButton = m_ui.buttonBox->addButton(tr("&Dismiss"), QDialogButtonBox::AcceptRole);
dismissButton->setDefault(true);
dismissButton->setFocus();
connect(dismissButton, &QPushButton::clicked, this, [this]() { done(0); });
enableUI(false);
}
@@ -214,8 +214,8 @@ void AchievementSettingsWidget::updateLoginState()
StringUtil::FromChars<u64>(Host::GetBaseStringSettingValue("Achievements", "LoginTimestamp", "0")).value_or(0);
const QDateTime login_timestamp(QDateTime::fromSecsSinceEpoch(static_cast<qint64>(login_unix_timestamp)));
m_ui.loginStatus->setText(tr("Username: %1\nLogin token generated on %2.")
.arg(QString::fromStdString(username))
.arg(login_timestamp.toString(Qt::TextDate)));
.arg(QString::fromStdString(username))
.arg(login_timestamp.toString(Qt::TextDate)));
m_ui.loginButton->setText(tr("Logout"));
}
else
+9 -9
View File
@@ -262,17 +262,17 @@ void AudioSettingsWidget::updateLatencyLabel()
if (expand_buffer_ms > 0)
{
m_ui.bufferingLabel->setText(tr("Maximum Latency: %1 ms (%2 ms buffer + %3 ms expand + %4 ms output)")
.arg(config_buffer_ms + expand_buffer_ms + output_latency_ms)
.arg(config_buffer_ms)
.arg(expand_buffer_ms)
.arg(output_latency_ms));
.arg(config_buffer_ms + expand_buffer_ms + output_latency_ms)
.arg(config_buffer_ms)
.arg(expand_buffer_ms)
.arg(output_latency_ms));
}
else
{
m_ui.bufferingLabel->setText(tr("Maximum Latency: %1 ms (%2 ms buffer + %3 ms output)")
.arg(config_buffer_ms + output_latency_ms)
.arg(config_buffer_ms)
.arg(output_latency_ms));
.arg(config_buffer_ms + output_latency_ms)
.arg(config_buffer_ms)
.arg(output_latency_ms));
}
}
else
@@ -280,8 +280,8 @@ void AudioSettingsWidget::updateLatencyLabel()
if (expand_buffer_ms > 0)
{
m_ui.bufferingLabel->setText(tr("Maximum Latency: %1 ms (%2 ms expand, minimum output latency unknown)")
.arg(expand_buffer_ms + config_buffer_ms)
.arg(expand_buffer_ms));
.arg(expand_buffer_ms + config_buffer_ms)
.arg(expand_buffer_ms));
}
else
{
@@ -203,7 +203,7 @@ void ControllerBindingWidget::onAutomaticBindingClicked()
{
// we set it as data, because the device list could get invalidated while the menu is up
QAction* action;
if (dev.first.compare(dev.second, Qt::CaseInsensitive) == 0)
if(dev.first.compare(dev.second, Qt::CaseInsensitive) == 0)
action = menu.addAction(dev.first);
else
action = menu.addAction(QStringLiteral("%1: %2").arg(dev.first).arg(dev.second));
@@ -1157,7 +1157,7 @@ void USBDeviceWidget::onAutomaticBindingClicked()
{
// we set it as data, because the device list could get invalidated while the menu is up
QAction* action;
if (dev.first.compare(dev.second, Qt::CaseInsensitive) == 0)
if(dev.first.compare(dev.second, Qt::CaseInsensitive) == 0)
action = menu.addAction(dev.first);
else
action = menu.addAction(QStringLiteral("%1: %2").arg(dev.first).arg(dev.second));
@@ -88,7 +88,7 @@ ControllerGlobalSettingsWidget::~ControllerGlobalSettingsWidget() = default;
void ControllerGlobalSettingsWidget::addDeviceToList(const QString& identifier, const QString& name)
{
QListWidgetItem* item = new QListWidgetItem();
if (identifier.compare(name, Qt::CaseInsensitive) == 0)
if(identifier.compare(name,Qt::CaseInsensitive) == 0)
item->setText(identifier);
else
item->setText(QStringLiteral("%1: %2").arg(identifier).arg(name));
+12 -24
View File
@@ -89,10 +89,10 @@ void ControllerSettingsWindow::onCurrentProfileChanged(int index)
void ControllerSettingsWindow::onNewProfileClicked()
{
const QString profile_name(QInputDialog::getText(this, tr("Create Input Profile"),
tr("Custom input profiles are used to override the Shared input profile for specific games.\n"
"To apply a custom input profile to a game, go to its Game Properties, then change the 'Input Profile' on the Summary tab.\n\n"
"Enter the name for the new input profile:")));
const QString profile_name(QInputDialog::getText(this, tr("Create Input Profile"),
tr("Custom input profiles are used to override the Shared input profile for specific games.\n"
"To apply a custom input profile to a game, go to its Game Properties, then change the 'Input Profile' on the Summary tab.\n\n"
"Enter the name for the new input profile:")));
if (profile_name.isEmpty())
return;
@@ -457,16 +457,10 @@ void ControllerSettingsWindow::createWidgets()
const QString display_name(QString::fromUtf8(ci ? ci->GetLocalizedName() : "Unknown"));
QListWidgetItem* item = new QListWidgetItem();
if (mtap_enabled[port])
{
//: Controller Port is an official term from Sony. Find the official translation for your language inside the console's manual.
item->setText(tr("Controller Port %1%2\n%3").arg(port + 1).arg(s_mtap_slot_names[slot]).arg(display_name));
}
else
{
//: Controller Port is an official term from Sony. Find the official translation for your language inside the console's manual.
item->setText(tr("Controller Port %1\n%2").arg(port + 1).arg(display_name));
}
//: Controller Port is an official term from Sony. Find the official translation for your language inside the console's manual.
item->setText(mtap_enabled[port] ? (tr("Controller Port %1%2\n%3").arg(port + 1).arg(s_mtap_slot_names[slot]).arg(display_name))
//: Controller Port is an official term from Sony. Find the official translation for your language inside the console's manual.
: tr("Controller Port %1\n%2").arg(port + 1).arg(display_name));
item->setIcon(m_port_bindings[global_slot]->getIcon());
item->setData(Qt::UserRole, QVariant(global_slot));
m_ui.settingsCategory->addItem(item);
@@ -519,16 +513,10 @@ void ControllerSettingsWindow::updateListDescription(u32 global_slot, Controller
const Pad::ControllerInfo* ci = Pad::GetControllerInfo(widget->getControllerType());
const QString display_name = QString::fromUtf8(ci ? ci->GetLocalizedName() : "Unknown");
if (mtap_enabled)
{
//: Controller Port is an official term from Sony. Find the official translation for your language inside the console's manual.
item->setText(tr("Controller Port %1%2\n%3").arg(port + 1).arg(s_mtap_slot_names[slot]).arg(display_name));
}
else
{
//: Controller Port is an official term from Sony. Find the official translation for your language inside the console's manual.
item->setText(tr("Controller Port %1\n%2").arg(port + 1).arg(display_name));
}
//: Controller Port is an official term from Sony. Find the official translation for your language inside the console's manual.
item->setText(mtap_enabled ? (tr("Controller Port %1%2\n%3").arg(port + 1).arg(s_mtap_slot_names[slot]).arg(display_name))
//: Controller Port is an official term from Sony. Find the official translation for your language inside the console's manual.
: tr("Controller Port %1\n%2").arg(port + 1).arg(display_name));
item->setIcon(widget->getIcon());
break;
}
-7
View File
@@ -92,13 +92,6 @@
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QCheckBox" name="saveHWConfig">
<property name="text">
<string>Save HW Config</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
@@ -112,7 +112,6 @@ DebugSettingsWidget::DebugSettingsWidget(SettingsWindow* settings_dialog, QWidge
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_gs.saveTransferImages, "EmuCore/GS", "SaveTransferImages", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_gs.saveDrawStats, "EmuCore/GS", "SaveDrawStats", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_gs.saveFrameStats, "EmuCore/GS", "SaveFrameStats", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_gs.saveHWConfig, "EmuCore/GS", "SaveHWConfig", 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);
@@ -220,7 +219,6 @@ void DebugSettingsWidget::onDrawDumpingChanged()
m_gs.saveTransferImages->setEnabled(enabled);
m_gs.saveDrawStats->setEnabled(enabled);
m_gs.saveFrameStats->setEnabled(enabled);
m_gs.saveHWConfig->setEnabled(enabled);
m_gs.saveDrawStart->setEnabled(enabled);
m_gs.saveDrawCount->setEnabled(enabled);
m_gs.saveFrameStart->setEnabled(enabled);
@@ -47,15 +47,7 @@ EmulationSettingsWidget::EmulationSettingsWidget(SettingsWindow* settings_dialog
if (dialog()->isPerGameSettings())
{
SettingWidgetBinder::DateTimeKeys rtc_keys;
rtc_keys.year = "RtcYear";
rtc_keys.month = "RtcMonth";
rtc_keys.day = "RtcDay";
rtc_keys.hour = "RtcHour";
rtc_keys.minute = "RtcMinute";
rtc_keys.second = "RtcSecond";
SettingWidgetBinder::BindWidgetToDateTimeSetting(sif, m_ui.rtcDateTime, "EmuCore", rtc_keys);
SettingWidgetBinder::BindWidgetToDateTimeSetting(sif, m_ui.rtcDateTime, "EmuCore");
m_ui.rtcDateTime->setDateRange(QDate(2000, 1, 1), QDate(2099, 12, 31));
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.manuallySetRealTimeClock, "EmuCore", "ManuallySetRealTimeClock", false);
connect(m_ui.manuallySetRealTimeClock, &QCheckBox::checkStateChanged, this, &EmulationSettingsWidget::onManuallySetRealTimeClockChanged);
+1 -1
View File
@@ -25,7 +25,7 @@ FolderSettingsWidget::FolderSettingsWidget(SettingsWindow* settings_dialog, QWid
SettingWidgetBinder::BindWidgetToFolderSetting(sif, m_ui.videoDumpingDirectory, m_ui.videoDumpingDirectoryBrowse, m_ui.videoDumpingDirectoryOpen, m_ui.videoDumpingDirectoryReset,
"Folders", "Videos", Path::Combine(EmuFolders::DataRoot, "videos"));
dialog()->registerWidgetHelp(m_ui.organizeSnapshotsByGame, tr("Organize Snapshots by Game"), tr("Unchecked"),
tr("Saves snapshots to per-game subfolders instead of a shared folder."));
tr("Saves snapshots to per-game subfolders instead of a shared folder."));
}
FolderSettingsWidget::~FolderSettingsWidget() = default;
@@ -118,8 +118,9 @@ void GameCheatSettingsWidget::onCheatListItemHovered(const QModelIndex& index)
const QModelIndex source_index = m_model_proxy->mapToSource(index);
const QModelIndex sibling_index = source_index.siblingAtColumn(0);
QStandardItem* item = m_model->itemFromIndex(sibling_index);
if (!item || !item->isCheckable())
if (!item)
{
// No item is selected.
m_ui.appliedLabel->clear();
return;
}
+5 -5
View File
@@ -342,15 +342,15 @@ void GameSummaryWidget::onVerifyClicked()
if (!hentry->version.empty())
{
setVerifyResult(tr("Verified as %1 [%2] (Version %3).")
.arg(QString::fromStdString(hentry->name))
.arg(QString::fromStdString(hentry->serial))
.arg(QString::fromStdString(hentry->version)));
.arg(QString::fromStdString(hentry->name))
.arg(QString::fromStdString(hentry->serial))
.arg(QString::fromStdString(hentry->version)));
}
else
{
setVerifyResult(tr("Verified as %1 [%2].")
.arg(QString::fromStdString(hentry->name))
.arg(QString::fromStdString(hentry->serial)));
.arg(QString::fromStdString(hentry->name))
.arg(QString::fromStdString(hentry->serial)));
}
}
else
+1 -1
View File
@@ -11,7 +11,7 @@ class HddCreateQt : public HddCreate
{
public:
HddCreateQt(QWidget* parent);
virtual ~HddCreateQt() {}
virtual ~HddCreateQt(){};
private:
QWidget* m_parent;
@@ -197,8 +197,8 @@ InterfaceSettingsWidget::InterfaceSettingsWidget(SettingsWindow* settings_dialog
"and unpauses when you switch back."));
dialog()->registerWidgetHelp(m_ui.pauseOnControllerDisconnection, tr("Pause On Controller Disconnection"),
tr("Unchecked"), tr("Pauses the emulator when a controller with bindings is disconnected."));
dialog()->registerWidgetHelp(m_ui.promptOnStateLoadSaveFailure, tr("Prompt On State Load/Save Failure"),
tr("Checked"), tr("Displays a modal dialog when a save state load/save operation fails."));
dialog()->registerWidgetHelp(m_ui.promptOnStateLoadSaveFailure, tr("Pause On State Load/Save Failure"),
tr("Checked"), tr("Display a modal dialog when a save state load/save operation fails."));
dialog()->registerWidgetHelp(m_ui.startFullscreen, tr("Start Fullscreen"), tr("Unchecked"),
tr("Automatically switches to fullscreen mode when a game is started."));
dialog()->registerWidgetHelp(m_ui.hideMouseCursor, tr("Hide Cursor In Fullscreen"), tr("Unchecked"),
+34 -31
View File
@@ -37,39 +37,41 @@ MemoryCardConvertDialog::MemoryCardConvertDialog(QWidget* parent, QString select
m_ui.progressBar->setRange(0, 100);
m_ui.progressBar->setValue(0);
connect(m_ui.conversionTypeSelect, &QComboBox::currentIndexChanged, this, [this]() {
switch (m_srcCardInfo.type)
connect(m_ui.conversionTypeSelect, &QComboBox::currentIndexChanged, this, [this]()
{
case MemoryCardType::File:
SetType(MemoryCardType::Folder, MemoryCardFileType::Unknown, tr("Uses a folder on your PC filesystem, instead of a file. Infinite capacity, while keeping the same compatibility as an 8 MB Memory Card."));
break;
case MemoryCardType::Folder:
switch (m_ui.conversionTypeSelect->currentData().toInt())
{
case 8:
SetType(MemoryCardType::File, MemoryCardFileType::PS2_8MB, tr("A standard, 8 MB Memory Card. Most compatible, but smallest capacity."));
break;
case 16:
SetType(MemoryCardType::File, MemoryCardFileType::PS2_16MB, tr("2x larger than a standard Memory Card. May have some compatibility issues."));
break;
case 32:
SetType(MemoryCardType::File, MemoryCardFileType::PS2_32MB, tr("4x larger than a standard Memory Card. Likely to have compatibility issues."));
break;
case 64:
SetType(MemoryCardType::File, MemoryCardFileType::PS2_64MB, tr("8x larger than a standard Memory Card. Likely to have compatibility issues."));
break;
default:
//: MemoryCardType should be left as-is.
QMessageBox::critical(this, tr("Convert Memory Card Failed"), tr("Invalid MemoryCardType"));
return;
}
break;
default:
//: MemoryCardType should be left as-is.
QMessageBox::critical(this, tr("Convert Memory Card Failed"), tr("Invalid MemoryCardType"));
return;
switch (m_srcCardInfo.type)
{
case MemoryCardType::File:
SetType(MemoryCardType::Folder, MemoryCardFileType::Unknown, tr("Uses a folder on your PC filesystem, instead of a file. Infinite capacity, while keeping the same compatibility as an 8 MB Memory Card."));
break;
case MemoryCardType::Folder:
switch (m_ui.conversionTypeSelect->currentData().toInt())
{
case 8:
SetType(MemoryCardType::File, MemoryCardFileType::PS2_8MB, tr("A standard, 8 MB Memory Card. Most compatible, but smallest capacity."));
break;
case 16:
SetType(MemoryCardType::File, MemoryCardFileType::PS2_16MB, tr("2x larger than a standard Memory Card. May have some compatibility issues."));
break;
case 32:
SetType(MemoryCardType::File, MemoryCardFileType::PS2_32MB, tr("4x larger than a standard Memory Card. Likely to have compatibility issues."));
break;
case 64:
SetType(MemoryCardType::File, MemoryCardFileType::PS2_64MB, tr("8x larger than a standard Memory Card. Likely to have compatibility issues."));
break;
default:
//: MemoryCardType should be left as-is.
QMessageBox::critical(this, tr("Convert Memory Card Failed"), tr("Invalid MemoryCardType"));
return;
}
break;
default:
//: MemoryCardType should be left as-is.
QMessageBox::critical(this, tr("Convert Memory Card Failed"), tr("Invalid MemoryCardType"));
return;
}
}
});
);
disconnect(m_ui.buttonBox, &QDialogButtonBox::accepted, this, nullptr);
@@ -86,6 +88,7 @@ bool MemoryCardConvertDialog::IsSetup()
void MemoryCardConvertDialog::onStatusUpdated()
{
}
void MemoryCardConvertDialog::onProgressUpdated(int value, int range)
+1 -1
View File
@@ -64,4 +64,4 @@ namespace CardCapacity
static constexpr size_t _16_MB = 0x3e80 * 512 * 2; //(0x3fa7 - 0x49) * 2 * 512;
static constexpr size_t _32_MB = 0x7d00 * 512 * 2; //(0x7f67 - 0x89) * 2 * 512;
static constexpr size_t _64_MB = 0xfde8 * 512 * 2; //(0xfee7 - 0x0109) * 2 * 512;
} // namespace CardCapacity
}
@@ -8,7 +8,7 @@
#include "common/FileSystem.h"
MemoryCardConvertWorker::MemoryCardConvertWorker(QWidget* parent, MemoryCardType type, MemoryCardFileType fileType, const std::string& srcFileName, const std::string& destFileName)
: QtAsyncProgressThread(parent)
: QtAsyncProgressThread(parent)
{
this->type = type;
this->fileType = fileType;
+3 -2
View File
@@ -99,8 +99,9 @@ void MemoryCardCreateDialog::updateState()
void MemoryCardCreateDialog::createCard()
{
const QString name = m_ui.name->text();
const QString type = (m_fileType == MemoryCardFileType::PS1) ? QStringLiteral("mcr") : QStringLiteral("ps2");
const std::string name_str = QStringLiteral("%1.%2").arg(name).arg(type).toStdString();
const std::string name_str = QStringLiteral("%1.%2").arg(name)
.arg((m_fileType == MemoryCardFileType::PS1) ? QStringLiteral("mcr") : QStringLiteral("ps2"))
.toStdString();
if (!Path::IsValidFileName(name_str, false))
{
QMessageBox::critical(this, tr("Create Memory Card"),
+4 -26
View File
@@ -4,7 +4,6 @@
#include "ShortcutCreationDialog.h"
#include "QtHost.h"
#include <fmt/format.h>
#include <QtWidgets/QButtonGroup>
#include <QtWidgets/QFileDialog>
#include <QtWidgets/QMessageBox>
#include "common/Console.h"
@@ -41,12 +40,6 @@ ShortcutCreationDialog::ShortcutCreationDialog(QWidget* parent, const QString& t
m_ui.shortcutStartMenu->setText(tr("Application Launcher"));
#endif
QButtonGroup* buttonGroup = new QButtonGroup(this);
buttonGroup->setExclusive(true);
buttonGroup->addButton(m_ui.fastForwardTurboOption);
buttonGroup->addButton(m_ui.fastForwardUnlimitedOption);
m_ui.fastForwardTurboOption->setChecked(true);
connect(m_ui.overrideBootELFButton, &QPushButton::clicked, [&]() {
const QString path = QFileDialog::getOpenFileName(this, tr("Select ELF File"), QString(), tr("ELF Files (*.elf);;All Files (*.*)"));
if (!path.isEmpty())
@@ -67,11 +60,6 @@ ShortcutCreationDialog::ShortcutCreationDialog(QWidget* parent, const QString& t
connect(m_ui.loadStateFileToggle, &QCheckBox::toggled, m_ui.loadStateFileBrowse, &QPushButton::setEnabled);
connect(m_ui.bootOptionToggle, &QCheckBox::toggled, m_ui.bootOptionDropdown, &QPushButton::setEnabled);
connect(m_ui.fullscreenMode, &QCheckBox::toggled, m_ui.fullscreenModeDropdown, &QPushButton::setEnabled);
connect(m_ui.fastForwardOptionToggle, &QCheckBox::toggled, [this] {
const bool enabled = m_ui.fastForwardOptionToggle->isChecked();
m_ui.fastForwardTurboOption->setEnabled(enabled);
m_ui.fastForwardUnlimitedOption->setEnabled(enabled);
});
m_ui.loadStateIndex->setMaximum(VMManager::NUM_SAVE_STATE_SLOTS);
@@ -126,14 +114,6 @@ ShortcutCreationDialog::ShortcutCreationDialog(QWidget* parent, const QString& t
if (m_ui.bigPictureModeToggle->isChecked())
args.push_back("-bigpicture");
if (m_ui.fastForwardOptionToggle->isChecked())
{
if (m_ui.fastForwardTurboOption->isChecked())
args.push_back("-turbo");
else if (m_ui.fastForwardUnlimitedOption->isChecked())
args.push_back("-unlimited");
}
std::string custom_args = m_ui.customArgsInput->text().toStdString();
ShortcutCreationDialog::CreateShortcut(title.toStdString(), path.toStdString(), args, custom_args, m_ui.shortcutDesktop->isChecked());
@@ -377,6 +357,7 @@ void ShortcutCreationDialog::CreateShortcut(const std::string name, const std::s
{
executable_path = "flatpak run net.pcsx2.PCSX2";
icon_name = "net.pcsx2.PCSX2";
}
else
{
@@ -414,12 +395,9 @@ void ShortcutCreationDialog::CreateShortcut(const std::string name, const std::s
"Type=Application\n"
"Terminal=false\n"
"StartupWMClass=PCSX2\n"
"Exec=" +
final_args + "\n" +
"Name=" +
clean_name + "\n" +
"Icon=" +
icon_name + "\n" +
"Exec=" + final_args + "\n"
"Name=" + clean_name + "\n"
"Icon=" + icon_name + "\n"
"Categories=Game;Emulator;\n";
std::string_view sv(file_content);
+88 -119
View File
@@ -20,38 +20,28 @@
<string/>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="12" column="0" colspan="4">
<widget class="QGroupBox" name="customArgsGroup">
<property name="title">
<string/>
<item row="7" column="0">
<widget class="QLabel" name="displayOptionLabel">
<property name="text">
<string>Display Options</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="overrideBootELFToggle">
<property name="text">
<string>Override boot ELF:</string>
</property>
</widget>
</item>
<item row="11" column="0">
<widget class="QLabel" name="customArgsLabel">
<property name="text">
<string>Custom Arguments</string>
</property>
<property name="buddy">
<cstring>customArgsInput</cstring>
</property>
<layout class="QGridLayout" name="customArgsGrid">
<item row="1" column="0">
<widget class="QLineEdit" name="customArgsInput"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="customArgsInstruction">
<property name="text">
<string>You may add additional (space-separated) &lt;a href=&quot;https://pcsx2.net/docs/advanced/cli/&quot;&gt;custom arguments&lt;/a&gt; that are not listed above here:</string>
</property>
<property name="textFormat">
<enum>Qt::TextFormat::RichText</enum>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::TextInteractionFlag::TextBrowserInteraction</set>
</property>
<property name="buddy">
<cstring>customArgsInput</cstring>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="8" column="0" colspan="4">
@@ -94,10 +84,34 @@
</layout>
</widget>
</item>
<item row="5" column="0">
<widget class="QCheckBox" name="fastForwardOptionToggle">
<item row="3" column="2" colspan="2">
<widget class="QLineEdit" name="gameArgs">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item row="4" column="2" colspan="2">
<widget class="QComboBox" name="bootOptionDropdown">
<property name="enabled">
<bool>false</bool>
</property>
<item>
<property name="text">
<string>Fast Boot</string>
</property>
</item>
<item>
<property name="text">
<string>Full Boot</string>
</property>
</item>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="bootOptionToggle">
<property name="text">
<string>Fast Forward:</string>
<string>Boot mode:</string>
</property>
</widget>
</item>
@@ -111,51 +125,13 @@
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="displayOptionLabel">
<property name="text">
<string>Display Options</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="bootOptionToggle">
<property name="text">
<string>Boot mode:</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="3">
<widget class="QCheckBox" name="portableModeToggle">
<property name="text">
<string>Portable Mode (Stores data in local PCSX2 directory)</string>
</property>
</widget>
</item>
<item row="3" column="2" colspan="2">
<widget class="QLineEdit" name="gameArgs">
<item row="2" column="2">
<widget class="QLineEdit" name="overrideBootELFPath">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item row="11" column="0">
<widget class="QLabel" name="customArgsLabel">
<property name="text">
<string>Custom Arguments</string>
</property>
<property name="buddy">
<cstring>customArgsInput</cstring>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="overrideBootELFToggle">
<property name="text">
<string>Override boot ELF:</string>
</property>
</widget>
</item>
<item row="10" column="0" colspan="4">
<widget class="QGroupBox" name="saveStateGroup">
<property name="title">
@@ -219,13 +195,6 @@
</layout>
</widget>
</item>
<item row="2" column="2">
<widget class="QLineEdit" name="overrideBootELFPath">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="saveStateLabel">
<property name="text">
@@ -240,45 +209,45 @@
</property>
</widget>
</item>
<item row="5" column="2" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QRadioButton" name="fastForwardTurboOption">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Turbo</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="fastForwardUnlimitedOption">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Unlimited</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="4" column="2" colspan="2">
<widget class="QComboBox" name="bootOptionDropdown">
<property name="enabled">
<bool>false</bool>
<item row="12" column="0" colspan="4">
<widget class="QGroupBox" name="customArgsGroup">
<property name="title">
<string/>
</property>
<layout class="QGridLayout" name="customArgsGrid">
<item row="1" column="0">
<widget class="QLineEdit" name="customArgsInput"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="customArgsInstruction">
<property name="text">
<string>You may add additional (space-separated) &lt;a href=&quot;https://pcsx2.net/docs/advanced/cli/&quot;&gt;custom arguments&lt;/a&gt; that are not listed above here:</string>
</property>
<property name="textFormat">
<enum>Qt::TextFormat::RichText</enum>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::TextInteractionFlag::TextBrowserInteraction</set>
</property>
<property name="buddy">
<cstring>customArgsInput</cstring>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="0" colspan="3">
<widget class="QCheckBox" name="portableModeToggle">
<property name="text">
<string>Portable Mode (Stores data in local PCSX2 directory)</string>
</property>
<item>
<property name="text">
<string>Fast Boot</string>
</property>
</item>
<item>
<property name="text">
<string>Full Boot</string>
</property>
</item>
</widget>
</item>
</layout>
+5 -6
View File
@@ -341,12 +341,11 @@ bool QtHost::DownloadMissingFont(QWidget* dialog_parent, const char* font_name,
msgbox.setWindowModality(Qt::WindowModal);
msgbox.setIcon(QMessageBox::Critical);
msgbox.setTextFormat(Qt::RichText);
msgbox.setText(
qApp->translate("MainWindow",
"The font file '%1' is required for the On-Screen Display and Big Picture Mode to show messages in your language.<br><br>"
"Do you want to download this file now? These files are usually less than 10 megabytes in size.<br><br>"
"<strong>If you do not download this file, on-screen messages will not be readable.</strong>")
.arg(QLatin1StringView(font_name)));
msgbox.setText(qApp->translate("MainWindow",
"The font file '%1' is required for the On-Screen Display and Big Picture Mode to show messages in your language.<br><br>"
"Do you want to download this file now? These files are usually less than 10 megabytes in size.<br><br>"
"<strong>If you do not download this file, on-screen messages will not be readable.</strong>")
.arg(QLatin1StringView(font_name)));
msgbox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
if (msgbox.exec() != QMessageBox::Yes)
return false;
File diff suppressed because it is too large Load Diff
-2
View File
@@ -89,7 +89,6 @@
<Manifest Include="..\pcsx2\windows\PCSX2.manifest" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="AsyncDialogs.cpp" />
<ClCompile Include="ColorPickerButton.cpp" />
<ClCompile Include="Debugger\SymbolTree\NewSymbolDialogs.cpp" />
<ClCompile Include="Debugger\SymbolTree\SymbolTreeDelegates.cpp" />
@@ -184,7 +183,6 @@
<ClCompile Include="VCRuntimeChecker.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="AsyncDialogs.h" />
<QtMoc Include="SetupWizardDialog.h" />
<QtMoc Include="Settings\InterfaceSettingsWidget.h" />
<QtMoc Include="Settings\GameListSettingsWidget.h" />
-2
View File
@@ -43,7 +43,6 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="PrecompiledHeader.cpp" />
<ClCompile Include="AsyncDialogs.cpp" />
<ClCompile Include="QtHost.cpp" />
<ClCompile Include="MainWindow.cpp" />
<ClCompile Include="$(IntDir)moc_MainWindow.cpp">
@@ -519,7 +518,6 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="PrecompiledHeader.h" />
<ClInclude Include="AsyncDialogs.h" />
<ClInclude Include="QtUtils.h" />
<ClInclude Include="SettingWidgetBinder.h" />
<ClInclude Include="Settings\HddCreateQt.h">
+55 -330
View File
@@ -143,7 +143,6 @@ namespace Achievements
static void HandleResetEvent(const rc_client_event_t* event);
static void HandleUnlockEvent(const rc_client_event_t* event);
static void HandleGameCompleteEvent(const rc_client_event_t* event);
static void HandleSubsetCompleteEvent(const rc_client_event_t* event);
static void HandleLeaderboardStartedEvent(const rc_client_event_t* event);
static void HandleLeaderboardFailedEvent(const rc_client_event_t* event);
static void HandleLeaderboardSubmittedEvent(const rc_client_event_t* event);
@@ -170,7 +169,6 @@ namespace Achievements
static void UpdateNotificationPosition();
static std::string GetAchievementBadgePath(const rc_client_achievement_t* achievement, int state);
static std::string GetSubsetBadgePath(const rc_client_subset_t* subset);
static std::string GetUserBadgePath(const std::string_view username);
static std::string GetLeaderboardUserBadgePath(const rc_client_leaderboard_entry_t* entry);
@@ -178,7 +176,6 @@ namespace Achievements
static void DrawLeaderboardListEntry(const rc_client_leaderboard_t* lboard);
static void DrawLeaderboardEntry(const rc_client_leaderboard_entry_t& entry, bool is_self, float rank_column_width,
float name_column_width, float time_column_width, float column_spacing);
static void OpenSubset(const rc_client_subset_t* subset);
static void OpenLeaderboard(const rc_client_leaderboard_t* lboard);
static void LeaderboardFetchNearbyCallback(
int result, const char* error_message, rc_client_leaderboard_entry_list_t* list, rc_client_t* client, void* callback_userdata);
@@ -186,7 +183,6 @@ namespace Achievements
int result, const char* error_message, rc_client_leaderboard_entry_list_t* list, rc_client_t* client, void* callback_userdata);
static void FetchNextLeaderboardEntries();
static void CloseLeaderboard();
static void CloseSubset();
static bool s_hardcore_mode = false;
@@ -217,11 +213,9 @@ namespace Achievements
static rc_client_async_handle_t* s_load_game_request;
static rc_client_achievement_list_t* s_achievement_list;
static rc_client_subset_list_t* s_subset_list;
static rc_client_leaderboard_list_t* s_leaderboard_list;
static std::vector<std::pair<const void*, std::string>> s_achievement_badge_paths;
static const rc_client_leaderboard_t* s_open_leaderboard = nullptr;
static const rc_client_subset_t* s_open_subset = nullptr;
static rc_client_async_handle_t* s_leaderboard_fetch_handle = nullptr;
static std::vector<rc_client_leaderboard_entry_list_t*> s_leaderboard_entry_lists;
static rc_client_leaderboard_entry_list_t* s_leaderboard_nearby_entries;
@@ -826,10 +820,6 @@ void Achievements::ClientEventHandler(const rc_client_event_t* event, rc_client_
HandleGameCompleteEvent(event);
break;
case RC_CLIENT_EVENT_SUBSET_COMPLETED:
HandleSubsetCompleteEvent(event);
break;
case RC_CLIENT_EVENT_LEADERBOARD_STARTED:
HandleLeaderboardStartedEvent(event);
break;
@@ -1221,33 +1211,6 @@ void Achievements::HandleGameCompleteEvent(const rc_client_event_t* event)
}
}
void Achievements::HandleSubsetCompleteEvent(const rc_client_event_t* event)
{
const rc_client_subset_t* subset = event->subset;
Console.WriteLn("Achievements: Subset '%s' (%u) complete", subset->title, subset->id);
UpdateGameSummary();
if (EmuConfig.Achievements.Notifications)
{
std::string title = fmt::format(TRANSLATE_FS("Achievements", "Mastered {}"), subset->title);
std::string message = fmt::format(
TRANSLATE_FS("Achievements", "{0}, {1}"),
TRANSLATE_PLURAL_STR("Achievements", "%n achievements", "Mastery popup",
s_game_summary.num_unlocked_achievements),
TRANSLATE_PLURAL_STR("Achievements", "%n points", "Mastery popup", s_game_summary.points_unlocked));
std::string badge_path = GetSubsetBadgePath(subset);
MTGS::RunOnGSThread([title = std::move(title), message = std::move(message), badge_path = std::move(badge_path)]() {
if (ImGuiManager::InitializeFullscreenUI())
{
ImGuiFullscreen::AddNotification(
"achievement_subset_mastery", GAME_COMPLETE_NOTIFICATION_TIME, std::move(title), std::move(message), std::move(badge_path));
}
});
}
}
void Achievements::HandleLeaderboardStartedEvent(const rc_client_event_t* event)
{
DevCon.WriteLn("Achievements: Leaderboard %u (%s) started", event->leaderboard->id, event->leaderboard->title);
@@ -2370,15 +2333,6 @@ bool Achievements::PrepareAchievementsWindow()
s_achievement_badge_paths = {};
if (s_subset_list)
{
rc_client_destroy_subset_list(s_subset_list);
s_subset_list = nullptr;
}
CloseSubset();
s_subset_list = rc_client_create_subset_list(s_client);
if (s_achievement_list)
rc_client_destroy_achievement_list(s_achievement_list);
s_achievement_list = rc_client_create_achievement_list(s_client, RC_CLIENT_ACHIEVEMENT_CATEGORY_CORE_AND_UNOFFICIAL,
@@ -2406,9 +2360,6 @@ void Achievements::DrawAchievementsWindow()
// ensure image downloads still happen while we're paused
Achievements::IdleUpdate();
const bool has_multiple_subsets = (s_subset_list && s_subset_list->num_subsets > 1);
bool s_sidebar_has_focus = false;
static constexpr float alpha = 0.8f;
static constexpr float heading_alpha = 0.95f;
static constexpr float heading_height_unscaled = 110.0f;
@@ -2458,7 +2409,7 @@ void Achievements::DrawAchievementsWindow()
}
const ImRect title_bb(ImVec2(left, top), ImVec2(right, top + g_large_font.second));
text.assign(s_open_subset ? s_open_subset->title : s_game_title);
text.assign(s_game_title);
if (s_hardcore_mode)
text.append(TRANSLATE_SV("Achievements", " (Hardcore Mode)"));
@@ -2470,28 +2421,18 @@ void Achievements::DrawAchievementsWindow()
ImGui::PopFont();
const ImRect summary_bb(ImVec2(left, top), ImVec2(right, top + g_medium_font.second));
UpdateGameSummary();
rc_client_user_game_summary_t display_summary = {};
const rc_client_user_game_summary_t* summary_ptr = &s_game_summary;
if (s_open_subset)
if (s_game_summary.num_core_achievements > 0)
{
rc_client_get_user_subset_summary(s_client, s_open_subset->id, &display_summary);
summary_ptr = &display_summary;
}
if (summary_ptr->num_core_achievements > 0)
{
if (summary_ptr->num_unlocked_achievements == summary_ptr->num_core_achievements)
if (s_game_summary.num_unlocked_achievements == s_game_summary.num_core_achievements)
{
text.format(TRANSLATE_FS("Achievements", "You have unlocked all achievements and earned {} points!"),
summary_ptr->points_unlocked);
s_game_summary.points_unlocked);
}
else
{
text.format(TRANSLATE_FS("Achievements", "You have unlocked {0} of {1} achievements, earning {2} of {3} possible points."),
summary_ptr->num_unlocked_achievements, summary_ptr->num_core_achievements, summary_ptr->points_unlocked,
summary_ptr->points_core);
s_game_summary.num_unlocked_achievements, s_game_summary.num_core_achievements, s_game_summary.points_unlocked,
s_game_summary.points_core);
}
}
else
@@ -2506,12 +2447,12 @@ void Achievements::DrawAchievementsWindow()
summary_bb.Min, summary_bb.Max, text.c_str(), text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f), &summary_bb);
ImGui::PopFont();
if (summary_ptr->num_core_achievements > 0)
if (s_game_summary.num_core_achievements > 0)
{
const float progress_height = ImGuiFullscreen::LayoutScale(20.0f);
const ImRect progress_bb(ImVec2(left, top), ImVec2(right, top + progress_height));
const float fraction =
static_cast<float>(summary_ptr->num_unlocked_achievements) / static_cast<float>(summary_ptr->num_core_achievements);
static_cast<float>(s_game_summary.num_unlocked_achievements) / static_cast<float>(s_game_summary.num_core_achievements);
dl->AddRectFilled(progress_bb.Min, progress_bb.Max, ImGui::GetColorU32(ImGuiFullscreen::UIPrimaryDarkColor));
dl->AddRectFilled(progress_bb.Min, ImVec2(progress_bb.Min.x + fraction * progress_bb.GetWidth(), progress_bb.Max.y),
ImGui::GetColorU32(ImGuiFullscreen::UISecondaryColor));
@@ -2532,203 +2473,68 @@ void Achievements::DrawAchievementsWindow()
ImGui::SetNextWindowBgAlpha(alpha);
const float sidebar_width = has_multiple_subsets ? LayoutScale(200.0f) : 0.0f;
if (has_multiple_subsets && !s_open_subset)
{
OpenSubset(s_subset_list->subsets[0]);
}
if (ImGuiFullscreen::BeginFullscreenWindow(
ImVec2(0.0f, heading_height),
ImVec2(display_size.x, display_size.y - heading_height - LayoutScale(ImGuiFullscreen::LAYOUT_FOOTER_HEIGHT)),
"achievements", background, 0.0f, ImVec2(0.0f, 0.0f), 0))
"achievements", background, 0.0f, ImVec2(ImGuiFullscreen::LAYOUT_MENU_WINDOW_X_PADDING, 0.0f), 0))
{
if (has_multiple_subsets)
static std::map<std::pair<u32, u32>, bool> buckets_collapsed;
static const char* bucket_names[NUM_RC_CLIENT_ACHIEVEMENT_BUCKETS] = {
TRANSLATE_NOOP("Achievements", "Unknown"),
TRANSLATE_NOOP("Achievements", "Locked"),
TRANSLATE_NOOP("Achievements", "Unlocked"),
TRANSLATE_NOOP("Achievements", "Unsupported"),
TRANSLATE_NOOP("Achievements", "Unofficial"),
TRANSLATE_NOOP("Achievements", "Recently Unlocked"),
TRANSLATE_NOOP("Achievements", "Active Challenges"),
TRANSLATE_NOOP("Achievements", "Almost There"),
};
ImGuiFullscreen::BeginMenuButtons();
for (u32 bucket_type : {RC_CLIENT_ACHIEVEMENT_BUCKET_ACTIVE_CHALLENGE, RC_CLIENT_ACHIEVEMENT_BUCKET_RECENTLY_UNLOCKED,
RC_CLIENT_ACHIEVEMENT_BUCKET_UNLOCKED, RC_CLIENT_ACHIEVEMENT_BUCKET_ALMOST_THERE, RC_CLIENT_ACHIEVEMENT_BUCKET_LOCKED,
RC_CLIENT_ACHIEVEMENT_BUCKET_UNOFFICIAL, RC_CLIENT_ACHIEVEMENT_BUCKET_UNSUPPORTED})
{
const ImVec4 sidebar_bg(0.10f, 0.10f, 0.10f, alpha);
ImGui::PushStyleColor(ImGuiCol_ChildBg, sidebar_bg);
if (ImGui::BeginChild("subset_sidebar", ImVec2(sidebar_width, 0.0f), ImGuiChildFlags_NavFlattened, 0))
for (u32 bucket_idx = 0; bucket_idx < s_achievement_list->num_buckets; bucket_idx++)
{
ImGuiFullscreen::BeginMenuButtons();
const rc_client_achievement_bucket_t& bucket = s_achievement_list->buckets[bucket_idx];
if (bucket.bucket_type != bucket_type)
continue;
for (u32 i = 0; i < s_subset_list->num_subsets; i++)
pxAssert(bucket.bucket_type < NUM_RC_CLIENT_ACHIEVEMENT_BUCKETS);
bool& bucket_collapsed = buckets_collapsed[std::make_pair(bucket.subset_id, bucket.bucket_type)];
const char* translated_bucket_name = Host::TranslateToCString("Achievements", bucket_names[bucket.bucket_type]);
if (bucket.subset_id != 0)
{
const rc_client_subset_t* subset = s_subset_list->subsets[i];
TinyString id_str;
id_str.format("sidebar_subset_{}", subset->id);
ImRect bb;
bool visible, hovered;
ImGuiFullscreen::MenuButtonFrame(id_str, true, ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY,
&visible, &hovered, &bb.Min, &bb.Max, 0, 1.0f);
if (ImGui::IsItemHovered() || ImGui::IsItemFocused())
s_sidebar_has_focus = true;
const float padding = LayoutScale(10.0f);
const float spacing = LayoutScale(8.0f);
const float icon_size = LayoutScale(28.0f);
if (s_open_subset && s_open_subset->id == subset->id)
{
const float line_width = LayoutScale(4.0f);
const ImVec2 line_min(bb.Min.x, bb.Min.y);
const ImVec2 line_max(bb.Min.x + line_width, bb.Max.y);
ImGui::GetWindowDrawList()->AddRectFilled(line_min, line_max, IM_COL32(52, 152, 219, 255));
}
const ImVec2 icon_min(bb.Min.x + padding, bb.Min.y + (bb.Max.y - bb.Min.y - icon_size) * 0.5f);
const ImVec2 icon_max(icon_min.x + icon_size, icon_min.y + icon_size);
std::string badge_path = GetSubsetBadgePath(subset);
if (!badge_path.empty())
{
GSTexture* badge = ImGuiFullscreen::GetCachedTextureAsync(badge_path);
if (badge)
{
ImGui::GetWindowDrawList()->AddImage(reinterpret_cast<ImTextureID>(badge->GetNativeHandle()),
icon_min, icon_max, ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f), IM_COL32(255, 255, 255, 255));
}
}
const float text_x = icon_max.x + spacing;
const ImRect text_bb(ImVec2(text_x, bb.Min.y), ImVec2(bb.Max.x - padding, bb.Max.y));
ImGui::PushFont(g_medium_font.first, g_medium_font.second);
ImGui::RenderTextClipped(text_bb.Min, text_bb.Max, subset->title, nullptr, nullptr, ImVec2(0.0f, 0.5f), &text_bb);
ImGui::PopFont();
if (ImGui::IsItemClicked() || ImGui::IsItemActivated())
OpenSubset(subset);
const rc_client_subset_t* subset_info = rc_client_get_subset_info(s_client, bucket.subset_id);
bucket_collapsed ^=
ImGuiFullscreen::MenuHeadingButton(TinyString::from_format("{} - {}",
subset_info != nullptr ? subset_info->title : TRANSLATE("Achievements", "Unknown Subset"),
translated_bucket_name), bucket_collapsed ? ICON_FA_CHEVRON_DOWN : ICON_FA_CHEVRON_UP);
}
ImGuiFullscreen::EndMenuButtons();
}
ImGui::EndChild();
if (ImGui::IsItemHovered() || ImGui::IsItemFocused())
s_sidebar_has_focus = true;
ImGui::PopStyleColor();
ImGui::SameLine();
}
const float content_width = has_multiple_subsets ? (display_size.x - sidebar_width) : display_size.x;
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(ImGuiFullscreen::LAYOUT_MENU_WINDOW_X_PADDING, 0.0f));
ImGui::PushStyleColor(ImGuiCol_ChildBg, background);
ImGui::PushStyleColor(ImGuiCol_Header, ImGui::GetColorU32(ImGuiFullscreen::UIPrimaryDarkColor));
ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImGui::GetColorU32(ImGuiFullscreen::UIPrimaryColor));
ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImGui::GetColorU32(ImGuiFullscreen::UISecondaryColor));
if (ImGui::BeginChild("achievements_content", ImVec2(content_width, 0.0f), ImGuiChildFlags_NavFlattened, 0))
{
if (ImGui::IsWindowHovered() || ImGui::IsWindowFocused())
s_sidebar_has_focus = false;
static std::map<std::pair<u32, u32>, bool> buckets_collapsed;
static const char* bucket_names[NUM_RC_CLIENT_ACHIEVEMENT_BUCKETS] = {
TRANSLATE_NOOP("Achievements", "Unknown"),
TRANSLATE_NOOP("Achievements", "Locked"),
TRANSLATE_NOOP("Achievements", "Unlocked"),
TRANSLATE_NOOP("Achievements", "Unsupported"),
TRANSLATE_NOOP("Achievements", "Unofficial"),
TRANSLATE_NOOP("Achievements", "Recently Unlocked"),
TRANSLATE_NOOP("Achievements", "Active Challenges"),
TRANSLATE_NOOP("Achievements", "Almost There"),
};
ImGuiFullscreen::BeginMenuButtons();
for (u32 bucket_type : {RC_CLIENT_ACHIEVEMENT_BUCKET_ACTIVE_CHALLENGE, RC_CLIENT_ACHIEVEMENT_BUCKET_RECENTLY_UNLOCKED,
RC_CLIENT_ACHIEVEMENT_BUCKET_UNLOCKED, RC_CLIENT_ACHIEVEMENT_BUCKET_ALMOST_THERE, RC_CLIENT_ACHIEVEMENT_BUCKET_LOCKED,
RC_CLIENT_ACHIEVEMENT_BUCKET_UNOFFICIAL, RC_CLIENT_ACHIEVEMENT_BUCKET_UNSUPPORTED})
{
for (u32 bucket_idx = 0; bucket_idx < s_achievement_list->num_buckets; bucket_idx++)
else
{
const rc_client_achievement_bucket_t& bucket = s_achievement_list->buckets[bucket_idx];
if (bucket.bucket_type != bucket_type)
continue;
if (s_open_subset && bucket.subset_id != 0 && bucket.subset_id != s_open_subset->id)
continue;
pxAssert(bucket.bucket_type < NUM_RC_CLIENT_ACHIEVEMENT_BUCKETS);
bool& bucket_collapsed = buckets_collapsed[std::make_pair(bucket.subset_id, bucket.bucket_type)];
const char* translated_bucket_name = Host::TranslateToCString("Achievements", bucket_names[bucket.bucket_type]);
// Game without subsets
bucket_collapsed ^=
ImGuiFullscreen::MenuHeadingButton(translated_bucket_name,
bucket_collapsed ? ICON_FA_CHEVRON_DOWN : ICON_FA_CHEVRON_UP);
}
if (!bucket_collapsed)
{
for (u32 i = 0; i < bucket.num_achievements; i++)
DrawAchievement(bucket.achievements[i]);
}
if (!bucket_collapsed)
{
for (u32 i = 0; i < bucket.num_achievements; i++)
DrawAchievement(bucket.achievements[i]);
}
}
ImGuiFullscreen::EndMenuButtons();
}
ImGui::EndChild();
ImGui::PopStyleColor(4);
ImGui::PopStyleVar();
ImGuiFullscreen::EndMenuButtons();
}
ImGuiFullscreen::EndFullscreenWindow();
if (has_multiple_subsets)
{
if (ImGuiFullscreen::IsGamepadInputSource())
{
const bool circleOK = ImGui::GetIO().ConfigNavSwapGamepadButtons;
if (s_sidebar_has_focus)
{
ImGuiFullscreen::SetFullscreenFooterText(std::array{
std::make_pair(ICON_PF_DPAD_UP_DOWN, TRANSLATE_SV("Achievements", "Navigate Subsets")),
std::make_pair(ICON_PF_DPAD_LEFT_RIGHT, TRANSLATE_SV("Achievements", "Back to List")),
std::make_pair(circleOK ? ICON_PF_BUTTON_CIRCLE : ICON_PF_BUTTON_CROSS, TRANSLATE_SV("Achievements", "Select")),
std::make_pair(circleOK ? ICON_PF_BUTTON_CROSS : ICON_PF_BUTTON_CIRCLE, TRANSLATE_SV("Achievements", "Back")),
});
}
else
{
ImGuiFullscreen::SetFullscreenFooterText(std::array{
std::make_pair(ICON_PF_DPAD_LEFT_RIGHT, TRANSLATE_SV("Achievements", "Navigate Subsets")),
std::make_pair(ICON_PF_DPAD_UP_DOWN, TRANSLATE_SV("Achievements", "Change Selection")),
std::make_pair(circleOK ? ICON_PF_BUTTON_CROSS : ICON_PF_BUTTON_CIRCLE, TRANSLATE_SV("Achievements", "Back")),
});
}
}
else
{
if (s_sidebar_has_focus)
{
ImGuiFullscreen::SetFullscreenFooterText(std::array{
std::make_pair(ICON_PF_ARROW_UP ICON_PF_ARROW_DOWN, TRANSLATE_SV("Achievements", "Navigate Subsets")),
std::make_pair(ICON_PF_ARROW_LEFT ICON_PF_ARROW_RIGHT, TRANSLATE_SV("Achievements", "Back to List")),
std::make_pair(ICON_PF_ENTER, TRANSLATE_SV("Achievements", "Select")),
std::make_pair(ICON_PF_ESC, TRANSLATE_SV("Achievements", "Back")),
});
}
else
{
ImGuiFullscreen::SetFullscreenFooterText(std::array{
std::make_pair(ICON_PF_ARROW_LEFT ICON_PF_ARROW_RIGHT, TRANSLATE_SV("Achievements", "Navigate Subsets")),
std::make_pair(ICON_PF_ARROW_UP ICON_PF_ARROW_DOWN, TRANSLATE_SV("Achievements", "Change Selection")),
std::make_pair(ICON_PF_ESC, TRANSLATE_SV("Achievements", "Back")),
});
}
}
}
else
{
FullscreenUI::SetStandardSelectionFooterText(true);
}
FullscreenUI::SetStandardSelectionFooterText(true);
}
void Achievements::DrawAchievement(const rc_client_achievement_t* cheevo)
@@ -2804,36 +2610,23 @@ void Achievements::DrawAchievement(const rc_client_achievement_t* cheevo)
const float points_start = points_template_start + ((points_template_size.x - points_size.x) * 0.5f);
const char* right_icon_text;
const char* badge_text;
const char* badge_icon;
ImVec4 badge_color;
switch (cheevo->type)
{
case RC_CLIENT_ACHIEVEMENT_TYPE_MISSABLE:
badge_text = TRANSLATE("Achievements", "Missable");
badge_icon = ICON_PF_ACHIEVEMENTS_MISSABLE;
badge_color = ImVec4(0.78f, 0.55f, 0.30f, 1.0f);
right_icon_text = is_unlocked ? ICON_FA_LOCK_OPEN : ICON_FA_LOCK;
right_icon_text = ICON_PF_ACHIEVEMENTS_MISSABLE; // Missable
break;
case RC_CLIENT_ACHIEVEMENT_TYPE_PROGRESSION:
badge_text = TRANSLATE("Achievements", "Progression");
badge_icon = ICON_PF_ACHIEVEMENTS_PROGRESSION;
badge_color = ImVec4(0.62f, 0.48f, 0.80f, 1.0f);
right_icon_text = is_unlocked ? ICON_FA_LOCK_OPEN : ICON_FA_LOCK;
right_icon_text = ICON_PF_ACHIEVEMENTS_PROGRESSION; // Progression
break;
case RC_CLIENT_ACHIEVEMENT_TYPE_WIN:
badge_text = TRANSLATE("Achievements", "Win Condition");
badge_icon = ICON_PF_ACHIEVEMENTS_WIN;
badge_color = ImVec4(0.36f, 0.62f, 0.36f, 1.0f);
right_icon_text = is_unlocked ? ICON_FA_LOCK_OPEN : ICON_FA_LOCK;
right_icon_text = ICON_PF_ACHIEVEMENTS_WIN; // Win Condition
break;
// Just use the lock for standard achievements.
case RC_CLIENT_ACHIEVEMENT_TYPE_STANDARD:
default:
badge_text = nullptr;
badge_icon = nullptr;
right_icon_text = is_unlocked ? ICON_FA_LOCK_OPEN : ICON_FA_LOCK;
break;
}
@@ -2841,34 +2634,7 @@ void Achievements::DrawAchievement(const rc_client_achievement_t* cheevo)
const ImVec2 right_icon_size(g_large_font.first->CalcTextSizeA(g_large_font.second, FLT_MAX, 0.0f, right_icon_text));
const float text_start_x = bb.Min.x + image_size.x + LayoutScale(15.0f);
const float badge_padding = LayoutScale(6.0f);
const float icon_text_spacing = LayoutScale(4.0f);
const float badge_title_spacing = LayoutScale(6.0f);
ImVec2 badge_size = ImVec2(0.0f, 0.0f);
ImVec2 badge_icon_size = ImVec2(0.0f, 0.0f);
ImVec2 badge_text_size = ImVec2(0.0f, 0.0f);
if (badge_text && badge_icon)
{
badge_icon_size = g_medium_font.first->CalcTextSizeA(g_medium_font.second, FLT_MAX, 0.0f, badge_icon);
badge_text_size = g_medium_font.first->CalcTextSizeA(g_medium_font.second, FLT_MAX, 0.0f, badge_text);
badge_size = ImVec2(badge_icon_size.x + icon_text_spacing + badge_text_size.x + (badge_padding * 2.0f),
g_medium_font.second + badge_padding);
}
const ImVec2 title_size(g_large_font.first->CalcTextSizeA(g_large_font.second, FLT_MAX, 0.0f, cheevo->title));
const float title_text_end_x = text_start_x + title_size.x;
float title_max_x = points_start;
float badge_x = 0.0f;
if (badge_text && badge_icon)
{
const float effective_title_max_x = points_start - (badge_size.x + badge_title_spacing);
badge_x = std::min(title_text_end_x + badge_title_spacing, effective_title_max_x);
title_max_x = badge_x - badge_title_spacing;
}
const ImRect title_bb(ImVec2(text_start_x, bb.Min.y), ImVec2(title_max_x, midpoint));
const ImRect title_bb(ImVec2(text_start_x, bb.Min.y), ImVec2(points_start, midpoint));
const ImRect summary_bb(ImVec2(text_start_x, midpoint), ImVec2(points_start, midpoint + g_medium_font.second + extra_summary_height));
const ImRect points_bb(ImVec2(points_start, midpoint), bb.Max);
const ImRect lock_bb(
@@ -2879,24 +2645,6 @@ void Achievements::DrawAchievement(const rc_client_achievement_t* cheevo)
ImGui::RenderTextClipped(lock_bb.Min, lock_bb.Max, right_icon_text, nullptr, &right_icon_size, ImVec2(0.0f, 0.0f), &lock_bb);
ImGui::PopFont();
if (badge_text && badge_icon)
{
ImDrawList* dl = ImGui::GetWindowDrawList();
const ImVec2 badge_min(badge_x, bb.Min.y + ((midpoint - bb.Min.y) / 2.0f) - (badge_size.y / 2.0f));
const ImVec2 badge_max(badge_min.x + badge_size.x, badge_min.y + badge_size.y);
dl->AddRectFilled(badge_min, badge_max, ImGui::GetColorU32(badge_color), LayoutScale(3.0f));
const float icon_y = badge_min.y + ((badge_size.y - badge_icon_size.y) * 0.5f);
const float text_y = badge_min.y + ((badge_size.y - badge_text_size.y) * 0.5f);
const ImVec2 icon_pos(badge_min.x + badge_padding, icon_y);
dl->AddText(g_medium_font.first, g_medium_font.second, icon_pos, IM_COL32(255, 255, 255, 255), badge_icon);
const ImVec2 text_pos(icon_pos.x + badge_icon_size.x + icon_text_spacing, text_y);
dl->AddText(g_medium_font.first, g_medium_font.second, text_pos, IM_COL32(255, 255, 255, 255), badge_text);
}
ImGui::PushFont(g_medium_font.first, g_medium_font.second);
if (cheevo->description && summary_length > 0)
{
@@ -3538,29 +3286,6 @@ void Achievements::CloseLeaderboard()
s_open_leaderboard = nullptr;
}
std::string Achievements::GetSubsetBadgePath(const rc_client_subset_t* subset)
{
if (!subset || !subset->badge_name[0])
return {};
std::string path = Path::Combine(s_image_directory, fmt::format("subset_{}.png", subset->badge_name));
if (!path.empty() && subset->badge_url && !FileSystem::FileExists(path.c_str()))
DownloadImage(subset->badge_url, path);
return path;
}
void Achievements::OpenSubset(const rc_client_subset_t* subset)
{
Console.WriteLn("Achievements: Opening subset '%s' (%u)", subset->title, subset->id);
s_open_subset = subset;
}
void Achievements::CloseSubset()
{
s_open_subset = nullptr;
}
#ifdef ENABLE_RAINTEGRATION
#include "RA_Consoles.h"
+2 -8
View File
@@ -102,16 +102,10 @@ static void CDVD_INT(int eCycle)
// test (which will cause the exception to be handled).
static void cdvdSetIrq(uint id = (1 << Irq_CommandComplete))
{
if (!(cdvd.IntrStat & id))
{
iopIntcIrq(2);
psxSetNextBranchDelta(20);
}
else
DevCon.Warning("CDVD trying to double issue IRQ %x", id);
cdvd.IntrStat |= id;
cdvd.AbortRequested = false;
iopIntcIrq(2);
psxSetNextBranchDelta(20);
}
static int mg_BIToffset(u8* buffer)
+1 -12
View File
@@ -247,6 +247,7 @@ set(pcsx2SPU2Sources
SPU2/ADSR.cpp
SPU2/Debug.cpp
SPU2/Dma.cpp
SPU2/Mixer.cpp
SPU2/spu2.cpp
SPU2/ReadInput.cpp
SPU2/RegTable.cpp
@@ -257,7 +258,6 @@ set(pcsx2SPU2Sources
)
set(pcsx2SPU2SourcesUnshared
SPU2/Mixer.cpp
SPU2/ReverbResample.cpp
)
@@ -710,13 +710,6 @@ elseif(LINUX)
list(APPEND pcsx2USBHeaders
USB/usb-eyetoy/cam-linux.h
)
elseif(APPLE)
list(APPEND pcsx2USBSources
USB/usb-eyetoy/cam-macos.mm
)
list(APPEND pcsx2USBHeaders
USB/usb-eyetoy/cam-macos.h
)
else()
list(APPEND pcsx2USBSources
USB/usb-eyetoy/cam-noop.cpp
@@ -1250,15 +1243,11 @@ if (APPLE)
find_library(IOKIT_LIBRARY IOKit)
find_library(METAL_LIBRARY Metal)
find_library(QUARTZCORE_LIBRARY QuartzCore)
find_library(AVFOUNDATION_LIBRARY AVFoundation)
find_library(COREMEDIA_LIBRARY CoreMedia)
target_link_libraries(PCSX2_FLAGS INTERFACE
${APPKIT_LIBRARY}
${IOKIT_LIBRARY}
${METAL_LIBRARY}
${QUARTZCORE_LIBRARY}
${AVFOUNDATION_LIBRARY}
${COREMEDIA_LIBRARY}
)
endif()
+1 -2
View File
@@ -788,7 +788,6 @@ struct Pcsx2Config
SaveTransferImages : 1,
SaveDrawStats : 1,
SaveFrameStats : 1,
SaveHWConfig : 1,
DumpReplaceableTextures : 1,
DumpReplaceableMipmaps : 1,
DumpTexturesWithFMVActive : 1,
@@ -918,7 +917,7 @@ struct Pcsx2Config
bool operator!=(const GSOptions& right) const;
// Should we dump this draw/frame?
bool ShouldDump(u64 draw, int frame) const;
bool ShouldDump(int draw, int frame) const;
};
struct SPU2Options
+2 -2
View File
@@ -222,7 +222,7 @@ HANDLE TAPOpen(const std::string& device_guid)
unsigned long minor;
unsigned long debug;
} version;
DWORD version_len;
LONG version_len;
std::string device_path = USERMODEDEVICEDIR + device_guid + TAPSUFFIX;
@@ -242,7 +242,7 @@ HANDLE TAPOpen(const std::string& device_guid)
const BOOL bret = DeviceIoControl(handle.get(), TAP_IOCTL_GET_VERSION,
&version, sizeof(version),
&version, sizeof(version), &version_len, NULL);
&version, sizeof(version), (LPDWORD)&version_len, NULL);
if (bret == FALSE)
{
+2 -17
View File
@@ -9,7 +9,6 @@
#include "GS/Renderers/Common/GSDevice.h"
#include "GS/Renderers/Common/GSRenderer.h"
#include "common/AlignedMalloc.h"
#include "common/Console.h"
GSClut::GSClut(GSLocalMemory* mem)
: m_mem(mem)
@@ -410,6 +409,7 @@ void GSClut::Read32(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
}
}
m_current_gpu_clut = nullptr;
if (GSConfig.UserHacks_GPUTargetCLUTMode != GSGPUTargetCLUTMode::Disabled)
{
const bool is_4bit = (TEX0.PSM == PSMT4 || TEX0.PSM == PSMT4HL || TEX0.PSM == PSMT4HH);
@@ -440,36 +440,21 @@ void GSClut::Read32(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
GSTexture* dst = is_4bit ? m_gpu_clut4 : m_gpu_clut8;
const u32 dst_size = is_4bit ? 16 : 256;
const u32 dOffset = (TEX0.CSA & ((TEX0.CPSM == PSMCT16 || TEX0.CPSM == PSMCT16S) ? 15u : 31u)) << 4;
if (src != m_current_gpu_clut && (src != m_last_gpu_clut || m_gpu_clut_last_offset != offset))
m_gpu_clut_dirty = true;
if (!dst)
{
// allocate texture lazily
dst = g_gs_device->CreateRenderTarget(dst_size, 1, GSTexture::Format::Color, false);
is_4bit ? (m_gpu_clut4 = dst) : (m_gpu_clut8 = dst);
m_gpu_clut_dirty = true;
}
if (dst)
{
GL_PUSH("Update GPU CLUT [CBP=%04X, CPSM=%s, CBW=%u, CSA=%u, Offset=(%d,%d)]",
TEX0.CBP, GSUtil::GetPSMName(TEX0.CPSM), CBW, TEX0.CSA, offset.x, offset.y);
if (m_gpu_clut_dirty)
{
m_last_gpu_clut = src;
g_gs_device->UpdateCLUTTexture(src, scale, offset.x, offset.y, dst, dOffset, dst_size);
}
m_gpu_clut_dirty = false;
g_gs_device->UpdateCLUTTexture(src, scale, offset.x, offset.y, dst, dOffset, dst_size);
m_current_gpu_clut = dst;
m_gpu_clut_last_offset = offset;
}
return;
}
}
m_current_gpu_clut = nullptr;
}
}
+1 -12
View File
@@ -49,10 +49,6 @@ class alignas(32) GSClut final : public GSAlignedClass<32>
GSTexture* m_gpu_clut4 = nullptr;
GSTexture* m_gpu_clut8 = nullptr;
GSTexture* m_current_gpu_clut = nullptr;
GSTexture* m_last_gpu_clut = nullptr;
GSVector2i m_gpu_clut_last_offset = 0;
u64 m_gpu_clut_draw = 0;
bool m_gpu_clut_dirty = true;
typedef void (GSClut::*writeCLUT)(const GIFRegTEX0& TEX0, const GIFRegTEXCLUT& TEXCLUT);
@@ -101,14 +97,7 @@ public:
~GSClut();
__fi GSTexture* GetGPUTexture() const { return m_current_gpu_clut; }
__fi void SetGPUTextureDirty(u64 draw, GSTexture* texture)
{
if (texture == m_last_gpu_clut && draw > m_gpu_clut_draw)
{
m_gpu_clut_draw = draw;
m_gpu_clut_dirty = true;
}
}
void Reset();
bool InvalidateRange(u32 start_block, u32 end_block, bool is_draw = false);
u8 IsInvalid();
+109 -374
View File
@@ -19,9 +19,9 @@
#include <iomanip>
#include <bit>
u64 GSState::s_n = 0;
u64 GSState::s_last_transfer_draw_n = 0;
u64 GSState::s_transfer_n = 0;
int GSState::s_n = 0;
int GSState::s_last_transfer_draw_n = 0;
int GSState::s_transfer_n = 0;
static __fi bool IsAutoFlushEnabled()
{
@@ -444,7 +444,7 @@ void GSState::DumpDrawInfo(bool dump_regs, bool dump_verts, bool dump_transfers)
// Dump Register state
if (dump_regs)
{
s = GetDrawDumpPath("%05lld_context.txt", s_n);
s = GetDrawDumpPath("%05d_context.txt", s_n);
m_draw_env->Dump(s);
m_context->Dump(s);
@@ -453,14 +453,14 @@ void GSState::DumpDrawInfo(bool dump_regs, bool dump_verts, bool dump_transfers)
// Dump vertices
if (dump_verts)
{
s = GetDrawDumpPath("%05lld_vertex.txt", s_n);
s = GetDrawDumpPath("%05d_vertex.txt", s_n);
DumpVertices(s);
}
// Dump transfers
if (dump_transfers)
{
s = GetDrawDumpPath("%05lld_transfers.txt", s_n);
s = GetDrawDumpPath("%05d_transfers.txt", s_n);
DumpTransferList(s);
}
}
@@ -860,14 +860,14 @@ void GSState::DumpTransferImages()
if ((transfer.transfer_type == EEGS_TransferType::EE_to_GS) || transfer.zero_clear)
{
// clear or EE->GS: only the destination info is relevant.
filename = GetDrawDumpPath("%05lld_transfer%02d_%s_%04x_%d_%s_%d_%d_%d_%d.png",
filename = GetDrawDumpPath("%05d_transfer%02d_%s_%04x_%d_%s_%d_%d_%d_%d.png",
s_n, transfer_n++, (transfer.zero_clear ? "clear" : "EE_to_GS"), transfer.blit.DBP, transfer.blit.DBW,
GSUtil::GetPSMName(transfer.blit.DPSM), transfer.rect.x, transfer.rect.y, transfer.rect.z, transfer.rect.w);
}
else
{
// GS->GS: the source and destination info are both relevant.
filename = GetDrawDumpPath("%05lld_transfer%02d_GS_to_GS_%04x_%d_%s_%04x_%d_%s_%d_%d_%d_%d.bmp",
filename = GetDrawDumpPath("%05d_transfer%02d_GS_to_GS_%04x_%d_%s_%04x_%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);
@@ -2157,7 +2157,7 @@ void GSState::FlushPrim()
if (GSConfig.SaveDrawStats)
{
m_perfmon_draw = g_perfmon - m_perfmon_draw;
m_perfmon_draw.Dump(GetDrawDumpPath("%05lld_draw_stats.txt", s_n), GSIsHardwareRenderer());
m_perfmon_draw.Dump(GetDrawDumpPath("%05d_draw_stats.txt", s_n), GSIsHardwareRenderer());
m_perfmon_draw = g_perfmon;
}
}
@@ -2405,7 +2405,7 @@ void GSState::Write(const u8* mem, int len)
m_draw_transfers.push_back(new_transfer);
}
GL_CACHE("Write! %u ... => 0x%x W:%d F:%s (DIR %d%d), dPos(%d %d) size(%d %d) draw %lld", s_transfer_n,
GL_CACHE("Write! %u ... => 0x%x W:%d F:%s (DIR %d%d), dPos(%d %d) size(%d %d) draw %d", s_transfer_n,
blit.DBP, blit.DBW, GSUtil::GetPSMName(blit.DPSM),
m_tr.m_pos.DIRX, m_tr.m_pos.DIRY,
m_tr.x, m_tr.y, m_tr.w, m_tr.h, s_n);
@@ -2466,7 +2466,7 @@ void GSState::InitReadFIFO(u8* mem, int len)
if (GSConfig.SaveRT && GSConfig.ShouldDump(s_n, g_perfmon.GetFrame()))
{
const std::string s(GetDrawDumpPath(
"%05lld_read_%05x_%d_%s_%d_%d_%d_%d.bmp",
"%05d_read_%05x_%d_%s_%d_%d_%d_%d.bmp",
s_n, (int)m_env.BITBLTBUF.SBP, (int)m_env.BITBLTBUF.SBW, GSUtil::GetPSMName(m_env.BITBLTBUF.SPSM),
r.left, r.top, r.right, r.bottom));
@@ -2492,7 +2492,8 @@ void GSState::Read(u8* mem, int len)
if (!m_tr.Update(w, h, bpp, len))
return;
const u64 draw = s_n;
const int draw = s_n;
if (draw != s_n)
DevCon.Warning("Warning! Possible incorrect data download");
@@ -3559,7 +3560,7 @@ __forceinline bool AreTrianglesQuad(const GSVertex* RESTRICT vin, const u16* RES
return are_quad;
}
__forceinline bool AreTrianglesQuadNonAA(const GSVertex* RESTRICT vin, const u16* RESTRICT index0, const u16* RESTRICT index1)
bool GSState::AreTrianglesQuadNonAA(const GSVertex* RESTRICT vin, const u16* RESTRICT index0, const u16* RESTRICT index1)
{
u32 v0[3] = {
vin[index0[0]].XYZ.U32[0],
@@ -3753,11 +3754,12 @@ GSState::PRIM_OVERLAP GSState::GetPrimitiveOverlapDrawlistImpl(bool save_drawlis
const u16* RESTRICT index = m_index.buff;
const u32 count = m_index.tail;
const auto GetPoint = [&](int i) -> GSVector4i {
// Optimize out using indices for sprites and points; probably not much difference.
const auto GetIndex = [&](int i) {
if constexpr (primclass == GS_SPRITE_CLASS || primclass == GS_POINT_CLASS)
return GSVector4i(v[i].m[1]).upl16(); // Optimize out using the indices.
return i;
else
return GSVector4i(v[index[i]].m[1]).upl16();
return index[i];
};
// Batch prim into groups so that within each group the cumulative bboxes are non-overlapping.
@@ -3781,15 +3783,8 @@ GSState::PRIM_OVERLAP GSState::GetPrimitiveOverlapDrawlistImpl(bool save_drawlis
u32 i = 0;
u32 skip = 0; // Number of indices to skip if we have the bbox from the previous iteration.
// To cache a tristrip for the next iteration if we cannot use it in this iteration.
struct SavedTristrip {
bool saved = false;
u32 skip;
BoundingOct bbox;
} saved_tristrip;
BoundingOct all;
GSVector4i all(INT_MAX, INT_MAX, -INT_MAX, -INT_MAX);
while (i < count)
{
@@ -3797,394 +3792,149 @@ GSState::PRIM_OVERLAP GSState::GetPrimitiveOverlapDrawlistImpl(bool save_drawlis
skip = 0;
BoundingOct bbox;
GSVector4i bbox(INT_MAX, INT_MAX, -INT_MAX, -INT_MAX);
while (j < count)
{
bool got_bbox = false;
// Test overlap of two adjacent triangles give the indices of the
// shared edge and two unshared points.
const auto TrianglesOverlap = [GetPoint]
(u32 s0, u32 s1, u32 u0, u32 u1, bool& sign_out) -> bool {
// Assuming that indices 0-5 represent two triangles:
// Triangle strips: indices 1, 2 are identical to indices 3, 4. Indices 0, 5 are different.
// Triangles fans: indices 0, 2 are identical to indices 3, 4. Indices 1, 5 are different.
// Warning: this depends on how the vertices are arranged in the vertex kick.
// if that changes this detection will break.
constexpr std::array<std::array<std::array<int, 3>, 2>, 2> tri_order({
// Triangle strip expected indices.
std::array{ std::array<int, 3>{ 1, 2, 0 }, std::array<int, 3>{ 3, 4, 5 } },
const GSVector4i shared0 = GetPoint(s0);
const GSVector4i shared1 = GetPoint(s1) - shared0;
const GSVector4i unshared0 = GetPoint(u0) - shared0;
const GSVector4i unshared1 = GetPoint(u1) - shared0;
// Determine which side of the shared edge each triangle is on.
const bool sign0 = unshared0.x * shared1.y - unshared0.y * shared1.x >= 0;
const bool sign1 = unshared1.x * shared1.y - unshared1.y * shared1.x >= 0;
sign_out = sign0; // Output side of the first triangle with respect to the shared edge.
// Cross product signs comparison. If true, triangles are on same side of the shared edge.
return sign0 == sign1;
};
// Helper to detect triangles strips/fans (template 0 for strips, 1 for fans).
const auto CheckTriangleQuads = [index, count, TrianglesOverlap, GetPoint]
<int type>(u32 i, u32& skip, BoundingOct& bbox) -> bool {
// Assuming that indices 0-5 represent two triangles:
// Triangle strips: indices 1, 2 are identical to indices 3, 4. Indices 0, 5 are different.
// Triangles fans: indices 0, 2 are identical to indices 3, 4. Indices 1, 5 are different.
// Warning: this depends on how the vertices are arranged in the vertex kick.
// if that changes this detection will break.
constexpr std::array<std::array<std::array<int, 3>, 2>, 2> tri_order({
// Triangle strip expected indices.
std::array{ std::array<int, 3>{ 1, 2, 0 }, std::array<int, 3>{ 3, 4, 5 } },
// Triangle fan expected indices.
std::array{ std::array<int, 3>{ 0, 2, 1 }, std::array<int, 3>{ 3, 4, 5 } },
});
// Triangle fan expected indices.
std::array{ std::array<int, 3>{ 0, 2, 1 }, std::array<int, 3>{ 3, 4, 5 } },
});
const auto CheckTriangleQuads = [&]<int type>() {
constexpr std::array<int, 3> tri0 = tri_order[type][0];
constexpr std::array<int, 3> tri1 = tri_order[type][1];
// Check that the initial two triangles form a strip.
if (!(primclass == GS_TRIANGLE_CLASS && i + 6 <= count &&
index[i + tri0[0]] == index[i + tri1[0]] &&
index[i + tri0[1]] == index[i + tri1[1]]))
if (!got_bbox && primclass == GS_TRIANGLE_CLASS && j + 3 < count &&
index[j + tri0[0]] == index[j + tri1[0]] &&
index[j + tri0[1]] == index[j + tri1[1]])
{
return false;
}
// Get the initial triangle bbox.
bbox = GSVector4i(v[index[j + 0]].m[1]).upl16().xyxy();
bbox = bbox.runion(GSVector4i(v[index[j + 1]].m[1]).upl16().xyxy());
bbox = bbox.runion(GSVector4i(v[index[j + 2]].m[1]).upl16().xyxy());
u32 j = i;
// Get the initial triangle bbox.
bbox = BoundingOct::FromPoint(GetPoint(j + 0));
bbox = bbox.Union(GetPoint(j + 1));
bbox = bbox.Union(GetPoint(j + 2));
while (true)
{
// Check if the two triangles overlap.
[[maybe_unused]] bool sign;// ignore
if (TrianglesOverlap(j + tri1[0], j + tri1[1], j + tri0[2], j + tri1[2], sign))
while (true)
{
break;
}
// There is a shared edge between this and next triangle.
// Check if the unshared point is on opposite sides of the shared edge.
const GSVector4i shared0 = GSVector4i(v[index[j + skip + tri0[0]]].m[1]).upl16();
const GSVector4i shared1 = GSVector4i(v[index[j + skip + tri0[1]]].m[1]).upl16() - shared0;
const GSVector4i unshared0 = GSVector4i(v[index[j + skip + tri0[2]]].m[1]).upl16() - shared0;
const GSVector4i unshared1 = GSVector4i(v[index[j + skip + tri1[2]]].m[1]).upl16() - shared0;
// Corners are on opposite sides so we can assume a non-axis-aligned quad.
// Take union with the single unshared point.
bbox = bbox.Union(GetPoint(j + tri1[2]));
j += 3;
// Cross product signs comparison.
if ((unshared0.x * shared1.y - unshared0.y * shared1.x >= 0) ==
(unshared1.x * shared1.y - unshared1.y * shared1.x >= 0))
{
break; // Triangles are on same side of the shared edge so there's overlap.
}
if (!(j + 6 <= count &&
index[j + tri0[0]] == index[j + tri1[0]] &&
index[j + tri0[1]] == index[j + tri1[1]]))
{
// Cannot continue the strip/fan.
break;
// Corners are on opposite sides so we can assume a non-axis-aligned quad.
// Take union with the single unshared point.
bbox = bbox.runion(GSVector4i(v[index[j + skip + tri1[2]]].m[1]).upl16().xyxy());
skip += 3;
got_bbox = true;
if (!(j + skip + 3 < count &&
index[j + skip + tri0[0]] == index[j + skip + tri1[0]] &&
index[j + skip + tri0[1]] == index[j + skip + tri1[1]]))
{
// Cannot continue the strip/fan. Consume the last triangle and exit.
skip += 3;
break;
}
}
}
if (j == i)
{
return false; // Only a single triangle in the strip.
}
skip = j - i + 3; // Number of vertices in the loop + first triangle.
return true;
};
// Helper functions to find a common edge between two triangles and check if they overlap.
// Template parameter indicates if the triangle is at the end of the strip or beginning.
const auto MatchTriangles = [v, index, TrianglesOverlap]<bool end0, bool end1>
(u32 tri0, u32 tri1, bool& sign) -> bool {
// First check: see if the triangles are part of triangle strip/fan.
if (primclass == GS_TRIANGLE_CLASS)
{
CheckTriangleQuads.template operator()<0>(); // Check triangle strips.
CheckTriangleQuads.template operator()<1>(); // Check triangle fans.
}
// For the end triangle only consider the last edge of the triangle.
// For the start triangle only consider the first edge of the triangle.
const u32 base0 = end0 ? 1 : 0;
const u32 base1 = end1 ? 1 : 0;
for (int i0 = base0; i0 < base0 + 2; i0++)
{
for (int i1 = base1; i1 < base1 + 2; i1++)
{
if (v[index[tri0 + i0]].XYZ.U32[0] == v[index[tri1 + i1]].XYZ.U32[0])
{
// Get the index that should be shared between the adjacent triangles.
const int j0 = end0 ? (i0 == 2 ? 0 : i0 - 4) : (i0 == 0 ? 2 : i0 + 4);
const int j1 = end1 ? (i1 == 2 ? 0 : i1 - 4) : (i1 == 0 ? 2 : i1 + 4);
if (v[index[tri0 + j0]].XYZ.U32[0] != v[index[tri1 + j1]].XYZ.U32[0])
{
return false; // Edge is not shared.
}
// Get the indices that should be unshared.
const int k0 = end0 ? 3 - i0 : 1 - i0;
const int k1 = end1 ? 3 - i1 : 1 - i1;
// Get the shared edge in the order of the first strip's increasing indices.
// Consistency is important for the sign check to work correctly.
const int s0 = std::min(i0, j0);
const int t0 = std::max(i0, j0);
return !TrianglesOverlap(tri0 + s0, tri0 + t0, tri0 + k0, tri1 + k1, sign);
}
}
}
return false;
};
// Helper function to detect triangles strips and merge them together into
// a grid of triangles strips.
const auto CheckTriangleStrips = [count, CheckTriangleQuads, MatchTriangles, GetPoint]
(u32 i, u32& skip, BoundingOct& bbox_all, SavedTristrip& saved_tristrip) -> bool {
if (!(primclass == GS_TRIANGLE_CLASS && i + 6 <= count))
{
return false;
}
u32 j = i;
u32 prev_tri0; // First triangle of previous tristrip.
u32 prev_tri1; // Last triangle of previous tristrip.
bool all_small; // Whether all strips so far have 2 triangles only.
u32 n_tristrips = 0; // Number of tristrips merged so far.
// Used to make sure the tristrips are adjacent in the same direction so there's not overlap.
bool expected_sign;
// For another heuristic to determine if the tristrips are overlapping themselves.
// Stores the maximum difference in X/Y from the starting point.
GSVector4i start_pt;
GSVector4i max_delta(0, 0);
// Whether the current tristrip is oriented in the same direction as the first.
bool orientation = true;
BoundingOct bbox; // BBox of current strip.
// Check for the first tristrip in the chain.
if (saved_tristrip.saved)
{
// Have a tristrip saved from a previous iteration.
skip = saved_tristrip.skip;
bbox = saved_tristrip.bbox;
saved_tristrip.saved = false;
}
else if (!CheckTriangleQuads.template operator()<0>(j, skip, bbox))
{
return false;// Could not find a new tristrip.
}
// Initialize loop variables.
prev_tri0 = j;
prev_tri1 = j + skip - 3;
all_small = (skip <= 6);
bbox_all = bbox;
start_pt = GetPoint(prev_tri0);
n_tristrips++;
j += skip;
while (j < count)
{
if (!CheckTriangleQuads.template operator()<0>(j, skip, bbox))
{
break; // Cannot continue tristrip grid.
}
// Save the tristrip in case it can be used on the next iteration.
saved_tristrip.saved = true;
saved_tristrip.skip = skip;
saved_tristrip.bbox = bbox;
// Get first/last triangle of current tristrip.
const u32 tri0 = j;
const u32 tri1 = j + skip - 3;
all_small = all_small && (skip <= 6);
// First heuristic: check if the previous and this tristrip are part of a grid by
// checking if the first/last triangles in each strip have a common edge and do not overlap.
bool sign0, sign1; // Orientation of how the first and last triangles are adjacent.
bool flip; // Whether to flip the expected orientation because the two strips are in opposite directions.
// Check the first two vertices of first triangles and last two vertices of last triangles.
if (MatchTriangles.template operator()<false, false>(prev_tri0, tri0, sign0) &&
MatchTriangles.template operator()<true, true>(prev_tri1, tri1, sign1))
{
flip = false; // Tristrips are in the same directions.
}
else if (MatchTriangles.template operator()<false, true>(prev_tri0, tri1, sign0) &&
MatchTriangles.template operator()<true, false>(prev_tri1, tri0, sign1))
{
flip = true; // Tristrips are in opposite directions.
}
else
{
break; // Cannot continue the tristrip chain.
}
// Second heuristic: make sure the new tristrip is always on the same side as the previous one.
if (n_tristrips >= 2)
{
if (!(sign0 == expected_sign && sign1 == expected_sign))
{
break; // New tristrip is on the wrong side.
}
}
else
{
if (sign0 != sign1)
{
break; // First/last triangles are on different sides.
}
expected_sign = sign0;
}
if (flip)
{
expected_sign = !expected_sign;
orientation = !orientation;
}
// Third heuristic: for small tristrips make sure that we never move closer to
// the first tristrip in the grid. Small tristrips appears to be more likely to
// overlap themself.
const GSVector4i curr_pt = GetPoint(orientation ? tri0 : tri1 + 2);
const GSVector4i curr_delta = (curr_pt - start_pt).abs32();
// Check if we moved closer.
if (n_tristrips >= 2 && all_small)
{
if (((curr_delta <= max_delta).mask() & 0xFF) == 0xFF)
{
break; // We moved closer to the start point in both X/Y so end the merging.
}
}
// Update maximum displacement from start.
max_delta = max_delta.max_i32(curr_delta);
prev_tri0 = tri0;
prev_tri1 = tri1;
bbox_all = bbox_all.Union(bbox);
j += skip;
saved_tristrip.saved = false; // We consumed the new tristrip.
n_tristrips++;
}
skip = j - i;
return true;
};
// Helper functions to detect when two triangles form an axis-aligned quad.
const auto GetBBoxAxisAlignedTriangles = [v, index, count, GetPoint]
(u32 i, u32& skip, BoundingOct& bbox) -> bool {
if (!(primclass == GS_TRIANGLE_CLASS && i + 6 <= count))
{
return false;
}
const u32 off0 = i + 0;
const u32 off1 = i + 3;
// Second check: see if triangles form an axis-aligned quad.
if (!got_bbox && primclass == GS_TRIANGLE_CLASS && check_quads && j + 3 < count)
{
const u16* RESTRICT idx0 = &index[j + 0];
const u16* RESTRICT idx1 = &index[j + 3];
TriangleOrdering tri0;
TriangleOrdering tri1;
if (!AreTrianglesQuad<0, 0>(v, index + off0, index + off1, &tri0, &tri1))
if (AreTrianglesQuad<0, 0>(v, idx0, idx1, &tri0, &tri1))
{
return false;
}
// tri.b is right angle corner
bbox = GSVector4i(v[idx0[tri0.b]].m[1]).upl16().xyxy();
bbox = bbox.runion(GSVector4i(v[idx1[tri1.b]].m[1]).upl16().xyxy());
skip = 6;
// tri.b is right angle corner
const GSVector4i pt0 = GetPoint(off0 + tri0.b);
const GSVector4i pt1 = GetPoint(off1 + tri1.b);
bbox = BoundingOct::FromSprite(pt0, pt1);
skip = 6;
return true;
};
// Helper functions to just get the individual prim bbox.
const auto GetBBox = [GetPoint](u32 i, u32& skip, BoundingOct& bbox) -> bool {
if constexpr (primclass == GS_SPRITE_CLASS)
{
bbox = BoundingOct::FromSprite(GetPoint(i + 0), GetPoint(i + 1));
got_bbox = true;
}
else
{
bbox = BoundingOct::FromPoint(GetPoint(i + 0));
for (u32 j = 1; j < n; j++) // Unroll
{
bbox = bbox.Union(GetPoint(i + j));
}
// If we fail a quad check assume the rest are not quads since the check is relatively expensive.
check_quads = false;
}
skip = n;
return true;
};
// First check: see if the triangles are part of a triangle strip.
if (!got_bbox)
{
got_bbox = CheckTriangleStrips(j, skip, bbox, saved_tristrip);
}
// Second check: see if the triangles are part of triangle fan.
if (!got_bbox)
{
got_bbox = CheckTriangleQuads.template operator()<1>(j, skip, bbox);
}
// Third check: see if a pair of triangles are an axis-aligned quad.
// This doesn't require indices to match like the tristrip check.
if (!got_bbox && check_quads)
{
got_bbox = GetBBoxAxisAlignedTriangles(j, skip, bbox);
// If we fail a quad check assume the rest are not quads since the check is relatively expensive.
check_quads = got_bbox;
}
// Default case: just take the bbox of the prim vertices.
if (!got_bbox)
{
got_bbox = GetBBox(j, skip, bbox);
bbox = GSVector4i(v[GetIndex(j)].m[1]).upl16().xyxy();
for (int k = 1; k < n; k++) // Unroll
bbox = bbox.runion(GSVector4i(v[GetIndex(j + k)].m[1]).upl16().xyxy());
skip = n;
got_bbox = true;
}
// Avoid degenerate bbox.
bbox = bbox.FixDegenerate();
bbox = bbox.blend(bbox + GSVector4i(0, 0, 1, 1), bbox.xyxy() == bbox.zwzw());
if (all.Intersects(bbox))
if (all.rintersects(bbox))
{
overlap = PRIM_OVERLAP_YES;
break;
}
all = all.Union(bbox);
all = all.runion(bbox);
j += skip;
skip = 0;
}
if (save_drawlist)
{
m_drawlist.push_back((j - i) / n); // Prim count
}
else if (j < count)
{
return PRIM_OVERLAP_YES; // Early exit if not saving drawlist.
}
if (save_bbox)
{
m_drawlist_bbox.push_back(ProcessBBox(all.ToBBox()));
m_drawlist_bbox.push_back(ProcessBBox(all));
}
all = bbox;
i = j;
}
return overlap;
}
@@ -6362,30 +6112,15 @@ void GSState::GSPCRTCRegs::CalculateFramebufferOffset(bool scanmask, GSRegDISPFB
if (GSConfig.PCRTCAntiBlur && PCRTCSameSrc && !scanmask && abs(fb1.y - fb0.y) <= 1)
{
const bool alternating_0 = framebuffer0Reg.DBY != PCRTCDisplays[0].prevFramebufferReg.DBY;
const bool alternating_1 = framebuffer1Reg.DBY != PCRTCDisplays[1].prevFramebufferReg.DBY;
if (alternating_0 && alternating_1)
if (framebuffer0Reg.DBY != PCRTCDisplays[0].prevFramebufferReg.DBY)
{
const int index = (static_cast<u32>(PCRTCDisplays[1].framebufferRect.y) < static_cast<u32>(PCRTCDisplays[0].framebufferRect.y)) ? 0 : 1;
const int offset = PCRTCDisplays[1 - index].framebufferRect.y - PCRTCDisplays[index].framebufferRect.y;
if (std::abs(offset) <= 4)
{
PCRTCDisplays[index].framebufferRect.y += offset;
PCRTCDisplays[index].framebufferRect.w += offset;
}
PCRTCDisplays[0].framebufferRect.y = PCRTCDisplays[1].framebufferRect.y;
PCRTCDisplays[0].framebufferRect.w = PCRTCDisplays[1].framebufferRect.w;
}
else // Only one rect is alternating
else
{
const int index = alternating_1 ? 1 : 0;
const int offset = PCRTCDisplays[1 - index].framebufferRect.y - PCRTCDisplays[index].framebufferRect.y;
if (std::abs(offset) <= 4)
{
PCRTCDisplays[index].framebufferRect.y += offset;
PCRTCDisplays[index].framebufferRect.w += offset;
}
PCRTCDisplays[1].framebufferRect.y = PCRTCDisplays[0].framebufferRect.y;
PCRTCDisplays[1].framebufferRect.w = PCRTCDisplays[0].framebufferRect.w;
}
}
}
+5 -4
View File
@@ -222,7 +222,7 @@ public:
{
GIFRegBITBLTBUF blit;
GSVector4i rect;
u64 draw;
int draw;
bool zero_clear;
EEGS_TransferType transfer_type;
};
@@ -269,9 +269,9 @@ public:
GSVector4i m_r = {};
GSVector4i m_r_no_scissor = {};
static u64 s_n;
static u64 s_last_transfer_draw_n;
static u64 s_transfer_n;
static int s_n;
static int s_last_transfer_draw_n;
static int s_transfer_n;
GSPerfMon m_perfmon_frame; // Track stat across a frame.
GSPerfMon m_perfmon_draw; // Track stat across a draw.
@@ -478,6 +478,7 @@ public:
template<bool shuffle_check>
bool TrianglesAreQuadsImpl();
bool AreTrianglesQuadNonAA(const GSVertex* RESTRICT vin, const u16* RESTRICT index0, const u16* RESTRICT index1);
bool TrianglesAreQuads(bool shuffle_check = false);
template <u32 primclass>
PRIM_OVERLAP GetPrimitiveOverlapDrawlistImpl(bool save_drawlist = false, bool save_bbox = false, float bbox_scale = 1.0f);
-86
View File
@@ -76,89 +76,3 @@ public:
return GetClassVertexCount(GetPrimClass(prim));
}
};
// Class that represents an octogonal bounding area with sides at 45 degree increments.
class BoundingOct
{
private:
GSVector4i bbox0; // Standard bbox.
GSVector4i bbox1; // Bounding diamond (rotated 45 degrees axes and scaled, so (x, y) becomes (x + y, x - y)).
// Assumes that v is of the form { x, y, x, y }.
static GSVector4i Rotate45(const GSVector4i& v)
{
const GSVector4i swap = v.yxwz();
return (v + swap).blend32<0xa>(swap - v);
}
BoundingOct(const GSVector4i& bbox0, const GSVector4i& bbox1)
: bbox0(bbox0)
, bbox1(bbox1)
{
}
public:
// Initialize to null bounding area.
BoundingOct()
: bbox0(GSVector4i(INT_MAX, INT_MAX, INT_MIN, INT_MIN))
, bbox1(GSVector4i(INT_MAX, INT_MAX, INT_MIN, INT_MIN))
{
}
static BoundingOct FromPoint(GSVector4i v)
{
v = v.xyxy();
return { v, Rotate45(v) };
}
// The two inputs are assumed to be diagonally opposite to each other in an axis-aligned quad (i.e. sprite).
static BoundingOct FromSprite(GSVector4i v0, GSVector4i v1)
{
const GSVector4i min = v0.min_i32(v1);
const GSVector4i max = v0.max_i32(v1);
const GSVector4i bbox = min.upl64(max);
// Rotate45(x, y) => (x + y, x - y), we want the (min, max) result for any pair of (x, y)
// Min: (min.x + min.y, min.x - max.y)
// Max: (max.x + max.y, max.x - min.y)
const GSVector4i x = GSVector4i::cast(GSVector4::cast(min).xxxx(GSVector4::cast(max))); // Don't use bbox immediately to help the compiler optimize.
const GSVector4i y = bbox.ywwy();
return {
bbox,
(x + y).blend32<0xa>(x - y),
};
}
BoundingOct Union(GSVector4i v) const
{
v = v.xyxy();
return { bbox0.runion(v), bbox1.runion(Rotate45(v)) };
}
BoundingOct Union(const BoundingOct& other) const
{
return { bbox0.runion(other.bbox0), bbox1.runion(other.bbox1) };
}
BoundingOct UnionSprite(GSVector4i pt0, GSVector4i pt1) const
{
return Union(FromSprite(pt0, pt1));
}
bool Intersects(const BoundingOct& other) const
{
return bbox0.rintersects(other.bbox0) && bbox1.rintersects(other.bbox1);
}
BoundingOct FixDegenerate() const
{
return {
bbox0.blend(bbox0 + GSVector4i(0, 0, 1, 1), bbox0.xyxy() == bbox0.zwzw()),
bbox1.blend(bbox1 + GSVector4i(0, 0, 1, 1), bbox1.xyxy() == bbox1.zwzw()),
};
}
const GSVector4i& ToBBox()
{
return bbox0;
}
};
-30
View File
@@ -494,16 +494,6 @@ public:
return GSVector4i(_mm_packus_epi32(m, m));
}
__forceinline GSVector4i pkl32(const GSVector4i& a) const
{
return GSVector4i(_mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(m), _mm_castsi128_ps(a.m), _MM_SHUFFLE(2, 0, 2, 0))));
}
__forceinline GSVector4i pku32(const GSVector4i& a) const
{
return GSVector4i(_mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(m), _mm_castsi128_ps(a.m), _MM_SHUFFLE(3, 1, 3, 1))));
}
__forceinline GSVector4i upl8(const GSVector4i& a) const
{
return GSVector4i(_mm_unpacklo_epi8(m, a));
@@ -850,11 +840,6 @@ public:
return GSVector4i(_mm_srli_epi64(m, i));
}
__forceinline GSVector4i abs32() const
{
return GSVector4i(_mm_abs_epi32(m));
}
__forceinline GSVector4i add8(const GSVector4i& v) const
{
return GSVector4i(_mm_add_epi8(m, v.m));
@@ -870,11 +855,6 @@ public:
return GSVector4i(_mm_add_epi32(m, v.m));
}
__forceinline GSVector4i hadd32(const GSVector4i& v) const
{
return GSVector4i(_mm_hadd_epi32(m, v.m));
}
__forceinline GSVector4i adds8(const GSVector4i& v) const
{
return GSVector4i(_mm_adds_epi8(m, v.m));
@@ -915,11 +895,6 @@ public:
return GSVector4i(_mm_sub_epi32(m, v.m));
}
__forceinline GSVector4i hsub32(const GSVector4i& v) const
{
return GSVector4i(_mm_hsub_epi32(m, v.m));
}
__forceinline GSVector4i subs8(const GSVector4i& v) const
{
return GSVector4i(_mm_subs_epi8(m, v.m));
@@ -1992,11 +1967,6 @@ public:
return v ^ GSVector4i(i);
}
__forceinline friend GSVector4i operator-(const GSVector4i& v)
{
return GSVector4i(_mm_sub_epi32(_mm_setzero_si128(), v));
}
__forceinline friend GSVector4i operator~(const GSVector4i& v)
{
return v ^ (v == v);
-30
View File
@@ -506,16 +506,6 @@ public:
return GSVector4i(vreinterpretq_s32_u16(vcombine_u16(vqmovun_s32(v4s), vqmovun_s32(v4s))));
}
__forceinline GSVector4i pkl32(const GSVector4i& a) const
{
return GSVector4i(vuzp1q_u32(v4s, a.v4s));
}
__forceinline GSVector4i pku32(const GSVector4i& a) const
{
return GSVector4i(vuzp2q_u32(v4s, a.v4s));
}
__forceinline GSVector4i upl8(const GSVector4i& a) const
{
return GSVector4i(vreinterpretq_s32_s8(vzip1q_s8(vreinterpretq_s8_s32(v4s), vreinterpretq_s8_s32(a.v4s))));
@@ -817,11 +807,6 @@ public:
vreinterpretq_s32_u64(vshlq_u64(vreinterpretq_u64_s32(v4s), vnegq_s64(vreinterpretq_s64_s32(v.v4s)))));
}
__forceinline GSVector4i abs32() const
{
return GSVector4i(vabsq_s32(v4s));
}
__forceinline GSVector4i add8(const GSVector4i& v) const
{
return GSVector4i(vreinterpretq_s32_s8(vaddq_s8(vreinterpretq_s8_s32(v4s), vreinterpretq_s8_s32(v.v4s))));
@@ -837,11 +822,6 @@ public:
return GSVector4i(vaddq_s32(v4s, v.v4s));
}
__forceinline GSVector4i hadd32(const GSVector4i& v) const
{
return GSVector4i(vpaddq_s32(v4s, v.v4s));
}
__forceinline GSVector4i adds8(const GSVector4i& v) const
{
return GSVector4i(vreinterpretq_s32_s8(vqaddq_s8(vreinterpretq_s8_s32(v4s), vreinterpretq_s8_s32(v.v4s))));
@@ -886,11 +866,6 @@ public:
return GSVector4i(vsubq_s32(v4s, v.v4s));
}
__forceinline GSVector4i hsub32(const GSVector4i& v) const
{
return GSVector4i(vsubq_u32(vuzp1q_u32(v4s, v.v4s), vuzp2q_u32(v4s, v.v4s)));
}
__forceinline GSVector4i subs8(const GSVector4i& v) const
{
return GSVector4i(vreinterpretq_s32_s8(vqsubq_s8(vreinterpretq_s8_s32(v4s), vreinterpretq_s8_s32(v.v4s))));
@@ -1945,11 +1920,6 @@ public:
return v ^ GSVector4i(i);
}
__forceinline friend GSVector4i operator-(const GSVector4i& v)
{
return GSVector4i(vnegq_s32(v.v4s));
}
__forceinline friend GSVector4i operator~(const GSVector4i& v)
{
return GSVector4i(vmvnq_s32(v.v4s));
-454
View File
@@ -4,7 +4,6 @@
#include "GS/Renderers/Common/GSDevice.h"
#include "GS/GSGL.h"
#include "GS/GS.h"
#include "GS/GSUtil.h"
#include "Host.h"
#include "common/Console.h"
@@ -19,8 +18,6 @@
#include "imgui.h"
#include <algorithm>
#include <ostream>
#include <fstream>
int SetDATMShader(SetDATM datm)
{
@@ -1057,457 +1054,6 @@ bool GSHWDrawConfig::BlendState::IsEffective(ColorMaskSelector colormask) const
((colormask.key & 8u) && (src_factor_alpha != GSDevice::CONST_ONE || dst_factor_alpha != GSDevice::CONST_ZERO)));
}
std::string GSHWDrawConfig::GetTopologyName(u32 topology)
{
switch (static_cast<GSHWDrawConfig::Topology>(topology))
{
case GSHWDrawConfig::Topology::Point: return "Point";
case GSHWDrawConfig::Topology::Line: return "Line";
case GSHWDrawConfig::Topology::Triangle: return "Triangle";
default: return std::to_string(topology);
}
}
std::string GSHWDrawConfig::GetVSExpandName(u32 vsexpand)
{
switch (static_cast<GSHWDrawConfig::VSExpand>(vsexpand))
{
case GSHWDrawConfig::VSExpand::None: return "None";
case GSHWDrawConfig::VSExpand::Point: return "Point";
case GSHWDrawConfig::VSExpand::Line: return "Line";
case GSHWDrawConfig::VSExpand::Sprite: return "Sprite";
default: return std::to_string(vsexpand);
}
}
std::string GSHWDrawConfig::GetPSDateName(u32 date)
{
switch (date)
{
case 0: return "None";
case 1: return "0_pass_PrimID_init";
case 2: return "1_pass_PrimID_init";
case 3: return "PrimID_main";
case 5: return "0_pass_main";
case 6: return "1_pass_main";
default: return std::to_string(date);
}
}
std::string GSHWDrawConfig::GetPSAlphaTestName(u32 atst)
{
switch (static_cast<GSHWDrawConfig::PSAlphaTest>(atst))
{
case GSHWDrawConfig::PSAlphaTest::PS_ATST_NONE: return "NONE";
case GSHWDrawConfig::PSAlphaTest::PS_ATST_LEQUAL: return "LEQUAL";
case GSHWDrawConfig::PSAlphaTest::PS_ATST_GEQUAL: return "GEQUAL";
case GSHWDrawConfig::PSAlphaTest::PS_ATST_EQUAL: return "EQUAL";
case GSHWDrawConfig::PSAlphaTest::PS_ATST_NOTEQUAL: return "NOTEQUAL";
default: return std::to_string(atst);
};
}
std::string GSHWDrawConfig::GetPSDstFmtName(u32 dstfmt)
{
switch (dstfmt)
{
case 0: return "32bit";
case 1: return "24bit";
case 2: return "16bit";
default: return std::to_string(dstfmt);
}
}
std::string GSHWDrawConfig::GetPSDepthFmtName(u32 depthfmt)
{
switch (depthfmt)
{
case 0: return "None";
case 1: return "32bit";
case 2: return "16bit";
case 3: return "RGBA";
default: return std::to_string(depthfmt);
}
}
std::string GSHWDrawConfig::GetPSBlendABDName(u32 abd)
{
switch (abd)
{
case 0: return "Cs";
case 1: return "Cd";
case 2: return "Zero";
default: return std::to_string(abd);
}
}
std::string GSHWDrawConfig::GetPSBlendCName(u32 c)
{
switch (c)
{
case 0: return "As";
case 1: return "Ad";
case 2: return "Af";
default: return std::to_string(c);
}
}
std::string GSHWDrawConfig::GetPSBlendHWName(u32 blendhw)
{
switch (static_cast<HWBlendType>(blendhw))
{
case HWBlendType::SRC_ONE_DST_FACTOR: return "SRC_ONE_DST_FACTOR";
case HWBlendType::SRC_ALPHA_DST_FACTOR: return "SRC_ALPHA_DST_FACTOR";
case HWBlendType::SRC_DOUBLE: return "SRC_DOUBLE";
case HWBlendType::SRC_HALF_ONE_DST_FACTOR: return "SRC_HALF_ONE_DST_FACTOR";
case HWBlendType::SRC_INV_DST_BLEND_HALF: return "SRC_INV_DST_BLEND_HALF";
case HWBlendType::INV_SRC_DST_BLEND_HALF: return "INV_SRC_DST_BLEND_HALF";
default: return std::to_string(blendhw);
}
}
std::string GSHWDrawConfig::GetPSBlendMixName(u32 blendmix)
{
switch (static_cast<HWBlendType>(blendmix))
{
case HWBlendType::BMIX1_ALPHA_HIGH_ONE: return "BMIX1_ALPHA_HIGH_ONE";
case HWBlendType::BMIX1_SRC_HALF: return "BMIX1_SRC_HALF";
case HWBlendType::BMIX2_OVERFLOW: return "BMIX2_OVERFLOW";
default: return std::to_string(blendmix);
}
}
std::string GSHWDrawConfig::GetPSChannelName(u32 channel)
{
switch (channel)
{
case 0: return "None";
case 1: return "FetchRed";
case 2: return "FetchGreen";
case 3: return "FetchBlue";
case 4: return "FetchAlpha";
case 5: return "FetchRGB";
case 6: return "FetchGXBY";
default: return std::to_string(channel);
}
}
std::string GSHWDrawConfig::GetPSDitherName(u32 dither)
{
switch (dither)
{
case 0: return "None";
case 1: return "Standard";
case 2: return "ReciprocalScaled";
default: return std::to_string(dither);
}
}
std::string GSHWDrawConfig::GetSSTrilnName(u32 triln)
{
switch (static_cast<GS_MIN_FILTER>(triln))
{
case GS_MIN_FILTER::Nearest: return "Nearest";
case GS_MIN_FILTER::Linear: return "Linear";
case GS_MIN_FILTER::Nearest_Mipmap_Nearest: return "Nearest_Mipmap_Nearest";
case GS_MIN_FILTER::Nearest_Mipmap_Linear: return "Nearest_Mipmap_Linear";
case GS_MIN_FILTER::Linear_Mipmap_Nearest: return "Linear_Mipmap_Nearest";
case GS_MIN_FILTER::Linear_Mipmap_Linear: return "Linear_Mipmap_Linear";
default: return std::to_string(triln);
}
}
std::string GSHWDrawConfig::GetBlendOpName(u32 blendop)
{
switch (blendop)
{
case 0: return "ADD";
case 1: return "SUBTRACT";
case 2: return "REVERSE_SUBTRACT";
default: return std::to_string(blendop);
}
}
std::string GSHWDrawConfig::GetBlendFactorName(u32 blendfactor)
{
switch (blendfactor)
{
case 0: return "SRC_COLOR";
case 1: return "ONE_MINUS_SRC_COLOR";
case 2: return "DST_COLOR";
case 3: return "ONE_MINUS_DST_COLOR";
case 4: return "SRC1_COLOR";
case 5: return "ONE_MINUS_SRC1_COLOR";
case 6: return "SRC_ALPHA";
case 7: return "ONE_MINUS_SRC_ALPHA";
case 8: return "DST_ALPHA";
case 9: return "ONE_MINUS_DST_ALPHA";
case 10: return "SRC1_ALPHA";
case 11: return "ONE_MINUS_SRC1_ALPHA";
case 12: return "CONSTANT_COLOR";
case 13: return "ONE_MINUS_CONSTANT_COLOR";
case 14: return "ONE";
case 15: return "ZERO";
default: return std::to_string(blendfactor);
}
}
std::string GSHWDrawConfig::GetDestinationAlphaModeName(u32 datm)
{
switch (static_cast<GSHWDrawConfig::DestinationAlphaMode>(datm))
{
case GSHWDrawConfig::DestinationAlphaMode::Off: return "Off";
case GSHWDrawConfig::DestinationAlphaMode::Stencil: return "Stencil";
case GSHWDrawConfig::DestinationAlphaMode::StencilOne: return "StencilOne";
case GSHWDrawConfig::DestinationAlphaMode::PrimIDTracking: return "PrimIDTracking";
case GSHWDrawConfig::DestinationAlphaMode::Full: return "Full";
default: return std::to_string(datm);
}
}
std::string GSHWDrawConfig::GetColClipModeName(u32 ccmode)
{
switch (static_cast<GSHWDrawConfig::ColClipMode>(ccmode))
{
case GSHWDrawConfig::ColClipMode::NoModify: return "NoModify";
case GSHWDrawConfig::ColClipMode::ConvertOnly: return "ConvertOnly";
case GSHWDrawConfig::ColClipMode::ResolveOnly: return "ResolveOnly";
case GSHWDrawConfig::ColClipMode::ConvertAndResolve: return "ConvertAndResolve";
case GSHWDrawConfig::ColClipMode::EarlyResolve: return "EarlyResolve";
default: return std::to_string(ccmode);
}
}
std::string GSHWDrawConfig::GetSetDATMName(u32 datm)
{
switch (static_cast<SetDATM>(datm))
{
case SetDATM::DATM0: return "DATM0";
case SetDATM::DATM1: return "DATM1";
case SetDATM::DATM0_RTA_CORRECTION: return "DATM0_RTA_CORRECTION";
case SetDATM::DATM1_RTA_CORRECTION: return "DATM1_RTA_CORRECTION";
default: return std::to_string(datm);
};
}
static constexpr const char* INDENT = " ";
void GSHWDrawConfig::DumpPSSelector(std::ostream& out, const PSSelector& ps, const std::string& indent)
{
out.imbue(std::locale::classic()); // Disable integer separators
out << std::dec;
out << indent << "aem_fmt: " << static_cast<u32>(ps.aem_fmt) << std::endl;
out << indent << "pal_fmt: " << static_cast<u32>(ps.pal_fmt) << std::endl;
out << indent << "dst_fmt: " << static_cast<u32>(ps.dst_fmt) << " # " << GetPSDstFmtName(static_cast<u32>(ps.dst_fmt)) << std::endl;
out << indent << "depth_fmt: " << static_cast<u32>(ps.depth_fmt) << " # " << GetPSDepthFmtName(static_cast<u32>(ps.depth_fmt)) << std::endl;
out << indent << "aem: " << static_cast<u32>(ps.aem) << std::endl;
out << indent << "fba: " << static_cast<u32>(ps.fba) << std::endl;
out << indent << "fog: " << static_cast<u32>(ps.fog) << std::endl;
out << indent << "iip: " << static_cast<u32>(ps.iip) << std::endl;
out << indent << "date: " << static_cast<u32>(ps.date) << " # " << GetPSDateName(static_cast<u32>(ps.date)) << std::endl;
out << indent << "atst: " << static_cast<u32>(ps.atst) << " # " << GetPSAlphaTestName(static_cast<u32>(ps.atst)) << std::endl;
out << indent << "afail: " << static_cast<u32>(ps.afail) << " # " << GSUtil::GetAFAILName(static_cast<u32>(ps.afail)) << std::endl;
out << indent << "fst: " << static_cast<u32>(ps.fst) << std::endl;
out << indent << "tfx: " << static_cast<u32>(ps.tfx) << std::endl;
out << indent << "tcc: " << GSUtil::GetTCCName(static_cast<u32>(ps.tcc)) << std::endl;
out << indent << "wms: " << static_cast<u32>(ps.tcc) << " # " << static_cast<u32>(ps.wms) << std::endl;
out << indent << "wmt: " << static_cast<u32>(ps.wmt) << std::endl;
out << indent << "adjs: " << static_cast<u32>(ps.adjs) << std::endl;
out << indent << "adjt: " << static_cast<u32>(ps.adjt) << std::endl;
out << indent << "ltf: " << static_cast<u32>(ps.ltf) << std::endl;
out << indent << "shuffle: " << static_cast<u32>(ps.shuffle) << std::endl;
out << indent << "shuffle_same: " << static_cast<u32>(ps.shuffle_same) << std::endl;
out << indent << "real16src: " << static_cast<u32>(ps.real16src) << std::endl;
out << indent << "process_ba: " << static_cast<u32>(ps.process_ba) << std::endl;
out << indent << "process_rg: " << static_cast<u32>(ps.process_rg) << std::endl;
out << indent << "shuffle_across: " << static_cast<u32>(ps.shuffle_across) << std::endl;
out << indent << "write_rg: " << static_cast<u32>(ps.write_rg) << std::endl;
out << indent << "fbmask: " << static_cast<u32>(ps.fbmask) << std::endl;
out << indent << "blend_a: " << static_cast<u32>(ps.blend_a) << " # " << GetPSBlendABDName(static_cast<u32>(ps.blend_a)) << std::endl;
out << indent << "blend_b: " << static_cast<u32>(ps.blend_b) << " # " << GetPSBlendABDName(static_cast<u32>(ps.blend_b)) << std::endl;
out << indent << "blend_c: " << static_cast<u32>(ps.blend_c) << " # " << GetPSBlendCName(static_cast<u32>(ps.blend_c)) << std::endl;
out << indent << "blend_d: " << static_cast<u32>(ps.blend_d) << " # " << GetPSBlendABDName(static_cast<u32>(ps.blend_d)) << std::endl;
out << indent << "fixed_one_a: " << static_cast<u32>(ps.fixed_one_a) << std::endl;
out << indent << "blend_hw: " << static_cast<u32>(ps.blend_hw) << " # " << GetPSBlendHWName(static_cast<u32>(ps.blend_hw)) << std::endl;
out << indent << "a_masked: " << static_cast<u32>(ps.a_masked) << std::endl;
out << indent << "colclip_hw: " << static_cast<u32>(ps.colclip_hw) << std::endl;
out << indent << "rta_correction: " << static_cast<u32>(ps.rta_correction) << std::endl;
out << indent << "rta_source_correction: " << static_cast<u32>(ps.rta_source_correction) << std::endl;
out << indent << "colclip: " << static_cast<u32>(ps.colclip) << std::endl;
out << indent << "blend_mix: " << static_cast<u32>(ps.blend_mix) << " # " << GetPSBlendMixName(static_cast<u32>(ps.blend_mix)) << std::endl;
out << indent << "round_inv: " << static_cast<u32>(ps.round_inv) << std::endl;
out << indent << "pabe: " << static_cast<u32>(ps.pabe) << std::endl;
out << indent << "no_color: " << static_cast<u32>(ps.no_color) << std::endl;
out << indent << "no_color1: " << static_cast<u32>(ps.no_color1) << std::endl;
out << indent << "channel: " << static_cast<u32>(ps.channel) << " # " << GetPSChannelName(static_cast<u32>(ps.channel)) << std::endl;
out << indent << "channel_fb: " << static_cast<u32>(ps.channel_fb) << std::endl;
out << indent << "dither: " << static_cast<u32>(ps.dither) << " # " << GetPSDitherName(static_cast<u32>(ps.dither)) << std::endl;
out << indent << "dither_adjust: " << static_cast<u32>(ps.dither_adjust) << std::endl;
out << indent << "zclamp: " << static_cast<u32>(ps.zclamp) << std::endl;
out << indent << "tcoffsethack: " << static_cast<u32>(ps.tcoffsethack) << std::endl;
out << indent << "urban_chaos_hle: " << static_cast<u32>(ps.urban_chaos_hle) << std::endl;
out << indent << "tales_of_abyss_hle: " << static_cast<u32>(ps.tales_of_abyss_hle) << std::endl;
out << indent << "tex_is_fb: " << static_cast<u32>(ps.tex_is_fb) << std::endl;
out << indent << "automatic_lod: " << static_cast<u32>(ps.automatic_lod) << std::endl;
out << indent << "manual_lod: " << static_cast<u32>(ps.manual_lod) << std::endl;
out << indent << "point_sampler: " << static_cast<u32>(ps.point_sampler) << std::endl;
out << indent << "region_rect: " << static_cast<u32>(ps.region_rect) << std::endl;
out << indent << "scanmsk: " << static_cast<u32>(ps.scanmsk) << " # " << GSUtil::GetSCANMSKName(static_cast<u32>(ps.scanmsk)) << std::endl;
}
void GSHWDrawConfig::DumpVSSelector(std::ostream& out, const VSSelector& vs, const std::string& indent)
{
out.imbue(std::locale::classic()); // Disable integer separators
out << std::dec;
out << indent << "fst: " << static_cast<u32>(vs.fst) << std::endl;
out << indent << "tme: " << static_cast<u32>(vs.tme) << std::endl;
out << indent << "iip: " << static_cast<u32>(vs.iip) << std::endl;
out << indent << "point_size: " << static_cast<u32>(vs.point_size) << std::endl;
out << indent << "expand: " << static_cast<u32>(vs.expand) << " # " << GetVSExpandName(static_cast<u32>(vs.expand)) << std::endl;
}
void GSHWDrawConfig::DumpBlendState(std::ostream& out, const BlendState& bs, const std::string& indent)
{
out.imbue(std::locale::classic()); // Disable integer separators
out << std::dec;
out << indent << "enable: " << static_cast<u32>(bs.enable) << std::endl;
out << indent << "constant_enable: " << static_cast<u32>(bs.constant_enable) << std::endl;
out << indent << "op: " << static_cast<u32>(bs.op) << " # " << GetBlendOpName(static_cast<u32>(bs.op)) << std::endl;
out << indent << "src_factor: " << static_cast<u32>(bs.src_factor) << " # " << GetBlendFactorName(static_cast<u32>(bs.src_factor)) << std::endl;
out << indent << "dst_factor: " << static_cast<u32>(bs.dst_factor) << " # " << GetBlendFactorName(static_cast<u32>(bs.dst_factor)) << std::endl;
out << indent << "src_factor_alpha: " << static_cast<u32>(bs.src_factor_alpha) << " # " << GetBlendFactorName(static_cast<u32>(bs.src_factor_alpha)) << std::endl;
out << indent << "dst_factor_alpha: " << static_cast<u32>(bs.dst_factor_alpha) << " # " << GetBlendFactorName(static_cast<u32>(bs.dst_factor_alpha)) << std::endl;
out << indent << "constant: " << static_cast<u32>(bs.constant) << std::endl;
}
void GSHWDrawConfig::DumpDepthStencilSelctor(std::ostream& out, const DepthStencilSelector& dss, const std::string& indent)
{
out.imbue(std::locale::classic()); // Disable integer separators
out << std::dec;
out << indent << "ztst: " << static_cast<u32>(dss.ztst) << " # " << GSUtil::GetZTSTName(static_cast<u32>(dss.ztst)) << std::endl;
out << indent << "zwe: " << static_cast<u32>(dss.zwe) << std::endl;
out << indent << "date: " << static_cast<u32>(dss.date) << std::endl;
out << indent << "date_one: " << static_cast<u32>(dss.date_one) << std::endl;
}
void GSHWDrawConfig::DumpSamplerSelector(std::ostream& out, const SamplerSelector& ss, const std::string& indent)
{
out.imbue(std::locale::classic()); // Disable integer separators
out << std::dec;
out << indent << "tau: " << static_cast<u32>(ss.tau) << std::endl;
out << indent << "tav: " << static_cast<u32>(ss.tav) << std::endl;
out << indent << "biln: " << static_cast<u32>(ss.biln) << std::endl;
out << indent << "triln: " << static_cast<u32>(ss.triln) << " # " << GetSSTrilnName(static_cast<u32>(ss.triln)) << std::endl;
out << indent << "aniso: " << static_cast<u32>(ss.aniso) << std::endl;
out << indent << "lodclamp: " << static_cast<u32>(ss.lodclamp) << std::endl;
}
void GSHWDrawConfig::DumpAlphaPass(std::ostream& out, const AlphaPass& ap, const std::string& indent)
{
out.imbue(std::locale::classic()); // Disable integer separators
out << std::dec;
out << indent << "enable: " << static_cast<u32>(ap.enable) << std::endl;
out << indent << "require_one_barrier: " << static_cast<u32>(ap.require_one_barrier) << std::endl;
out << indent << "require_full_barrier: " << static_cast<u32>(ap.require_full_barrier) << std::endl;
out << indent << "colormask: " << std::showbase << std::hex << static_cast<u32>(ap.colormask.wrgba) << std::dec << std::endl;
out << indent << "ps_aref: " << static_cast<u32>(ap.ps_aref) << std::endl;
out << indent << "ps:" << std::endl;
DumpPSSelector(out, ap.ps, indent + INDENT);
out << indent << "dss:" << std::endl;
DumpDepthStencilSelctor(out, ap.depth, indent + INDENT);
}
void GSHWDrawConfig::DumpBlendMultipass(std::ostream& out, const BlendMultiPass& bmp, const std::string& indent)
{
out.imbue(std::locale::classic()); // Disable integer separators
out << std::dec;
out << indent << "enable: " << static_cast<u32>(bmp.enable) << std::endl;
out << indent << "no_color1: " << static_cast<u32>(bmp.no_color1) << std::endl;
out << indent << "blend_hw: " << static_cast<u32>(bmp.blend_hw) << " # " << GetPSBlendHWName(static_cast<u32>(bmp.blend_hw)) << std::endl;
out << indent << "dither: " << static_cast<u32>(bmp.dither) << std::endl;
out << indent << "blend:" << std::endl;
DumpBlendState(out, bmp.blend, indent + INDENT);
}
void GSHWDrawConfig::DumpConfig(std::ostream& out, const GSHWDrawConfig& conf,
bool ps, bool vs, bool bs, bool dss, bool ss, bool asp, bool bmp)
{
out.imbue(std::locale::classic()); // Disable integer separators
out << std::dec;
out << "topology: " << static_cast<u32>(conf.topology) << " # " << GetTopologyName(static_cast<u32>(conf.topology)) << std::endl;
out << "require_one_barrier: " << static_cast<u32>(conf.require_one_barrier) << std::endl;
out << "require_full_barrier: " << static_cast<u32>(conf.require_full_barrier) << std::endl;
out << "destination_alpha: " << static_cast<u32>(conf.destination_alpha) << " # " << GetDestinationAlphaModeName(static_cast<u32>(conf.destination_alpha)) << std::endl;
out << "datm: " << static_cast<u32>(conf.datm) << " # " << GetSetDATMName(static_cast<u32>(conf.datm)) << std::endl;
out << "line_expand: " << conf.line_expand << std::endl;
out << "colormask: " << std::hex << std::showbase << static_cast<u32>(conf.colormask.wrgba) << std::dec << std::endl;
if (ps)
{
out << "ps:" << std::endl;
DumpPSSelector(out, conf.ps, INDENT);
}
if (vs)
{
out << "vs:" << std::endl;
DumpVSSelector(out, conf.vs, INDENT);
}
if (bs)
{
out << "blend:" << std::endl;
DumpBlendState(out, conf.blend, INDENT);
}
if (ss)
{
out << "sampler:" << std::endl;
DumpSamplerSelector(out, conf.sampler, INDENT);
}
if (dss)
{
out << "depth:" << std::endl;
DumpDepthStencilSelctor(out, conf.depth, INDENT);
}
if (asp)
{
out << "alpha_second_pass:" << std::endl;
DumpAlphaPass(out, conf.alpha_second_pass, INDENT);
}
if (bmp)
{
out << "blend_multi_pass:" << std::endl;
DumpBlendMultipass(out, conf.blend_multi_pass, INDENT);
}
}
void GSHWDrawConfig::DumpConfig(const std::string& fn, const GSHWDrawConfig& conf,
bool ps, bool vs, bool bs, bool dss, bool ss, bool asp, bool bmp)
{
std::ofstream file(fn);
if (!file.is_open())
return;
DumpConfig(file, conf, ps, vs, bs, dss, ss, asp, bmp);
}
// clang-format off
// Maps PS2 blend modes to our best approximation of them with PC hardware
-41
View File
@@ -328,16 +328,6 @@ struct alignas(16) GSHWDrawConfig
};
static_assert(sizeof(VSSelector) == 1, "VSSelector is a single byte");
#pragma pack(pop)
enum PSAlphaTest
{
PS_ATST_NONE = 0,
PS_ATST_LEQUAL = 1,
PS_ATST_GEQUAL = 2,
PS_ATST_EQUAL = 3,
PS_ATST_NOTEQUAL = 4
};
#pragma pack(push, 4)
struct PSSelector
{
@@ -790,37 +780,6 @@ struct alignas(16) GSHWDrawConfig
ColClipMode colclip_mode;
GIFRegFRAME colclip_frame;
GSVector4i colclip_update_area; ///< Area in the framebuffer which colclip will modify;
// Dumping
static std::string GetTopologyName(u32 topology);
static std::string GetVSExpandName(u32 vsexpand);
static std::string GetPSAlphaTestName(u32 dstfmt);
static std::string GetPSDstFmtName(u32 dstfmt);
static std::string GetPSDepthFmtName(u32 depthfmt);
static std::string GetPSBlendABDName(u32 abd);
static std::string GetPSBlendCName(u32 c);
static std::string GetPSBlendHWName(u32 blendhw);
static std::string GetPSBlendMixName(u32 blendmix);
static std::string GetPSDitherName(u32 dither);
static std::string GetPSChannelName(u32 channel);
static std::string GetSSTrilnName(u32 triln);
static std::string GetBlendOpName(u32 blendop);
static std::string GetBlendFactorName(u32 blendfactor);
static std::string GetDestinationAlphaModeName(u32 datm);
static std::string GetPSDateName(u32 date);
static std::string GetColClipModeName(u32 ccmode);
static std::string GetSetDATMName(u32 setdatm);
static void DumpPSSelector(std::ostream& out, const PSSelector& ps, const std::string& indent = "");
static void DumpVSSelector(std::ostream& out, const VSSelector& vs, const std::string& indent = "");
static void DumpBlendState(std::ostream& out, const BlendState& bs, const std::string& indent = "");
static void DumpDepthStencilSelctor(std::ostream& out, const DepthStencilSelector& ds, const std::string& indent = "");
static void DumpSamplerSelector(std::ostream& out, const SamplerSelector& ss, const std::string& indent = "");
static void DumpAlphaPass(std::ostream& out, const AlphaPass& ap, const std::string& indent = "");
static void DumpBlendMultipass(std::ostream& out, const BlendMultiPass& bmp, const std::string& indent = "");
static void DumpConfig(std::ostream& out, const GSHWDrawConfig& conf,
bool ps = true, bool vs = true, bool bs = true, bool dss = true, bool ss = true, bool asp = true, bool bmp = true);
static void DumpConfig(const std::string& fn, const GSHWDrawConfig& conf,
bool ps = true, bool vs = true, bool bs = true, bool dss = true, bool ss = true, bool asp = true, bool bmp = true);
};
static inline u32 GetExpansionFactor(GSHWDrawConfig::VSExpand expand)
+2 -2
View File
@@ -575,7 +575,7 @@ void GSRenderer::VSync(u32 field, bool registers_written, bool idle_frame)
{
if (GSConfig.SaveInfo)
{
DumpGSPrivRegs(*m_regs, GetDrawDumpPath("%05lld_f%05lld_vsync_gs_reg.txt", s_n, g_perfmon.GetFrame()));
DumpGSPrivRegs(*m_regs, GetDrawDumpPath("%05d_f%05lld_vsync_gs_reg.txt", s_n, g_perfmon.GetFrame()));
DumpDrawInfo(false, false, true);
}
@@ -586,7 +586,7 @@ void GSRenderer::VSync(u32 field, bool registers_written, bool idle_frame)
if (GSConfig.SaveFrameStats)
{
m_perfmon_frame = g_perfmon - m_perfmon_frame;
m_perfmon_frame.Dump(GetDrawDumpPath("%05lld_f%05lld_frame_stats.txt", s_n, g_perfmon.GetFrame()), GSIsHardwareRenderer());
m_perfmon_frame.Dump(GetDrawDumpPath("%05d_f%05lld_frame_stats.txt", s_n, g_perfmon.GetFrame()), GSIsHardwareRenderer());
m_perfmon_frame = g_perfmon;
}
}
+2 -2
View File
@@ -21,8 +21,8 @@ private:
u32 m_skipped_duplicate_frames = 0;
// Tracking draw counters for idle frame detection.
u64 m_last_draw_n = 0;
u64 m_last_transfer_n = 0;
int m_last_draw_n = 0;
int m_last_transfer_n = 0;
protected:
GSVector2i m_real_size{0, 0};
+23
View File
@@ -17,6 +17,7 @@
#include "IconsFontAwesome.h"
#include <appmodel.h>
#include <array>
#include <d3d11.h>
#include <d3d12.h>
@@ -381,7 +382,29 @@ GSRendererType D3D::GetPreferredRenderer()
return device;
};
#ifdef ENABLE_VULKAN
static constexpr auto check_for_mapping_layers = []() {
PCWSTR familyName = L"Microsoft.D3DMappingLayers_8wekyb3d8bbwe";
UINT32 numPackages = 0, bufferLength = 0;
const DWORD error = GetPackagesByPackageFamily(familyName, &numPackages, nullptr, &bufferLength, nullptr);
if (error == ERROR_INSUFFICIENT_BUFFER || numPackages > 0)
{
Host::AddIconOSDMessage("VKDriverUnsupported", ICON_FA_TV,
TRANSLATE_STR("GS",
"Your system has the \"OpenCL, OpenGL, and Vulkan Compatibility Pack\" installed.\n"
"This Vulkan driver crashes PCSX2 on some GPUs.\n"
"To use the Vulkan renderer, you should remove this app package."),
Host::OSD_WARNING_DURATION);
return true;
}
return false;
};
static constexpr auto check_vulkan_supported = []() {
// Don't try to enumerate Vulkan devices if the DX12 Vulkan driver is present.
// It crashes on AMD GPUs.
if (check_for_mapping_layers())
return false;
if (!GSDeviceVK::EnumerateGPUs().empty())
return true;
+9 -17
View File
@@ -1413,7 +1413,7 @@ void GSDevice11::PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture*
cb.SetSource(sRect, sTex->GetSize());
cb.SetTarget(dRect, ds);
cb.SetTime(shaderTime);
UpdateSubresource(m_present.ps_cb.get(), &cb, &m_present.cb_uniforms, sizeof(cb));
m_ctx->UpdateSubresource(m_present.ps_cb.get(), 0, nullptr, &cb, 0, 0);
// om
@@ -1465,7 +1465,7 @@ void GSDevice11::UpdateCLUTTexture(GSTexture* sTex, float sScale, u32 offsetX, u
u32 pad2;
};
const Uniforms cb = {sScale, {}, offsetX, offsetY, dOffset, 0};
UpdateSubresource(m_merge.cb.get(), &cb, &m_merge.cb_uniforms, sizeof(cb));
m_ctx->UpdateSubresource(m_merge.cb.get(), 0, nullptr, &cb, 0, 0);
const GSVector4 dRect(0, 0, dSize, 1);
const ShaderConvert shader = (dSize == 16) ? ShaderConvert::CLUT_4 : ShaderConvert::CLUT_8;
@@ -1484,7 +1484,7 @@ void GSDevice11::ConvertToIndexedTexture(GSTexture* sTex, float sScale, u32 offs
};
const Uniforms cb = {sScale, {}, SBW, DBW, SPSM, 0};
UpdateSubresource(m_merge.cb.get(), &cb, &m_merge.cb_uniforms, sizeof(cb));
m_ctx->UpdateSubresource(m_merge.cb.get(), 0, nullptr, &cb, 0, 0);
const GSVector4 dRect(0, 0, dTex->GetWidth(), dTex->GetHeight());
const ShaderConvert shader = ((SPSM & 0xE) == 0) ? ShaderConvert::RGBA_TO_8I : ShaderConvert::RGB5A1_TO_8I;
@@ -1505,7 +1505,7 @@ void GSDevice11::FilteredDownsampleTexture(GSTexture* sTex, GSTexture* dTex, u32
const Uniforms cb = {
static_cast<float>(downsample_factor * downsample_factor), (GSConfig.UserHacks_NativeScaling > GSNativeScaling::Aggressive) ? 2.0f : 1.0f, {}, clamp_min, static_cast<int>(downsample_factor), 0};
UpdateSubresource(m_merge.cb.get(), &cb, &m_merge.cb_uniforms, sizeof(cb));
m_ctx->UpdateSubresource(m_merge.cb.get(), 0, nullptr, &cb, 0, 0);
const ShaderConvert shader = ShaderConvert::DOWNSAMPLE_COPY;
DoStretchRect(sTex, GSVector4::zero(), dTex, dRect, m_convert.ps[static_cast<int>(shader)].get(), m_merge.cb.get(), nullptr, false);
@@ -1599,6 +1599,7 @@ void GSDevice11::DoMultiStretchRects(const MultiStretchRect* rects, u32 num_rect
DrawIndexedPrimitive();
}
void GSDevice11::DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE, const GSRegEXTBUF& EXTBUF, u32 c, const bool linear)
{
const GSVector4 full_r(0.0f, 0.0f, 1.0f, 1.0f);
@@ -1615,7 +1616,7 @@ void GSDevice11::DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex,
if (feedback_write_2 || feedback_write_1 || sTex[0])
{
const MergeConstantBuffer cb = {GSVector4::unorm8(c), EXTBUF.EMODA, EXTBUF.EMODC};
UpdateSubresource(m_merge.cb.get(), &cb, &m_merge.cb_uniforms, sizeof(cb));
m_ctx->UpdateSubresource(m_merge.cb.get(), 0, nullptr, &cb, 0, 0);
}
if (sTex[1] && (PMODE.SLBG == 0 || feedback_write_2_but_blend_bg))
@@ -1651,7 +1652,7 @@ void GSDevice11::DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex,
void GSDevice11::DoInterlace(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderInterlace shader, bool linear, const InterlaceConstantBuffer& cb)
{
UpdateSubresource(m_interlace.cb.get(), &cb, &m_interlace.cb_uniforms, sizeof(cb));
m_ctx->UpdateSubresource(m_interlace.cb.get(), 0, nullptr, &cb, 0, 0);
DoStretchRect(sTex, sRect, dTex, dRect, m_interlace.ps[static_cast<int>(shader)].get(), m_interlace.cb.get(), linear);
}
@@ -1689,7 +1690,7 @@ void GSDevice11::DoShadeBoost(GSTexture* sTex, GSTexture* dTex, const float para
const GSVector4 sRect(0, 0, 1, 1);
const GSVector4 dRect(0, 0, s.x, s.y);
UpdateSubresource(m_shadeboost.cb.get(), params, &m_shadeboost.cb_uniforms, sizeof(float) * 4);
m_ctx->UpdateSubresource(m_shadeboost.cb.get(), 0, nullptr, params, 0, 0);
DoStretchRect(sTex, sRect, dTex, dRect, m_shadeboost.ps.get(), m_shadeboost.cb.get(), false);
}
@@ -2112,7 +2113,7 @@ void GSDevice11::RenderImGui()
};
// clang-format on
UpdateSubresource(m_imgui.vs_cb.get(), ortho_projection, &m_imgui.vs_cb_uniforms, sizeof(ortho_projection));
m_ctx->UpdateSubresource(m_imgui.vs_cb.get(), 0, nullptr, ortho_projection, 0, 0);
const UINT vb_stride = sizeof(ImDrawVert);
const UINT vb_offset = 0;
@@ -2611,15 +2612,6 @@ void GSDevice11::SetScissor(const GSVector4i& scissor)
}
}
void GSDevice11::UpdateSubresource(ID3D11Buffer* buffer, const void* cb_uniforms, void* cached_cb_uniforms, size_t cb_uniforms_size)
{
if (memcmp(cb_uniforms, cached_cb_uniforms, cb_uniforms_size) != 0)
{
memcpy(cached_cb_uniforms, cb_uniforms, cb_uniforms_size);
m_ctx->UpdateSubresource(buffer, 0, nullptr, cached_cb_uniforms, 0, 0);
}
}
void GSDevice11::ShaderMacro::AddMacro(const char* n, int d)
{
AddMacro(n, std::to_string(d));
-7
View File
@@ -191,7 +191,6 @@ private:
wil::com_ptr_nothrow<ID3D11VertexShader> vs;
wil::com_ptr_nothrow<ID3D11PixelShader> ps[static_cast<int>(PresentShader::Count)];
wil::com_ptr_nothrow<ID3D11Buffer> ps_cb;
DisplayConstantBuffer cb_uniforms;
} m_present;
struct
@@ -199,14 +198,12 @@ private:
wil::com_ptr_nothrow<ID3D11PixelShader> ps[2];
wil::com_ptr_nothrow<ID3D11Buffer> cb;
wil::com_ptr_nothrow<ID3D11BlendState> bs;
MergeConstantBuffer cb_uniforms;
} m_merge;
struct
{
wil::com_ptr_nothrow<ID3D11PixelShader> ps[NUM_INTERLACE_SHADERS];
wil::com_ptr_nothrow<ID3D11Buffer> cb;
InterlaceConstantBuffer cb_uniforms;
} m_interlace;
wil::com_ptr_nothrow<ID3D11PixelShader> m_fxaa_ps;
@@ -215,7 +212,6 @@ private:
{
wil::com_ptr_nothrow<ID3D11PixelShader> ps;
wil::com_ptr_nothrow<ID3D11Buffer> cb;
float cb_uniforms[4];
} m_shadeboost;
struct
@@ -239,7 +235,6 @@ private:
wil::com_ptr_nothrow<ID3D11PixelShader> ps;
wil::com_ptr_nothrow<ID3D11BlendState> bs;
wil::com_ptr_nothrow<ID3D11Buffer> vs_cb;
GSVector4 vs_cb_uniforms[4];
} m_imgui;
// Shaders...
@@ -347,8 +342,6 @@ public:
void SetViewport(const GSVector2i& viewport);
void SetScissor(const GSVector4i& scissor);
void UpdateSubresource(ID3D11Buffer* buffer, const void* cb_uniforms, void* cached_cb_uniforms, size_t cb_uniforms_size);
void SetupVS(VSSelector sel, const GSHWDrawConfig::VSConstantBuffer* cb);
void SetupPS(const PSSelector& sel, const GSHWDrawConfig::PSConstantBuffer* cb, PSSamplerSelector ssel);
void SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, u8 afix);
@@ -197,18 +197,20 @@ bool D3D12StreamBuffer::WaitForClearSpace(u32 num_bytes)
u32 new_space = 0;
u32 new_gpu_position = 0;
auto iter = std::find_if(m_tracked_fences.begin(), m_tracked_fences.end(), [&, this](const auto& iter) {
auto iter = m_tracked_fences.begin();
for (; iter != m_tracked_fences.end(); ++iter)
{
// Would this fence bring us in line with the GPU?
// This is the "last resort" case, where a command buffer execution has been forced
// after no additional data has been written to it, so we can assume that after the
// fence has been signaled the entire buffer is now consumed.
u32 gpu_position = iter.second;
u32 gpu_position = iter->second;
if (m_current_offset == gpu_position)
{
new_offset = 0;
new_space = m_size;
new_gpu_position = 0;
return true;
break;
}
// Assuming that we wait for this fence, are we allocating in front of the GPU?
@@ -223,7 +225,7 @@ bool D3D12StreamBuffer::WaitForClearSpace(u32 num_bytes)
new_offset = m_current_offset;
new_space = m_size - m_current_offset;
new_gpu_position = gpu_position;
return true;
break;
}
// We can wrap around to the start, behind the GPU, if there is enough space.
@@ -234,7 +236,7 @@ bool D3D12StreamBuffer::WaitForClearSpace(u32 num_bytes)
new_offset = 0;
new_space = gpu_position;
new_gpu_position = gpu_position;
return true;
break;
}
}
else
@@ -249,11 +251,10 @@ bool D3D12StreamBuffer::WaitForClearSpace(u32 num_bytes)
new_offset = m_current_offset;
new_space = gpu_position - m_current_offset;
new_gpu_position = gpu_position;
return true;
break;
}
}
return false;
});
}
// Did any fences satisfy this condition?
// Has the command buffer been executed yet? If not, the caller should execute it.
+2 -2
View File
@@ -817,7 +817,7 @@ void GSTexture12::TransitionToState(const D3D12CommandList& cmdlist, ResourceSta
m_resource_state = state;
}
void GSTexture12::TransitionSubresourceToState(const D3D12CommandList& cmdlist, u32 level,
void GSTexture12::TransitionSubresourceToState(const D3D12CommandList& cmdlist, int level,
ResourceState before_state, ResourceState after_state) const
{
if (GSDevice12::GetInstance()->UseEnhancedBarriers())
@@ -829,7 +829,7 @@ void GSTexture12::TransitionSubresourceToState(const D3D12CommandList& cmdlist,
D3D12_TEXTURE_BARRIER barriers[2] = {{D3D12_BARRIER_SYNC_NONE, D3D12_BARRIER_SYNC_NONE,
D3D12_BARRIER_ACCESS_COMMON, D3D12_BARRIER_ACCESS_COMMON,
D3D12_BARRIER_LAYOUT_COMMON, D3D12_BARRIER_LAYOUT_COMMON,
m_resource.get(), {level, 0, 0, 0, 0, 0}, D3D12_TEXTURE_BARRIER_FLAG_NONE}};
m_resource.get(), {static_cast<u32>(level), 0, 0, 0, 0, 0}, D3D12_TEXTURE_BARRIER_FLAG_NONE}};
uint num_barriers = 1;
D3D12_TEXTURE_BARRIER& barrier = barriers[0];
+1 -1
View File
@@ -74,7 +74,7 @@ public:
void Destroy(bool defer = true);
void TransitionToState(const D3D12CommandList&, ResourceState state);
void TransitionSubresourceToState(const D3D12CommandList& cmdlist, u32 level, ResourceState before_state,
void TransitionSubresourceToState(const D3D12CommandList& cmdlist, int level, ResourceState before_state,
ResourceState after_state) const;
// Call when the texture is bound to the pipeline, or read from in a copy.
+2 -2
View File
@@ -1131,7 +1131,7 @@ bool GSHwHack::OI_SonicUnleashed(GSRendererHW& r, GSTexture* rt, GSTexture* ds,
if ((!rt) || (!RPRIM->TME) || (GSLocalMemory::m_psm[Texture.PSM].bpp != 16) || (GSLocalMemory::m_psm[Frame.PSM].bpp != 16) || (Texture.TBP0 == Frame.TBP0) || (Frame.TBW != 16 && Texture.TBW != 16))
return true;
GL_INS("OI_SonicUnleashed replace draw by a copy draw %lld", r.s_n);
GL_INS("OI_SonicUnleashed replace draw by a copy draw %d", r.s_n);
GSTextureCache::Target* src = g_texture_cache->LookupTarget(Texture, GSVector2i(1, 1), r.GetTextureScaleFactor(), GSTextureCache::RenderTarget, true, 0, false, false, true, true, GSVector4i::zero(), true);
@@ -1344,7 +1344,7 @@ static bool GetMoveTargetPair(GSRendererHW& r, GSTextureCache::Target** src, GST
req_target, preserve_target);
}
static u64 s_last_hacked_move_n = 0;
static int s_last_hacked_move_n = 0;
bool GSHwHack::MV_Growlanser(GSRendererHW& r)
{
+285 -64
View File
@@ -101,7 +101,7 @@ void GSRendererHW::VSync(u32 field, bool registers_written, bool idle_frame)
{
// If it did draws very recently, we should keep the recent stuff in case it hasn't been preloaded/used yet.
// Rocky Legend does this with the main menu FMV's.
if ((s_n - s_last_transfer_draw_n) < 5)
if (s_last_transfer_draw_n > (s_n - 5))
{
for (auto iter = m_draw_transfers.rbegin(); iter != m_draw_transfers.rend(); iter++)
{
@@ -181,7 +181,7 @@ GSTexture* GSRendererHW::GetOutput(int i, float& scale, int& y_offset)
if (GSConfig.SaveFrame && GSConfig.ShouldDump(s_n, g_perfmon.GetFrame()))
{
t->Save(GetDrawDumpPath("%05lld_f%05lld_fr%d_%05x_%s.bmp", s_n, g_perfmon.GetFrame(), i, static_cast<int>(TEX0.TBP0), GSUtil::GetPSMName(TEX0.PSM)));
t->Save(GetDrawDumpPath("%05d_f%05lld_fr%d_%05x_%s.bmp", s_n, g_perfmon.GetFrame(), i, static_cast<int>(TEX0.TBP0), GSUtil::GetPSMName(TEX0.PSM)));
}
}
@@ -207,7 +207,7 @@ GSTexture* GSRendererHW::GetFeedbackOutput(float& scale)
scale = rt->m_scale;
if (GSConfig.SaveFrame && GSConfig.ShouldDump(s_n, g_perfmon.GetFrame()))
t->Save(GetDrawDumpPath("%05lld_f%05lld_fr%d_%05x_%s.bmp", s_n, g_perfmon.GetFrame(), 3, static_cast<int>(TEX0.TBP0), GSUtil::GetPSMName(TEX0.PSM)));
t->Save(GetDrawDumpPath("%05d_f%05lld_fr%d_%05x_%s.bmp", s_n, g_perfmon.GetFrame(), 3, static_cast<int>(TEX0.TBP0), GSUtil::GetPSMName(TEX0.PSM)));
return t;
}
@@ -1920,7 +1920,7 @@ void GSRendererHW::Move()
const int w = m_env.TRXREG.RRW;
const int h = m_env.TRXREG.RRH;
GL_CACHE("HW: Starting Move! 0x%x W:%d F:%s => 0x%x W:%d F:%s (DIR %d%d), sPos(%d %d) dPos(%d %d) size(%d %d) draw %lld",
GL_CACHE("HW: Starting Move! 0x%x W:%d F:%s => 0x%x W:%d F:%s (DIR %d%d), sPos(%d %d) dPos(%d %d) size(%d %d) draw %d",
m_env.BITBLTBUF.SBP, m_env.BITBLTBUF.SBW, GSUtil::GetPSMName(m_env.BITBLTBUF.SPSM),
m_env.BITBLTBUF.DBP, m_env.BITBLTBUF.DBW, GSUtil::GetPSMName(m_env.BITBLTBUF.DPSM),
m_env.TRXPOS.DIRX, m_env.TRXPOS.DIRY,
@@ -2335,7 +2335,7 @@ void GSRendererHW::Draw()
if (IsBadFrame())
{
GL_INS("HW: Warning skipping a draw call (%lld)", s_n);
GL_INS("HW: Warning skipping a draw call (%d)", s_n);
return;
}
@@ -2384,7 +2384,7 @@ void GSRendererHW::Draw()
{
if (m_last_rt)
{
//DevCon.Warning("Skipped %d draw %lld was abort %d", num_skipped_channel_shuffle_draws, s_n, (int)m_channel_shuffle_abort);
//DevCon.Warning("Skipped %d draw %d was abort %d", num_skipped_channel_shuffle_draws, s_n, (int)m_channel_shuffle_abort);
// Some games like Tomb raider abort early, we're never going to know the real height, and the system doesn't work right for partials.
// But it's good enough for games like Hitman Blood Money which only shuffle part of the screen
const int width = std::max(static_cast<int>(m_last_rt->m_TEX0.TBW) * 64, 64);
@@ -2421,7 +2421,7 @@ void GSRendererHW::Draw()
{
const u64 frame = g_perfmon.GetFrame();
std::string s = GetDrawDumpPath("%05lld_f%05lld_rt1_%05x_(%05x)_%s.bmp", s_n - 1, frame, m_last_channel_shuffle_fbp, m_last_rt->m_TEX0.TBP0, GSUtil::GetPSMName(m_cached_ctx.FRAME.PSM));
std::string s = GetDrawDumpPath("%05d_f%05lld_rt1_%05x_(%05x)_%s.bmp", s_n - 1, frame, m_last_channel_shuffle_fbp, m_last_rt->m_TEX0.TBP0, GSUtil::GetPSMName(m_cached_ctx.FRAME.PSM));
m_last_rt->m_texture->Save(s);
}
@@ -2440,7 +2440,7 @@ void GSRendererHW::Draw()
}
#ifdef ENABLE_OGL_DEBUG
if (num_skipped_channel_shuffle_draws > 0)
GL_CACHE("HW: Skipped %d channel shuffle draws ending at %lld", num_skipped_channel_shuffle_draws, s_n);
GL_CACHE("HW: Skipped %d channel shuffle draws ending at %d", num_skipped_channel_shuffle_draws, s_n);
#endif
num_skipped_channel_shuffle_draws = 0;
}
@@ -2457,7 +2457,7 @@ void GSRendererHW::Draw()
m_channel_shuffle_finish = false;
m_channel_shuffle_src_valid = GSVector4i::zero();
GL_PUSH("HW: Draw %lld (Context %u)", s_n, PRIM->CTXT);
GL_PUSH("HW: Draw %d (Context %u)", s_n, PRIM->CTXT);
GL_INS("HW: FLUSH REASON: %s%s", GetFlushReasonString(m_state_flush_reason),
(m_state_flush_reason != GSFlushReason::CONTEXTCHANGE && m_dirty_gs_regs) ? " AND POSSIBLE CONTEXT CHANGE" :
"");
@@ -2616,7 +2616,7 @@ void GSRendererHW::Draw()
// Draw is too small, just skip it.
if (m_r.rempty())
{
GL_INS("HW: Draw %lld skipped due to having an empty rect", s_n);
GL_INS("HW: Draw %d skipped due to having an empty rect");
return;
}
@@ -2820,7 +2820,7 @@ void GSRendererHW::Draw()
(fb_mask != 0 && (fb_mask >> 16) == (fb_mask & 0xFFFF) && ((fb_mask >> 8) & 0xFF) != (fb_mask & 0xFF))))
{
GL_CACHE("Clear 16bit with 32bit %lld", s_n);
GL_CACHE("Clear 16bit with 32bit %d", s_n);
// May have already been resized through the split draw checks.
if (!(m_cached_ctx.FRAME.PSM & 2))
@@ -3496,7 +3496,7 @@ void GSRendererHW::Draw()
const u32 new_width = std::max(new_size.x, ds->m_unscaled_size.x);
const u32 new_height = std::max(new_size.y, ds->m_unscaled_size.y);
//DevCon.Warning("HW: Resizing texture %d x %d draw %lld", ds->m_unscaled_size.x, new_height, s_n);
//DevCon.Warning("HW: Resizing texture %d x %d draw %d", ds->m_unscaled_size.x, new_height, s_n);
ds->ResizeTexture(new_width, new_height);
}
else if ((IsPageCopy() || is_possible_mem_clear) && m_r.width() <= zbuf_psm.pgs.x && m_r.height() <= zbuf_psm.pgs.y)
@@ -3793,7 +3793,7 @@ void GSRendererHW::Draw()
const u32 new_width = std::max(new_size.x, rt->m_unscaled_size.x);
const u32 new_height = std::max(new_size.y, rt->m_unscaled_size.y);
//DevCon.Warning("HW: Resizing texture %d x %d draw %lld", rt->m_unscaled_size.x, new_height, s_n);
//DevCon.Warning("HW: Resizing texture %d x %d draw %d", rt->m_unscaled_size.x, new_height, s_n);
rt->ResizeTexture(new_width, new_height);
}
else if ((IsPageCopy() || is_possible_mem_clear) && m_r.width() <= frame_psm.pgs.x && m_r.height() <= frame_psm.pgs.y)
@@ -3844,7 +3844,7 @@ void GSRendererHW::Draw()
const GSVector4 sRect = GSVector4(((ds->m_valid.x + horizontal_offset) * ds->m_scale) / static_cast<float>(g_texture_cache->GetTemporaryZ()->GetWidth()), static_cast<float>((ds->m_valid.y + vertical_offset) * ds->m_scale) / static_cast<float>(g_texture_cache->GetTemporaryZ()->GetHeight()), (((ds->m_valid.z + horizontal_offset) + (1.0f / ds->m_scale)) * ds->m_scale) / static_cast<float>(g_texture_cache->GetTemporaryZ()->GetWidth()),
static_cast<float>((ds->m_valid.w + vertical_offset + (1.0f / ds->m_scale)) * ds->m_scale) / static_cast<float>(g_texture_cache->GetTemporaryZ()->GetHeight()));
GL_CACHE("HW: RT in RT Z copy back draw %lld z_vert_offset %d z_offset %d", s_n, z_vertical_offset, vertical_offset);
GL_CACHE("HW: RT in RT Z copy back draw %d z_vert_offset %d z_offset %d", s_n, z_vertical_offset, vertical_offset);
g_gs_device->StretchRect(g_texture_cache->GetTemporaryZ(), sRect, ds->m_texture, GSVector4(dRect), ShaderConvert::DEPTH_COPY, false);
}
@@ -3854,7 +3854,7 @@ void GSRendererHW::Draw()
}
else if (!m_r.rintersect(z_address_info.rect_since).rempty() && m_cached_ctx.TEST.ZTST > ZTST_ALWAYS)
{
GL_CACHE("HW: RT in RT Updating Z copy on draw %lld z_offset %d", s_n, z_address_info.offset);
GL_CACHE("HW: RT in RT Updating Z copy on draw %d z_offset %d", s_n, z_address_info.offset);
GSVector4 sRect = GSVector4(z_address_info.rect_since.x / static_cast<float>(ds->m_unscaled_size.x), z_address_info.rect_since.y / static_cast<float>(ds->m_unscaled_size.y), (z_address_info.rect_since.z + (1.0f / ds->m_scale)) / static_cast<float>(ds->m_unscaled_size.x), (z_address_info.rect_since.w + (1.0f / ds->m_scale)) / static_cast<float>(ds->m_unscaled_size.y));
GSVector4i dRect = GSVector4i((old_z_horizontal_offset + z_address_info.rect_since.x) * ds->m_scale, (old_z_vertical_offset + z_address_info.rect_since.y) * ds->m_scale, (old_z_horizontal_offset + z_address_info.rect_since.z + (1.0f / ds->m_scale)) * ds->m_scale, (old_z_vertical_offset + z_address_info.rect_since.w + (1.0f / ds->m_scale)) * ds->m_scale);
@@ -3904,7 +3904,7 @@ void GSRendererHW::Draw()
sRect.z = std::min(sRect.z, sRect.x + ((1.0f * ds->m_scale) + (static_cast<float>(m_cached_ctx.FRAME.FBW * 64)) / static_cast<float>(ds->m_unscaled_size.x)));
dRect.z = std::min(dRect.z, dRect.x + static_cast<int>(1 * ds->m_scale) + static_cast<int>(static_cast<float>(m_cached_ctx.FRAME.FBW * 64) * ds->m_scale));
GL_CACHE("HW: RT in RT Z copy on draw %lld z_vert_offset %d", s_n, page_offset);
GL_CACHE("HW: RT in RT Z copy on draw %d z_vert_offset %d", s_n, page_offset);
if (m_cached_ctx.TEST.ZTST > ZTST_ALWAYS || !dRect.rintersect(GSVector4i(GSVector4(m_r) * ds->m_scale)).eq(dRect))
{
@@ -4657,7 +4657,7 @@ void GSRendererHW::Draw()
if (GSConfig.SaveTexture && src)
{
s = GetDrawDumpPath("%05lld_f%05lld_itex_%s_%05x(%05x)_%s_%d%d_%02x_%02x_%02x_%02x.dds",
s = GetDrawDumpPath("%05d_f%05lld_itex_%s_%05x(%05x)_%s_%d%d_%02x_%02x_%02x_%02x.dds",
s_n, frame, (src->m_from_target ? "tgt" : "gs"), static_cast<int>(m_cached_ctx.TEX0.TBP0), (src->m_from_target ? src->m_from_target->m_TEX0.TBP0 : src->m_TEX0.TBP0), GSUtil::GetPSMName(m_cached_ctx.TEX0.PSM),
static_cast<int>(m_cached_ctx.CLAMP.WMS), static_cast<int>(m_cached_ctx.CLAMP.WMT),
static_cast<int>(m_cached_ctx.CLAMP.MINU), static_cast<int>(m_cached_ctx.CLAMP.MAXU),
@@ -4667,7 +4667,7 @@ void GSRendererHW::Draw()
if (src->m_palette)
{
s = GetDrawDumpPath("%05lld_f%05lld_itpx_%05x_%s.dds", s_n, frame, m_cached_ctx.TEX0.CBP, GSUtil::GetPSMName(m_cached_ctx.TEX0.CPSM));
s = GetDrawDumpPath("%05d_f%05lld_itpx_%05x_%s.dds", s_n, frame, m_cached_ctx.TEX0.CBP, GSUtil::GetPSMName(m_cached_ctx.TEX0.CPSM));
src->m_palette->Save(s);
}
@@ -4675,7 +4675,7 @@ void GSRendererHW::Draw()
if (rt && GSConfig.SaveRT)
{
s = GetDrawDumpPath("%05lld_f%05lld_rt0_%05x_(%05x)_%s.bmp", s_n, frame, m_cached_ctx.FRAME.Block(), rt->m_TEX0.TBP0, GSUtil::GetPSMName(m_cached_ctx.FRAME.PSM));
s = GetDrawDumpPath("%05d_f%05lld_rt0_%05x_(%05x)_%s.bmp", s_n, frame, m_cached_ctx.FRAME.Block(), rt->m_TEX0.TBP0, GSUtil::GetPSMName(m_cached_ctx.FRAME.PSM));
if (rt->m_texture)
rt->m_texture->Save(s);
@@ -4683,7 +4683,7 @@ void GSRendererHW::Draw()
if (ds && GSConfig.SaveDepth)
{
s = GetDrawDumpPath("%05lld_f%05lld_rz0_%05x_(%05x)_%s.bmp", s_n, frame, m_cached_ctx.ZBUF.Block(), ds->m_TEX0.TBP0, GSUtil::GetPSMName(m_cached_ctx.ZBUF.PSM));
s = GetDrawDumpPath("%05d_f%05lld_rz0_%05x_(%05x)_%s.bmp", s_n, frame, m_cached_ctx.ZBUF.Block(), ds->m_TEX0.TBP0, GSUtil::GetPSMName(m_cached_ctx.ZBUF.PSM));
if (m_using_temp_z)
g_texture_cache->GetTemporaryZ()->Save(s);
@@ -4694,14 +4694,14 @@ void GSRendererHW::Draw()
if (m_oi && !m_oi(*this, rt ? rt->m_texture : nullptr, ds ? ds->m_texture : nullptr, src))
{
GL_INS("HW: Warning skipping a draw call (%lld)", s_n);
GL_INS("HW: Warning skipping a draw call (%d)", s_n);
CleanupDraw(true);
return;
}
if (!OI_BlitFMV(rt, src, m_r))
{
GL_INS("HW: Warning skipping a draw call (%lld)", s_n);
GL_INS("HW: Warning skipping a draw call (%d)", s_n);
CleanupDraw(true);
return;
}
@@ -4711,31 +4711,260 @@ void GSRendererHW::Draw()
// Note: second hack corrects only the texture coordinate
// Be careful to not correct downscaled targets, this can get messy and break post processing
// but it still needs to adjust native stuff from memory as it's not been compensated for upscaling (Dragon Quest 8 font for example).
if (CanUpscale() && (m_vt.m_primclass == GS_SPRITE_CLASS) && rt && rt->GetScale() > 1.0f)
if (CanUpscale() && ((m_vt.m_primclass == GS_SPRITE_CLASS) || ((m_index.tail % 6 == 0) && m_vt.m_primclass == GS_TRIANGLE_CLASS && m_vt.m_eq.z)) && rt && rt->GetScale() > 1.0f)
{
const u32 count = m_vertex.next;
GSVertex* v = &m_vertex.buff[0];
bool valid_format = true;
// Hack to avoid vertical black line in various games (ace combat/tekken)
if (GSConfig.UserHacks_AlignSpriteX)
if (m_vt.m_primclass == GS_TRIANGLE_CLASS)
{
// Note for performance reason I do the check only once on the first
// primitive
const int win_position = v[1].XYZ.X - context->XYOFFSET.OFX;
const bool unaligned_position = ((win_position & 0xF) == 8);
const bool unaligned_texture = ((v[1].U & 0xF) == 0) && PRIM->FST; // I'm not sure this check is useful
const bool hole_in_vertex = (count < 4) || (v[1].XYZ.X != v[2].XYZ.X);
if (hole_in_vertex && unaligned_position && (unaligned_texture || !PRIM->FST))
const GSVertex* RESTRICT v = m_vertex.buff;
const u16* RESTRICT index = m_index.buff;
const size_t count = m_index.tail;
for (int i = 0; i < count; i += 6)
{
// Normaly vertex are aligned on full pixels and texture in half
// pixels. Let's extend the coverage of an half-pixel to avoid
// hole after upscaling
for (u32 i = 0; i < count; i += 2)
// Non-axis aligned check when only two triangles
if (!AreTrianglesQuadNonAA(v, &index[i], &index[i + 3]))
{
v[i + 1].XYZ.X += 8;
// I really don't know if it is a good idea. Neither what to do for !PRIM->FST
if (unaligned_texture)
v[i + 1].U += 8;
valid_format = false;
break;
}
}
}
if (valid_format)
{
const u32 count = m_vertex.next;
GSVertex* v = &m_vertex.buff[0];
u16* idx = &m_index.buff[0];
const bool indexed_texture = src && src->m_scale == 1.0f && GSLocalMemory::m_psm[src->m_TEX0.PSM].pal > 0;
// Shortcut for when the sprites are right up against each other.
if (GSConfig.UserHacks_AlignSpriteX && m_vt.m_primclass == GS_SPRITE_CLASS && indexed_texture && PRIM->FST && m_index.tail > 2 &&
((v[idx[1]].U == v[idx[2]].U && (v[idx[1]].XYZ.X == v[idx[2]].XYZ.X) && v[idx[0]].V == v[idx[2]].V) ||
(v[idx[1]].V == v[idx[2]].V && (v[idx[1]].XYZ.Y == v[idx[2]].XYZ.Y) && v[idx[0]].U == v[idx[2]].U)))
{
for (int i = 0; i < m_index.tail; i += 2)
{
if (!((v[idx[i + 1]].U == v[idx[i + 2]].U && (v[idx[i + 1]].XYZ.X == v[idx[i + 2]].XYZ.X) && v[idx[i]].V == v[idx[i + 2]].V)))
{
if (v[idx[i + 1]].U & 0x8)
v[idx[i + 1]].U -= 8;
}
if (!((v[idx[i + 1]].V == v[idx[i + 2]].V && (v[idx[i + 1]].XYZ.Y == v[idx[i + 2]].XYZ.Y) && v[idx[i]].U == v[idx[i + 2]].U)))
{
if (v[idx[i + 1]].V & 0x8)
v[idx[i + 11]].V -= 8;
}
}
if (v[idx[m_index.tail - 1]].U & 0x8)
v[idx[m_index.tail - 1]].U -= 8;
if (v[idx[m_index.tail - 1]].V & 0x8)
v[idx[m_index.tail - 1]].V -= 8;
}
else
// Hack to avoid vertical black line in various games (ace combat/tekken)
if (GSConfig.UserHacks_AlignSpriteX)
{
// Note for performance reason I do the check only once on the first
// primitive
const int win_position0 = v[idx[0]].XYZ.X - context->XYOFFSET.OFX;
const int win_position1 = v[idx[1]].XYZ.X - context->XYOFFSET.OFX;
const bool unaligned_position = ((win_position0 & 0xf) != 0) || ((win_position1 & 0xF) != 0);
const int first_s = (v[idx[0]].ST.S / v[idx[0]].RGBAQ.Q) * static_cast<int>(1 << m_cached_ctx.TEX0.TW);
const bool unaligned_texture = (PRIM->FST && ((v[1].U & 0xF) == 0)) || (!PRIM->FST && (first_s & 0xF) == 0); // I'm not sure this check is useful
const int gap = std::min(static_cast<int>(v[2].XYZ.X), static_cast<int>(v[3].XYZ.X)) - std::max(static_cast<int>(v[0].XYZ.X), static_cast<int>(v[1].XYZ.X));
bool hole_in_vertex = (count < 4) || (v[1].XYZ.X != v[2].XYZ.X && ((v[1].XYZ.X ^ v[2].XYZ.X) & 0xF) != 0);
const bool is_tri = m_vt.m_primclass == GS_TRIANGLE_CLASS;
const int skip = is_tri ? 3 : 2;
GSVector2 gradient = GSVector2(1.0f, 1.0f);
if (m_lod.y == 0)
{
bool can_disable_linear = true;
for (u32 i = 0; i < m_index.tail; i += skip)
{
const int x_offset = (is_tri && v[idx[i]].XYZ.X == v[idx[i + 1]].XYZ.X) ? 2 : 1;
const int y_offset = (is_tri && v[idx[i]].XYZ.Y == v[idx[i + 1]].XYZ.Y) ? 2 : 1;
GSVector2 vert = GSVector2(std::abs(static_cast<float>(v[idx[i]].XYZ.X - v[idx[i + x_offset]].XYZ.X)), std::abs(static_cast<float>(v[idx[i]].XYZ.Y - v[idx[i + y_offset]].XYZ.Y)));
GSVector2 tex;
if (!PRIM->FST)
{
const int s_offset = (is_tri && (v[idx[i]].ST.S / v[idx[i]].RGBAQ.Q) == (v[idx[i + 1]].ST.S / v[idx[i + 1]].RGBAQ.Q)) ? 2 : 1;
const int t_offset = (is_tri && (v[idx[i]].ST.T / v[idx[i]].RGBAQ.Q) == (v[idx[i + 1]].ST.T / v[idx[i + 1]].RGBAQ.Q)) ? 2 : 1;
GSVector2 v0, v1;
float s = std::min((v[idx[i]].ST.S / v[idx[i]].RGBAQ.Q), 1.0f);
float t = std::min((v[idx[i]].ST.T / v[idx[i]].RGBAQ.Q), 1.0f);
v0.x = static_cast<int>((1 << m_cached_ctx.TEX0.TW) * s * 16.0f);
v0.y = static_cast<int>((1 << m_cached_ctx.TEX0.TH) * t * 16.0f);
s = std::min((v[idx[i + s_offset]].ST.S / v[idx[i + s_offset]].RGBAQ.Q), 1.0f);
t = std::min((v[idx[i + t_offset]].ST.T / v[idx[i + t_offset]].RGBAQ.Q), 1.0f);
v1.x = static_cast<int>((1 << m_cached_ctx.TEX0.TW) * s * 16.0f);
v1.y = static_cast<int>((1 << m_cached_ctx.TEX0.TH) * t * 16.0f);
tex = GSVector2(std::abs(v1.x - v0.x), std::abs(v1.y - v0.y));
}
else
{
const int u_offset = (is_tri && v[idx[i]].U == v[idx[i + 1]].U) ? 2 : 1;
const int v_offset = (is_tri && v[idx[i]].V == v[idx[i + 1]].V) ? 2 : 1;
tex = GSVector2(std::abs(static_cast<float>(v[idx[i]].U - v[idx[i + u_offset]].U)), std::abs(static_cast<float>(v[idx[i]].V - v[idx[i + v_offset]].V)));
}
GSVector2 grad = tex / vert;
if ((grad.x != gradient.x && grad.x != floor(grad.x)) || (grad.y != gradient.y && grad.y != floor(grad.y)))
{
can_disable_linear = false;
gradient = grad;
break;
}
}
if (can_disable_linear)
{
m_vt.m_filter.linear = 0;
m_vt.m_filter.opt_linear = 0;
}
}
/*if ((m_vt.m_primclass == GS_SPRITE_CLASS) && hole_in_vertex && unaligned_position && (unaligned_texture || !PRIM->FST))
{
// Normaly vertex are aligned on full pixels and texture in half
// pixels. Let's extend the coverage of an half-pixel to avoid
// hole after upscaling
for (u32 i = 0; i < count; i += 2)
{
v[i + 1].XYZ.X += 8;
// I really don't know if it is a good idea. Neither what to do for !PRIM->FST
if (unaligned_texture)
v[i + 1].U += 8;
}
}
else */if (indexed_texture && (gradient.x > (1.0f / 16.0f) || gradient.y > (1.0f / 16.0f)))
{
const int comparitor = unaligned_position ? 0 : 8;
if (!PRIM->FST)
{
int s_offset = (is_tri && (v[idx[0]].ST.S / v[idx[0]].RGBAQ.Q) == (v[idx[1]].ST.S / v[idx[1]].RGBAQ.Q)) ? 2 : 1;
int t_offset = (is_tri && (v[idx[0]].ST.T / v[idx[0]].RGBAQ.Q) == (v[idx[1]].ST.T / v[idx[1]].RGBAQ.Q)) ? 2 : 1;
GSVector2i v0, v1;
float q = v[idx[0]].RGBAQ.Q == 0 ? FLT_MIN : v[idx[0]].RGBAQ.Q;
float s = v[idx[0]].ST.S / q;
float t = v[idx[0]].ST.T / q;
v0.x = static_cast<int>((1 << m_cached_ctx.TEX0.TW) * s * 16.0f);
v0.y = static_cast<int>((1 << m_cached_ctx.TEX0.TH) * t * 16.0f);
q = v[idx[s_offset]].RGBAQ.Q == 0 ? FLT_MIN : v[idx[s_offset]].RGBAQ.Q;
s = v[idx[s_offset]].ST.S / q;
t = v[idx[t_offset]].ST.T / q;
v1.x = static_cast<int>((1 << m_cached_ctx.TEX0.TW) * s * 16.0f);
v1.y = static_cast<int>((1 << m_cached_ctx.TEX0.TH) * t * 16.0f);
bool small_texture = std::abs(v1.x - v0.x) <= (64 * 16) || std::abs(v1.y - v0.y) <= (64 * 16);
bool offset_texture_x = (m_vt.IsLinear() || ((v0.x & 0xF) && (v1.x & 0xF))) && small_texture; // Keep them relatively small to avoid full screen stuff.
bool offset_texture_y = (m_vt.IsLinear() || ((v0.y & 0xF) && (v1.y & 0xF))) && small_texture;
//if (offset_texture_x && offset_texture_y)
{
for (u32 i = m_index.buff[0]; i < m_index.tail; i += skip)
{
GSVector2 st;
if (gradient.x > (1.0f / 16.0f))
{
float largest_s = std::max(is_tri ? (v[i + 2].ST.S / v[i + 2].RGBAQ.Q) : static_cast<float>(0), std::max((v[i].ST.S / v[i].RGBAQ.Q), (v[i + 1].ST.S / v[i + 1].RGBAQ.Q)));
float smallest_s = std::min(is_tri ? (v[i + 2].ST.S / v[i + 2].RGBAQ.Q) : static_cast<float>(0), std::min((v[i].ST.S / v[i].RGBAQ.Q), (v[i + 1].ST.S / v[i + 1].RGBAQ.Q)));
for (int j = 0; j < skip; j++)
{
q = v[i + j].RGBAQ.Q == 0 ? FLT_MIN : v[i + j].RGBAQ.Q;
float s = v[i + j].ST.S / q;
st.x = static_cast<float>(1 << m_cached_ctx.TEX0.TW) * s;
if ((v[i + j].ST.S / q) == largest_s)
v[i + j].ST.S = ((st.x - 0.5f) / static_cast<float>(1 << m_cached_ctx.TEX0.TW)) * q;
// Check the minimap in Persona 3.
if ((static_cast<int>(st.x * 16) & 0x8) == comparitor && (v[i + j].ST.S / q) == smallest_s)
v[i + j].ST.S = (std::max(0.0f, (st.x - 0.5f)) / static_cast<float>(1 << m_cached_ctx.TEX0.TW)) * q;
}
}
if (gradient.y > (1.0f / 16.0f))
{
float largest_t = std::max(is_tri ? (v[i + 2].ST.T / v[i + 2].RGBAQ.Q) : static_cast<float>(0), std::max((v[i].ST.T / v[i].RGBAQ.Q), (v[i + 1].ST.T / v[i + 1].RGBAQ.Q)));
float smallest_t = std::min(is_tri ? (v[i + 2].ST.T / v[i + 2].RGBAQ.Q) : static_cast<float>(0), std::min((v[i].ST.T / v[i].RGBAQ.Q), (v[i + 1].ST.T / v[i + 1].RGBAQ.Q)));
for (int j = 0; j < skip; j++)
{
q = v[i + j].RGBAQ.Q == 0 ? FLT_MIN : v[i + j].RGBAQ.Q;
float t = v[i + j].ST.T / q;
st.y = static_cast<float>(1 << m_cached_ctx.TEX0.TH) * t;
if ((v[i + j].ST.T / q) == largest_t)
v[i + j].ST.T = ((st.y - 0.5f) / static_cast<float>(1 << m_cached_ctx.TEX0.TH)) * q;
// Check the minimap in Persona 3.
if ((static_cast<int>(st.y * 16) & 0x8) == comparitor && (v[i + j].ST.T / q) == smallest_t)
v[i + j].ST.T = (std::max(0.0f, (st.y - 0.5f)) / static_cast<float>(1 << m_cached_ctx.TEX0.TH)) * q;
}
}
}
}
}
else
{
int u_offset = (is_tri && (v[0].U == v[1].U)) ? 2 : 1;
int v_offset = (is_tri && (v[0].V == v[1].V)) ? 2 : 1;
bool small_texture = std::abs(static_cast<int>(v[idx[u_offset]].U) - static_cast<int>(v[idx[0]].U)) <= (64 * 16) || std::abs(static_cast<int>(v[idx[v_offset]].V) - static_cast<int>(v[idx[0]].V)) <= (64 * 16);
bool offset_texture_x = (m_vt.IsLinear() || ((v[0].U & 0xF) && (v[idx[u_offset]].U & 0xF))) && small_texture;
bool offset_texture_y = (m_vt.IsLinear() || ((v[0].V & 0xF) && (v[idx[v_offset]].V & 0xF))) && small_texture;
if (offset_texture_x && offset_texture_y)
{
for (u32 i = m_index.buff[0]; i < m_index.tail; i += skip)
{
if (gradient.x > (1.0f / 16.0f))
{
const u16 largest_u = std::max(is_tri ? v[idx[i + 2]].U : static_cast<u16>(0), std::max(v[idx[i]].U, v[idx[i + 1]].U));
if ((v[idx[i]].U & 0x8) == comparitor && v[idx[i]].U == largest_u)
v[idx[i]].U = std::max(static_cast<int>(v[idx[i]].U) - 8, 0);
if ((v[idx[i + 1]].U & 0x8) == comparitor && v[idx[i + 1]].U == largest_u)
v[idx[i + 1]].U = std::max(static_cast<int>(v[idx[i + 1]].U) - 8, 0);
if (is_tri && (v[idx[i + 2]].U & 0x8) == comparitor && v[idx[i + 2]].U == largest_u)
v[idx[i + 2]].U = std::max(static_cast<int>(v[idx[i + 2]].U) - 8, 0);
}
if (gradient.y > (1.0f / 16.0f))
{
const u16 largest_v = std::max(is_tri ? v[idx[i + 2]].V : static_cast<u16>(0), std::max(v[idx[i]].V, v[idx[i + 1]].V));
if ((v[idx[i]].V & 0x8) == comparitor && v[idx[i]].V == largest_v)
v[idx[i]].V = std::max(static_cast<int>(v[idx[i]].V) - 8, 0);
if ((v[idx[i + 1]].V & 0x8) == comparitor && v[idx[i + 1]].V == largest_v)
v[idx[i + 1]].V = std::max(static_cast<int>(v[idx[i + 1]].V) - 8, 0);
if (is_tri && (v[idx[i + 2]].V & 0x8) == comparitor && v[idx[i + 2]].V == largest_v)
v[idx[i + 2]].V = std::max(static_cast<int>(v[idx[i + 2]].V) - 8, 0);
}
}
}
}
}
else if ((m_vt.m_primclass == GS_SPRITE_CLASS) && hole_in_vertex && unaligned_position && (unaligned_texture || !PRIM->FST))
{
// Normaly vertex are aligned on full pixels and texture in half
// pixels. Let's extend the coverage of an half-pixel to avoid
// hole after upscaling
for (u32 i = 0; i < count; i += 2)
{
v[i + 1].XYZ.X += 8;
// I really don't know if it is a good idea. Neither what to do for !PRIM->FST
if (unaligned_texture)
v[i + 1].U += 8;
}
}
}
}
@@ -4824,7 +5053,7 @@ void GSRendererHW::Draw()
((real_rect.z + (1.0f / ds->m_scale)) * ds->m_scale) / static_cast<float>(g_texture_cache->GetTemporaryZ()->GetWidth()),
static_cast<float>((real_rect.w + (1.0f / ds->m_scale)) * ds->m_scale) / static_cast<float>(g_texture_cache->GetTemporaryZ()->GetHeight()));
GL_CACHE("HW: RT in RT Z copy back draw %lld z_vert_offset %d rt_vert_offset %d z_horz_offset %d rt_horz_offset %d", s_n, z_vertical_offset, vertical_offset, z_horizontal_offset, horizontal_offset);
GL_CACHE("HW: RT in RT Z copy back draw %d z_vert_offset %d rt_vert_offset %d z_horz_offset %d rt_horz_offset %d", s_n, z_vertical_offset, vertical_offset, z_horizontal_offset, horizontal_offset);
g_gs_device->StretchRect(g_texture_cache->GetTemporaryZ(), sRect, ds->m_texture, GSVector4(dRect), ShaderConvert::DEPTH_COPY, false);
}
else if (m_temp_z_full_copy)
@@ -4836,7 +5065,7 @@ void GSRendererHW::Draw()
(((ds->m_valid.z + horizontal_offset) + (1.0f / ds->m_scale)) * ds->m_scale) / static_cast<float>(g_texture_cache->GetTemporaryZ()->GetWidth()),
static_cast<float>((ds->m_valid.w + vertical_offset + (1.0f / ds->m_scale)) * ds->m_scale) / static_cast<float>(g_texture_cache->GetTemporaryZ()->GetHeight()));
GL_CACHE("HW: RT in RT Z copy back draw %lld z_vert_offset %d z_offset %d", s_n, z_vertical_offset, vertical_offset);
GL_CACHE("HW: RT in RT Z copy back draw %d z_vert_offset %d z_offset %d", s_n, z_vertical_offset, vertical_offset);
g_gs_device->StretchRect(g_texture_cache->GetTemporaryZ(), sRect, ds->m_texture, GSVector4(dRect), ShaderConvert::DEPTH_COPY, false);
}
@@ -4876,14 +5105,14 @@ void GSRendererHW::Draw()
if (rt && GSConfig.SaveRT && !m_last_rt)
{
s = GetDrawDumpPath("%05lld_f%05lld_rt1_%05x_(%05x)_%s.bmp", s_n, frame, m_cached_ctx.FRAME.Block(), rt->m_TEX0.TBP0, GSUtil::GetPSMName(m_cached_ctx.FRAME.PSM));
s = GetDrawDumpPath("%05d_f%05lld_rt1_%05x_(%05x)_%s.bmp", s_n, frame, m_cached_ctx.FRAME.Block(), rt->m_TEX0.TBP0, GSUtil::GetPSMName(m_cached_ctx.FRAME.PSM));
rt->m_texture->Save(s);
}
if (ds && GSConfig.SaveDepth)
{
s = GetDrawDumpPath("%05lld_f%05lld_rz1_%05x_%s.bmp", s_n, frame, m_cached_ctx.ZBUF.Block(), GSUtil::GetPSMName(m_cached_ctx.ZBUF.PSM));
s = GetDrawDumpPath("%05d_f%05lld_rz1_%05x_%s.bmp", s_n, frame, m_cached_ctx.ZBUF.Block(), GSUtil::GetPSMName(m_cached_ctx.ZBUF.PSM));
if (m_using_temp_z)
g_texture_cache->GetTemporaryZ()->Save(s);
@@ -4900,9 +5129,6 @@ void GSRendererHW::Draw()
if ((fm & fm_mask) != fm_mask && !no_rt)
{
if (m_mem.m_clut.GetGPUTexture() && m_mem.m_clut.GetGPUTexture() == rt->m_texture)
m_mem.m_clut.SetGPUTextureDirty(rt->m_last_draw, rt->m_texture);
g_texture_cache->InvalidateVideoMem(context->offset.fb, real_rect, false);
// Remove overwritten Zs at the FBP.
@@ -5616,7 +5842,7 @@ __ri u32 GSRendererHW::EmulateChannelShuffle(GSTextureCache::Target* src, bool t
{
const bool req_offset = (m_cached_ctx.CLAMP.WMS != 3 || (m_cached_ctx.CLAMP.MAXU & ~0xF) == 0) &&
(m_cached_ctx.CLAMP.WMT != 3 || (m_cached_ctx.CLAMP.MAXV & ~0x3) == 0);
//DevCon.Warning("HW: Draw %lld offset %d", s_n, frame_page_offset);
//DevCon.Warning("HW: Draw %d offset %d", s_n, frame_page_offset);
// Offset the frame but clear the draw offset
if (req_offset)
m_cached_ctx.FRAME.FBP += frame_page_offset;
@@ -7280,27 +7506,27 @@ void GSRendererHW::EmulateATST(float& AREF, GSHWDrawConfig::PSSelector& ps, bool
{
case ATST_LESS:
AREF = aref - 0.1f;
ps.atst = GSHWDrawConfig::PSAlphaTest::PS_ATST_LEQUAL;
ps.atst = 1;
break;
case ATST_LEQUAL:
AREF = aref - 0.1f + 1.0f;
ps.atst = GSHWDrawConfig::PSAlphaTest::PS_ATST_LEQUAL;
ps.atst = 1;
break;
case ATST_GEQUAL:
AREF = aref - 0.1f;
ps.atst = GSHWDrawConfig::PSAlphaTest::PS_ATST_GEQUAL;
ps.atst = 2;
break;
case ATST_GREATER:
AREF = aref - 0.1f + 1.0f;
ps.atst = GSHWDrawConfig::PSAlphaTest::PS_ATST_GEQUAL;
ps.atst = 2;
break;
case ATST_EQUAL:
AREF = aref;
ps.atst = GSHWDrawConfig::PSAlphaTest::PS_ATST_EQUAL;
ps.atst = 3;
break;
case ATST_NOTEQUAL:
AREF = aref;
ps.atst = GSHWDrawConfig::PSAlphaTest::PS_ATST_NOTEQUAL;
ps.atst = 4;
break;
case ATST_NEVER: // Draw won't be done so no need to implement it in shader
case ATST_ALWAYS:
@@ -7595,7 +7821,7 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
GL_PERF("DATE: Accurate with alpha %d-%d", GetAlphaMinMax().min, GetAlphaMinMax().max);
DATE_PRIMID = true;
}
else if (features.texture_barrier || features.multidraw_fb_copy)
else if (features.texture_barrier)
{
GL_PERF("DATE: Accurate with alpha %d-%d", GetAlphaMinMax().min, GetAlphaMinMax().max);
m_conf.require_full_barrier = true;
@@ -8209,11 +8435,6 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
m_conf.alpha_second_pass.enable = false;
}
if (GSConfig.SaveHWConfig && GSConfig.ShouldDump(s_n, g_perfmon.GetFrame()))
{
GSHWDrawConfig::DumpConfig(GetDrawDumpPath("%05d_hwconfig.txt", s_n), m_conf);
}
if (!m_channel_shuffle_width)
g_gs_device->RenderHW(m_conf);
else
@@ -8372,7 +8593,7 @@ GSRendererHW::CLUTDrawTestResult GSRendererHW::PossibleCLUTDraw()
// Debugging stuff..
//const u32 startbp = psm.info.bn(m_vt.m_min.p.x, m_vt.m_min.p.y, m_FRAME.Block(), m_FRAME.FBW);
//const u32 endbp = psm.info.bn(m_vt.m_max.p.x, m_vt.m_max.p.y, m_FRAME.Block(), m_FRAME.FBW);
//DevCon.Warning("HW: Draw width %f height %f page width %f height %f TPSM %x TBP0 %x FPSM %x FBP %x CBP %x valid size %d Invalid %d DISPFB0 %x DISPFB1 %x start %x end %x draw %lld", draw_width, draw_height, page_width, page_height, m_cached_ctx.TEX0.PSM, m_cached_ctx.TEX0.TBP0, m_FRAME.PSM, m_FRAME.Block(), m_mem.m_clut.GetCLUTCBP(), valid_size, m_mem.m_clut.IsInvalid(), m_regs->DISP[0].DISPFB.Block(), m_regs->DISP[1].DISPFB.Block(), startbp, endbp, s_n);
//DevCon.Warning("HW: Draw width %f height %f page width %f height %f TPSM %x TBP0 %x FPSM %x FBP %x CBP %x valid size %d Invalid %d DISPFB0 %x DISPFB1 %x start %x end %x draw %d", draw_width, draw_height, page_width, page_height, m_cached_ctx.TEX0.PSM, m_cached_ctx.TEX0.TBP0, m_FRAME.PSM, m_FRAME.Block(), m_mem.m_clut.GetCLUTCBP(), valid_size, m_mem.m_clut.IsInvalid(), m_regs->DISP[0].DISPFB.Block(), m_regs->DISP[1].DISPFB.Block(), startbp, endbp, s_n);
return CLUTDrawTestResult::CLUTDrawOnCPU;
}
@@ -9395,7 +9616,7 @@ int GSRendererHW::IsScalingDraw(GSTextureCache::Source* src, bool no_gaps)
if (no_gaps_or_single_sprite && ((is_upscale && !m_context->ALPHA.IsOpaque()) ||
(is_downscale && (dst_discarded || (PRIM->ABE && m_context->ALPHA.C == 2 && m_context->ALPHA.FIX == 255)))))
{
GL_INS("HW: %s draw detected - from %dx%d to %dx%d draw %lld", is_downscale ? "Downscale" : "Upscale", tex_size.x, tex_size.y, draw_size.x, draw_size.y, s_n);
GL_INS("HW: %s draw detected - from %dx%d to %dx%d draw %d", is_downscale ? "Downscale" : "Upscale", tex_size.x, tex_size.y, draw_size.x, draw_size.y, s_n);
return is_upscale ? 2 : 1;
}
-1
View File
@@ -242,7 +242,6 @@ public:
void PurgeTextureCache(bool sources, bool targets, bool hash_cache) override;
void ReadbackTextureCache() override;
GSTexture* LookupPaletteSource(u32 CBP, u32 CPSM, u32 CBW, GSVector2i& offset, float* scale, const GSVector2i& size) override;
/// Called by the texture cache to know for certain whether there is a channel shuffle.
+12 -14
View File
@@ -430,7 +430,7 @@ GSVector4i GSTextureCache::TranslateAlignedRectByPage(u32 tbp, u32 tebp, u32 tbw
// The width is mismatched to the page.
if (!is_invalidation && GSConfig.UserHacks_TextureInsideRt < GSTextureInRtMode::MergeTargets)
{
DevCon.Warning("Uneven pages mess up sbp %x dbp %x spgw %d dpgw %d src fmt %d dst fmt %d src_rect %d, %d, %d, %d draw %lld", sbp, tbp, src_pgw, dst_pgw, spsm, tpsm, in_rect.x, in_rect.y, in_rect.z, in_rect.w, GSState::s_n);
DevCon.Warning("Uneven pages mess up sbp %x dbp %x spgw %d dpgw %d src fmt %d dst fmt %d src_rect %d, %d, %d, %d draw %d", sbp, tbp, src_pgw, dst_pgw, spsm, tpsm, in_rect.x, in_rect.y, in_rect.z, in_rect.w, GSState::s_n);
return GSVector4i::zero();
}
@@ -2342,7 +2342,7 @@ void GSTextureCache::CombineAlignedInsideTargets(Target* target, GSTextureCache:
target->m_valid_alpha_high |= t->m_valid_alpha_high;
target->m_valid_alpha_low |= t->m_valid_alpha_low;
GL_CACHE("Combining %x-%x in to %x-%x draw %lld", t->m_TEX0.TBP0, t->m_end_block, target->m_TEX0.TBP0, target->m_end_block, GSState::s_n);
GL_CACHE("Combining %x-%x in to %x-%x draw %d", t->m_TEX0.TBP0, t->m_end_block, target->m_TEX0.TBP0, target->m_end_block, GSState::s_n);
if (target->m_type == RenderTarget)
{
@@ -2837,7 +2837,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
m_target_memory_usage = (m_target_memory_usage - dst->m_texture->GetMemUsage()) + tex->GetMemUsage();
// If we're changing resolution scale, just toss the texture, it's not going to get reused.
if ((!GSConfig.UserHacks_NativePaletteDraw && !dst->m_downscaled && scale != 1.0f) || (dst->m_scale != 1.0f && scale != 1.0f))
if ((!GSConfig.UserHacks_NativePaletteDraw && !dst->m_downscaled) || (dst->m_scale != 1.0f && scale != 1.0f))
delete dst->m_texture;
else
g_gs_device->Recycle(dst->m_texture);
@@ -3346,12 +3346,12 @@ GSTextureCache::Target* GSTextureCache::CreateTarget(GIFRegTEX0 TEX0, const GSVe
{
if (type == DepthStencil)
{
GL_CACHE("TC: Lookup Target(Depth) %dx%d, miss (0x%x, TBW %d, %s) draw %lld", size.x, size.y, TEX0.TBP0,
GL_CACHE("TC: Lookup Target(Depth) %dx%d, miss (0x%x, TBW %d, %s) draw %d", size.x, size.y, TEX0.TBP0,
TEX0.TBW, GSUtil::GetPSMName(TEX0.PSM), g_gs_renderer->s_n);
}
else
{
GL_CACHE("TC: Lookup %s(Color) %dx%d FBMSK %08x, miss (0x%x, TBW %d, %s) draw %lld", is_frame ? "Frame" : "Target",
GL_CACHE("TC: Lookup %s(Color) %dx%d FBMSK %08x, miss (0x%x, TBW %d, %s) draw %d", is_frame ? "Frame" : "Target",
size.x, size.y, fbmask, TEX0.TBP0, TEX0.TBW, GSUtil::GetPSMName(TEX0.PSM), g_gs_renderer->s_n);
}
// Avoid making garbage targets (usually PCRTC).
@@ -3727,7 +3727,7 @@ bool GSTextureCache::PreloadTarget(GIFRegTEX0 TEX0, const GSVector2i& size, cons
if (texture_height > dst->m_unscaled_size.y && !dst->ResizeTexture(dst->m_unscaled_size.x, texture_height, true))
{
// Resize failed, probably ran out of VRAM, better luck next time. Fall back to CPU.
DevCon.Warning("Failed to resize target on preload? Draw %lld", GSState::s_n);
DevCon.Warning("Failed to resize target on preload? Draw %d", GSState::s_n);
i++;
continue;
}
@@ -5247,7 +5247,7 @@ bool GSTextureCache::Move(u32 SBP, u32 SBW, u32 SPSM, int sx, int sy, u32 DBP, u
// Make sure the copy doesn't go out of bounds (it shouldn't).
if ((scaled_dx + scaled_w) > dst->m_texture->GetWidth() || (scaled_dy + scaled_h) > dst->m_texture->GetHeight())
return false;
GL_CACHE("TC: HW Move after draw %lld 0x%x[BW:%u PSM:%s] to 0x%x[BW:%u PSM:%s] <%d,%d->%d,%d> -> <%d,%d->%d,%d>", GSState::s_n, SBP, SBW,
GL_CACHE("TC: HW Move after draw %d 0x%x[BW:%u PSM:%s] to 0x%x[BW:%u PSM:%s] <%d,%d->%d,%d> -> <%d,%d->%d,%d>", GSState::s_n, SBP, SBW,
GSUtil::GetPSMName(SPSM), DBP, DBW, GSUtil::GetPSMName(DPSM), sx, sy, sx + w, sy + h, dx, dy, dx + w, dy + h);
const bool cover_whole_target = dst->m_type == RenderTarget && GSVector4i(dx, dy, dx + w, dy + h).rintersect(dst->m_valid).eq(dst->m_valid);
@@ -5689,7 +5689,7 @@ GSVector2i GSTextureCache::GetTargetSize(u32 bp, u32 fbw, u32 psm, s32 min_width
}
}
DbgCon.WriteLn("TC: New size at %x %u %u: %ux%u draw %lld", bp, fbw, psm, min_width, min_height, GSState::s_n);
DbgCon.WriteLn("TC: New size at %x %u %u: %ux%u draw %d", bp, fbw, psm, min_width, min_height, GSState::s_n);
m_target_heights.push_front(search);
return GSVector2i(min_width, min_height);
}
@@ -6956,7 +6956,7 @@ GSTextureCache::HashCacheEntry* GSTextureCache::LookupHashCache(const GIFRegTEX0
return &m_hash_cache.emplace(key, entry).first->second;
}
GSTextureCache::HashCacheMap::iterator GSTextureCache::RemoveFromHashCache(HashCacheMap::iterator it)
void GSTextureCache::RemoveFromHashCache(HashCacheMap::iterator it)
{
HashCacheEntry& e = it->second;
const u32 mem_usage = e.texture->GetMemUsage();
@@ -6965,7 +6965,7 @@ GSTextureCache::HashCacheMap::iterator GSTextureCache::RemoveFromHashCache(HashC
else
m_hash_cache_memory_usage -= mem_usage;
g_gs_device->Recycle(e.texture);
return m_hash_cache.erase(it);
m_hash_cache.erase(it);
}
void GSTextureCache::AgeHashCache()
@@ -6992,7 +6992,7 @@ void GSTextureCache::AgeHashCache()
if (++e.age > MAX_HASH_CACHE_AGE)
{
it = RemoveFromHashCache(it);
RemoveFromHashCache(it++);
continue;
}
@@ -7118,8 +7118,6 @@ GSTexture* GSTextureCache::LookupPaletteSource(u32 CBP, u32 CPSM, u32 CBW, GSVec
continue;
}
GSRendererHW::GetInstance()->m_mem.m_clut.SetGPUTextureDirty(t->m_last_draw, t->m_texture);
offset = this_offset;
*scale = t->m_scale;
@@ -7884,7 +7882,7 @@ void GSTextureCache::Target::Update(bool cannot_scale)
const GSTextureCache::TempZAddress z_address_info = g_texture_cache->GetTemporaryZInfo();
if (m_TEX0.TBP0 == z_address_info.ZBP)
{
//GL_CACHE("TC: RT in RT Updating Z copy on draw %lld z_offset %d", s_n, z_address_info.offset);
//GL_CACHE("TC: RT in RT Updating Z copy on draw %d z_offset %d", s_n, z_address_info.offset);
const GSVector4i dRect = GSVector4i(total_rect.x * m_scale, (z_address_info.offset + total_rect.y) * m_scale, (total_rect.z + (1.0f / m_scale)) * m_scale, (z_address_info.offset + total_rect.w + (1.0f / m_scale)) * m_scale);
g_gs_device->StretchRect(m_texture, GSVector4(total_rect.x / static_cast<float>(m_unscaled_size.x), total_rect.y / static_cast<float>(m_unscaled_size.y), (total_rect.z + (1.0f / m_scale)) / static_cast<float>(m_unscaled_size.x), (total_rect.w + (1.0f / m_scale)) / static_cast<float>(m_unscaled_size.y)), g_texture_cache->GetTemporaryZ(), GSVector4(dRect), ShaderConvert::DEPTH_COPY, false);
}
+2 -2
View File
@@ -242,7 +242,7 @@ public:
bool m_valid_rgb = false;
bool m_rt_alpha_scale = false;
bool m_downscaled = false;
u64 m_last_draw = 0;
int m_last_draw = 0;
bool m_is_frame = false;
bool m_used = false;
@@ -471,7 +471,7 @@ protected:
bool PrepareDownloadTexture(u32 width, u32 height, GSTexture::Format format, std::unique_ptr<GSDownloadTexture>* tex);
HashCacheEntry* LookupHashCache(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, bool& paltex, const u32* clut, const GSVector2i* lod, SourceRegion region);
HashCacheMap::iterator RemoveFromHashCache(HashCacheMap::iterator it);
void RemoveFromHashCache(HashCacheMap::iterator it);
void AgeHashCache();
static void PreloadTexture(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, SourceRegion region, GSLocalMemory& mem, bool paltex, GSTexture* tex, u32 level, std::pair<u8, u8>* alpha_minmax);
+14 -14
View File
@@ -181,7 +181,7 @@ GSTexture* GSRendererSW::GetOutput(int i, float& scale, int& y_offset)
if (GSConfig.SaveFrame && GSConfig.ShouldDump(s_n, g_perfmon.GetFrame()))
{
m_texture[index]->Save(GetDrawDumpPath("%05lld_f%05lld_fr%d_%05x_%s.bmp", s_n, g_perfmon.GetFrame(), i, (int)curFramebuffer.Block(), GSUtil::GetPSMName(curFramebuffer.PSM)));
m_texture[index]->Save(GetDrawDumpPath("%05d_f%05lld_fr%d_%05x_%s.bmp", s_n, g_perfmon.GetFrame(), i, (int)curFramebuffer.Block(), GSUtil::GetPSMName(curFramebuffer.PSM)));
}
}
@@ -556,11 +556,11 @@ void GSRendererSW::Draw()
if (texture_shuffle)
{
// Dump the RT in 32 bits format. It helps to debug texture shuffle effect
s = GetDrawDumpPath("%05lld_f%05lld_itexraw_%05x_32bits.bmp", s_n, frame, (int)m_context->TEX0.TBP0);
s = GetDrawDumpPath("%05d_f%05lld_itexraw_%05x_32bits.bmp", s_n, frame, (int)m_context->TEX0.TBP0);
m_mem.SaveBMP(s, m_context->TEX0.TBP0, m_context->TEX0.TBW, 0, 1 << m_context->TEX0.TW, 1 << m_context->TEX0.TH);
}
s = GetDrawDumpPath("%05lld_f%05lld_itexraw_%05x_%s.bmp", s_n, frame, (int)m_context->TEX0.TBP0, GSUtil::GetPSMName(m_context->TEX0.PSM));
s = GetDrawDumpPath("%05d_f%05lld_itexraw_%05x_%s.bmp", s_n, frame, (int)m_context->TEX0.TBP0, GSUtil::GetPSMName(m_context->TEX0.PSM));
m_mem.SaveBMP(s, m_context->TEX0.TBP0, m_context->TEX0.TBW, m_context->TEX0.PSM, 1 << m_context->TEX0.TW, 1 << m_context->TEX0.TH);
}
@@ -570,17 +570,17 @@ void GSRendererSW::Draw()
if (texture_shuffle)
{
// Dump the RT in 32 bits format. It helps to debug texture shuffle effect
s = GetDrawDumpPath("%05lld_f%05lld_rt0_%05x_32bits.bmp", s_n, frame, m_context->FRAME.Block());
s = GetDrawDumpPath("%05d_f%05lld_rt0_%05x_32bits.bmp", s_n, frame, m_context->FRAME.Block());
m_mem.SaveBMP(s, m_context->FRAME.Block(), m_context->FRAME.FBW, 0, r.z, r.w);
}
s = GetDrawDumpPath("%05lld_f%05lld_rt0_%05x_%s.bmp", s_n, frame, m_context->FRAME.Block(), GSUtil::GetPSMName(m_context->FRAME.PSM));
s = GetDrawDumpPath("%05d_f%05lld_rt0_%05x_%s.bmp", s_n, frame, m_context->FRAME.Block(), GSUtil::GetPSMName(m_context->FRAME.PSM));
m_mem.SaveBMP(s, m_context->FRAME.Block(), m_context->FRAME.FBW, m_context->FRAME.PSM, r.z, r.w);
}
if (GSConfig.SaveDepth)
{
s = GetDrawDumpPath("%05lld_f%05lld_rz0_%05x_%s.bmp", s_n, frame, m_context->ZBUF.Block(), GSUtil::GetPSMName(m_context->ZBUF.PSM));
s = GetDrawDumpPath("%05d_f%05lld_rz0_%05x_%s.bmp", s_n, frame, m_context->ZBUF.Block(), GSUtil::GetPSMName(m_context->ZBUF.PSM));
m_mem.SaveBMP(s, m_context->ZBUF.Block(), m_context->FRAME.FBW, m_context->ZBUF.PSM, r.z, r.w);
}
@@ -594,17 +594,17 @@ void GSRendererSW::Draw()
if (texture_shuffle)
{
// Dump the RT in 32 bits format. It helps to debug texture shuffle effect
s = GetDrawDumpPath("%05lld_f%05lld_rt1_%05x_32bits.bmp", s_n, frame, m_context->FRAME.Block());
s = GetDrawDumpPath("%05d_f%05lld_rt1_%05x_32bits.bmp", s_n, frame, m_context->FRAME.Block());
m_mem.SaveBMP(s, m_context->FRAME.Block(), m_context->FRAME.FBW, 0, r.z, r.w);
}
s = GetDrawDumpPath("%05lld_f%05lld_rt1_%05x_%s.bmp", s_n, frame, m_context->FRAME.Block(), GSUtil::GetPSMName(m_context->FRAME.PSM));
s = GetDrawDumpPath("%05d_f%05lld_rt1_%05x_%s.bmp", s_n, frame, m_context->FRAME.Block(), GSUtil::GetPSMName(m_context->FRAME.PSM));
m_mem.SaveBMP(s, m_context->FRAME.Block(), m_context->FRAME.FBW, m_context->FRAME.PSM, r.z, r.w);
}
if (GSConfig.SaveDepth)
{
s = GetDrawDumpPath("%05lld_f%05lld_rz1_%05x_%s.bmp", s_n, frame, m_context->ZBUF.Block(), GSUtil::GetPSMName(m_context->ZBUF.PSM));
s = GetDrawDumpPath("%05d_f%05lld_rz1_%05x_%s.bmp", s_n, frame, m_context->ZBUF.Block(), GSUtil::GetPSMName(m_context->ZBUF.PSM));
m_mem.SaveBMP(s, m_context->ZBUF.Block(), m_context->FRAME.FBW, m_context->ZBUF.PSM, r.z, r.w);
}
@@ -687,14 +687,14 @@ void GSRendererSW::Sync(int reason)
if (GSConfig.SaveRT)
{
s = GetDrawDumpPath("%05lld_f%05lld_rt1_%05x_%s.bmp", s_n, g_perfmon.GetFrame(), m_context->FRAME.Block(), GSUtil::GetPSMName(m_context->FRAME.PSM));
s = GetDrawDumpPath("%05d_f%05lld_rt1_%05x_%s.bmp", s_n, g_perfmon.GetFrame(), m_context->FRAME.Block(), GSUtil::GetPSMName(m_context->FRAME.PSM));
m_mem.SaveBMP(s, m_context->FRAME.Block(), m_context->FRAME.FBW, m_context->FRAME.PSM, PCRTCDisplays.GetFramebufferRect(-1).width(), 512);
}
if (GSConfig.SaveDepth)
{
s = GetDrawDumpPath("%05lld_f%05lld_zb1_%05x_%s.bmp", s_n, g_perfmon.GetFrame(), m_context->ZBUF.Block(), GSUtil::GetPSMName(m_context->ZBUF.PSM));
s = GetDrawDumpPath("%05d_f%05lld_zb1_%05x_%s.bmp", s_n, g_perfmon.GetFrame(), m_context->ZBUF.Block(), GSUtil::GetPSMName(m_context->ZBUF.PSM));
m_mem.SaveBMP(s, m_context->ZBUF.Block(), m_context->FRAME.FBW, m_context->ZBUF.PSM, PCRTCDisplays.GetFramebufferRect(-1).width(), 512);
}
@@ -706,7 +706,7 @@ void GSRendererSW::Sync(int reason)
if constexpr (LOG)
{
fprintf(s_fp, "sync n=%lld r=%d t=%" PRIu64 " p=%d %c\n", s_n, reason, t, pixels, t > 10000000 ? '*' : ' ');
fprintf(s_fp, "sync n=%d r=%d t=%" PRIu64 " p=%d %c\n", s_n, reason, t, pixels, t > 10000000 ? '*' : ' ');
fflush(s_fp);
}
@@ -1656,14 +1656,14 @@ void GSRendererSW::SharedData::UpdateSource()
{
const GIFRegTEX0& TEX0 = g_gs_renderer->GetTex0Layer(i);
s = GetDrawDumpPath("%05lld_f%05lld_itex%d_%05x_%s.bmp", g_gs_renderer->s_n, frame, i, TEX0.TBP0, GSUtil::GetPSMName(TEX0.PSM));
s = GetDrawDumpPath("%05d_f%05lld_itex%d_%05x_%s.bmp", g_gs_renderer->s_n, frame, i, TEX0.TBP0, GSUtil::GetPSMName(TEX0.PSM));
m_tex[i].t->Save(s);
}
if (global.clut)
{
s = GetDrawDumpPath("%05lld_f%05lld_itexp_%05x_%s.bmp", g_gs_renderer->s_n, frame, (int)g_gs_renderer->m_context->TEX0.CBP, GSUtil::GetPSMName(g_gs_renderer->m_context->TEX0.CPSM));
s = GetDrawDumpPath("%05d_f%05lld_itexp_%05x_%s.bmp", g_gs_renderer->s_n, frame, (int)g_gs_renderer->m_context->TEX0.CBP, GSUtil::GetPSMName(g_gs_renderer->m_context->TEX0.CPSM));
GSPng::Save((IsDevBuild || GSConfig.SaveAlpha) ? GSPng::RGB_A_PNG : GSPng::RGB_PNG, s, reinterpret_cast<const u8*>(global.clut), 256, 1, sizeof(u32) * 256, GSConfig.PNGCompressionLevel, false);
}
}
+56 -16
View File
@@ -629,8 +629,9 @@ bool GSDeviceVK::CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT};
VkPhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesEXT attachment_feedback_loop_feature = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_FEATURES_EXT};
// VK_EXT_swapchain_maintenance1 types/enums are aliases of VK_KHR_swapchain_maintenance1 types/enums.
VkPhysicalDeviceSwapchainMaintenance1FeaturesKHR swapchain_maintenance1_feature = {
VkPhysicalDeviceSwapchainMaintenance1FeaturesEXT swapchain_maintenance1_ext_feature = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_EXT};
VkPhysicalDeviceSwapchainMaintenance1FeaturesKHR swapchain_maintenance1_khr_feature = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_KHR};
if (m_optional_extensions.vk_ext_provoking_vertex)
@@ -655,8 +656,16 @@ bool GSDeviceVK::CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer
}
if (m_optional_extensions.vk_swapchain_maintenance1)
{
swapchain_maintenance1_feature.swapchainMaintenance1 = VK_TRUE;
Vulkan::AddPointerToChain(&device_info, &swapchain_maintenance1_feature);
if (m_optional_extensions.vk_swapchain_maintenance1_is_khr)
{
swapchain_maintenance1_khr_feature.swapchainMaintenance1 = VK_TRUE;
Vulkan::AddPointerToChain(&device_info, &swapchain_maintenance1_khr_feature);
}
else
{
swapchain_maintenance1_ext_feature.swapchainMaintenance1 = VK_TRUE;
Vulkan::AddPointerToChain(&device_info, &swapchain_maintenance1_ext_feature);
}
}
VkResult res = vkCreateDevice(m_physical_device, &device_info, nullptr, &m_device);
@@ -723,8 +732,9 @@ bool GSDeviceVK::ProcessDeviceExtensions()
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT};
VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesEXT rasterization_order_access_feature = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_EXT};
// VK_EXT_swapchain_maintenance1 types/enums are aliases of VK_KHR_swapchain_maintenance1 types/enums.
VkPhysicalDeviceSwapchainMaintenance1FeaturesKHR swapchain_maintenance1_feature = {
VkPhysicalDeviceSwapchainMaintenance1FeaturesEXT swapchain_maintenance1_ext_feature = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_EXT, nullptr, VK_TRUE};
VkPhysicalDeviceSwapchainMaintenance1FeaturesKHR swapchain_maintenance1_khr_feature = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_KHR, nullptr, VK_TRUE};
VkPhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesEXT attachment_feedback_loop_feature = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_FEATURES_EXT};
@@ -738,8 +748,10 @@ bool GSDeviceVK::ProcessDeviceExtensions()
Vulkan::AddPointerToChain(&features2, &rasterization_order_access_feature);
if (m_optional_extensions.vk_ext_attachment_feedback_loop_layout)
Vulkan::AddPointerToChain(&features2, &attachment_feedback_loop_feature);
if (m_optional_extensions.vk_swapchain_maintenance1)
Vulkan::AddPointerToChain(&features2, &swapchain_maintenance1_feature);
if (m_optional_extensions.vk_swapchain_maintenance1 && m_optional_extensions.vk_swapchain_maintenance1_is_khr)
Vulkan::AddPointerToChain(&features2, &swapchain_maintenance1_khr_feature);
if (m_optional_extensions.vk_swapchain_maintenance1 && !m_optional_extensions.vk_swapchain_maintenance1_is_khr)
Vulkan::AddPointerToChain(&features2, &swapchain_maintenance1_ext_feature);
// query
vkGetPhysicalDeviceFeatures2(m_physical_device, &features2);
@@ -814,8 +826,9 @@ bool GSDeviceVK::ProcessDeviceExtensions()
m_optional_extensions.vk_ext_calibrated_timestamps = false;
}
m_optional_extensions.vk_swapchain_maintenance1 &=
(swapchain_maintenance1_feature.swapchainMaintenance1 == VK_TRUE);
m_optional_extensions.vk_swapchain_maintenance1 &= m_optional_extensions.vk_swapchain_maintenance1_is_khr ?
(swapchain_maintenance1_khr_feature.swapchainMaintenance1 == VK_TRUE) :
(swapchain_maintenance1_ext_feature.swapchainMaintenance1 == VK_TRUE);
Console.WriteLn(
"VK_EXT_provoking_vertex is %s", m_optional_extensions.vk_ext_provoking_vertex ? "supported" : "NOT supported");
@@ -5804,11 +5817,26 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
Console.Warning("VK: Failed to allocate temp texture for RT copy.");
}
// We don't need the very first barrier if this is the first draw after switching to feedback loop,
// because the layout change in itself enforces the execution dependency. colclip hw needs a barrier between
// setup and the first draw to read it. TODO: Make colclip hw use subpasses instead.
// However, it turns out *not* doing this causes GPU resets on RDNA3, specifically Windows drivers.
// Despite the layout changing enforcing the execution dependency between previous draws and the first
// input attachment read, it still wants the region/fragment-local barrier...
const bool skip_first_barrier =
(draw_rt && draw_rt->GetLayout() != GSTextureVK::Layout::FeedbackLoop && !pipe.ps.colclip_hw && !IsDeviceAMD());
OMSetRenderTargets(draw_rt, draw_ds, config.scissor, static_cast<FeedbackLoopFlag>(pipe.feedback_loop_flags));
if (pipe.IsRTFeedbackLoop())
{
pxAssertMsg(m_features.texture_barrier, "Texture barriers enabled");
PSSetShaderResource(2, draw_rt, false);
// If this is the first draw to the target as a feedback loop, make sure we re-generate the texture descriptor.
// Otherwise, we might have a previous descriptor left over, that has the RT in a different state.
m_dirty_flags |= (skip_first_barrier ? static_cast<u32>(DIRTY_FLAG_TFX_TEXTURE_RT) : 0);
}
// Begin render pass if new target or out of the area.
@@ -5883,7 +5911,7 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
// now we can do the actual draw
if (BindDrawPipeline(pipe))
SendHWDraw(config, draw_rt, config.require_one_barrier, config.require_full_barrier);
SendHWDraw(config, draw_rt, config.require_one_barrier, config.require_full_barrier, skip_first_barrier);
// blend second pass
if (config.blend_multi_pass.enable)
@@ -5919,7 +5947,7 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
if (BindDrawPipeline(pipe))
{
SendHWDraw(config, draw_rt, config.alpha_second_pass.require_one_barrier,
config.alpha_second_pass.require_full_barrier);
config.alpha_second_pass.require_full_barrier, false);
}
}
@@ -6042,7 +6070,7 @@ VkDependencyFlags GSDeviceVK::GetColorBufferBarrierFlags() const
}
void GSDeviceVK::SendHWDraw(const GSHWDrawConfig& config, GSTextureVK* draw_rt,
bool one_barrier, bool full_barrier)
bool one_barrier, bool full_barrier, bool skip_first_barrier)
{
if (!m_features.texture_barrier) [[unlikely]]
{
@@ -6064,9 +6092,21 @@ void GSDeviceVK::SendHWDraw(const GSHWDrawConfig& config, GSTextureVK* draw_rt,
const u32 draw_list_size = static_cast<u32>(config.drawlist->size());
GL_PUSH("Split the draw");
g_perfmon.Put(GSPerfMon::Barriers, static_cast<u32>(draw_list_size));
g_perfmon.Put(
GSPerfMon::Barriers, static_cast<u32>(draw_list_size) - static_cast<u32>(skip_first_barrier));
for (u32 n = 0, p = 0; n < draw_list_size; n++)
u32 p = 0;
u32 n = 0;
if (skip_first_barrier)
{
const u32 count = (*config.drawlist)[n] * indices_per_prim;
DrawIndexedPrimitive(p, count);
p += count;
++n;
}
for (; n < draw_list_size; n++)
{
vkCmdPipelineBarrier(GetCurrentCommandBuffer(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, barrier_flags, 0, nullptr, 0, nullptr, 1, &barrier);
@@ -6079,7 +6119,7 @@ void GSDeviceVK::SendHWDraw(const GSHWDrawConfig& config, GSTextureVK* draw_rt,
return;
}
if (one_barrier)
if (one_barrier && !skip_first_barrier)
{
g_perfmon.Put(GSPerfMon::Barriers, 1);

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