mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-07-31 03:08:40 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
054cb9e9fa | ||
|
|
1f77e7d90a | ||
|
|
7ed33832b8 | ||
|
|
d19e9cc662 | ||
|
|
846c9cec6a | ||
|
|
460e4b8bb3 | ||
|
|
2e6bd23f22 | ||
|
|
7763948fe4 | ||
|
|
2a0f001902 | ||
|
|
14df69e180 | ||
|
|
28b6389b36 | ||
|
|
905c0b8c7a | ||
|
|
b674cc95ac | ||
|
|
bccb2509b5 | ||
|
|
cd980c6604 | ||
|
|
ddff4ec083 | ||
|
|
5bf97be8ef | ||
|
|
7fadb6ed05 | ||
|
|
89688d67dd | ||
|
|
279007544a | ||
|
|
1c0f0e1423 | ||
|
|
1ab909addc | ||
|
|
99dfd15469 | ||
|
|
be18ecf74e | ||
|
|
713bd132dc | ||
|
|
20f03e237e | ||
|
|
7d3c3911ea | ||
|
|
ccfee2be83 | ||
|
|
1193b0b990 | ||
|
|
5a3ba4e563 | ||
|
|
e9c342ef74 | ||
|
|
8927ffa035 | ||
|
|
fdb0312326 | ||
|
|
2f21caa41c | ||
|
|
51a35d40e5 | ||
|
|
6ec524adec | ||
|
|
7d4a7ec8c7 | ||
|
|
0256c4521d | ||
|
|
be3ed181c1 | ||
|
|
38cf7884fe | ||
|
|
25d426e8b2 | ||
|
|
edff9ae684 | ||
|
|
a622e3bda6 | ||
|
|
4d54e28e63 | ||
|
|
c89d023f91 | ||
|
|
c7cfea1daa | ||
|
|
beb07365a0 | ||
|
|
0787c65e51 | ||
|
|
d48dea7273 | ||
|
|
2432cc6ed2 | ||
|
|
cf523d4215 | ||
|
|
906d87c4b8 | ||
|
|
9c4a92c015 | ||
|
|
0c056ba691 | ||
|
|
424158b28d | ||
|
|
57f118a5b5 | ||
|
|
65e75f3da2 | ||
|
|
41174cde45 | ||
|
|
cb7d01fb36 | ||
|
|
3e78f8e87d | ||
|
|
f2c032ba07 | ||
|
|
2ef1589e76 | ||
|
|
5c394557e3 | ||
|
|
5c4a5b0a61 | ||
|
|
be22b7349d | ||
|
|
023e4774a1 | ||
|
|
56b706f25e | ||
|
|
9d07ee43eb | ||
|
|
147a6c81a1 | ||
|
|
5972f4947d | ||
|
|
9c99a624d7 | ||
|
|
d812d83dda | ||
|
|
f81c5c2455 | ||
|
|
dc8c5e6209 | ||
|
|
14833582b2 | ||
|
|
cca813fd1d | ||
|
|
d4102e75c5 | ||
|
|
76a04efc5c | ||
|
|
a34e139843 | ||
|
|
a1727a2ac7 | ||
|
|
7ac224adf3 | ||
|
|
d5e3d02a98 | ||
|
|
68ad3e8db4 | ||
|
|
31029b2fe4 | ||
|
|
8b0c101768 | ||
|
|
50b66f526b | ||
|
|
f3fcf010fb | ||
|
|
4da53bd00d | ||
|
|
c6cef45f0e | ||
|
|
e36cd7fe5c | ||
|
|
0c24f2db7b | ||
|
|
8866faa8d5 | ||
|
|
b2dc31ba80 | ||
|
|
061ea30199 | ||
|
|
0e9e94d090 | ||
|
|
3321cb37ef | ||
|
|
d60a818791 | ||
|
|
3937a52b4f | ||
|
|
2c3902b1a1 | ||
|
|
f43b5ee76f | ||
|
|
bab16a5251 | ||
|
|
08c734d7fd | ||
|
|
36126a3ad9 | ||
|
|
ce505d33bd | ||
|
|
de0d859502 | ||
|
|
ce96d4bcc5 | ||
|
|
fb242274d5 | ||
|
|
938bc7cdd7 | ||
|
|
36865f2930 | ||
|
|
12e79cccf6 | ||
|
|
6180f12ba3 | ||
|
|
c00b6c6237 | ||
|
|
dbdc74fdef | ||
|
|
5bb0a07164 | ||
|
|
543f09999f | ||
|
|
812f32efdd | ||
|
|
784264eba4 | ||
|
|
ff9ca059c7 | ||
|
|
d4b0c39485 | ||
|
|
87c42aeaf4 | ||
|
|
5ba6e57c71 | ||
|
|
6d2ba5c2d0 | ||
|
|
0d42b81285 | ||
|
|
9ce2ae613b | ||
|
|
13c9e0e666 | ||
|
|
784118e9c1 | ||
|
|
df32a32d99 | ||
|
|
655241aed3 | ||
|
|
60a2b246e2 | ||
|
|
ebd60d93f3 | ||
|
|
cc4ba935b5 | ||
|
|
824147fd7d | ||
|
|
c3446a16cc | ||
|
|
82135d1892 | ||
|
|
1cff63bc01 | ||
|
|
e488e74313 | ||
|
|
1a17c9da86 | ||
|
|
20e1f773fc | ||
|
|
56d80ff293 | ||
|
|
80e176136a | ||
|
|
0ae66d3e24 | ||
|
|
802ab8238e | ||
|
|
ec9c07a646 | ||
|
|
b75ad663f2 | ||
|
|
e4a017fc00 | ||
|
|
5b486ca6b8 | ||
|
|
1c39ed6130 | ||
|
|
a47563b12f | ||
|
|
84491ff655 | ||
|
|
e5991a4379 | ||
|
|
0b3d4615b8 | ||
|
|
a8f6336b47 | ||
|
|
0b33df3341 | ||
|
|
744cc4b705 | ||
|
|
9d3cd5784f | ||
|
|
06ea58198a | ||
|
|
3692d7d090 | ||
|
|
460a2dbbd3 | ||
|
|
228f4f1010 | ||
|
|
2703b91e41 | ||
|
|
24171787f8 | ||
|
|
49d3338d4a | ||
|
|
a9d693e1c3 | ||
|
|
4ef69248d0 | ||
|
|
247b3ed740 | ||
|
|
1edca6235c | ||
|
|
ab5c03b1d9 | ||
|
|
d4cb35469d | ||
|
|
fd1b1d0c24 | ||
|
|
bf96ceeacc | ||
|
|
2c08b385e5 | ||
|
|
051d13ec7a | ||
|
|
a2a9643123 | ||
|
|
1286bfe75b | ||
|
|
1f74f82796 | ||
|
|
876b576679 | ||
|
|
c927e4785b | ||
|
|
97672828e8 | ||
|
|
b96978494b | ||
|
|
2f105cbe15 | ||
|
|
2539a07b7d | ||
|
|
73f903f402 | ||
|
|
94c48a4c2d | ||
|
|
eb8d938c94 | ||
|
|
92b8316182 | ||
|
|
610cb2626b | ||
|
|
2033f813da | ||
|
|
a6fbd0fe69 | ||
|
|
abadb7f80f | ||
|
|
1c6be3f400 | ||
|
|
52111be20a | ||
|
|
eae29bb1f2 | ||
|
|
9191e8ce91 | ||
|
|
2b4c7d12b6 | ||
|
|
7dd1f7321a | ||
|
|
088630a999 | ||
|
|
d2a5cdcca7 | ||
|
|
4b50d016b5 | ||
|
|
7a073e0e8d | ||
|
|
b56958abe4 | ||
|
|
57d042ca4a | ||
|
|
3895f3c826 | ||
|
|
75aed7c44f | ||
|
|
041c0ce86c | ||
|
|
90aabdf499 | ||
|
|
40f7ec3ca1 | ||
|
|
1e32fcaebe | ||
|
|
9f23755a62 | ||
|
|
dad03478fd | ||
|
|
484b75f755 | ||
|
|
7138faa5cd | ||
|
|
fef1706fc8 | ||
|
|
1929b20a6c | ||
|
|
3991ff5d3a | ||
|
|
e4b1c89719 | ||
|
|
3d51eec89c | ||
|
|
f9016f3ea7 | ||
|
|
3dce969a5e | ||
|
|
542d257b8f | ||
|
|
2eb7c47572 |
+4
-4
@@ -115,11 +115,11 @@
|
||||
- 'pcsx2/IPU/*'
|
||||
- 'pcsx2/IPU/**/*'
|
||||
'Memory Card':
|
||||
- 'pcsx2/gui/MemoryCard*'
|
||||
- 'pcsx2/gui/**/MemoryCard*'
|
||||
- 'pcsx2/SIO/Memcard/*'
|
||||
- 'pcsx2/SIO/Memcard/**/*'
|
||||
'PAD':
|
||||
- 'pcsx2/PAD/*'
|
||||
- 'pcsx2/PAD/**/*'
|
||||
- 'pcsx2/SIO/Pad/*'
|
||||
- 'pcsx2/SIO/Pad/**/*'
|
||||
'SPU2':
|
||||
- 'pcsx2/SPU2/*'
|
||||
- 'pcsx2/SPU2/**/*'
|
||||
|
||||
@@ -37,5 +37,6 @@ jobs:
|
||||
cmakeflags: ""
|
||||
publish: true
|
||||
branch: stable
|
||||
fetchTags: true
|
||||
secrets: inherit
|
||||
|
||||
|
||||
@@ -67,9 +67,9 @@ jobs:
|
||||
brew unlink libjpeg || true # Conflicts with our self-built dependencies
|
||||
brew unlink libpng || true
|
||||
# Unlike other packages, brew's MoltenVK build uses MoltenVK's minimum macOS version of 10.13 so we can use it
|
||||
if ! brew install molten-vk ccache; then
|
||||
if ! brew install molten-vk ccache nasm; then
|
||||
brew update
|
||||
brew install molten-vk ccache
|
||||
brew install molten-vk ccache nasm
|
||||
fi
|
||||
|
||||
- name: Cache Dependencies
|
||||
@@ -105,10 +105,12 @@ jobs:
|
||||
cmake -DCMAKE_PREFIX_PATH="$HOME/deps" \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DUSE_OPENGL=OFF \
|
||||
-DUSE_VULKAN=OFF \
|
||||
-DDISABLE_ADVANCE_SIMD=ON \
|
||||
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON \
|
||||
-DUSE_SYSTEM_LIBS=OFF \
|
||||
-DUSE_SYSTEM_SDL2=ON \
|
||||
-DUSE_LINKED_FFMPEG=ON \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON \
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
name: 📢 Announce Release
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
announce:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
|
||||
- name: Announce Release
|
||||
env:
|
||||
DISCORD_BUILD_WEBHOOK: ${{ secrets.DISCORD_BUILD_WEBHOOK }}
|
||||
run: |
|
||||
cd ./.github/workflows/scripts/releases/announce-release
|
||||
npm ci
|
||||
node index.js
|
||||
@@ -27,8 +27,10 @@ permissions:
|
||||
jobs:
|
||||
cut-release:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
runs-on: ubuntu-latest
|
||||
name: "Create Tag and Release"
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
new_tag: ${{ steps.tag_version.outputs.new_tag }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
@@ -131,6 +133,7 @@ jobs:
|
||||
upload_artifacts:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
needs:
|
||||
- cut-release
|
||||
- build_linux_flatpak
|
||||
- build_linux_qt
|
||||
- build_windows_qt
|
||||
@@ -140,10 +143,6 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
# actions/checkout elides tags, fetch them primarily for releases
|
||||
- name: Fetch Tags
|
||||
run: git fetch --tags --no-recurse-submodules
|
||||
|
||||
- name: Prepare Artifact Folder
|
||||
run: mkdir ./ci-artifacts/
|
||||
|
||||
@@ -169,7 +168,7 @@ jobs:
|
||||
SCAN_DIR: ${{ github.WORKSPACE }}/ci-artifacts
|
||||
OUT_DIR: ${{ github.WORKSPACE }}/ci-artifacts/out
|
||||
run: |
|
||||
TAG_VAL=$(git tag --points-at HEAD)
|
||||
TAG_VAL=${{needs.cut-release.outputs.new_tag}}
|
||||
echo "TAG_VAL=${TAG_VAL}"
|
||||
gh release list --repo PCSX2/pcsx2
|
||||
mkdir -p ${{ github.WORKSPACE }}/ci-artifacts/out
|
||||
@@ -181,6 +180,22 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
TAG_VAL=$(git tag --points-at HEAD)
|
||||
TAG_VAL=${{needs.cut-release.outputs.new_tag}}
|
||||
echo "TAG_VAL=${TAG_VAL}"
|
||||
gh release edit ${TAG_VAL} --draft=false --repo PCSX2/pcsx2
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
|
||||
- name: Announce Release
|
||||
env:
|
||||
OWNER: PCSX2
|
||||
REPO: pcsx2
|
||||
DISCORD_BUILD_WEBHOOK: ${{ secrets.DISCORD_BUILD_WEBHOOK }}
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
TAG_VAL=${{needs.cut-release.outputs.new_tag}}
|
||||
cd ./.github/workflows/scripts/releases/announce-release
|
||||
npm ci
|
||||
TAG_VAL=${TAG_VAL} node index.js
|
||||
|
||||
@@ -78,16 +78,33 @@ OUTDIR=$(realpath "./$APPDIRNAME")
|
||||
SCRIPTDIR=$(dirname "${BASH_SOURCE[0]}")
|
||||
rm -fr "$OUTDIR"
|
||||
|
||||
# Why the nastyness? linuxdeploy strips our main binary, and there's no option to turn it off.
|
||||
# It also doesn't strip the Qt libs. We can't strip them after running linuxdeploy, because
|
||||
# patchelf corrupts the libraries (but they still work), but patchelf+strip makes them crash
|
||||
# on load. So, make a backup copy, strip the original (since that's where linuxdeploy finds
|
||||
# the libs to copy), then swap them back after we're done.
|
||||
# Isn't Linux packaging amazing?
|
||||
|
||||
rm -fr "$DEPSDIR.bak"
|
||||
cp -a "$DEPSDIR" "$DEPSDIR.bak"
|
||||
IFS="
|
||||
"
|
||||
for i in $(find "$DEPSDIR" -iname '*.so'); do
|
||||
echo "Stripping deps library ${i}"
|
||||
strip "$i"
|
||||
done
|
||||
|
||||
echo "Copying desktop file..."
|
||||
cp "$PCSX2DIR/.github/workflows/scripts/linux/pcsx2-qt.desktop" .
|
||||
cp "$PCSX2DIR/.github/workflows/scripts/linux/pcsx2-qt.desktop" "net.pcsx2.PCSX2.desktop"
|
||||
cp "$PCSX2DIR/bin/resources/icons/AppIconLarge.png" "PCSX2.png"
|
||||
|
||||
echo "Running linuxdeploy to create AppDir..."
|
||||
EXTRA_QT_PLUGINS="core;gui;network;svg;waylandclient;widgets;xcbqpa" \
|
||||
EXTRA_PLATFORM_PLUGINS="libqwayland-egl.so;libqwayland-generic.so" \
|
||||
QMAKE="$DEPSDIR/bin/qmake" \
|
||||
NO_STRIP="1" \
|
||||
$LINUXDEPLOY --plugin qt --appdir="$OUTDIR" --executable="$BUILDDIR/bin/pcsx2-qt" \
|
||||
--desktop-file="pcsx2-qt.desktop" --icon-file="PCSX2.png"
|
||||
--desktop-file="net.pcsx2.PCSX2.desktop" --icon-file="PCSX2.png"
|
||||
|
||||
echo "Copying resources into AppDir..."
|
||||
cp -a "$BUILDDIR/bin/resources" "$OUTDIR/usr/bin"
|
||||
@@ -100,7 +117,6 @@ for lib in "${MANUAL_QT_LIBS[@]}"; do
|
||||
echo " $srcpath -> $dstpath"
|
||||
cp "$srcpath" "$dstpath"
|
||||
$PATCHELF --set-rpath '$ORIGIN' "$dstpath"
|
||||
$STRIP "$dstpath"
|
||||
done
|
||||
|
||||
# .. and plugins.
|
||||
@@ -118,15 +134,23 @@ for GROUP in "${MANUAL_QT_PLUGINS[@]}"; do
|
||||
echo " $srcsopath -> $dstsopath"
|
||||
cp "$srcsopath" "$dstsopath"
|
||||
$PATCHELF --set-rpath '$ORIGIN/../../lib:$ORIGIN' "$dstsopath"
|
||||
$STRIP "$dstsopath"
|
||||
done
|
||||
done
|
||||
|
||||
# Restore unstripped deps (for cache).
|
||||
rm -fr "$DEPSDIR"
|
||||
mv "$DEPSDIR.bak" "$DEPSDIR"
|
||||
|
||||
# Fix up translations.
|
||||
rm -fr "$OUTDIR/usr/bin/translations"
|
||||
mv "$OUTDIR/usr/translations" "$OUTDIR/usr/bin"
|
||||
cp -a "$BUILDDIR/bin/translations" "$OUTDIR/usr/bin"
|
||||
|
||||
# Generate AppStream meta-info.
|
||||
echo "Generating AppStream metainfo..."
|
||||
mkdir -p "$OUTDIR/usr/share/metainfo"
|
||||
"$SCRIPTDIR/generate-metainfo.sh" "$OUTDIR/usr/share/metainfo/net.pcsx2.PCSX2.appdata.xml"
|
||||
|
||||
echo "Generating AppImage..."
|
||||
rm -f "$NAME.AppImage"
|
||||
$APPIMAGETOOL -v "$OUTDIR" "$NAME.AppImage"
|
||||
|
||||
@@ -5,7 +5,7 @@ set -e
|
||||
INSTALLDIR="$HOME/deps"
|
||||
NPROCS="$(getconf _NPROCESSORS_ONLN)"
|
||||
SDL=SDL2-2.28.1
|
||||
QT=6.5.0
|
||||
QT=6.5.2
|
||||
LIBBACKTRACE=ad106d5fdd5d960bd33fae1c48a351af567fd075
|
||||
|
||||
mkdir -p deps-build
|
||||
@@ -14,17 +14,19 @@ cd deps-build
|
||||
cat > SHASUMS <<EOF
|
||||
4977ceba5c0054dbe6c2f114641aced43ce3bf2b41ea64b6a372d6ba129cb15d $SDL.tar.gz
|
||||
fd6f417fe9e3a071cf1424a5152d926a34c4a3c5070745470be6cf12a404ed79 $LIBBACKTRACE.zip
|
||||
fde1aa7b4fbe64ec1b4fc576a57f4688ad1453d2fab59cbadd948a10a6eaf5ef qtbase-everywhere-src-$QT.tar.xz
|
||||
64ca7e61f44d51e28bcbb4e0509299b53a9a7e38879e00a7fe91643196067a4f qtsvg-everywhere-src-$QT.tar.xz
|
||||
49c33d96b0a44988be954269b8ce3d1a495b439726e03a6be7c0d50a686369c4 qttools-everywhere-src-$QT.tar.xz
|
||||
fc85d0fd8393f518653ccada1014177a56df6e73f30f3b64eea0c2e4a0067a3d qttranslations-everywhere-src-$QT.tar.xz
|
||||
ccc57fa277fc5f1c1c2c4733eae80a60996b67a067233c47809e542aa31759a3 qtwayland-everywhere-src-$QT.tar.xz
|
||||
3db4c729b4d80a9d8fda8dd77128406353baff4755ca619177eda4cddae71269 qtbase-everywhere-src-$QT.tar.xz
|
||||
aae0c08924c6a5e47f9d57e031673d611ffff7aab2bee2e1cc460471ecac6743 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
48b4cc1093af2e0ab3bea30f60651bddd877a2335d16e7207879a2e9e81963a3 qtsvg-everywhere-src-$QT.tar.xz
|
||||
551ffb22751d8fd4d88e9ebd55b9131f4ca55341ee497fdbbba4da8d10d94341 qttools-everywhere-src-$QT.tar.xz
|
||||
337c45637e757e754c2f0ea65c20de3e6e53a841dda1253db15baa622515beeb qttranslations-everywhere-src-$QT.tar.xz
|
||||
3020be86fb7fd0abb8509906ca6583cadcaee168159abceaeb5b3e9d42563c9a qtwayland-everywhere-src-$QT.tar.xz
|
||||
EOF
|
||||
|
||||
curl -L \
|
||||
-O "https://libsdl.org/release/$SDL.tar.gz" \
|
||||
-O "https://github.com/ianlancetaylor/libbacktrace/archive/$LIBBACKTRACE.zip" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtbase-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtimageformats-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtsvg-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qttools-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qttranslations-everywhere-src-$QT.tar.xz" \
|
||||
@@ -73,6 +75,16 @@ cmake --build . --parallel
|
||||
cmake --install .
|
||||
cd ../../
|
||||
|
||||
echo "Building Qt Image Formats..."
|
||||
tar xf "qtimageformats-everywhere-src-$QT.tar.xz"
|
||||
cd "qtimageformats-everywhere-src-$QT"
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -G Ninja -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DCMAKE_BUILD_TYPE=Release ..
|
||||
cmake --build . --parallel
|
||||
cmake --install .
|
||||
cd ../../
|
||||
|
||||
echo "Building Qt Wayland..."
|
||||
tar xf "qtwayland-everywhere-src-$QT.tar.xz"
|
||||
cd "qtwayland-everywhere-src-$QT"
|
||||
|
||||
@@ -49,7 +49,7 @@ retry_command sudo flatpak -y install "${FLATPAK_PACKAGES[@]}"
|
||||
echo "Downloading flat-manager-client"
|
||||
mkdir -p "$FLAT_MANAGER_CLIENT_DIR"
|
||||
pushd "$FLAT_MANAGER_CLIENT_DIR"
|
||||
aria2c -Z "https://raw.githubusercontent.com/flatpak/flat-manager/master/flat-manager-client"
|
||||
aria2c -Z "https://raw.githubusercontent.com/flatpak/flat-manager/9401efbdc0d6bd489507d8401c567ba219d735d5/flat-manager-client"
|
||||
chmod +x flat-manager-client
|
||||
echo "$FLAT_MANAGER_CLIENT_DIR" >> $GITHUB_PATH
|
||||
popd
|
||||
|
||||
@@ -10,7 +10,8 @@ SDL=SDL2-2.28.1
|
||||
PNG=1.6.37
|
||||
JPG=9e
|
||||
SOUNDTOUCH=soundtouch-2.3.1
|
||||
QT=6.4.3
|
||||
FFMPEG=6.0
|
||||
QT=6.4.3 # Currently stuck on Qt 6.4 due to 6.5 requiring macOS 11.0.
|
||||
|
||||
mkdir deps-build
|
||||
cd deps-build
|
||||
@@ -25,7 +26,9 @@ cat > SHASUMS <<EOF
|
||||
505e70834d35383537b6491e7ae8641f1a4bed1876dbfe361201fc80868d88ca libpng-$PNG.tar.xz
|
||||
4077d6a6a75aeb01884f708919d25934c93305e49f7e3f36db9129320e6f4f3d jpegsrc.v$JPG.tar.gz
|
||||
6900996607258496ce126924a19fe9d598af9d892cf3f33d1e4daaa9b42ae0b1 $SOUNDTOUCH.tar.gz
|
||||
57be87c22d9b49c112b6d24bc67d42508660e6b718b3db89c44e47e289137082 ffmpeg-$FFMPEG.tar.xz
|
||||
5087c9e5b0165e7bc3c1a4ab176b35d0cd8f52636aea903fa377bdba00891a60 qtbase-everywhere-src-$QT.tar.xz
|
||||
0aff58062e74b84617c5da8325d8cdad5368d8f4d2a11ceafcd58329fe99b798 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
88315f886cf81898705e487cedba6e6160724359d23c518c92c333c098879a4a qtsvg-everywhere-src-$QT.tar.xz
|
||||
867df829cd5cd3ae8efe62e825503123542764b13c96953511e567df70c5a091 qttools-everywhere-src-$QT.tar.xz
|
||||
79e56b7800d49649a8a8010818538c367a829e0b7a09d5f60bd3aecf5abe972c qttranslations-everywhere-src-$QT.tar.xz
|
||||
@@ -36,7 +39,9 @@ curl -L \
|
||||
-O "https://downloads.sourceforge.net/project/libpng/libpng16/$PNG/libpng-$PNG.tar.xz" \
|
||||
-O "https://www.ijg.org/files/jpegsrc.v$JPG.tar.gz" \
|
||||
-O "https://www.surina.net/soundtouch/$SOUNDTOUCH.tar.gz" \
|
||||
-O "https://ffmpeg.org/releases/ffmpeg-$FFMPEG.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtbase-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtimageformats-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtsvg-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qttools-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qttranslations-everywhere-src-$QT.tar.xz" \
|
||||
@@ -75,6 +80,18 @@ make -C build "-j$NPROCS"
|
||||
make -C build install
|
||||
cd ..
|
||||
|
||||
echo "Installing FFmpeg..."
|
||||
tar xf "ffmpeg-$FFMPEG.tar.xz"
|
||||
cd "ffmpeg-$FFMPEG"
|
||||
./configure --prefix="$INSTALLDIR" --disable-all --disable-autodetect --disable-static --enable-shared \
|
||||
--enable-avcodec --enable-avformat --enable-avutil --enable-swresample --enable-swscale \
|
||||
--enable-audiotoolbox --enable-videotoolbox \
|
||||
--enable-encoder=ffv1,qtrle,pcm_s16be,pcm_s16le,*_at,*_videotoolbox \
|
||||
--enable-muxer=avi,matroska,mov,mp3,mp4,wav \
|
||||
--enable-protocol=file
|
||||
make "-j$NPROCS"
|
||||
make install
|
||||
cd ..
|
||||
|
||||
echo "Installing Qt Base..."
|
||||
tar xf "qtbase-everywhere-src-$QT.tar.xz"
|
||||
@@ -174,6 +191,13 @@ cmake -B build -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTAL
|
||||
make -C build "-j$NPROCS"
|
||||
make -C build install
|
||||
cd ..
|
||||
echo "Installing Qt Image Formats..."
|
||||
tar xf "qtimageformats-everywhere-src-$QT.tar.xz"
|
||||
cd "qtimageformats-everywhere-src-$QT"
|
||||
cmake -B build -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DCMAKE_BUILD_TYPE=MinSizeRel
|
||||
make -C build "-j$NPROCS"
|
||||
make -C build install
|
||||
cd ..
|
||||
echo "Installing Qt Tools..."
|
||||
tar xf "qttools-everywhere-src-$QT.tar.xz"
|
||||
cd "qttools-everywhere-src-$QT"
|
||||
|
||||
@@ -1,7 +1,58 @@
|
||||
import { MessageEmbed, WebhookClient } from "discord.js";
|
||||
import * as github from '@actions/github';
|
||||
import { Octokit } from "@octokit/rest";
|
||||
import { throttling } from "@octokit/plugin-throttling";
|
||||
import { retry } from "@octokit/plugin-retry";
|
||||
|
||||
const releaseInfo = github.context.payload.release;
|
||||
let owner = process.env.OWNER;
|
||||
let repo = process.env.REPO;
|
||||
|
||||
Octokit.plugin(throttling);
|
||||
Octokit.plugin(retry);
|
||||
const octokit = new Octokit({
|
||||
auth: process.env.GITHUB_TOKEN,
|
||||
userAgent: `${owner}/${repo}`,
|
||||
log: {
|
||||
debug: () => { },
|
||||
info: () => { },
|
||||
warn: console.warn,
|
||||
error: console.error
|
||||
},
|
||||
throttle: {
|
||||
onRateLimit: (retryAfter, options) => {
|
||||
octokit.log.warn(
|
||||
`Request quota exhausted for request ${options.method} ${options.url}`
|
||||
);
|
||||
|
||||
// Retry twice after hitting a rate limit error, then give up
|
||||
if (options.request.retryCount <= 2) {
|
||||
console.log(`Retrying after ${retryAfter} seconds!`);
|
||||
return true;
|
||||
}
|
||||
},
|
||||
onAbuseLimit: (retryAfter, options) => {
|
||||
// does not retry, only logs a warning
|
||||
octokit.log.warn(
|
||||
`Abuse detected for request ${options.method} ${options.url}`
|
||||
);
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
if (process.env.TAG_VAL === undefined || process.env.TAG_VAL === "") {
|
||||
console.log(`Not announcing - TAG_VAL not defined`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const { data: releaseInfo } = await octokit.rest.repos.getReleaseByTag({
|
||||
owner: owner,
|
||||
repo: repo,
|
||||
tag: process.env.TAG_VAL,
|
||||
});
|
||||
|
||||
if (releaseInfo === undefined) {
|
||||
console.log(`Not announcing - could not locate release with tag ${process.env.TAG_VAL}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!releaseInfo.prerelease) {
|
||||
console.log("Not announcing - release was not a pre-release (aka a Nightly)");
|
||||
@@ -18,6 +69,7 @@ const embed = new MessageEmbed()
|
||||
{ name: 'Installation Steps', value: '[See Here](https://github.com/PCSX2/pcsx2/wiki/Nightly-Build-Usage-Guide)', inline: true },
|
||||
{ name: 'Included Changes', value: releaseInfo.body, inline: false }
|
||||
);
|
||||
console.log(embed);
|
||||
|
||||
// Get all webhooks, simple comma-sep string
|
||||
const webhookUrls = process.env.DISCORD_BUILD_WEBHOOK.split(",");
|
||||
|
||||
@@ -5,32 +5,16 @@
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "announce-release",
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@actions/github": "^5.0.0",
|
||||
"@octokit/plugin-retry": "^3.0.9",
|
||||
"@octokit/plugin-throttling": "^3.5.2",
|
||||
"@octokit/rest": "^18.12.0",
|
||||
"discord.js": "^13.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/github": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@actions/github/-/github-5.0.0.tgz",
|
||||
"integrity": "sha512-QvE9eAAfEsS+yOOk0cylLBIO/d6WyWIOvsxxzdrPFaud39G6BOkUwScXZn1iBzQzHyu9SBkkLSWlohDWdsasAQ==",
|
||||
"dependencies": {
|
||||
"@actions/http-client": "^1.0.11",
|
||||
"@octokit/core": "^3.4.0",
|
||||
"@octokit/plugin-paginate-rest": "^2.13.3",
|
||||
"@octokit/plugin-rest-endpoint-methods": "^5.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/http-client": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.11.tgz",
|
||||
"integrity": "sha512-VRYHGQV1rqnROJqdMvGUbY/Kn8vriQe/F9HR2AlYHzmKuM/p3kjNuXhmdBfcVgsvRWTz5C5XW5xvndZrVBuAYg==",
|
||||
"dependencies": {
|
||||
"tunnel": "0.0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@discordjs/builders": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.6.0.tgz",
|
||||
@@ -131,6 +115,14 @@
|
||||
"@octokit/types": "^6.33.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-request-log": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz",
|
||||
"integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==",
|
||||
"peerDependencies": {
|
||||
"@octokit/core": ">=3"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-rest-endpoint-methods": {
|
||||
"version": "5.12.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.12.1.tgz",
|
||||
@@ -140,6 +132,27 @@
|
||||
"deprecation": "^2.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-retry": {
|
||||
"version": "3.0.9",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-3.0.9.tgz",
|
||||
"integrity": "sha512-r+fArdP5+TG6l1Rv/C9hVoty6tldw6cE2pRHNGmFPdyfrc696R6JjrQ3d7HdVqGwuzfyrcaLAKD7K8TX8aehUQ==",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^6.0.3",
|
||||
"bottleneck": "^2.15.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-throttling": {
|
||||
"version": "3.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-3.7.0.tgz",
|
||||
"integrity": "sha512-qrKT1Yl/KuwGSC6/oHpLBot3ooC9rq0/ryDYBCpkRtoj+R8T47xTMDT6Tk2CxWopFota/8Pi/2SqArqwC0JPow==",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^6.0.1",
|
||||
"bottleneck": "^2.15.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@octokit/core": "^3.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/request": {
|
||||
"version": "5.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.2.tgz",
|
||||
@@ -163,6 +176,17 @@
|
||||
"once": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/rest": {
|
||||
"version": "18.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.12.0.tgz",
|
||||
"integrity": "sha512-gDPiOHlyGavxr72y0guQEhLsemgVjwRePayJ+FcKc2SJqKUbxbkvf5kAZEWA/MKvsfYlQAMVzNJE3ezQcxMJ2Q==",
|
||||
"dependencies": {
|
||||
"@octokit/core": "^3.5.1",
|
||||
"@octokit/plugin-paginate-rest": "^2.16.8",
|
||||
"@octokit/plugin-request-log": "^1.0.4",
|
||||
"@octokit/plugin-rest-endpoint-methods": "^5.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/types": {
|
||||
"version": "6.33.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.33.0.tgz",
|
||||
@@ -214,6 +238,11 @@
|
||||
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz",
|
||||
"integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ=="
|
||||
},
|
||||
"node_modules/bottleneck": {
|
||||
"version": "2.19.5",
|
||||
"resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz",
|
||||
"integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw=="
|
||||
},
|
||||
"node_modules/callsites": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
|
||||
@@ -388,14 +417,6 @@
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
|
||||
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
|
||||
},
|
||||
"node_modules/tunnel": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
|
||||
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
|
||||
"engines": {
|
||||
"node": ">=0.6.11 <=0.7.0 || >=0.7.3"
|
||||
}
|
||||
},
|
||||
"node_modules/type-fest": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz",
|
||||
@@ -461,25 +482,6 @@
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@actions/github": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@actions/github/-/github-5.0.0.tgz",
|
||||
"integrity": "sha512-QvE9eAAfEsS+yOOk0cylLBIO/d6WyWIOvsxxzdrPFaud39G6BOkUwScXZn1iBzQzHyu9SBkkLSWlohDWdsasAQ==",
|
||||
"requires": {
|
||||
"@actions/http-client": "^1.0.11",
|
||||
"@octokit/core": "^3.4.0",
|
||||
"@octokit/plugin-paginate-rest": "^2.13.3",
|
||||
"@octokit/plugin-rest-endpoint-methods": "^5.1.1"
|
||||
}
|
||||
},
|
||||
"@actions/http-client": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.11.tgz",
|
||||
"integrity": "sha512-VRYHGQV1rqnROJqdMvGUbY/Kn8vriQe/F9HR2AlYHzmKuM/p3kjNuXhmdBfcVgsvRWTz5C5XW5xvndZrVBuAYg==",
|
||||
"requires": {
|
||||
"tunnel": "0.0.6"
|
||||
}
|
||||
},
|
||||
"@discordjs/builders": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.6.0.tgz",
|
||||
@@ -569,6 +571,12 @@
|
||||
"@octokit/types": "^6.33.0"
|
||||
}
|
||||
},
|
||||
"@octokit/plugin-request-log": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz",
|
||||
"integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==",
|
||||
"requires": {}
|
||||
},
|
||||
"@octokit/plugin-rest-endpoint-methods": {
|
||||
"version": "5.12.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.12.1.tgz",
|
||||
@@ -578,6 +586,24 @@
|
||||
"deprecation": "^2.3.1"
|
||||
}
|
||||
},
|
||||
"@octokit/plugin-retry": {
|
||||
"version": "3.0.9",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-3.0.9.tgz",
|
||||
"integrity": "sha512-r+fArdP5+TG6l1Rv/C9hVoty6tldw6cE2pRHNGmFPdyfrc696R6JjrQ3d7HdVqGwuzfyrcaLAKD7K8TX8aehUQ==",
|
||||
"requires": {
|
||||
"@octokit/types": "^6.0.3",
|
||||
"bottleneck": "^2.15.3"
|
||||
}
|
||||
},
|
||||
"@octokit/plugin-throttling": {
|
||||
"version": "3.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-3.7.0.tgz",
|
||||
"integrity": "sha512-qrKT1Yl/KuwGSC6/oHpLBot3ooC9rq0/ryDYBCpkRtoj+R8T47xTMDT6Tk2CxWopFota/8Pi/2SqArqwC0JPow==",
|
||||
"requires": {
|
||||
"@octokit/types": "^6.0.1",
|
||||
"bottleneck": "^2.15.3"
|
||||
}
|
||||
},
|
||||
"@octokit/request": {
|
||||
"version": "5.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.2.tgz",
|
||||
@@ -601,6 +627,17 @@
|
||||
"once": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"@octokit/rest": {
|
||||
"version": "18.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.12.0.tgz",
|
||||
"integrity": "sha512-gDPiOHlyGavxr72y0guQEhLsemgVjwRePayJ+FcKc2SJqKUbxbkvf5kAZEWA/MKvsfYlQAMVzNJE3ezQcxMJ2Q==",
|
||||
"requires": {
|
||||
"@octokit/core": "^3.5.1",
|
||||
"@octokit/plugin-paginate-rest": "^2.16.8",
|
||||
"@octokit/plugin-request-log": "^1.0.4",
|
||||
"@octokit/plugin-rest-endpoint-methods": "^5.12.0"
|
||||
}
|
||||
},
|
||||
"@octokit/types": {
|
||||
"version": "6.33.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.33.0.tgz",
|
||||
@@ -642,6 +679,11 @@
|
||||
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz",
|
||||
"integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ=="
|
||||
},
|
||||
"bottleneck": {
|
||||
"version": "2.19.5",
|
||||
"resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz",
|
||||
"integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw=="
|
||||
},
|
||||
"callsites": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
|
||||
@@ -765,11 +807,6 @@
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
|
||||
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
|
||||
},
|
||||
"tunnel": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
|
||||
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="
|
||||
},
|
||||
"type-fest": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz",
|
||||
|
||||
@@ -10,7 +10,9 @@
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@actions/github": "^5.0.0",
|
||||
"@octokit/plugin-retry": "^3.0.9",
|
||||
"@octokit/plugin-throttling": "^3.5.2",
|
||||
"@octokit/rest": "^18.12.0",
|
||||
"discord.js": "^13.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+1
-1
Submodule 3rdparty/rcheevos/rcheevos updated: 31f8788fe0...3af1e2fc51
@@ -22,17 +22,23 @@ Installers and binaries for both stable and development builds are available fro
|
||||
|
||||
| Operating System | CPU | GPU | RAM |
|
||||
| ------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- |
|
||||
| - Windows 10 Version 1809 or later (64-bit) <br/> - Ubuntu 22.04/Debian or newer, Arch Linux, or other distro (64-bit) <br/> - macOS 10.14 | - Supports SSE4.1 <br/> - [PassMark Thread Performance](https://www.cpubenchmark.net/CPU_mega_page.html) rating near or greater than 1800<br/> - Two physical cores, with hyperthreading | - Direct3D10 support <br/> - OpenGL 3.x support <br/> - Vulkan 1.1 support <br/> - Metal support <br/> - [PassMark G3D Mark](https://www.videocardbenchmark.net/high_end_gpus.html) rating around 3000 (Geforce GTX 750, Radeon RX 560, Intel Arc A380) <br/> - 2 GB Video Memory | 4 GB |
|
||||
|
||||
_Note: Recommended Single Thread Performance is based on moderately complex games. Games that pushed the PS2 hardware to its limits will struggle on CPUs at this level. Some release titles and 2D games which underutilized the PS2 hardware may run on CPUs rated as low as 1200. A quick reference for CPU **intensive games**: [Wiki](https://wiki.pcsx2.net/Category:CPU_intensive_games), [Forum](https://forums.pcsx2.net/Thread-LIST-The-Most-CPU-Intensive-Games) and CPU **light** games: [Forum](https://forums.pcsx2.net/Thread-LIST-Games-that-don-t-need-a-strong-CPU-to-emulate)_
|
||||
| - Windows 10 Version 1809 or later (64-bit) <br/> - Ubuntu 22.04/Debian or newer, Arch Linux, or other distro (64-bit) <br/> - macOS 10.14 | - Supports SSE4.1 <br/> - [PassMark Thread Performance](https://www.cpubenchmark.net/CPU_mega_page.html) rating near or greater than 1500<br/> - Two physical cores, with hyperthreading | - Direct3D 11 (Feature Level 11.0) support <br/> - OpenGL 3.3 support <br/> - Vulkan 1.1 support <br/> - Metal support <br/> - [PassMark G3D Mark](https://www.videocardbenchmark.net/high_end_gpus.html) rating around 3000 (Geforce GTX 750, Radeon RX 560, Intel Arc A380) <br/> - 2 GB Video Memory | 4 GB |
|
||||
|
||||
### Recommended
|
||||
|
||||
| Operating System | CPU | GPU | RAM |
|
||||
| ----------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- |
|
||||
| - Windows 10 22H2 (64-bit) <br/> - Ubuntu 23.04/Debian or newer, Arch Linux, or other distro (64-bit) <br/> - macOS 10.14 | - Supports AVX2 <br/> - [PassMark Single Thread Performance](https://www.cpubenchmark.net/CPU_mega_page.html) rating near or greater than 2000<br/> - Four physical cores, with or without hyperthreading | - Direct3D12 support <br/> - OpenGL 4.6 support <br/> - Vulkan 1.3 support <br/> - Metal support <br/> - [PassMark G3D Mark](https://www.videocardbenchmark.net/high_end_gpus.html) rating around 6000 (GeForce GTX 1650, Radeon RX 570) <br/> - 4 GB Video Memory | 8 GB |
|
||||
|
||||
### Heavy
|
||||
|
||||
| Operating System | CPU | GPU | RAM |
|
||||
| ----------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- |
|
||||
| - Windows 10 22H2 (64-bit) <br/> - Ubuntu 23.04/Debian or newer, Arch Linux, or other distro (64-bit) <br/> - macOS 10.14 | - Supports AVX2 <br/> - [PassMark Single Thread Performance](https://www.cpubenchmark.net/CPU_mega_page.html) rating near or greater than 2600<br/> - Four physical cores, with or without hyperthreading | - Direct3D12 support <br/> - OpenGL 4.6 support <br/> - Vulkan 1.3 support <br/> - Metal support <br/> - [PassMark G3D Mark](https://www.videocardbenchmark.net/high_end_gpus.html) rating around 6000 (GeForce GTX 1650, Radeon RX 570) <br/> - 4 GB Video Memory | 8 GB |
|
||||
|
||||
_Note: Recommended GPU is based on 3x Internal, ~1080p resolution requirements. Higher resolutions will require stronger cards; 6x Internal, ~4K resolution will require a [PassMark G3D Mark](https://www.videocardbenchmark.net/high_end_gpus.html) rating around 12000 (GeForce RTX 2060 Radeon RX 6600 Intel Arc A750). Just like CPU requirements, this is also highly game dependent. A quick reference for GPU **intensive games**: [Wiki](https://wiki.pcsx2.net/Category:GPU_intensive_games)_
|
||||
_Note1: Recommended Single Thread Performance is based on moderately complex games. Games that pushed the PS2 hardware to its limits will struggle on CPUs at this level. Some release titles and 2D games which underutilized the PS2 hardware may run on CPUs rated as low as 1200. A quick reference for CPU **intensive games**: [Wiki](https://wiki.pcsx2.net/Category:CPU_intensive_games), [Forum](https://forums.pcsx2.net/Thread-LIST-The-Most-CPU-Intensive-Games) and CPU **light** games: [Forum](https://forums.pcsx2.net/Thread-LIST-Games-that-don-t-need-a-strong-CPU-to-emulate)_
|
||||
|
||||
_Note2: Recommended GPU is based on 3x Internal, ~1080p resolution requirements. Higher resolutions will require stronger cards; 6x Internal, ~4K resolution will require a [PassMark G3D Mark](https://www.videocardbenchmark.net/high_end_gpus.html) rating around 12000 (GeForce RTX 2060 Radeon RX 6600 Intel Arc A750). Just like CPU requirements, this is also highly game dependent. A quick reference for GPU **intensive games**: [Wiki](https://wiki.pcsx2.net/Category:GPU_intensive_games)_
|
||||
|
||||
### Technical Notes
|
||||
|
||||
|
||||
+4747
-232
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -315,6 +315,7 @@
|
||||
03000000d81d00001000000000000000,iBuffalo BSGP1204P Series,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:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
|
||||
030000005c0a00000285000000000000,iDroidCon,a:b0,b:b1,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:b4,y:b6,platform:Windows,
|
||||
03000000696400006964000000000000,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:Windows,
|
||||
03000000511d00000230000000000000,iGUGU Gamecore,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b1,leftstick:b4,lefttrigger:b3,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b2,platform:Windows,
|
||||
03000000b50700001403000000000000,Impact Black,a:b2,b:b3,back:b8,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:Windows,
|
||||
030000006f0e00002401000000000000,Injustice Fightstick PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000830500005130000000000000,InterAct ActionPad,a:b0,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows,
|
||||
@@ -1065,10 +1066,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
05000000c82d00002038000000010000,8BitDo NES30 Pro,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:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
|
||||
03000000c82d00000751000000010000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:a8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
05000000c82d00000851000000010000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:a8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000c82d00000660000011010000,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:Linux,
|
||||
05000000c82d00000660000000010000,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:Linux,
|
||||
03000000c82d00000631000014010000,8BitDo Pro 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000c82d00000660000011010000,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:Linux,
|
||||
03000000c82d00001030000011010000,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:Linux,
|
||||
05000000c82d00000660000000010000,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:Linux,
|
||||
03000000c82d00000020000000000000,8BitDo Pro 2 for Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
06000000c82d00000020000006010000,8BitDo Pro 2 for Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000c82d00000131000011010000,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:Linux,
|
||||
@@ -1094,9 +1095,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
05000000c82d00000261000000010000,8BitDo SN30 Pro Plus,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,
|
||||
05000000202800000900000000010000,8BitDo SNES30,a:b1,b:b0,back:b10,dpdown:b122,dpleft:b119,dpright:b120,dpup:b117,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,
|
||||
05000000c82d00001230000000010000,8BitDo Ultimate,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,
|
||||
03000000c82d00001730000011010000,8BitDo Ultimate C,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,
|
||||
03000000c82d00001530000011010000,8BitDo Ultimate C,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,
|
||||
03000000c82d00001630000011010000,8BitDo Ultimate C,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,
|
||||
03000000c82d00001730000011010000,8BitDo Ultimate C,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,
|
||||
03000000c82d00001130000011010000,8BitDo Ultimate Wired,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,misc1:b26,paddle1:b24,paddle2:b25,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000c82d00000760000011010000,8BitDo Ultimate Wireless,a:b1,b:b0,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:b4,y:b3,platform:Linux,
|
||||
03000000c82d00001230000011010000,8BitDo Ultimate Wireless,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,
|
||||
@@ -1462,6 +1463,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000321500000009000011010000,Razer Serval,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,
|
||||
050000003215000000090000163a0000,Razer Serval,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,
|
||||
0300000032150000030a000001010000,Razer Wildcat,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,
|
||||
03000000321500000b10000011010000,Razer Wolverine PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
|
||||
03000000790000001100000010010000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Linux,
|
||||
190000004b4800000111000000010000,RetroGame Joypad,a:b1,b:b0,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
|
||||
0300000081170000990a000001010000,Retronic Adapter,a:b0,leftx:a0,lefty:a1,platform:Linux,
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
#if defined(SHADER_MODEL) || defined(FXAA_GLSL_130) || defined(FXAA_GLSL_VK) || defined(__METAL_VERSION__)
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SHADER_MODEL
|
||||
#define SHADER_MODEL 0
|
||||
#endif
|
||||
#ifndef FXAA_HLSL_4
|
||||
#define FXAA_HLSL_4 0
|
||||
#endif
|
||||
#ifndef FXAA_HLSL_5
|
||||
#define FXAA_HLSL_5 0
|
||||
#endif
|
||||
@@ -36,7 +43,7 @@ layout(location = 0) in vec2 PSin_t;
|
||||
layout(location = 0) out vec4 SV_Target0;
|
||||
layout(set = 0, binding = 0) uniform sampler2D TextureSampler;
|
||||
|
||||
#elif (SHADER_MODEL >= 0x400)
|
||||
#elif (FXAA_HLSL_5 == 1)
|
||||
Texture2D Texture : register(t0);
|
||||
SamplerState TextureSampler : register(s0);
|
||||
|
||||
@@ -65,26 +72,6 @@ static constexpr sampler MAIN_SAMPLER(coord::normalized, address::clamp_to_edge,
|
||||
[FXAA CODE SECTION]
|
||||
------------------------------------------------------------------------------*/
|
||||
|
||||
// We don't use gather4 for alpha/luminance because it would require an additional
|
||||
// pass to compute the values, which would be slower than the extra shader loads.
|
||||
|
||||
#if (SHADER_MODEL >= 0x500)
|
||||
#undef FXAA_HLSL_5
|
||||
#define FXAA_HLSL_5 1
|
||||
#define FXAA_GATHER4_ALPHA 0
|
||||
|
||||
#elif (SHADER_MODEL >= 0x400)
|
||||
#undef FXAA_HLSL_4
|
||||
#define FXAA_HLSL_4 1
|
||||
#define FXAA_GATHER4_ALPHA 0
|
||||
|
||||
#elif (FXAA_GLSL_130 == 1 || FXAA_GLSL_VK == 1)
|
||||
#define FXAA_GATHER4_ALPHA 0
|
||||
|
||||
#elif defined(__METAL_VERSION__)
|
||||
#define FXAA_GATHER4_ALPHA 0
|
||||
#endif
|
||||
|
||||
#if (FXAA_HLSL_5 == 1)
|
||||
struct FxaaTex { SamplerState smpl; Texture2D tex; };
|
||||
#define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0)
|
||||
@@ -94,13 +81,6 @@ struct FxaaTex { SamplerState smpl; Texture2D tex; };
|
||||
#define FxaaDiscard clip(-1)
|
||||
#define FxaaSat(x) saturate(x)
|
||||
|
||||
#elif (FXAA_HLSL_4 == 1)
|
||||
struct FxaaTex { SamplerState smpl; Texture2D tex; };
|
||||
#define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0)
|
||||
#define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o)
|
||||
#define FxaaDiscard clip(-1)
|
||||
#define FxaaSat(x) saturate(x)
|
||||
|
||||
#elif (FXAA_GLSL_130 == 1 || FXAA_GLSL_VK == 1)
|
||||
#define int2 ivec2
|
||||
#define float2 vec2
|
||||
@@ -112,12 +92,6 @@ struct FxaaTex { SamplerState smpl; Texture2D tex; };
|
||||
#define FxaaTexTop(t, p) textureLod(t, p, 0.0)
|
||||
#define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o)
|
||||
|
||||
#if (FXAA_GATHER4_ALPHA == 1)
|
||||
// use #extension GL_ARB_gpu_shader5 : enable
|
||||
#define FxaaTexAlpha4(t, p) textureGather(t, p, 3)
|
||||
#define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3)
|
||||
#endif
|
||||
|
||||
#elif defined(__METAL_VERSION__)
|
||||
#define FxaaTex texture2d<float>
|
||||
#define FxaaTexTop(t, p) t.sample(MAIN_SAMPLER, p)
|
||||
@@ -206,21 +180,6 @@ float4 FxaaPixelShader(float2 pos, FxaaTex tex, float2 fxaaRcpFrame, float fxaaS
|
||||
posM.x = pos.x;
|
||||
posM.y = pos.y;
|
||||
|
||||
#if (FXAA_GATHER4_ALPHA == 1)
|
||||
float4 rgbyM = FxaaTexTop(tex, posM);
|
||||
float4 luma4A = FxaaTexAlpha4(tex, posM);
|
||||
float4 luma4B = FxaaTexOffAlpha4(tex, posM, int2(-1, -1));
|
||||
rgbyM.w = RGBLuminance(rgbyM.xyz);
|
||||
|
||||
#define lumaM rgbyM.w
|
||||
#define lumaE luma4A.z
|
||||
#define lumaS luma4A.x
|
||||
#define lumaSE luma4A.y
|
||||
#define lumaNW luma4B.w
|
||||
#define lumaN luma4B.z
|
||||
#define lumaW luma4B.x
|
||||
|
||||
#else
|
||||
float4 rgbyM = FxaaTexTop(tex, posM);
|
||||
rgbyM.w = RGBLuminance(rgbyM.xyz);
|
||||
#define lumaM rgbyM.w
|
||||
@@ -229,7 +188,6 @@ float4 FxaaPixelShader(float2 pos, FxaaTex tex, float2 fxaaRcpFrame, float fxaaS
|
||||
float lumaE = FxaaLuma(FxaaTexOff(tex, posM, int2( 1, 0), fxaaRcpFrame.xy));
|
||||
float lumaN = FxaaLuma(FxaaTexOff(tex, posM, int2( 0,-1), fxaaRcpFrame.xy));
|
||||
float lumaW = FxaaLuma(FxaaTexOff(tex, posM, int2(-1, 0), fxaaRcpFrame.xy));
|
||||
#endif
|
||||
|
||||
float maxSM = max(lumaS, lumaM);
|
||||
float minSM = min(lumaS, lumaM);
|
||||
@@ -249,15 +207,10 @@ float4 FxaaPixelShader(float2 pos, FxaaTex tex, float2 fxaaRcpFrame, float fxaaS
|
||||
if(earlyExit) { return rgbyM; }
|
||||
#endif
|
||||
|
||||
#if (FXAA_GATHER4_ALPHA == 0)
|
||||
float lumaNW = FxaaLuma(FxaaTexOff(tex, posM, int2(-1,-1), fxaaRcpFrame.xy));
|
||||
float lumaSE = FxaaLuma(FxaaTexOff(tex, posM, int2( 1, 1), fxaaRcpFrame.xy));
|
||||
float lumaNE = FxaaLuma(FxaaTexOff(tex, posM, int2( 1,-1), fxaaRcpFrame.xy));
|
||||
float lumaSW = FxaaLuma(FxaaTexOff(tex, posM, int2(-1, 1), fxaaRcpFrame.xy));
|
||||
#else
|
||||
float lumaNE = FxaaLuma(FxaaTexOff(tex, posM, int2( 1,-1), fxaaRcpFrame.xy));
|
||||
float lumaSW = FxaaLuma(FxaaTexOff(tex, posM, int2(-1, 1), fxaaRcpFrame.xy));
|
||||
#endif
|
||||
|
||||
float lumaNS = lumaN + lumaS;
|
||||
float lumaWE = lumaW + lumaE;
|
||||
@@ -503,14 +456,14 @@ float4 FxaaPixelShader(float2 pos, FxaaTex tex, float2 fxaaRcpFrame, float fxaaS
|
||||
|
||||
#if (FXAA_GLSL_130 == 1 || FXAA_GLSL_VK == 1)
|
||||
float4 FxaaPass(float4 FxaaColor, float2 uv0)
|
||||
#elif (SHADER_MODEL >= 0x400)
|
||||
#elif (FXAA_HLSL_5 == 1)
|
||||
float4 FxaaPass(float4 FxaaColor : COLOR0, float2 uv0 : TEXCOORD0)
|
||||
#elif defined(__METAL_VERSION__)
|
||||
float4 FxaaPass(float4 FxaaColor, float2 uv0, texture2d<float> tex)
|
||||
#endif
|
||||
{
|
||||
|
||||
#if (SHADER_MODEL >= 0x400)
|
||||
#if (FXAA_HLSL_5 == 1)
|
||||
FxaaTex tex;
|
||||
tex.tex = Texture;
|
||||
tex.smpl = TextureSampler;
|
||||
@@ -544,8 +497,8 @@ void main()
|
||||
SV_Target0 = float4(color.rgb, 1.0);
|
||||
}
|
||||
|
||||
#elif (SHADER_MODEL >= 0x400)
|
||||
PS_OUTPUT ps_main(VS_OUTPUT input)
|
||||
#elif (FXAA_HLSL_5 == 1)
|
||||
PS_OUTPUT main(VS_OUTPUT input)
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
|
||||
@@ -561,5 +514,3 @@ PS_OUTPUT ps_main(VS_OUTPUT input)
|
||||
|
||||
// Metal main function in in fxaa.metal
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,4 +1,17 @@
|
||||
#ifdef SHADER_MODEL // make safe to include in resource file to enforce dependency
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
struct VS_INPUT
|
||||
{
|
||||
@@ -398,5 +411,3 @@ float ps_stencil_image_init_1(PS_INPUT input) : SV_Target
|
||||
c = float(0x7FFFFFFF);
|
||||
return c;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
cbuffer vertexBuffer : register(b0)
|
||||
{
|
||||
float4x4 ProjectionMatrix;
|
||||
|
||||
@@ -1,4 +1,17 @@
|
||||
#ifdef SHADER_MODEL // make safe to include in resource file to enforce dependency
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
Texture2D Texture;
|
||||
SamplerState Sampler;
|
||||
@@ -180,5 +193,3 @@ float4 ps_main4(PS_INPUT input) : SV_Target0
|
||||
|
||||
return float4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,4 +1,17 @@
|
||||
#ifdef SHADER_MODEL // make safe to include in resource file to enforce dependency
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
Texture2D Texture;
|
||||
SamplerState Sampler;
|
||||
@@ -30,4 +43,3 @@ float4 ps_main1(PS_INPUT input) : SV_Target0
|
||||
c.a = BGColor.a;
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,8 +1,17 @@
|
||||
#ifdef SHADER_MODEL // make safe to include in resource file to enforce dependency
|
||||
|
||||
#ifndef PS_SCALE_FACTOR
|
||||
#define PS_SCALE_FACTOR 1
|
||||
#endif
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
struct VS_INPUT
|
||||
{
|
||||
@@ -436,5 +445,3 @@ PS_OUTPUT ps_automagical_supersampling(PS_INPUT input)
|
||||
output.c = float4(col / div, 1);
|
||||
return output;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,4 +1,17 @@
|
||||
#ifdef SHADER_MODEL // make safe to include in resource file to enforce dependency
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
Texture2D Texture;
|
||||
SamplerState Sampler;
|
||||
@@ -49,5 +62,3 @@ float4 ps_main(PS_INPUT input) : SV_Target0
|
||||
float4 c = Texture.Sample(Sampler, input.t);
|
||||
return ContrastSaturationBrightness(c);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define FMT_32 0
|
||||
#define FMT_24 1
|
||||
#define FMT_16 2
|
||||
@@ -37,6 +52,7 @@
|
||||
#define PS_POINT_SAMPLER 0
|
||||
#define PS_REGION_RECT 0
|
||||
#define PS_SHUFFLE 0
|
||||
#define PS_SHUFFLE_SAME 0
|
||||
#define PS_READ_BA 0
|
||||
#define PS_READ16_SRC 0
|
||||
#define PS_DFMT 0
|
||||
@@ -646,7 +662,7 @@ float4 sample_color(float2 st, float uv_w)
|
||||
float4 tfx(float4 T, float4 C)
|
||||
{
|
||||
float4 C_out;
|
||||
float4 FxT = trunc(trunc(C) * T / 128.0f);
|
||||
float4 FxT = trunc((C * T) / 128.0f);
|
||||
|
||||
#if (PS_TFX == 0)
|
||||
C_out = FxT;
|
||||
@@ -925,8 +941,17 @@ PS_OUTPUT ps_main(PS_INPUT input)
|
||||
{
|
||||
uint4 denorm_c = uint4(C);
|
||||
uint2 denorm_TA = uint2(float2(TA.xy) * 255.0f + 0.5f);
|
||||
|
||||
if (PS_READ16_SRC)
|
||||
|
||||
// Special case for 32bit input and 16bit output, shuffle used by The Godfather
|
||||
if (PS_SHUFFLE_SAME)
|
||||
{
|
||||
if (PS_READ_BA)
|
||||
C = (float4)(float((denorm_c.b & 0x7Fu) | (denorm_c.a & 0x80u)));
|
||||
else
|
||||
C.ga = C.rg;
|
||||
}
|
||||
// Copy of a 16bit source in to this target
|
||||
else if (PS_READ16_SRC)
|
||||
{
|
||||
C.rb = (float2)float((denorm_c.r >> 3) | (((denorm_c.g >> 3) & 0x7u) << 5));
|
||||
if (denorm_c.a & 0x80u)
|
||||
@@ -934,28 +959,23 @@ PS_OUTPUT ps_main(PS_INPUT input)
|
||||
else
|
||||
C.ga = (float2)float((denorm_c.g >> 6) | ((denorm_c.b >> 3) << 2) | (denorm_TA.x & 0x80u));
|
||||
}
|
||||
// Write RB part. Mask will take care of the correct destination
|
||||
else if (PS_READ_BA)
|
||||
{
|
||||
C.rb = C.bb;
|
||||
if (denorm_c.a & 0x80u)
|
||||
C.ga = (float2)(float((denorm_c.a & 0x7Fu) | (denorm_TA.y & 0x80u)));
|
||||
else
|
||||
C.ga = (float2)(float((denorm_c.a & 0x7Fu) | (denorm_TA.x & 0x80u)));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Mask will take care of the correct destination
|
||||
if (PS_READ_BA)
|
||||
C.rb = C.bb;
|
||||
else
|
||||
C.rb = C.rr;
|
||||
C.rb = C.rr;
|
||||
if (denorm_c.g & 0x80u)
|
||||
C.ga = (float2)(float((denorm_c.g & 0x7Fu) | (denorm_TA.y & 0x80u)));
|
||||
|
||||
if (PS_READ_BA)
|
||||
{
|
||||
if (denorm_c.a & 0x80u)
|
||||
C.ga = (float2)(float((denorm_c.a & 0x7Fu) | (denorm_TA.y & 0x80u)));
|
||||
else
|
||||
C.ga = (float2)(float((denorm_c.a & 0x7Fu) | (denorm_TA.x & 0x80u)));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (denorm_c.g & 0x80u)
|
||||
C.ga = (float2)(float((denorm_c.g & 0x7Fu) | (denorm_TA.y & 0x80u)));
|
||||
else
|
||||
C.ga = (float2)(float((denorm_c.g & 0x7Fu) | (denorm_TA.x & 0x80u)));
|
||||
}
|
||||
C.ga = (float2)(float((denorm_c.g & 0x7Fu) | (denorm_TA.x & 0x80u)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//#version 420 // Keep it for editor detection
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout(location = 0) in vec2 Position;
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//#version 420 // Keep it for editor detection
|
||||
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//#version 420 // Keep it for editor detection
|
||||
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//#version 420 // Keep it for editor detection
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//#version 420 // Keep it for editor detection
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//#version 420 // Keep it for text editor detection
|
||||
|
||||
#define FMT_32 0
|
||||
@@ -599,7 +614,7 @@ vec4 sample_color(vec2 st)
|
||||
vec4 tfx(vec4 T, vec4 C)
|
||||
{
|
||||
vec4 C_out;
|
||||
vec4 FxT = trunc(trunc(C) * T / 128.0f);
|
||||
vec4 FxT = trunc((C * T) / 128.0f);
|
||||
|
||||
#if (PS_TFX == 0)
|
||||
C_out = FxT;
|
||||
@@ -764,17 +779,19 @@ float As = As_rgba.a;
|
||||
return;
|
||||
#endif
|
||||
|
||||
vec3 Cs = Color.rgb;
|
||||
|
||||
#if SW_BLEND_NEEDS_RT
|
||||
vec4 RT = trunc(fetch_rt() * 255.0f + 0.1f);
|
||||
#else
|
||||
// Not used, but we define it to make the selection below simpler.
|
||||
vec4 RT = vec4(0.0f);
|
||||
#endif
|
||||
// FIXME FMT_16 case
|
||||
// FIXME Ad or Ad * 2?
|
||||
float Ad = RT.a / 128.0f;
|
||||
|
||||
// Let the compiler do its jobs !
|
||||
vec3 Cd = RT.rgb;
|
||||
#endif
|
||||
vec3 Cs = Color.rgb;
|
||||
|
||||
#if PS_BLEND_A == 0
|
||||
vec3 A = Cs;
|
||||
@@ -935,26 +952,30 @@ void ps_main()
|
||||
#if PS_SHUFFLE
|
||||
uvec4 denorm_c = uvec4(C);
|
||||
uvec2 denorm_TA = uvec2(vec2(TA.xy) * 255.0f + 0.5f);
|
||||
#if PS_READ16_SRC
|
||||
|
||||
// Special case for 32bit input and 16bit output, shuffle used by The Godfather
|
||||
#if PS_SHUFFLE_SAME
|
||||
#if (PS_READ_BA)
|
||||
C = vec4(float((denorm_c.b & 0x7Fu) | (denorm_c.a & 0x80u)));
|
||||
#else
|
||||
C.ga = C.rg;
|
||||
#endif
|
||||
// Copy of a 16bit source in to this target
|
||||
#elif PS_READ16_SRC
|
||||
C.rb = vec2(float((denorm_c.r >> 3) | (((denorm_c.g >> 3) & 0x7u) << 5)));
|
||||
if (bool(denorm_c.a & 0x80u))
|
||||
C.ga = vec2(float((denorm_c.g >> 6) | ((denorm_c.b >> 3) << 2) | (denorm_TA.y & 0x80u)));
|
||||
else
|
||||
C.ga = vec2(float((denorm_c.g >> 6) | ((denorm_c.b >> 3) << 2) | (denorm_TA.x & 0x80u)));
|
||||
#else
|
||||
// Write RB part. Mask will take care of the correct destination
|
||||
#if PS_READ_BA
|
||||
// Write RB part. Mask will take care of the correct destination
|
||||
#elif PS_READ_BA
|
||||
C.rb = C.bb;
|
||||
#else
|
||||
C.rb = C.rr;
|
||||
#endif
|
||||
|
||||
// FIXME precompute my_TA & 0x80
|
||||
|
||||
// Write GA part. Mask will take care of the correct destination
|
||||
// Note: GLSL 4.50/GL_EXT_shader_integer_mix support a mix instruction to select a component\n"
|
||||
// However Nvidia emulate it with an if (at least on kepler arch) ...\n"
|
||||
#if PS_READ_BA
|
||||
|
||||
// bit field operation requires GL4 HW. Could be nice to merge it with step/mix below
|
||||
// uint my_ta = (bool(bitfieldExtract(denorm_c.a, 7, 1))) ? denorm_TA.y : denorm_TA.x;
|
||||
// denorm_c.a = bitfieldInsert(denorm_c.a, bitfieldExtract(my_ta, 7, 1), 7, 1);
|
||||
@@ -966,6 +987,7 @@ void ps_main()
|
||||
C.ga = vec2(float((denorm_c.a & 0x7Fu) | (denorm_TA.x & 0x80u)));
|
||||
|
||||
#else
|
||||
C.rb = C.rr;
|
||||
if (bool(denorm_c.g & 0x80u))
|
||||
C.ga = vec2(float((denorm_c.g & 0x7Fu) | (denorm_TA.y & 0x80u)));
|
||||
else
|
||||
@@ -977,9 +999,8 @@ void ps_main()
|
||||
// float sel = step(128.0f, c.g);
|
||||
// vec2 c_shuffle = vec2((denorm_c.gg & 0x7Fu) | (denorm_TA & 0x80u));
|
||||
// c.ga = mix(c_shuffle.xx, c_shuffle.yy, sel);
|
||||
#endif // PS_READ_BA
|
||||
|
||||
#endif // READ16_SRC
|
||||
#endif // PS_SHUFFLE_SAME
|
||||
#endif // PS_SHUFFLE
|
||||
|
||||
// Must be done before alpha correction
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//#version 420 // Keep it for text editor detection
|
||||
|
||||
layout(std140, binding = 1) uniform cb20
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout(location = 0) in vec4 a_pos;
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout(location = 0) in vec2 Position;
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout(location = 0) in vec4 a_pos;
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout(location = 0) in vec4 a_pos;
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout(location = 0) in vec4 a_pos;
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//#version 420 // Keep it for editor detection
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Vertex Shader
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
@@ -262,7 +277,9 @@ void main()
|
||||
#define PS_TCOFFSETHACK 0
|
||||
#define PS_POINT_SAMPLER 0
|
||||
#define PS_SHUFFLE 0
|
||||
#define PS_SHUFFLE_SAME 0
|
||||
#define PS_READ_BA 0
|
||||
#define PS_WRITE_RG 0
|
||||
#define PS_READ16_SRC 0
|
||||
#define PS_DFMT 0
|
||||
#define PS_DEPTH_FMT 0
|
||||
@@ -285,7 +302,7 @@ void main()
|
||||
#endif
|
||||
|
||||
#define SW_BLEND (PS_BLEND_A || PS_BLEND_B || PS_BLEND_D)
|
||||
#define SW_BLEND_NEEDS_RT (PS_BLEND_A == 1 || PS_BLEND_B == 1 || PS_BLEND_C == 1 || PS_BLEND_D == 1)
|
||||
#define SW_BLEND_NEEDS_RT (SW_BLEND && (PS_BLEND_A == 1 || PS_BLEND_B == 1 || PS_BLEND_C == 1 || PS_BLEND_D == 1))
|
||||
#define SW_AD_TO_HW (PS_BLEND_C == 1 && PS_A_MASKED)
|
||||
|
||||
#define PS_FEEDBACK_LOOP_IS_NEEDED (PS_TEX_IS_FB == 1 || PS_FBMASK || SW_BLEND_NEEDS_RT || (PS_DATE >= 5))
|
||||
@@ -337,16 +354,16 @@ layout(set = 1, binding = 1) uniform texture2D Palette;
|
||||
|
||||
#if PS_FEEDBACK_LOOP_IS_NEEDED
|
||||
#if defined(DISABLE_TEXTURE_BARRIER) || defined(HAS_FEEDBACK_LOOP_LAYOUT)
|
||||
layout(set = 2, binding = 0) uniform texture2D RtSampler;
|
||||
layout(set = 1, binding = 2) uniform texture2D RtSampler;
|
||||
vec4 sample_from_rt() { return texelFetch(RtSampler, ivec2(gl_FragCoord.xy), 0); }
|
||||
#else
|
||||
layout(input_attachment_index = 0, set = 2, binding = 0) uniform subpassInput RtSampler;
|
||||
layout(input_attachment_index = 0, set = 1, binding = 2) uniform subpassInput RtSampler;
|
||||
vec4 sample_from_rt() { return subpassLoad(RtSampler); }
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if PS_DATE > 0
|
||||
layout(set = 2, binding = 1) uniform texture2D PrimMinTexture;
|
||||
layout(set = 1, binding = 3) uniform texture2D PrimMinTexture;
|
||||
#endif
|
||||
|
||||
#if NEEDS_TEX
|
||||
@@ -834,7 +851,7 @@ vec4 sample_color(vec2 st)
|
||||
vec4 tfx(vec4 T, vec4 C)
|
||||
{
|
||||
vec4 C_out;
|
||||
vec4 FxT = trunc(trunc(C) * T / 128.0f);
|
||||
vec4 FxT = trunc((C * T) / 128.0f);
|
||||
|
||||
#if (PS_TFX == 0)
|
||||
C_out = FxT;
|
||||
@@ -1182,33 +1199,36 @@ void main()
|
||||
#if PS_SHUFFLE
|
||||
uvec4 denorm_c = uvec4(C);
|
||||
uvec2 denorm_TA = uvec2(vec2(TA.xy) * 255.0f + 0.5f);
|
||||
#if PS_READ16_SRC
|
||||
|
||||
// Special case for 32bit input and 16bit output, shuffle used by The Godfather
|
||||
#if PS_SHUFFLE_SAME
|
||||
#if (PS_READ_BA)
|
||||
C = vec4(float((denorm_c.b & 0x7Fu) | (denorm_c.a & 0x80u)));
|
||||
#else
|
||||
C.ga = C.rg;
|
||||
#endif
|
||||
// Copy of a 16bit source in to this target
|
||||
#elif PS_READ16_SRC
|
||||
C.rb = vec2(float((denorm_c.r >> 3) | (((denorm_c.g >> 3) & 0x7u) << 5)));
|
||||
if ((denorm_c.a & 0x80u) != 0u)
|
||||
C.ga = vec2(float((denorm_c.g >> 6) | ((denorm_c.b >> 3) << 2) | (denorm_TA.y & 0x80u)));
|
||||
else
|
||||
C.ga = vec2(float((denorm_c.g >> 6) | ((denorm_c.b >> 3) << 2) | (denorm_TA.x & 0x80u)));
|
||||
// Write RB part. Mask will take care of the correct destination
|
||||
#elif PS_READ_BA
|
||||
C.rb = C.bb;
|
||||
if ((denorm_c.a & 0x80u) != 0u)
|
||||
C.ga = vec2(float((denorm_c.a & 0x7Fu) | (denorm_TA.y & 0x80u)));
|
||||
else
|
||||
C.ga = vec2(float((denorm_c.a & 0x7Fu) | (denorm_TA.x & 0x80u)));
|
||||
#else
|
||||
// Mask will take care of the correct destination
|
||||
#if PS_READ_BA
|
||||
C.rb = C.bb;
|
||||
#else
|
||||
C.rb = C.rr;
|
||||
#endif
|
||||
|
||||
#if PS_READ_BA
|
||||
if ((denorm_c.a & 0x80u) != 0u)
|
||||
C.ga = vec2(float((denorm_c.a & 0x7Fu) | (denorm_TA.y & 0x80u)));
|
||||
else
|
||||
C.ga = vec2(float((denorm_c.a & 0x7Fu) | (denorm_TA.x & 0x80u)));
|
||||
#else
|
||||
if ((denorm_c.g & 0x80u) != 0u)
|
||||
C.ga = vec2(float((denorm_c.g & 0x7Fu) | (denorm_TA.y & 0x80u)));
|
||||
else
|
||||
C.ga = vec2(float((denorm_c.g & 0x7Fu) | (denorm_TA.x & 0x80u)));
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
C.rb = C.rr;
|
||||
if ((denorm_c.g & 0x80u) != 0u)
|
||||
C.ga = vec2(float((denorm_c.g & 0x7Fu) | (denorm_TA.y & 0x80u)));
|
||||
else
|
||||
C.ga = vec2(float((denorm_c.g & 0x7Fu) | (denorm_TA.x & 0x80u)));
|
||||
#endif // PS_SHUFFLE_SAME
|
||||
#endif // PS_SHUFFLE
|
||||
|
||||
// Must be done before alpha correction
|
||||
|
||||
|
||||
@@ -36,6 +36,9 @@ if(UNIX AND NOT APPLE)
|
||||
option(X11_API "Enable X11 support" ON)
|
||||
option(WAYLAND_API "Enable Wayland support" ON)
|
||||
option(DBUS_API "Enable DBus support for screensaver inhibiting" ON)
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
option(USE_LINKED_FFMPEG "Links with ffmpeg instead of using dynamic loading" OFF)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2021 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// An implementation of bit_cast until we get c++20
|
||||
|
||||
template<class T2, class T1>
|
||||
T2 bit_cast(const T1& src)
|
||||
{
|
||||
static_assert(sizeof(T2) == sizeof(T1), "bit_cast: types must be equal size");
|
||||
static_assert(std::is_pod<T1>::value, "bit_cast: source must be POD");
|
||||
static_assert(std::is_pod<T2>::value, "bit_cast: destination must be POD");
|
||||
T2 dst;
|
||||
memcpy(&dst, &src, sizeof(T2));
|
||||
return dst;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2021 PCSX2 Dev Team
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
@@ -14,8 +14,29 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/Pcsx2Defs.h"
|
||||
|
||||
#include <bit>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#include <intrin.h>
|
||||
|
||||
#else
|
||||
|
||||
static inline int _BitScanReverse(unsigned long* const Index, const unsigned long Mask)
|
||||
{
|
||||
if (Mask == 0)
|
||||
return 0;
|
||||
|
||||
// For some reason, clang won't emit bsr if we use std::countl_zeros()...
|
||||
*Index = 31 - __builtin_clz(Mask);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
namespace Common
|
||||
{
|
||||
template <typename T>
|
||||
@@ -54,46 +75,24 @@ namespace Common
|
||||
return value & static_cast<T>(~static_cast<T>(alignment - 1));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static constexpr __fi bool IsPow2(T value)
|
||||
{
|
||||
return (value & (value - 1)) == 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static constexpr __fi T PreviousPow2(T value)
|
||||
{
|
||||
if (value == static_cast<T>(0))
|
||||
return 0;
|
||||
|
||||
value |= (value >> 1);
|
||||
value |= (value >> 2);
|
||||
value |= (value >> 4);
|
||||
value |= (value >> 8);
|
||||
value |= (value >> 16);
|
||||
return value - (value >> 1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static constexpr __fi T NextPow2(T value)
|
||||
{
|
||||
if (value == static_cast<T>(0))
|
||||
return 0;
|
||||
|
||||
value--;
|
||||
value |= value >> 1;
|
||||
value |= value >> 2;
|
||||
value |= value >> 4;
|
||||
value |= value >> 8;
|
||||
value |= value >> 16;
|
||||
value++;
|
||||
return value;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static constexpr T PageAlign(T size)
|
||||
{
|
||||
static_assert(Common::IsPow2(__pagesize), "Page size is a power of 2");
|
||||
static_assert(std::has_single_bit(__pagesize), "Page size is a power of 2");
|
||||
return Common::AlignUpPow2(size, __pagesize);
|
||||
}
|
||||
|
||||
__fi static u32 CountLeadingSignBits(s32 n)
|
||||
{
|
||||
// If the sign bit is 1, we invert the bits to 0 for count-leading-zero.
|
||||
if (n < 0)
|
||||
n = ~n;
|
||||
|
||||
// If BSR is used directly, it would have an undefined value for 0.
|
||||
if (n == 0)
|
||||
return 32;
|
||||
|
||||
// Perform our count leading zero.
|
||||
return std::countl_zero(static_cast<u32>(n));
|
||||
}
|
||||
} // namespace Common
|
||||
@@ -61,10 +61,10 @@ target_sources(common PRIVATE
|
||||
|
||||
# x86emitter headers
|
||||
target_sources(common PRIVATE
|
||||
Align.h
|
||||
AlignedMalloc.h
|
||||
Assertions.h
|
||||
boost_spsc_queue.hpp
|
||||
BitUtils.h
|
||||
ByteSwap.h
|
||||
Console.h
|
||||
CrashHandler.h
|
||||
|
||||
@@ -748,13 +748,6 @@ s64 FileSystem::FTell64(std::FILE* fp)
|
||||
|
||||
s64 FileSystem::FSize64(std::FILE* fp)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
const int fd = _fileno(fp);
|
||||
if (fd >= 0)
|
||||
{
|
||||
return _filelengthi64(fd);
|
||||
}
|
||||
#else
|
||||
const s64 pos = FTell64(fp);
|
||||
if (pos >= 0)
|
||||
{
|
||||
@@ -765,7 +758,6 @@ s64 FileSystem::FSize64(std::FILE* fp)
|
||||
return size;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -71,43 +71,6 @@ using UnorderedStringSet =
|
||||
using UnorderedStringMultiSet =
|
||||
std::unordered_multiset<std::string, detail::transparent_string_hash, detail::transparent_string_equal>;
|
||||
|
||||
template <typename KeyType, typename ValueType>
|
||||
__fi typename UnorderedStringMap<ValueType>::const_iterator
|
||||
UnorderedStringMapFind(const UnorderedStringMap<ValueType>& map, const KeyType& key)
|
||||
{
|
||||
return map.find(key);
|
||||
}
|
||||
template <typename KeyType, typename ValueType>
|
||||
__fi typename UnorderedStringMap<ValueType>::iterator
|
||||
UnorderedStringMapFind(UnorderedStringMap<ValueType>& map, const KeyType& key)
|
||||
{
|
||||
return map.find(key);
|
||||
}
|
||||
template <typename KeyType, typename ValueType>
|
||||
__fi typename UnorderedStringMultimap<ValueType>::const_iterator
|
||||
UnorderedStringMultiMapFind(const UnorderedStringMultimap<ValueType>& map, const KeyType& key)
|
||||
{
|
||||
return map.find(key);
|
||||
}
|
||||
template <typename KeyType, typename ValueType>
|
||||
__fi std::pair<typename UnorderedStringMultimap<ValueType>::const_iterator, typename UnorderedStringMultimap<ValueType>::const_iterator>
|
||||
UnorderedStringMultiMapEqualRange(const UnorderedStringMultimap<ValueType>& map, const KeyType& key)
|
||||
{
|
||||
return map.equal_range(key);
|
||||
}
|
||||
template <typename KeyType, typename ValueType>
|
||||
__fi typename UnorderedStringMultimap<ValueType>::iterator
|
||||
UnorderedStringMultiMapFind(UnorderedStringMultimap<ValueType>& map, const KeyType& key)
|
||||
{
|
||||
return map.find(key);
|
||||
}
|
||||
template <typename KeyType, typename ValueType>
|
||||
__fi std::pair<typename UnorderedStringMultimap<ValueType>::iterator, typename UnorderedStringMultimap<ValueType>::iterator>
|
||||
UnorderedStringMultiMapEqualRange(UnorderedStringMultimap<ValueType>& map, const KeyType& key)
|
||||
{
|
||||
return map.equal_range(key);
|
||||
}
|
||||
|
||||
template <typename ValueType>
|
||||
using StringMap = std::map<std::string, ValueType, detail::transparent_string_less>;
|
||||
template <typename ValueType>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
#include "fmt/core.h"
|
||||
|
||||
#include "common/Align.h"
|
||||
#include "common/BitUtils.h"
|
||||
#include "common/Assertions.h"
|
||||
#include "common/Console.h"
|
||||
#include "common/General.h"
|
||||
@@ -108,7 +108,8 @@ static void SysPageFaultSignalFilter(int signal, siginfo_t* siginfo, void* ctx)
|
||||
void* const exception_pc = nullptr;
|
||||
#endif
|
||||
|
||||
const PageFaultInfo pfi{(uptr)exception_pc, (uptr)siginfo->si_addr & ~__pagemask};
|
||||
const PageFaultInfo pfi{
|
||||
reinterpret_cast<uptr>(exception_pc), reinterpret_cast<uptr>(siginfo->si_addr) & ~static_cast<uptr>(__pagemask)};
|
||||
|
||||
s_in_exception_handler = true;
|
||||
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2014- PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
// Hopefully this file will be used for cross-source math utilities.
|
||||
// Currently these are strewn across the code base. Please collect them all!
|
||||
|
||||
#include "common/Pcsx2Defs.h"
|
||||
|
||||
// On GCC >= 4.7, this is equivalent to __builtin_clrsb(n);
|
||||
inline u32 count_leading_sign_bits(s32 n)
|
||||
{
|
||||
// If the sign bit is 1, we invert the bits to 0 for count-leading-zero.
|
||||
if (n < 0)
|
||||
n = ~n;
|
||||
|
||||
// If BSR is used directly, it would have an undefined value for 0.
|
||||
if (n == 0)
|
||||
return 32;
|
||||
|
||||
// Perform our count leading zero.
|
||||
#ifdef _MSC_VER
|
||||
unsigned long ret;
|
||||
_BitScanReverse(&ret, n);
|
||||
return 31 - (u32)ret;
|
||||
#else
|
||||
return __builtin_clz(n);
|
||||
#endif
|
||||
}
|
||||
@@ -32,7 +32,7 @@ void MemorySettingsInterface::Clear()
|
||||
|
||||
bool MemorySettingsInterface::GetIntValue(const char* section, const char* key, s32* value) const
|
||||
{
|
||||
const auto sit = UnorderedStringMapFind(m_sections, section);
|
||||
const auto sit = m_sections.find(section);
|
||||
if (sit == m_sections.end())
|
||||
return false;
|
||||
|
||||
@@ -50,11 +50,11 @@ bool MemorySettingsInterface::GetIntValue(const char* section, const char* key,
|
||||
|
||||
bool MemorySettingsInterface::GetUIntValue(const char* section, const char* key, u32* value) const
|
||||
{
|
||||
const auto sit = UnorderedStringMapFind(m_sections, section);
|
||||
const auto sit = m_sections.find(section);
|
||||
if (sit == m_sections.end())
|
||||
return false;
|
||||
|
||||
const auto iter = UnorderedStringMultiMapFind(sit->second, key);
|
||||
const auto iter = sit->second.find(key);
|
||||
if (iter == sit->second.end())
|
||||
return false;
|
||||
|
||||
@@ -68,11 +68,11 @@ bool MemorySettingsInterface::GetUIntValue(const char* section, const char* key,
|
||||
|
||||
bool MemorySettingsInterface::GetFloatValue(const char* section, const char* key, float* value) const
|
||||
{
|
||||
const auto sit = UnorderedStringMapFind(m_sections, section);
|
||||
const auto sit = m_sections.find(section);
|
||||
if (sit == m_sections.end())
|
||||
return false;
|
||||
|
||||
const auto iter = UnorderedStringMultiMapFind(sit->second, key);
|
||||
const auto iter = sit->second.find(key);
|
||||
if (iter == sit->second.end())
|
||||
return false;
|
||||
|
||||
@@ -86,11 +86,11 @@ bool MemorySettingsInterface::GetFloatValue(const char* section, const char* key
|
||||
|
||||
bool MemorySettingsInterface::GetDoubleValue(const char* section, const char* key, double* value) const
|
||||
{
|
||||
const auto sit = UnorderedStringMapFind(m_sections, section);
|
||||
const auto sit = m_sections.find(section);
|
||||
if (sit == m_sections.end())
|
||||
return false;
|
||||
|
||||
const auto iter = UnorderedStringMultiMapFind(sit->second, key);
|
||||
const auto iter = sit->second.find(key);
|
||||
if (iter == sit->second.end())
|
||||
return false;
|
||||
|
||||
@@ -104,11 +104,11 @@ bool MemorySettingsInterface::GetDoubleValue(const char* section, const char* ke
|
||||
|
||||
bool MemorySettingsInterface::GetBoolValue(const char* section, const char* key, bool* value) const
|
||||
{
|
||||
const auto sit = UnorderedStringMapFind(m_sections, section);
|
||||
const auto sit = m_sections.find(section);
|
||||
if (sit == m_sections.end())
|
||||
return false;
|
||||
|
||||
const auto iter = UnorderedStringMultiMapFind(sit->second, key);
|
||||
const auto iter = sit->second.find(key);
|
||||
if (iter == sit->second.end())
|
||||
return false;
|
||||
|
||||
@@ -122,11 +122,11 @@ bool MemorySettingsInterface::GetBoolValue(const char* section, const char* key,
|
||||
|
||||
bool MemorySettingsInterface::GetStringValue(const char* section, const char* key, std::string* value) const
|
||||
{
|
||||
const auto sit = UnorderedStringMapFind(m_sections, section);
|
||||
const auto sit = m_sections.find(section);
|
||||
if (sit == m_sections.end())
|
||||
return false;
|
||||
|
||||
const auto iter = UnorderedStringMultiMapFind(sit->second, key);
|
||||
const auto iter = sit->second.find(key);
|
||||
if (iter == sit->second.end())
|
||||
return false;
|
||||
|
||||
@@ -167,7 +167,7 @@ void MemorySettingsInterface::SetStringValue(const char* section, const char* ke
|
||||
std::vector<std::pair<std::string, std::string>> MemorySettingsInterface::GetKeyValueList(const char* section) const
|
||||
{
|
||||
std::vector<std::pair<std::string, std::string>> output;
|
||||
auto sit = UnorderedStringMapFind(m_sections, section);
|
||||
auto sit = m_sections.find(section);
|
||||
if (sit != m_sections.end())
|
||||
{
|
||||
for (const auto& it : sit->second)
|
||||
@@ -178,7 +178,7 @@ std::vector<std::pair<std::string, std::string>> MemorySettingsInterface::GetKey
|
||||
|
||||
void MemorySettingsInterface::SetKeyValueList(const char* section, const std::vector<std::pair<std::string, std::string>>& items)
|
||||
{
|
||||
auto sit = UnorderedStringMapFind(m_sections, section);
|
||||
auto sit = m_sections.find(section);
|
||||
sit->second.clear();
|
||||
for (const auto& [key, value] : items)
|
||||
sit->second.emplace(key, value);
|
||||
@@ -186,11 +186,11 @@ void MemorySettingsInterface::SetKeyValueList(const char* section, const std::ve
|
||||
|
||||
void MemorySettingsInterface::SetValue(const char* section, const char* key, std::string value)
|
||||
{
|
||||
auto sit = UnorderedStringMapFind(m_sections, section);
|
||||
auto sit = m_sections.find(section);
|
||||
if (sit == m_sections.end())
|
||||
sit = m_sections.emplace(std::make_pair(std::string(section), KeyMap())).first;
|
||||
|
||||
const auto range = UnorderedStringMultiMapEqualRange(sit->second, key);
|
||||
const auto range = sit->second.equal_range(key);
|
||||
if (range.first == sit->second.end())
|
||||
{
|
||||
sit->second.emplace(std::string(key), std::move(value));
|
||||
@@ -213,10 +213,10 @@ std::vector<std::string> MemorySettingsInterface::GetStringList(const char* sect
|
||||
{
|
||||
std::vector<std::string> ret;
|
||||
|
||||
const auto sit = UnorderedStringMapFind(m_sections, section);
|
||||
const auto sit = m_sections.find(section);
|
||||
if (sit != m_sections.end())
|
||||
{
|
||||
const auto range = UnorderedStringMultiMapEqualRange(sit->second, key);
|
||||
const auto range = sit->second.equal_range(key);
|
||||
for (auto iter = range.first; iter != range.second; ++iter)
|
||||
ret.emplace_back(iter->second);
|
||||
}
|
||||
@@ -226,11 +226,11 @@ std::vector<std::string> MemorySettingsInterface::GetStringList(const char* sect
|
||||
|
||||
void MemorySettingsInterface::SetStringList(const char* section, const char* key, const std::vector<std::string>& items)
|
||||
{
|
||||
auto sit = UnorderedStringMapFind(m_sections, section);
|
||||
auto sit = m_sections.find(section);
|
||||
if (sit == m_sections.end())
|
||||
sit = m_sections.emplace(std::make_pair(std::string(section), KeyMap())).first;
|
||||
|
||||
const auto range = UnorderedStringMultiMapEqualRange(sit->second, key);
|
||||
const auto range = sit->second.equal_range(key);
|
||||
for (auto iter = range.first; iter != range.second;)
|
||||
sit->second.erase(iter++);
|
||||
|
||||
@@ -241,11 +241,11 @@ void MemorySettingsInterface::SetStringList(const char* section, const char* key
|
||||
|
||||
bool MemorySettingsInterface::RemoveFromStringList(const char* section, const char* key, const char* item)
|
||||
{
|
||||
auto sit = UnorderedStringMapFind(m_sections, section);
|
||||
auto sit = m_sections.find(section);
|
||||
if (sit == m_sections.end())
|
||||
sit = m_sections.emplace(std::make_pair(std::string(section), KeyMap())).first;
|
||||
|
||||
const auto range = UnorderedStringMultiMapEqualRange(sit->second, key);
|
||||
const auto range = sit->second.equal_range(key);
|
||||
bool result = false;
|
||||
for (auto iter = range.first; iter != range.second;)
|
||||
{
|
||||
@@ -265,11 +265,11 @@ bool MemorySettingsInterface::RemoveFromStringList(const char* section, const ch
|
||||
|
||||
bool MemorySettingsInterface::AddToStringList(const char* section, const char* key, const char* item)
|
||||
{
|
||||
auto sit = UnorderedStringMapFind(m_sections, section);
|
||||
auto sit = m_sections.find(section);
|
||||
if (sit == m_sections.end())
|
||||
sit = m_sections.emplace(std::make_pair(std::string(section), KeyMap())).first;
|
||||
|
||||
const auto range = UnorderedStringMultiMapEqualRange(sit->second, key);
|
||||
const auto range = sit->second.equal_range(key);
|
||||
for (auto iter = range.first; iter != range.second; ++iter)
|
||||
{
|
||||
if (iter->second == item)
|
||||
@@ -282,7 +282,7 @@ bool MemorySettingsInterface::AddToStringList(const char* section, const char* k
|
||||
|
||||
bool MemorySettingsInterface::ContainsValue(const char* section, const char* key) const
|
||||
{
|
||||
const auto sit = UnorderedStringMapFind(m_sections, section);
|
||||
const auto sit = m_sections.find(section);
|
||||
if (sit == m_sections.end())
|
||||
return false;
|
||||
|
||||
@@ -291,18 +291,18 @@ bool MemorySettingsInterface::ContainsValue(const char* section, const char* key
|
||||
|
||||
void MemorySettingsInterface::DeleteValue(const char* section, const char* key)
|
||||
{
|
||||
auto sit = UnorderedStringMapFind(m_sections, section);
|
||||
auto sit = m_sections.find(section);
|
||||
if (sit == m_sections.end())
|
||||
return;
|
||||
|
||||
const auto range = UnorderedStringMultiMapEqualRange(sit->second, key);
|
||||
const auto range = sit->second.equal_range(key);
|
||||
for (auto iter = range.first; iter != range.second;)
|
||||
sit->second.erase(iter++);
|
||||
}
|
||||
|
||||
void MemorySettingsInterface::ClearSection(const char* section)
|
||||
{
|
||||
auto sit = UnorderedStringMapFind(m_sections, section);
|
||||
auto sit = m_sections.find(section);
|
||||
if (sit == m_sections.end())
|
||||
return;
|
||||
|
||||
|
||||
+1
-1
@@ -110,7 +110,7 @@ struct crash_info_t
|
||||
u64 reserved;
|
||||
u64 reserved2;
|
||||
};
|
||||
#define CRASH_ANNOTATION __attribute__((section("__DATA,__crash_info")))
|
||||
#define CRASH_ANNOTATION __attribute__((used, section("__DATA,__crash_info")))
|
||||
#define CRASH_VERSION 4
|
||||
extern "C" crash_info_t gCRAnnotations CRASH_ANNOTATION = { CRASH_VERSION };
|
||||
#endif
|
||||
|
||||
+3
-4
@@ -81,10 +81,9 @@
|
||||
|
||||
// Defines the memory page size for the target platform at compilation. All supported platforms
|
||||
// (which means Intel only right now) have a 4k granularity.
|
||||
#define PCSX2_PAGESIZE 0x1000
|
||||
static constexpr int __pagesize = PCSX2_PAGESIZE;
|
||||
static constexpr int __pageshift = 12;
|
||||
static constexpr size_t __pagemask = PCSX2_PAGESIZE - 1;
|
||||
static constexpr unsigned int __pagesize = 0x1000;
|
||||
static constexpr unsigned int __pageshift = 12;
|
||||
static constexpr unsigned int __pagemask = __pagesize - 1;
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Microsoft Visual Studio
|
||||
|
||||
@@ -92,31 +92,31 @@ public:
|
||||
return value;
|
||||
}
|
||||
|
||||
__fi std::optional<int> GetOptionalIntValue(const char* section, const char* key, std::optional<int> default_value = std::nullopt)
|
||||
__fi std::optional<int> GetOptionalIntValue(const char* section, const char* key, std::optional<int> default_value = std::nullopt) const
|
||||
{
|
||||
int ret;
|
||||
return GetIntValue(section, key, &ret) ? std::optional<int>(ret) : default_value;
|
||||
}
|
||||
|
||||
__fi std::optional<uint> GetOptionalUIntValue(const char* section, const char* key, std::optional<uint> default_value = std::nullopt)
|
||||
__fi std::optional<uint> GetOptionalUIntValue(const char* section, const char* key, std::optional<uint> default_value = std::nullopt) const
|
||||
{
|
||||
uint ret;
|
||||
return GetUIntValue(section, key, &ret) ? std::optional<uint>(ret) : default_value;
|
||||
}
|
||||
|
||||
__fi std::optional<float> GetOptionalFloatValue(const char* section, const char* key, std::optional<float> default_value = std::nullopt)
|
||||
__fi std::optional<float> GetOptionalFloatValue(const char* section, const char* key, std::optional<float> default_value = std::nullopt) const
|
||||
{
|
||||
float ret;
|
||||
return GetFloatValue(section, key, &ret) ? std::optional<float>(ret) : default_value;
|
||||
}
|
||||
|
||||
__fi std::optional<double> GetOptionalDoubleValue(const char* section, const char* key, std::optional<double> default_value = std::nullopt)
|
||||
__fi std::optional<double> GetOptionalDoubleValue(const char* section, const char* key, std::optional<double> default_value = std::nullopt) const
|
||||
{
|
||||
double ret;
|
||||
return GetDoubleValue(section, key, &ret) ? std::optional<double>(ret) : default_value;
|
||||
}
|
||||
|
||||
__fi std::optional<bool> GetOptionalBoolValue(const char* section, const char* key, std::optional<bool> default_value = std::nullopt)
|
||||
__fi std::optional<bool> GetOptionalBoolValue(const char* section, const char* key, std::optional<bool> default_value = std::nullopt) const
|
||||
{
|
||||
bool ret;
|
||||
return GetBoolValue(section, key, &ret) ? std::optional<bool>(ret) : default_value;
|
||||
|
||||
@@ -643,7 +643,9 @@ bool unpack_bc7_mode0_2(uint32_t mode, const uint64_t* data_chunks, color_rgba*
|
||||
const uint32_t ENDPOINT_BITS = (mode == 0) ? 4 : 5;
|
||||
const uint32_t ENDPOINT_MASK = (1 << ENDPOINT_BITS) - 1;
|
||||
const uint32_t PBITS = (mode == 0) ? 6 : 0;
|
||||
#ifndef BC7DECOMP_USE_SSE2
|
||||
const uint32_t WEIGHT_VALS = 1 << WEIGHT_BITS;
|
||||
#endif
|
||||
const uint32_t PART_BITS = (mode == 0) ? 4 : 6;
|
||||
const uint32_t PART_MASK = (1 << PART_BITS) - 1;
|
||||
|
||||
@@ -740,7 +742,9 @@ bool unpack_bc7_mode1_3_7(uint32_t mode, const uint64_t* data_chunks, color_rgba
|
||||
const uint32_t ENDPOINT_MASK = (1 << ENDPOINT_BITS) - 1;
|
||||
const uint32_t PBITS = (mode == 1) ? 2 : 4;
|
||||
const uint32_t SHARED_PBITS = (mode == 1) ? true : false;
|
||||
#ifndef BC7DECOMP_USE_SSE2
|
||||
const uint32_t WEIGHT_VALS = 1 << WEIGHT_BITS;
|
||||
#endif
|
||||
|
||||
const uint64_t low_chunk = data_chunks[0];
|
||||
const uint64_t high_chunk = data_chunks[1];
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
#include "common/Align.h"
|
||||
#include "common/BitUtils.h"
|
||||
#include "common/RedtapeWindows.h"
|
||||
#include "common/Console.h"
|
||||
#include "common/General.h"
|
||||
|
||||
@@ -103,9 +103,8 @@
|
||||
<MASM Include="FastJmp.asm" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Align.h" />
|
||||
<ClInclude Include="BitUtils.h" />
|
||||
<ClInclude Include="AlignedMalloc.h" />
|
||||
<ClInclude Include="BitCast.h" />
|
||||
<ClInclude Include="ByteSwap.h" />
|
||||
<ClInclude Include="CrashHandler.h" />
|
||||
<ClInclude Include="DynamicLibrary.h" />
|
||||
@@ -135,7 +134,6 @@
|
||||
<ClInclude Include="Assertions.h" />
|
||||
<ClInclude Include="Console.h" />
|
||||
<ClInclude Include="General.h" />
|
||||
<ClInclude Include="MathUtils.h" />
|
||||
<ClInclude Include="Path.h" />
|
||||
<ClInclude Include="PrecompiledHeader.h" />
|
||||
<ClInclude Include="ReadbackSpinManager.h" />
|
||||
|
||||
@@ -201,9 +201,6 @@
|
||||
<ClInclude Include="emitter\legacy_types.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MathUtils.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Path.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@@ -270,15 +267,12 @@
|
||||
<ClInclude Include="SettingsWrapper.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Align.h">
|
||||
<ClInclude Include="BitUtils.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="WindowInfo.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="BitCast.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="StringUtil.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
||||
+49
-10
@@ -48,7 +48,7 @@
|
||||
#include "pcsx2/Input/InputManager.h"
|
||||
#include "pcsx2/LogSink.h"
|
||||
#include "pcsx2/MTGS.h"
|
||||
#include "pcsx2/PAD/Host/PAD.h"
|
||||
#include "pcsx2/SIO/Pad/Pad.h"
|
||||
#include "pcsx2/PerformanceMetrics.h"
|
||||
#include "pcsx2/VMManager.h"
|
||||
|
||||
@@ -80,11 +80,18 @@ static bool s_no_console = false;
|
||||
// Owned by the GS thread.
|
||||
static u32 s_dump_frame_number = 0;
|
||||
static u32 s_loop_number = s_loop_count;
|
||||
static double s_last_draws = 0;
|
||||
static double s_last_render_passes = 0;
|
||||
static double s_last_barriers = 0;
|
||||
static double s_last_copies = 0;
|
||||
static double s_last_uploads = 0;
|
||||
static double s_last_readbacks = 0;
|
||||
static u64 s_total_draws = 0;
|
||||
static u64 s_total_render_passes = 0;
|
||||
static u64 s_total_barriers = 0;
|
||||
static u64 s_total_copies = 0;
|
||||
static u64 s_total_uploads = 0;
|
||||
static u64 s_total_readbacks = 0;
|
||||
static u32 s_total_frames = 0;
|
||||
|
||||
bool GSRunner::InitializeConfig()
|
||||
@@ -110,7 +117,7 @@ bool GSRunner::InitializeConfig()
|
||||
si.SetStringValue("SPU2/Output", "OutputModule", "nullout");
|
||||
|
||||
// none of the bindings are going to resolve to anything
|
||||
PAD::ClearPortBindings(si, 0);
|
||||
Pad::ClearPortBindings(si, 0);
|
||||
si.ClearSection("Hotkeys");
|
||||
|
||||
// make sure any gamesettings inis in your tree don't get loaded
|
||||
@@ -250,7 +257,7 @@ void Host::OnInputDeviceDisconnected(const std::string_view& identifier)
|
||||
{
|
||||
}
|
||||
|
||||
void Host::SetRelativeMouseMode(bool enabled)
|
||||
void Host::SetMouseMode(bool relative_mode, bool hide_cursor)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -277,11 +284,18 @@ void Host::BeginPresentFrame()
|
||||
|
||||
if (GSConfig.UseHardwareRenderer())
|
||||
{
|
||||
s_total_draws += static_cast<u64>(g_perfmon.GetCounter(GSPerfMon::DrawCalls));
|
||||
s_total_render_passes += static_cast<u64>(g_perfmon.GetCounter(GSPerfMon::RenderPasses));
|
||||
s_total_barriers += static_cast<u64>(g_perfmon.GetCounter(GSPerfMon::Barriers));
|
||||
s_total_copies += static_cast<u64>(g_perfmon.GetCounter(GSPerfMon::TextureCopies));
|
||||
s_total_uploads += static_cast<u64>(g_perfmon.GetCounter(GSPerfMon::TextureUploads));
|
||||
static constexpr auto update_stat = [](GSPerfMon::counter_t counter, u64& dst, double& last) {
|
||||
// perfmon resets every 30 frames to zero
|
||||
const double val = g_perfmon.GetCounter(counter);
|
||||
dst += static_cast<u64>((val < last) ? val : (val - last));
|
||||
last = val;
|
||||
};
|
||||
update_stat(GSPerfMon::DrawCalls, s_total_draws, s_last_draws);
|
||||
update_stat(GSPerfMon::RenderPasses, s_total_render_passes, s_last_render_passes);
|
||||
update_stat(GSPerfMon::Barriers, s_total_barriers, s_last_barriers);
|
||||
update_stat(GSPerfMon::TextureCopies, s_total_copies, s_last_copies);
|
||||
update_stat(GSPerfMon::TextureUploads, s_total_uploads, s_last_uploads);
|
||||
update_stat(GSPerfMon::Readbacks, s_total_readbacks, s_last_readbacks);
|
||||
s_total_frames++;
|
||||
std::atomic_thread_fence(std::memory_order_release);
|
||||
}
|
||||
@@ -371,12 +385,15 @@ void Host::RequestVMShutdown(bool allow_confirm, bool allow_save_state, bool def
|
||||
VMManager::SetState(VMState::Stopping);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_ACHIEVEMENTS
|
||||
void Host::OnAchievementsLoginRequested(Achievements::LoginRequestReason reason)
|
||||
{
|
||||
// noop
|
||||
}
|
||||
|
||||
void Host::OnAchievementsRefreshed()
|
||||
{
|
||||
// noop
|
||||
}
|
||||
#endif
|
||||
|
||||
std::optional<u32> InputManager::ConvertHostKeyboardStringToCode(const std::string_view& str)
|
||||
{
|
||||
@@ -630,9 +647,15 @@ void GSRunner::DumpStats()
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Barriers: {} (avg {})", s_total_barriers, static_cast<u64>(std::ceil(s_total_barriers / static_cast<double>(s_total_frames)))));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Copies: {} (avg {})", s_total_copies, static_cast<u64>(std::ceil(s_total_copies / static_cast<double>(s_total_frames)))));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Uploads: {} (avg {})", s_total_uploads, static_cast<u64>(std::ceil(s_total_uploads / static_cast<double>(s_total_frames)))));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Readbacks: {} (avg {})", s_total_readbacks, static_cast<u64>(std::ceil(s_total_readbacks / static_cast<double>(s_total_frames)))));
|
||||
Console.WriteLn("============================================");
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
// We can't handle unicode in filenames if we don't use wmain on Win32.
|
||||
#define main real_main
|
||||
#endif
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
GSRunner::InitializeConsole();
|
||||
@@ -797,4 +820,20 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
return DefWindowProcW(hwnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
int wmain(int argc, wchar_t** argv)
|
||||
{
|
||||
std::vector<std::string> u8_args;
|
||||
u8_args.reserve(static_cast<size_t>(argc));
|
||||
for (int i = 0; i < argc; i++)
|
||||
u8_args.push_back(StringUtil::WideStringToUTF8String(argv[i]));
|
||||
|
||||
std::vector<char*> u8_argptrs;
|
||||
u8_argptrs.reserve(u8_args.size());
|
||||
for (int i = 0; i < argc; i++)
|
||||
u8_argptrs.push_back(u8_args[i].data());
|
||||
u8_argptrs.push_back(nullptr);
|
||||
|
||||
return real_main(argc, u8_argptrs.data());
|
||||
}
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
.modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
z-index: 1;
|
||||
padding-top: 100px;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
background-color: black;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
position: relative;
|
||||
margin: auto;
|
||||
padding: 0;
|
||||
width: 90%;
|
||||
max-width: 1200px;
|
||||
}
|
||||
|
||||
.close {
|
||||
color: white;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 25px;
|
||||
font-size: 35px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.close:hover,
|
||||
.close:focus {
|
||||
color: #999;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.prev,
|
||||
.next {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
width: auto;
|
||||
padding: 16px;
|
||||
margin-top: -50px;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
font-size: 20px;
|
||||
transition: 0.6s ease;
|
||||
border-radius: 0 3px 3px 0;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
|
||||
.next {
|
||||
right: 0;
|
||||
border-radius: 3px 0 0 3px;
|
||||
}
|
||||
|
||||
.prev:hover,
|
||||
.next:hover {
|
||||
background-color: rgba(0, 0, 0, 0.8);
|
||||
}
|
||||
|
||||
.item img {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#compareTitle {
|
||||
color: white;
|
||||
font-size: 20px;
|
||||
font-family: sans-serif;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#compareCaption {
|
||||
color: white;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
#compareState {
|
||||
display: block;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
color: red;
|
||||
font-family: sans-serif;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#compareImage {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/* Worst script known to man */
|
||||
/* Sources:
|
||||
https://www.w3schools.com/howto/howto_js_lightbox.asp
|
||||
https://css-tricks.com/prevent-page-scrolling-when-a-modal-is-open/
|
||||
*/
|
||||
|
||||
function openModal() {
|
||||
document.body.style.position = 'fixed';
|
||||
document.body.style.top = `-${window.scrollY}px`;
|
||||
document.getElementById("myModal").style.display = "block";
|
||||
document.getElementById("myModal").focus();
|
||||
setImageIndex(0);
|
||||
}
|
||||
|
||||
function closeModal() {
|
||||
document.getElementById("myModal").style.display = "none";
|
||||
const scrollY = document.body.style.top;
|
||||
document.body.style.position = '';
|
||||
document.body.style.top = '';
|
||||
window.scrollTo(0, parseInt(scrollY || '0') * -1);
|
||||
}
|
||||
|
||||
function isModalOpen() {
|
||||
return (document.getElementById("myModal").style.display == "block");
|
||||
}
|
||||
|
||||
function formatLines(str) {
|
||||
let lines = str.split("\n")
|
||||
lines = lines.filter(line => !line.startsWith("Difference in frames"))
|
||||
return lines.join("<br>")
|
||||
}
|
||||
|
||||
function extractItem(elem) {
|
||||
return {
|
||||
name: elem.querySelector("h1").innerText,
|
||||
beforeImg: elem.querySelector(".before").getAttribute("src"),
|
||||
afterImg: elem.querySelector(".after").getAttribute("src"),
|
||||
details: formatLines(elem.querySelector("pre").innerText)
|
||||
};
|
||||
}
|
||||
|
||||
const items = [...document.querySelectorAll(".item")].map(extractItem)
|
||||
let currentImage = 0;
|
||||
let currentState = 0;
|
||||
|
||||
function getImageIndexForUri(uri) {
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
if (items[i].beforeImg == uri || items[i].afterImg == uri)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
function setImageState(state) {
|
||||
const item = items[currentImage]
|
||||
const uri = (state === 0) ? item.beforeImg : item.afterImg;
|
||||
const stateText = (state === 0) ? "BEFORE" : "AFTER";
|
||||
const posText = "(" + (currentImage + 1).toString() + "/" + (items.length).toString() + ") ";
|
||||
document.getElementById("compareImage").setAttribute("src", uri);
|
||||
document.getElementById("compareState").innerText = stateText;
|
||||
document.getElementById("compareTitle").innerText = posText + item.name;
|
||||
document.getElementById("compareCaption").innerHTML = item.details;
|
||||
currentState = state;
|
||||
}
|
||||
|
||||
function setImageIndex(index) {
|
||||
if (index < 0 || index > items.length)
|
||||
return;
|
||||
|
||||
currentImage = index;
|
||||
setImageState(0);
|
||||
}
|
||||
|
||||
function handleKey(key) {
|
||||
if (key == " ") {
|
||||
setImageState((currentState === 0) ? 1 : 0);
|
||||
return true;
|
||||
} else if (key == "ArrowLeft") {
|
||||
setImageIndex(currentImage - 1);
|
||||
return true;
|
||||
} else if (key == "ArrowRight") {
|
||||
setImageIndex(currentImage + 1);
|
||||
return true;
|
||||
} else if (key == "Escape") {
|
||||
closeModal();
|
||||
return true;
|
||||
} else {
|
||||
console.log(key);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById("myModal").addEventListener("keydown", function(ev) {
|
||||
if (ev.defaultPrevented)
|
||||
return;
|
||||
|
||||
if (handleKey(ev.key))
|
||||
ev.preventDefault();
|
||||
});
|
||||
|
||||
document.querySelector("#myModal .prev").addEventListener("click", function() {
|
||||
setImageIndex(currentImage - 1);
|
||||
});
|
||||
document.querySelector("#myModal .next").addEventListener("click", function() {
|
||||
setImageIndex(currentImage + 1);
|
||||
});
|
||||
document.querySelectorAll(".item img").forEach(elem => elem.addEventListener("click", function() {
|
||||
if (!isModalOpen())
|
||||
openModal();
|
||||
setImageIndex(getImageIndexForUri(this.getAttribute("src")));
|
||||
}));
|
||||
@@ -7,17 +7,35 @@ import hashlib
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
MAX_DIFF_FRAMES = 9999
|
||||
|
||||
SCRIPTDIR = os.path.abspath(os.path.dirname(__file__))
|
||||
CSS_PATH = Path(os.path.join(SCRIPTDIR, "comparer.css")).as_uri()
|
||||
JS_PATH = Path(os.path.join(SCRIPTDIR, "comparer.js")).as_uri()
|
||||
|
||||
FILE_HEADER = """
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Comparison</title>
|
||||
""" + f"<link rel=\"stylesheet\" href=\"{CSS_PATH}\" />" + """
|
||||
</head>
|
||||
<body>
|
||||
"""
|
||||
|
||||
FILE_FOOTER = """
|
||||
<div id="myModal" class="modal" tabindex="0">
|
||||
<span class="close cursor" onclick="closeModal()">×</span>
|
||||
<div class="modal-content">
|
||||
<div id="compareTitle"></div>
|
||||
<img id="compareImage" />
|
||||
<div id="compareState"></div>
|
||||
<a class="prev">❮</a>
|
||||
<a class="next">❯</a>
|
||||
<div id="compareCaption"></div>
|
||||
</div>
|
||||
</div>
|
||||
""" + f"<script src=\"{JS_PATH}\"></script>\n" + """
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
@@ -103,6 +121,7 @@ def check_regression_test(baselinedir, testdir, name):
|
||||
diff_frames.append(framenum)
|
||||
|
||||
if first_fail:
|
||||
write("<div class=\"item\">")
|
||||
write("<h1>{}</h1>".format(name))
|
||||
write("<table width=\"100%\">")
|
||||
first_fail = False
|
||||
@@ -110,14 +129,17 @@ def check_regression_test(baselinedir, testdir, name):
|
||||
imguri1 = Path(path1).as_uri()
|
||||
imguri2 = Path(path2).as_uri()
|
||||
write("<tr><td colspan=\"2\">Frame %d</td></tr>" % (framenum))
|
||||
write("<tr><td><img src=\"%s\" /></td><td><img src=\"%s\" /></td></tr>" % (imguri1, imguri2))
|
||||
write("<tr><td><img class=\"before\" src=\"%s\" /></td><td><img class=\"after\" src=\"%s\" /></td></tr>" % (imguri1, imguri2))
|
||||
|
||||
if len(diff_frames) == MAX_DIFF_FRAMES:
|
||||
break
|
||||
|
||||
if len(diff_frames) > 0:
|
||||
write("</table>")
|
||||
write("<pre>Difference in frames [%s] for %s</pre>" % (",".join(map(str, diff_frames)), name))
|
||||
write("<pre>Difference in frames [%s] for %s%s%s</pre>" % (",".join(map(str, diff_frames)), name, "\n" if len(stats) > 0 else "", "\n".join(stats)))
|
||||
write("</div>")
|
||||
print("*** Difference in frames [%s] for %s" % (",".join(map(str, diff_frames)), name))
|
||||
if len(stats) > 0:
|
||||
write("<pre>%s</pre>" % "\n".join(stats))
|
||||
print(stats)
|
||||
elif len(stats) > 0:
|
||||
write("<h1>{}</h1>".format(name))
|
||||
@@ -149,9 +171,11 @@ if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Check frame dump images for regression tests")
|
||||
parser.add_argument("-baselinedir", action="store", required=True, help="Directory containing baseline frames to check against")
|
||||
parser.add_argument("-testdir", action="store", required=True, help="Directory containing frames to check")
|
||||
parser.add_argument("-maxframes", type=int, action="store", required=False, default=9999, help="Max frames to compare")
|
||||
parser.add_argument("outfile", action="store", help="The file to write the output to")
|
||||
|
||||
args = parser.parse_args()
|
||||
MAX_DIFF_FRAMES = args.maxframes
|
||||
|
||||
outfile = open(args.outfile, "w")
|
||||
write(FILE_HEADER)
|
||||
|
||||
@@ -380,6 +380,8 @@ void AutoUpdaterDialog::getChangesComplete(QNetworkReply* reply)
|
||||
changes_html.prepend(tr("<h2>Save State Warning</h2><p>Installing this update will make your save states "
|
||||
"<b>incompatible</b>. Please ensure you have saved your games to a Memory Card "
|
||||
"before installing this update or you will lose progress.</p>"));
|
||||
|
||||
m_update_will_break_save_states = true;
|
||||
}
|
||||
|
||||
if (update_increases_settings_version)
|
||||
@@ -407,6 +409,23 @@ void AutoUpdaterDialog::getChangesComplete(QNetworkReply* reply)
|
||||
|
||||
void AutoUpdaterDialog::downloadUpdateClicked()
|
||||
{
|
||||
if (m_update_will_break_save_states)
|
||||
{
|
||||
QMessageBox msgbox;
|
||||
msgbox.setIcon(QMessageBox::Critical);
|
||||
msgbox.setWindowTitle(tr("Savestate Warning"));
|
||||
msgbox.setText(tr("<h1>WARNING</h1><p style='font-size:12pt;'>Installing this update will make your <b>save states incompatible</b>, <i>be sure to save any progress to your memory cards before proceeding</i>.</p><p>Do you wish to continue?</p>"));
|
||||
msgbox.addButton(QMessageBox::Yes);
|
||||
msgbox.addButton(QMessageBox::No);
|
||||
msgbox.setDefaultButton(QMessageBox::No);
|
||||
// This makes the box wider, for some reason sizing boxes in Qt is hard - Source: The internet.
|
||||
QSpacerItem* horizontalSpacer = new QSpacerItem(500, 0, QSizePolicy::Minimum, QSizePolicy::Expanding);
|
||||
QGridLayout* layout = (QGridLayout*)msgbox.layout();
|
||||
layout->addItem(horizontalSpacer, layout->rowCount(), 0, 1, layout->columnCount());
|
||||
if (msgbox.exec() != QMessageBox::Yes)
|
||||
return;
|
||||
}
|
||||
|
||||
m_display_messages = true;
|
||||
QUrl url(m_download_url);
|
||||
QNetworkRequest request(url);
|
||||
|
||||
@@ -55,6 +55,7 @@ target_sources(pcsx2-qt PRIVATE
|
||||
Settings/BIOSSettingsWidget.ui
|
||||
Settings/ControllerBindingWidget.ui
|
||||
Settings/ControllerBindingWidget_DualShock2.ui
|
||||
Settings/ControllerBindingWidget_Guitar.ui
|
||||
Settings/ControllerBindingWidgets.cpp
|
||||
Settings/ControllerBindingWidgets.h
|
||||
Settings/ControllerLEDSettingsDialog.ui
|
||||
@@ -133,6 +134,7 @@ target_sources(pcsx2-qt PRIVATE
|
||||
Settings/SettingsDialog.ui
|
||||
Settings/USBBindingWidget_DrivingForce.ui
|
||||
Settings/USBBindingWidget_GTForce.ui
|
||||
Settings/USBBindingWidget_GunCon2.ui
|
||||
Debugger/CpuWidget.cpp
|
||||
Debugger/CpuWidget.h
|
||||
Debugger/CpuWidget.ui
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
#include "DebugTools/Breakpoints.h"
|
||||
#include "DebugTools/BiosDebugData.h"
|
||||
#include "DebugTools/MipsStackWalk.h"
|
||||
#include "common/BitCast.h"
|
||||
|
||||
#include "QtUtils.h"
|
||||
#include <QtGui/QClipboard>
|
||||
@@ -539,7 +538,7 @@ static std::vector<u32> searchWorker(DebugInterface* cpu, u32 start, u32 end, T
|
||||
{
|
||||
const float fTop = value + 0.00001f;
|
||||
const float fBottom = value - 0.00001f;
|
||||
const float memValue = bit_cast<float, u32>(cpu->read32(addr));
|
||||
const float memValue = std::bit_cast<float, u32>(cpu->read32(addr));
|
||||
if (fBottom < memValue && memValue < fTop)
|
||||
{
|
||||
hitAddresses.emplace_back(addr);
|
||||
@@ -556,7 +555,7 @@ static std::vector<u32> searchWorker(DebugInterface* cpu, u32 start, u32 end, T
|
||||
{
|
||||
const double dTop = value + 0.00001f;
|
||||
const double dBottom = value - 0.00001f;
|
||||
const double memValue = bit_cast<double, u64>(cpu->read64(addr));
|
||||
const double memValue = std::bit_cast<double, u64>(cpu->read64(addr));
|
||||
if (dBottom < memValue && memValue < dTop)
|
||||
{
|
||||
hitAddresses.emplace_back(addr);
|
||||
@@ -588,9 +587,9 @@ static std::vector<u32> searchWorkerByteArray(DebugInterface* cpu, u32 start, u3
|
||||
for (u32 addr = start; addr < end; addr += 1)
|
||||
{
|
||||
bool hit = true;
|
||||
for (size_t i = 0; i < value.length(); i++)
|
||||
for (qsizetype i = 0; i < value.length(); i++)
|
||||
{
|
||||
if (cpu->read8(addr + i) != value[i])
|
||||
if (static_cast<char>(cpu->read8(addr + i)) != value[i])
|
||||
{
|
||||
hit = false;
|
||||
break;
|
||||
|
||||
@@ -151,9 +151,10 @@ void DisassemblyWidget::contextNoopInstruction()
|
||||
|
||||
void DisassemblyWidget::contextRunToCursor()
|
||||
{
|
||||
Host::RunOnCPUThread([&] { CBreakPoints::AddBreakPoint(m_cpu->getCpuType(), m_selectedAddressStart); });
|
||||
|
||||
m_cpu->resumeCpu();
|
||||
Host::RunOnCPUThread([&] {
|
||||
CBreakPoints::AddBreakPoint(m_cpu->getCpuType(), m_selectedAddressStart, true);
|
||||
m_cpu->resumeCpu();
|
||||
});
|
||||
}
|
||||
|
||||
void DisassemblyWidget::contextJumpToCursor()
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
|
||||
#include "MemoryViewWidget.h"
|
||||
|
||||
#include "common/BitCast.h"
|
||||
|
||||
#include "QtHost.h"
|
||||
#include "QtUtils.h"
|
||||
#include <QtGui/QMouseEvent>
|
||||
|
||||
@@ -78,7 +78,7 @@ QVariant BreakpointModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
QString type("");
|
||||
type += (mc->cond & MEMCHECK_READ) ? tr("Read") : "";
|
||||
type += ((mc->cond & MEMCHECK_BOTH) == MEMCHECK_BOTH) ? ", " : " ";
|
||||
type += ((mc->cond & MEMCHECK_READWRITE) == MEMCHECK_READWRITE) ? ", " : " ";
|
||||
//: (C) = changes, as in "look for changes".
|
||||
type += (mc->cond & MEMCHECK_WRITE) ? (mc->cond & MEMCHECK_WRITE_ONCHANGE) ? tr("Write(C)") : tr("Write") : "";
|
||||
return type;
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
|
||||
#include "RegisterWidget.h"
|
||||
|
||||
#include "common/BitCast.h"
|
||||
|
||||
#include "QtUtils.h"
|
||||
#include <QtGui/QMouseEvent>
|
||||
#include <QtWidgets/QTabBar>
|
||||
@@ -30,6 +28,7 @@
|
||||
#include <QtWidgets/QMessageBox>
|
||||
|
||||
#include <algorithm>
|
||||
#include <bit>
|
||||
|
||||
#define CAT_SHOW_FLOAT (categoryIndex == EECAT_FPR && m_showFPRFloat) || (categoryIndex == EECAT_VU0F && m_showVU0FFloat)
|
||||
|
||||
@@ -151,7 +150,7 @@ void RegisterWidget::paintEvent(QPaintEvent* event)
|
||||
|
||||
if (categoryIndex == EECAT_VU0F && m_showVU0FFloat)
|
||||
painter.drawText(m_fieldStartX[j], yStart, m_fieldWidth, m_rowHeight, Qt::AlignLeft,
|
||||
painter.fontMetrics().elidedText(QString::number(bit_cast<float>(m_cpu->getRegister(categoryIndex, registerIndex)._u32[regIndex])), Qt::ElideRight, m_fieldWidth - painter.fontMetrics().averageCharWidth()));
|
||||
painter.fontMetrics().elidedText(QString::number(std::bit_cast<float>(m_cpu->getRegister(categoryIndex, registerIndex)._u32[regIndex])), Qt::ElideRight, m_fieldWidth - painter.fontMetrics().averageCharWidth()));
|
||||
else
|
||||
painter.drawText(m_fieldStartX[j], yStart, m_fieldWidth, m_rowHeight,
|
||||
Qt::AlignLeft, FilledQStringFromValue(curRegister._u32[regIndex], 16));
|
||||
@@ -168,7 +167,7 @@ void RegisterWidget::paintEvent(QPaintEvent* event)
|
||||
|
||||
if (categoryIndex == EECAT_FPR && m_showFPRFloat)
|
||||
painter.drawText(safeValueStartX, yStart, renderSize.width(), m_rowHeight, Qt::AlignLeft,
|
||||
QString("%1").arg(QString::number(bit_cast<float>(m_cpu->getRegister(categoryIndex, registerIndex)._u32[0]))).toUpper());
|
||||
QString("%1").arg(QString::number(std::bit_cast<float>(m_cpu->getRegister(categoryIndex, registerIndex)._u32[0]))).toUpper());
|
||||
else if (m_cpu->getRegisterSize(categoryIndex) == 64)
|
||||
painter.drawText(safeValueStartX, yStart, renderSize.width(), m_rowHeight, Qt::AlignLeft,
|
||||
FilledQStringFromValue(m_cpu->getRegister(categoryIndex, registerIndex).lo, 16));
|
||||
@@ -299,7 +298,7 @@ void RegisterWidget::contextCopyValue()
|
||||
const int categoryIndex = ui.registerTabs->currentIndex();
|
||||
const u128 val = m_cpu->getRegister(categoryIndex, m_selectedRow);
|
||||
if (CAT_SHOW_FLOAT)
|
||||
QApplication::clipboard()->setText(QString("%1").arg(QString::number(bit_cast<float>(val._u32[0])).toUpper(), 16));
|
||||
QApplication::clipboard()->setText(QString("%1").arg(QString::number(std::bit_cast<float>(val._u32[0])).toUpper(), 16));
|
||||
else
|
||||
QApplication::clipboard()->setText(QString("%1").arg(QString::number(val._u64[0], 16).toUpper(), 16));
|
||||
}
|
||||
@@ -323,7 +322,7 @@ void RegisterWidget::contextCopySegment()
|
||||
const int categoryIndex = ui.registerTabs->currentIndex();
|
||||
const u128 val = m_cpu->getRegister(categoryIndex, m_selectedRow);
|
||||
if (CAT_SHOW_FLOAT)
|
||||
QApplication::clipboard()->setText(FilledQStringFromValue(bit_cast<float>(val._u32[3 - m_selected128Field]), 10));
|
||||
QApplication::clipboard()->setText(FilledQStringFromValue(std::bit_cast<float>(val._u32[3 - m_selected128Field]), 10));
|
||||
else
|
||||
QApplication::clipboard()->setText(FilledQStringFromValue(val._u32[3 - m_selected128Field], 16));
|
||||
}
|
||||
@@ -340,7 +339,7 @@ bool RegisterWidget::contextFetchNewValue(u64& out, u64 currentValue, bool segme
|
||||
if (!floatingPoint)
|
||||
existingValue = existingValue.arg(currentValue, regSize == 64 ? 16 : 8, 16, QChar('0'));
|
||||
else
|
||||
existingValue = existingValue.arg(bit_cast<float>((u32)currentValue));
|
||||
existingValue = existingValue.arg(std::bit_cast<float>((u32)currentValue));
|
||||
|
||||
//: Changing the value in a CPU register (e.g. "Change t0")
|
||||
QString input = QInputDialog::getText(this, tr("Change %1").arg(m_cpu->getRegisterName(categoryIndex, m_selectedRow)), "",
|
||||
@@ -360,7 +359,7 @@ bool RegisterWidget::contextFetchNewValue(u64& out, u64 currentValue, bool segme
|
||||
}
|
||||
else
|
||||
{
|
||||
out = bit_cast<u32>(input.toFloat(&ok));
|
||||
out = std::bit_cast<u32>(input.toFloat(&ok));
|
||||
if (!ok)
|
||||
{
|
||||
QMessageBox::warning(this, tr("Invalid register value"), tr("Invalid floating-point register value."));
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "QtHost.h"
|
||||
#include "QtUtils.h"
|
||||
|
||||
#include "pcsx2/GS/GSIntrin.h" // _BitScanForward
|
||||
#include "pcsx2/ImGui/ImGuiManager.h"
|
||||
|
||||
#include "common/Assertions.h"
|
||||
@@ -32,6 +31,8 @@
|
||||
#include <QtGui/QScreen>
|
||||
#include <QtGui/QWindow>
|
||||
#include <QtGui/QWindowStateChangeEvent>
|
||||
|
||||
#include <bit>
|
||||
#include <cmath>
|
||||
|
||||
#if defined(_WIN32)
|
||||
@@ -301,11 +302,12 @@ bool DisplayWidget::event(QEvent* event)
|
||||
case QEvent::MouseButtonDblClick:
|
||||
case QEvent::MouseButtonRelease:
|
||||
{
|
||||
unsigned long button_index;
|
||||
if (_BitScanForward(&button_index, static_cast<u32>(static_cast<const QMouseEvent*>(event)->button())))
|
||||
if (const u32 button_mask = static_cast<u32>(static_cast<const QMouseEvent*>(event)->button()))
|
||||
{
|
||||
Host::RunOnCPUThread([button_index, pressed = (event->type() != QEvent::MouseButtonRelease)]() {
|
||||
InputManager::InvokeEvents(InputManager::MakePointerButtonKey(0, button_index), static_cast<float>(pressed));
|
||||
Host::RunOnCPUThread([button_index = std::countr_zero(button_mask),
|
||||
pressed = (event->type() != QEvent::MouseButtonRelease)]() {
|
||||
InputManager::InvokeEvents(
|
||||
InputManager::MakePointerButtonKey(0, button_index), static_cast<float>(pressed));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+41
-13
@@ -25,6 +25,7 @@
|
||||
#include "QtHost.h"
|
||||
#include "QtUtils.h"
|
||||
#include "SettingWidgetBinder.h"
|
||||
#include "Settings/AchievementLoginDialog.h"
|
||||
#include "Settings/ControllerSettingsDialog.h"
|
||||
#include "Settings/GameListSettingsWidget.h"
|
||||
#include "Settings/InterfaceSettingsWidget.h"
|
||||
@@ -414,7 +415,7 @@ void MainWindow::connectVMThreadSignals(EmuThread* thread)
|
||||
connect(thread, &EmuThread::onAcquireRenderWindowRequested, this, &MainWindow::acquireRenderWindow, Qt::BlockingQueuedConnection);
|
||||
connect(thread, &EmuThread::onReleaseRenderWindowRequested, this, &MainWindow::releaseRenderWindow, Qt::BlockingQueuedConnection);
|
||||
connect(thread, &EmuThread::onResizeRenderWindowRequested, this, &MainWindow::displayResizeRequested);
|
||||
connect(thread, &EmuThread::onRelativeMouseModeRequested, this, &MainWindow::relativeMouseModeRequested);
|
||||
connect(thread, &EmuThread::onMouseModeRequested, this, &MainWindow::mouseModeRequested);
|
||||
connect(thread, &EmuThread::onVMStarting, this, &MainWindow::onVMStarting);
|
||||
connect(thread, &EmuThread::onVMStarted, this, &MainWindow::onVMStarted);
|
||||
connect(thread, &EmuThread::onVMPaused, this, &MainWindow::onVMPaused);
|
||||
@@ -423,6 +424,7 @@ void MainWindow::connectVMThreadSignals(EmuThread* thread)
|
||||
connect(thread, &EmuThread::onGameChanged, this, &MainWindow::onGameChanged);
|
||||
connect(thread, &EmuThread::onCaptureStarted, this, &MainWindow::onCaptureStarted);
|
||||
connect(thread, &EmuThread::onCaptureStopped, this, &MainWindow::onCaptureStopped);
|
||||
connect(thread, &EmuThread::onAchievementsLoginRequested, this, &MainWindow::onAchievementsLoginRequested);
|
||||
|
||||
connect(m_ui.actionReset, &QAction::triggered, thread, &EmuThread::resetVM);
|
||||
connect(m_ui.actionPause, &QAction::toggled, thread, &EmuThread::setVMPaused);
|
||||
@@ -628,6 +630,14 @@ void MainWindow::onCaptureStopped()
|
||||
m_ui.actionToolsVideoCapture->setChecked(false);
|
||||
}
|
||||
|
||||
void MainWindow::onAchievementsLoginRequested(Achievements::LoginRequestReason reason)
|
||||
{
|
||||
auto lock = pauseAndLockVM();
|
||||
|
||||
AchievementLoginDialog dlg(this, reason);
|
||||
dlg.exec();
|
||||
}
|
||||
|
||||
void MainWindow::onSettingsTriggeredFromToolbar()
|
||||
{
|
||||
if (s_vm_valid)
|
||||
@@ -887,7 +897,8 @@ bool MainWindow::isRenderingToMain() const
|
||||
|
||||
bool MainWindow::shouldHideMouseCursor() const
|
||||
{
|
||||
return (isRenderingFullscreen() && Host::GetBoolSettingValue("UI", "HideMouseCursor", false)) || m_relative_mouse_mode;
|
||||
return ((isRenderingFullscreen() && Host::GetBoolSettingValue("UI", "HideMouseCursor", false)) ||
|
||||
m_relative_mouse_mode || m_hide_mouse_cursor);
|
||||
}
|
||||
|
||||
bool MainWindow::shouldHideMainWindow() const
|
||||
@@ -1126,8 +1137,9 @@ void MainWindow::onGameListEntryContextMenuRequested(const QPoint& point)
|
||||
if (action->isEnabled())
|
||||
{
|
||||
connect(action, &QAction::triggered, [entry]() {
|
||||
SettingsDialog::openGamePropertiesDialog(
|
||||
entry, (entry->type != GameList::EntryType::ELF) ? std::string_view(entry->serial) : std::string_view(), entry->crc);
|
||||
SettingsDialog::openGamePropertiesDialog(entry, entry->title,
|
||||
(entry->type != GameList::EntryType::ELF) ? entry->serial : std::string(),
|
||||
entry->crc);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1319,13 +1331,15 @@ void MainWindow::onViewGamePropertiesActionTriggered()
|
||||
return;
|
||||
|
||||
// prefer to use a game list entry, if we have one, that way the summary is populated
|
||||
if (!m_current_disc_path.isEmpty() && m_current_elf_override.isEmpty())
|
||||
if (!m_current_disc_path.isEmpty() || !m_current_elf_override.isEmpty())
|
||||
{
|
||||
auto lock = GameList::GetLock();
|
||||
const GameList::Entry* entry = GameList::GetEntryForPath(m_current_disc_path.toUtf8().constData());
|
||||
const QString& path = (m_current_elf_override.isEmpty() ? m_current_disc_path : m_current_elf_override);
|
||||
const GameList::Entry* entry = GameList::GetEntryForPath(path.toUtf8().constData());
|
||||
if (entry)
|
||||
{
|
||||
SettingsDialog::openGamePropertiesDialog(entry, entry->serial, entry->crc);
|
||||
SettingsDialog::openGamePropertiesDialog(
|
||||
entry, entry->title, m_current_elf_override.isEmpty() ? entry->serial : std::string(), entry->crc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1339,9 +1353,15 @@ void MainWindow::onViewGamePropertiesActionTriggered()
|
||||
|
||||
// can't use serial for ELFs, because they might have a disc set
|
||||
if (m_current_elf_override.isEmpty())
|
||||
SettingsDialog::openGamePropertiesDialog(nullptr, m_current_disc_serial.toStdString(), m_current_disc_crc);
|
||||
{
|
||||
SettingsDialog::openGamePropertiesDialog(
|
||||
nullptr, m_current_title.toStdString(), m_current_disc_serial.toStdString(), m_current_disc_crc);
|
||||
}
|
||||
else
|
||||
SettingsDialog::openGamePropertiesDialog(nullptr, std::string_view(), m_current_disc_crc);
|
||||
{
|
||||
SettingsDialog::openGamePropertiesDialog(
|
||||
nullptr, m_current_title.toStdString(), std::string(), m_current_disc_crc);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::onGitHubRepositoryActionTriggered()
|
||||
@@ -1994,12 +2014,13 @@ void MainWindow::displayResizeRequested(qint32 width, qint32 height)
|
||||
QtUtils::ResizePotentiallyFixedSizeWindow(this, width, height + extra_height);
|
||||
}
|
||||
|
||||
void MainWindow::relativeMouseModeRequested(bool enabled)
|
||||
void MainWindow::mouseModeRequested(bool relative_mode, bool hide_cursor)
|
||||
{
|
||||
if (m_relative_mouse_mode == enabled)
|
||||
if (m_relative_mouse_mode == relative_mode && m_hide_mouse_cursor == hide_cursor)
|
||||
return;
|
||||
|
||||
m_relative_mouse_mode = enabled;
|
||||
m_relative_mouse_mode = relative_mode;
|
||||
m_hide_mouse_cursor = hide_cursor;
|
||||
if (m_display_widget && !s_vm_paused)
|
||||
updateDisplayWidgetCursor();
|
||||
}
|
||||
@@ -2264,7 +2285,8 @@ void MainWindow::setGameListEntryCoverImage(const GameList::Entry* entry)
|
||||
if (filename.isEmpty())
|
||||
return;
|
||||
|
||||
if (!GameList::GetCoverImagePathForEntry(entry).empty())
|
||||
const QString old_filename = QString::fromStdString(GameList::GetCoverImagePathForEntry(entry));
|
||||
if (!old_filename.isEmpty())
|
||||
{
|
||||
if (QMessageBox::question(this, tr("Cover Already Exists"),
|
||||
tr("A cover image for this game already exists, do you wish to replace it?"), QMessageBox::Yes,
|
||||
@@ -2290,6 +2312,12 @@ void MainWindow::setGameListEntryCoverImage(const GameList::Entry* entry)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!old_filename.isEmpty() && old_filename != new_filename && !QFile::remove(old_filename))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Copy Error"), tr("Failed to remove '%1'").arg(old_filename));
|
||||
return;
|
||||
}
|
||||
|
||||
m_game_list_widget->refreshGridCovers();
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,11 @@ class ControllerSettingsDialog;
|
||||
|
||||
class EmuThread;
|
||||
|
||||
namespace Achievements
|
||||
{
|
||||
enum class LoginRequestReason;
|
||||
}
|
||||
|
||||
namespace GameList
|
||||
{
|
||||
struct Entry;
|
||||
@@ -124,7 +129,7 @@ private Q_SLOTS:
|
||||
|
||||
std::optional<WindowInfo> acquireRenderWindow(bool recreate_window, bool fullscreen, bool render_to_main, bool surfaceless);
|
||||
void displayResizeRequested(qint32 width, qint32 height);
|
||||
void relativeMouseModeRequested(bool enabled);
|
||||
void mouseModeRequested(bool relative_mode, bool hide_cursor);
|
||||
void releaseRenderWindow();
|
||||
void focusDisplayWidget();
|
||||
|
||||
@@ -186,6 +191,8 @@ private Q_SLOTS:
|
||||
void onCaptureStarted(const QString& filename);
|
||||
void onCaptureStopped();
|
||||
|
||||
void onAchievementsLoginRequested(Achievements::LoginRequestReason reason);
|
||||
|
||||
protected:
|
||||
void showEvent(QShowEvent* event) override;
|
||||
void closeEvent(QCloseEvent* event) override;
|
||||
@@ -293,6 +300,7 @@ private:
|
||||
|
||||
bool m_display_created = false;
|
||||
bool m_relative_mouse_mode = false;
|
||||
bool m_hide_mouse_cursor = false;
|
||||
bool m_was_paused_on_surface_loss = false;
|
||||
bool m_was_disc_change_request = false;
|
||||
bool m_is_closing = false;
|
||||
|
||||
@@ -184,6 +184,10 @@
|
||||
<property name="title">
|
||||
<string>Input Recording</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="keyboard-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<addaction name="actionInputRecNew"/>
|
||||
<addaction name="actionInputRecPlay"/>
|
||||
<addaction name="actionInputRecStop"/>
|
||||
@@ -863,6 +867,10 @@
|
||||
<property name="text">
|
||||
<string>Toggle Software Rendering</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="brush-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDebugger">
|
||||
<property name="icon">
|
||||
@@ -877,6 +885,10 @@
|
||||
<property name="text">
|
||||
<string>Reload Cheats/Patches</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="refresh-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionEnableSystemConsole">
|
||||
<property name="checkable">
|
||||
@@ -914,6 +926,10 @@
|
||||
<property name="text">
|
||||
<string>Save Single Frame GS Dump</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="save-3-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionInputRecNew">
|
||||
<property name="enabled">
|
||||
|
||||
+8
-3
@@ -40,7 +40,6 @@
|
||||
#include "pcsx2/Input/InputManager.h"
|
||||
#include "pcsx2/LogSink.h"
|
||||
#include "pcsx2/MTGS.h"
|
||||
#include "pcsx2/PAD/Host/PAD.h"
|
||||
#include "pcsx2/PerformanceMetrics.h"
|
||||
#include "pcsx2/SysForwardDefs.h"
|
||||
#include "pcsx2/VMManager.h"
|
||||
@@ -1080,6 +1079,11 @@ void Host::OnSaveStateSaved(const std::string_view& filename)
|
||||
}
|
||||
|
||||
#ifdef ENABLE_ACHIEVEMENTS
|
||||
void Host::OnAchievementsLoginRequested(Achievements::LoginRequestReason reason)
|
||||
{
|
||||
emit g_emu_thread->onAchievementsLoginRequested(reason);
|
||||
}
|
||||
|
||||
void Host::OnAchievementsRefreshed()
|
||||
{
|
||||
u32 game_id = 0;
|
||||
@@ -1469,9 +1473,9 @@ void Host::OnInputDeviceDisconnected(const std::string_view& identifier)
|
||||
emit g_emu_thread->onInputDeviceDisconnected(identifier.empty() ? QString() : QString::fromUtf8(identifier.data(), identifier.size()));
|
||||
}
|
||||
|
||||
void Host::SetRelativeMouseMode(bool enabled)
|
||||
void Host::SetMouseMode(bool relative_mode, bool hide_cursor)
|
||||
{
|
||||
emit g_emu_thread->onRelativeMouseModeRequested(enabled);
|
||||
emit g_emu_thread->onMouseModeRequested(relative_mode, hide_cursor);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -1779,6 +1783,7 @@ void QtHost::RegisterTypes()
|
||||
qRegisterMetaType<InputBindingKey>();
|
||||
qRegisterMetaType<CDVD_SourceType>();
|
||||
qRegisterMetaType<const GameList::Entry*>();
|
||||
qRegisterMetaType<Achievements::LoginRequestReason>();
|
||||
}
|
||||
|
||||
bool QtHost::RunSetupWizard()
|
||||
|
||||
+10
-1
@@ -41,11 +41,17 @@ struct VMBootParameters;
|
||||
|
||||
enum class CDVD_SourceType : uint8_t;
|
||||
|
||||
namespace Achievements
|
||||
{
|
||||
enum class LoginRequestReason;
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(std::shared_ptr<VMBootParameters>);
|
||||
Q_DECLARE_METATYPE(std::optional<bool>);
|
||||
Q_DECLARE_METATYPE(GSRendererType);
|
||||
Q_DECLARE_METATYPE(InputBindingKey);
|
||||
Q_DECLARE_METATYPE(CDVD_SourceType);
|
||||
Q_DECLARE_METATYPE(Achievements::LoginRequestReason);
|
||||
|
||||
class EmuThread : public QThread
|
||||
{
|
||||
@@ -119,7 +125,7 @@ Q_SIGNALS:
|
||||
std::optional<WindowInfo> onAcquireRenderWindowRequested(bool recreate_window, bool fullscreen, bool render_to_main, bool surfaceless);
|
||||
void onResizeRenderWindowRequested(qint32 width, qint32 height);
|
||||
void onReleaseRenderWindowRequested();
|
||||
void onRelativeMouseModeRequested(bool enabled);
|
||||
void onMouseModeRequested(bool relative_mode, bool hide_cursor);
|
||||
|
||||
/// Called when the VM is starting initialization, but has not been completed yet.
|
||||
void onVMStarting();
|
||||
@@ -155,6 +161,9 @@ Q_SIGNALS:
|
||||
/// just signifies that the save has started, not necessarily completed.
|
||||
void onSaveStateSaved(const QString& path);
|
||||
|
||||
/// Called when achievements login is requested.
|
||||
void onAchievementsLoginRequested(Achievements::LoginRequestReason reason);
|
||||
|
||||
/// Called when achievements are reloaded/refreshed (e.g. game change, login, option change).
|
||||
void onAchievementsRefreshed(quint32 id, const QString& game_info_string, quint32 total, quint32 points);
|
||||
|
||||
|
||||
+18
-1
@@ -513,5 +513,22 @@ std::optional<std::string> InputManager::ConvertHostKeyboardCodeToString(u32 cod
|
||||
|
||||
u32 QtUtils::KeyEventToCode(const QKeyEvent* ev)
|
||||
{
|
||||
return static_cast<u32>(ev->key()) | (static_cast<u32>(ev->modifiers()) & static_cast<u32>(Qt::KeypadModifier));
|
||||
int key = ev->key();
|
||||
Qt::KeyboardModifiers modifiers = ev->modifiers();
|
||||
|
||||
#ifdef __APPLE__
|
||||
// On macOS, Qt applies the Keypad modifier regardless of whether the arrow keys, or numpad was pressed.
|
||||
// The only way to differentiate between the keypad and the arrow keys is by the text.
|
||||
// Hopefully some keyboard layouts don't change the numpad positioning...
|
||||
if (modifiers & Qt::KeypadModifier && key >= Qt::Key_Insert && key <= Qt::Key_PageDown)
|
||||
{
|
||||
if (ev->text().isEmpty())
|
||||
{
|
||||
// Drop the modifier, because it's probably not actually a numpad push.
|
||||
modifiers &= ~Qt::KeypadModifier;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return static_cast<u32>(key) | (static_cast<u32>(modifiers) & static_cast<u32>(Qt::KeypadModifier));
|
||||
}
|
||||
|
||||
@@ -1078,7 +1078,10 @@ namespace SettingWidgetBinder
|
||||
static inline void BindSliderToIntSetting(SettingsInterface* sif, QSlider* slider, QLabel* label, const QString& label_suffix,
|
||||
std::string section, std::string key, s32 default_value)
|
||||
{
|
||||
const s32 global_value = Host::GetBaseIntSettingValue(section.c_str(), key.c_str(), default_value);
|
||||
s32 global_value = Host::GetBaseIntSettingValue(section.c_str(), key.c_str(), default_value);
|
||||
|
||||
//Clamp in case setting was updated manually using INI
|
||||
global_value = std::clamp(global_value, slider->minimum(), slider->maximum());
|
||||
|
||||
if (sif)
|
||||
{
|
||||
@@ -1086,7 +1089,9 @@ namespace SettingWidgetBinder
|
||||
QFont bold_font(orig_font);
|
||||
bold_font.setBold(true);
|
||||
|
||||
const s32 current_value = sif->GetOptionalIntValue(section.c_str(), key.c_str()).value_or(global_value);
|
||||
s32 current_value = sif->GetOptionalIntValue(section.c_str(), key.c_str()).value_or(global_value);
|
||||
current_value = std::clamp(current_value, slider->minimum(), slider->maximum());
|
||||
|
||||
slider->setValue(current_value);
|
||||
|
||||
label->setText(QStringLiteral("%1%2").arg(current_value).arg(label_suffix));
|
||||
@@ -1100,8 +1105,10 @@ namespace SettingWidgetBinder
|
||||
[sif, slider, label, label_suffix, orig_font = std::move(orig_font), section, key, default_value](const QPoint& pt) {
|
||||
QMenu menu(slider);
|
||||
slider->connect(menu.addAction(qApp->translate("SettingWidgetBinder", "Reset")), &QAction::triggered, slider,
|
||||
[sif, label, label_suffix, orig_font, section, key, default_value]() {
|
||||
const s32 global_value = Host::GetBaseIntSettingValue(section.c_str(), key.c_str(), default_value);
|
||||
[sif, slider, label, label_suffix, orig_font, section, key, default_value]() {
|
||||
s32 global_value = Host::GetBaseIntSettingValue(section.c_str(), key.c_str(), default_value);
|
||||
global_value = std::clamp(global_value, slider->minimum(), slider->maximum());
|
||||
|
||||
label->setText(QStringLiteral("%1%2").arg(global_value).arg(label_suffix));
|
||||
label->setFont(orig_font);
|
||||
|
||||
|
||||
@@ -22,13 +22,22 @@
|
||||
|
||||
#include <QtWidgets/QMessageBox>
|
||||
|
||||
AchievementLoginDialog::AchievementLoginDialog(QWidget* parent)
|
||||
AchievementLoginDialog::AchievementLoginDialog(QWidget* parent, Achievements::LoginRequestReason reason)
|
||||
: QDialog(parent)
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
m_ui.loginIcon->setPixmap(QIcon::fromTheme("login-box-line").pixmap(32));
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
|
||||
// Adjust text if needed based on reason.
|
||||
if (reason == Achievements::LoginRequestReason::TokenInvalid)
|
||||
{
|
||||
m_ui.instructionText->setText(
|
||||
tr("<strong>Your RetroAchievements login token is no longer valid.</strong> You must re-enter your "
|
||||
"credentials for achievements to be tracked. Your password will not be saved in PCSX2, an access token "
|
||||
"will be generated and used instead."));
|
||||
}
|
||||
|
||||
m_login = m_ui.buttonBox->addButton(tr("&Login"), QDialogButtonBox::AcceptRole);
|
||||
m_login->setEnabled(false);
|
||||
connectUi();
|
||||
|
||||
@@ -18,12 +18,17 @@
|
||||
#include <QtWidgets/QDialog>
|
||||
#include <QtWidgets/QPushButton>
|
||||
|
||||
namespace Achievements
|
||||
{
|
||||
enum class LoginRequestReason;
|
||||
}
|
||||
|
||||
class AchievementLoginDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AchievementLoginDialog(QWidget* parent);
|
||||
AchievementLoginDialog(QWidget* parent, Achievements::LoginRequestReason reason);
|
||||
~AchievementLoginDialog();
|
||||
|
||||
private Q_SLOTS:
|
||||
@@ -38,4 +43,5 @@ private:
|
||||
|
||||
Ui::AchievementLoginDialog m_ui;
|
||||
QPushButton* m_login;
|
||||
Achievements::LoginRequestReason m_reason;
|
||||
};
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<widget class="QLabel" name="instructionText">
|
||||
<property name="text">
|
||||
<string>Please enter user name and password for retroachievements.org below. Your password will not be saved in PCSX2, an access token will be generated and used instead.</string>
|
||||
</property>
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
#include <QtCore/QDateTime>
|
||||
#include <QtWidgets/QMessageBox>
|
||||
|
||||
static constexpr s32 DEFAULT_NOTIFICATIONS_DURATION = 5;
|
||||
|
||||
AchievementSettingsWidget::AchievementSettingsWidget(SettingsDialog* dialog, QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, m_dialog(dialog)
|
||||
@@ -48,6 +50,9 @@ AchievementSettingsWidget::AchievementSettingsWidget(SettingsDialog* dialog, QWi
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.soundEffects, "Achievements", "SoundEffects", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.primedIndicators, "Achievements", "PrimedIndicators", true);
|
||||
|
||||
SettingWidgetBinder::BindSliderToIntSetting(sif, m_ui.notifications_duration, m_ui.notifications_duration_seconds,
|
||||
tr(" seconds"), "Achievements", "NotificationsDuration", DEFAULT_NOTIFICATIONS_DURATION);
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.enable, tr("Enable Achievements"), tr("Unchecked"),
|
||||
tr("When enabled and logged in, PCSX2 will scan for achievements on game load."));
|
||||
dialog->registerWidgetHelp(m_ui.testMode, tr("Enable Test Mode"), tr("Unchecked"),
|
||||
@@ -70,10 +75,18 @@ AchievementSettingsWidget::AchievementSettingsWidget(SettingsDialog* dialog, QWi
|
||||
dialog->registerWidgetHelp(m_ui.primedIndicators, tr("Show Challenge Indicators"), tr("Checked"),
|
||||
tr("Shows icons in the lower-right corner of the screen when a challenge/primed achievement is active."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.notifications_duration, tr("Notification Duration"),
|
||||
tr("5 seconds"), tr("The duration, in seconds, an achievement popup notification will remain on screen."));
|
||||
dialog->registerWidgetHelp(m_ui.notifications_duration_label, tr("Notification Duration"),
|
||||
tr("5 seconds"), tr("The duration, in seconds, an achievement popup notification will remain on screen."));
|
||||
dialog->registerWidgetHelp(m_ui.notifications_duration_seconds, tr("Notification Duration"),
|
||||
tr("5 seconds"), tr("The duration, in seconds, an achievement popup notification will remain on screen."));
|
||||
|
||||
connect(m_ui.enable, &QCheckBox::stateChanged, this, &AchievementSettingsWidget::updateEnableState);
|
||||
connect(m_ui.notifications, &QCheckBox::stateChanged, this, &AchievementSettingsWidget::updateEnableState);
|
||||
connect(m_ui.challengeMode, &QCheckBox::stateChanged, this, &AchievementSettingsWidget::updateEnableState);
|
||||
connect(m_ui.challengeMode, &QCheckBox::stateChanged, this, &AchievementSettingsWidget::onChallengeModeStateChanged);
|
||||
connect(m_ui.notifications_duration, &QSlider::valueChanged, this, &AchievementSettingsWidget::onNotificationsDurationChanged);
|
||||
|
||||
if (!m_dialog->isPerGameSettings())
|
||||
{
|
||||
@@ -105,6 +118,8 @@ void AchievementSettingsWidget::updateEnableState()
|
||||
{
|
||||
const bool enabled = m_dialog->getEffectiveBoolValue("Achievements", "Enabled", false);
|
||||
const bool challenge = m_dialog->getEffectiveBoolValue("Achievements", "ChallengeMode", false);
|
||||
const bool notifications = m_dialog->getEffectiveBoolValue("Achievements", "Notifications", true);
|
||||
|
||||
m_ui.testMode->setEnabled(enabled);
|
||||
m_ui.unofficialTestMode->setEnabled(enabled);
|
||||
m_ui.richPresence->setEnabled(enabled);
|
||||
@@ -113,6 +128,10 @@ void AchievementSettingsWidget::updateEnableState()
|
||||
m_ui.notifications->setEnabled(enabled);
|
||||
m_ui.soundEffects->setEnabled(enabled);
|
||||
m_ui.primedIndicators->setEnabled(enabled);
|
||||
|
||||
m_ui.notifications_duration->setEnabled(enabled && notifications);
|
||||
m_ui.notifications_duration_label->setEnabled(enabled && notifications);
|
||||
m_ui.notifications_duration_seconds->setEnabled(enabled && notifications);
|
||||
}
|
||||
|
||||
void AchievementSettingsWidget::onChallengeModeStateChanged()
|
||||
@@ -173,7 +192,7 @@ void AchievementSettingsWidget::onLoginLogoutPressed()
|
||||
return;
|
||||
}
|
||||
|
||||
AchievementLoginDialog login(this);
|
||||
AchievementLoginDialog login(this, Achievements::LoginRequestReason::UserInitiated);
|
||||
int res = login.exec();
|
||||
if (res != 0)
|
||||
return;
|
||||
@@ -196,3 +215,9 @@ void AchievementSettingsWidget::onAchievementsRefreshed(quint32 id, const QStrin
|
||||
{
|
||||
m_ui.gameInfo->setText(game_info_string);
|
||||
}
|
||||
|
||||
void AchievementSettingsWidget::onNotificationsDurationChanged()
|
||||
{
|
||||
m_ui.notifications_duration_seconds->setText(tr("%1 seconds")
|
||||
.arg(m_ui.notifications_duration->value()));
|
||||
}
|
||||
@@ -33,6 +33,7 @@ private Q_SLOTS:
|
||||
void onLoginLogoutPressed();
|
||||
void onViewProfilePressed();
|
||||
void onAchievementsRefreshed(quint32 id, const QString& game_info_string, quint32 total, quint32 points);
|
||||
void onNotificationsDurationChanged();
|
||||
|
||||
private:
|
||||
void updateLoginState();
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>658</width>
|
||||
<height>496</height>
|
||||
<width>829</width>
|
||||
<height>641</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -39,13 +39,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="primedIndicators">
|
||||
<property name="text">
|
||||
<string>Show Challenge Indicators</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="richPresence">
|
||||
<property name="text">
|
||||
@@ -74,13 +67,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QCheckBox" name="testMode">
|
||||
<property name="text">
|
||||
<string>Enable Test Mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="soundEffects">
|
||||
<property name="text">
|
||||
@@ -89,12 +75,93 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="primedIndicators">
|
||||
<property name="text">
|
||||
<string>Show Challenge Indicators</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="testMode">
|
||||
<property name="text">
|
||||
<string>Enable Test Mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="notificationBox">
|
||||
<property name="title">
|
||||
<string>Notifications</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="notifications_box_layout" stretch="0,0">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="notifications">
|
||||
<property name="text">
|
||||
<string>Show Notifications</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="notifications_duration_layout" stretch="0,0,0">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="notifications_duration_label">
|
||||
<property name="text">
|
||||
<string>Duration</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="notifications_duration">
|
||||
<property name="minimum">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="invertedAppearance">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksBelow</enum>
|
||||
</property>
|
||||
<property name="tickInterval">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="notifications_duration_seconds">
|
||||
<property name="text">
|
||||
<string>5 seconds</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@@ -0,0 +1,317 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ControllerBindingWidget_Guitar</class>
|
||||
<widget class="QWidget" name="ControllerBindingWidget_Guitar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1100</width>
|
||||
<height>500</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="horizontalLayoutWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1101</width>
|
||||
<height>322</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>800</width>
|
||||
<height>320</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="../resources/resources.qrc">:/images/guitar.png</pixmap>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="gridLayoutWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>320</y>
|
||||
<width>1101</width>
|
||||
<height>181</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="6">
|
||||
<widget class="QGroupBox" name="groupBox_7">
|
||||
<property name="title">
|
||||
<string>Yellow</string>
|
||||
</property>
|
||||
<widget class="InputBindingWidget" name="Yellow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>24</x>
|
||||
<y>30</y>
|
||||
<width>90</width>
|
||||
<height>40</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Start</string>
|
||||
</property>
|
||||
<widget class="InputBindingWidget" name="Start">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>24</x>
|
||||
<y>30</y>
|
||||
<width>90</width>
|
||||
<height>40</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="7">
|
||||
<widget class="QGroupBox" name="groupBox_8">
|
||||
<property name="title">
|
||||
<string>Red</string>
|
||||
</property>
|
||||
<widget class="InputBindingWidget" name="Red">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>24</x>
|
||||
<y>30</y>
|
||||
<width>90</width>
|
||||
<height>40</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="8">
|
||||
<widget class="QGroupBox" name="groupBox_9">
|
||||
<property name="title">
|
||||
<string>Green</string>
|
||||
</property>
|
||||
<widget class="InputBindingWidget" name="Green">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>24</x>
|
||||
<y>30</y>
|
||||
<width>90</width>
|
||||
<height>40</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QGroupBox" name="groupBox_5">
|
||||
<property name="title">
|
||||
<string>Orange</string>
|
||||
</property>
|
||||
<widget class="InputBindingWidget" name="Orange">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>24</x>
|
||||
<y>30</y>
|
||||
<width>90</width>
|
||||
<height>40</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="title">
|
||||
<string>Select</string>
|
||||
</property>
|
||||
<widget class="InputBindingWidget" name="Select">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>24</x>
|
||||
<y>30</y>
|
||||
<width>90</width>
|
||||
<height>40</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Strum Up</string>
|
||||
</property>
|
||||
<widget class="InputBindingWidget" name="Up">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>24</x>
|
||||
<y>30</y>
|
||||
<width>90</width>
|
||||
<height>40</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QGroupBox" name="groupBox_4">
|
||||
<property name="title">
|
||||
<string>Strum Down</string>
|
||||
</property>
|
||||
<widget class="InputBindingWidget" name="Down">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>24</x>
|
||||
<y>30</y>
|
||||
<width>90</width>
|
||||
<height>40</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="5">
|
||||
<widget class="QGroupBox" name="groupBox_6">
|
||||
<property name="title">
|
||||
<string>Blue</string>
|
||||
</property>
|
||||
<widget class="InputBindingWidget" name="Blue">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>24</x>
|
||||
<y>30</y>
|
||||
<width>90</width>
|
||||
<height>40</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QGroupBox" name="groupBox_10">
|
||||
<property name="title">
|
||||
<string>Whammy Bar</string>
|
||||
</property>
|
||||
<widget class="InputBindingWidget" name="Whammy">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>24</x>
|
||||
<y>30</y>
|
||||
<width>90</width>
|
||||
<height>40</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QGroupBox" name="groupBox_11">
|
||||
<property name="title">
|
||||
<string>Tilt</string>
|
||||
</property>
|
||||
<widget class="InputBindingWidget" name="Tilt">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>30</y>
|
||||
<width>90</width>
|
||||
<height>40</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>InputBindingWidget</class>
|
||||
<extends>QPushButton</extends>
|
||||
<header>Settings/InputBindingWidget.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../resources/resources.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -26,7 +26,7 @@
|
||||
#include "common/StringUtil.h"
|
||||
|
||||
#include "pcsx2/Host.h"
|
||||
#include "pcsx2/PAD/Host/PAD.h"
|
||||
#include "pcsx2/SIO/Pad/Pad.h"
|
||||
|
||||
#include "Settings/ControllerBindingWidgets.h"
|
||||
#include "Settings/ControllerSettingsDialog.h"
|
||||
@@ -38,6 +38,7 @@
|
||||
|
||||
#include "ui_USBBindingWidget_DrivingForce.h"
|
||||
#include "ui_USBBindingWidget_GTForce.h"
|
||||
#include "ui_USBBindingWidget_GunCon2.h"
|
||||
|
||||
ControllerBindingWidget::ControllerBindingWidget(QWidget* parent, ControllerSettingsDialog* dialog, u32 port)
|
||||
: QWidget(parent)
|
||||
@@ -51,8 +52,8 @@ ControllerBindingWidget::ControllerBindingWidget(QWidget* parent, ControllerSett
|
||||
populateControllerTypes();
|
||||
onTypeChanged();
|
||||
|
||||
ControllerSettingWidgetBinder::BindWidgetToInputProfileString(
|
||||
m_dialog->getProfileSettingsInterface(), m_ui.controllerType, m_config_section, "Type", PAD::GetDefaultPadType(port));
|
||||
ControllerSettingWidgetBinder::BindWidgetToInputProfileString(m_dialog->getProfileSettingsInterface(),
|
||||
m_ui.controllerType, m_config_section, "Type", Pad::GetControllerInfo(Pad::GetDefaultPadType(port))->name);
|
||||
|
||||
connect(m_ui.controllerType, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ControllerBindingWidget::onTypeChanged);
|
||||
connect(m_ui.bindings, &QPushButton::clicked, this, &ControllerBindingWidget::onBindingsClicked);
|
||||
@@ -71,14 +72,22 @@ QIcon ControllerBindingWidget::getIcon() const
|
||||
|
||||
void ControllerBindingWidget::populateControllerTypes()
|
||||
{
|
||||
for (const auto& [name, display_name] : PAD::GetControllerTypeNames())
|
||||
m_ui.controllerType->addItem(qApp->translate("Pad", display_name), QString::fromStdString(name));
|
||||
for (const auto& [name, display_name] : Pad::GetControllerTypeNames())
|
||||
m_ui.controllerType->addItem(QString::fromUtf8(display_name), QString::fromUtf8(name));
|
||||
}
|
||||
|
||||
void ControllerBindingWidget::onTypeChanged()
|
||||
{
|
||||
const bool is_initializing = (m_ui.stackedWidget->count() == 0);
|
||||
m_controller_type = m_dialog->getStringValue(m_config_section.c_str(), "Type", PAD::GetDefaultPadType(m_port_number));
|
||||
const std::string type_name = m_dialog->getStringValue(
|
||||
m_config_section.c_str(), "Type", Pad::GetControllerInfo(Pad::GetDefaultPadType(m_port_number))->name);
|
||||
const Pad::ControllerInfo* cinfo = Pad::GetControllerInfoByName(type_name);
|
||||
if (!cinfo)
|
||||
{
|
||||
Console.Error(fmt::format("Invalid controller type name '{}' in config, ignoring.", type_name));
|
||||
cinfo = Pad::GetControllerInfo(Pad::ControllerType::NotConnected);
|
||||
}
|
||||
m_controller_type = cinfo->type;
|
||||
|
||||
if (m_bindings_widget)
|
||||
{
|
||||
@@ -99,25 +108,31 @@ void ControllerBindingWidget::onTypeChanged()
|
||||
m_macros_widget = nullptr;
|
||||
}
|
||||
|
||||
const PAD::ControllerInfo* cinfo = PAD::GetControllerInfo(m_controller_type);
|
||||
const bool has_settings = (cinfo && cinfo->num_settings > 0);
|
||||
const bool has_macros = (cinfo && cinfo->num_bindings > 0);
|
||||
const bool has_settings = (!cinfo->settings.empty());
|
||||
const bool has_macros = (!cinfo->bindings.empty());
|
||||
m_ui.settings->setEnabled(has_settings);
|
||||
m_ui.macros->setEnabled(has_macros);
|
||||
|
||||
if (m_controller_type == "DualShock2")
|
||||
if (cinfo->type == Pad::ControllerType::DualShock2)
|
||||
{
|
||||
m_bindings_widget = ControllerBindingWidget_DualShock2::createInstance(this);
|
||||
}
|
||||
else if (cinfo->type == Pad::ControllerType::Guitar)
|
||||
{
|
||||
m_bindings_widget = ControllerBindingWidget_Guitar::createInstance(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bindings_widget = new ControllerBindingWidget_Base(this);
|
||||
}
|
||||
|
||||
m_ui.stackedWidget->addWidget(m_bindings_widget);
|
||||
m_ui.stackedWidget->setCurrentWidget(m_bindings_widget);
|
||||
|
||||
if (has_settings)
|
||||
{
|
||||
const std::span<const SettingInfo> settings(cinfo->settings, cinfo->num_settings);
|
||||
m_settings_widget = new ControllerCustomSettingsWidget(
|
||||
settings, m_config_section, std::string(), "Pad", getDialog(), m_ui.stackedWidget);
|
||||
cinfo->settings, m_config_section, std::string(), "Pad", getDialog(), m_ui.stackedWidget);
|
||||
m_ui.stackedWidget->addWidget(m_settings_widget);
|
||||
}
|
||||
|
||||
@@ -210,13 +225,13 @@ void ControllerBindingWidget::onClearBindingsClicked()
|
||||
{
|
||||
{
|
||||
auto lock = Host::GetSettingsLock();
|
||||
PAD::ClearPortBindings(*Host::Internal::GetBaseSettingsLayer(), m_port_number);
|
||||
Pad::ClearPortBindings(*Host::Internal::GetBaseSettingsLayer(), m_port_number);
|
||||
}
|
||||
Host::CommitBaseSettingChanges();
|
||||
}
|
||||
else
|
||||
{
|
||||
PAD::ClearPortBindings(*m_dialog->getProfileSettingsInterface(), m_port_number);
|
||||
Pad::ClearPortBindings(*m_dialog->getProfileSettingsInterface(), m_port_number);
|
||||
m_dialog->getProfileSettingsInterface()->Save();
|
||||
}
|
||||
|
||||
@@ -240,14 +255,14 @@ void ControllerBindingWidget::doDeviceAutomaticBinding(const QString& device)
|
||||
{
|
||||
{
|
||||
auto lock = Host::GetSettingsLock();
|
||||
result = PAD::MapController(*Host::Internal::GetBaseSettingsLayer(), m_port_number, mapping);
|
||||
result = Pad::MapController(*Host::Internal::GetBaseSettingsLayer(), m_port_number, mapping);
|
||||
}
|
||||
if (result)
|
||||
Host::CommitBaseSettingChanges();
|
||||
}
|
||||
else
|
||||
{
|
||||
result = PAD::MapController(*m_dialog->getProfileSettingsInterface(), m_port_number, mapping);
|
||||
result = Pad::MapController(*m_dialog->getProfileSettingsInterface(), m_port_number, mapping);
|
||||
if (result)
|
||||
{
|
||||
m_dialog->getProfileSettingsInterface()->Save();
|
||||
@@ -312,7 +327,7 @@ ControllerMacroEditWidget::ControllerMacroEditWidget(ControllerMacroWidget* pare
|
||||
|
||||
ControllerSettingsDialog* dialog = m_bwidget->getDialog();
|
||||
const std::string& section = m_bwidget->getConfigSection();
|
||||
const PAD::ControllerInfo* cinfo = PAD::GetControllerInfo(m_bwidget->getControllerType());
|
||||
const Pad::ControllerInfo* cinfo = Pad::GetControllerInfo(m_bwidget->getControllerType());
|
||||
if (!cinfo)
|
||||
{
|
||||
// Shouldn't ever happen.
|
||||
@@ -325,20 +340,19 @@ ControllerMacroEditWidget::ControllerMacroEditWidget(ControllerMacroWidget* pare
|
||||
|
||||
for (const std::string_view& button : buttons_split)
|
||||
{
|
||||
for (u32 i = 0; i < cinfo->num_bindings; i++)
|
||||
for (const InputBindingInfo& bi : cinfo->bindings)
|
||||
{
|
||||
if (button == cinfo->bindings[i].name)
|
||||
if (button == bi.name)
|
||||
{
|
||||
m_binds.push_back(&cinfo->bindings[i]);
|
||||
m_binds.push_back(&bi);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// populate list view
|
||||
for (u32 i = 0; i < cinfo->num_bindings; i++)
|
||||
for (const InputBindingInfo& bi : cinfo->bindings)
|
||||
{
|
||||
const InputBindingInfo& bi = cinfo->bindings[i];
|
||||
if (bi.bind_type == InputBindingInfo::Type::Motor)
|
||||
continue;
|
||||
|
||||
@@ -350,8 +364,12 @@ ControllerMacroEditWidget::ControllerMacroEditWidget(ControllerMacroWidget* pare
|
||||
|
||||
ControllerSettingWidgetBinder::BindWidgetToInputProfileNormalized(
|
||||
dialog->getProfileSettingsInterface(), m_ui.pressure, section, fmt::format("Macro{}Pressure", index + 1u), 100.0f, 1.0f);
|
||||
ControllerSettingWidgetBinder::BindWidgetToInputProfileNormalized(
|
||||
dialog->getProfileSettingsInterface(), m_ui.deadzone, section, fmt::format("Macro{}Deadzone", index + 1u), 100.0f, 0.0f);
|
||||
connect(m_ui.pressure, &QSlider::valueChanged, this, &ControllerMacroEditWidget::onPressureChanged);
|
||||
connect(m_ui.deadzone, &QSlider::valueChanged, this, &ControllerMacroEditWidget::onDeadzoneChanged);
|
||||
onPressureChanged();
|
||||
onDeadzoneChanged();
|
||||
|
||||
m_frequency = dialog->getIntValue(section.c_str(), fmt::format("Macro{}Frequency", index + 1u).c_str(), 0);
|
||||
updateFrequencyText();
|
||||
@@ -384,6 +402,11 @@ void ControllerMacroEditWidget::onPressureChanged()
|
||||
m_ui.pressureValue->setText(tr("%1%").arg(m_ui.pressure->value()));
|
||||
}
|
||||
|
||||
void ControllerMacroEditWidget::onDeadzoneChanged()
|
||||
{
|
||||
m_ui.deadzoneValue->setText(tr("%1%").arg(m_ui.deadzone->value()));
|
||||
}
|
||||
|
||||
void ControllerMacroEditWidget::onSetFrequencyClicked()
|
||||
{
|
||||
bool okay;
|
||||
@@ -423,12 +446,12 @@ void ControllerMacroEditWidget::updateFrequencyText()
|
||||
void ControllerMacroEditWidget::updateBinds()
|
||||
{
|
||||
ControllerSettingsDialog* dialog = m_bwidget->getDialog();
|
||||
const PAD::ControllerInfo* cinfo = PAD::GetControllerInfo(m_bwidget->getControllerType());
|
||||
const Pad::ControllerInfo* cinfo = Pad::GetControllerInfo(m_bwidget->getControllerType());
|
||||
if (!cinfo)
|
||||
return;
|
||||
|
||||
std::vector<const InputBindingInfo*> new_binds;
|
||||
for (u32 i = 0, bind_index = 0; i < cinfo->num_bindings; i++)
|
||||
for (u32 i = 0, bind_index = 0; i < static_cast<u32>(cinfo->bindings.size()); i++)
|
||||
{
|
||||
const InputBindingInfo& bi = cinfo->bindings[i];
|
||||
if (bi.bind_type == InputBindingInfo::Type::Motor)
|
||||
@@ -793,16 +816,15 @@ QIcon ControllerBindingWidget_Base::getIcon() const
|
||||
|
||||
void ControllerBindingWidget_Base::initBindingWidgets()
|
||||
{
|
||||
const PAD::ControllerInfo* cinfo = PAD::GetControllerInfo(getControllerType());
|
||||
const Pad::ControllerInfo* cinfo = Pad::GetControllerInfo(getControllerType());
|
||||
if (!cinfo)
|
||||
return;
|
||||
|
||||
const std::string& config_section = getConfigSection();
|
||||
SettingsInterface* sif = getDialog()->getProfileSettingsInterface();
|
||||
|
||||
for (u32 i = 0; i < cinfo->num_bindings; i++)
|
||||
for (const InputBindingInfo& bi : cinfo->bindings)
|
||||
{
|
||||
const InputBindingInfo& bi = cinfo->bindings[i];
|
||||
if (bi.bind_type == InputBindingInfo::Type::Axis || bi.bind_type == InputBindingInfo::Type::HalfAxis ||
|
||||
bi.bind_type == InputBindingInfo::Type::Button || bi.bind_type == InputBindingInfo::Type::Pointer ||
|
||||
bi.bind_type == InputBindingInfo::Type::Device)
|
||||
@@ -820,7 +842,7 @@ void ControllerBindingWidget_Base::initBindingWidgets()
|
||||
|
||||
switch (cinfo->vibration_caps)
|
||||
{
|
||||
case PAD::VibrationCapabilities::LargeSmallMotors:
|
||||
case Pad::VibrationCapabilities::LargeSmallMotors:
|
||||
{
|
||||
InputVibrationBindingWidget* widget = findChild<InputVibrationBindingWidget*>(QStringLiteral("LargeMotor"));
|
||||
if (widget)
|
||||
@@ -832,7 +854,7 @@ void ControllerBindingWidget_Base::initBindingWidgets()
|
||||
}
|
||||
break;
|
||||
|
||||
case PAD::VibrationCapabilities::SingleMotor:
|
||||
case Pad::VibrationCapabilities::SingleMotor:
|
||||
{
|
||||
InputVibrationBindingWidget* widget = findChild<InputVibrationBindingWidget*>(QStringLiteral("Motor"));
|
||||
if (widget)
|
||||
@@ -840,7 +862,7 @@ void ControllerBindingWidget_Base::initBindingWidgets()
|
||||
}
|
||||
break;
|
||||
|
||||
case PAD::VibrationCapabilities::NoVibration:
|
||||
case Pad::VibrationCapabilities::NoVibration:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -867,6 +889,27 @@ ControllerBindingWidget_Base* ControllerBindingWidget_DualShock2::createInstance
|
||||
return new ControllerBindingWidget_DualShock2(parent);
|
||||
}
|
||||
|
||||
ControllerBindingWidget_Guitar::ControllerBindingWidget_Guitar(ControllerBindingWidget* parent)
|
||||
: ControllerBindingWidget_Base(parent)
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
initBindingWidgets();
|
||||
}
|
||||
|
||||
ControllerBindingWidget_Guitar::~ControllerBindingWidget_Guitar()
|
||||
{
|
||||
}
|
||||
|
||||
QIcon ControllerBindingWidget_Guitar::getIcon() const
|
||||
{
|
||||
return QIcon::fromTheme("guitar-line");
|
||||
}
|
||||
|
||||
ControllerBindingWidget_Base* ControllerBindingWidget_Guitar::createInstance(ControllerBindingWidget* parent)
|
||||
{
|
||||
return new ControllerBindingWidget_Guitar(parent);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
USBDeviceWidget::USBDeviceWidget(QWidget* parent, ControllerSettingsDialog* dialog, u32 port)
|
||||
@@ -1240,6 +1283,11 @@ USBBindingWidget* USBBindingWidget::createInstance(
|
||||
has_template = true;
|
||||
}
|
||||
}
|
||||
else if (type == "guncon2")
|
||||
{
|
||||
Ui::USBBindingWidget_GunCon2().setupUi(widget);
|
||||
has_template = true;
|
||||
}
|
||||
|
||||
if (has_template)
|
||||
widget->bindWidgets(bindings);
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "PAD/Host/PAD.h"
|
||||
#include "pcsx2/SIO/Pad/PadTypes.h"
|
||||
|
||||
#include <QtWidgets/QWidget>
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include "ui_ControllerBindingWidget.h"
|
||||
#include "ui_ControllerBindingWidget_DualShock2.h"
|
||||
#include "ui_ControllerBindingWidget_Guitar.h"
|
||||
#include "ui_ControllerMacroWidget.h"
|
||||
#include "ui_ControllerMacroEditWidget.h"
|
||||
#include "ui_USBDeviceWidget.h"
|
||||
@@ -48,7 +49,7 @@ public:
|
||||
|
||||
__fi ControllerSettingsDialog* getDialog() const { return m_dialog; }
|
||||
__fi const std::string& getConfigSection() const { return m_config_section; }
|
||||
__fi const std::string& getControllerType() const { return m_controller_type; }
|
||||
__fi Pad::ControllerType getControllerType() const { return m_controller_type; }
|
||||
__fi u32 getPortNumber() const { return m_port_number; }
|
||||
|
||||
private Q_SLOTS:
|
||||
@@ -69,7 +70,7 @@ private:
|
||||
ControllerSettingsDialog* m_dialog;
|
||||
|
||||
std::string m_config_section;
|
||||
std::string m_controller_type;
|
||||
Pad::ControllerType m_controller_type;
|
||||
u32 m_port_number;
|
||||
|
||||
ControllerBindingWidget_Base* m_bindings_widget = nullptr;
|
||||
@@ -91,7 +92,7 @@ public:
|
||||
void updateListItem(u32 index);
|
||||
|
||||
private:
|
||||
static constexpr u32 NUM_MACROS = PAD::NUM_MACRO_BUTTONS_PER_CONTROLLER;
|
||||
static constexpr u32 NUM_MACROS = Pad::NUM_MACRO_BUTTONS_PER_CONTROLLER;
|
||||
|
||||
void createWidgets(ControllerBindingWidget* parent);
|
||||
|
||||
@@ -114,6 +115,7 @@ public:
|
||||
|
||||
private Q_SLOTS:
|
||||
void onPressureChanged();
|
||||
void onDeadzoneChanged();
|
||||
void onSetFrequencyClicked();
|
||||
void updateBinds();
|
||||
|
||||
@@ -168,7 +170,7 @@ public:
|
||||
|
||||
__fi ControllerSettingsDialog* getDialog() const { return static_cast<ControllerBindingWidget*>(parent())->getDialog(); }
|
||||
__fi const std::string& getConfigSection() const { return static_cast<ControllerBindingWidget*>(parent())->getConfigSection(); }
|
||||
__fi const std::string& getControllerType() const { return static_cast<ControllerBindingWidget*>(parent())->getControllerType(); }
|
||||
__fi Pad::ControllerType getControllerType() const { return static_cast<ControllerBindingWidget*>(parent())->getControllerType(); }
|
||||
__fi u32 getPortNumber() const { return static_cast<ControllerBindingWidget*>(parent())->getPortNumber(); }
|
||||
|
||||
virtual QIcon getIcon() const;
|
||||
@@ -193,6 +195,22 @@ private:
|
||||
Ui::ControllerBindingWidget_DualShock2 m_ui;
|
||||
};
|
||||
|
||||
class ControllerBindingWidget_Guitar final : public ControllerBindingWidget_Base
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ControllerBindingWidget_Guitar(ControllerBindingWidget* parent);
|
||||
~ControllerBindingWidget_Guitar();
|
||||
|
||||
QIcon getIcon() const override;
|
||||
|
||||
static ControllerBindingWidget_Base* createInstance(ControllerBindingWidget* parent);
|
||||
|
||||
private:
|
||||
Ui::ControllerBindingWidget_Guitar m_ui;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class USBDeviceWidget final : public QWidget
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>691</width>
|
||||
<height>547</height>
|
||||
<height>433</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -83,6 +83,9 @@
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksBelow</enum>
|
||||
</property>
|
||||
<property name="tickInterval">
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -123,6 +126,46 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<layout class="QHBoxLayout" name="deadzoneLayout" stretch="0,1,0">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Deadzone:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="deadzone">
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksBelow</enum>
|
||||
</property>
|
||||
<property name="tickInterval">
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="deadzoneValue">
|
||||
<property name="text">
|
||||
<string>100%</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
#include "Settings/HotkeySettingsWidget.h"
|
||||
|
||||
#include "pcsx2/INISettingsInterface.h"
|
||||
#include "pcsx2/PAD/Host/PAD.h"
|
||||
#include "pcsx2/Sio.h"
|
||||
#include "pcsx2/SIO/Pad/Pad.h"
|
||||
#include "pcsx2/SIO/Sio.h"
|
||||
#include "pcsx2/VMManager.h"
|
||||
|
||||
#include "common/Assertions.h"
|
||||
@@ -130,7 +130,7 @@ void ControllerSettingsDialog::onNewProfileClicked()
|
||||
{
|
||||
// from global
|
||||
auto lock = Host::GetSettingsLock();
|
||||
PAD::CopyConfiguration(&temp_si, *Host::Internal::GetBaseSettingsLayer(), true, true, false);
|
||||
Pad::CopyConfiguration(&temp_si, *Host::Internal::GetBaseSettingsLayer(), true, true, false);
|
||||
USB::CopyConfiguration(&temp_si, *Host::Internal::GetBaseSettingsLayer(), true, true);
|
||||
}
|
||||
else
|
||||
@@ -138,7 +138,7 @@ void ControllerSettingsDialog::onNewProfileClicked()
|
||||
// from profile
|
||||
const bool copy_hotkey_bindings = m_profile_interface->GetBoolValue("Pad", "UseProfileHotkeyBindings", false);
|
||||
temp_si.SetBoolValue("Pad", "UseProfileHotkeyBindings", copy_hotkey_bindings);
|
||||
PAD::CopyConfiguration(&temp_si, *m_profile_interface, true, true, copy_hotkey_bindings);
|
||||
Pad::CopyConfiguration(&temp_si, *m_profile_interface, true, true, copy_hotkey_bindings);
|
||||
USB::CopyConfiguration(&temp_si, *m_profile_interface, true, true);
|
||||
}
|
||||
}
|
||||
@@ -167,7 +167,7 @@ void ControllerSettingsDialog::onLoadProfileClicked()
|
||||
|
||||
{
|
||||
auto lock = Host::GetSettingsLock();
|
||||
PAD::CopyConfiguration(Host::Internal::GetBaseSettingsLayer(), *m_profile_interface, true, true, false);
|
||||
Pad::CopyConfiguration(Host::Internal::GetBaseSettingsLayer(), *m_profile_interface, true, true, false);
|
||||
USB::CopyConfiguration(Host::Internal::GetBaseSettingsLayer(), *m_profile_interface, true, true);
|
||||
}
|
||||
Host::CommitBaseSettingChanges();
|
||||
@@ -403,8 +403,8 @@ void ControllerSettingsDialog::createWidgets()
|
||||
m_port_bindings[global_slot] = new ControllerBindingWidget(m_ui.settingsContainer, this, global_slot);
|
||||
m_ui.settingsContainer->addWidget(m_port_bindings[global_slot]);
|
||||
|
||||
const PAD::ControllerInfo* ci = PAD::GetControllerInfo(m_port_bindings[global_slot]->getControllerType());
|
||||
const QString display_name(ci ? qApp->translate("Pad", ci->display_name) : QStringLiteral("Unknown"));
|
||||
const Pad::ControllerInfo* ci = Pad::GetControllerInfo(m_port_bindings[global_slot]->getControllerType());
|
||||
const QString display_name(QString::fromUtf8(ci ? ci->GetLocalizedName() : "Unknown"));
|
||||
|
||||
QListWidgetItem* item = new QListWidgetItem();
|
||||
//: Controller Port is an official term from Sony. Find the official translation for your language inside the console's manual.
|
||||
@@ -459,8 +459,8 @@ void ControllerSettingsDialog::updateListDescription(u32 global_slot, Controller
|
||||
const auto [port, slot] = sioConvertPadToPortAndSlot(global_slot);
|
||||
const bool mtap_enabled = getBoolValue("Pad", (port == 0) ? "MultitapPort1" : "MultitapPort2", false);
|
||||
|
||||
const PAD::ControllerInfo* ci = PAD::GetControllerInfo(widget->getControllerType());
|
||||
const QString display_name(ci ? qApp->translate("Pad", ci->display_name) : QStringLiteral("Unknown"));
|
||||
const Pad::ControllerInfo* ci = Pad::GetControllerInfo(widget->getControllerType());
|
||||
const QString display_name = QString::fromUtf8(ci ? ci->GetLocalizedName() : "Unknown");
|
||||
|
||||
//: 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)) :
|
||||
@@ -492,7 +492,7 @@ void ControllerSettingsDialog::updateListDescription(u32 port, USBDeviceWidget*
|
||||
|
||||
void ControllerSettingsDialog::refreshProfileList()
|
||||
{
|
||||
const std::vector<std::string> names(PAD::GetInputProfileNames());
|
||||
const std::vector<std::string> names = Pad::GetInputProfileNames();
|
||||
|
||||
QSignalBlocker sb(m_ui.currentProfile);
|
||||
m_ui.currentProfile->clear();
|
||||
|
||||
@@ -27,10 +27,8 @@
|
||||
|
||||
#include "common/HeterogeneousContainers.h"
|
||||
|
||||
GameCheatSettingsWidget::GameCheatSettingsWidget(const GameList::Entry* entry, SettingsDialog* dialog, QWidget* parent)
|
||||
GameCheatSettingsWidget::GameCheatSettingsWidget(SettingsDialog* dialog, QWidget* parent)
|
||||
: m_dialog(dialog)
|
||||
, m_serial(entry->serial)
|
||||
, m_crc(entry->crc)
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
QtUtils::ResizeColumnsForTreeView(m_ui.cheatList, {300, 100, -1});
|
||||
@@ -154,7 +152,7 @@ void GameCheatSettingsWidget::setStateRecursively(QTreeWidgetItem* parent, bool
|
||||
void GameCheatSettingsWidget::reloadList()
|
||||
{
|
||||
u32 num_unlabelled_codes = 0;
|
||||
m_patches = Patch::GetPatchInfo(m_serial, m_crc, true, &num_unlabelled_codes);
|
||||
m_patches = Patch::GetPatchInfo(m_dialog->getSerial(), m_dialog->getDiscCRC(), true, &num_unlabelled_codes);
|
||||
m_enabled_patches =
|
||||
m_dialog->getSettingsInterface()->GetStringList(Patch::CHEATS_CONFIG_SECTION, Patch::PATCH_ENABLE_CONFIG_KEY);
|
||||
|
||||
@@ -194,7 +192,7 @@ QTreeWidgetItem* GameCheatSettingsWidget::getTreeWidgetParent(const std::string_
|
||||
if (parent.empty())
|
||||
return nullptr;
|
||||
|
||||
auto it = UnorderedStringMapFind(m_parent_map, parent);
|
||||
auto it = m_parent_map.find(parent);
|
||||
if (it != m_parent_map.end())
|
||||
return it->second;
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ class GameCheatSettingsWidget : public QWidget
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GameCheatSettingsWidget(const GameList::Entry* entry, SettingsDialog* dialog, QWidget* parent);
|
||||
GameCheatSettingsWidget(SettingsDialog* dialog, QWidget* parent);
|
||||
~GameCheatSettingsWidget();
|
||||
|
||||
private Q_SLOTS:
|
||||
@@ -59,9 +59,6 @@ private:
|
||||
Ui::GameCheatSettingsWidget m_ui;
|
||||
SettingsDialog* m_dialog;
|
||||
|
||||
std::string m_serial;
|
||||
u32 m_crc;
|
||||
|
||||
UnorderedStringMap<QTreeWidgetItem*> m_parent_map;
|
||||
std::vector<Patch::PatchInfo> m_patches;
|
||||
std::vector<std::string> m_enabled_patches;
|
||||
|
||||
@@ -51,6 +51,7 @@ GameListSettingsWidget::GameListSettingsWidget(SettingsDialog* dialog, QWidget*
|
||||
&GameListSettingsWidget::onAddSearchDirectoryButtonClicked);
|
||||
connect(m_ui.removeSearchDirectoryButton, &QPushButton::clicked, this,
|
||||
&GameListSettingsWidget::onRemoveSearchDirectoryButtonClicked);
|
||||
connect(m_ui.addExcludedFile, &QPushButton::clicked, this, &GameListSettingsWidget::onAddExcludedFileButtonClicked);
|
||||
connect(m_ui.addExcludedPath, &QPushButton::clicked, this, &GameListSettingsWidget::onAddExcludedPathButtonClicked);
|
||||
connect(m_ui.removeExcludedPath, &QPushButton::clicked, this,
|
||||
&GameListSettingsWidget::onRemoveExcludedPathButtonClicked);
|
||||
@@ -215,10 +216,21 @@ void GameListSettingsWidget::onRemoveSearchDirectoryButtonClicked()
|
||||
delete item;
|
||||
}
|
||||
|
||||
void GameListSettingsWidget::onAddExcludedFileButtonClicked()
|
||||
{
|
||||
QString path =
|
||||
QDir::toNativeSeparators(QFileDialog::getOpenFileName(QtUtils::GetRootWidget(this), tr("Select File")));
|
||||
if (path.isEmpty())
|
||||
return;
|
||||
|
||||
addExcludedPath(path.toStdString());
|
||||
}
|
||||
|
||||
void GameListSettingsWidget::onAddExcludedPathButtonClicked()
|
||||
{
|
||||
QString path =
|
||||
QDir::toNativeSeparators(QFileDialog::getOpenFileName(QtUtils::GetRootWidget(this), tr("Select Path")));
|
||||
QDir::toNativeSeparators(QFileDialog::getExistingDirectory(QtUtils::GetRootWidget(this), tr("Select Directory")));
|
||||
|
||||
if (path.isEmpty())
|
||||
return;
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ private Q_SLOTS:
|
||||
void onDirectoryListContextMenuRequested(const QPoint& point);
|
||||
void onAddSearchDirectoryButtonClicked();
|
||||
void onRemoveSearchDirectoryButtonClicked();
|
||||
void onAddExcludedFileButtonClicked();
|
||||
void onAddExcludedPathButtonClicked();
|
||||
void onRemoveExcludedPathButtonClicked();
|
||||
void onScanForNewGamesClicked();
|
||||
|
||||
@@ -57,12 +57,15 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add</string>
|
||||
<string>Add...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="folder-add-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -80,6 +83,9 @@
|
||||
<iconset theme="folder-reduce-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
@@ -129,12 +135,35 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add</string>
|
||||
<string>Directory...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="folder-add-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="addExcludedFile">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>File...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="file-add-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -152,6 +181,9 @@
|
||||
<iconset theme="file-reduce-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
||||
@@ -59,10 +59,8 @@ void GamePatchDetailsWidget::onEnabledStateChanged(int state)
|
||||
g_emu_thread->reloadGameSettings();
|
||||
}
|
||||
|
||||
GamePatchSettingsWidget::GamePatchSettingsWidget(const GameList::Entry* entry, SettingsDialog* dialog, QWidget* parent)
|
||||
GamePatchSettingsWidget::GamePatchSettingsWidget(SettingsDialog* dialog, QWidget* parent)
|
||||
: m_dialog(dialog)
|
||||
, m_serial(entry->serial)
|
||||
, m_crc(entry->crc)
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
m_ui.scrollArea->setFrameShape(QFrame::WinPanel);
|
||||
@@ -86,7 +84,7 @@ void GamePatchSettingsWidget::onReloadClicked()
|
||||
void GamePatchSettingsWidget::reloadList()
|
||||
{
|
||||
// Patches shouldn't have any unlabelled patch groups, because they're new.
|
||||
std::vector<Patch::PatchInfo> patches = Patch::GetPatchInfo(m_serial, m_crc, false, nullptr);
|
||||
std::vector<Patch::PatchInfo> patches = Patch::GetPatchInfo(m_dialog->getSerial(), m_dialog->getDiscCRC(), false, nullptr);
|
||||
std::vector<std::string> enabled_list =
|
||||
m_dialog->getSettingsInterface()->GetStringList(Patch::PATCHES_CONFIG_SECTION, Patch::PATCH_ENABLE_CONFIG_KEY);
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ class GamePatchSettingsWidget : public QWidget
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GamePatchSettingsWidget(const GameList::Entry* entry, SettingsDialog* dialog, QWidget* parent);
|
||||
GamePatchSettingsWidget(SettingsDialog* dialog, QWidget* parent);
|
||||
~GamePatchSettingsWidget();
|
||||
|
||||
private Q_SLOTS:
|
||||
@@ -63,7 +63,4 @@ private:
|
||||
|
||||
Ui::GamePatchSettingsWidget m_ui;
|
||||
SettingsDialog* m_dialog;
|
||||
|
||||
std::string m_serial;
|
||||
u32 m_crc;
|
||||
};
|
||||
|
||||
@@ -15,21 +15,28 @@
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
|
||||
#include "pcsx2/SIO/Pad/Pad.h"
|
||||
#include "GameSummaryWidget.h"
|
||||
#include "SettingsDialog.h"
|
||||
#include "MainWindow.h"
|
||||
#include "QtHost.h"
|
||||
#include "QtProgressCallback.h"
|
||||
#include "QtUtils.h"
|
||||
|
||||
#include "pcsx2/CDVD/IsoHasher.h"
|
||||
#include "pcsx2/GameDatabase.h"
|
||||
#include "pcsx2/GameList.h"
|
||||
#include "pcsx2/PAD/Host/PAD.h"
|
||||
|
||||
#include "common/Error.h"
|
||||
#include "common/MD5Digest.h"
|
||||
#include "common/ScopedGuard.h"
|
||||
#include "common/StringUtil.h"
|
||||
|
||||
#include "fmt/format.h"
|
||||
|
||||
#include <QtCore/QDir>
|
||||
#include <QtWidgets/QFileDialog>
|
||||
#include <QtWidgets/QMessageBox>
|
||||
|
||||
GameSummaryWidget::GameSummaryWidget(const GameList::Entry* entry, SettingsDialog* dialog, QWidget* parent)
|
||||
: m_dialog(dialog)
|
||||
@@ -51,15 +58,23 @@ GameSummaryWidget::GameSummaryWidget(const GameList::Entry* entry, SettingsDialo
|
||||
populateInputProfiles();
|
||||
populateDetails(entry);
|
||||
populateDiscPath(entry);
|
||||
populateTrackList(entry);
|
||||
|
||||
connect(m_ui.inputProfile, &QComboBox::currentIndexChanged, this, &GameSummaryWidget::onInputProfileChanged);
|
||||
connect(m_ui.verify, &QAbstractButton::clicked, this, &GameSummaryWidget::onVerifyClicked);
|
||||
connect(m_ui.searchHash, &QAbstractButton::clicked, this, &GameSummaryWidget::onSearchHashClicked);
|
||||
|
||||
bool has_custom_title = false, has_custom_region = false;
|
||||
GameList::CheckCustomAttributesForPath(m_entry_path, has_custom_title, has_custom_region);
|
||||
m_ui.restoreTitle->setEnabled(has_custom_title);
|
||||
m_ui.restoreRegion->setEnabled(has_custom_region);
|
||||
}
|
||||
|
||||
GameSummaryWidget::~GameSummaryWidget() = default;
|
||||
|
||||
void GameSummaryWidget::populateInputProfiles()
|
||||
{
|
||||
for (const std::string& name : PAD::GetInputProfileNames())
|
||||
for (const std::string& name : Pad::GetInputProfileNames())
|
||||
m_ui.inputProfile->addItem(QString::fromStdString(name));
|
||||
}
|
||||
|
||||
@@ -78,6 +93,24 @@ void GameSummaryWidget::populateDetails(const GameList::Entry* entry)
|
||||
m_ui.inputProfile->setCurrentIndex(m_ui.inputProfile->findText(QString::fromStdString(profile.value())));
|
||||
else
|
||||
m_ui.inputProfile->setCurrentIndex(0);
|
||||
|
||||
connect(m_ui.title, &QLineEdit::editingFinished, this, [this]() {
|
||||
if (m_ui.title->isModified())
|
||||
{
|
||||
setCustomTitle(m_ui.title->text().toStdString());
|
||||
m_ui.title->setModified(false);
|
||||
}
|
||||
});
|
||||
connect(m_ui.restoreTitle, &QAbstractButton::clicked, this, [this]() {
|
||||
setCustomTitle("");
|
||||
});
|
||||
|
||||
connect(m_ui.region, &QComboBox::currentIndexChanged, this, [this](int index) {
|
||||
setCustomRegion(index);
|
||||
});
|
||||
connect(m_ui.restoreRegion, &QAbstractButton::clicked, this, [this]() {
|
||||
setCustomRegion(-1);
|
||||
});
|
||||
}
|
||||
|
||||
void GameSummaryWidget::populateDiscPath(const GameList::Entry* entry)
|
||||
@@ -119,12 +152,7 @@ void GameSummaryWidget::onDiscPathChanged(const QString& value)
|
||||
|
||||
// force rescan of elf to update the serial
|
||||
g_main_window->rescanFile(m_entry_path);
|
||||
|
||||
// and re-fill our details (mainly the serial)
|
||||
auto lock = GameList::GetLock();
|
||||
const GameList::Entry* entry = GameList::GetEntryForPath(m_entry_path.c_str());
|
||||
if (entry)
|
||||
populateDetails(entry);
|
||||
repopulateCurrentDetails();
|
||||
}
|
||||
|
||||
void GameSummaryWidget::onDiscPathBrowseClicked()
|
||||
@@ -137,3 +165,236 @@ void GameSummaryWidget::onDiscPathBrowseClicked()
|
||||
// let the signal take care of it
|
||||
m_ui.discPath->setText(QDir::toNativeSeparators(filename));
|
||||
}
|
||||
|
||||
void GameSummaryWidget::populateTrackList(const GameList::Entry* entry)
|
||||
{
|
||||
if (entry->type != GameList::EntryType::PS1Disc && entry->type != GameList::EntryType::PS2Disc)
|
||||
{
|
||||
m_ui.verify->setEnabled(false);
|
||||
m_ui.verifyResult->setPlainText(tr("Game is not a CD/DVD."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (QtHost::IsVMValid())
|
||||
{
|
||||
m_ui.verify->setEnabled(false);
|
||||
m_ui.verifyResult->setPlainText(tr("Track list unavailable while virtual machine is running."));
|
||||
return;
|
||||
}
|
||||
|
||||
IsoHasher hasher;
|
||||
Error error;
|
||||
if (!hasher.Open(m_entry_path, &error))
|
||||
{
|
||||
m_ui.verify->setEnabled(false);
|
||||
m_ui.verifyResult->setPlainText(QString::fromStdString(error.GetDescription()));
|
||||
return;
|
||||
}
|
||||
|
||||
const auto AddColumn = [this](const QString& text) {
|
||||
QTableWidgetItem* item = new QTableWidgetItem(text);
|
||||
const int column = m_ui.tracks->columnCount();
|
||||
m_ui.tracks->insertColumn(column);
|
||||
m_ui.tracks->setHorizontalHeaderItem(column, item);
|
||||
};
|
||||
const auto SetColumn = [this](int row, int column, const QString& text) {
|
||||
QTableWidgetItem* item = new QTableWidgetItem(text);
|
||||
m_ui.tracks->setItem(row, column, item);
|
||||
};
|
||||
|
||||
// columns depend on CD vs DVD.
|
||||
AddColumn(tr("#"));
|
||||
if (hasher.IsCD())
|
||||
{
|
||||
AddColumn(tr("Mode"));
|
||||
AddColumn(tr("Start"));
|
||||
AddColumn(tr("Sectors"));
|
||||
AddColumn(tr("Size"));
|
||||
AddColumn(tr("MD5"));
|
||||
AddColumn(tr("Status"));
|
||||
}
|
||||
else
|
||||
{
|
||||
AddColumn(tr("Start"));
|
||||
AddColumn(tr("Sectors"));
|
||||
AddColumn(tr("Size"));
|
||||
AddColumn(tr("MD5"));
|
||||
AddColumn(tr("Status"));
|
||||
}
|
||||
|
||||
for (const IsoHasher::Track& track : hasher.GetTracks())
|
||||
{
|
||||
const int row = m_ui.tracks->rowCount();
|
||||
m_ui.tracks->insertRow(row);
|
||||
|
||||
SetColumn(row, 0, tr("%1").arg(track.number));
|
||||
|
||||
if (hasher.IsCD())
|
||||
{
|
||||
SetColumn(row, 1, QtUtils::StringViewToQString(IsoHasher::GetTrackTypeString(track.type)));
|
||||
SetColumn(row, 2, tr("%1").arg(track.start_lsn));
|
||||
SetColumn(row, 3, tr("%1").arg(track.sectors));
|
||||
SetColumn(row, 4, tr("%1").arg(track.size));
|
||||
SetColumn(row, 5, tr("<not computed>"));
|
||||
SetColumn(row, 6, QString());
|
||||
}
|
||||
else
|
||||
{
|
||||
SetColumn(row, 1, tr("%1").arg(track.start_lsn));
|
||||
SetColumn(row, 2, tr("%1").arg(track.sectors));
|
||||
SetColumn(row, 3, tr("%1").arg(track.size));
|
||||
SetColumn(row, 4, tr("<not computed>"));
|
||||
SetColumn(row, 5, QString());
|
||||
}
|
||||
}
|
||||
|
||||
if (hasher.IsCD())
|
||||
QtUtils::ResizeColumnsForTableView(m_ui.tracks, {20, 60, 70, 70, 100, 220, 40});
|
||||
else
|
||||
QtUtils::ResizeColumnsForTableView(m_ui.tracks, {20, 100, 100, 100, 220, 40});
|
||||
}
|
||||
|
||||
void GameSummaryWidget::onVerifyClicked()
|
||||
{
|
||||
// Can't do this while a VM is running because of stupid CDVD.
|
||||
if (QtHost::IsVMValid())
|
||||
{
|
||||
QMessageBox::critical(QtUtils::GetRootWidget(this), tr("Error"), tr("Cannot verify image while a game is running."));
|
||||
return;
|
||||
}
|
||||
|
||||
IsoHasher hasher;
|
||||
Error error;
|
||||
if (!hasher.Open(m_entry_path, &error))
|
||||
{
|
||||
setVerifyResult(QString::fromStdString(error.GetDescription()));
|
||||
return;
|
||||
}
|
||||
|
||||
QtModalProgressCallback callback(this);
|
||||
hasher.ComputeHashes(&callback);
|
||||
if (callback.IsCancelled())
|
||||
return;
|
||||
|
||||
const int hash_column = hasher.IsCD() ? 5 : 4;
|
||||
int row = 0;
|
||||
|
||||
// convert to database format
|
||||
std::vector<GameDatabase::TrackHash> thashes;
|
||||
thashes.reserve(hasher.GetTrackCount());
|
||||
for (const IsoHasher::Track& track : hasher.GetTracks())
|
||||
{
|
||||
GameDatabase::TrackHash thash;
|
||||
thash.size = track.size;
|
||||
if (track.hash.empty() || !thash.parseHash(track.hash))
|
||||
{
|
||||
m_ui.verify->setEnabled(false);
|
||||
m_ui.verifyResult->setPlainText(tr("One or more tracks is missing."));
|
||||
return;
|
||||
}
|
||||
|
||||
// Use the first track's hash as the redump search term.
|
||||
if (m_redump_search_keyword.empty())
|
||||
m_redump_search_keyword = thash.toString();
|
||||
|
||||
thashes.push_back(thash);
|
||||
}
|
||||
|
||||
// match the hashes. can't use vector<bool> here because it's not an actual array
|
||||
std::unique_ptr<bool[]> val_results = std::make_unique<bool[]>(hasher.GetTrackCount());
|
||||
std::string match_error;
|
||||
const GameDatabase::HashDatabaseEntry* hentry =
|
||||
GameDatabase::lookupHash(thashes.data(), thashes.size(), val_results.get(), &match_error);
|
||||
|
||||
// fill the UI with both the hashes and validation results
|
||||
for (u32 i = 0; i < hasher.GetTrackCount(); i++)
|
||||
{
|
||||
QTableWidgetItem* const hash_item = m_ui.tracks->item(row, hash_column);
|
||||
QTableWidgetItem* const status_item = m_ui.tracks->item(row, hash_column + 1);
|
||||
|
||||
const bool result = val_results[i];
|
||||
const QBrush brush(result ? QColor(0, 200, 0) : QColor(200, 0, 0));
|
||||
|
||||
hash_item->setText(QString::fromStdString(hasher.GetTrack(i).hash));
|
||||
hash_item->setForeground(brush);
|
||||
status_item->setText(result ? QStringLiteral("\u2713") : QStringLiteral("\u2715"));
|
||||
status_item->setForeground(brush);
|
||||
row++;
|
||||
}
|
||||
|
||||
if (hentry)
|
||||
{
|
||||
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)));
|
||||
}
|
||||
else
|
||||
{
|
||||
setVerifyResult(tr("Verified as %1 [%2].")
|
||||
.arg(QString::fromStdString(hentry->name))
|
||||
.arg(QString::fromStdString(hentry->serial)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setVerifyResult(QString::fromStdString(match_error));
|
||||
}
|
||||
}
|
||||
|
||||
void GameSummaryWidget::onSearchHashClicked()
|
||||
{
|
||||
if (m_redump_search_keyword.empty())
|
||||
return;
|
||||
|
||||
QtUtils::OpenURL(this, fmt::format("http://redump.org/discs/quicksearch/{}", m_redump_search_keyword).c_str());
|
||||
}
|
||||
|
||||
void GameSummaryWidget::setVerifyResult(QString error)
|
||||
{
|
||||
m_ui.verify->setVisible(false);
|
||||
m_ui.verifyButtonLayout->removeWidget(m_ui.verify);
|
||||
m_ui.verify->deleteLater();
|
||||
m_ui.verify = nullptr;
|
||||
m_ui.verifyButtonLayout->removeItem(m_ui.verifyButtonSpacer);
|
||||
delete m_ui.verifyButtonSpacer;
|
||||
m_ui.verifyButtonSpacer = nullptr;
|
||||
m_ui.verifyLayout->removeItem(m_ui.verifyButtonLayout);
|
||||
m_ui.verifyButtonLayout->deleteLater();
|
||||
m_ui.verifyButtonLayout = nullptr;
|
||||
m_ui.verifyLayout->update();
|
||||
updateGeometry();
|
||||
|
||||
m_ui.verifyResult->setPlainText(error);
|
||||
m_ui.verifyResult->setVisible(true);
|
||||
m_ui.searchHash->setVisible(true);
|
||||
}
|
||||
|
||||
void GameSummaryWidget::repopulateCurrentDetails()
|
||||
{
|
||||
auto lock = GameList::GetLock();
|
||||
const GameList::Entry* entry = GameList::GetEntryForPath(m_entry_path.c_str());
|
||||
if (entry)
|
||||
{
|
||||
populateDetails(entry);
|
||||
m_dialog->setWindowTitle(QString::fromStdString(entry->title));
|
||||
}
|
||||
}
|
||||
|
||||
void GameSummaryWidget::setCustomTitle(const std::string& text)
|
||||
{
|
||||
m_ui.restoreTitle->setEnabled(!text.empty());
|
||||
|
||||
GameList::SaveCustomTitleForPath(m_entry_path, text);
|
||||
repopulateCurrentDetails();
|
||||
}
|
||||
|
||||
void GameSummaryWidget::setCustomRegion(int region)
|
||||
{
|
||||
m_ui.restoreRegion->setEnabled(region >= 0);
|
||||
|
||||
GameList::SaveCustomRegionForPath(m_entry_path, region);
|
||||
repopulateCurrentDetails();
|
||||
}
|
||||
|
||||
@@ -34,16 +34,26 @@ public:
|
||||
GameSummaryWidget(const GameList::Entry* entry, SettingsDialog* dialog, QWidget* parent);
|
||||
~GameSummaryWidget();
|
||||
|
||||
private Q_SLOTS:
|
||||
void onInputProfileChanged(int index);
|
||||
void onDiscPathChanged(const QString& value);
|
||||
void onDiscPathBrowseClicked();
|
||||
void onVerifyClicked();
|
||||
void onSearchHashClicked();
|
||||
|
||||
private:
|
||||
void populateInputProfiles();
|
||||
void populateDetails(const GameList::Entry* entry);
|
||||
void populateDiscPath(const GameList::Entry* entry);
|
||||
void populateTrackList(const GameList::Entry* entry);
|
||||
void setVerifyResult(QString error);
|
||||
void repopulateCurrentDetails();
|
||||
|
||||
void onInputProfileChanged(int index);
|
||||
void onDiscPathChanged(const QString& value);
|
||||
void onDiscPathBrowseClicked();
|
||||
void setCustomTitle(const std::string& text);
|
||||
void setCustomRegion(int region);
|
||||
|
||||
Ui::GameSummaryWidget m_ui;
|
||||
SettingsDialog* m_dialog;
|
||||
std::string m_entry_path;
|
||||
std::string m_redump_search_keyword;
|
||||
};
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>692</width>
|
||||
<height>562</height>
|
||||
<width>641</width>
|
||||
<height>467</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="detailsFormLayout">
|
||||
@@ -34,11 +34,25 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="title">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="title">
|
||||
<property name="placeholderText">
|
||||
<string>Clear the line to restore the original title...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="restoreTitle">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Restore</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
@@ -140,170 +154,178 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QComboBox" name="region">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">NTSC-B (Brazil)</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||
<item>
|
||||
<widget class="QComboBox" name="region">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">NTSC-B (Brazil)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">NTSC-C (China)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">NTSC-HK (Hong Kong)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">NTSC-J (Japan)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">NTSC-K (Korea)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">NTSC-T (Taiwan)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">NTSC-U (US)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Other</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-A (Australia)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-AF (South Africa)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-AU (Austria)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-BE (Belgium)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-E (Europe/Australia)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-F (France)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-FI (Finland)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-G (Germany)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-GR (Greece)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-I (Italy)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-IN (India)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-M (Europe/Australia)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-NL (Netherlands)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-NO (Norway)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-P (Portugal)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-PL (Poland)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-R (Russia)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-S (Spain)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-SC (Scandinavia)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-SW (Sweden)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-SWI (Switzerland)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-UK (United Kingdom)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="restoreRegion">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Restore</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">NTSC-C (China)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">NTSC-HK (Hong Kong)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">NTSC-J (Japan)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">NTSC-K (Korea)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">NTSC-T (Taiwan)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">NTSC-U (US)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Other</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-A (Australia)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-AF (South Africa)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-AU (Austria)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-BE (Belgium)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-E (Europe/Australia)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-F (France)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-FI (Finland)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-G (Germany)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-GR (Greece)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-I (Italy)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-IN (India)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-M (Europe/Australia)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-NL (Netherlands)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-NO (Norway)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-P (Portugal)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-PL (Poland)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-R (Russia)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-S (Spain)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-SC (Scandinavia)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-SW (Sweden)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-SWI (Switzerland)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-UK (United Kingdom)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
@@ -413,7 +435,7 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<item row="10" column="0" colspan="2">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
@@ -426,6 +448,90 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="9" column="0" colspan="2">
|
||||
<layout class="QVBoxLayout" name="verifyLayout">
|
||||
<item>
|
||||
<widget class="QTableWidget" name="tracks">
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="cornerButtonEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="verifyButtonLayout">
|
||||
<item>
|
||||
<spacer name="verifyButtonSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="verify">
|
||||
<property name="text">
|
||||
<string>Verify</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="2" column="2">
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="0" rowspan="3">
|
||||
<widget class="QPlainTextEdit" name="verifyResult">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>60</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="visible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="searchHash">
|
||||
<property name="visible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Search on Redump.org...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
|
||||
@@ -181,7 +181,6 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// HW Renderer Fixes
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.halfScreenFix, "EmuCore/GS", "UserHacks_Half_Bottom_Override", -1, -1);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.cpuSpriteRenderBW, "EmuCore/GS", "UserHacks_CPUSpriteRenderBW", 0);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.cpuSpriteRenderLevel, "EmuCore/GS", "UserHacks_CPUSpriteRenderLevel", 0);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.cpuCLUTRender, "EmuCore/GS", "UserHacks_CPUCLUTRender", 0);
|
||||
@@ -218,12 +217,12 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.halfPixelOffset, "EmuCore/GS", "UserHacks_HalfPixelOffset", 0);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.roundSprite, "EmuCore/GS", "UserHacks_round_sprite_offset", 0);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.bilinearHack, "EmuCore/GS", "UserHacks_BilinearHack", 0);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.textureOffsetX, "EmuCore/GS", "UserHacks_TCOffsetX", 0);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.textureOffsetY, "EmuCore/GS", "UserHacks_TCOffsetY", 0);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.alignSprite, "EmuCore/GS", "UserHacks_align_sprite_X", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.mergeSprite, "EmuCore/GS", "UserHacks_merge_pp_sprite", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.wildHack, "EmuCore/GS", "UserHacks_WildHack", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.bilinearHack, "EmuCore/GS", "UserHacks_BilinearHack", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.nativePaletteDraw, "EmuCore/GS", "UserHacks_NativePaletteDraw", false);
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Texture Replacements
|
||||
@@ -515,9 +514,6 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
|
||||
|
||||
// Hardware Fixes tab
|
||||
{
|
||||
dialog->registerWidgetHelp(m_ui.halfScreenFix, tr("Half Screen Fix"), tr("Automatic (Default)"),
|
||||
tr("Control the half-screen fix detection on texture shuffling."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.cpuSpriteRenderBW, tr("CPU Sprite Renderer Size"), tr("0 (Disabled)"), tr(""));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.cpuCLUTRender, tr("Software CLUT Render"), tr("0 (Disabled)"), tr(""));
|
||||
@@ -1050,7 +1046,6 @@ void GraphicsSettingsWidget::resetManualHardwareFixes()
|
||||
|
||||
check_bool("EmuCore/GS", "UserHacks", false);
|
||||
|
||||
check_int("EmuCore/GS", "UserHacks_Half_Bottom_Override", -1);
|
||||
check_int("EmuCore/GS", "UserHacks_CPUSpriteRenderBW", 0);
|
||||
check_int("EmuCore/GS", "UserHacks_CPUCLUTRender", 0);
|
||||
check_int("EmuCore/GS", "UserHacks_GPUTargetCLUTMode", 0);
|
||||
|
||||
@@ -787,25 +787,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="halfScreenFix">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Automatic (Default)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Force Disabled</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Force Enabled</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_36">
|
||||
<property name="text">
|
||||
@@ -1168,14 +1149,14 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="textureOffsetLabel">
|
||||
<property name="text">
|
||||
<string>Texture Offsets:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<item row="3" column="1">
|
||||
<layout class="QHBoxLayout" name="textureOffsetLayout" stretch="0,1,0,1">
|
||||
<item>
|
||||
<widget class="QLabel" name="textureOffsetXLabel">
|
||||
@@ -1207,7 +1188,7 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<item row="4" column="0" colspan="2">
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="alignSprite">
|
||||
@@ -1216,20 +1197,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="bilinearHack">
|
||||
<property name="text">
|
||||
<string>Bilinear Dirty Upscale</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="mergeSprite">
|
||||
<property name="text">
|
||||
<string>Merge Sprite</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="nativePaletteDraw">
|
||||
<property name="text">
|
||||
@@ -1244,8 +1211,41 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="mergeSprite">
|
||||
<property name="text">
|
||||
<string>Merge Sprite</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Bilinear Dirty Upscale:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="bilinearHack">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Automatic (Default)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Force Bilinear</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Force Nearest</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab">
|
||||
|
||||
@@ -27,8 +27,7 @@
|
||||
|
||||
#include "fmt/format.h"
|
||||
|
||||
// _BitScanForward()
|
||||
#include "pcsx2/GS/GSIntrin.h"
|
||||
#include <bit>
|
||||
|
||||
InputBindingDialog::InputBindingDialog(SettingsInterface* sif, InputBindingInfo::Type bind_type, std::string section_name,
|
||||
std::string key_name, std::vector<std::string> bindings, QWidget* parent)
|
||||
@@ -97,9 +96,8 @@ bool InputBindingDialog::eventFilter(QObject* watched, QEvent* event)
|
||||
else if (event_type == QEvent::MouseButtonPress || event_type == QEvent::MouseButtonDblClick)
|
||||
{
|
||||
// double clicks get triggered if we click bind, then click again quickly.
|
||||
unsigned long button_index;
|
||||
if (_BitScanForward(&button_index, static_cast<u32>(static_cast<const QMouseEvent*>(event)->button())))
|
||||
m_new_bindings.push_back(InputManager::MakePointerButtonKey(0, button_index));
|
||||
if (const u32 button_mask = static_cast<u32>(static_cast<const QMouseEvent*>(event)->button()))
|
||||
m_new_bindings.push_back(InputManager::MakePointerButtonKey(0, std::countr_zero(button_mask)));
|
||||
return true;
|
||||
}
|
||||
else if (event_type == QEvent::Wheel)
|
||||
|
||||
@@ -21,13 +21,12 @@
|
||||
#include <QtGui/QWheelEvent>
|
||||
#include <QtWidgets/QInputDialog>
|
||||
#include <QtWidgets/QMessageBox>
|
||||
#include <bit>
|
||||
#include <cmath>
|
||||
#include <sstream>
|
||||
|
||||
#include "pcsx2/Host.h"
|
||||
|
||||
#include "pcsx2/GS/GSIntrin.h" // _BitScanForward
|
||||
|
||||
#include "QtHost.h"
|
||||
#include "QtUtils.h"
|
||||
#include "Settings/ControllerSettingsDialog.h"
|
||||
@@ -134,9 +133,8 @@ bool InputBindingWidget::eventFilter(QObject* watched, QEvent* event)
|
||||
else if (event_type == QEvent::MouseButtonPress || event_type == QEvent::MouseButtonDblClick)
|
||||
{
|
||||
// double clicks get triggered if we click bind, then click again quickly.
|
||||
unsigned long button_index;
|
||||
if (_BitScanForward(&button_index, static_cast<u32>(static_cast<const QMouseEvent*>(event)->button())))
|
||||
m_new_bindings.push_back(InputManager::MakePointerButtonKey(0, button_index));
|
||||
if (const u32 button_mask = static_cast<u32>(static_cast<const QMouseEvent*>(event)->button()))
|
||||
m_new_bindings.push_back(InputManager::MakePointerButtonKey(0, std::countr_zero(button_mask)));
|
||||
return true;
|
||||
}
|
||||
else if (event_type == QEvent::Wheel)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user