mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-07-13 18:54:27 +02:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6b752a888e |
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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: "電車でGO!FINAL [体験版]"
|
||||
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"
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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;
|
||||
};
|
||||
};
|
||||
@@ -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"))
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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, []() {
|
||||
|
||||
@@ -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."));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ public slots:
|
||||
void contextCopyInstructionHex();
|
||||
void contextCopyInstructionText();
|
||||
void contextCopyFunctionName();
|
||||
void contextPasteInstructionText();
|
||||
void contextPasteInstructionText();
|
||||
void contextAssembleInstruction();
|
||||
void contextNoopInstruction();
|
||||
void contextRestoreInstruction();
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"));
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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(¤tFloatVal, ¤tIntVal, 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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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."));
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
@@ -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).
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,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);
|
||||
|
||||
|
||||
@@ -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) <a href="https://pcsx2.net/docs/advanced/cli/">custom arguments</a> 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) <a href="https://pcsx2.net/docs/advanced/cli/">custom arguments</a> 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>
|
||||
|
||||
@@ -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
@@ -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" />
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user